Run git init my-test-project && cd my-test-project. Expect: a normal git init message
ending Initialized empty Git repository in .../my-test-project/.git/.
wolf-orchestra
Derived from: no git repo present at ~/Projects/wolf-orchestra (confirmed via `git
Flows
check each step and final checkFresh-project bootstrap (the Quickstart copy-in)
Proves the README's stated install path actually produces a working project skeleton.
Persona / precondition: a new, empty directory outside this repo; none of wolf-orchestra's files present yet.
Run cp -r ~/Projects/wolf-orchestra/{.claude,.claude-plugin,skills,scripts,CLAUDE.md} .
exactly as the README's Quickstart shows it. Expect: the copy succeeds with no error, andls -A now shows .claude, .claude-plugin, skills, scripts, CLAUDE.md — verified
this exact command copies cleanly on the reference machine.
Run test -f .claude/settings.json && test -x scripts/worktree.sh && echo OK. Expect:OK — the hook config and an executable script both survived the copy.
Open CLAUDE.md in the new project. Expect: it opens with # wolf-orchestra — Conductor and lists the routing table (Escalation ceiling / Conductor / Implementer /
Constitution
Recon / Codex worker / … / Verdict oracle) — ten rows, matching this repo's own CLAUDE.md.
Start claude inside the new project (manual — needs an interactive terminal). Expect: the
session starts as the conductor and, per Hard rule 6 in CLAUDE.md, is expected to end its
first unit of work with a red/yellow/green /recap line. NOT independently exercised in
this pass — confirm manually in a live session.
Final check: diff -rq ~/Projects/wolf-orchestra/scripts my-test-project/scripts reports
no differences — the copied scripts are byte-identical to the source, so nothing about the
copy step silently mutated them.
Worktree lifecycle: one-vendor-per-worktree enforcement
Proves Hard rule 1 ("one vendor per worktree") is a real, live-tested guard, not just prose.
Persona / precondition: a scratch git repo (git init, one commit) with ORCHESTRA_ROOT exported to point at it, so nothing touches the real wolf-orchestra checkout.
Run ~/Projects/wolf-orchestra/scripts/worktree.sh new TEST-1. Expect: stderr shows[orchestra] worktree ready: <path> and stdout's last line is the bare worktree path<ORCHESTRA_ROOT>/.orchestra/worktrees/TEST-1; git worktree list now shows two entries
(main checkout + the new one on branch orchestra/TEST-1) — verified live, exit 0.
Run the identical command again: scripts/worktree.sh new TEST-1. Expect: it refuses
rather than silently reusing or duplicating — exact stderr [orchestra] FATAL: worktree, exit 1 — verified live.
exists for TEST-1 (one vendor per worktree)
Run scripts/worktree.sh clean TEST-1. Expect: stderr shows [orchestra] cleaned TEST-1,
exit 0, and git worktree list is back down to just the main checkout — verified live.
Run scripts/worktree.sh clean NEVER-EXISTED (a task that was never created). Expect: it
does not error — [orchestra] cleaned NEVER-EXISTED, exit 0 (the script's || true guards
on both the worktree remove and branch -D calls) — verified live.
Inspect .orchestra/.gitignore in the scratch repo. Expect: it was auto-created containing
exactly *, so worktrees and reports never show up in git status of a consumer project —
verified live.
Final check: git status --short in the scratch repo shows nothing untracked from any of
the above — the self-ignoring .orchestra/.gitignore from step 5 is doing its job.
Vendor CLI flags are still accurate (Article III re-verification)
Proves the "flags verified against installed CLI" comments in the run-.sh wrappers are not stale — each wrapper's exact invocation is checked against the CLI actually installed today.*
Persona / precondition: codex, agy, and grok installed and on PATH.
Run codex exec --help and check for -m, --model, -s, --sandbox <SANDBOX_MODE> withworkspace-write listed as a possible value, and -o, --output-last-message <FILE>.
Expect: all three are present exactly as scripts/run-codex.sh uses them
(codex exec --model "$model" --sandbox workspace-write -o "$last" ...) — verified live
against codex-cli 0.146.0.
Run agy --help and check for -p/--print, --model, and --print-timeout with a
stated default. Expect: all three present, and the default is 5m0s — matchingscripts/run-gemini.sh's own comment ("--print-timeout defaults to only 5m, so raise it")
and its ${AGY_PRINT_TIMEOUT:-30m} override — verified live against agy 1.1.9.
Run grok --help and check for -p, --single <PROMPT>, --json-schema <SCHEMA> (its help
text says it "Implies --output-format json"), and -m, --model <MODEL>. Expect: all three
present exactly as scripts/run-grok.sh uses them — verified live against grok 0.2.117.
Compare the README's Quickstart dependency line ("codex ... · gemini · grok (x.ai/cli) ·
ollama") against what scripts/run-gemini.sh actually invokes. Expect (KNOWN DEFECT,
confirmed): the script calls require agy ... and runs the agy binary — never gemini —
yet neither the README's deps line nor its Config section names agy anywhere (CLAUDE.md
and AGENTS.md DO say "codex/grok/agy/ollama" in Article I, so the two docs disagree with
each other on the vendor's actual command name). A user who installs the real Googlegemini CLI following the README literally will find it never gets invoked, and agy is
not on PATH. Confirmed: command -v gemini → not found, command -v agy → found, on this
machine. This currently fails; correct behavior is the README naming the binary it actually
shells out to.
Grep the README's Config section for AGY_PRINT_TIMEOUT and GROK_FLAGS. Expect (KNOWN
DEFECT, confirmed): neither appears, even though scripts/run-gemini.sh readsAGY_PRINT_TIMEOUT and scripts/run-grok.sh reads GROK_FLAGS as live overrides. This
currently fails; correct behavior is both env vars listed alongside CODEX_MODEL etc.
Final check: none of the three vendor wrappers' documented flags have silently changed
meaning since the "Jul 2026" comment date — re-running steps 1-3 a month later (2026-08-07)
still matches, so Article III's guard is currently satisfied for the flags themselves (only
the naming/docs gaps in steps 4-5 are open).
Async run polling contract (start / wait / status)
Proves the reason this harness exists at all: no single Bash call ever blocks past the harness timeout, because long vendor runs are detached and polled in bounded chunks.
[sensitive content omitted]
Run scripts/run-async.sh status NOPE-1 for a task that was never started. Expect: prints
exactly NONE, exit 0 — verified live.
Manually create .orchestra/reports/SIM-1.async/ with t0 (a timestamp) and exit
containing 0 (simulating a vendor run that already finished successfully — the same
files run-async.sh start's detached _exec branch would have written). Runscripts/run-async.sh status SIM-1. Expect: DONE, exit 0. Then runscripts/run-async.sh wait SIM-1. Expect: stderr logs [orchestra] SIM-1 finished exit=0, stdout prints
(log: ...)DONE, exit 0 — verified live.
Repeat step 2 with exit containing 3 (simulating a failed vendor run) under taskSIM-2. Expect: status prints FAILED (exit 3); wait prints bare FAILED (no exit
code suffix) and exits 3 — this asymmetry between status's and wait's FAILED text is
real script behavior, not a typo; both were verified live.
elapses with no exit file, it kills the process tree (pkill -P then kill),
logs a TIMEOUT line, and prints FAILED with exit 3 — read from source, not forced live
(forcing a real 3600s timeout is impractical for this pass).
Final check: every exit code run-async.sh can produce (0 = DONE, 3 = FAILED, 10 =
RUNNING/call-again) is accounted for by the two subagent courier specs (codex-worker.md,grok-swarm.md) that loop on it — both explicitly say "RUNNING (exit 10) means the vendor is
still working — call wait again; do not treat it as an error."
Report validation gate
Proves Hard rule 3 ("reports must validate against report.schema.json") actually rejects a malformed report rather than waving it through.
Persona / precondition: scratch repo with a copy of skills/report-protocol/references/report.schema.json under the same relative path (so scripts/lib/common.sh's SCHEMA variable resolves).
Write a report JSON with all nine required fields (task_id, agent, model, status,worktree, files_touched, commands_run, evidence, uncertainties) andstatus: "done". Source scripts/lib/common.sh and call validate_report on it. Expect:
exit 0 (valid) — verified live.
Write a second report missing the agent field entirely. Call validate_report on it.
Expect: exit 1 (invalid) — the schema's required list is enforced, not decorative —
verified live.
Write a fake vendor transcript: some free-text prose, then a fenced `json block
containing a valid report object. Call extract_json on the transcript file. Expect: it
prints the fenced JSON object exactly (parses clean via python3 -m json.tool) — this is
the exact mechanism normalize-report.sh's deterministic fast-path depends on before it
ever calls the (paid) Nemotron fallback — verified live.
Final check: report-protocol/SKILL.md's claim "Grok emits it natively via
--json-schema" matches scripts/run-grok.sh, which pipes grok's own --json-schema-
constrained stdout straight to validate_report with no Nemotron step in between — read from
source, consistent.
Verdict-oracle dependency guard
Proves the notebooklm-oracle path fails loudly and exactly when its dependency is missing, rather than silently downgrading a verdict.
Persona / precondition: a machine where notebooklm (the notebooklm-py pip CLI) is NOT installed — true on the reference machine at snapshot time.
Confirm the precondition: run command -v notebooklm. Expect: not found (this machine has
codex/agy/grok/ollama but never had notebooklm-py installed) — verified live.
Run scripts/ask-notebooklm.sh some-notebook "test claim". Expect: it does not hang or
produce a partial/garbage verdict — exact stderr [orchestra] FATAL: missing dependency:, exit 1 — verified live.
notebooklm (pip install notebooklm-py && notebooklm login)
Re-read skills/report-protocol/SKILL.md's conductor obligation #4 ("A model cannot
self-finalize 'validated' — the citation is the evidence"). Expect: consistent with step 2
— since the script cannot even start without the dependency, there is no code path where a
claim reaches "validated" without a real NotebookLM citation.
Final check: once pip install notebooklm-py && notebooklm login has actually been run
(not done in this pass — would install software on the host per Article IV consent rules),
re-running step 2 should instead reach the real notebooklm chat call. NOT independently
verified in this pass.
Conductor model-pin doctrine consistency
Proves the workspace's live settings match what CLAUDE.md/AGENTS.md tell every session to believe about who the conductor is.
Persona / precondition: read access to .claude/settings.local.json and this repo's own CLAUDE.md.
Read .claude/settings.local.json. Expect to find a "model" key. Confirmed present:"model": "claude-fable-5".
Read CLAUDE.md's routing table. Expect: Conductor | Claude Opus 4.8 | this session: plan, is a DIFFERENT row from
route, judge, integrateEscalation ceiling | Claude Fable 5 | — and
wrong-is-expensive, long-horizon core componentsskills/conductor-routing/ likewise dispatches the
references/routing.jsonescalation-ceiling tier only tosubagent:fable-core (a worktree-isolated subagent), never to main-session. Confirmed
present as described.
Compare steps 1 and 2 (KNOWN DEFECT, confirmed). Expect: the interactive session's model
pin should match the tier the docs call "Conductor" (claude-opus-4-8 per routing.json's
own tier id), since Fable 5 is documented and dispatched exclusively as the escalation-
ceiling subagent, not the main session. Actual: the live pin is claude-fable-5 — the
escalation-ceiling model — with no corresponding doc update. .claude/ (the pre-change backup, still present in the repo)
settings.local.json.bak-model-pin
confirms this was a deliberate, dated edit that never propagated to CLAUDE.md/AGENTS.md/
routing.json. This currently fails.
Final check: whichever way this is resolved (repin the session to Opus, or update the
three doc surfaces to declare Fable 5 the new conductor tier), CLAUDE.md, AGENTS.md, and
routing.json must all say the same thing after the fix — they are three independent copies of
the same claim today.
Worked-example routing coverage
Proves the one worked example (ClipMark) actually routes through tiers that exist, so a new user copying its pattern doesn't dispatch to a tier the routing table doesn't define.
Persona / precondition: examples/clipmark/TICKETS.md and skills/conductor-routing/references/routing.json both present.
List every tier id in routing.json's tiers array. Expect exactly ten: escalation- — verified live via
ceiling, conductor, implementer, recon, codex-worker, codex-bulk, big-context-audit,
cheap-swarm, local-glue, verdict-oraclepython3 -m json.load.
For each of the 15 tickets (CLIP-001 … CLIP-015) in TICKETS.md's table, check that its
"Tier → Worker" column names one of the ten tiers from step 1. Expect: 13 of 15 do
(escalation-ceiling, conductor, implementer ×2, codex-worker ×2, codex-bulk, big-context-
audit, cheap-swarm ×2, local-glue ×2, verdict-oracle) — verified live, all match.
Look at the remaining two: CLIP-014 ("second-opinion: Sol via codex, cross-checked by
conductor") and CLIP-015 ("one-shot Pro-tier escalation"). Expect: these are deliberately
descriptive one-off escalations rather than routing-table tier names — consistent with
conductor-routing's escalation ladder being a default path, not the only path, for a
named "nastiest bug budget" ticket. Not a defect; noted so a tester doesn't mistake it for
one.
Final check: every tier actually named in step 2 has a real subagent or script backing it
(fable-core.md, sonnet-impl.md, codex-worker.md + run-codex.sh, gemini-auditor.md +run-gemini.sh, grok-swarm.md + run-grok.sh, nemotron-local.md + run-nemotron.sh,notebooklm-oracle.md + ask-notebooklm.sh) — confirmed all seven files exist.
Marketplace plugin manifest shape
Proves the plugin half of the install path (/plugin marketplace add <this-repo>) has a well-formed manifest before a human ever points Claude Code at it.
Persona / precondition: .claude-plugin/plugin.json present.
Run python3 -m json.tool .claude-plugin/plugin.json. Expect: parses with no error —
verified live.
Inspect the parsed object. Expect fields: name: "wolf-orchestra", a non-emptydescription, version: "1.1.0", author.name: "[redacted]", license: "MIT" — all present
as read from the file.
Confirm plugin.json does not itself list commands, agents, or scripts paths.
Expect: it doesn't — consistent with the README's claim that only skills/ auto-
discovers at the plugin root, and agents/commands/scripts "ride the project-copy path"
instead. Read from source; the actual /plugin marketplace add install behavior itself
is NOT independently exercised in this pass (needs a live Claude Code marketplace call) —
confirm manually.
Final check: after a manual /plugin marketplace add + install, skills/conductor-,
routingskills/handoff-packets, and skills/report-protocol should each appear as
discovered skills — confirm manually.
Kanban board reflects reality
Proves Observify's board for this project is telling the truth about a kit that has no git history and has never run a live session.
Persona / precondition: Observify reachable at http://127.0.0.1:8787.
GET http://127.0.0.1:8787/api/kanban?project=wolf-orchestra. Expect: "reachable": true
and a projects entry with "id": "wolf-orchestra" — verified live.
Check that project's column_counts. Expect: "backlog": 3 and every other column
(in_progress, running, in_development, testing, done, deployed) at 0 —
matching the fact that no work has been marked started on this kit — verified live.
Check git_last_touch_ts and freshness for this project. Expect: git_last_touch_ts: and
null"freshness": "unknown" — a direct, correct consequence of this project having
no .git directory (confirmed in this document's provenance line), not a board bug.
Read the three backlog card texts. Expect one of them to be the literal baseline cardRepo baseline — wolf-orchestra (README.md) and one to include NEXT: run the ClipMark — verified live, both present.
pilot end-to-end
Final check: none of this GET request created, modified, or deleted anything on the
board — confirmed by re-running step 1 and getting byte-identical column_counts.
Illustrative docs open cleanly
Proves the two files in docs/ — the only visual explanation of the pipeline a new reader gets before their first /orchestrate — are not broken artifacts.
Persona / precondition: a browser and, ideally, a Mermaid-aware viewer (VS Code's Mermaid preview, or pasting into an Artifact).
Open docs/session-view.html directly in a browser (file:// path is fine — it's fully
self-contained, no external requests). Expect: a dark terminal-styled mock-up titled
"wolf-orchestra — session view" renders with no visible broken layout. Structurally
verified (all HTML tags balanced via a parse check); visual rendering itself NOT
independently confirmed in this pass — confirm manually.
Open docs/workflow.mermaid in a Mermaid-aware viewer. Expect: a flowchart renders with
four subgraphs (CONDUCTOR, DISPATCH, SPECIALISTS, EXT) and no syntax error. Structurally
verified (4 subgraph / 4 matching end — balanced); actual rendering NOT independently
confirmed in this pass (no local Mermaid renderer available) — confirm manually.
Final check: the flowchart's escalation node (ESC{"escalate 1 rung ..."}) and its two
inbound edges (RV -->|blocked / failed| ESC, VF -->|contradicted| ESC) both point at the
same node id — confirmed by reading the source text.
This file is discoverable by Observify's /testit surface
Proves the two-consumer promise in the Founder's request: one authoring pass lights up both the board-book chapter and Observify's own /testit page — verified against the SHIPPED parser, not a re-implementation.
Persona / precondition: this exact file at ~/Projects/wolf-orchestra/USER_TESTING.md.
Load observify.py's actual _TESTIT_FLOW_RE, _TESTIT_STEP_RE, _TESTIT_FINAL_RE,_TESTIT_RECORD_RE, _TESTIT_DERIVED_RE, and _testit_parse_text into a scratch
namespace (sliced verbatim from /Users/wolf/Projects/observify/observify.py, not
retyped) and run this file's text through _testit_parse_text. Expect: it returns a
non-empty derived_from string and a flows list of length 12. Verified live — see
session evidence below.
Check each flow's item_count is greater than zero (every flow has at least one
parseable numbered step or Final check). Expect: true for all 12 flows — verified live.
Sum every flow's len(items). Expect this to equal the total item count Observify's own_testit_parse_text reports in its return value's item_count field — verified live
(see the exact number reported alongside this plan).
Place this file at ~/Projects/wolf-orchestra/USER_TESTING.md (already true — this is
where it was written) and confirm _testit_discover_plans()'s directory-name filterre.fullmatch(r"[a-z0-9-]+", entry.name) accepts wolf-orchestra as a slug. Expect:
match succeeds (all lowercase, digits, and hyphens) — verified live.
Final check: open Observify's /testit index page in a browser and confirm awolf-orchestra card now appears alongside agentify's — confirm manually (this pass
verified the parser accepts the file; it did not drive the live HTTP page).
Not covered and why
[sensitive content omitted]
across Codex, Grok, and (if configured) Gemini/agy for a full pipeline run; F1-F9 verify
every stage of that pipeline's contract in isolation instead, without spending money.
- NotebookLM verdict oracle end-to-end —
notebooklm-pyis not installed on the
reference machine (F6 verifies the dependency guard instead of the real call).
- Live
/plugin marketplace addinstall — needs an interactive Claude Code session
driving its own marketplace UI; F9 verifies the manifest shape it would consume.
- Fable-core / sonnet-impl subagents actually producing a component — these are Claude
Code subagents invoked from within a live session, not standalone scripts; their contract
(worktree isolation, report-protocol output) is read from source and cross-checked in F5
and F8, not executed here.
- The SessionStart hook's live injection (
kit-remember-hook.sh) — running it exercises
the much larger think-like-fable/tools/remember.py canon-read machinery, which is out of
scope for this project's own USER_TESTING pass; confirmed only that the hook file exists,
is executable, and is wired correctly in .claude/settings.json.
Results
| Flow | Verdict | Failures → tickets |
|---|---|---|
| F1 fresh-project bootstrap | ||
| F2 worktree lifecycle | ||
| F3 vendor CLI flags | ||
| F4 async run polling | ||
| F5 report validation gate | ||
| F6 verdict-oracle dependency guard | ||
| F7 conductor model-pin consistency | ||
| F8 worked-example routing coverage | ||
| F9 marketplace plugin manifest | ||
| F10 kanban board reflects reality | ||
| F11 illustrative docs open cleanly | ||
| F12 /testit self-discovery |