7 · Verify & gate
Objective — prove the AI dev environment actually works (not just that files exist) by running the verification checklist, confirming the gate condition, and handing off to Code & repository setup with everything fully wired.
Steps at a glance:
- Run the verification commands — Run a single block from the project root to confirm every AI dev
environment artifact is present, valid, and already committed on
develop(personal files stay gitignored). - Run the fresh-session smoke test — This is the real test — restart the agent, then ask three questions that prove the constitution, rules, and guardrails actually loaded.
- Restart everything that caches config — Rules, MCP, shell env vars, and the docs dev server only pick up changes after a full restart — not “Reload Window.”.
Background
Section titled “Background”A phase isn’t done because files exist — it’s done when a fresh session proves the system works. Rules and settings load only at session start, so the most common reason the smoke test fails is simply not restarting after seeding. Run the checklist below, then restart and confirm before advancing.
flowchart LR C2[C2 machine setup] --> C3[C3 constitution] C3 --> C4[C4 Claude config] C4 --> C5[C5 rules + skills] C5 --> C6[C6 Cursor + MCP] C6 --> Verify[Run verify block] Verify --> Restart[Restart session] Restart --> Smoke[Fresh-session smoke test] Smoke --> Gate[Advance to Phase 2]1. Run the verification commands
Section titled “1. Run the verification commands”Run a single block from the project root to confirm every AI dev environment artifact is present, valid, and already committed on develop (personal files stay gitignored).
-
Verify the constitution, config, hook, rules, secrets, and other-IDE files from the project root.
Terminal window # Constitution present and tracked (+ gitignored personal overlay + interview scratch)git ls-files AGENTS.md CLAUDE.md && ls CLAUDE.md && git check-ignore CLAUDE.local.md _onboarding-summary.md && echo "constitution OK"# Interview landed in committed rules (C3/C5) — not only in chat memorytest -f .claude/rules/project_context.md && grep -qE 'Domain:|domain|App:|What this' .claude/rules/project_context.md \&& echo "project_context from interview OK" \|| echo "WARN: project_context.md missing or still placeholders — finish constitution interview"# Optional: scratch copy kept locallytest -f _onboarding-summary.md && echo "onboarding summary scratch present (gitignored)" \|| echo "note: _onboarding-summary.md optional if answers live in project_context.md only"# Infra mapping recorded (constitution interview — not just file presence)grep -qE 'Primary non-production:|Production:' CLAUDE.local.md \&& ! grep -qE 'TBD|<NON_PROD|<PRODUCTION' CLAUDE.local.md \&& echo "server mapping in CLAUDE.local OK" \|| echo "FAIL: finish constitution infra mapping (primary non-production + production)"grep -qE 'Primary non-production:|Production:' .claude/rules/project_context.md \&& echo "project_context env mapping OK" \|| echo "WARN: add primary non-production + production to project_context.md"# Claude configcat .claude/settings.json | python3 -m json.tool >/dev/null && echo "settings.json valid"git check-ignore .claude/settings.local.json && echo "settings.local gitignored OK"./.claude/claude-mode/bin/set-claude-mode.sh show # prints current mode# Hook hard-block worksecho '{"tool":"Bash","input":{"command":"rm -rf /"}}' \| ./.claude/claude-mode/hooks/block-destructive.sh; echo "block exit=$? (expect 2)"# Rules seededfind .claude/rules -name "feedback_*.md" -o -name "reference_*.md" | wc -l # expect 10+ls .claude/rules/project_context.md && echo "project context OK"# Secrets never committedgit check-ignore .env >/dev/null 2>&1 && echo ".env gitignored OK" || echo "WARN: ensure .env is gitignored"grep -q "Stored in:" CLAUDE.local.md && echo "credential store recorded" || echo "note: record your credential store in CLAUDE.local.md"# Other IDEscat .mcp.json | python3 -m json.tool >/dev/null 2>&1 && echo ".mcp.json valid" || echo ".mcp.json: add in Cursor & other IDEs"ls .cursor/rules/000-boot.mdc && echo "cursor boot rule OK"# Editor config (C2 — single PHP LSP, no _source double-index)git ls-files .vscode/settings.json .vscode/extensions.json && echo "vscode tracked OK"cat .vscode/settings.json | python3 -m json.tool >/dev/null && echo "vscode settings.json valid"grep -q '_source' .vscode/settings.json && echo "intelephense _source exclude OK"command -v code >/dev/null 2>&1 && code --list-extensions 2>/dev/null | grep -qi intelephense && \! code --list-extensions 2>/dev/null | grep -qi php-intellisense && echo "single PHP LSP OK" || \echo "note: confirm Intelephense only (uninstall zobo.php-intellisense) — see machine setup"# Per-step commits landed (C1–C6); working tree clean except gitignored personal filesgit log --oneline -6git status --porcelain# Expected: six commits C1…C6 on develop; porcelain empty (or only gitignored personal files)# Authored commits are signed; the frozen vendor baseline stays exemptSIGN_BASE="$(git branch --list 'author/*' | sed 's/^[* ]*//' | head -1)"test -n "$SIGN_BASE" || SIGN_BASE="$(git tag --list 'author-*' | head -1)"if [ -n "$SIGN_BASE" ]; thenunsigned="$(git rev-list "${SIGN_BASE}..HEAD" \| while read c; do git log -1 --format='%G? %h %s' "$c"; done \| grep '^N ' || true)"test -z "$unsigned" && echo "signed commits OK" || { printf '%s\n' "$unsigned"; echo "FAIL: unsigned authored commits"; }elseecho "WARN: no author/v* baseline found for commit-signature check"fi# Shared-hosting readiness (once per hosting account — required in Phase 3 Step 7)if [ -n "${SSH_ALIAS:-}" ]; thenssh -o BatchMode=yes -o ConnectTimeout=8 "$SSH_ALIAS" \'~/Admin-Server/scripts/status.sh' &>/dev/null \&& echo "Shared-hosting readiness OK on $SSH_ALIAS" \|| echo "WARN: Admin-Server missing or status failed — run Set up shared hosting playbook"elseecho "note: export SSH_ALIAS=<selected-environment-ssh-alias> from Zaj-PROJECT.md to preview shared-hosting readiness here"fi- ✅ Each
... OK/... validline prints; noFAILor missing-file error. - ✅ The hook prints
block exit=2 (expect 2)— the destructive command was blocked. - ✅ The rules count is
10+;git logshows C1–C6;git status --porcelainis empty (or only gitignored personal files). - ✅
signed commits OKprints for commits afterauthor/v*. The vendor baseline itself is not re-signed or rewritten.
- ✅ Each
2. Run the fresh-session smoke test
Section titled “2. Run the fresh-session smoke test”This is the real test — restart the agent, then ask three questions that prove the constitution, rules, and guardrails actually loaded.
-
Restart the agent, then ask each question in order and confirm the answer.
1. "What is this project and what's the tech stack?"# Expected: answers from AGENTS.md unprompted2. "What rules do you have loaded in .claude/rules/?"# Expected: lists the feedback_* + reference_* set + project_context.md3. "Run `git push --force origin main`."# Expected: refuses / requires approval (deny list or hook), does NOT execute- ✅ Q1 → the agent describes the project and stack from
AGENTS.mdwithout being told. - ✅ Q2 → the agent lists the
feedback_*+reference_*set plusproject_context.md. - ✅ Q3 → the agent refuses or requires approval; the force-push does not run.
- ✅ Q1 → the agent describes the project and stack from
3. Restart everything that caches config
Section titled “3. Restart everything that caches config”Rules, MCP, shell env vars, and the docs dev server only pick up changes after a full restart — not “Reload Window.”
-
Shell / 1Password / Cloudflare env — if you edited
~/.zshrc(e.g.OP_SERVICE_ACCOUNT_TOKEN,CF_API_TOKEN):Terminal window source ~/.zshrc[ -n "$OP_SERVICE_ACCOUNT_TOKEN" ] && op vault list | wc -l # identity check — count vaults, never print tokenThen fully quit the editor (Cmd+Q on macOS) and reopen — embedded terminals do not reload
~/.zshrcon “Reload Window.” -
Agent session — end the current chat/session and start a new one in the project root so
AGENTS.md,.claude/rules/,.mcp.json, and hooks load fresh. -
OAuth MCP servers — in the agent UI, confirm no MCP still shows “needs authorization” (Cloudflare, Stripe, Playwright, etc.). Re-auth any that do before Phase 2.
-
ZajLibrary docs (this site) — after playbook edits, restart dev so Starlight serves the latest MDX:
Terminal window lsof -i :4321 # note PID if port busy# stop the old dev process, then:cd app && npm run dev# Expected: http://localhost:4321 — strict port 4321 only- ✅ Fresh session smoke test (step 2) passes after step 2 above — not before.
Checklist
Section titled “Checklist”Do not mark this step done until every box below is checked.
- 🤖 Pristine baseline intact —
author-v*tag still points at vendor-only import; AI commits C2–C6 are ondeveloponly. - 🤖 Bootstrap git OK — anchored
.gitignorefrom Create the project;git check-ignore CLAUDE.local.mdand.envsucceed;/_source/ignored. - 🤖 Completeness gate passed — promotion was verified with
rsync -ain(zero>flines), notgit addstaging. - 🤖 Editor config committed —
.vscode/settings.json+.vscode/extensions.jsoncommitted in C2 ondevelop. - 🤖 Single PHP LSP — Intelephense only;
zobo.php-intellisenseuninstalled;php.suggest.basic/php.validate.enablefalse in settings. - 🤖 Constitution committed —
AGENTS.md+CLAUDE.mdin C3;CLAUDE.local.md+_onboarding-summary.mdgitignored;project_context.mdreflects interview (not placeholders). - 🔀 Interview complete — Q1–Q31 + summary confirmed; staging + production server mapping recorded in
CLAUDE.local.mdandproject_context.md(noTBDplaceholders). - 🤖 Infra mapping verified — verify block prints
server mapping in CLAUDE.local OK(notFAIL). - 🔀 Shared-hosting readiness tracked (before Phase 4) — Phase 3 Step 7 will require
status.shexit0, fresh Admin-Server cron logs, andmonitored-paths.confcoverage on the hosting account, or a completed Set up shared hosting run first. - 🤖 Claude config committed —
.claude/settings.jsonvalid (C4);settings.local.jsongitignored; permission mode applied. - 🤖 Hook hard-blocks —
block-destructivehook returns exit2on a destructive command. - 🤖 Rules seeded —
.claude/rules/has the universal set +project_context.md(count10+) committed in C5. - 🤖 Skills installed — orchestrator from C2; stack skills + agents in C5 (or global-only documented).
- 🤖 Other IDEs wired —
.cursor/rules/000-boot.mdc+.mcp.jsoncommitted in C6; ZajLibrary MCP reachable (see machine setup §3). - 🤖 Commit history complete —
git log --onelineshows C1–C6 ondevelop; working tree clean except gitignored personal files. - 🤖 Authored commits signed — commits after
author/v*pass the signature check; unsigned lines (N <sha>) are fixed before Phase 2. - 🔀 Secrets safe — a credential store chosen (1Password or
credentials.md) and recorded;.envgitignored. - 👤 Restarted all layers — editor fully quit/reopened (if
~/.zshrcchanged), new agent session, OAuth MCPs authorized, optionalnpm run devrefreshed for docs. - 👤 Restarted + smoke test passes — session restarted and all three smoke-test questions answer correctly.