Run ./assess.sh. Expect: the first line reads == FLEET ASSESSMENT ==, and the
line right under it reads fleet 100.0% (83/83 tickets) fable-terminal:83/83+.
fable-terminal-build
Derived from: fable-terminal-build is not itself a git repository (it is a plain
Flows
check each step and final checkCold re-entry: fleet assessment
Proves a human or agent resuming this project can reconstruct its state from disk alone, with an honest next-action per unit — the empirical-state-first rule this whole kit runs on.
Persona / precondition: a shell in ~/Projects/fable-terminal-build, no other context.
Find the per-unit classification line. Expect: it reads exactlyDONE-MARKED fable-terminal 83/59 atom:none — idle -> audit-done.sh + dogfood-verify.sh before trusting
— the 83/59 (ground truth over spec total) is correct, not a typo: scope grew past
the original 59-ticket backlog through post-ship directive rounds, so ground truth
exceeding the original denominator is expected here.
Read the closing block. Expect: a QUESTIONS the orchestrator should resolve:
header followed by three bullets, the third one readingDONE-CLAIMED/DONE-MARKED units: run the audit before accepting; strip any that fail (L1)
— i.e. the script is explicitly telling you to go run F6 next, not asking you to trust
its own DONE-MARKED line at face value.
Final check: echo $? right after the run prints 0 — the assessment is read-only
and never fails the shell just because a unit happens to be done.
Ground truth progress, never ledger claims
Proves the fleet's percent-complete number is computed from git-verified atoms, not a self-reported ledger, and that scope growth past the original backlog is floored honestly instead of reporting a nonsensical percentage over 100%.
Persona / precondition: same shell.
Run ./progress.sh. Expect: exactly one line:fleet 100.0% (83/83 tickets) fable-terminal:83/83+.
Cross-check the 83 independently:git -C /Users/wolf/Projects/fable-terminal log --format=%s dev | grep -oE 'FT-T[0-9]+' | sort -u | wc -l.
Expect: 83 — the exact same number, computed the exact same way progress.sh
computes it internally (this is its ATOMS_DONE_CMD from project.env, run by hand).
Cross-check the spec's original total independently:grep -ohE 'FT-T[0-9]+' /Users/wolf/Projects/holt-ecosystem-packets/think-like-fable/build-fable-terminal/BACKLOG.yaml | sort -u | wc -l.
Expect: 59 — the trailing + on 83/83+ in step 1 is progress.sh's
denominator-floor marker: ground truth (83) exceeded the original 59-ticket backlog,
so it floors the denominator at 83 rather than printing a misleading ">100%".
Final check: the percentage from step 1 and the two independently-run counts from
steps 2-3 all agree with what F1 already reported — three separate reads, one consistent
story, none of them a ledger's self-report.
Cross-unit ledger survey
Proves the cheap survey tool reads real ledger fields correctly and degrades safely — no crash, no false report — when pointed at a slug that doesn't exist.
Persona / precondition: same shell.
Run ./watch.sh with no argument. Expect: one block starting=== fable-terminal OPEN-directives:0, followed by a line containing all four ofcurrent-atom: none — idle, last-gate: PASS @ 2026-07-11T01:28:35Z,milestone: complete, and blockers: DONE.
Run ./watch.sh fable-terminal (explicit slug this time). Expect: the identical
block to step 1.
Run ./watch.sh nonexistent-slug-xyz. Expect: no output at all, and exit code 0
— an unknown slug is silently skipped rather than erroring. Worth knowing even though
it's arguably not a bug: a typo'd slug produces silence, not a "not found" message.
Final check: echo $? after step 3 still prints 0 — watch.sh never fails the
shell regardless of what it does or doesn't find.
Live dashboard and its alive-check — KNOWN DEFECT
Proves the per-agent dashboard renders ledger and log narration correctly, AND exposes a real, currently-reproducible false positive in its "is a worker actually running" check.
Persona / precondition: same shell; confirm no real fleet worker is currently running before you start (step 2 below is how).
Run ./dashboard.sh. Expect: one block shaped like<●|○> fable-terminal | current-atom: none — idle | last-gate: PASS @ 2026-07-11T01:28:35Z | blockers: DONE
followed by a └─ narration line pulled from logs/fable-terminal.log (plain
worker-voice text, e.g. mentioning a ⚠ Deferred: note about live Pi verification —
no raw diff hunks, no exec echo lines).
Independently confirm whether a real worker is alive, using the tightened patternassess.sh itself uses (executor name AND slug, not slug alone):pgrep -fl "codex.*fable-terminal". Expect: no output — nothing matches, so the
correct marker in step 1 is ○ (dead).
Expose the defect. Start a decoy background process whose command line merely
contains the slug substring and has nothing whatsoever to do with the fleet:yes fable-terminal >/dev/null & echo "decoy pid: $!" (note the PID it prints). Run./dashboard.sh again. Correct behaviour: the marker should stay ○ — a bareyes fable-terminal process is not a fleet worker. Currently fails: the marker
flips to ● (alive), because dashboard.sh's check is the untightenedpgrep -f "$slug" — it matches any process anywhere on the machine whose full
command line contains the slug string, not specifically the executor running it.assess.sh already carries the fix for exactly this failure class (it greps"${WORKER_CMD%% *}.*$slug", i.e. codex.*fable-terminal); dashboard.sh was never
patched to match. Clean up: kill <the decoy pid>.
Re-run ./dashboard.sh after killing the decoy. Expect (once the defect above is
fixed): the marker returns to ○. Caveat observed live while authoring this
plan: it can still read ● with the decoy gone, because any other unrelated
process on the machine whose command line happens to contain fable-terminal (e.g. a
shell sitting in that directory, or another tool grepping the project path) satisfies
the same untightened match — this is the same defect surfacing again, not a second bug.
Final check: grep -n 'pgrep -f "\$slug"' dashboard.sh still finds the line — until
it is patched to the same codex.*<slug>-style pattern assess.sh uses, do not trustdashboard.sh's ●/○ marker on its own; cross-check with step 2's command by hand.
Control-bus integrity sweep
Proves every unit's control bus is valid, parseable YAML before anything reads from it or appends to it — corruption caught here is corruption that never steers a worker wrong.
Persona / precondition: same shell; python3 on PATH.
Run ./bus-sweep.sh. Expect: bus sweep clean (1 buses parse) and exit code 0.
Confirm independently what it actually validated:python3 -c "import yaml; yaml.safe_load(open('/Users/wolf/Projects/fable-terminal/_pipeline/CONTROL.yaml')); print('VALID')".
Expect: VALID printed — the exact same file bus-sweep.sh swept.
Final check: F3's OPEN-directives:0 and this flow's clean sweep agree — a bus with
zero pending directives and a clean parse is why F1 correctly classifies the unit as fully
resolved rather than "RUNNING (+N pending directive)".
Audit a DONE claim before trusting it
Proves the integrity gate a DONE marker must clear before anyone accepts it — a marker is a claim, ground truth is what settles it — by cross-checking ledger claims against git history and required completion deliverables.
Persona / precondition: same shell; about to accept fable-terminal's DONE marker per F1's own stated advice.
Run ./audit-done.sh fable-terminal. Expect, in order:== done-audit: fable-terminal (1 dir(s)), then atoms — spec total: 59, ledger claims: 83, ground truth: 83, then ✓ eval-report.md, then ✓ self-use recorded, then AUDIT PASS, exit code 0.
Run it with no slug: ./audit-done.sh. Expect: a slug usage error on stderr
(bash's ${1:?slug} firing) and exit code 1.
Run it against a slug that was never built: ./audit-done.sh nonexistent-slug-xyz.
Expect: no workspace dirs for nonexistent-slug-xyz and exit code 1 — it refuses
to audit something with no workspace rather than reporting a false pass.
Final check: the 83 ledger-claims count and the 83 ground-truth count from step 1
agree exactly. If a future re-run ever shows ledger claims exceeding ground truth, that is
this script's own ✗ ledger claims exceed ground truth — FABRICATION SUSPECT line firing
— the marker gets stripped at that point, not argued with.
The merge gate refuses an empty pass
Proves the reviewer/worker landing gate cannot be satisfied by silence — zero configured checks must fail loud, never pass by accident.
Persona / precondition: same shell.
Run ./gate.sh with no argument. Expect: usage: gate.sh <unit-workspace-dir> on
stderr and exit code 1.
Run ./gate.sh /Users/wolf/Projects/does-not-exist. Expect:GATE FAIL: no such unit /Users/wolf/Projects/does-not-exist and exit code 2.
Run ./gate.sh /Users/wolf/Projects/fable-terminal-build — this harness directory
itself, which has no package.json and no GATE_CMD. Expect:GATE FAIL: no checks defined (set GATE_CMD, add a package 'gate' script, or uncomment checks)
and exit code 2 — an empty gate must fail loud rather than silently pass, which is
the exact regression the script's own header comment documents having fixed before.
Not run this session — this is a heavy build (bun run gate = typecheck + lint +
test + build inside a live sibling repo), and this pass's scope was read-only/no
service restarts, so it was deliberately skipped: running./gate.sh /Users/wolf/Projects/fable-terminal for real. The historical record in that
repo's own _pipeline/STATUS.md claims last-gate: PASS @ 2026-07-11T01:28:35Z
(379 pass / 4 skip / 0 fail, 2367 expects) — treat this as an expectation to confirm,
not a fact verified today. A tester with a time budget should run it for real and
compare against that historical line.
Final check: grep -n GATE_CMD project.env in this harness prints nothing — confirms
step 3's fail path is the actual live configuration a tester will hit, not a contrived one.
Mutating tools fail closed on bad arguments
Proves the write-path tools validate their argument shape BEFORE touching a live control bus or launching a worker — a dropped argument must be a loud usage error, never a silent misfire that shoves the wrong thing into a payload field.
Persona / precondition: same shell. This flow deliberately never supplies valid, complete arguments — it only walks the refuse-to-run boundary, so nothing is appended to any control bus and no worker is launched.
Run ./inject.sh with no arguments. Expect: a unit dir usage error on stderr and
exit code 1.
Run ./inject.sh /Users/wolf/Projects/fable-terminal bogus-type target "instr".
Expect:usage error: unknown type 'bogus-type' — arg order is <unit-dir> <type> <target> "<instruction>" [guard]
on stderr and exit code 2 — the fixed directive-type vocabulary
(correct|reprioritize|skip-atom|pause|resume|run|stop) is enforced before any file on
disk is touched.
Run ./pool.sh with no arguments. Expect:usage: pool.sh <concurrency> <slug...> on stderr and exit code 1.
Run ./keep-fed.sh with no arguments. Expect:usage: keep-fed.sh <K> <slug...> on stderr and exit code 1.
Not executed this session (a real run would append a live directive to the control
bus) — verified by reading inject.sh's source instead of running it: it cp's the
control bus to a .pre-inject backup before appending, then re-parses the whole file
with python3 -c "import yaml..." after the append; on a parse failure it mv's the
backup back over the live file and prints INJECT REJECTED + ROLLED BACK: rather than
leaving a poisoned bus behind. This is an expectation to confirm by reading the code at
the lines guarded by its own header comment (WF-19/L22), not something this pass
exercised end-to-end.
Final check: git -C /Users/wolf/Projects/fable-terminal status --short _pipeline/CONTROL.yaml
prints nothing — confirms steps 1-4 mutated nothing in the live control bus.
Remote-offload capacity check
Proves the memory-pressure probe that decides local-vs-remote relaunch reports a real, current number rather than a placeholder, and that the remote lane is honestly unconfigured for this single-unit build rather than silently assumed.
Persona / precondition: same shell.
Run ./offload.sh check. Expect: a line matching OK free=<N>% threshold=20%
(or PRESSURE/CRITICAL if this machine happens to be under real memory pressure right
now) where <N> is a live, non-placeholder percentage.
Confirm no remote targets are configured: grep '^OFFLOAD_HOSTS=' project.env.
Expect: OFFLOAD_HOSTS="" — this is a stated, intentional gap for a single-unit
build (see project.env's own comment above that line), not a defect: offload.sh auto
would have nowhere to send work even under real pressure.
Final check: step 1's reported percentage is above threshold=20% (an OK verdict,
not PRESSURE/CRITICAL) — consistent with this being an idle, already-completed fleet
with no active build load on the machine.
Generated surfaces stay in sync
Proves the kit's "generated files are never hand-edited, and every mirror stays synced" rule actually holds for this project's two instruction surfaces and its vendored kit copy.
Persona / precondition: same shell.
Run diff CLAUDE.md AGENTS.md. Expect: exactly one changed line pair (1c1) — the
two files differ ONLY in their generator-source comment (CLAUDE-block.md vsAGENTS-block.md); every doctrine line below it is byte-identical between the two.
Confirm both carry the required generated-file header:head -2 CLAUDE.md && head -2 AGENTS.md. Expect: every line printed contains bothGENERATED FROM and DO NOT EDIT.
Run diff -rq ./think-like-fable /Users/wolf/Projects/holt-ecosystem-packets/think-like-fable.
Expect: no output at all — the kit-kernel mirror vendored into this build harness is
fully in sync with the canonical source, zero drift.
Final check: none of steps 1-3 required editing anything — this flow is purely
diff-based, proving sync exists without risking a hand-edit to a generated file.
The Kanban board's claim about this project — KNOWN GAP
Proves (or, here, disproves) that Observify's board reflects this project's actual, disk-verified state rather than a stale guess frozen at whatever it last saw.
Persona / precondition: the Observify server reachable at 127.0.0.1:8787; this flow is a read-only GET only, nothing is posted.
Run curl -s "http://127.0.0.1:8787/api/kanban?project=fable-terminal-build".
Expect: the JSON has "reachable": true and a "projects" entry whose "id" is"fable-terminal-build".
In that same JSON, read the project entry's "column_counts". Expect (this is where
the board is currently WRONG, not this document):{"backlog": 2, "in_progress": 0, "running": 0, "in_development": 0, "testing": 0, "done": 0, "deployed": 0}
— both of this project's cards sit in Backlog with every other column at zero, even
though this session's own ground truth (F1, F2, F6) shows the fleet is 100% complete,AUDIT PASSed, and Pi-deploy-verified through directive d69 per its own _handoff doc.
Correct placement is deployed or done, not backlog.
Read the project entry's "freshness" field. Expect: "unknown" — not a bug by
itself: fable-terminal-build has no .git (F10 territory is the sibling repo, not
this harness), so the board has no git-timestamp signal to compute freshness from, and
it says so honestly rather than guessing.
Read either card's "last_activity" block. Expect: an "age_text" of several days
(e.g. "7d ago" as of this authoring pass, timestamped Jul 31, 2026) — the board is
honestly reporting staleness at the card level, it just hasn't been reconciled into a
corrected column per step 2.
Final check: this is the concrete, testable fix for step 2 — run /update-board (not executed in this read-only pass), then repeat step 1's
fable-terminal-buildcurl;column_counts should move both cards out of backlog into deployed/done.
Not covered and why
- **A real end-to-end
gate.sh/dogfood-verify.shrun against the livefable-terminal
unit:** heavy build (typecheck+lint+test+build, plus a transient dev-server boot for the
health probe) — out of scope for a read-only pass; F7 step 4 names the exact command and
the historical baseline to compare against.
- A real
inject.shappend,pool.shlaunch, orkeep-fed.shloop: each would either
mutate the live control bus or actually spawn a codex exec worker against the unit —
F8 proves the argument-validation boundary only, by design.
offload.sh bootstrap/run/autoagainst a real remote host:OFFLOAD_HOSTSis
unset (F9), so there is no remote target to bootstrap against; this is a genuine
never-configured surface, not a skipped test.
- The five
done.txt.bak-*backup files' provenance: they appear to be the Article-IV
"backup before destructive write" trail from repeated keep-fed/inject rounds; not
independently verified beyond confirming they exist and all carry the same completion
marker (per the project's own _handoff note).
EXECUTORS_FILE=executors.txt(referenced inproject.env, absent on disk):
confirmed absent; harmless per the file's own comment (optional; single unit — DEFAULT_MODEL) and never consulted by this run's single-executor path — a stated gap,
usually suffices
not exercised here.
Results
| Flow | Verdict | Failures → tickets |
|---|---|---|
| F1 cold re-entry assessment | ||
| F2 ground-truth progress | ||
| F3 cross-unit ledger survey | ||
| F4 dashboard alive-check (KNOWN DEFECT) | ||
| F5 control-bus integrity sweep | ||
| F6 audit a DONE claim | ||
| F7 merge gate empty-pass refusal | ||
| F8 mutating-tool argument safety | ||
| F9 remote-offload capacity check | ||
| F10 generated-surface sync | ||
| F11 Kanban board ground-truth (KNOWN GAP) |