Skip to content
prod 352bb92
Browse

7 · Project standards (recommended)

Objective — surface three SHOULD-not-skip topics (project structure, commit + doc standards with the Zaj customization strategy, and SemVer + Zaj-CHANGELOG version management) and capture the operator’s decision on each — never silently drop them.

Steps at a glance:

  1. Decide which topics to adopt — Present all three to the operator and record each choice in the project log before scaffolding anything.
  2. Scaffold the project structure — A consistent Admin-Local/ layout gives every later phase a known home for credentials, docs, version snapshots, schema baselines, and the 90-DevLog build journal.
  3. Adopt commit & documentation standards — Consistent commit hygiene prevents secrets leaking and makes history searchable. Never commit (already in .gitignore): .env / .env.* (except .env.example), vendor/, node_modules/, IDE settings.
  4. Adopt version management — SemVer + Zaj-CHANGELOG — If you’ll ship updates (almost everyone), adopt semantic versioning and a Zaj-CHANGELOG.md now so your versions stay distinct from the vendor’s author-vX.X.X line.

These three topics are SHOULD, not skip-by-default. The agent must surface them and capture the operator’s decision — never silently drop them.

TopicWhat it gives youAdopt when
Project structureA predictable Admin-Local/ home for the vault, docs, and versionsYou want the full scaffold from day one (recommended)
Commit & doc standardsSearchable history + an auditable vendor seamTeam work, or you want disciplined history
Version managementSemVer + Zaj-CHANGELOG.md distinct from the vendor’s lineYou’ll ship updates over time (almost everyone)

Present all three to the operator and record each choice in Zaj-PROJECT.md before scaffolding anything.

  1. Surface the three topics and record the decisions.

    • ✅ Each of the three topics was presented, and its adopt/skip decision is written in Zaj-PROJECT.md.

2. Scaffold the project structure (if adopted)

Section titled “2. Scaffold the project structure (if adopted)”

