Add /spec-loop skill: five-phase spec loop with cross-model review - #66
Add /spec-loop skill: five-phase spec loop with cross-model review#66yulonglin wants to merge 4 commits into
Conversation
SPEC-A deliverables: the spec-loop skill (Workflow template driving plan/implement/test/run/analyze with a codex-companion adversarial review after each phase, findings injected into the next phase's prompt), three spec-refinement prompts carrying the five-section template, the detect-only warn_spec_outside_vault.sh hook plus its settings wiring, spec-conventions updated to the five-section template, interview conventions, and three test suites (template 53/53, prompts 28/28, hook 15/15). Template hard-won fixes pinned by tests: Workflow args can arrive as a JSON-encoded string (T8); codex-companion's terminal success status is "completed", not "success" (T4). Claude-Session: https://claude.ai/code/session_01Mm1WU9eHyEYQWVUPtq46Um
Lands after the skill commit per the e2e mini-spec's A2 landing dependency: the row must not exist before claude/skills/spec-loop/ does (verified: git cat-file -e HEAD:claude/skills/spec-loop/SKILL.md). Claude-Session: https://claude.ai/code/session_01Mm1WU9eHyEYQWVUPtq46Um
| @@ -0,0 +1,9 @@ | |||
| # Interview Conventions | |||
|
|
|||
| How spec interviews (`/spec-interview`, `/spec-interview-research`, `/grill-me`, and the spec-loop plan phase) collect decisions from Yulong. | |||
There was a problem hiding this comment.
Shall we standardise/merge?
There was a problem hiding this comment.
Merged — interview-conventions.md is deleted and its content now lives as an "Interview conventions" section in claude/rules/spec-conventions.md, so one file owns spec + interview standards. Note /spec-interview and /spec-interview-research are plugin skills outside this repo, so the rule documents the convention they should follow rather than editing them directly.
|
|
||
| How spec interviews (`/spec-interview`, `/spec-interview-research`, `/grill-me`, and the spec-loop plan phase) collect decisions from Yulong. | ||
|
|
||
| **Channel by question count.** Four questions or fewer → one batched `AskUserQuestion` call. More than four → a single markdown answer file delivered via `SendUserFile`, never a sequence of prompts. |
There was a problem hiding this comment.
A large batched AskUserQuestion call with 10-20 is fine too?
There was a problem hiding this comment.
Yes — encoded in the merged section: AskUserQuestion caps a single call at 4 questions, so 10-20 questions run as a series of successive batched calls (explicitly blessed as fine), or as a single markdown answer file when questions need long what-I-found preambles or async answering. The anti-pattern is a drip of one-question prompts; /grilling stays the deliberate one-at-a-time exception.
| @@ -0,0 +1,8 @@ | |||
| <!-- Verbatim body from ~/vault/specs/2026-08-09-workflow-specs-interview-round1.md §Q5 "Cleaning spec". Do not edit between the verbatim markers — the body is sha256-guarded in tests/test_spec_loop_prompts.sh. --> | |||
| <!-- verbatim-begin --> | |||
| clean this up for clarity and concision. remove unnecessary details | |||
There was a problem hiding this comment.
critique and improve on this. also some things like audit trails aren't always needed. and signposting/bullet points are better than long walls of text!
There was a problem hiding this comment.
Rewritten. clean-spec now says: remove unnecessary detail — process artifacts (audit trails, change logs, interview transcripts) are opt-in, never default; prefer signposting and bullet points over walls of text; cut repetition. The five-section template mandate stays. Body is itself bullets now, practicing what it preaches.
| @@ -0,0 +1,20 @@ | |||
| <!-- Verbatim body from ~/vault/specs/2026-08-09-workflow-specs-interview-round1.md §Q5 "Writing spec". Do not edit between the verbatim markers — the body is sha256-guarded in tests/test_spec_loop_prompts.sh. --> | |||
There was a problem hiding this comment.
it's weird for us to sha256 guard these things?? I should be able to manually edit the prompts, or maybe with new coding agents
There was a problem hiding this comment.
Agreed, dropped. The sha256 pinning is gone — all three prompts are now plain editable text headed "Edit freely". What replaced it: tests/test_spec_loop_prompts.sh pins only the structure the skill relies on (five-section template mandate, the six improve-spec dimensions, /grill-me pointers, clean-spec cleaning guidance) — so you or any agent can reword freely, and the test only fails if a load-bearing piece disappears.
| Launch the Workflow tool with the template below, adapted to the spec: fill in the per-phase briefs from the spec's Requirements — each brief MUST name which predecessor artifacts the phase consumes — and pass configuration via `args`, never hardcoded into the script. The harness may deliver `args` to the script as a JSON-encoded string rather than an object (observed live 2026-08-09: `args.reviewer` read as `undefined` and string interpolation silently produced `"Spec: undefined"`), so the template's first line parses defensively into `cfg` — keep that line, and reference `cfg.*`, never `args.*`: | ||
|
|
||
| - `args.specPath` — the spec file. | ||
| - `args.timestamp` — an ISO timestamp from the session (`Date.now()` is unavailable inside Workflow scripts). | ||
| - `args.reviewer` — the reviewer channel as command templates, e.g. `{ "plan": "codex-companion plan-review <planFile> [--resume]", "diff": "codex-companion adversarial-review", "task": "codex-companion task <prompt>" }`. The reviewer is injected config so a future channel cutover (e.g. a model-router-backed reviewer) changes only the args. Reviewer agents MUST start the command via the Monitor tool (the CLI's own contract — never detached, never bare Bash), wait for a terminal status, fetch the result, and report `terminalStatus`, `outputPresent`, and a `resultSummary` truthfully — the script rejects a review whose command did not verifiably succeed with output, so a failed reviewer can never pass as an empty-findings review. |
There was a problem hiding this comment.
is this standard for claude code workflows? if it is, and is structured, good. otherwise seems a bit odd to me cf just writing down what to do
There was a problem hiding this comment.
Yes, this is standard — Workflow is Claude Code's native orchestration tool and these scripts are its documented format (the meta block, agent(), phase(), JSON schemas for structured output). What it buys over "just writing down what to do": deterministic control flow (the loop/retry logic runs as code, not model judgment), parallel fan-out with structured results, and resumability — a killed run resumes with completed phases served from cache. Prose instructions get re-interpreted each session; the script executes the same way every time.
There was a problem hiding this comment.
should this skill be shorter? for memory purposes
There was a problem hiding this comment.
Memory cost is smaller than it looks: only the frontmatter name + description load per session; the body loads on invocation only. So length costs nothing until the skill is actually used. Still trimmed where prose wasn't load-bearing (args paragraph, refinement section), and the embedded template is the irreducible core — it IS the deliverable the skill pastes into Workflow.
There was a problem hiding this comment.
we should have /simplify, prune and refactoring for readability, maintainability, extensibility at the end?
cos there might be repetitive work, extraneous tests (e.g. for the sake of it)
fewer lines of code (but readable/understandable) is good
There was a problem hiding this comment.
also, a few other things:
Legibility over cleverness. When an agent can generate 500 lines in a minute, the scarce resource is your ability to check that those lines do what you think. Boring, conventional, explicit code wins. Flat structure, obvious naming, minimal indirection, no clever abstractions that save keystrokes at the cost of auditability. This was always good advice for research code; agents make it non-negotiable, because you're now reviewing far more code than you write.
Fast, cheap feedback loops. Agents are dramatically better when they can run something and see whether it worked. Small units that execute in seconds, smoke tests on tiny models/datasets, a --debug mode that runs the full pipeline in 30 seconds. If your only feedback signal is "the 6-hour training run finished and the numbers look plausible", both you and the agent are flying blind.
Aggressive defence against silent wrongness. The classic research-code failure mode isn't crashing — it's running fine and producing subtly wrong results: leakage across a train/test split, a shape bug that broadcasting papers over, off-by-one in an index. Agents amplify this because they produce highly plausible code at speed, and plausible-but-wrong is exactly what slips through review. So: assertions on shapes and value ranges everywhere, sanity checks baked into the pipeline (does the random baseline get chance accuracy? does the metric hit 1.0 on a known-perfect input?), and plots of intermediate quantities, not just final numbers.
Protect the trusted core. Split your codebase mentally into two tiers. The load-bearing parts — metric definitions, eval harness, data splits, the statistical analysis — should be small, hand-reviewed line by line, tested, and rarely touched. The experimental scaffolding around it — sweep scripts, plotting, one-off analyses — can be agent-churned freely, because errors there are visible or cheap. Most agent-induced research disasters come from letting the agent casually "refactor" the thing that defines whether your result is real. (For your line of work specifically: never let an agent modify the eval while it's also trying to make the eval pass. That's a conflict of interest you of all people should recognise.)
Provenance and reproducibility, ratcheted up. Agents let you run ten variants where you'd previously run two, so "which code state produced this number" becomes the question you'll ask constantly. Everything in git, small commits, config files rather than edited constants, seeds logged, and every result file stamped with the commit hash and config that produced it. The cost is low and it's exactly the discipline agents are happy to maintain for you if you ask.
There was a problem hiding this comment.
Added a Simplify phase — a /simplify-style pass over everything produced so far (implementation, tests, AND analysis scripts): prune repetition and extraneous tests-for-their-own-sake, fewer lines while staying readable, full suite green afterwards, behavior unchanged. One deliberate deviation from "at the end": it runs between Test and Run, not after Analyze — so the run's numbers come from the final code state (your provenance principle: every result stamped with the commit that produced it). Analysis scripts written during Analyze get the same simplify treatment inside that phase. Flag if you want a second full pass at the very end too.
There was a problem hiding this comment.
All five encoded as a PRINCIPLES constant injected into every doer brief in the template: legibility over cleverness; fast cheap feedback loops (smoke tests on tiny models, --debug mode); defence against silent wrongness (assert shapes/ranges, random-baseline-hits-chance and metric-hits-1.0-on-perfect-input sanity checks, plot intermediates); protect the trusted core (metric definitions, eval harness, splits, analysis stay small and hand-reviewed — NEVER modify the eval while also trying to make it pass); provenance (config files over edited constants, seeds logged, results stamped with commit + config). T9 in tests/test_spec_loop_template.mjs pins that all six doer briefs carry them.
- Add Simplify phase between Test and Run (before Run so the run's numbers come from the final code state); it prunes repetition, extraneous tests, and analysis scripts alike - Inject five working principles into every doer brief: legibility over cleverness, fast feedback loops, defence against silent wrongness, protect the trusted core, provenance - Drop sha256 pinning of refinement prompts; prompts are now plain editable text with a structure-only test guard (tests/test_spec_loop_prompts.sh) - clean-spec rewritten: process artifacts (audit trails etc.) are opt-in, signposting/bullets over walls of text - Merge interview-conventions.md into spec-conventions.md (single standard: batched AskUserQuestion up to 4, successive batches or answer file beyond) - Update template test for six phases + T9 principles-injection check Claude-Session: https://claude.ai/code/session_01Mm1WU9eHyEYQWVUPtq46Um
|
|
||
| How spec interviews (`/spec-interview`, `/spec-interview-research`, `/grill-me`, and the spec-loop plan phase) collect decisions from Yulong. | ||
|
|
||
| **Channel by question count.** Four questions or fewer → one batched `AskUserQuestion` call (the tool caps a call at four questions). More → either a run of successive batched `AskUserQuestion` calls — 10-20 questions delivered that way is fine — or a single markdown answer file via `SendUserFile`; never a drip of one-question prompts. Prefer the answer file when questions need long what-I-found preambles or asynchronous answering. `/grilling` is the deliberate exception: one question per call, walking decision dependencies one at a time. |
There was a problem hiding this comment.
Even for grilling, we shouldn't have only one qn per call. That's annoying. Just think for longer to come up with a good list of questions!
There was a problem hiding this comment.
Done in e5e10c2 — the exception is gone at both ends: /grilling's own skill now says think longer upfront, map the decision tree, assemble a good question list, and deliver it in batched AskUserQuestion calls (four per call, the tool's cap); a question is held back only when it genuinely depends on an earlier answer. spec-conventions.md now reads "never a drip of one-question prompts, /grilling included."
|
|
||
| **Channel by question count.** Four questions or fewer → one batched `AskUserQuestion` call (the tool caps a call at four questions). More → either a run of successive batched `AskUserQuestion` calls — 10-20 questions delivered that way is fine — or a single markdown answer file via `SendUserFile`; never a drip of one-question prompts. Prefer the answer file when questions need long what-I-found preambles or asynchronous answering. `/grilling` is the deliberate exception: one question per call, walking decision dependencies one at a time. | ||
|
|
||
| **Answer-file format.** Each question carries a short what-I-found preamble, checkbox options with the recommended default listed FIRST and marked "(recommended)", and a `Comments:` line. A question left blank means the recommended default is accepted. (Checkboxes are permitted here as an exception to `markdown-style.md` — an answer file is a working form, not a doc.) |
There was a problem hiding this comment.
Not necessarily what you found, but just an explanation of what's happening, rather than jumping in without context
There was a problem hiding this comment.
Reframed in e5e10c2: the preamble is now "an explanation of what's happening and why the question arises, so it never lands cold" — findings go in when relevant, but context is the point. (Was "what-I-found preamble", which over-indexed on findings.)
Two review comments on PR #66: - /grilling loses its one-question-per-call carve-out. The skill now says: think longer upfront, map the decision tree, assemble a good question list, and deliver it in batched AskUserQuestion calls — holding a question back only when it genuinely depends on an earlier answer. spec-conventions.md drops the exception accordingly. - Answer-file preambles reframed: a short explanation of what's happening and why the question arises, so questions never land cold — findings included when relevant, but context is the point (previously "what-I-found preamble"). Tests: test_spec_loop_prompts.sh 24/24, test_spec_loop_template.mjs 55/55. Claude-Session: https://claude.ai/code/session_01Mm1WU9eHyEYQWVUPtq46Um
SPEC-A "Spec-Driven Agent Workflow" deliverables, built and reviewed via the five-phase loop the spec itself describes (doer per phase, codex-companion adversarial review after each phase, findings injected forward).
What's in here (two commits, ordering is deliberate)
/spec-loopskill (claude/skills/spec-loop/SKILL.md, a Workflow template driving plan → implement → test → run → analyze with cross-model review), three spec-refinement prompts carrying the five-section template, the detect-onlywarn_spec_outside_vault.shhook + settings wiring,spec-conventions.mdupdated to the five-section template,interview-conventions.md, and three test suites./spec-looprow alone. Lands second because the row must never exist without the skill (amendment A2 from the e2e run); verifiedgit cat-file -e HEAD:claude/skills/spec-loop/SKILL.mdbefore committing.Merge note: use a merge commit (not squash) to preserve the skill-before-row commit ordering on main.
Verification
tests/test_spec_loop_template.mjstests/test_spec_loop_prompts.shtests/test_spec_outside_vault_hook.shThe template was validated by a real end-to-end run (
wf_d66350d0-07d, 13 agents, status ok, kill+resume exercised twice) which caught two template defects live — Workflowargsarriving as a JSON-encoded string, and codex-companion's terminal status being"completed"not"success"— both fixed and pinned by tests T8/T4.Full run report:
~/vault/tooling/dotfiles/docs/2026-08-09-spec-loop-spec-a-report.md(vault; not on this public branch).https://claude.ai/code/session_01Mm1WU9eHyEYQWVUPtq46Um