A consistent Admin-Local/ layout gives every later phase a known home for credentials, docs, and version snapshots.

  1. Create the Admin-Local/ scaffold.

    Terminal window
    mkdir -p Admin-Local/{0-SuperAdmin,1-Project,2-Docs,3-Versions,4-Backups,5-Archive}
    mkdir -p Admin-Local/1-Project/{1-Info,2-Vault,3-Templates,4-Audit-Reports,5-Scripts,6-Schema,90-DevLog}
    mkdir -p Admin-Local/1-Project/90-DevLog/{Plans,Sessions,Decisions,Prompts,Handoffs,_Archive}
    mkdir -p Admin-Local/3-Versions/1-v${VERSION}/{1-Originals,2-Modifications}
    # Expected: the Admin-Local tree is created
    • ✅ Phases 3–12 now have a known home for credentials, docs, audit reports, replay-script records, schema baselines, the build journal, and versions.
  2. Lock the vault so credentials can never be committed.

    Terminal window
    printf '*\n!.gitignore\n!README.md\n' > Admin-Local/1-Project/2-Vault/.gitignore
    # Expected: the vault ignores everything except its .gitignore + README
    • Admin-Local/1-Project/2-Vault/.gitignore ignores all but itself + README.
  3. Create the replay-script index only. Do not pre-create empty payment/email/content folders. Scripts are generated later from the guide step + rules + boilerplate, so the project starts with only the taxonomy and provider inventory matrix.

    Terminal window
    cat > Admin-Local/1-Project/5-Scripts/README.md <<'EOF'
    # 5-Scripts — <PROJECT>
    Persist replay scripts here when a setup, operations, migration, or growth step needs repeatable writes to the vendor database or a third-party API.
    ## Taxonomy
    - `1-Setup/` initial configuration during Phases 6-8.
    - `2-Operations/` future re-syncs, cleanups, and health checks.
    - `3-Migrations/` future data migrations and vendor-update data fixes.
    - `4-Growth/` future promos, new tiers, and experiments.
    - `archive/` retired scripts moved for audit, never deleted.
    ## Provider inventory
    | Function | Provider/service | Status | Script path | Notes |
    |---|---|---|---|---|
    | Payments | Stripe | 🟡 placeholder | | Use if this app has Stripe billing. |
    | Payments | PayPal | not used | | |
    | Email | SMTP | 🟡 placeholder | | |
    | Email | SendGrid | not used | | |
    | Content | DemoContentCleanup | 🟡 placeholder | | Use only if demo rows need scripted cleanup. |
    | Auth | Roles | 🟡 placeholder | | |
    | Branding | Assets | 🟡 placeholder | | |
    | Database | SchemaInspection | 🟡 placeholder | | |
    Status: ` configured` = script exists, `🟡 placeholder` = expected but no script yet, ` not used` = intentionally out of scope.
    EOF
    # Expected: only 5-Scripts/README.md exists; lane/function/provider folders are lazy-created later
    • Admin-Local/1-Project/5-Scripts/README.md records the taxonomy and provider inventory without empty script folders.
  4. Seed the build journal. 90-DevLog/ is the working journal for plans, session logs, decisions, prompt capture, and handoffs. It is a high-band meta lane: 1-9 lanes hold project content; 90-99 lanes hold process/meta artifacts that should sort last.

    Terminal window
    DEVLOG=Admin-Local/1-Project/90-DevLog
    mkdir -p "$DEVLOG"/{Plans,Sessions,Decisions,Prompts,Handoffs,_Archive}
    touch "$DEVLOG"/{Plans,Sessions,Decisions,Handoffs,_Archive}/.gitkeep
    printf '# keep\n' > "$DEVLOG/Prompts/.gitkeep"
    cat > "$DEVLOG/Prompts/.gitignore" <<'EOF'
    *.jsonl
    distilled/
    !.gitignore
    !.gitkeep
    !README.md
    EOF
    cat > "$DEVLOG/README.md" <<'EOF'
    # 90-DevLog — the build journal
    Single home for dev-process artifacts: plans, session logs, decisions, prompts, and handoffs.
    Numbered `90-` as a reserved high band so it sorts last and never forces a renumber of the
    `1-9` content lanes (`1-Info`, `2-Vault`, `5-Scripts`, `6-Schema`, etc.).
    Boundary: root `Zaj-*` files are the canonical record of what shipped. `90-DevLog/` is the
    working journal for how the work happened.
    ## Lanes
    | Path | Holds | Naming |
    |---|---|---|
    | `STATUS.md` | Active plan, in-flight agents, hot-file locks, blockers | fixed name |
    | `Plans/` | Phase or feature plans | `NNN-type-slug.md` |
    | `Sessions/` | Per-session logs | `YYYY-MM-DD-HHMM-agent-slug.md` |
    | `Decisions/` | ADR-lite decisions | `NNN-type-slug.md` |
    | `Prompts/` | Local prompt JSONL from `UserPromptSubmit` | `YYYY-Www.jsonl` |
    | `Handoffs/` | Agent-switch handoffs | `YYYY-MM-DD-HHMM-from-to.md` |
    | `_Archive/` | Completed/stale journal artifacts | mirror source name |
    ## Rules
    - `1-9` = project content lanes; `90-99` = sorts-last/meta lanes.
    - Plans and Decisions use monotonic IDs; never reset, reuse, or reorder them.
    - Sessions, Handoffs, and Prompts use timestamps so parallel agents do not race a shared counter.
    - Agent identity belongs in frontmatter and slug, never as the sort key.
    - `STATUS.md` is the coordination surface; claim hot files before editing.
    EOF
    cat > "$DEVLOG/STATUS.md" <<'EOF'
    # DevLog STATUS — <PROJECT>
    Last updated: <YYYY-MM-DD> (<AGENT>)
    ## Where we are
    - Current phase: Phase 2 Code & repository setup
    ## Active plan
    - None yet.
    ## In-flight agents
    | Agent | Working on | Hot files claimed |
    |---|---|---|
    | <agent> | <task> | `<path>` |
    > Hot-file locks: one agent per hot file. Do not edit, move, overwrite, or archive another live agent's claimed file without coordinating first.
    ## Blockers
    - None.
    EOF
    # Expected: 90-DevLog has README, STATUS, lanes, and prompt JSONL is ignored by default
    • Admin-Local/1-Project/90-DevLog/ exists with README.md, STATUS.md, lane stubs, and local prompt JSONL ignored by default.
  5. Seed the per-project templates into 3-Templates/. These are minimal, self-contained, and require no external pack. (If your org’s handbook _Docs pack is available, you may copy its richer versions over these instead.)

    Terminal window
    TPL=Admin-Local/1-Project/3-Templates
    # Zaj-PROJECT template — current truth for non-secret project facts
    cat > "$TPL/T01-Zaj-PROJECT.md" <<'EOF'
    # Zaj-PROJECT — <PROJECT>
    Last updated: <YYYY-MM-DD>
    Current phase: Phase 2 Code & repository setup
    > Non-secret project bible. Current truth for project identity, toolchain versions, paths, environments, SSH aliases, and tracker links.
    > Boundary: this file records current facts; `Zaj-CUSTOMIZATIONS.md` records vendor deviations and why they exist.
    ## Project Identity
    | Field | Value |
    |---|---|
    | Project name | <PROJECT> |
    | CodeCanyon item | <url> |
    | Vendor / author | <vendor> |
    | Vendor version | <author-vX.Y.Z> |
    | Product type | <SaaS / marketplace / directory / other> |
    ## Repository And Branch Model
    | Field | Value |
    |---|---|
    | Repo URL | <git@host:org/repo.git> |
    | Default branch | develop |
    | Release branch | main |
    ## Environment Matrix
    Use one row per real environment. `staging-primary` is only the common example; use the actual keys this project has, such as `qa`, `uat`, `client-demo`, `sandbox`, or multiple staging rows.
    | Env key | Role | URL / domain | Hosting account | SSH alias | Host | User | Port | Deploy target | Source branch | Web PHP | CLI PHP binary | DB name | Noindex / robots | Credential pointer | Last verified |
    |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
    | local | Local dev | https://<project>.test | N/A | N/A | 127.0.0.1 | <local user> | N/A | local | develop | Herd <x.y> | <path> | <project>_local | N/A | op://<vault>/Local | <date> |
    | staging-primary | Non-production | https://nonprod.example.com | <account/order> | <alias> | <host/IP> | <user> | <port> | staging | staging | <pending Phase 4> | <pending Phase 4> | <project>_staging | noindex + Disallow | op://<vault>/Staging | <date> |
    | production | Production | https://<domain> | <account/order> | <alias> | <host/IP> | <user> | <port> | production | main | <pending Phase 12> | <pending Phase 4> | <project>_production | index allowed | op://<vault>/Production | <date> |
    ## Toolchain Parity
    | Surface | Local | Non-production target(s) | Production | Target / rule |
    |---|---|---|---|---|
    | PHP | <x.y.z> | <pending> | <pending> | strictest root `composer.json` + production package requirement in `composer.lock` |
    | Composer | <2.x> | <pending> | <pending> | same major/minor where practical |
    | Node | <x.y.z> | build-local only | build-local only | `.tool-versions` / package lock |
    | DB engine | <MySQL/MariaDB x.y> | <x.y> | <x.y> | same engine family when possible |
    | DB charset/collation | utf8mb4 / utf8mb4_unicode_ci | utf8mb4 / utf8mb4_unicode_ci | utf8mb4 / utf8mb4_unicode_ci | must match before deploy |
    ## Canonical Paths
    | Purpose | Path |
    |---|---|
    | Project profile | `Zaj-PROJECT.md` |
    | Progress tracker | `Zaj-PROGRESS.md` |
    | Deferred work | `Zaj-BACKLOG.md` |
    | Internal changelog | `Zaj-CHANGELOG.md` |
    | Vendor-deviation ledger | `Zaj-CUSTOMIZATIONS.md` |
    | Project info lane | `Admin-Local/1-Project/1-Info/` |
    | Research reports | `Admin-Local/1-Project/1-Info/Research/` |
    | Build journal | `Admin-Local/1-Project/90-DevLog/` |
    | Playbook feedback | `Admin-Local/1-Project/playbook-feedback.md` |
    ## 1Password Pointers
    | Item | Pointer | Expected fields |
    |---|---|---|
    | Local credential item | `op://<vault>/Local` | `DB_CONNECTION`, `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`, `APP_KEY`, `env_file` |
    | Staging credential item | `op://<vault>/Staging` | Same flat field set; use the real non-production item name if this row is `qa`, `uat`, `client-demo`, etc. |
    | Production credential item | `op://<vault>/Production` | Same flat field set; `DB_PASSWORD`, `APP_KEY`, and `env_file` are concealed. |
    EOF
    cat > "$TPL/tool-versions.template" <<'EOF'
    php <PHP_VERSION>
    nodejs <NODE_VERSION>
    composer <COMPOSER_VERSION>
    EOF
    # Expected: T01-Zaj-PROJECT.md + tool-versions.template exist in 3-Templates/
  6. Instantiate the project records from those templates:

    Terminal window
    TPL=Admin-Local/1-Project/3-Templates
    cp "$TPL/T01-Zaj-PROJECT.md" Zaj-PROJECT.md
    cp "$TPL/tool-versions.template" .tool-versions
    printf '# Project vault\n\nGitignored credentials and env templates.\n' \
    > Admin-Local/1-Project/2-Vault/README.md
    # Expected: Zaj-PROJECT.md + .tool-versions + vault README exist

    Fill Zaj-PROJECT from infrastructure created in Prerequisites — domains, IPs, SSH aliases, repo URL, DB names, current local PHP/Composer/Node, and placeholder deploy PHP rows that Phase 4 will confirm. Keep .tool-versions aligned with the chosen PHP / Node / Composer targets. (Zaj-CHANGELOG.md is created in §4 below — keep it out of this step so the public/internal split is set up correctly.)

    AI agent wiring: if Phase 1 did not already seed rules, drop Cursor/Gemini/AntiGravity rule files into the project’s own AI config (e.g. .cursor/rules/, GEMINI.md) and ensure .cursorignore / .geminiignore exclude vendor/, node_modules/, and Admin-Local/1-Project/2-Vault/. Do not assume a host-side Guides-v2/Templates/ pack — author them in-project or copy from your handbook if you have one.

    • Zaj-PROJECT.md exists with real domains, IPs, SSH aliases, repo URL, DB names, local toolchain facts, and the 90-DevLog canonical path; .tool-versions exists; per-project templates are seeded in 3-Templates/; vault README explains the gitignored area.

3. Adopt commit & documentation standards (if adopted)

Section titled “3. Adopt commit & documentation standards (if adopted)”

Consistent commit hygiene prevents secrets leaking and makes history searchable. Never commit (already in .gitignore): .env / .env.* (except .env.example), vendor/, node_modules/, IDE settings. Always commit: composer.json + composer.lock, package.json + package-lock.json, config/*.php, database/migrations/*.php, project docs.

A conventional commit format keeps the log self-documenting — emoji + type tag + verb-thing + description:

TypeFormatExample
Author import📦 ⬜ T1 Setup-Author: …📦 ⬜ T1 Setup-Author: Import v10.4
Setup/config🔧 🟦 T2 Setup-Config: …🔧 🟦 T2 Setup-Config: Add GA tracking
App feature🔨 🟪 T3 Add-Feature: …🔨 🟪 T3 Add-Feature: Arabic support
Deploy🚀 🟩 T4 Deploy-App: …🚀 🟩 T4 Deploy-App: Deploy v1.5.1
ServerSync🔄 ⬛ T5 ServerSync-Setup: …🔄 ⬛ T5 ServerSync-Setup: Capture SMTP config

Documentation update schedule — refresh when the trigger fires, not “whenever you remember”:

FileUpdate when
Zaj-PROJECT.mdEvery current-truth change: repo, toolchain, DB names, SSH aliases, deploy paths, server/runtime versions
Zaj-PROGRESS.mdDuring active phase/step work and after each verified gate
Zaj-BACKLOG.mdDeferred work, phase-entry blockers, human-only follow-ups, and future work
Zaj-CHANGELOG.mdEach phase completion and release-worthy internal change
Zaj-CUSTOMIZATIONS.mdAny vendor/config deviation or operational decision that affects future upgrades
Admin-Local/1-Project/90-DevLog/Decisions/Material “why” decisions that need an audit trail
Admin-Local/1-Project/4-Audit-Reports/Security, compliance, audit, and QA evidence
CLAUDE.md / AGENTS.mdAI rules, vendor doc extracts, tooling changes

Before any customization in this or later phases, know which mechanism to use — this is what prevents “modified vendor file” sprawl that blocks future updates:

MechanismUse whenLives in
Vendor CustomizationsPatching an existing vendor fileresources/vendor-customizations/
ZajModulesAdding new functionality (route, view, service)packages/ZajModules/{Type}/{Cat}/{Name}/
_zaj migrationsExtending a vendor table schemadatabase/migrations/*_zaj.php

The decision is three questions: editing an existing vendor file → Vendor Customization; adding something new → ZajModule; adding columns to a vendor table → _zaj migration.

4. Adopt version management — SemVer + Zaj-CHANGELOG (if adopted)

Section titled “4. Adopt version management — SemVer + Zaj-CHANGELOG (if adopted)”

If you’ll ship updates (almost everyone), adopt semantic versioning and a Zaj-CHANGELOG.md now so your versions stay distinct from the vendor’s author-vX.X.X line. vMAJOR.MINOR.PATCH — bump by the nature of the change:

ChangeBumpExample
Bug fix / security patchPATCH (1.0.0 → 1.0.1)Fixed login error
New feature, backward compatibleMINOR (1.0.0 → 1.1.0)Added export
Breaking changeMAJOR (1.0.0 → 2.0.0)Changed API responses

Git tags:

TypeCommandUse for
Annotated (recommended)git tag -a v1.0.0 -m "First stable release"Production releases
Lightweightgit tag v1.0.0Quick local markers only

Release workflow:

  1. Develop workdevelop branch; Zaj-CHANGELOG.md [Unreleased] section grows.
  2. Prepare release — promote to staging, test, bump version in composer.json / package.json.
  3. Release — deploy production, create annotated tag vX.Y.Z.
  4. Sync branches — mirror production to main when your pipeline uses it.

Decision journal — the current version fields live in Zaj-PROJECT.md; the release history lives in Zaj-CHANGELOG.md; material “why” decisions live in 90-DevLog/Decisions/. If this project needs an audit trail for the version-management choice, add one decision note there:

Terminal window
mkdir -p Admin-Local/1-Project/90-DevLog/Decisions
DECISION="Admin-Local/1-Project/90-DevLog/Decisions/001-decision-version-management.md"
if [ ! -f "$DECISION" ]; then
cat > "$DECISION" <<'EOF'
# Decision 001 — Version management
Date: <YYYY-MM-DD>
Decision: Use project SemVer with root Zaj-CHANGELOG.md and internal Vendor base markers.
Rationale: Keep our release line separate from the CodeCanyon author snapshot line.
Evidence: composer.json/package.json version fields, author-vX.X.X tag, Zaj-CHANGELOG.md.
EOF
fi
# Expected: optional decision note lives under 90-DevLog/Decisions/; no separate 1-Info work-log file is created

Keep changelogs in Keep a Changelog form (Added / Changed / Deprecated / Removed / Fixed / Security), and align package metadata: set composer.json and package.json name/version/description, change license to proprietary, and keep package.json private: true.

Terminal window
echo "composer.json:" && grep '"version"' composer.json | head -1
echo "package.json:" && grep '"version"' package.json | head -1
# Expected: both show "1.0.0" (your project line, not the vendor's author tag)

Two changelogs: INTERNAL (vendor-aware) vs PUBLIC (sanitized)

Section titled “Two changelogs: INTERNAL (vendor-aware) vs PUBLIC (sanitized)”

A public-facing CHANGELOG or release-notes page must never name the CodeCanyon vendor — not “WorkDo”, “CodeCanyon”, “Envato”, the vendor product name, nor an author-vX tag. That’s both a product-naming rule (customers see your brand, not the underlying script) and basic operational hygiene. So keep two documents:

DocumentAudienceMay mention vendor?Records
Zaj-CHANGELOG.md (internal)You + your team✅ Yes — that’s the pointProject SemVer + vendor base per release (e.g. Vendor base: <Vendor> v7.6), vendor upgrades logged as ### Changed
docs/public-changelog.md (or release-notes page)Customers / publicNeverProject name + your own SemVer + user-facing changes only

Two version lines stay distinct in BOTH:

  • Project version (v1.0.0, v1.1.0, …) — your own SemVer, tagged vX.Y.Z. First release is v1.0.0 even if the vendor is at v7.6.
  • Vendor (author) version (author-v7.6, …) — the CodeCanyon base, tracked by author-vX.X.X git tags. Internal only — never in the public document.

Each release records, internally, the vendor base it was built on so any project release is traceable to the exact CodeCanyon version underneath it. The public document carries only the project SemVer and the user-facing change.

Internal Zaj-CHANGELOG.md (vendor base recorded):

## [Unreleased]
> **Vendor base:** <Vendor> v7.6 (`author-v7.6`)
### Added
- Subscription export.
### Changed
- Upgraded vendor base v7.6 → v7.8.

Public docs/public-changelog.md (same release, sanitized):

## v1.1.0 — <YYYY-MM-DD>
### Added
- Export your subscriptions to CSV.
### Changed
- Performance and reliability improvements.

Scrub gate — the public document must not leak the vendor. Run this before publishing any public release notes; it must print ✅ clean:

Terminal window
PUBLIC=docs/public-changelog.md
if grep -iE 'workdo|codecanyon|envato|author-v|dash[- ]?saas' "$PUBLIC" >/dev/null 2>&1; then
echo "❌ vendor reference leaked into $PUBLIC — sanitize before publishing:"
grep -inE 'workdo|codecanyon|envato|author-v|dash[- ]?saas' "$PUBLIC"
else
echo "✅ clean — no vendor references in $PUBLIC"
fi
# Expected: ✅ clean — add YOUR vendor's product name to the pattern too

Replace dash[- ]?saas with your own vendor’s product name(s) so the grep catches the specific script you’re built on, not just the generic terms.

Do not mark this step done until every box below is checked.

  • 👤 Topics surfaced — each recommended topic was presented and the operator’s choice recorded.
  • 🤖 Scaffold (if adopted)Admin-Local/ + gitignored vault exist; per-project templates seeded in Admin-Local/1-Project/3-Templates/; 4-Audit-Reports/ and 6-Schema/ exist; 5-Scripts/README.md exists without pre-created script folders; 90-DevLog/ exists with README, STATUS, lanes, and prompt JSONL ignored by default.
  • 🔀 Standards (if adopted) — commit format + Zaj customization strategy understood.
  • 🔀 Versioning (if adopted) — internal Zaj-CHANGELOG.md (records vendor base) started, package metadata set, and the public-changelog scrub gate prints ✅ clean before any public release notes ship.