From 6ce4ad2d6a7d1880670d359af03eba17374aa35a Mon Sep 17 00:00:00 2001 From: Maslenok Date: Thu, 23 Jul 2026 14:05:57 +0200 Subject: [PATCH 1/8] Worktree init resolves a default in-skill instead of blocking --- .claude/skills/speccy/DECISION_LOG.md | 8 ++++++++ .claude/skills/speccy/SKILL.md | 15 +++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.claude/skills/speccy/DECISION_LOG.md b/.claude/skills/speccy/DECISION_LOG.md index 67b7bf2..5bbab04 100644 --- a/.claude/skills/speccy/DECISION_LOG.md +++ b/.claude/skills/speccy/DECISION_LOG.md @@ -156,6 +156,14 @@ Scope makes this the right line. Speccy targets scoped changes on live repos, wh This extends the philosophy that already puts the human at the spec and plan-review gates: review accountability sits with the initiating human, and Speccy's job is to make that review time well spent. +### Worktree init resolves a default in-skill instead of blocking (2026-07-22) + +The Worktree-init precondition previously did one of: use the CLAUDE.md `## Worktree init` section if present, else "note the gap, offer to draft it, have the user review and commit before proceeding." On a real run the project had neither `worktree.baseRef` nor the section, the user was away, and the only non-blocking option was to force the whole run sequential — losing all parallelism for a purely mechanical reason. + +Fix: the precondition now **resolves a sensible default in-skill and carries on** rather than prompting or silently serialising. `worktree.baseRef` missing → ensure `head`. `## Worktree init` missing → synthesise a minimal `worktreeInit` from `.gitignore` + the verify commands (idempotently symlink the gitignored dependency/config dirs — `node_modules`, `.venv`, `vendor`, `target`, generated config — from the main checkout via `ln -snf`, resolving the checkout with `git rev-parse --show-toplevel`) and pass it to plan-execution. Sequential-only fallback survives, but only for the genuinely-undeterminable case (no recognisable lockfile/manifest). Drafting the section into CLAUDE.md becomes an after-the-fact convenience the user may accept, never a gate. + +Rationale: almost every worktree just needs its ignored dependency dir linked in; that default is safe and derivable, so a missing section shouldn't cost parallelism or an interactive prompt. Keeps an unattended fan-out run moving. + A corollary follows. Since the verdict is the human's, a completed run is a handoff — the wrap-up reports what was built and self-reviewed, then leaves the call to the user. Announcing "done" would invite a rubber stamp and undermine that. The Wrap-up section of SKILL.md is worded accordingly. ### Gate reports are re-verified, not trusted; hard gates beat soft style preferences (2026-06-23) diff --git a/.claude/skills/speccy/SKILL.md b/.claude/skills/speccy/SKILL.md index bb32d04..ba36726 100644 --- a/.claude/skills/speccy/SKILL.md +++ b/.claude/skills/speccy/SKILL.md @@ -91,14 +91,17 @@ Documented is not the same as working. **Smoke-test the tooling now, on the clea ### Worktree init -Worktrees come into play only for **parallel** tasks. Plan-execution runs sequential tasks directly on the main checkout; only parallel tasks get git worktrees, which lack gitignored state. You won't know whether the plan produces parallel tasks until breakdown, so treat this as preparation that may not be exercised this run. Check whether CLAUDE.md has a `## Worktree init` section with gather/apply blocks. If it does, nothing to do — plan-execution will use it if parallel tasks arise. If it's missing: +Worktrees come into play only for **parallel** tasks. Plan-execution runs sequential tasks directly on the main checkout; only parallel tasks get git worktrees, which lack gitignored state. You won't know whether the plan produces parallel tasks until breakdown, so treat this as preparation that may not be exercised this run. Check whether CLAUDE.md has a `## Worktree init` section with gather/apply blocks. If it does, nothing to do — plan-execution will use it if parallel tasks arise. -1. Note that worktree agents (parallel tasks only) will lack gitignored files (node_modules, tool configs, generated artifacts). -2. Offer to help draft the section — look at `.gitignore` and the verification commands for clues about what needs recreating. -3. The format is gather (commands run in the main checkout, capturing stdout as named variables) and apply (commands run in the worktree, substituting gathered values). See existing CLAUDE.md examples. -4. Have the user review and commit the section before proceeding. +**If either the `worktree.baseRef` setting or the `## Worktree init` section is missing, do NOT stop, prompt for a hand-authored section, or silently force the whole run sequential — resolve a sensible default in-skill and carry on:** -A purely sequential plan never touches worktrees, so a project that only runs sequential work can skip this — but it's cheap insurance for any run that fans out. +- **`worktree.baseRef` missing** → ensure it is `head` (write it to `.claude/settings.json` via Bash/python; direct Edit is blocked). The default `fresh` branches from `origin/` and misses feature-branch commits. (Plan-execution also self-heals this, so it's belt-and-suspenders.) +- **`## Worktree init` section missing** → synthesize a minimal default from `.gitignore` + the verification commands rather than punting. Almost every project's worktree just needs its gitignored dependency/config artifacts linked in from the main checkout. Build a `worktreeInit` array that idempotently symlinks those (`ln -snf / `), covering at minimum the package-manager install dir the verify commands need (`node_modules`, `.venv`, `vendor`, `target`, …) plus any generated config the verify step reads. Pass that array straight to plan-execution as `worktreeInit`. Resolve `` with `git rev-parse --show-toplevel` at gather time. +- **Only if you genuinely cannot determine the dependency dirs** (no recognizable lockfile/manifest, opaque build) → fall back to instructing breakdown to stay sequential-only, and say so. + +In every case, after resolving the default, offer the user the drafted `## Worktree init` block to commit into CLAUDE.md so next time it's explicit — but this is an after-the-fact convenience, never a blocker. + +A purely sequential plan never touches worktrees, so a project that only runs sequential work exercises none of this — but the default above means a fan-out run is never blocked on a missing section. ### Git state From 826d43aedde63768ffcc891f11c289966a9a8545 Mon Sep 17 00:00:00 2001 From: Maslenok Date: Thu, 23 Jul 2026 14:06:32 +0200 Subject: [PATCH 2/8] Ship a one-page human-reading digest alongside the full spec --- .claude/skills/speccy/DECISION_LOG.md | 8 ++++++++ .claude/skills/speccy/SKILL.md | 2 ++ 2 files changed, 10 insertions(+) diff --git a/.claude/skills/speccy/DECISION_LOG.md b/.claude/skills/speccy/DECISION_LOG.md index 5bbab04..f097de6 100644 --- a/.claude/skills/speccy/DECISION_LOG.md +++ b/.claude/skills/speccy/DECISION_LOG.md @@ -358,3 +358,11 @@ A new cross-cutting section (beside "trust files, not returns") makes the orches The multi-lens panel (2026-07-13) runs speccy's generic lenses plus the built-in `code-review` skill, but is blind to a repo that carries its *own* review gate — a `/review`-style skill, project-defined reviewer agents, or a `.claude/review.config.json`. Such a gate encodes the house security bar, thresholds, and invariants a generic reviewer structurally can't replicate, so where it exists it is the highest-signal reviewer available — and leaving it out means the panel re-derives, worse, what the repo already maintains. So it becomes an extra lens, in the same category as `code-review` rather than a bespoke prompt: run it the way the repo documents (its own agents, models, thresholds — not overridden), invoke it **directly in the main conversation** because a project gate is usually itself multi-agent (same reasoning as running `code-review` inline, 2026-07-14), normalise its findings into the shared shape, and merge with the triage step deduping its overlap with `code-review`, codebase fit, and local-doc adherence. It is **spec-blind**, so it complements the spec-fidelity lens rather than replacing it. Absent in a repo → the lens is skipped cleanly. The accepted cost is coupling to the repo gate's output shape, the same trade already accepted for `code-review`. + +### The full spec ships with a one-page human-reading digest (2026-07-22) + +The hardened full spec is dense by design — the critique loop grows it into an implementation reference, not something a human reads to grasp the work at the review gate. Pointing the user at the full spec makes them re-derive the shape of the change from prose meant for the build. + +Fix: Phase 1c now also writes `specs/-digest.md`, a colocated one-page entry point — the goal in a few lines, the load-bearing decisions each with a one-line *why*, the build order, and the open spikes/risks, with every item pointing back into the full spec by section so it stays the derived view rather than a second source of truth. Regenerate it whenever the spec materially changes, at minimum once the critique loop converges. The user-review gate now leads with the digest and keeps the full spec for depth. + +The bilingual rule is inlined at the point of use rather than cross-referenced: the digest, like every doc, is English and git-tracked; a translated copy for the user's own reading is written only under a gitignored `.users-files/` zone and never becomes the canonical copy — on conflict the tracked English digest wins. diff --git a/.claude/skills/speccy/SKILL.md b/.claude/skills/speccy/SKILL.md index ba36726..be37ed9 100644 --- a/.claude/skills/speccy/SKILL.md +++ b/.claude/skills/speccy/SKILL.md @@ -189,6 +189,8 @@ Create a feature branch before committing anything. Pick a short, descriptive na Save to `specs/.md`. Commit the spec. +**Always ship a short human-reading digest alongside the full spec.** The full spec is the implementation reference and it hardens (and grows dense) through the critique rounds — it is NOT what a busy human reads to understand the work. So maintain a **one-page digest** next to it (`specs/-digest.md`): the goal in 2–3 lines, the load-bearing decisions as a scannable list (each with a one-line *why*), what gets built and in what order, and the open spikes/risks. Every item **references the full spec's section** (e.g. "(§ Auth)") so the reader drills in only where needed — the full spec stays canonical, the digest never restates it in full or diverges. Regenerate the digest whenever the spec materially changes (after the critique loop converges, at minimum). At the user-review gate, point the user at the **digest first**, the full spec for depth. (Bilingual note — the rule, inline: the canonical digest, like every doc, is **English and git-tracked** in the repo's normal docs location — never a non-English copy in a tracked path. If the user reads or edits in their own language, ALSO write a translated copy, kept ONLY in a **gitignored `.users-files/`** zone; never put a translation in a tracked path, and never put the canonical doc inside `.users-files/`. Keep the two in sync — **on conflict the English git-tracked copy wins** — and leave the section references in the canonical English so they don't drift.) + Generate a `runId`: lowercase kebab from the slug plus a `YYYYMMDD-HHmm` timestamp (e.g. `auth-refactor-20260609-1430`). Create `.speccy//` and ensure `.speccy/` is in `.gitignore`. Write the initial `state.json` (phase: `spec-critique`, with runId, slug, baseBranch, adversaryModel, builderModel, engagementChecks, specPath). Also write the runId to `.speccy/.current-runid` (plain text, no newline needed) so a later session can find this run without globbing. Tell the user about the directory — critique rounds, the plan, review notes, and run state will be saved there so they can open them in their editor rather than scrolling terminal output. Mention the path once here; don't repeat it at every save. From 3214f32d0ea898703fb428dadf279c3bce5afcd9 Mon Sep 17 00:00:00 2001 From: Maslenok Date: Thu, 23 Jul 2026 14:07:24 +0200 Subject: [PATCH 3/8] Make the cold-start flow trace a mandatory pass in critique + a spec-critique exit gate --- .claude/skills/speccy/DECISION_LOG.md | 8 ++++++++ .claude/skills/speccy/SKILL.md | 2 ++ .claude/skills/speccy/prompts/plan-critique.md | 2 ++ .claude/skills/speccy/prompts/spec-critique.md | 2 ++ 4 files changed, 14 insertions(+) diff --git a/.claude/skills/speccy/DECISION_LOG.md b/.claude/skills/speccy/DECISION_LOG.md index f097de6..160c321 100644 --- a/.claude/skills/speccy/DECISION_LOG.md +++ b/.claude/skills/speccy/DECISION_LOG.md @@ -366,3 +366,11 @@ The hardened full spec is dense by design — the critique loop grows it into an Fix: Phase 1c now also writes `specs/-digest.md`, a colocated one-page entry point — the goal in a few lines, the load-bearing decisions each with a one-line *why*, the build order, and the open spikes/risks, with every item pointing back into the full spec by section so it stays the derived view rather than a second source of truth. Regenerate it whenever the spec materially changes, at minimum once the critique loop converges. The user-review gate now leads with the digest and keeps the full spec for depth. The bilingual rule is inlined at the point of use rather than cross-referenced: the digest, like every doc, is English and git-tracked; a translated copy for the user's own reading is written only under a gitignored `.users-files/` zone and never becomes the canonical copy — on conflict the tracked English digest wins. + +### A cold-start flow trace is a mandatory critique pass (2026-07-22) + +Both critique prompts already check decisions and consistency section by section, but that misses *temporal* contradictions: a step that consumes a resource, credential, or piece of state only produced by a later step (or by the very step being configured), or two individually-sound choices that turn out mutually exclusive once the flow actually runs in order. No single section is wrong in either case, so section-by-section review — however thorough — never surfaces them. + +Fix: `spec-critique.md` and `plan-critique.md` each gain a mandatory pass that walks every primary flow step by step from an empty/first-run state and asks, at each step, whether its prerequisites already exist at that point. `spec-critique.md`'s exit gate in SKILL.md now hard-requires at least one round to have done this trace before the spec-critique phase can close, and the same trace repeats at the Phase 2b plan review, since planning can reintroduce an ordering dependency the spec didn't have. + +The 3-round general critique cap already tolerates a round finding nothing; the exit gate makes this specific pass non-skippable regardless, because bootstrap contradictions are exactly the kind that survive every other round and still ship. diff --git a/.claude/skills/speccy/SKILL.md b/.claude/skills/speccy/SKILL.md index be37ed9..13c6026 100644 --- a/.claude/skills/speccy/SKILL.md +++ b/.claude/skills/speccy/SKILL.md @@ -209,6 +209,8 @@ For each round (up to 3): After 3 rounds, proceed regardless, noting any unaddressed feedback. Update state.json after each round (`specCritiqueRounds`). When the critique loop exits, set `phase: "planning"`. +**Mandatory exit gate — the cold-start flow trace.** Do NOT leave the spec-critique phase until at least one critique round has explicitly done the **end-to-end / first-run dependency trace** described in `prompts/spec-critique.md` — walking each primary flow step by step from an empty/first-run state and confirming every step's prerequisites already exist at that point — and any bootstrap / ordering / mutually-exclusive-mechanism contradiction it surfaced has been resolved. This is separate from section-by-section consistency: a spec can pass every consistency pass and still hide a step that depends on something only produced later (a circular/bootstrap dependency) or two individually-sound choices that collide once the flow runs in order. Section-consistency critique does not catch these; only tracing the actual flow does. If the layered fold-ins across rounds could have introduced such a contradiction (they easily can), run one more round whose sole job is this trace before declaring the spec ready. The same trace is required at the Phase 2b plan review — walk the built flow cold once more, since planning can reintroduce an ordering dependency the spec didn't have. + Only once the loop has fully exited, reach the primary context-clearing point. The spec interview and critique are the heaviest interactive context in the run, and the approved spec now captures every decision in a committed file — so the window can reset before planning, which is largely subagent-driven. Verify all run state is in files (state.json current, spec committed, external references recorded in the spec — not left only in conversation), then suggest the user `/clear` and re-invoke to resume at planning. If they'd rather continue, proceed to Phase 2. ## Phase 2 — Planning diff --git a/.claude/skills/speccy/prompts/plan-critique.md b/.claude/skills/speccy/prompts/plan-critique.md index 2f921f8..fa8fba0 100644 --- a/.claude/skills/speccy/prompts/plan-critique.md +++ b/.claude/skills/speccy/prompts/plan-critique.md @@ -8,6 +8,8 @@ Check the plan's named design decisions against the project's static-analysis co Check that any load-bearing mechanism the plan depends on has been **proven feasible, not merely asserted**. If the plan relies on specific platform/runtime behaviour, timing, ordering, or an API capability (e.g. a synchronous same-transaction update, a hook firing at a particular point, a write being permitted from a given execution context, an API returning a given result), confirm the plan's evidence actually exercised that risky action against the real environment — not adjacent facts that surround it. A probe that verifies a precondition ("the data is present") does not prove the action ("the write from that context succeeds"). Treat an unproven load-bearing mechanism as a high-severity risk: it is exactly the kind of assumption that survives review and then collapses at build time. If feasibility cannot be confirmed from the plan, the finding is that this mechanism needs a feasibility spike before the plan can be trusted; flag it and the orchestrator will run one (see `plan-spike.md`). Your job is to judge the plan's evidence, not to run the spike yourself. +**Trace the end-to-end flow from a cold start — mandatory.** Beyond judging decisions in isolation, walk each primary flow the plan builds **step by step from an empty/first-run state** and check that every step's prerequisites already exist at that point in time. Flag any *temporal / bootstrap* dependency — a step that consumes a resource, credential, component, token, or state only produced by a later step or by the very step being set up — and any two individually-sound choices that become mutually exclusive once the flow runs in order (e.g. a transport whose prerequisite another decision rejected). These ordering/dependency contradictions survive decision-by-decision review because no single choice is wrong. Name the exact step and the prerequisite missing at that moment. + Also flag content that restates `CLAUDE.md` (root or nested) or the docs it links. Read those first so you can recognise the duplication. Every piece of feedback must identify a specific problem and explain why it matters. If you cannot find legitimate flaws, say so. diff --git a/.claude/skills/speccy/prompts/spec-critique.md b/.claude/skills/speccy/prompts/spec-critique.md index 5e569b2..5480a8a 100644 --- a/.claude/skills/speccy/prompts/spec-critique.md +++ b/.claude/skills/speccy/prompts/spec-critique.md @@ -4,6 +4,8 @@ Find: missing deliverables, ambiguous scope, unstated constraints, contradiction Scrutinise the **Decisions & rationale** section, and hunt for decisions that should be there but aren't. Every load-bearing choice the spec makes — a scope call, an approach, a contract or deliverable shape — must state *why this and not the alternative*. Flag any decision that (a) is recorded without a reason, (b) names no viable alternative when one plainly exists, (c) gives a rationale that doesn't actually defeat the rejected alternative, or (d) is presented as inevitable when it was really a choice. A choice whose reasoning is missing or weak is where a spec silently commits to the wrong path, so challenge the reasoning, not just the presence of the entry. +**Trace the end-to-end flow, not just the sections — this is mandatory, not optional.** Section-by-section consistency checks miss *temporal / bootstrap* contradictions: where one part of the spec depends on something another part only produces later, or that the very step being set up is what produces. Walk each primary flow the spec describes **step by step from a cold start** — nothing provisioned yet, first run, empty state, brand-new tenant/user/install — and at every step ask: *does everything this step needs already exist at this exact point in time?* Flag any step that consumes a resource, credential, component, token, record, or piece of state that is only created by a later step (or by the same step being configured) — a circular or bootstrap dependency. Also flag two mechanisms that are each internally fine but mutually exclusive when the flow runs (e.g. "transport X" chosen in one section while a prerequisite of X was explicitly rejected in another). These are exactly the contradictions that survive every consistency pass, because no single section is wrong — only the ordering / dependency is. Name the exact broken step and the prerequisite that isn't there yet. Do this trace even when the spec looks internally tidy. + Also flag content that restates `CLAUDE.md` (root or nested) or the docs it links. Read those first so you can recognise the duplication. Pay particular attention to the Assumptions section. These are the spec author's best guesses where the feature description was ambiguous. Challenge any assumption that seems wrong, risky, or worth validating before building. From cbbdabbdfcd64cf09557a8c780462f6a1791cfc9 Mon Sep 17 00:00:00 2001 From: Maslenok Date: Thu, 23 Jul 2026 14:07:59 +0200 Subject: [PATCH 4/8] Harden the Phase 3 build guidance: parallelism, gate-trust with the documented harness, round-trip economy, test-rerun scope --- .claude/skills/speccy/DECISION_LOG.md | 8 ++++++++ .claude/skills/speccy/SKILL.md | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.claude/skills/speccy/DECISION_LOG.md b/.claude/skills/speccy/DECISION_LOG.md index 160c321..5ad9778 100644 --- a/.claude/skills/speccy/DECISION_LOG.md +++ b/.claude/skills/speccy/DECISION_LOG.md @@ -374,3 +374,11 @@ Both critique prompts already check decisions and consistency section by section Fix: `spec-critique.md` and `plan-critique.md` each gain a mandatory pass that walks every primary flow step by step from an empty/first-run state and asks, at each step, whether its prerequisites already exist at that point. `spec-critique.md`'s exit gate in SKILL.md now hard-requires at least one round to have done this trace before the spec-critique phase can close, and the same trace repeats at the Phase 2b plan review, since planning can reintroduce an ordering dependency the spec didn't have. The 3-round general critique cap already tolerates a round finding nothing; the exit gate makes this specific pass non-skippable regardless, because bootstrap contradictions are exactly the kind that survive every other round and still ship. + +### Phase 3 build guidance: parallelism, verified gates via the documented harness, and test-rerun scope (2026-07-22) + +Phase 3 as written left three costs on the table. Plan-execution's breakdown defaults to sequential steps even when tasks touch disjoint files with no data dependency, so a run pays full serial wall-clock for authoring that could overlap. The gate-trust rule said "re-run the project's load-bearing gates yourself" without saying *how* — on a project that names a specific MCP tool for deploy/test in CLAUDE.md, that gap invites a raw-CLI shortcut instead of the harness the project actually documents. And nothing bounded how often a fix loop re-runs the test suite, so a one-line fix in one test could trigger a full remote re-run every round. + +Fix, three parts: the Phase 3 instruction to plan-execution now asks breakdown to parallelize genuinely independent authoring, with the caveat stated up front — a single shared verify environment (one scratch org, one CI runner) still serialises the deploy/test step, so parallelism buys authoring time, not the shared-resource round-trip. The trust rule now says to use the project's documented harness the way CLAUDE.md specifies it (an MCP tool named there beats a raw-CLI wrapper, which is a fallback only). And a hard test-rerun-scope rule caps the fix loop: only the touched/failing test(s) re-run while fixing, and the full suite runs exactly once, at the very end, as the completeness gate — never per-fix. + +Together these keep Phase 3's round-trip cost proportional to what actually changed, instead of paying full serial and full-suite cost by default. diff --git a/.claude/skills/speccy/SKILL.md b/.claude/skills/speccy/SKILL.md index 13c6026..0f03fba 100644 --- a/.claude/skills/speccy/SKILL.md +++ b/.claude/skills/speccy/SKILL.md @@ -259,7 +259,17 @@ Invoke the `plan-execution` skill directly via the Skill tool from the main conv Do _not_ wrap this in an Agent subagent — Agent subagents lack `Workflow`, so the call breaks. Plan-execution already backgrounds its own work (breakdown, execute, integrate, verify); only the final result returns. -When the workflow reports complete, do not advance on its "gates pass" / "0 violations" summary — a build agent can satisfy a gate by fabricating or inverting a rule and still report green. Re-run the project's load-bearing gates yourself (the build, lint / static-analysis, and test commands from CLAUDE.md) and confirm the actual tool output. If a gate fails, the run isn't done: carry the real tool output into a fix round (the Phase 4 implementation-fix agent handles exactly this), re-run the gates after it, and repeat until you have seen them pass. Only then set `phase: "review"` in state.json and continue. +**Push for parallelism where the plan allows.** Plan-execution's breakdown defaults to sequential steps; a purely serial run is the single biggest wall-clock cost. When invoking plan-execution, augment the breakdown instruction to **parallelize genuinely independent work** — group tasks that touch disjoint files with no data dependency into parallel steps (each maps to a spec/plan acceptance criterion). Authoring independent units concurrently (e.g. a test class per production class, or separate feature files) is the clearest win. **Caveat, state it to the breakdown:** if the project verifies against a single shared environment (one scratch org, one database), the *deploy/test* step of parallel tasks contends on that resource and effectively serialises — so parallelism cuts authoring time, not the shared-environment round-trip. Only parallelise the authoring, and let integration/verification funnel through the shared resource. + +When the workflow reports complete, do not advance on its "gates pass" / "0 violations" summary — a build agent can satisfy a gate by fabricating or inverting a rule and still report green. Re-run the project's load-bearing gates yourself (the build, lint / static-analysis, and test commands from CLAUDE.md) and confirm the actual tool output. **Use the project's documented harness the way CLAUDE.md specifies it** — if CLAUDE.md names an MCP tool for a gate (e.g. a deploy/test MCP), invoke that MCP tool rather than shelling out to the raw CLI; a raw-CLI wrapper is a fallback, not the default. If a gate fails, the run isn't done: carry the real tool output into a fix round (the Phase 4 implementation-fix agent handles exactly this), re-run the gates after it, and repeat until you have seen them pass. Only then set `phase: "review"` in state.json and continue. + +**Economise the round-trips** (the dominant wall-clock cost when the gate hits a remote environment — a scratch org, a CI runner, a container). The trust rule (see it pass yourself) is non-negotiable; what's negotiable is not paying for the full remote round-trip on every intermediate step. + +**Test re-run scope — the hard rule (do not violate):** +- While fixing, re-run **only the specific test(s) you just touched or that were failing** — never the whole suite. Re-running every test to confirm a one-line fix in one test is waste; it does not happen. +- Run the **full suite of ALL tests exactly once, at the very end**, after every fix is in — that single final run is the completeness gate. Not per-fix, not per-round. +- Concretely: fix test/class X → run X (and its production class's targeted tests) → green → move on. Only when the whole fix list is exhausted do you run the entire suite once to confirm nothing regressed. +- For *intermediate* checks inside a fix loop prefer the cheapest signal that still proves the fix — compile / type-check / `--dry-run` / the single changed test. Batch several fix findings into one fix agent and re-check once, rather than re-gating after each small edit. If the implementation workflow exits incomplete, stop the pipeline. Report what's done and what remains — the user has a branch with partial progress. State.json remains at `phase: "implementation"` so the run can be resumed later. From 3d46aa87f14c38c856f81d3f09bea589e084ba28 Mon Sep 17 00:00:00 2001 From: Maslenok Date: Tue, 4 Aug 2026 18:05:03 +0200 Subject: [PATCH 5/8] Lead with the project's own capabilities at every phase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discover a project's skills, research/hunter subagents, governing docs, and any routing hints once, as a precondition; persist the manifest to .speccy//capabilities.md at run creation; inject a phase-scoped "prefer these over generic approaches" block at every spawn site. All signals optional — absence degrades cleanly to the generic pipeline; routing needs no map because skills self-describe their triggers. --- .claude/skills/speccy/DECISION_LOG.md | 8 ++++ .claude/skills/speccy/SKILL.md | 39 ++++++++++++++++++- .../speccy/prompts/project-capabilities.md | 30 ++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 .claude/skills/speccy/prompts/project-capabilities.md diff --git a/.claude/skills/speccy/DECISION_LOG.md b/.claude/skills/speccy/DECISION_LOG.md index ea276f1..476d560 100644 --- a/.claude/skills/speccy/DECISION_LOG.md +++ b/.claude/skills/speccy/DECISION_LOG.md @@ -447,3 +447,11 @@ The deeper issue the run exposed: the three pre-questions and the three "what co What survived was only the *word* — the `adversaryModel` default token `"ladder"` and a SKILL.md line calling the defaults a "ladder scheme" — now naming a flat, per-phase policy that doesn't ladder. A misnomer that outlives its mechanism is exactly the scar tissue a future reader decodes wrongly, so the name goes. Fix: state records the concrete model each phase runs, not a token. `adversaryModel` defaults to `"opus"` (the tier for critique and the panel's judgment lenses) and `builderModel` to `"sonnet"` — no sentinel to decode, and SKILL.md states each phase's model plainly. The one phase with no single model is implementation review, a panel spanning tiers (judgment on opus, suppressions and comments on sonnet); its per-lens mix stays a documented design detail rather than something a state field encodes, so `adversaryModel` names the adversary *tier* and the cheaper lenses sit a rung below it. The two overrides that were doing real work stay: a pinned `adversaryModel` for critique and review lenses, and `builderModel` (commonly raised to opus). Per-phase *override* knobs were considered and declined — everything high-leverage already sits at opus, so there is nothing left to raise, and the log's own arc records cheaper tiers costing more than they saved. This is a rename, not a capability change. + +### The pipeline leads with the project's own capabilities (2026-08-04) + +Speccy used a project's own machinery only reactively. The review panel would catch a house-convention violation after the build — a whole fix-round late — while the research and build agents re-derived, generically and worse, what the repo already maintains: skills carrying house conventions, read-only research/"hunter" subagents that answer where-does-this-live / does-this-already-exist, governing docs, sometimes a review gate. Nothing told a subagent these existed. + +The fix is discover-once-then-inject. A new precondition probes what the project exposes — skills, `.claude/agents/*.md` subagents tagged research/reviewer/other, governing docs, and any explicit skill→area map — into a manifest persisted at `.speccy//capabilities.md` (Phase 1c), so every phase and a resumed context read one inventory instead of re-probing. Each spawn site then prepends a phase-scoped "prefer these over generic approaches" block (`prompts/project-capabilities.md`): spec/plan research delegates discovery to project hunters before any generic sweep; breakdown attaches trigger-matched skills to each task and bakes in hunter-resolved placement answers (a build agent inside the workflow can invoke a Skill but cannot dispatch an Agent, so placement/existence questions are resolved up front); the local-doc lens judges against the house skill set. + +Two boundaries were chosen deliberately. Nothing is required: every signal is optional and its absence degrades cleanly to the generic pipeline — there is no mandatory config artifact, because projects differ in what they ship. And the base router needs no map: skills self-describe their triggers ("use when …"), so matching a task to a skill is judgment over trigger text; an explicit skill→area map, where one exists, only accelerates. Capabilities are treated as project truth — the same standing the project review gate already has — not claims to adversarially re-verify. diff --git a/.claude/skills/speccy/SKILL.md b/.claude/skills/speccy/SKILL.md index caf96fb..29b64fc 100644 --- a/.claude/skills/speccy/SKILL.md +++ b/.claude/skills/speccy/SKILL.md @@ -92,6 +92,10 @@ Check that CLAUDE.md documents the project's verification tools (build, lint, st Documented is not the same as working. **Smoke-test the tooling now, on the clean tree, before investing in spec and plan** — a broken or pathological verification setup discovered at implementation has already cost a spec, several critique rounds, and a plan. Run each documented command once and confirm it completes, passes (or note its baseline failures), and returns in a reasonable time. Surface anything that hangs, errors, or floods output before proceeding. +### Project capabilities + +Discover the project's own capabilities now and hold the manifest — skills, specialized subagents, governing docs, and any explicit routing hints (see **Lead with the project's own capabilities** for what to probe and how each phase uses it). This is discovery only: it never blocks, and a project that exposes none of it just runs the generic pipeline. Doing it here, before the spec, means every downstream phase reads one manifest instead of re-probing. The run directory doesn't exist yet, so keep the manifest in context now; you persist it to `.speccy//capabilities.md` when the run is created in Phase 1c. + ### Worktree init Worktrees come into play only for **parallel** tasks. Plan-execution runs sequential tasks directly on the main checkout; only parallel tasks get git worktrees, which lack gitignored state. You won't know whether the plan produces parallel tasks until breakdown, so treat this as preparation that may not be exercised this run. Check whether CLAUDE.md has a `## Worktree init` section with gather/apply blocks. If it does, nothing to do — plan-execution will use it if parallel tasks arise. @@ -132,6 +136,31 @@ The main session may be governed by a behavioural or output style a fresh agent So **before spawning any subagent, restate the active style concisely at the top of its prompt** — enough that both its reasoning and its written output match the session's voice. Two things are out of reach and don't need carrying: conventions already in `CLAUDE.md` (subagents read it anyway), and the built-in `code-review` skill run inline (it manages its own prompt — the orchestrator just applies the session's voice when it normalises those findings into the lens file). This rule applies to every spawn site in the phases below; it is stated once here rather than repeated at each. Speccy's own narration back to the user follows the same style as a matter of course. +## Lead with the project's own capabilities + +A project often ships capabilities that beat speccy's generic defaults for *this* codebase: **skills** (house conventions, domain rules, verification harnesses), **specialized subagents** (read-only research / "hunter" agents that answer where-does-this-live / how-does-X-work / does-Y-already-exist, plus the project's own review agents), **governing docs** (CLAUDE.md and what it points to), and sometimes an explicit **review gate**. A generic pipeline that ignores these re-derives — worse — what the repo already maintains, and only catches the divergence at review, a whole fix-round late. So **discover them once, up front, and prefer them at every phase.** + +Nothing here is required. Each signal is optional and its absence degrades cleanly to the generic path — a project that exposes none of this just runs the pipeline as written. Do not depend on any one artifact existing (there is no mandatory config file); probe whatever the project actually exposes. + +**Discover once (a precondition).** Probe, in layers, only what the project has: + +- **Skills** — the skills available in this session. Each self-describes its trigger in its own description ("use when …"). +- **Specialized subagents** — read `.claude/agents/*.md` and any subagent types this session offers. From each one's description and tools, tag it *research* (read-only — answers where / how / exists), *reviewer* (a project review agent), or *other*, and note read-only vs mutating. +- **Governing docs** — CLAUDE.md / AGENTS.md and the docs they point to. +- **Explicit routing hints, opportunistic** — if the project happens to expose a skill→area map (a `.claude/review.config.json`, a skills table in CLAUDE.md, zone globs in a skill's own frontmatter), keep it as an accelerator. Its absence changes nothing. + +Record the result in `.speccy//capabilities.md` so it survives a `/clear` and every phase reads one manifest. Found nothing? Record that and run the generic pipeline unchanged. + +**Route by relevance — the base mechanism needs no map.** Because skills self-describe their triggers, the default router is judgment: match the task in front of a subagent to the skills whose trigger text fits, and name them. An explicit skill→area map, where one exists, only accelerates this — it is never a precondition for it. + +**Inject per phase.** Before spawning a subagent, prepend a short "Project capabilities — prefer these over generic approaches" block scoped to that phase's slice (format in `prompts/project-capabilities.md`): + +- **Spec & plan research** — the *research* subagents and governing docs. Have the planner delegate discovery to a project hunter (architecture / frontend / docs) before any generic codebase sweep, and cite what it returns. +- **Build** — the skills whose triggers match each task's files, attached to that task as "consult these first"; plus, for any placement / existence question, an answer pre-resolved by a project research agent and baked in (a build agent runs inside the workflow and cannot spawn its own subagents). +- **Review** — the project review gate is already a lens (Phase 4); also pass the skill catalog to the local-doc and codebase-fit lenses so they judge against house rules, not generic taste. + +**Project capabilities are project truth.** A hunter's finding or a house skill's rule reflects how this repo actually works — treat it as authoritative context, the same standing the project review gate already has, not a claim to adversarially re-verify. + ## Steering away from cognitive surrender Speccy's own output is the hazard. Adversarially-hardened specs and plans read as authoritative, and the more authoritative they read, the stronger the pull for the user to approve without understanding (cognitive surrender: borrowed confidence, surface correctness hiding deeper flaws). The pipeline already hardens its artifacts. These habits guard the user's engagement, which nothing else does. @@ -180,6 +209,8 @@ Ask only about gaps the intake leaves genuinely open and that materially change Identify external context that would improve the spec or plan — documentation, other projects with relevant patterns, standards, API references. Ask the user about anything you can't access directly. This is worth doing early: missing context discovered mid-build is expensive. Record the references that matter in the spec itself (under Open questions, or a short references note) so they survive the context clear before planning — anything left only in conversation is lost when the user `/clear`s. +**Gather in-repo context through the project's own research agents first.** If the capability manifest found read-only research / hunter agents (architecture / frontend / docs), dispatch the relevant one to answer where a thing lives, how an existing flow works, or whether something already exists — it knows the repo better than a cold grep. Fall back to a generic Explore only when none fits. Feed what it returns into the spec's references so it survives the clear. + **Never ask what code or the environment can answer.** If a quick look at the repo, config, or tooling would settle it, look — don't ask. Questions needing deeper codebase research: mark open and defer to planning. **Asking nothing is fine.** If the intake settles what you need, write the draft and skip the interview. (Clarifying questions only; the habits under **Steering away from cognitive surrender** still apply.) @@ -202,7 +233,7 @@ Save to `specs/.md`. Commit the spec. **Always ship a short human-reading digest alongside the full spec.** The full spec is the implementation reference and it hardens (and grows dense) through the critique rounds — it is NOT what a busy human reads to understand the work. So maintain a **one-page digest** next to it (`specs/-digest.md`): the goal in 2–3 lines, the load-bearing decisions as a scannable list (each with a one-line *why*), what gets built and in what order, and the open spikes/risks. Every item **references the full spec's section** (e.g. "(§ Auth)") so the reader drills in only where needed — the full spec stays canonical, the digest never restates it in full or diverges. Regenerate the digest whenever the spec materially changes (after the critique loop converges, at minimum). At the user-review gate, point the user at the **digest first**, the full spec for depth. (Bilingual note — the rule, inline: the canonical digest, like every doc, is **English and git-tracked** in the repo's normal docs location — never a non-English copy in a tracked path. If the user reads or edits in their own language, ALSO write a translated copy, kept ONLY in a **gitignored `.users-files/`** zone; never put a translation in a tracked path, and never put the canonical doc inside `.users-files/`. Keep the two in sync — **on conflict the English git-tracked copy wins** — and leave the section references in the canonical English so they don't drift.) -Generate a `runId`: lowercase kebab from the slug plus a `YYYYMMDD-HHmm` timestamp (e.g. `auth-refactor-20260609-1430`). Create `.speccy//` and ensure `.speccy/` is in `.gitignore`. Write the initial `state.json` (phase: `spec-critique`, with runId, slug, baseBranch, adversaryModel, builderModel, specPath). Also write the runId to `.speccy/.current-runid` (plain text, no newline needed) so a later session can find this run without globbing. +Generate a `runId`: lowercase kebab from the slug plus a `YYYYMMDD-HHmm` timestamp (e.g. `auth-refactor-20260609-1430`). Create `.speccy//` and ensure `.speccy/` is in `.gitignore`. Write the initial `state.json` (phase: `spec-critique`, with runId, slug, baseBranch, adversaryModel, builderModel, specPath). Also write the runId to `.speccy/.current-runid` (plain text, no newline needed) so a later session can find this run without globbing. Now persist the capability manifest discovered in preconditions to `.speccy//capabilities.md`, so every downstream phase — and a resumed context — reads it from disk rather than conversation memory. Tell the user about the directory — critique rounds, the plan, review notes, and run state will be saved there so they can open them in their editor rather than scrolling terminal output. Mention the path once here; don't repeat it at every save. @@ -232,6 +263,8 @@ Planning research happens in a subagent to keep the codebase-reading noise out o Spawn a planning subagent (Agent tool) with the plan-research prompt, the spec path, the target plan path (`.speccy//plan.md`), and the path to `prompts/plan-spike.md` so the planner can prove any load-bearing mechanism (preferably by spawning a spike subagent, or inline). If the spec recorded external context (docs, standards, related projects), pass those references too — read them from the spec rather than relying on conversation memory, since planning may run in a freshly cleared context. +Pass the capability manifest (`.speccy//capabilities.md`) as well, with the phase preamble (`prompts/project-capabilities.md`): instruct the planner to delegate codebase discovery to the project's research / hunter agents before any generic sweep, to consult the skills whose triggers match the area it's planning, and to cite what each returns — so the plan is grounded in how the repo actually works, not a generic reading of it. + When it completes, brief the user on the approach, key decisions, and risks from `.speccy//plan.md` — point them there for the full text rather than dumping it inline. Update state.json with `planPath` and `phase: "plan-critique"`. **If the plan flags a contradicted spec assumption**, stop before the plan-critique loop and put it to the user as a blocking choice: accept the adjusted scope, or revise the spec and re-plan. A falsified assumption can invalidate scope, so this blocking gate always fires. @@ -274,6 +307,8 @@ Do _not_ wrap this in an Agent subagent — Agent subagents lack `Workflow`, so **Push for parallelism where the plan allows.** Plan-execution's breakdown defaults to sequential steps; a purely serial run is the single biggest wall-clock cost. When invoking plan-execution, augment the breakdown instruction to **parallelize genuinely independent work** — group tasks that touch disjoint files with no data dependency into parallel steps (each maps to a spec/plan acceptance criterion). Authoring independent units concurrently (e.g. a test class per production class, or separate feature files) is the clearest win. **Caveat, state it to the breakdown:** if the project verifies against a single shared environment (one scratch org, one database), the *deploy/test* step of parallel tasks contends on that resource and effectively serialises — so parallelism cuts authoring time, not the shared-environment round-trip. Only parallelise the authoring, and let integration/verification funnel through the shared resource. +**Route the project's capabilities into each task.** Also instruct breakdown to attach to every task the skills whose triggers match that task's files — an explicit "consult these before writing" list the build agent activates itself (it can invoke a Skill; it cannot dispatch an Agent). Placement and existence questions are different — "where does this belong", "does a primitive for this already exist" — and a build agent inside the workflow can't spawn a research agent to settle them, so resolve those up front with the project's hunter agents and bake the answer into the task description. Pass the capability manifest path (`.speccy//capabilities.md`) so breakdown has the roster; if the manifest is empty, this augmentation is a no-op and breakdown proceeds as usual. + When the workflow reports complete, do not advance on its "gates pass" / "0 violations" summary — a build agent can satisfy a gate by fabricating or inverting a rule and still report green. Re-run the project's load-bearing gates yourself (the build, lint / static-analysis, and test commands from CLAUDE.md) and confirm the actual tool output. **Use the project's documented harness the way CLAUDE.md specifies it** — if CLAUDE.md names an MCP tool for a gate (e.g. a deploy/test MCP), invoke that MCP tool rather than shelling out to the raw CLI; a raw-CLI wrapper is a fallback, not the default. If a gate fails, the run isn't done: carry the real tool output into a fix round (the Phase 4 implementation-fix agent handles exactly this), re-run the gates after it, and repeat until you have seen them pass. Only then set `phase: "review"` in state.json and continue. **Economise the round-trips** (the dominant wall-clock cost when the gate hits a remote environment — a scratch org, a CI runner, a container). The trust rule (see it pass yourself) is non-negotiable; what's negotiable is not paying for the full remote round-trip on every intermediate step. @@ -303,7 +338,7 @@ Pass each bespoke lens `prompts/review-output-contract.md` alongside its own pro - **Spec fidelity** — `prompts/review-spec-fidelity.md`, with the spec path. Does the code satisfy the spec's completion criteria and intent? - **Tests** — `prompts/review-tests.md`, with the spec and plan paths. Test-strategy adherence, test quality, and consolidation of new tests against the existing suite. - **Codebase fit** — `prompts/review-codebase-fit.md`. Does this change worsen an already-imperfect area or repeat an existing smell? Judged against the touched files' current state, not the diff alone. -- **Local-doc adherence** — `prompts/review-local-docs.md`. Violations of the repo's governing docs, including CLAUDE.md — which it deliberately re-checks even though code-review covers it too. +- **Local-doc adherence** — `prompts/review-local-docs.md`. Violations of the repo's governing docs, including CLAUDE.md — which it deliberately re-checks even though code-review covers it too. Pass it the capability manifest so it judges against the project's actual skills and governing docs, not a generic reading; where a house skill states a rule, a violation of that rule is a finding. - **Suppressions** — `prompts/review-suppressions.md`. Extremely harsh on any linter/analysis/type/test-gate suppression the change adds or leans on. Each must be watertight or it is a finding. - **Comments** — `prompts/review-comments.md`. Comments the change adds or edits that restate the code, narrate edit history, or pad a real point. Proposes deletions only; the fixer mends any seam. diff --git a/.claude/skills/speccy/prompts/project-capabilities.md b/.claude/skills/speccy/prompts/project-capabilities.md new file mode 100644 index 0000000..5026270 --- /dev/null +++ b/.claude/skills/speccy/prompts/project-capabilities.md @@ -0,0 +1,30 @@ +# Project capabilities — manifest & injection block + +Speccy discovers a project's own capabilities once (see the SKILL's **Lead with the project's own capabilities**) and prefers them over generic defaults at every phase. This file holds the two reusable pieces: the manifest shape, and the preamble to prepend to a spawned subagent's prompt. + +Everything here is optional. Probe only what the project actually exposes; omit whatever came up empty. If all of it is empty, the manifest says so and the pipeline runs generically — never invent a capability to fill a slot. + +## Manifest shape (`.speccy//capabilities.md`) + +A short, human-readable inventory. One line per entry. + +- **Skills** — `id` + its trigger ("use when …"), copied from the skill's own description. This is the routing key: a skill self-describes when it applies. +- **Research agents** — read-only "hunter" agents: `name · what it answers · how to dispatch`. These gather in-repo context — where things live, how an existing flow works, whether something already exists. +- **Reviewer agents / review gate** — the project's own review agents or `/review`-style gate, if any. Used as a Phase 4 lens, not re-derived. +- **Governing docs** — CLAUDE.md / AGENTS.md and the key docs they point to. +- **Routing hints** — any explicit skill→area map found (a review-config's zones, a CLAUDE.md skills table, zone globs in a skill's frontmatter). A convenience accelerator over trigger-text matching, never a requirement. + +## Injection preamble (prepend to a subagent prompt, scoped to the phase) + +> **Project capabilities — prefer these over generic approaches.** +> Before doing this the generic way, use what the project already ships: +> - SKILLS relevant here: `` — consult / activate these first. +> - RESEARCH AGENTS: `` — context already gathered for you below, or dispatch if your context allows it. +> - GOVERNING DOCS: ``. +> Match by relevance — a skill's own trigger text tells you when it applies. Treat a project skill's rule or a hunter's finding as how this repo actually works, not a claim to re-litigate. + +Include only the slice that fits the phase, and drop any line the manifest has nothing for: + +- **Spec / plan research** — research agents + governing docs. The planner delegates discovery to a hunter before a generic sweep. +- **Build task** — the skills whose triggers match the task's files, plus any placement/existence answer already resolved by a hunter and baked in (a build agent inside the workflow can't dispatch one itself). +- **Review lens** — the skill catalog, so local-doc / codebase-fit judge against house rules rather than generic taste. From 56b4d22e66ca8d6fec745249233c7087b0358de7 Mon Sep 17 00:00:00 2001 From: Maslenok Date: Tue, 4 Aug 2026 18:05:14 +0200 Subject: [PATCH 6/8] Breakdown attaches project capabilities; execute consults them first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Breakdown gives each task the trigger-matched project skills as a "consult these before writing" list and pre-resolves placement/existence questions via the project's hunter agents — the executing agent can invoke a Skill but cannot dispatch an Agent. Execute activates the listed skills before writing and treats baked-in research findings as authoritative. Additive: with no capabilities present, both prompts behave as before. --- .claude/skills/plan-execution/DECISION_LOG.md | 6 ++++++ .claude/skills/plan-execution/prompts.md | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/.claude/skills/plan-execution/DECISION_LOG.md b/.claude/skills/plan-execution/DECISION_LOG.md index 9623edd..3cb1c48 100644 --- a/.claude/skills/plan-execution/DECISION_LOG.md +++ b/.claude/skills/plan-execution/DECISION_LOG.md @@ -140,6 +140,12 @@ The first covers a task that edits a shared type, interface, or fixture: its dow The second covers a task that hard-codes a convention value from the plan rather than checking the real sibling files. Such a value is wrong when it differs from what the code uses, and dead when it matches nothing. The rule has the task discover the convention against the real files at build time instead of freezing a template value. +### Breakdown attaches project capabilities; execute consults them first (2026-08-04) + +Execute agents run in fresh, isolated contexts and were re-deriving house conventions a project already ships as skills — and getting caught only at review. Worse, a task hinging on where-something-belongs or whether-something-already-exists had no way to ask: an executing agent inside the workflow can invoke a Skill but cannot dispatch an Agent, so a project's read-only research/hunter agents were unreachable exactly when they were needed. + +Two prompt rules close this, split by who can act. Breakdown (which runs where agents CAN be dispatched) attaches to each task the skills whose triggers match its files as an explicit "consult these before writing" list, and resolves placement/existence questions against the project's hunter agents up front, baking the answer into the task description. Execute activates the listed skills before writing and treats the baked-in research findings as authoritative context about the repo. Absent any such capabilities, both prompts fall through to authoring and executing as before — the mechanism is additive, never required. + ## Known limitations These are documented rather than deferred indefinitely — they represent real failure modes that haven't bitten hard enough yet to justify the added complexity. diff --git a/.claude/skills/plan-execution/prompts.md b/.claude/skills/plan-execution/prompts.md index 5ab3165..9bd4f82 100644 --- a/.claude/skills/plan-execution/prompts.md +++ b/.claude/skills/plan-execution/prompts.md @@ -24,6 +24,8 @@ For each task, write self-contained instructions — a fresh agent with no knowl **Conform to the target file's convention; don't prescribe one.** When a task names a concrete convention (a metadata element, a field or key name, a file layout), tell it to match what sibling files actually use, not a value asserted here. A prescribed value that differs from the real convention is wrong at worst, dead at best. +**Attach the project's own capabilities to each task.** If a project-capability manifest is provided (or the project's skills and agents are otherwise visible to you), give each task the skills whose triggers match its files as an explicit "consult these before writing" list — the executing agent can invoke a Skill, so naming them makes it apply the house convention instead of re-deriving it. For a task that turns on where-something-belongs or whether-something-already-exists, resolve it *now* against the project's read-only research / hunter agents and bake the answer into the task description: the executing agent runs in an isolated worktree and cannot dispatch an agent of its own. Absent any such capabilities, author the task as usual. + Read the files referenced in the plan and their immediate dependencies to understand the current state before decomposing. Write each task description to `.tasks/{run-id}/{task-id}.md`, using the run ID provided below. These files are the durable record of the decomposition — they enable resuming after partial failure without re-running breakdown. Ensure `.tasks/` is in `.gitignore`. @@ -36,6 +38,8 @@ When a task's instructions reference its own task file (or another task file), g Execute this task in your worktree. Do NOT merge or modify other branches. +**Use the project's own conventions first.** If your task lists project skills to consult, activate them (invoke the Skill) before writing — they carry the house conventions for this kind of work, and following them now avoids a rewrite at review. Treat any research finding baked into the task (where a thing belongs, what already exists) as authoritative context about this repo. + The plan and spec are authoritative — treat them as read-only. Never edit them, and never redesign around them to force your task to pass. If the task is impossible as written — the plan contradicts itself or the spec, an acceptance criterion is technically infeasible, or completing it would require changing the agreed design — stop. Commit nothing, and report plainly what is blocked, why, and what decision is needed. Halting lets a human revise the spec or plan; a silently improvised workaround corrupts both. Before committing, run the verification level your task specifies. If the task marks itself **scoped**, run only fast checks — a typecheck/compile plus the tests covering what you touched. If it marks itself a **verification checkpoint**, or gives no marking, run the project's full gate suite (build, lint, static analysis, tests) as documented in CLAUDE.md and fix any breakage — a checkpoint's footprint is the whole integrated base, so it may repair regressions wherever they surface, not only in files it introduced. Either way, never hand broken code downstream. If CLAUDE.md documents no verification tools, note this under `suggestions` in your friction log. From cf46ceb5fa92934e1b59a471d8f30f84b78ca6e5 Mon Sep 17 00:00:00 2001 From: Maslenok Date: Tue, 4 Aug 2026 18:09:33 +0200 Subject: [PATCH 7/8] Rewrite the speccy skill prose to a readability standard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Point first in every section, one idea per sentence, long sentences split, parenthetical asides unfolded, condition sets as bullets. Language-only: an independent fresh-context audit compared old vs new file by file — every rule, threshold, ordering, path, model assignment, gate, and exception survives; nothing lost, weakened, or invented. Code blocks, schemas, and frontmatter untouched. --- .claude/skills/speccy/DECISION_LOG.md | 8 + .claude/skills/speccy/SKILL.md | 285 +++++++++--------- .../speccy/prompts/implementation-fix.md | 6 +- .../skills/speccy/prompts/plan-critique.md | 12 +- .../skills/speccy/prompts/plan-research.md | 32 +- .claude/skills/speccy/prompts/plan-spike.md | 6 +- .../speccy/prompts/project-capabilities.md | 12 +- .../speccy/prompts/review-codebase-fit.md | 10 +- .../skills/speccy/prompts/review-comments.md | 18 +- .../speccy/prompts/review-local-docs.md | 6 +- .../speccy/prompts/review-output-contract.md | 6 +- .../speccy/prompts/review-spec-fidelity.md | 10 +- .../speccy/prompts/review-suppressions.md | 15 +- .claude/skills/speccy/prompts/review-tests.md | 10 +- .claude/skills/speccy/prompts/revise.md | 8 +- .../skills/speccy/prompts/spec-critique.md | 15 +- .../skills/speccy/prompts/spec-template.md | 20 +- 17 files changed, 253 insertions(+), 226 deletions(-) diff --git a/.claude/skills/speccy/DECISION_LOG.md b/.claude/skills/speccy/DECISION_LOG.md index 476d560..23d2cc1 100644 --- a/.claude/skills/speccy/DECISION_LOG.md +++ b/.claude/skills/speccy/DECISION_LOG.md @@ -455,3 +455,11 @@ Speccy used a project's own machinery only reactively. The review panel would ca The fix is discover-once-then-inject. A new precondition probes what the project exposes — skills, `.claude/agents/*.md` subagents tagged research/reviewer/other, governing docs, and any explicit skill→area map — into a manifest persisted at `.speccy//capabilities.md` (Phase 1c), so every phase and a resumed context read one inventory instead of re-probing. Each spawn site then prepends a phase-scoped "prefer these over generic approaches" block (`prompts/project-capabilities.md`): spec/plan research delegates discovery to project hunters before any generic sweep; breakdown attaches trigger-matched skills to each task and bakes in hunter-resolved placement answers (a build agent inside the workflow can invoke a Skill but cannot dispatch an Agent, so placement/existence questions are resolved up front); the local-doc lens judges against the house skill set. Two boundaries were chosen deliberately. Nothing is required: every signal is optional and its absence degrades cleanly to the generic pipeline — there is no mandatory config artifact, because projects differ in what they ship. And the base router needs no map: skills self-describe their triggers ("use when …"), so matching a task to a skill is judgment over trigger text; an explicit skill→area map, where one exists, only accelerates. Capabilities are treated as project truth — the same standing the project review gate already has — not claims to adversarially re-verify. + +### The prose is rewritten to a readability standard (2026-08-04) + +The skill's text is dense by necessity — nearly every paragraph carries a rule an orchestrator must execute — but the *sentences* had grown expensive: 40-word constructions with nested parenthetical asides, points buried mid-paragraph, condition sets folded into prose. That shape taxes both executors, the model following the instructions and the human auditing them. + +So the prose is held to a standard: the point leads each section, one idea per sentence, sentences past roughly 25 words split, parenthetical asides unfolded into their own sentences, enumerable conditions turned into bullets. This is a language-only change. An independent fresh-context audit compared old against new file by file and confirmed every behavioral rule, threshold, ordering, path, model assignment, gate, and exception survives — nothing lost, weakened, or invented. Code blocks, JSON schemas, and frontmatter are untouched, so trigger behavior is unchanged. + +The rationale stays inline. Much of this skill's density is compressed why — the boundary conditions live inside the reasons — so the rewrite shortens wording, not justification. Word count drops only a few percent; the gain is per-sentence cost, not length. diff --git a/.claude/skills/speccy/SKILL.md b/.claude/skills/speccy/SKILL.md index 29b64fc..9915d71 100644 --- a/.claude/skills/speccy/SKILL.md +++ b/.claude/skills/speccy/SKILL.md @@ -9,51 +9,51 @@ allowed-tools: Bash(bash *skills/speccy/banner.sh), Read(.speccy/**), Write(.spe Full pipeline: specification → spec critique → planning → plan critique → implementation → implementation review. -The orchestrator runs in the main conversation. Heavy work — adversarial critiques, codebase research for planning, applying critique revisions, implementation, and code review — is delegated to subagents so the main context stays small. Persistent state lives in files; the run can be paused at any phase boundary, `/clear`ed, and resumed. +The orchestrator runs in the main conversation. Heavy work goes to subagents — critiques, planning research, revisions, the build, code review — so the main context stays small. State lives in files. The run can pause at any phase boundary, be `/clear`ed, and resume. ## Getting started -When the skill triggers, **show the Speccy banner first**, on every invocation. Run `banner.sh` from this skill's own directory (alongside this SKILL.md) by its **absolute path** — a relative path breaks when the Bash cwd has drifted or the skill is installed as a plugin. Don't prepend `cd` and don't use command substitution; both break the pre-approved permission match. +Show the Speccy banner first, on every invocation. Run `banner.sh` from this skill's own directory, by its absolute path — a relative path breaks when the Bash cwd has drifted or the skill is installed as a plugin. Do not prepend `cd` and do not use command substitution; both break the pre-approved permission match. ```bash bash /banner.sh ``` -The script prints two Markdown lines. **Reproduce them verbatim at the top of your reply** — that is what the user sees. Running the script alone isn't enough; its tool output is hidden by default. +The script prints two Markdown lines. Reproduce them verbatim at the top of your reply — that is what the user sees. Running the script alone is not enough; its tool output is hidden by default. -The banner is cosmetic. If the script fails or would prompt, just proceed without it — never block the run on it. +The banner is cosmetic. If the script fails or would prompt, proceed without it. Never block the run on it. -Then check for an in-progress run (see **Resuming a run** below). If one exists, offer to resume before starting fresh. +Then check for an in-progress run (see **Resuming a run**). If one exists, offer to resume before starting fresh. -For a new run, give a one-sentence introduction: this skill walks through writing a spec, getting it independently critiqued, building the implementation, and reviewing the result. Then ask two things in one turn: +For a new run, introduce the skill in one sentence: it walks from writing a spec, through independent critique, to a built and reviewed implementation. Then ask two things in one turn: -1. **Walkthrough or start?** Tell the user they can ask for a walkthrough of the process, or just describe what they want to build to get going. If they ask for the walkthrough, explain each phase in a few sentences, organised around what the user does vs what runs autonomously: - - **Spec** (interactive) — the skill interviews the user to build a structured spec, then the user reviews and edits until satisfied. - - **Spec critique** (user-in-the-loop) — an independent reviewer critiques the spec each round. The user decides what feedback to incorporate. - - **Plan** (autonomous loop) — a subagent researches the codebase and drafts a plan; an independent reviewer critiques and a revise agent applies findings until the plan is clean. +1. **Walkthrough or start?** The user can ask for a walkthrough of the process, or describe what they want to build and start. The walkthrough explains each phase in a few sentences, organised by what the user does versus what runs autonomously: + - **Spec** (interactive) — an interview builds a structured spec; the user reviews and edits until satisfied. + - **Spec critique** (user-in-the-loop) — an independent reviewer critiques the spec each round; the user decides what to incorporate. + - **Plan** (autonomous loop) — a subagent researches the codebase and drafts a plan; a reviewer critiques and a revise agent applies findings until the plan is clean. - **Plan review** (user decides) — the user reviews the hardened plan, raises concerns, approves. - - **Implementation** (autonomous loop) — the skill builds to the plan; parallel reviewers check the code across several lenses (correctness and quality via the built-in `code-review` skill, the repo's own review gate when it ships one, plus spec fidelity, tests, codebase fit, local-doc adherence, and strict scrutiny of linter/analysis suppressions); fixes are applied directly, or deferred as future work. + - **Implementation** (autonomous loop) — the build follows the plan. Parallel reviewers then check the code across several lenses: correctness and quality via the built-in `code-review` skill, the repo's own review gate when it ships one, plus spec fidelity, tests, codebase fit, local-doc adherence, and strict scrutiny of suppressions. Fixes are applied directly or deferred as future work. - **Wrap-up** — summary, decision log, retrospective. The user reviews the final diff on the branch. - Also mention: state is saved after every phase boundary, so the user can `/clear` and re-invoke the skill at any point to resume with a fresh context. Useful for long runs where the main conversation has grown. + Also mention: state is saved at every phase boundary, so the user can `/clear` and re-invoke at any point to resume with a fresh context. Useful for long runs where the conversation has grown. -2. **Defaults you can change.** Note the per-phase model defaults (just below) and that they're overridable. No need to ask — just flag that the options exist. +2. **Defaults you can change.** Flag the per-phase model defaults below and that they are overridable. Don't ask — just flag that the options exist. -Each phase has its own model default: +Per-phase model defaults: -- **Spec and plan critique** — opus every round (both the adversary and the revise agent), up to 3 rounds. These are short, high-leverage artifacts where cheaper tiers cost more in false-positive triage than they save. -- **Implementation review** — parallel review lenses, up to 3 rounds (see Phase 4). The four judgment lenses (spec fidelity, tests, codebase fit, local-doc adherence) run on opus and the suppressions lens on sonnet; the built-in `code-review` skill runs alongside them at `high` effort and manages its own models. -- **Builder** (execute/integrate/verify inside plan-execution) — sonnet; plan-execution's breakdown agent always uses opus. +- **Spec and plan critique** — opus every round, for both the adversary and the revise agent, up to 3 rounds. These artifacts are short and high-leverage; cheaper tiers cost more in false-positive triage than they save. +- **Implementation review** — parallel review lenses, up to 3 rounds (see Phase 4). The four judgment lenses — spec fidelity, tests, codebase fit, local-doc adherence — run on opus; the suppressions lens runs on sonnet. The built-in `code-review` skill runs alongside at `high` effort and manages its own models. +- **Builder** — sonnet, for execute/integrate/verify inside plan-execution. Plan-execution's breakdown agent always uses opus. Two overrides: pin a single adversary model (`adversaryModel`), then used for every critique round and review lens; and raise the builder (`builderModel`), commonly to opus for high-stakes work. -Each loop restarts at round 1 and early-exits when a round surfaces no valuable criticism. +Each loop restarts at round 1 and exits early when a round surfaces no valuable criticism. -If the user's trigger message already includes a description of what to build, skip straight to the adversary model note and proceed to the precondition check and Phase 1. +If the trigger message already describes what to build, skip straight to the model note, then the precondition checks, then Phase 1. ## Resuming a run -Run state lives at `.speccy//state.json` and is written after every phase boundary. Schema: +Run state lives at `.speccy//state.json`, written at every phase boundary. Schema: ```json { @@ -74,41 +74,41 @@ Run state lives at `.speccy//state.json` and is written after every phas } ``` -`adversaryModel` defaults to `"opus"` — the tier for every critique round and the review panel's judgment lenses (the suppressions and comment lenses run a tier below; see **Getting started**). If the user pinned a different adversary model, store that name here instead and use it for every critique round and review lens. +`adversaryModel` defaults to `"opus"` — the tier for every critique round and the review panel's judgment lenses. The suppressions and comment lenses run a tier below; see **Getting started**. If the user pinned a different adversary model, store that name here and use it for every critique round and review lens. -On trigger, read `.speccy/.current-runid` — a pointer to the most recent run, written when the run is created (see Phase 1c). If it exists, read that run's `state.json`; if `phase` is not `"complete"`, surface the run to the user and ask whether to resume or start fresh. To resume, read the artifacts state.json references (spec, plan, latest critique round) and continue from the recorded phase. A resumed run skips the precondition checks, so if the recorded phase is anything past the spec interview, suggest auto-accept mode (shift+tab) first — the rest of the run is autonomous tool calls. +On trigger, read `.speccy/.current-runid` — a pointer to the most recent run, written when the run is created (Phase 1c). If it exists, read that run's `state.json`. If `phase` is not `"complete"`, surface the run and ask whether to resume or start fresh. To resume, read the artifacts state.json references — spec, plan, latest critique round — and continue from the recorded phase. A resumed run skips the precondition checks; if the recorded phase is past the spec interview, suggest auto-accept mode (shift+tab) first, because the rest of the run is autonomous tool calls. -After completing each phase, update state.json and continue to the next phase. The user can `/clear` and re-invoke the skill at any point to resume from the recorded phase — no need to ask permission at phase boundaries. +After completing each phase, update state.json and continue. The user can `/clear` and re-invoke at any point to resume from the recorded phase — do not ask permission at phase boundaries. -Read and write `.speccy/` state with the Read/Write tools — these paths are pre-approved in this skill's `allowed-tools`, so they won't prompt. Do **not** rely on the Glob tool: it isn't available in every session, which is why run discovery uses the `.current-runid` pointer. The pointer tracks the latest run; earlier runs remain in `.speccy/` if the user wants to revisit one. +Read and write `.speccy/` state with the Read/Write tools; these paths are pre-approved in `allowed-tools`, so they won't prompt. Do not rely on the Glob tool — it isn't available in every session, which is why run discovery uses the `.current-runid` pointer. The pointer tracks the latest run; earlier runs remain in `.speccy/` if the user wants to revisit one. ## Preconditions -Before running any of the checks below, suggest the user enable auto-accept mode (shift+tab). From here to the end of the run the work is mostly tool calls — the verification smoke-test runs the project's linters and tests, then planning, critique, implementation, and review run autonomous loops — so approving each one by hand is pure friction. The spec interview is a conversation regardless, so auto-accept doesn't take any decisions away: the user still reviews and edits the spec content directly. +Before the checks below, suggest the user enable auto-accept mode (shift+tab). From here to the end of the run the work is mostly tool calls: the verification smoke-test runs the project's linters and tests, then planning, critique, implementation, and review run autonomous loops. Approving each call by hand is pure friction. The spec interview stays a conversation either way, so auto-accept takes no decisions away from the user. ### Verification tools -Check that CLAUDE.md documents the project's verification tools (build, lint, static analysis, test commands). These are needed during implementation — execute agents run them to validate their work. If they're missing, tell the user before proceeding. Establishing verification standards is part of project setup, not something to discover mid-build. +Check that CLAUDE.md documents the project's verification tools: build, lint, static analysis, test commands. Execute agents run them to validate their work. If they're missing, tell the user before proceeding — verification standards are project setup, not something to discover mid-build. -Documented is not the same as working. **Smoke-test the tooling now, on the clean tree, before investing in spec and plan** — a broken or pathological verification setup discovered at implementation has already cost a spec, several critique rounds, and a plan. Run each documented command once and confirm it completes, passes (or note its baseline failures), and returns in a reasonable time. Surface anything that hangs, errors, or floods output before proceeding. +Documented is not the same as working. Smoke-test the tooling now, on the clean tree, before investing in spec and plan — a broken verification setup discovered at implementation has already cost a spec, several critique rounds, and a plan. Run each documented command once. Confirm it completes, passes (or note its baseline failures), and returns in reasonable time. Surface anything that hangs, errors, or floods output before proceeding. ### Project capabilities -Discover the project's own capabilities now and hold the manifest — skills, specialized subagents, governing docs, and any explicit routing hints (see **Lead with the project's own capabilities** for what to probe and how each phase uses it). This is discovery only: it never blocks, and a project that exposes none of it just runs the generic pipeline. Doing it here, before the spec, means every downstream phase reads one manifest instead of re-probing. The run directory doesn't exist yet, so keep the manifest in context now; you persist it to `.speccy//capabilities.md` when the run is created in Phase 1c. +Discover the project's own capabilities now and hold the manifest: skills, specialized subagents, governing docs, and any explicit routing hints. See **Lead with the project's own capabilities** for what to probe and how each phase uses it. This is discovery only — it never blocks, and a project that exposes none of it just runs the generic pipeline. Doing it before the spec means every downstream phase reads one manifest instead of re-probing. The run directory doesn't exist yet, so hold the manifest in context; persist it to `.speccy//capabilities.md` when the run is created in Phase 1c. ### Worktree init -Worktrees come into play only for **parallel** tasks. Plan-execution runs sequential tasks directly on the main checkout; only parallel tasks get git worktrees, which lack gitignored state. You won't know whether the plan produces parallel tasks until breakdown, so treat this as preparation that may not be exercised this run. Check whether CLAUDE.md has a `## Worktree init` section with gather/apply blocks. If it does, nothing to do — plan-execution will use it if parallel tasks arise. +Worktrees matter only for **parallel** tasks. Plan-execution runs sequential tasks on the main checkout; only parallel tasks get git worktrees, which lack gitignored state. Whether the plan produces parallel tasks is unknown until breakdown, so treat this as preparation that may go unused. Check whether CLAUDE.md has a `## Worktree init` section with gather/apply blocks. If it does, nothing to do — plan-execution will use it. -**If either the `worktree.baseRef` setting or the `## Worktree init` section is missing, do NOT stop, prompt for a hand-authored section, or silently force the whole run sequential — resolve a sensible default in-skill and carry on:** +If the `worktree.baseRef` setting or the `## Worktree init` section is missing, do NOT stop, prompt for a hand-authored section, or silently force the run sequential. Resolve a default in-skill and carry on: -- **`worktree.baseRef` missing** → ensure it is `head` (write it to `.claude/settings.json` via Bash/python; direct Edit is blocked). The default `fresh` branches from `origin/` and misses feature-branch commits. (Plan-execution also self-heals this, so it's belt-and-suspenders.) -- **`## Worktree init` section missing** → synthesize a minimal default from `.gitignore` + the verification commands rather than punting. Almost every project's worktree just needs its gitignored dependency/config artifacts linked in from the main checkout. Build a `worktreeInit` array that idempotently symlinks those (`ln -snf / `), covering at minimum the package-manager install dir the verify commands need (`node_modules`, `.venv`, `vendor`, `target`, …) plus any generated config the verify step reads. Pass that array straight to plan-execution as `worktreeInit`. Resolve `` with `git rev-parse --show-toplevel` at gather time. -- **Only if you genuinely cannot determine the dependency dirs** (no recognizable lockfile/manifest, opaque build) → fall back to instructing breakdown to stay sequential-only, and say so. +- **`worktree.baseRef` missing** → ensure it is `head`. Write it to `.claude/settings.json` via Bash/python; direct Edit is blocked. The default `fresh` branches from `origin/` and misses feature-branch commits. Plan-execution also self-heals this, so it's belt-and-suspenders. +- **`## Worktree init` section missing** → synthesize a minimal default from `.gitignore` plus the verification commands. Almost every project's worktree just needs its gitignored dependency and config artifacts linked in from the main checkout. Build a `worktreeInit` array that idempotently symlinks those (`ln -snf / `) — at minimum the package-manager install dir the verify commands need (`node_modules`, `.venv`, `vendor`, `target`, …) plus any generated config the verify step reads. Pass the array straight to plan-execution as `worktreeInit`. Resolve `` with `git rev-parse --show-toplevel` at gather time. +- **Dependency dirs genuinely undeterminable** — no recognizable lockfile or manifest, opaque build → fall back to instructing breakdown to stay sequential-only, and say so. -In every case, after resolving the default, offer the user the drafted `## Worktree init` block to commit into CLAUDE.md so next time it's explicit — but this is an after-the-fact convenience, never a blocker. +In every case, after resolving the default, offer the user the drafted `## Worktree init` block to commit into CLAUDE.md so next time it's explicit. That is an after-the-fact convenience, never a blocker. -A purely sequential plan never touches worktrees, so a project that only runs sequential work exercises none of this — but the default above means a fan-out run is never blocked on a missing section. +A purely sequential plan never touches worktrees, so a sequential-only project exercises none of this. The default above means a fan-out run is never blocked on a missing section. ### Git state @@ -120,69 +120,70 @@ Before starting work: ## Formatting -Use bullet lists and unnumbered headings by default. Reserve numbered lists for sequences where order is the point — steps that must execute in a specific order, or items that will be referenced by position. If inserting or removing an item forces renumbering, it shouldn't have been numbered. +Use bullet lists and unnumbered headings by default. Reserve numbered lists for sequences where order is the point: steps that must run in a specific order, or items referenced by position. If inserting or removing an item forces renumbering, it shouldn't have been numbered. This applies to all generated artifacts: specs, plans, critiques, and review notes. ## Subagent results: trust files, not returns -Subagents run in the background, and their completion notifications are unreliable: the returned summary can arrive **misrouted** under a different agent's completion, and the notification's apparent identity (which agent, which round) can be wrong — a round-3 critique may surface labelled as the round-2 revise agent. This is expected harness noise. +Subagents run in the background, and their completion notifications are unreliable. A returned summary can arrive misrouted under a different agent's completion. The notification's apparent identity — which agent, which round — can be wrong; a round-3 critique may surface labelled as the round-2 revise agent. This is expected harness noise. -So for every spawned agent: you know what it was spawned to do and the exact file it writes, and the round number comes from state.json, not the notification. When a completion arrives, read that file and act only on its contents — never branch control flow (early-exit, round counting, commit messages, what you tell the user) on a returned summary or a notification's label. Don't narrate or diagnose misrouting; read the right file and carry on. +For every spawned agent you know what it was spawned to do and the exact file it writes, and the round number comes from state.json, not the notification. When a completion arrives, read that file and act only on its contents. Never branch control flow — early-exit, round counting, commit messages, what you tell the user — on a returned summary or a notification's label. Don't narrate or diagnose misrouting; read the right file and carry on. ## Propagate the session's voice to subagents -The main session may be governed by a behavioural or output style a fresh agent context does **not** inherit — a house-voice hook (e.g. one injected at session start), a configured output style, or communication conventions that live beyond the project's `CLAUDE.md`. A subagent starts clean and never sees the main session's system prompt, so unless you carry that style across, every critic, revise agent, planner, review lens, and fixer speaks in a default voice that clashes with how this session talks — and the artifacts they write (critiques, plan, review notes) read in a different register from the rest of the run. +The main session may be governed by a style a fresh agent does not inherit: a house-voice hook injected at session start, a configured output style, or communication conventions beyond the project's `CLAUDE.md`. A subagent starts clean and never sees the main session's system prompt. Unless you carry the style across, every critic, planner, review lens, and fixer speaks in a default voice — and the artifacts they write read in a different register from the rest of the run. -So **before spawning any subagent, restate the active style concisely at the top of its prompt** — enough that both its reasoning and its written output match the session's voice. Two things are out of reach and don't need carrying: conventions already in `CLAUDE.md` (subagents read it anyway), and the built-in `code-review` skill run inline (it manages its own prompt — the orchestrator just applies the session's voice when it normalises those findings into the lens file). This rule applies to every spawn site in the phases below; it is stated once here rather than repeated at each. Speccy's own narration back to the user follows the same style as a matter of course. +So before spawning any subagent, restate the active style concisely at the top of its prompt — enough that its reasoning and its written output match the session's voice. Two things need no carrying: conventions already in `CLAUDE.md` (subagents read it anyway), and the built-in `code-review` skill run inline (it manages its own prompt; the orchestrator applies the session's voice when normalising its findings into the lens file). This rule covers every spawn site in the phases below; it is stated once here. Speccy's own narration to the user follows the same style as a matter of course. ## Lead with the project's own capabilities -A project often ships capabilities that beat speccy's generic defaults for *this* codebase: **skills** (house conventions, domain rules, verification harnesses), **specialized subagents** (read-only research / "hunter" agents that answer where-does-this-live / how-does-X-work / does-Y-already-exist, plus the project's own review agents), **governing docs** (CLAUDE.md and what it points to), and sometimes an explicit **review gate**. A generic pipeline that ignores these re-derives — worse — what the repo already maintains, and only catches the divergence at review, a whole fix-round late. So **discover them once, up front, and prefer them at every phase.** +A project often ships capabilities that beat speccy's generic defaults for this codebase: **skills** (house conventions, domain rules, verification harnesses), **specialized subagents** (read-only research or "hunter" agents that answer where-does-this-live, how-does-X-work, does-Y-already-exist — plus the project's own review agents), **governing docs** (CLAUDE.md and what it points to), and sometimes an explicit **review gate**. A generic pipeline that ignores these re-derives, worse, what the repo already maintains — and catches the divergence only at review, a whole fix-round late. So discover them once, up front, and prefer them at every phase. -Nothing here is required. Each signal is optional and its absence degrades cleanly to the generic path — a project that exposes none of this just runs the pipeline as written. Do not depend on any one artifact existing (there is no mandatory config file); probe whatever the project actually exposes. +Nothing here is required. Every signal is optional, and its absence degrades cleanly to the generic path. Do not depend on any one artifact existing — there is no mandatory config file. Probe whatever the project actually exposes. -**Discover once (a precondition).** Probe, in layers, only what the project has: +**Discover once, as a precondition.** Probe in layers, only what the project has: - **Skills** — the skills available in this session. Each self-describes its trigger in its own description ("use when …"). -- **Specialized subagents** — read `.claude/agents/*.md` and any subagent types this session offers. From each one's description and tools, tag it *research* (read-only — answers where / how / exists), *reviewer* (a project review agent), or *other*, and note read-only vs mutating. +- **Specialized subagents** — read `.claude/agents/*.md` and any subagent types this session offers. From each one's description and tools, tag it *research* (read-only: answers where / how / exists), *reviewer* (a project review agent), or *other*. Note read-only versus mutating. - **Governing docs** — CLAUDE.md / AGENTS.md and the docs they point to. -- **Explicit routing hints, opportunistic** — if the project happens to expose a skill→area map (a `.claude/review.config.json`, a skills table in CLAUDE.md, zone globs in a skill's own frontmatter), keep it as an accelerator. Its absence changes nothing. +- **Explicit routing hints, opportunistic** — a skill→area map the project happens to expose: a `.claude/review.config.json`, a skills table in CLAUDE.md, zone globs in a skill's frontmatter. Keep it as an accelerator. Its absence changes nothing. Record the result in `.speccy//capabilities.md` so it survives a `/clear` and every phase reads one manifest. Found nothing? Record that and run the generic pipeline unchanged. -**Route by relevance — the base mechanism needs no map.** Because skills self-describe their triggers, the default router is judgment: match the task in front of a subagent to the skills whose trigger text fits, and name them. An explicit skill→area map, where one exists, only accelerates this — it is never a precondition for it. +**Route by relevance — no map needed.** Skills self-describe their triggers, so the default router is judgment: match the task in front of a subagent to the skills whose trigger text fits, and name them. An explicit skill→area map only accelerates this; it is never a precondition. -**Inject per phase.** Before spawning a subagent, prepend a short "Project capabilities — prefer these over generic approaches" block scoped to that phase's slice (format in `prompts/project-capabilities.md`): +**Inject per phase.** Before spawning a subagent, prepend a short "Project capabilities — prefer these over generic approaches" block scoped to that phase's slice. Format in `prompts/project-capabilities.md`. -- **Spec & plan research** — the *research* subagents and governing docs. Have the planner delegate discovery to a project hunter (architecture / frontend / docs) before any generic codebase sweep, and cite what it returns. -- **Build** — the skills whose triggers match each task's files, attached to that task as "consult these first"; plus, for any placement / existence question, an answer pre-resolved by a project research agent and baked in (a build agent runs inside the workflow and cannot spawn its own subagents). -- **Review** — the project review gate is already a lens (Phase 4); also pass the skill catalog to the local-doc and codebase-fit lenses so they judge against house rules, not generic taste. +- **Spec & plan research** — the research subagents and governing docs. The planner delegates discovery to a project hunter (architecture / frontend / docs) before any generic codebase sweep, and cites what it returns. +- **Build** — the skills whose triggers match each task's files, attached to the task as "consult these first". For placement and existence questions, bake in an answer pre-resolved by a project research agent — a build agent runs inside the workflow and cannot spawn its own subagents. +- **Review** — the project review gate is already a lens (Phase 4). Also pass the skill catalog to the local-doc and codebase-fit lenses, so they judge against house rules rather than generic taste. -**Project capabilities are project truth.** A hunter's finding or a house skill's rule reflects how this repo actually works — treat it as authoritative context, the same standing the project review gate already has, not a claim to adversarially re-verify. +**Project capabilities are project truth.** A hunter's finding or a house skill's rule reflects how this repo actually works. Treat it as authoritative context — the same standing the project review gate already has — not a claim to adversarially re-verify. ## Steering away from cognitive surrender -Speccy's own output is the hazard. Adversarially-hardened specs and plans read as authoritative, and the more authoritative they read, the stronger the pull for the user to approve without understanding (cognitive surrender: borrowed confidence, surface correctness hiding deeper flaws). The pipeline already hardens its artifacts. These habits guard the user's engagement, which nothing else does. +Speccy's own output is the hazard. Adversarially-hardened specs and plans read as authoritative, and the more authoritative they read, the stronger the pull to approve without understanding — cognitive surrender: borrowed confidence, surface correctness hiding deeper flaws. The pipeline hardens its artifacts; these habits guard the user's engagement, which nothing else does. -Apply these habits at the run's three human gates and nowhere else: the spec critique (1d), the plan review (2b), and the wrap-up decision log (Phase 5). The other interactive moments are not gates — the intake and interview gather requirements, the first-draft review (1c) is the user's turn to read and edit, and the build kickoff (Phase 3) is a handoff — so pose no pre-question there. The pre-question in particular assumes the user has read the artifact and is about to see it critiqued; asked before a draft is read, or after a decision is already made, it has no referent and reads as the ritual this section exists to prevent. The three habits: +Apply these habits at the run's three human gates and nowhere else: the spec critique (1d), the plan review (2b), and the wrap-up decision log (Phase 5). The other interactive moments are not gates. The intake and interview gather requirements, the first-draft review (1c) is the user's turn to read and edit, and the build kickoff (Phase 3) is a handoff — pose no pre-question there. The pre-question assumes the user has read the artifact and is about to see it critiqued; asked before a draft is read, or after a decision is already made, it has no referent and reads as the ritual this section exists to prevent. The three habits: -- **Ask before you tell, then reveal.** Before showing the agent's findings, have the user commit a *prediction*, not an open judgment: the one thing they'd bet the critique flags, or the part they'd defend least confidently. An open "where is it weakest?" is too easy to shrug off; predicting forces the user to build their own model of the artifact first, which is the anti-anchoring point. If they genuinely have nothing, offer to look together at one thing *you* find risky — but only if a real one exists (many artifacts are straightforward; don't manufacture one), drawn from your own read rather than the critique you are holding, which would leak it early. Then when you present the critique, close the loop against their prediction — "you expected X; it flagged Y — surprised?". The consequence is what makes the question land; without the reveal it decays to a shrug. -- **Flag doubt; stay quiet about certainty.** Surface where the agent is unsure and what it assumed. Never offer high confidence as a reason to skip review, since a confident wrong call adopted wholesale is the worst outcome. Point the user's attention at the doubtful parts and let the settled ones pass. -- **Name what convinced you.** When the user approves a load-bearing decision, ask them to say what persuaded them, and to notice whether they verified it or simply trusted that the agent sounded sure. Keep this to one decision per gate, so it reads as a self-check rather than an interrogation. +- **Ask before you tell, then reveal.** Before showing the agent's findings, have the user commit a *prediction*, not an open judgment: the one thing they'd bet the critique flags, or the part they'd defend least confidently. An open "where is it weakest?" is too easy to shrug off; predicting forces the user to build their own model of the artifact first, which is the anti-anchoring point. If they genuinely have nothing, offer to look together at one thing *you* find risky — but only if a real one exists; many artifacts are straightforward, and manufacturing a risk is noise. Draw it from your own read, not from the critique you are holding, which would leak it early. When you present the critique, close the loop against their prediction: "you expected X; it flagged Y — surprised?". The consequence is what makes the question land; without the reveal it decays to a shrug. +- **Flag doubt; stay quiet about certainty.** Surface where the agent is unsure and what it assumed. Never offer high confidence as a reason to skip review — a confident wrong call adopted wholesale is the worst outcome. Point the user at the doubtful parts and let the settled ones pass. +- **Name what convinced you.** When the user approves a load-bearing decision, ask them to say what persuaded them, and to notice whether they verified it or trusted that the agent sounded sure. One decision per gate, so it reads as a self-check rather than an interrogation. -Ask these as ordinary questions inside the flow of the gate; never announce that you're doing them and never give them a label to the user (not "engagement check", not "cognitive surrender") — a prompt flagged as a check gets performed, not thought about. A user who would rather not be asked can simply decline, or say so at the start; honour that, and you need not advertise the possibility. +Ask these as ordinary questions inside the flow of the gate. Never announce them and never give them a label — not "engagement check", not "cognitive surrender" — a prompt flagged as a check gets performed, not thought about. A user who would rather not be asked can decline, or say so at the start; honour that, and don't advertise the possibility. -**Vary the questions across gates.** The job repeats at each gate but the wording must not: the same pre-question framing heard three times decays into a ritual the user pattern-matches and shrugs past, which is the ritualization this whole section fights. Before posing a pre-question or a "what convinced you", read `engagementQuestions` from state.json to see what earlier gates already asked, and come at this one from a fresh angle — a different referent, a different way in — rather than reciting the template. After you ask, append a short paraphrase of what you actually posed (`{ gate, asked }`) to `engagementQuestions` and save state.json. The list starts empty and survives a `/clear`, so a resumed context still knows what framings are spent. This is about not repeating yourself, not about hunting for perfect wording — the engagement comes from the loop, and variation only keeps the loop from going stale. +**Vary the questions across gates.** The job repeats at each gate; the wording must not. The same pre-question framing heard three times decays into a ritual the user pattern-matches and shrugs past — the ritualization this whole section fights. Before posing a pre-question or a "what convinced you", read `engagementQuestions` from state.json to see what earlier gates already asked, and come at this one from a fresh angle: a different referent, a different way in, not the template again. After you ask, append a short paraphrase of what you posed (`{ gate, asked }`) to `engagementQuestions` and save state.json. The list starts empty and survives a `/clear`, so a resumed context knows what framings are spent. This is about not repeating yourself, not hunting for perfect wording — the engagement comes from the loop; variation only keeps the loop from going stale. -**Each of these questions is a stop.** Ask it as the last thing in the turn and wait — the question is the failure point precisely because the orchestrator tends to ask, then keep thinking and running tool calls until it scrolls off unanswered. Nothing follows the question until the user replies, and a pre-question never reveals the critique in the same turn (which would pre-empt the answer and lose the anti-anchoring). Put it on its own line at the end of the reply. +**Each of these questions is a stop.** Ask it as the last thing in the turn and wait. The question is the failure point precisely because the orchestrator tends to ask, then keep running tool calls until it scrolls off unanswered. Nothing follows the question until the user replies, and a pre-question never reveals the critique in the same turn — that would pre-empt the answer and lose the anti-anchoring. Put it on its own line at the end of the reply. -**The long idle stretches are the other good moment.** The autonomous phases — plan critique (2a), the build (Phase 3), the review panel (Phase 4) — leave the user waiting on a subagent for a long while, and that idle time engages well with a different device from the gate habits: not a pre-question (there's no artifact to predict yet) but an offer to deepen understanding. Offer to walk through how a part of the system works relative to what's being built, or raise an implementation detail the plan left open and ask whether the user has a preference. Only when there's something genuine to say — manufactured filler trains the user to tune speccy out. Two rules keep it from backfiring, and both invert the gate question's "stop": +**The long idle stretches are the other good moment.** The autonomous phases — plan critique (2a), the build (Phase 3), the review panel (Phase 4) — leave the user waiting on a subagent for a long while. That idle time takes a different device from the gate habits: not a pre-question — there's no artifact to predict yet — but an offer to deepen understanding. Offer to walk through how a part of the system works relative to what's being built, or raise an implementation detail the plan left open and ask whether the user has a preference. Only when there's something genuine to say — manufactured filler trains the user to tune speccy out. Two rules keep it from backfiring, and both invert the gate question's "stop": -- **It never blocks.** The job runs regardless, and a completion that lands mid-conversation is surfaced at once — the chat is opportunistic filler, never a reason to sit on a finished job. +- **It never blocks.** The job runs regardless, and a completion that lands mid-conversation is surfaced at once. The chat is opportunistic filler, never a reason to sit on a finished job. - **Any steer feeds forward** — into an upcoming task or the review — never expecting the running build to have already adopted it. A preference that would change approved scope is a re-plan, not a mid-build aside. Apply the same standard to the final diff: read it as if a contributor you do not fully trust wrote it. + ## Phase 1 — Specification Build a structured spec through interview. @@ -191,183 +192,187 @@ Build a structured spec through interview. The user may or may not have provided a starting description alongside the trigger. -**If they provided something** — a sentence, a feature request, an existing spec file — use that as the seed. If they point to a file in the repo, that's the starting draft. +**If they provided something** — a sentence, a feature request, an existing spec file — use it as the seed. A file they point to is the starting draft. -**If they provided nothing** (e.g. just "spec mode") — ask what they want to build. Suggest the kind of information that's useful at this stage: what problem they're solving, who it's for, any constraints they already know about, and how they'll know it's done. Don't require all of this upfront — just enough to start the interview. +**If they provided nothing** (just "spec mode") — ask what they want to build. Suggest what helps at this stage: the problem, who it's for, known constraints, and how they'll know it's done. Don't require all of it — just enough to start the interview. ### 1b. Interview -**Treat the intake as settled.** Take what the user gave you at face value: don't re-ask what it answers, don't ask them to reconfirm a stated choice, and only reopen a settled point if they re-raise it or you have a serious, specific doubt. Prefer recording a reasonable default in the spec's Assumptions section over asking; the critique loop challenges it there. +**Treat the intake as settled.** Take what the user gave you at face value. Don't re-ask what it answers, don't ask them to reconfirm a stated choice, and reopen a settled point only if they re-raise it or you have a serious, specific doubt. Prefer recording a reasonable default in the spec's Assumptions section over asking — the critique loop challenges it there. Ask only about gaps the intake leaves genuinely open and that materially change the spec: - Scope boundaries — what's in, what's out - Edge cases and error scenarios -- Constraints (performance, security, compatibility) +- Constraints — performance, security, compatibility - Integration points with existing code - Non-functional requirements -Identify external context that would improve the spec or plan — documentation, other projects with relevant patterns, standards, API references. Ask the user about anything you can't access directly. This is worth doing early: missing context discovered mid-build is expensive. Record the references that matter in the spec itself (under Open questions, or a short references note) so they survive the context clear before planning — anything left only in conversation is lost when the user `/clear`s. +Identify external context that would improve the spec or plan: documentation, other projects with relevant patterns, standards, API references. Ask the user about anything you can't access directly. Do this early — missing context discovered mid-build is expensive. Record the references that matter in the spec itself, under Open questions or a short references note, so they survive the context clear before planning. Anything left only in conversation is lost when the user `/clear`s. -**Gather in-repo context through the project's own research agents first.** If the capability manifest found read-only research / hunter agents (architecture / frontend / docs), dispatch the relevant one to answer where a thing lives, how an existing flow works, or whether something already exists — it knows the repo better than a cold grep. Fall back to a generic Explore only when none fits. Feed what it returns into the spec's references so it survives the clear. +**Gather in-repo context through the project's own research agents first.** If the capability manifest found read-only research or hunter agents (architecture / frontend / docs), dispatch the relevant one to answer where a thing lives, how an existing flow works, or whether something already exists — it knows the repo better than a cold grep. Fall back to a generic Explore only when none fits. Feed what it returns into the spec's references so it survives the clear. **Never ask what code or the environment can answer.** If a quick look at the repo, config, or tooling would settle it, look — don't ask. Questions needing deeper codebase research: mark open and defer to planning. -**Asking nothing is fine.** If the intake settles what you need, write the draft and skip the interview. (Clarifying questions only; the habits under **Steering away from cognitive surrender** still apply.) +**Asking nothing is fine.** If the intake settles what you need, write the draft and skip the interview. Clarifying questions only; the habits under **Steering away from cognitive surrender** still apply. ### 1c. Structured spec -Produce a first-draft spec from the interview answers using the template in `prompts/spec-template.md` (relative to this SKILL.md's directory). Fill in every section; remove the HTML comments. +Produce a first-draft spec from the interview answers using the template in `prompts/spec-template.md`, relative to this SKILL.md's directory. Fill in every section; remove the HTML comments. -**Do not restate CLAUDE.md.** Reference it by file/section when a constraint matters; only spell out a rule if this feature diverges from it. +**Do not restate CLAUDE.md.** Reference it by file/section when a constraint matters. Spell out a rule only where this feature diverges from it. -The **Assumptions** section is important — it captures the reasonable defaults chosen where the user's description was ambiguous. Unstated assumptions can't be challenged during critique, so surface them here. +The **Assumptions** section captures the reasonable defaults chosen where the user's description was ambiguous. Unstated assumptions can't be challenged during critique, so surface them here. -The **Decisions & rationale** section is equally load-bearing — every spec makes choices, and a choice whose reasoning isn't written down reads as an arbitrary default and can't be challenged. For each meaningful decision the spec commits to (a scope call, an approach, a contract or deliverable shape), record what was chosen, the viable alternative(s) weighed, and the deciding factor — *why this and not that*. Draw the reasoning out during the interview, but only where the user hasn't already given it: when a choice has a real alternative and the description doesn't explain the pick, ask why the user leans that way rather than recording it silently. Don't re-ask about a decision the input already settles — a stated preference, mandate, or existing convention is a complete rationale on its own. This is not an assumption (a guess under ambiguity); a decision is a deliberate pick among options. Keep it spec-level — the "why" behind *what* to build, not code-level *how* (that is the plan's decision body). This section is also the up-front source the wrap-up co-authored decision log distils from, so capturing rationale now means the user isn't reconstructing it from memory later. +The **Decisions & rationale** section is equally load-bearing. A choice whose reasoning isn't written down reads as an arbitrary default and can't be challenged. For each meaningful decision the spec commits to — a scope call, an approach, a contract or deliverable shape — record what was chosen, the viable alternatives weighed, and the deciding factor: why this and not that. Draw the reasoning out during the interview, but only where the user hasn't already given it. When a choice has a real alternative and the description doesn't explain the pick, ask why the user leans that way. Don't re-ask about a decision the input already settles — a stated preference, mandate, or existing convention is a complete rationale on its own. A decision is a deliberate pick among options; an assumption is a guess under ambiguity. Keep it spec-level: the why behind *what* to build, not code-level *how* — that is the plan's decision body. This section is also the source the wrap-up decision log distils from, so capturing rationale now spares the user reconstructing it from memory later. -Let the user read and edit the draft until satisfied. This is their first read, not a gate — pose no engagement question here; the pre-question comes at the 1d critique, once they have the draft in hand. +Let the user read and edit the draft until satisfied. This is their first read, not a gate — pose no engagement question here. The pre-question comes at the 1d critique, once they have the draft in hand. -Create a feature branch before committing anything. Pick a short, descriptive name for the work; if it collides with an existing branch, adjust it. Then `git checkout -b `. +Create a feature branch before committing anything. Pick a short, descriptive name; if it collides with an existing branch, adjust it. Then `git checkout -b `. Save to `specs/.md`. Commit the spec. -**Always ship a short human-reading digest alongside the full spec.** The full spec is the implementation reference and it hardens (and grows dense) through the critique rounds — it is NOT what a busy human reads to understand the work. So maintain a **one-page digest** next to it (`specs/-digest.md`): the goal in 2–3 lines, the load-bearing decisions as a scannable list (each with a one-line *why*), what gets built and in what order, and the open spikes/risks. Every item **references the full spec's section** (e.g. "(§ Auth)") so the reader drills in only where needed — the full spec stays canonical, the digest never restates it in full or diverges. Regenerate the digest whenever the spec materially changes (after the critique loop converges, at minimum). At the user-review gate, point the user at the **digest first**, the full spec for depth. (Bilingual note — the rule, inline: the canonical digest, like every doc, is **English and git-tracked** in the repo's normal docs location — never a non-English copy in a tracked path. If the user reads or edits in their own language, ALSO write a translated copy, kept ONLY in a **gitignored `.users-files/`** zone; never put a translation in a tracked path, and never put the canonical doc inside `.users-files/`. Keep the two in sync — **on conflict the English git-tracked copy wins** — and leave the section references in the canonical English so they don't drift.) +**Always ship a one-page digest alongside the full spec.** The full spec is the implementation reference; it hardens and grows dense through critique. It is not what a busy human reads to understand the work. Maintain a digest next to it, `specs/-digest.md`: the goal in 2–3 lines, the load-bearing decisions as a scannable list with a one-line why each, what gets built in what order, and the open spikes and risks. Every item references the full spec's section — e.g. "(§ Auth)" — so the reader drills in only where needed. The full spec stays canonical; the digest never restates it in full or diverges. Regenerate the digest whenever the spec materially changes, at minimum once the critique loop converges. At the user-review gate, point the user at the digest first, the full spec for depth. + +Bilingual rule, inline: the canonical digest, like every doc, is English and git-tracked in the repo's normal docs location — never a non-English copy in a tracked path. If the user reads or edits in their own language, also write a translated copy, kept only in a gitignored `.users-files/` zone. Never put a translation in a tracked path, and never put the canonical doc inside `.users-files/`. Keep the two in sync — on conflict the English git-tracked copy wins — and leave the section references in English so they don't drift. -Generate a `runId`: lowercase kebab from the slug plus a `YYYYMMDD-HHmm` timestamp (e.g. `auth-refactor-20260609-1430`). Create `.speccy//` and ensure `.speccy/` is in `.gitignore`. Write the initial `state.json` (phase: `spec-critique`, with runId, slug, baseBranch, adversaryModel, builderModel, specPath). Also write the runId to `.speccy/.current-runid` (plain text, no newline needed) so a later session can find this run without globbing. Now persist the capability manifest discovered in preconditions to `.speccy//capabilities.md`, so every downstream phase — and a resumed context — reads it from disk rather than conversation memory. +Generate a `runId`: lowercase kebab from the slug plus a `YYYYMMDD-HHmm` timestamp, e.g. `auth-refactor-20260609-1430`. Create `.speccy//` and ensure `.speccy/` is in `.gitignore`. Write the initial `state.json` (phase: `spec-critique`, with runId, slug, baseBranch, adversaryModel, builderModel, specPath). Write the runId to `.speccy/.current-runid` — plain text, no newline needed — so a later session finds this run without globbing. Persist the capability manifest from preconditions to `.speccy//capabilities.md`, so every downstream phase — and a resumed context — reads it from disk rather than conversation memory. -Tell the user about the directory — critique rounds, the plan, review notes, and run state will be saved there so they can open them in their editor rather than scrolling terminal output. Mention the path once here; don't repeat it at every save. +Tell the user about the directory: critique rounds, the plan, review notes, and run state land there, easier to open in an editor than to scroll in the terminal. Mention the path once here; don't repeat it at every save. ### 1d. Adversarial spec critique -Before investing in planning, the spec gets an independent review. Read `prompts/spec-critique.md` (relative to this SKILL.md's directory). +Before investing in planning, the spec gets an independent review. Read `prompts/spec-critique.md`, relative to this SKILL.md's directory. -Run the loop to exhaustion before offering to clear or move on. The user is in the loop on which findings to incorporate each round, but a single revised round is not a stopping point — keep critiquing until a round surfaces no valuable criticism, or 3 rounds run. Don't offer the clear or planning as a mid-loop alternative to the next round. +Run the loop to exhaustion before offering to clear or move on. The user picks findings each round, but one revised round is not a stopping point — keep critiquing until a round surfaces no valuable criticism, or 3 rounds run. Don't offer the clear or planning as a mid-loop alternative to the next round. For each round (up to 3): -1. **Critique.** Spawn an adversary subagent (Agent tool) with the spec critique prompt and the path to the spec. Instruct it to **write its review to `.speccy//spec-critique-round-N.md`**. Use **opus** for the model override on every round (or the user's pinned model, if they set one). -2. **Present.** Before showing the critique, ask the user to predict it — the finding they'd bet the reviewer raises, or the part of the spec they'd defend least confidently (see **Steering away from cognitive surrender**). If they have none and you can see a genuine soft spot, offer to look at it together; if the spec is solid, let it go. Then read `.speccy//spec-critique-round-N.md` (N from state.json), present its findings, and close the loop against their prediction ("you expected X; it flagged Y — surprised?"). Point the user to the file for the full text. Ask which findings to incorporate, and on the most consequential accept-or-reject call, ask what convinced them. If the round surfaced no valuable criticism, the loop is done — exit it. -3. **Revise.** Spawn a revise subagent (Agent tool) **on opus** with `prompts/revise.md`, the spec path, the critique file path, and the list of accepted findings. The subagent rewrites the spec in place. Once it completes, commit the updated spec with a message summarising the accepted findings you incorporated — you already have that list, so build the message from it rather than from the agent's return. Then run the next round to check the revisions and probe deeper. +1. **Critique.** Spawn an adversary subagent (Agent tool) with the spec critique prompt and the spec path. Instruct it to write its review to `.speccy//spec-critique-round-N.md`. Use **opus** as the model override every round, or the user's pinned model. +2. **Present.** Before showing the critique, ask the user to predict it: the finding they'd bet the reviewer raises, or the part they'd defend least confidently (see **Steering away from cognitive surrender**). If they have none and you see a genuine soft spot, offer to look at it together; if the spec is solid, let it go. Then read `.speccy//spec-critique-round-N.md` (N from state.json), present the findings, and close the loop against their prediction — "you expected X; it flagged Y — surprised?". Point them to the file for the full text. Ask which findings to incorporate, and on the most consequential accept-or-reject call, ask what convinced them. If the round surfaced no valuable criticism, exit the loop. +3. **Revise.** Spawn a revise subagent (Agent tool) on **opus** with `prompts/revise.md`, the spec path, the critique file path, and the accepted findings. It rewrites the spec in place. When it completes, commit the updated spec with a message summarising the accepted findings — build the message from your own list, not the agent's return. Then run the next round to check the revisions and probe deeper. -After 3 rounds, proceed regardless, noting any unaddressed feedback. Update state.json after each round (`specCritiqueRounds`). When the critique loop exits, set `phase: "planning"`. +After 3 rounds, proceed regardless, noting unaddressed feedback. Update state.json after each round (`specCritiqueRounds`). When the loop exits, set `phase: "planning"`. -**Mandatory exit gate — the cold-start flow trace.** Do NOT leave the spec-critique phase until at least one critique round has explicitly done the **end-to-end / first-run dependency trace** described in `prompts/spec-critique.md` — walking each primary flow step by step from an empty/first-run state and confirming every step's prerequisites already exist at that point — and any bootstrap / ordering / mutually-exclusive-mechanism contradiction it surfaced has been resolved. This is separate from section-by-section consistency: a spec can pass every consistency pass and still hide a step that depends on something only produced later (a circular/bootstrap dependency) or two individually-sound choices that collide once the flow runs in order. Section-consistency critique does not catch these; only tracing the actual flow does. If the layered fold-ins across rounds could have introduced such a contradiction (they easily can), run one more round whose sole job is this trace before declaring the spec ready. The same trace is required at the Phase 2b plan review — walk the built flow cold once more, since planning can reintroduce an ordering dependency the spec didn't have. +**Mandatory exit gate — the cold-start flow trace.** Do not leave spec critique until at least one round has explicitly done the end-to-end, first-run dependency trace described in `prompts/spec-critique.md` — walking each primary flow step by step from an empty state and confirming every step's prerequisites already exist at that point — and every bootstrap, ordering, or mutually-exclusive-mechanism contradiction it surfaced is resolved. This is separate from section-by-section consistency. A spec can pass every consistency pass and still hide a step that depends on something only produced later, or two individually-sound choices that collide once the flow runs in order. Only tracing the actual flow catches these. Layered fold-ins across rounds can easily introduce such a contradiction; if they could have, run one more round whose sole job is this trace before declaring the spec ready. The same trace repeats at the Phase 2b plan review — planning can reintroduce an ordering dependency the spec didn't have. -Only once the loop has fully exited, reach the primary context-clearing point. The spec interview and critique are the heaviest interactive context in the run, and the approved spec now captures every decision in a committed file — so the window can reset before planning, which is largely subagent-driven. Verify all run state is in files (state.json current, spec committed, external references recorded in the spec — not left only in conversation), then suggest the user `/clear` and re-invoke to resume at planning. If they'd rather continue, proceed to Phase 2. +Only once the loop has fully exited, reach the primary context-clearing point. The spec interview and critique are the heaviest interactive context in the run, and the approved spec now captures every decision in a committed file — the window can reset before planning, which is largely subagent-driven. Verify all run state is in files: state.json current, spec committed, external references recorded in the spec, not left in conversation. Then suggest the user `/clear` and re-invoke to resume at planning. If they'd rather continue, proceed to Phase 2. ## Phase 2 — Planning -Before diving in, briefly orient the user on why planning is a separate step: the spec says _what_ to build, the plan says _how_. Planning is where we research the codebase, discover what already exists, make architecture decisions, and work out the order of operations. Without it, the spec's open questions carry into implementation and cause mid-build surprises. +Orient the user briefly on why planning is separate: the spec says *what* to build, the plan says *how*. Planning researches the codebase, discovers what exists, makes architecture decisions, and sets the order of operations. Without it, the spec's open questions carry into implementation and surface mid-build. -Planning research happens in a subagent to keep the codebase-reading noise out of the main context. Read `prompts/plan-research.md`. +Planning research happens in a subagent, to keep codebase-reading noise out of the main context. Read `prompts/plan-research.md`. -Spawn a planning subagent (Agent tool) with the plan-research prompt, the spec path, the target plan path (`.speccy//plan.md`), and the path to `prompts/plan-spike.md` so the planner can prove any load-bearing mechanism (preferably by spawning a spike subagent, or inline). If the spec recorded external context (docs, standards, related projects), pass those references too — read them from the spec rather than relying on conversation memory, since planning may run in a freshly cleared context. +Spawn a planning subagent (Agent tool) with the plan-research prompt, the spec path, the target plan path (`.speccy//plan.md`), and the path to `prompts/plan-spike.md` so the planner can prove any load-bearing mechanism — preferably by spawning a spike subagent, or inline. If the spec recorded external context (docs, standards, related projects), pass those references too. Read them from the spec, not conversation memory — planning may run in a freshly cleared context. -Pass the capability manifest (`.speccy//capabilities.md`) as well, with the phase preamble (`prompts/project-capabilities.md`): instruct the planner to delegate codebase discovery to the project's research / hunter agents before any generic sweep, to consult the skills whose triggers match the area it's planning, and to cite what each returns — so the plan is grounded in how the repo actually works, not a generic reading of it. +Pass the capability manifest (`.speccy//capabilities.md`) as well, with the phase preamble from `prompts/project-capabilities.md`. Instruct the planner to delegate codebase discovery to the project's research agents before any generic sweep, to consult the skills whose triggers match the area it plans, and to cite what each returns — so the plan is grounded in how the repo actually works. -When it completes, brief the user on the approach, key decisions, and risks from `.speccy//plan.md` — point them there for the full text rather than dumping it inline. Update state.json with `planPath` and `phase: "plan-critique"`. +When it completes, brief the user on the approach, key decisions, and risks from `.speccy//plan.md` — point them at the file rather than dumping it inline. Update state.json with `planPath` and `phase: "plan-critique"`. -**If the plan flags a contradicted spec assumption**, stop before the plan-critique loop and put it to the user as a blocking choice: accept the adjusted scope, or revise the spec and re-plan. A falsified assumption can invalidate scope, so this blocking gate always fires. +**If the plan flags a contradicted spec assumption**, stop before the plan-critique loop and put a blocking choice to the user: accept the adjusted scope, or revise the spec and re-plan. A falsified assumption can invalidate scope, so this gate always fires. ### 2a. Adversarial plan critique -The spec has already been hardened. Now the plan gets an independent review. This loop runs autonomously — the user reviews the final hardened plan in 2b. Read `prompts/plan-critique.md` (relative to this SKILL.md's directory). +The spec is already hardened; now the plan gets its independent review. This loop runs autonomously — the user reviews the hardened plan in 2b. Read `prompts/plan-critique.md`, relative to this SKILL.md's directory. For each round (up to 3): -1. **Critique.** Spawn an adversary subagent with the plan critique prompt, the path to the plan, and the path to the spec (for context — the spec itself should not be re-reviewed). Instruct it to **write its review to `.speccy//plan-critique-round-N.md`**. Use **opus** for the model override on every round (or the user's pinned model, if they set one). Read the critique file (N from state.json) to triage. If no legitimate flaws found, exit the loop. -2. **Spike, if the critique flags an unproven load-bearing mechanism.** The critic judges the plan's evidence but does not spike; when it flags a mechanism whose feasibility the plan hasn't proven, prove it before revising. Spawn a spike subagent with `prompts/plan-spike.md` and the mechanism to prove, writing its verdict to `.speccy//spike-round-N.md`. Read the verdict: - - `confirmed` → carry its evidence into the revise step so the plan records it in the Assumptions check. - - `refuted` or `unproven` → a load-bearing mechanism that can't be proven can invalidate scope, so treat it like a contradicted spec assumption: stop the loop and put a blocking choice to the user — accept a redesign around a mechanism that works, or revise the spec and re-plan. Like the contradicted-assumption gate, this one always fires. -3. **Revise.** Spawn a revise subagent **on opus** with `prompts/revise.md`, the plan path, the critique file path, and instructions to incorporate every finding in the critique. When it completes, the revised plan file is the truth — don't depend on its return. +1. **Critique.** Spawn an adversary subagent with the plan critique prompt, the plan path, and the spec path — the spec is context, not re-review material. Instruct it to write its review to `.speccy//plan-critique-round-N.md`. Use **opus** every round, or the user's pinned model. Read the critique file (N from state.json) to triage. No legitimate flaws → exit the loop. +2. **Spike, if the critique flags an unproven load-bearing mechanism.** The critic judges the plan's evidence but does not spike. When it flags a mechanism whose feasibility the plan hasn't proven, prove it before revising: spawn a spike subagent with `prompts/plan-spike.md` and the mechanism, writing its verdict to `.speccy//spike-round-N.md`. Read the verdict: + - `confirmed` → carry the evidence into the revise step so the plan records it in the Assumptions check. + - `refuted` or `unproven` → an unprovable load-bearing mechanism can invalidate scope. Treat it like a contradicted spec assumption: stop the loop and put a blocking choice to the user — accept a redesign around a mechanism that works, or revise the spec and re-plan. Like that gate, this one always fires. +3. **Revise.** Spawn a revise subagent on **opus** with `prompts/revise.md`, the plan path, the critique file path, and instructions to incorporate every finding. When it completes, the revised plan file is the truth — don't depend on its return. -After 3 rounds, exit the loop regardless. Update state.json after each round (`planCritiqueRounds`). When the loop exits, surface a one-line note of how many rounds ran and what changed, then proceed to 2b. +After 3 rounds, exit regardless. Update state.json after each round (`planCritiqueRounds`). On exit, surface a one-line note — how many rounds ran, what changed — then proceed to 2b. ### 2b. User review -This is the highest-stakes human gate, so engage it deliberately (see **Steering away from cognitive surrender**): +The highest-stakes human gate. Engage it deliberately (see **Steering away from cognitive surrender**): -- **Draw out the user first.** Before walking the plan, ask them to predict it: the choice they'd bet the critique loop pushed hardest on, or the decision they'd defend least confidently. If they have none and you can see a genuinely shaky or load-bearing decision, offer to look at that one together — only if a real one exists. When you then walk the plan, close the loop against their prediction and what the 2a critique actually changed ("you flagged the retry design; the critique reworked the idempotency key instead — surprised?"). -- **Then present, candidly.** Have them read the plan file directly rather than re-dumping it into the conversation. Walk through the two or three load-bearing decisions, and for each surface the alternative the plan rejected and its best argument. Flag where the plan is genuinely uncertain, and don't let a confident passage stand in for a verified one. -- **Name what convinced you.** On the single most consequential decision, ask the user to say what persuaded them, and whether they checked it or are trusting the plan's confidence. +- **Draw out the user first.** Before walking the plan, ask them to predict it: the choice they'd bet the critique pushed hardest on, or the decision they'd defend least confidently. If they have none and you see a genuinely shaky, load-bearing decision, offer to look at that one together — only if a real one exists. When you walk the plan, close the loop against their prediction and what the 2a critique actually changed: "you flagged the retry design; the critique reworked the idempotency key instead — surprised?". +- **Then present, candidly.** Have them read the plan file directly rather than re-dumping it. Walk the two or three load-bearing decisions; for each, surface the alternative the plan rejected and its best argument. Flag where the plan is genuinely uncertain. Don't let a confident passage stand in for a verified one. +- **Name what convinced you.** On the single most consequential decision, ask what persuaded them — and whether they checked it or are trusting the plan's confidence. -**Recommend a builder.** With the plan's shape now clear, tell the user whether Sonnet (the default) or Opus suits this build, and why — weigh complexity and novelty, how much is left to build-time judgment versus mechanical execution, and how tightly the plan pins down each task. They set `builderModel`. +**Recommend a builder.** With the plan's shape clear, tell the user whether sonnet (the default) or opus suits this build, and why. Weigh complexity and novelty, how much is left to build-time judgment versus mechanical execution, and how tightly the plan pins down each task. They set `builderModel`. -The adversary has already cleaned up obvious issues; this is the user's chance to raise concerns it missed, adjust the approach on their own knowledge, or approve as-is. Iterate until the user is satisfied. When approved, set `phase: "implementation"` in state.json. +The adversary has cleaned up the obvious issues; this gate is the user's chance to raise concerns it missed, adjust the approach on their own knowledge, or approve as-is. Iterate until satisfied. On approval, set `phase: "implementation"` in state.json. -Before starting implementation, verify all run state is in files: state.json current, spec and plan committed, review decisions reflected in the plan. The main clear already happened after the spec, so this is conditional: if plan critique and review accumulated heavy context, suggest the user `/clear` and re-invoke to resume at implementation; if planning stayed lean, just proceed. +Before implementation, verify all run state is in files: state.json current, spec and plan committed, review decisions reflected in the plan. The main clear already happened after the spec, so this one is conditional — if plan critique and review accumulated heavy context, suggest `/clear` and re-invoke to resume at implementation; if planning stayed lean, proceed. ## Phase 3 — Implementation -The build kickoff is a handoff, not a gate (see **Steering away from cognitive surrender**): 2b was the engagement point, so pose no pre-question and announce no check here. If you frame the handoff at all, keep it to a passing line: the build now runs autonomously and the user stays **on** the loop — free to watch it work and step in — rather than walking away from it, which is the vibe-coding failure mode speccy exists to avoid. ("In the loop" is for the spec and plan gates, where the user decides each acceptance; the build is supervision, not decision-by-decision.) Then start the build. +Invoke the `plan-execution` skill directly via the Skill tool from the main conversation. Pass the plan path as `args.planPath` — not the full plan text; the workflow reads the file itself, which keeps the call small and the plan editable mid-run. Pass the builder model as `args.model`, from state.json's `builderModel`, default sonnet. The breakdown agent inside plan-execution always uses opus; only execute/integrate/verify pick up the override. -Invoke the `plan-execution` skill directly via the Skill tool from the main conversation, passing the plan path as `args.planPath` (not the full plan text — the workflow reads the file itself, which keeps the orchestration call small and the plan editable mid-run) and the builder model as `args.model` (from state.json's `builderModel`, default sonnet). The breakdown agent inside plan-execution always uses Opus regardless; only execute/integrate/verify pick up the override. +Do not wrap this in an Agent subagent — Agent subagents lack `Workflow`, so the call breaks. Plan-execution already backgrounds its own work; only the final result returns. -Do _not_ wrap this in an Agent subagent — Agent subagents lack `Workflow`, so the call breaks. Plan-execution already backgrounds its own work (breakdown, execute, integrate, verify); only the final result returns. +The build kickoff is a handoff, not a gate (see **Steering away from cognitive surrender**): 2b was the engagement point, so pose no pre-question and announce no check here. If you frame the handoff at all, keep it to a passing line: the build now runs autonomously and the user stays **on** the loop — free to watch it work and step in — rather than walking away from it, which is the vibe-coding failure mode speccy exists to avoid. "In the loop" belongs to the spec and plan gates, where the user decides each acceptance; the build is supervision, not decision-by-decision. Then start the build. -**Push for parallelism where the plan allows.** Plan-execution's breakdown defaults to sequential steps; a purely serial run is the single biggest wall-clock cost. When invoking plan-execution, augment the breakdown instruction to **parallelize genuinely independent work** — group tasks that touch disjoint files with no data dependency into parallel steps (each maps to a spec/plan acceptance criterion). Authoring independent units concurrently (e.g. a test class per production class, or separate feature files) is the clearest win. **Caveat, state it to the breakdown:** if the project verifies against a single shared environment (one scratch org, one database), the *deploy/test* step of parallel tasks contends on that resource and effectively serialises — so parallelism cuts authoring time, not the shared-environment round-trip. Only parallelise the authoring, and let integration/verification funnel through the shared resource. +**Push for parallelism where the plan allows.** Plan-execution's breakdown defaults to sequential steps, and a purely serial run is the single biggest wall-clock cost. When invoking plan-execution, augment the breakdown instruction to parallelize genuinely independent work: group tasks that touch disjoint files with no data dependency into parallel steps, each mapping to a spec or plan acceptance criterion. Authoring independent units concurrently — a test class per production class, separate feature files — is the clearest win. State the caveat to the breakdown: if the project verifies against a single shared environment (one scratch org, one database), the deploy/test step of parallel tasks contends on that resource and effectively serialises. Parallelism cuts authoring time, not the shared-environment round-trip. Parallelise the authoring; let integration and verification funnel through the shared resource. -**Route the project's capabilities into each task.** Also instruct breakdown to attach to every task the skills whose triggers match that task's files — an explicit "consult these before writing" list the build agent activates itself (it can invoke a Skill; it cannot dispatch an Agent). Placement and existence questions are different — "where does this belong", "does a primitive for this already exist" — and a build agent inside the workflow can't spawn a research agent to settle them, so resolve those up front with the project's hunter agents and bake the answer into the task description. Pass the capability manifest path (`.speccy//capabilities.md`) so breakdown has the roster; if the manifest is empty, this augmentation is a no-op and breakdown proceeds as usual. +**Route the project's capabilities into each task.** Also instruct breakdown to attach to every task the skills whose triggers match that task's files — an explicit "consult these before writing" list the build agent activates itself. It can invoke a Skill; it cannot dispatch an Agent. Placement and existence questions — "where does this belong", "does a primitive for this already exist" — are different: a build agent inside the workflow can't spawn a research agent to settle them, so resolve those up front with the project's hunter agents and bake the answer into the task description. Pass the capability manifest path (`.speccy//capabilities.md`) so breakdown has the roster. If the manifest is empty, this augmentation is a no-op. -When the workflow reports complete, do not advance on its "gates pass" / "0 violations" summary — a build agent can satisfy a gate by fabricating or inverting a rule and still report green. Re-run the project's load-bearing gates yourself (the build, lint / static-analysis, and test commands from CLAUDE.md) and confirm the actual tool output. **Use the project's documented harness the way CLAUDE.md specifies it** — if CLAUDE.md names an MCP tool for a gate (e.g. a deploy/test MCP), invoke that MCP tool rather than shelling out to the raw CLI; a raw-CLI wrapper is a fallback, not the default. If a gate fails, the run isn't done: carry the real tool output into a fix round (the Phase 4 implementation-fix agent handles exactly this), re-run the gates after it, and repeat until you have seen them pass. Only then set `phase: "review"` in state.json and continue. +When the workflow reports complete, do not advance on its "gates pass" summary — a build agent can satisfy a gate by fabricating or inverting a rule and still report green. Re-run the project's load-bearing gates yourself — build, lint, static analysis, tests, from CLAUDE.md — and confirm the actual tool output. Use the project's documented harness the way CLAUDE.md specifies it: if CLAUDE.md names an MCP tool for a gate, invoke that MCP tool rather than shelling out to the raw CLI; the CLI wrapper is a fallback, not the default. If a gate fails, the run isn't done. Carry the real tool output into a fix round — the Phase 4 implementation-fix agent handles exactly this — re-run the gates after it, and repeat until you have seen them pass. Only then set `phase: "review"` in state.json and continue. -**Economise the round-trips** (the dominant wall-clock cost when the gate hits a remote environment — a scratch org, a CI runner, a container). The trust rule (see it pass yourself) is non-negotiable; what's negotiable is not paying for the full remote round-trip on every intermediate step. +**Economise the round-trips.** They dominate wall-clock when the gate hits a remote environment — a scratch org, a CI runner, a container. The trust rule (see it pass yourself) is non-negotiable; what's negotiable is paying the full remote round-trip on every intermediate step. -**Test re-run scope — the hard rule (do not violate):** -- While fixing, re-run **only the specific test(s) you just touched or that were failing** — never the whole suite. Re-running every test to confirm a one-line fix in one test is waste; it does not happen. -- Run the **full suite of ALL tests exactly once, at the very end**, after every fix is in — that single final run is the completeness gate. Not per-fix, not per-round. -- Concretely: fix test/class X → run X (and its production class's targeted tests) → green → move on. Only when the whole fix list is exhausted do you run the entire suite once to confirm nothing regressed. -- For *intermediate* checks inside a fix loop prefer the cheapest signal that still proves the fix — compile / type-check / `--dry-run` / the single changed test. Batch several fix findings into one fix agent and re-check once, rather than re-gating after each small edit. +**Test re-run scope — the hard rule, do not violate:** -If the implementation workflow exits incomplete, stop the pipeline. Report what's done and what remains — the user has a branch with partial progress. State.json remains at `phase: "implementation"` so the run can be resumed later. +- While fixing, re-run only the specific tests you just touched or that were failing — never the whole suite. Re-running every test to confirm a one-line fix in one test is waste; it does not happen. +- Run the full suite of ALL tests exactly once, at the very end, after every fix is in. That single final run is the completeness gate. Not per-fix, not per-round. +- Concretely: fix test/class X → run X and its production class's targeted tests → green → move on. Only when the fix list is exhausted, run the entire suite once to confirm nothing regressed. +- For intermediate checks inside a fix loop, prefer the cheapest signal that still proves the fix: compile, type-check, `--dry-run`, the single changed test. Batch several findings into one fix agent and re-check once, rather than re-gating after each small edit. + +If the implementation workflow exits incomplete, stop the pipeline. Report what's done and what remains — the user has a branch with partial progress. State.json stays at `phase: "implementation"` so the run can resume later. ## Phase 4 — Implementation review -After implementation is complete, the code gets an independent review across several lenses, run in parallel. Completeness is already verified by the task execution skill, so this phase is about quality, spec fidelity, and fit. +After implementation, the code gets an independent review across several lenses, run in parallel. Completeness is already verified by the task execution skill; this phase is about quality, spec fidelity, and fit. ### The lenses -Each round spawns these reviewers as **parallel** subagents (one message, one Agent call each), all **read-only** — none edits code. Each writes its findings to its own file `.speccy//review-round-N-.md`. Pass each the base branch so it can diff `...HEAD`. All prompt paths are relative to this SKILL.md's directory. +Each round spawns the reviewers as **parallel** subagents — one message, one Agent call each — all **read-only**; none edits code. Each writes its findings to its own file, `.speccy//review-round-N-.md`. Pass each the base branch so it can diff `...HEAD`. All prompt paths are relative to this SKILL.md's directory. -Pass each bespoke lens `prompts/review-output-contract.md` alongside its own prompt. It standardises the finding shape across lenses so triage is mechanical, and makes writing the file a hard contract — a lens that runs out of room mid-verification still leaves a file, marking the unconfirmed candidate `PLAUSIBLE`, rather than returning nothing. `code-review` is a built-in skill that won't read the contract; the orchestrator applies the same shape itself when it normalises `code-review`'s findings into the code-review lens file. +Pass each bespoke lens `prompts/review-output-contract.md` alongside its own prompt. It standardises the finding shape so triage is mechanical, and makes writing the file a hard contract: a lens that runs out of room mid-verification still leaves a file, marking the unconfirmed candidate `PLAUSIBLE`, rather than returning nothing. `code-review` is a built-in skill that won't read the contract; the orchestrator applies the same shape when normalising its findings into the code-review lens file. -- **Code review** — the built-in `code-review` skill, targeting `...HEAD` at `high` effort, with no `--fix` and no `--comment`. It covers correctness and general code quality, so the bespoke lenses handle only what it can't. Run it every round. +- **Code review** — the built-in `code-review` skill, targeting `...HEAD` at `high` effort, no `--fix`, no `--comment`. It covers correctness and general code quality; the bespoke lenses handle only what it can't. Run it every round. - Invoke it **directly in the main conversation** (via the `Skill` tool), not inside an Agent subagent — it spawns its own subagents, and wrapping a multi-agent skill stalls it. Parse its output tolerantly (the shape may change), normalise its verdicts into the shared finding shape, and write `review-round-N-code-review.md` yourself. -- **Project review gate** — the repo's *own* review gate, if it ships one: a `/review`-style skill, project-defined reviewer agents, or a `.claude/review.config.json`. When present, run it as an extra lens. It encodes the house security bar, thresholds, and invariants a generic reviewer can't replicate, so where it exists it is the highest-signal lens in the panel — run it the way the repo documents (its own agents, models, and thresholds; do not override them). Like `code-review`, a project gate is usually itself multi-agent, so invoke it **directly in the main conversation**, not wrapped in an Agent subagent (same reason, and see **Subagent results: trust files, not returns**). It is **spec-blind** — it checks house quality, not whether the build meets _this spec's_ criteria — so it complements the spec-fidelity lens, never replaces it. Normalise its findings into the shared shape and write `review-round-N-project-gate.md` yourself; the triage step dedups its overlap with `code-review`, codebase fit, and local-doc adherence like any other lens. If the repo has no such gate, skip this lens. + Invoke it directly in the main conversation via the Skill tool, not inside an Agent subagent — it spawns its own subagents, and wrapping a multi-agent skill stalls it. Parse its output tolerantly; the shape may change. Normalise its verdicts into the shared finding shape and write `review-round-N-code-review.md` yourself. +- **Project review gate** — the repo's own review gate, if it ships one: a `/review`-style skill, project-defined reviewer agents, or a `.claude/review.config.json`. When present, run it as an extra lens. It encodes the house security bar, thresholds, and invariants a generic reviewer can't replicate — where it exists it is the highest-signal lens in the panel. Run it the way the repo documents it: its own agents, models, and thresholds, not overridden. Like `code-review`, a project gate is usually itself multi-agent, so invoke it directly in the main conversation, not wrapped in an Agent subagent — same reason, and see **Subagent results: trust files, not returns**. It is spec-blind: it checks house quality, not whether the build meets this spec's criteria, so it complements the spec-fidelity lens, never replaces it. Normalise its findings into the shared shape and write `review-round-N-project-gate.md` yourself. The triage step dedups its overlap with `code-review`, codebase fit, and local-doc adherence like any other lens. No gate in the repo → skip this lens. - **Spec fidelity** — `prompts/review-spec-fidelity.md`, with the spec path. Does the code satisfy the spec's completion criteria and intent? - **Tests** — `prompts/review-tests.md`, with the spec and plan paths. Test-strategy adherence, test quality, and consolidation of new tests against the existing suite. - **Codebase fit** — `prompts/review-codebase-fit.md`. Does this change worsen an already-imperfect area or repeat an existing smell? Judged against the touched files' current state, not the diff alone. -- **Local-doc adherence** — `prompts/review-local-docs.md`. Violations of the repo's governing docs, including CLAUDE.md — which it deliberately re-checks even though code-review covers it too. Pass it the capability manifest so it judges against the project's actual skills and governing docs, not a generic reading; where a house skill states a rule, a violation of that rule is a finding. -- **Suppressions** — `prompts/review-suppressions.md`. Extremely harsh on any linter/analysis/type/test-gate suppression the change adds or leans on. Each must be watertight or it is a finding. +- **Local-doc adherence** — `prompts/review-local-docs.md`. Violations of the repo's governing docs, including CLAUDE.md — deliberately re-checked even though code-review covers it too. Pass it the capability manifest so it judges against the project's actual skills and governing docs; where a house skill states a rule, a violation is a finding. +- **Suppressions** — `prompts/review-suppressions.md`. Extremely harsh on any linter, analysis, type, or test-gate suppression the change adds or leans on. Each must be watertight or it is a finding. - **Comments** — `prompts/review-comments.md`. Comments the change adds or edits that restate the code, narrate edit history, or pad a real point. Proposes deletions only; the fixer mends any seam. -Run the bespoke lenses on **opus**, except suppressions and comments on **sonnet** (a mechanical scan, and a focused style pass). A pinned adversary model overrides all of them; `code-review` and any project review gate manage their own. +Run the bespoke lenses on **opus**, except suppressions and comments on **sonnet** — a mechanical scan and a focused style pass. A pinned adversary model overrides all of them; `code-review` and any project gate manage their own. ### The loop (up to 3 rounds) -1. **Review.** Spawn the bespoke lenses as parallel subagents in one message, and invoke the inline gates in the main conversation (see above) — `code-review` every round, and the project review gate if the repo ships one — their own fan-out overlaps with the spawned lenses. Round 1 is a cold review. **Rounds 2+ are fix-verification:** re-point each lens at "verify the round-(N-1) fixes hold, and catch any regression they introduced" rather than a fresh cold pass, and always pass it the `.speccy//deferred.md` list as accepted decisions it must not re-raise. Run all lenses every round by default; you may drop a lens only when the fix round provably didn't touch its surface (e.g. skip local-doc adherence when nothing under a governing doc changed). Note any lens you drop and why. +1. **Review.** Spawn the bespoke lenses as parallel subagents in one message, and invoke the inline gates in the main conversation — `code-review` every round, and the project gate if the repo ships one; their own fan-out overlaps with the spawned lenses. Round 1 is a cold review. Rounds 2+ are fix-verification: re-point each lens at "verify the round-(N-1) fixes hold, and catch any regression they introduced", and always pass the `.speccy//deferred.md` list as accepted decisions it must not re-raise. Run all lenses every round by default. Drop a lens only when the fix round provably didn't touch its surface — e.g. skip local-doc adherence when nothing under a governing doc changed — and note any lens you drop and why. - For the spawned lenses, don't branch on a returned summary (see **Subagent results: trust files, not returns**) — confirm the file exists. **Self-heal a stalled lens:** if a spawned lens's file is missing after it reports complete, `SendMessage` that agent to write its findings file as its final action, marking anything unconfirmed `PLAUSIBLE`, rather than re-spawning it from scratch. Once every lens file is present — the spawned lens files plus the inline-gate files you wrote (code-review, and the project gate if you ran one) — read them (N from state.json) and move to triage. -2. **Triage & merge.** Consolidate the findings across lenses yourself — drop false positives, de-duplicate overlaps, and resolve contradictory suggestions. Don't spawn a separate agent for this. Every lens emits the shared finding shape, so merge on `file:line`: two lenses landing on the same anchor is a **convergence signal**, and independent lenses pointing at one spot raise confidence rather than being noise — weight those up instead of collapsing them to a lone finding. As a backstop for anything the lenses re-raised despite being told not to, drop findings already in `.speccy//deferred.md`; a deferred finding must not churn back into the fix set. Then give each surviving finding a disposition: - - **Fix** — route it to the fixer this round. Where the finding is a copied smell, tell the fixer whether to diverge (fix cleanly here) or fix wider (also fix the existing instance); a wider fix grows the diff, so choose it deliberately. + For the spawned lenses, don't branch on a returned summary (see **Subagent results: trust files, not returns**) — confirm the file exists. Self-heal a stalled lens: if its file is missing after it reports complete, `SendMessage` that agent to write its findings file as its final action, marking anything unconfirmed `PLAUSIBLE`, rather than re-spawning from scratch. Once every lens file is present — the spawned files plus the inline-gate files you wrote — read them (N from state.json) and move to triage. +2. **Triage & merge.** Consolidate the findings yourself — drop false positives, de-duplicate overlaps, resolve contradictory suggestions. Don't spawn a separate agent for this. Every lens emits the shared shape, so merge on `file:line`. Two lenses landing on the same anchor is a convergence signal: independent lenses pointing at one spot raise confidence — weight those up instead of collapsing them to a lone finding. As a backstop for anything re-raised despite instructions, drop findings already in `.speccy//deferred.md`; a deferred finding must not churn back into the fix set. Give each surviving finding a disposition: + - **Fix** — route it to the fixer this round. Where the finding is a copied smell, tell the fixer whether to diverge (fix cleanly here) or fix wider (also fix the existing instance). A wider fix grows the diff, so choose it deliberately. - **Defer** — legitimate but out of scope for this PR. Append it to `.speccy//deferred.md`: what, and why deferred. + A suppression finding is effectively never Defer — remove it or make it watertight, this round. **Exit the loop when nothing is dispositioned Fix.** - You make these disposition calls yourself as the loop runs — the review is autonomous. But surface them to the human at wrap-up so they still review the judgment: deferrals in the deferred list, and any divergence-from-pattern or wider-than-the-diff fix in the summary and decision log. -3. **Fix.** If nothing is dispositioned Fix, skip to the next round's review (or exit). Otherwise read `prompts/implementation-fix.md` and spawn a fix subagent with that prompt, the Fix findings (point it at the lens files, and state any diverge / fix-wider instruction), the spec path, and the plan path. It makes the changes and commits. After it commits, re-run the load-bearing gates yourself and confirm the actual output before the next round — never advance on the fix agent's claim that the gates pass. (Gates passing doesn't prove coverage held — a dropped test still passes.) + You make these disposition calls yourself as the loop runs — the review is autonomous. Surface them at wrap-up so the human still reviews the judgment: deferrals in the deferred list, and any divergence-from-pattern or wider-than-the-diff fix in the summary and decision log. +3. **Fix.** If nothing is dispositioned Fix, skip to the next round's review, or exit. Otherwise read `prompts/implementation-fix.md` and spawn a fix subagent with that prompt, the Fix findings — point it at the lens files, and state any diverge or fix-wider instruction — the spec path, and the plan path. It makes the changes and commits. After it commits, re-run the load-bearing gates yourself and confirm the actual output before the next round. Never advance on the fix agent's claim that gates pass — gates passing doesn't prove coverage held; a dropped test still passes. After 3 rounds, proceed regardless. Update state.json after each round (`reviewRounds`) and set `phase: "complete"` when done. Any `deferred.md` items surface at wrap-up. ## Wrap-up -A completed run is a handoff. Speccy has built and self-reviewed the work; the verdict is the user's, reached through the diff, the artefacts below, CI, E2E, or running it themselves. Speccy stops at a reviewable PR — it does not merge, certify, or run end-to-end verification. Report what was built and leave the review to the user. When pointing them at the diff, suggest they read it as if a contributor they do not fully trust wrote it: the same standard they would apply to any other author's code (see **Steering away from cognitive surrender**). +A completed run is a handoff. Speccy has built and self-reviewed the work; the verdict is the user's, reached through the diff, the artefacts below, CI, E2E, or running it themselves. Speccy stops at a reviewable PR — it does not merge, certify, or run end-to-end verification. Report what was built and leave the review to the user. When pointing them at the diff, suggest they read it as if a contributor they do not fully trust wrote it — the standard they'd apply to any other author (see **Steering away from cognitive surrender**). -When all phases complete, report concisely — both in the chat and written to `.speccy//summary.md`, so the handoff survives a context clear and sits alongside the run's other artefacts. Cover: +When all phases complete, report concisely — in the chat and to `.speccy//summary.md`, so the handoff survives a context clear and sits with the run's other artefacts. Cover: -1. **Summary** — what was built, how many critique/review rounds ran, what changed, and that the branch is ready for review. -2. **Decision log, co-authored** — distil key decisions from the critique and review rounds into `specs/-decision-log.md` (including any review-phase divergence from an existing pattern). These are usually implementation-specific choices, not the durable architecture decisions an ADR captures for the wider team. Each entry: what was proposed, what was decided, why. Before writing it, ask the user to restate the rationale for one or two of those decisions in their own words, and build the entry from their account where they have one (see **Steering away from cognitive surrender**). A decision the user cannot reconstruct is the surrender signal worth catching here, while the code is fresh and they are about to own it. Commit the decision log. -3. **Deferred feedback** — substantial feedback set aside for later: findings the user skipped at spec critique, plus any review findings deferred to future work in `.speccy//deferred.md` (with the why). These are candidates for follow-up issues outside this PR. -4. **Retrospective** — if the task execution skill produced one, save it to `.speccy//retrospective.md` and surface the cross-cutting patterns. If it has a `## Repo-doc suggestions (CLAUDE.md / ADR)` section, present those for the user to accept or decline, never auto-applied. +1. **Summary** — what was built, how many critique and review rounds ran, what changed, and that the branch is ready for review. +2. **Decision log, co-authored** — distil the key decisions from the critique and review rounds into `specs/-decision-log.md`, including any review-phase divergence from an existing pattern. These are usually implementation-specific choices, not the durable architecture decisions an ADR captures for the wider team. Each entry: what was proposed, what was decided, why. Before writing it, ask the user to restate the rationale for one or two decisions in their own words, and build those entries from their account (see **Steering away from cognitive surrender**). A decision the user cannot reconstruct is the surrender signal worth catching here, while the code is fresh and they are about to own it. Commit the decision log. +3. **Deferred feedback** — substantial feedback set aside: findings the user skipped at spec critique, plus review findings deferred in `.speccy//deferred.md`, with the why. Candidates for follow-up issues outside this PR. +4. **Retrospective** — if the task execution skill produced one, save it to `.speccy//retrospective.md` and surface the cross-cutting patterns. If it has a `## Repo-doc suggestions (CLAUDE.md / ADR)` section, present those for the user to accept or decline — never auto-applied. -If the pipeline exited early (implementation failure), report what's done and what remains. The user has a branch with partial progress. +If the pipeline exited early on an implementation failure, report what's done and what remains. The user has a branch with partial progress. diff --git a/.claude/skills/speccy/prompts/implementation-fix.md b/.claude/skills/speccy/prompts/implementation-fix.md index f0dbd51..0036879 100644 --- a/.claude/skills/speccy/prompts/implementation-fix.md +++ b/.claude/skills/speccy/prompts/implementation-fix.md @@ -4,7 +4,7 @@ You will be given the review findings, the spec, and the plan. Fix only the issu Constraints: -- **Respect the plan's architecture decisions.** The plan was reviewed and approved. If a fix would require changing an architecture decision, skip it and explain why — that's a design change, not a code fix. -- **One commit per round.** Make all fixes for this round's findings in a single commit with a message describing what was fixed. +- **Respect the plan's architecture decisions.** The plan was reviewed and approved. If a fix would change an architecture decision, skip it and explain why — that's a design change, not a code fix. +- **One commit per round.** Make all of this round's fixes in a single commit, with a message describing what was fixed. - **Skip, don't hack.** If a finding can't be fixed without violating a constraint or introducing worse problems, skip it with an explanation rather than forcing a bad fix. -- **Hard gate beats soft preference.** When clearing an enforced completion gate (a failing lint / static-analysis check or a required test) forces violating a softer CLAUDE.md *style* preference, clear the gate and note the trade in your commit message. This applies to style/aesthetic preferences only — an enforced gate must never override a CLAUDE.md *safety or correctness* rule (e.g. "never log PII"); skip and explain instead. +- **Hard gate beats soft preference.** When clearing an enforced completion gate — a failing lint or static-analysis check, a required test — forces violating a softer CLAUDE.md *style* preference, clear the gate and note the trade in your commit message. This covers style and aesthetic preferences only. An enforced gate must never override a CLAUDE.md *safety or correctness* rule, such as "never log PII" — there, skip and explain instead. diff --git a/.claude/skills/speccy/prompts/plan-critique.md b/.claude/skills/speccy/prompts/plan-critique.md index fa8fba0..58809a8 100644 --- a/.claude/skills/speccy/prompts/plan-critique.md +++ b/.claude/skills/speccy/prompts/plan-critique.md @@ -1,14 +1,14 @@ -You are an adversarial reviewer. You are given an implementation plan and the spec it implements. The spec has already been independently reviewed and hardened — do not re-review it. Focus on the plan. +You are an adversarial reviewer. You are given an implementation plan and the spec it implements. The spec is already reviewed and hardened — do not re-review it. Focus on the plan. -Find: wrong decomposition, unstated assumptions, things that will break at integration time, unnecessary complexity, simpler alternatives, gaps in the test strategy, risks that aren't accounted for, unnecessary implementation detail that should be left to the build phase, and missing context — documentation, external references, or related projects that should have been consulted. Use judgement — the plan should describe the approach and key decisions, not dictate code. +Find: wrong decomposition, unstated assumptions, things that will break at integration time, unnecessary complexity, simpler alternatives, gaps in the test strategy, unaccounted risks, unnecessary implementation detail that should be left to the build, and missing context — documentation, external references, or related projects that should have been consulted. Use judgement: the plan should describe the approach and key decisions, not dictate code. -Hold every decision in the plan's decision body to its rationale. The plan is a sequence of choices, and each load-bearing one must state *why this approach and not the viable alternative*. Flag any decision that names no alternative when one plainly exists, gives a reason that doesn't actually defeat the alternative, or is presented as the only option when it was really a pick — an unjustified decision is where the plan commits to the wrong design unchallenged. When you propose a simpler alternative, you are testing exactly this: if the plan's rationale can't say why it isn't simpler that way, that's the finding. +Hold every decision in the plan's decision body to its rationale. The plan is a sequence of choices, and each load-bearing one must say *why this approach and not the viable alternative*. Flag any decision that names no alternative when one plainly exists, gives a reason that doesn't actually defeat the alternative, or is presented as the only option when it was really a pick. An unjustified decision is where the plan commits to the wrong design unchallenged. When you propose a simpler alternative, you are testing exactly this: if the plan's rationale can't say why it isn't simpler that way, that is the finding. -Check the plan's named design decisions against the project's static-analysis configuration (linters, ruleset-based analyzers, formatters). Learn which rules are actually enforced — read the analyzer config if present, or run the analyzer against a representative existing source file to see what fires. Pay attention to *unusual or opinionated* rules (e.g. ones that forbid static helpers, formal/doc comments, or mandate naming, return-value, or assertion conventions); the defaults rarely conflict with a sound design, so the unusual rules are the signal. If a design decision in the plan would violate an enforced rule, flag it — when "zero static-analysis violations" is a completion criterion, such a conflict is a build-time blocker, and reconciling design and ruleset now is far cheaper than discovering it mid-build. This step matters most for the first critique round; later rounds only re-check if the design changed. +Check the plan's design decisions against the project's static-analysis configuration — linters, ruleset-based analyzers, formatters. Learn which rules are actually enforced: read the analyzer config, or run the analyzer against a representative existing source file and see what fires. The signal is the *unusual or opinionated* rules — ones that forbid static helpers or formal comments, or mandate naming, return-value, or assertion conventions; defaults rarely conflict with a sound design. If a design decision would violate an enforced rule, flag it. When "zero static-analysis violations" is a completion criterion, such a conflict is a build-time blocker, and reconciling design and ruleset now is far cheaper than mid-build. This matters most in round 1; later rounds re-check only if the design changed. -Check that any load-bearing mechanism the plan depends on has been **proven feasible, not merely asserted**. If the plan relies on specific platform/runtime behaviour, timing, ordering, or an API capability (e.g. a synchronous same-transaction update, a hook firing at a particular point, a write being permitted from a given execution context, an API returning a given result), confirm the plan's evidence actually exercised that risky action against the real environment — not adjacent facts that surround it. A probe that verifies a precondition ("the data is present") does not prove the action ("the write from that context succeeds"). Treat an unproven load-bearing mechanism as a high-severity risk: it is exactly the kind of assumption that survives review and then collapses at build time. If feasibility cannot be confirmed from the plan, the finding is that this mechanism needs a feasibility spike before the plan can be trusted; flag it and the orchestrator will run one (see `plan-spike.md`). Your job is to judge the plan's evidence, not to run the spike yourself. +Check that every load-bearing mechanism is **proven feasible, not merely asserted**. When the plan relies on specific platform or runtime behaviour, timing, ordering, or an API capability — a synchronous same-transaction update, a hook firing at a particular point, a write permitted from a given execution context, an API returning a given result — confirm the plan's evidence exercised that risky action against the real environment, not adjacent facts around it. A probe that verifies a precondition ("the data is present") does not prove the action ("the write from that context succeeds"). Treat an unproven load-bearing mechanism as a high-severity risk: it is exactly the assumption that survives review and collapses at build time. If feasibility can't be confirmed from the plan, the finding is that the mechanism needs a feasibility spike; flag it and the orchestrator will run one (see `plan-spike.md`). You judge the plan's evidence — you do not run the spike. -**Trace the end-to-end flow from a cold start — mandatory.** Beyond judging decisions in isolation, walk each primary flow the plan builds **step by step from an empty/first-run state** and check that every step's prerequisites already exist at that point in time. Flag any *temporal / bootstrap* dependency — a step that consumes a resource, credential, component, token, or state only produced by a later step or by the very step being set up — and any two individually-sound choices that become mutually exclusive once the flow runs in order (e.g. a transport whose prerequisite another decision rejected). These ordering/dependency contradictions survive decision-by-decision review because no single choice is wrong. Name the exact step and the prerequisite missing at that moment. +**Trace the end-to-end flow from a cold start — mandatory.** Beyond judging decisions in isolation, walk each primary flow the plan builds **step by step from an empty, first-run state**, checking that every step's prerequisites already exist at that point. Flag any temporal or bootstrap dependency — a step consuming a resource, credential, component, token, or state only produced by a later step or by the very step being set up — and any two individually-sound choices that become mutually exclusive once the flow runs in order, such as a transport whose prerequisite another decision rejected. These contradictions survive decision-by-decision review because no single choice is wrong. Name the exact step and the prerequisite missing at that moment. Also flag content that restates `CLAUDE.md` (root or nested) or the docs it links. Read those first so you can recognise the duplication. diff --git a/.claude/skills/speccy/prompts/plan-research.md b/.claude/skills/speccy/prompts/plan-research.md index db05ef3..8136d95 100644 --- a/.claude/skills/speccy/prompts/plan-research.md +++ b/.claude/skills/speccy/prompts/plan-research.md @@ -1,34 +1,34 @@ -You are producing an implementation plan for a hardened specification. The spec has already been written and adversarially reviewed — your job is to research the codebase and decide _how_ to build what it describes. +You are producing an implementation plan for a hardened specification. The spec is already written and adversarially reviewed — your job is to research the codebase and decide *how* to build what it describes. -You will be given the path to the spec and the path where the plan must be written. +You will be given the spec path and the path where the plan must be written. Research: - Read the spec carefully, including its open questions and assumptions. - Read `CLAUDE.md` (root and any nested) and the docs it links — do not restate them in the plan. - Investigate the codebase to resolve the spec's open questions: existing utilities, patterns, integration points, platform constraints. Use Grep, Read, and any project-specific lookup tools. -- Test each **Assumption** in the spec against what you find and mark it `confirmed`, `contradicted`, or `still-open`. These are the quiet premises (e.g. "this table is append-only") that become silent build-time surprises if false. A contradicted one can invalidate scope, so treat it as a finding. -- Run the project's static-analysis tool on a small representative stub and read only the violations it actually fires — don't survey the ruleset. Two uses for that output: let any *design-shaping* rule (one that forbids a shape you'd build the design around, e.g. no static helpers, a mandated framework) inform the architecture before you commit; and record any violation that conflicts with a CLAUDE.md *style* preference under Risks as a decision for plan review. Cosmetic conflicts are cheap to fix during the build — don't try to predict them all. -- **Prove load-bearing mechanisms before committing the plan to them.** When the plan will lean on a non-trivial mechanism whose feasibility is not already demonstrated in the codebase — anything asserting specific platform/runtime behaviour, timing, ordering, or an API capability (e.g. "synchronously, in the same transaction", "the hook fires on X", "this API returns Y", "this write is allowed from that context") — prove it with a feasibility spike before you design around it. This applies equally to a constraint the design works *around* ("this value can't be looked up here", "that API can't do Z, so we resolve it in a second pass"): a false "can't" is worse than a false "can", because it never fails loudly at build time — it just ships as a justified-looking workaround. So when the design adds a layer to accommodate a limitation, spike the limitation itself; if it's false, the direct approach usually deletes the layer. Prefer to delegate the spike to a subagent following `plan-spike.md` (alongside this prompt); run it inline against that prompt if you can't spawn one. If the spike refutes the mechanism, design around it with one that works — or, when the spec mandates the infeasible mechanism, **stop and flag it for spec revision** rather than planning around an unproven claim. Record the verdict and its evidence in the Assumptions check. -- If the spec referenced external context (docs, standards, related projects), fetch and read it. +- Test each spec **Assumption** against what you find and mark it `confirmed`, `contradicted`, or `still-open`. These are the quiet premises — "this table is append-only" — that become silent build-time surprises if false. A contradicted one can invalidate scope; treat it as a finding. +- Run the project's static-analysis tool on a small representative stub and read only the violations it actually fires — don't survey the ruleset. Two uses for that output. First, let any *design-shaping* rule — one that forbids a shape you'd build the design around, like no static helpers or a mandated framework — inform the architecture before you commit. Second, record any violation that conflicts with a CLAUDE.md *style* preference under Risks, as a decision for plan review. Cosmetic conflicts are cheap to fix during the build; don't try to predict them all. +- **Prove load-bearing mechanisms before committing the plan to them.** When the plan leans on a non-trivial mechanism whose feasibility the codebase doesn't already demonstrate — specific platform or runtime behaviour, timing, ordering, an API capability ("synchronously, in the same transaction", "the hook fires on X", "this API returns Y", "this write is allowed from that context") — prove it with a feasibility spike before designing around it. The same applies to a constraint the design works *around* ("this value can't be looked up here", "that API can't do Z, so we resolve it in a second pass"). A false "can't" is worse than a false "can": it never fails loudly at build time — it ships as a justified-looking workaround. So when the design adds a layer to accommodate a limitation, spike the limitation itself; if it's false, the direct approach usually deletes the layer. Prefer delegating the spike to a subagent following `plan-spike.md`, alongside this prompt; run it inline against that prompt if you can't spawn one. If the spike refutes the mechanism, design around it with one that works. If the spec mandates the infeasible mechanism, **stop and flag it for spec revision** rather than planning around an unproven claim. Record the verdict and its evidence in the Assumptions check. +- If the spec referenced external context — docs, standards, related projects — fetch and read it. Produce a plan with two parts: 1. The implementation plan, for human and agent review. Every decision lives here. 2. The appendix of file detail, for the build agents. No decisions here. -- **Implementation approach** — describe the change as shifts in responsibility and shape: what role each part plays, which seams it crosses, what abstraction is missing or misused. Name the classes and types you touch, so the plan stays anchored to real code. But describe the *change* itself in these terms, not as a list of edits. -- **Architecture decisions** — with reasoning for each. For each structure the change extends, name the role it plays, then whether the change fits or strains it. An edit can be locally reasonable and still strain its host. That strain is a decision, not a detail: the Nth method on a per-resource family that should expose one composable vocabulary, or a feature-specific field on a type many callers share. For plan review, surface the choice and its cost: extend as-is, reshape the host, or route around it. Don't silently pick the largest. -- **Test strategy** — what to test, how (unit, integration, manual verification), and what coverage looks like. Each completion criterion in the spec should map to a test or verification step -- **Risks and dependencies** — anything discovered during research -- **Assumptions check** — each spec assumption with its verdict (`confirmed` / `contradicted` / `still-open`) and the evidence behind it -- **Order of operations** — what to build first and why -- **Build reference** (appendix) — the concrete touchpoints the build agents need: the files and classes the change lives in, integration points, and the test surface, each with a one-line note of its role. A map to build from, not a script to copy: no method bodies, no prescriptive diffs, since the build agents read the codebase themselves. **No decisions live here.** Anything the reviewer must weigh belongs in the body above. If an appendix entry turns out to be a judgment call, promote it. Needing to is the tell: a real smell won't stay down in the mechanics. +- **Implementation approach** — describe the change as shifts in responsibility and shape: what role each part plays, which seams it crosses, what abstraction is missing or misused. Name the classes and types you touch, so the plan stays anchored to real code. But describe the *change* in these terms, not as a list of edits. +- **Architecture decisions** — with reasoning for each. For each structure the change extends, name the role it plays, then whether the change fits or strains it. An edit can be locally reasonable and still strain its host. That strain is a decision, not a detail: the Nth method on a per-resource family that should expose one composable vocabulary, or a feature-specific field on a type many callers share. Surface the choice and its cost for plan review — extend as-is, reshape the host, or route around it. Don't silently pick the largest. +- **Test strategy** — what to test, how (unit, integration, manual verification), and what coverage looks like. Each completion criterion in the spec should map to a test or verification step. +- **Risks and dependencies** — anything discovered during research. +- **Assumptions check** — each spec assumption with its verdict (`confirmed` / `contradicted` / `still-open`) and the evidence behind it. +- **Order of operations** — what to build first and why. +- **Build reference** (appendix) — the concrete touchpoints the build agents need: the files and classes the change lives in, integration points, and the test surface, each with a one-line note of its role. A map to build from, not a script to copy: no method bodies, no prescriptive diffs — the build agents read the codebase themselves. **No decisions live here.** Anything the reviewer must weigh belongs in the body above. If an appendix entry turns out to be a judgment call, promote it. Needing to is the tell: a real smell won't stay down in the mechanics. -Use bullet lists and unnumbered headings by default. Only number a list when order is the point — steps that must execute in sequence, or items referenced by position. +Use bullet lists and unnumbered headings by default. Number a list only when order is the point — steps that must run in sequence, or items referenced by position. -The plan describes _how to build_, not _the build itself_. Do not write implementation code — no class bodies, method implementations, query strings, templates, or config blocks. Method signatures are acceptable when the spec defines a contract that downstream work depends on. The build agents will read the codebase themselves; giving them code to copy produces worse results than giving them clear intent. +The plan describes *how to build*, not *the build itself*. Write no implementation code: no class bodies, method implementations, query strings, templates, or config blocks. Method signatures are acceptable when the spec defines a contract downstream work depends on. The build agents read the codebase themselves; code to copy produces worse results than clear intent. Do not restate `CLAUDE.md`. Reference it by file/section when a decision hinges on it. -Write the plan to the given path. Return a short summary (5–10 lines): the chosen approach, the most important architecture decisions, and any risks the user should know about before reviewing the full plan. **If any spec assumption was contradicted, flag it explicitly in the summary** so the user can re-confirm scope before planning continues. The orchestrator will use your summary to brief the user — keep the full reasoning in the file. +Write the plan to the given path. Return a short summary, 5–10 lines: the chosen approach, the most important architecture decisions, and any risks the user should know before reviewing the full plan. **If any spec assumption was contradicted, flag it explicitly in the summary** so the user can re-confirm scope before planning continues. The orchestrator briefs the user from your summary — keep the full reasoning in the file. diff --git a/.claude/skills/speccy/prompts/plan-spike.md b/.claude/skills/speccy/prompts/plan-spike.md index 04dda74..4f00547 100644 --- a/.claude/skills/speccy/prompts/plan-spike.md +++ b/.claude/skills/speccy/prompts/plan-spike.md @@ -1,9 +1,9 @@ You are running a feasibility spike: prove or refute one load-bearing mechanism against the real environment, then report the verdict to the path you are given. -A spike earns its keep only by performing the risky action itself. The failure it guards against is subtle: a precondition that holds reads like proof but proves nothing about the action that depends on it. That the data is present says nothing about whether the write from that context is allowed; that a handler is registered says nothing about whether it fires when you need it. Exercise the actual write, call, timing, or ordering against the environment the codebase really uses. Adjacent facts are not evidence. +A spike earns its keep only by performing the risky action itself. The failure it guards against is subtle: a precondition that holds reads like proof but proves nothing about the action that depends on it. That the data is present says nothing about whether the write from that context is allowed. That a handler is registered says nothing about whether it fires when you need it. Exercise the actual write, call, timing, or ordering against the environment the codebase really uses. Adjacent facts are not evidence. If you cannot exercise the action — no access, no safe path — the verdict is `unproven`. An untested assumption dressed as a pass is the exact failure a spike exists to prevent. -Spike code is throwaway. Discard it and undo any state it created, so the environment is left as you found it. +Spike code is throwaway. Discard it and undo any state it created, leaving the environment as you found it. -Report the verdict (`confirmed`, `refuted`, or `unproven`), what you actually did, and the concrete signal behind it — the error, the returned value, the observed timing — so the reader can weigh the evidence rather than take the verdict on trust. If it fails, say what that means for the plan. +Report the verdict — `confirmed`, `refuted`, or `unproven` — what you actually did, and the concrete signal behind it: the error, the returned value, the observed timing. The reader weighs the evidence rather than taking the verdict on trust. If it fails, say what that means for the plan. diff --git a/.claude/skills/speccy/prompts/project-capabilities.md b/.claude/skills/speccy/prompts/project-capabilities.md index 5026270..c20b354 100644 --- a/.claude/skills/speccy/prompts/project-capabilities.md +++ b/.claude/skills/speccy/prompts/project-capabilities.md @@ -1,18 +1,18 @@ # Project capabilities — manifest & injection block -Speccy discovers a project's own capabilities once (see the SKILL's **Lead with the project's own capabilities**) and prefers them over generic defaults at every phase. This file holds the two reusable pieces: the manifest shape, and the preamble to prepend to a spawned subagent's prompt. +Speccy discovers a project's own capabilities once — see the SKILL's **Lead with the project's own capabilities** — and prefers them over generic defaults at every phase. This file holds the two reusable pieces: the manifest shape, and the preamble to prepend to a spawned subagent's prompt. -Everything here is optional. Probe only what the project actually exposes; omit whatever came up empty. If all of it is empty, the manifest says so and the pipeline runs generically — never invent a capability to fill a slot. +Everything here is optional. Probe only what the project actually exposes; omit whatever came up empty. If all of it is empty, the manifest says so and the pipeline runs generically. Never invent a capability to fill a slot. ## Manifest shape (`.speccy//capabilities.md`) A short, human-readable inventory. One line per entry. - **Skills** — `id` + its trigger ("use when …"), copied from the skill's own description. This is the routing key: a skill self-describes when it applies. -- **Research agents** — read-only "hunter" agents: `name · what it answers · how to dispatch`. These gather in-repo context — where things live, how an existing flow works, whether something already exists. +- **Research agents** — read-only "hunter" agents: `name · what it answers · how to dispatch`. These gather in-repo context: where things live, how an existing flow works, whether something already exists. - **Reviewer agents / review gate** — the project's own review agents or `/review`-style gate, if any. Used as a Phase 4 lens, not re-derived. - **Governing docs** — CLAUDE.md / AGENTS.md and the key docs they point to. -- **Routing hints** — any explicit skill→area map found (a review-config's zones, a CLAUDE.md skills table, zone globs in a skill's frontmatter). A convenience accelerator over trigger-text matching, never a requirement. +- **Routing hints** — any explicit skill→area map found: a review-config's zones, a CLAUDE.md skills table, zone globs in a skill's frontmatter. An accelerator over trigger-text matching, never a requirement. ## Injection preamble (prepend to a subagent prompt, scoped to the phase) @@ -26,5 +26,5 @@ A short, human-readable inventory. One line per entry. Include only the slice that fits the phase, and drop any line the manifest has nothing for: - **Spec / plan research** — research agents + governing docs. The planner delegates discovery to a hunter before a generic sweep. -- **Build task** — the skills whose triggers match the task's files, plus any placement/existence answer already resolved by a hunter and baked in (a build agent inside the workflow can't dispatch one itself). -- **Review lens** — the skill catalog, so local-doc / codebase-fit judge against house rules rather than generic taste. +- **Build task** — the skills whose triggers match the task's files, plus any placement or existence answer already resolved by a hunter and baked in. A build agent inside the workflow can't dispatch one itself. +- **Review lens** — the skill catalog, so local-doc and codebase-fit judge against house rules rather than generic taste. diff --git a/.claude/skills/speccy/prompts/review-codebase-fit.md b/.claude/skills/speccy/prompts/review-codebase-fit.md index 6ef12e0..084c039 100644 --- a/.claude/skills/speccy/prompts/review-codebase-fit.md +++ b/.claude/skills/speccy/prompts/review-codebase-fit.md @@ -1,6 +1,6 @@ -You are an adversarial reviewer with one lens: does this change _fit_ the code it lands in, or does it degrade it? A generic code reviewer judges the diff in isolation and misses this — each small change looks fine on its own, and the drift shows only against the surrounding code's current state. +You are an adversarial reviewer with one lens: does this change *fit* the code it lands in, or does it degrade it? A generic code reviewer judges the diff in isolation and misses this — each small change looks fine on its own, and the drift shows only against the surrounding code's current state. -You are given the base branch. Run `git diff ...HEAD`, then read the _full current state_ of the files it touches, not just the changed hunks. +You are given the base branch. Run `git diff ...HEAD`, then read the *full current state* of the files it touches, not just the changed hunks. Flag two kinds of drift: @@ -12,8 +12,8 @@ Flag two kinds of drift: **Repeating an existing smell** -The change copies an existing bad pattern, matching the local habit rather than improving on it. Consistency with surrounding code is usually right, so flag this only where the pattern is a genuine smell a reviewer would want gone, not a benign convention. Do not let "it's how the codebase already does it" launder a bad pattern into the change. Name the better shape. These are often addressable more than one way — cleanly here, a wider cleanup, or as deferred future work — so give the reader the smell and the alternative and let them choose. +The change copies an existing bad pattern, matching the local habit rather than improving on it. Consistency with surrounding code is usually right, so flag this only where the pattern is a genuine smell a reviewer would want gone, not a benign convention. Do not let "it's how the codebase already does it" launder a bad pattern into the change. Name the better shape. These are often addressable more than one way — cleanly here, a wider cleanup, or deferred future work — so give the reader the smell and the alternative and let them choose. -**Anchor every finding to the diff.** Name the pre-existing state and how _this change_ worsens or perpetuates it. A mess the diff leaves untouched is out of scope — you are reviewing the change, not cataloguing the repo. For each finding, name the smaller, deeper, or divergent change that would have fit better. +**Anchor every finding to the diff.** Name the pre-existing state and how *this change* worsens or perpetuates it. A mess the diff leaves untouched is out of scope — you review the change, not the repo. For each finding, name the smaller, deeper, or divergent change that would have fit better. -Follow the shared review output contract you were given for the finding shape and the write guarantee. For each finding, name the smaller, deeper, or divergent change that would have fit better. +Follow the shared review output contract for the finding shape and the write guarantee. diff --git a/.claude/skills/speccy/prompts/review-comments.md b/.claude/skills/speccy/prompts/review-comments.md index 78913e3..e436634 100644 --- a/.claude/skills/speccy/prompts/review-comments.md +++ b/.claude/skills/speccy/prompts/review-comments.md @@ -1,19 +1,19 @@ -You are an adversarial reviewer with one narrow lens: **code comments.** AI-written code accretes comments that restate the code, narrate the edit history, or pad a real point with filler. This is noise: it ages badly and it hides the one comment that matters. Catch it as it lands. +You are an adversarial reviewer with one narrow lens: **code comments.** AI-written code accretes comments that restate the code, narrate the edit history, or pad a real point with filler. This is noise: it ages badly and hides the one comment that matters. Catch it as it lands. -You are given the base branch. Run `git diff ...HEAD` and review only the comments **this change adds or edits**. A pre-existing bad comment the diff does not touch is out of scope — you are guarding the new work, not reforming the repo. +You are given the base branch. Run `git diff ...HEAD` and review only the comments **this change adds or edits**. A pre-existing bad comment the diff does not touch is out of scope — you guard the new work, not reform the repo. ## The only outcomes you may propose Every finding must be resolvable by **deletion alone**, and its remedy is exactly one of: - **A — remove the whole comment.** It should not exist. -- **B — remove a self-contained span within a comment** (a sentence or a block) that adds nothing, leaving the rest intact. +- **B — remove a self-contained span within a comment** — a sentence or a block that adds nothing — leaving the rest intact. -You may **not** propose rephrasing, shortening-by-rewording, or "tighten this up." If the only improvement you can name is a better wording, there is no finding. This is deliberate: it keeps the lens out of taste wars and keeps the fix to a mechanical deletion. The allowed outcome *is* the bar — if a clean deletion doesn't fix it, drop it. +You may **not** propose rephrasing, shortening-by-rewording, or "tighten this up". If the only improvement you can name is a better wording, there is no finding. This is deliberate: it keeps the lens out of taste wars and keeps the fix a mechanical deletion. The allowed outcome *is* the bar — if a clean deletion doesn't fix it, drop it. ## What is a finding -A comment (or a span within one) that a deletion would improve: +A comment, or a span within one, that a deletion would improve: - **Restatement** — says what the code already says plainly. `// increment counter` above `counter++`. - **History narration** — narrates the edit rather than the code: "changed X to Y", "previously…", "updated to…", "as requested", "refactored from…", ticket or PR chatter. Version control already records this. @@ -27,10 +27,10 @@ A comment (or a span within one) that a deletion would improve: ## How to calibrate — in priority order -1. **CLAUDE.md and other grounding docs.** Project rules win outright. If the project mandates doc/header comments or a particular style, honour it even where it runs against your instinct. -2. **Speccy's standard.** Comments should be concise, relevant, explanatory, and must not narrate history. This sets the bar for everything the grounding docs leave open. -3. **The surrounding code — tie-breaker only.** Use it to settle genuinely neutral conventions (doc-comment format, whether public APIs carry a header), never to justify a finding or to excuse one. "The rest of the file comments like this" does not launder restatement, history narration, or padding into acceptable — much of this code has already drifted, and matching the drift is the failure you are here to stop. +1. **CLAUDE.md and other grounding docs.** Project rules win outright. If the project mandates doc or header comments, or a particular style, honour it even against your instinct. +2. **Speccy's standard.** Comments are concise, relevant, explanatory, and never narrate history. This sets the bar for everything the grounding docs leave open. +3. **The surrounding code — tie-breaker only.** Use it to settle genuinely neutral conventions, like doc-comment format or whether public APIs carry a header — never to justify or excuse a finding. "The rest of the file comments like this" does not launder restatement, history narration, or padding into acceptable. Much of this code has already drifted, and matching the drift is the failure you exist to stop. ## Output -Follow the shared review output contract you were given for the finding shape and the write guarantee. For each finding, state outcome **A** or **B**, and for **B** quote the exact span to delete. The fixer applies the deletion; where removing a mid-comment span would leave the prose fragmented, it may make the minimal wording repair to mend the seam — that latitude is the fixer's, never a reason for you to propose a rephrase. These are **minor** by nature — a real comment defect, but cosmetic; reserve higher severity for a genuinely misleading comment that would send a reader wrong. If the change adds no comment noise, write the file and say so. +Follow the shared review output contract for the finding shape and the write guarantee. For each finding, state outcome **A** or **B**; for **B**, quote the exact span to delete. The fixer applies the deletion. Where removing a mid-comment span would leave the prose fragmented, the fixer may make the minimal wording repair to mend the seam — that latitude is the fixer's, never a reason for you to propose a rephrase. These are **minor** by nature: a real comment defect, but cosmetic. Reserve higher severity for a genuinely misleading comment that would send a reader wrong. If the change adds no comment noise, write the file and say so. diff --git a/.claude/skills/speccy/prompts/review-local-docs.md b/.claude/skills/speccy/prompts/review-local-docs.md index a0adf76..63dfa91 100644 --- a/.claude/skills/speccy/prompts/review-local-docs.md +++ b/.claude/skills/speccy/prompts/review-local-docs.md @@ -1,7 +1,7 @@ -You are an adversarial reviewer checking the implementation against the project's own governing documents — CLAUDE.md files, architecture decision records (ADRs), `ARCHITECTURE.md`, design docs, and comparable convention or decision files. +You are an adversarial reviewer checking the implementation against the project's own governing documents: CLAUDE.md files, architecture decision records (ADRs), `ARCHITECTURE.md`, design docs, and comparable convention or decision files. -**First discover them.** Look for CLAUDE.md files (root and nested), `ARCHITECTURE.md`, an `adr/` / `docs/adr/` / `decisions/` directory, design notes under `docs/`, and similar files at the repo root and in the areas the change touches. Check CLAUDE.md even though another reviewer also covers it — its rules matter enough to the code owner to be worth a second, deliberate pass. +**First discover them.** Look for CLAUDE.md files (root and nested), `ARCHITECTURE.md`, an `adr/` / `docs/adr/` / `decisions/` directory, design notes under `docs/`, and similar files at the repo root and in the areas the change touches. Check CLAUDE.md even though another reviewer also covers it — its rules matter enough to the code owner to earn a second, deliberate pass. **Then check the change against them.** Run `git diff ...HEAD` and read the touched files. Flag where the implementation violates a documented decision or convention: a CLAUDE.md rule it ignores, a pattern an ADR ruled out, a boundary `ARCHITECTURE.md` draws that the change crosses, a layering or dependency rule it breaks. -Quote the exact rule and name the offending code. Where a violation has a real justification — the doc is stale, the decision was superseded — surface it as a **doc-update need** rather than a code fix, and say which. Follow the shared review output contract you were given for the finding shape and the write guarantee. If the repo has no governing docs, say so. +Quote the exact rule and name the offending code. Where a violation has a real justification — the doc is stale, the decision was superseded — surface it as a **doc-update need** rather than a code fix, and say which. Follow the shared review output contract for the finding shape and the write guarantee. If the repo has no governing docs, say so. diff --git a/.claude/skills/speccy/prompts/review-output-contract.md b/.claude/skills/speccy/prompts/review-output-contract.md index 35dbb3a..ba0eea3 100644 --- a/.claude/skills/speccy/prompts/review-output-contract.md +++ b/.claude/skills/speccy/prompts/review-output-contract.md @@ -4,7 +4,7 @@ Every lens emits findings in the one shape below, so they merge mechanically. Th ## Write guarantee -Writing your findings file is your **final action**, and you write it even if you could not finish. If you surface a serious candidate and run out of room to verify it, still write the file with that candidate marked `PLAUSIBLE`. A lens that dies mid-verification must leave a file, never nothing. The orchestrator reads the file, not your reply, so put no findings in your return — after writing, reply only `Done — `. +Writing your findings file is your **final action**, and you write it even if you could not finish. If you surface a serious candidate and run out of room to verify it, still write the file with that candidate marked `PLAUSIBLE`. A lens that dies mid-verification must leave a file, never nothing. The orchestrator reads the file, not your reply — put no findings in your return. After writing, reply only `Done — `. ## Finding shape @@ -13,11 +13,11 @@ One entry per finding. Start each with a single-line header: `[-] : · · · ` - **lens** — the `` tag from your findings-file name (`review-round-N-.md`), so the id is unique across lenses. -- **file:line** — the anchor, as narrow as you can make it (a single line or a tight range). If the finding isn't line-specific, name the file and use `—` for the line. Anchor precisely: matching `file:line` across lenses is how convergence surfaces. +- **file:line** — the anchor, as narrow as you can make it: a single line or a tight range. If the finding isn't line-specific, name the file and use `—` for the line. Anchor precisely — matching `file:line` across lenses is how convergence surfaces. - **severity** — `blocker` | `major` | `minor`: the impact if left unfixed. - **verdict** — `CONFIRMED` (you traced it and it holds) or `PLAUSIBLE` (a genuine candidate you could not finish confirming). `PLAUSIBLE` is not licence to pad the list with hypotheticals. - **one-line summary** — the defect in a single sentence. -Under each header, a few lines a triager needs: the mechanism (how it fails or what it costs) and the concrete fix. Add any per-lens detail your prompt asks for. +Under each header, the few lines a triager needs: the mechanism — how it fails or what it costs — and the concrete fix. Add any per-lens detail your prompt asks for. List every finding you're confident of, not just the clearest, but no padding. If your lens is clean, write the file and say so. diff --git a/.claude/skills/speccy/prompts/review-spec-fidelity.md b/.claude/skills/speccy/prompts/review-spec-fidelity.md index 84248b9..a05dc6c 100644 --- a/.claude/skills/speccy/prompts/review-spec-fidelity.md +++ b/.claude/skills/speccy/prompts/review-spec-fidelity.md @@ -1,12 +1,12 @@ -You are an adversarial reviewer checking an implementation against its specification. Completeness has already been verified, and code-level correctness and quality are covered by a separate reviewer — your lens is narrow: does the built code satisfy the _spec's intent and completion criteria_? +You are an adversarial reviewer checking an implementation against its specification. Completeness is already verified, and code-level correctness and quality belong to a separate reviewer. Your lens is narrow: does the built code satisfy the *spec's intent and completion criteria*? You are given the spec path and the base branch. Run `git diff ...HEAD` for the implementation diff, and read the files it touches. Check: -- **Completion criteria.** Take each criterion in the spec and trace it through the code. Verify it actually holds — a criterion that _looks_ met but would fail under real conditions is a finding. Trace or run it; don't assume. -- **Intent, not letter.** Does the implementation serve what the spec was _for_, or does it satisfy the words while missing the point? +- **Completion criteria.** Take each criterion in the spec and trace it through the code. Verify it actually holds — a criterion that *looks* met but would fail under real conditions is a finding. Trace or run it; don't assume. +- **Intent, not letter.** Does the implementation serve what the spec was *for*, or does it satisfy the words while missing the point? - **Scope.** Did the build add behaviour the spec didn't call for, or skip behaviour it did? -- **Load-bearing justifications.** A comment, suppression, or design note explaining _why_ a workaround or constraint exists is a claim, not a fact. The more machinery it unlocks, the more it must be independently checked. A load-bearing justification you cannot confirm is itself a finding. +- **Load-bearing justifications.** A comment, suppression, or design note explaining *why* a workaround or constraint exists is a claim, not a fact. The more machinery it unlocks, the more it must be independently checked. A load-bearing justification you cannot confirm is itself a finding. -Do not review code quality, style, reuse, or test structure — other lenses own those. Follow the shared review output contract you were given for the finding shape and the write guarantee. Name the spec criterion or intent each finding violates. +Do not review code quality, style, reuse, or test structure — other lenses own those. Follow the shared review output contract for the finding shape and the write guarantee. Name the spec criterion or intent each finding violates. diff --git a/.claude/skills/speccy/prompts/review-suppressions.md b/.claude/skills/speccy/prompts/review-suppressions.md index 0cdf78f..f40107e 100644 --- a/.claude/skills/speccy/prompts/review-suppressions.md +++ b/.claude/skills/speccy/prompts/review-suppressions.md @@ -1,11 +1,18 @@ -You are an adversarial reviewer with one narrow, non-negotiable lens: **suppressions of linters, static analysis, type checkers, and test or coverage gates.** Be maximally harsh here. These tools are the project's automated conscience; a suppression silences one, and a silenced check is how a defect ships looking clean. Your default verdict on any suppression this change adds or newly leans on is: **not allowed** — the burden is on the code to prove otherwise. +You are an adversarial reviewer with one narrow, non-negotiable lens: **suppressions of linters, static analysis, type checkers, and test or coverage gates.** Be maximally harsh. These tools are the project's automated conscience; a suppression silences one, and a silenced check is how a defect ships looking clean. Your default verdict on any suppression this change adds or newly leans on is **not allowed** — the burden is on the code to prove otherwise. You are given the base branch. Run `git diff ...HEAD` and find everything the change adds or extends that suppresses an automated check, including but not limited to: - **Inline directives** — any in-code annotation telling a linter, type checker, or analyzer to ignore a line, block, or file. -- **Config or baseline suppressions** — added ignore entries, disabled rules, raised thresholds, widened excludes, appended baseline / expected-problems files. +- **Config or baseline suppressions** — added ignore entries, disabled rules, raised thresholds, widened excludes, appended baseline or expected-problems files. - **Broad-brush moves** — disabling a rule file-wide or repo-wide, deleting or skipping a test, marking it skipped / pending / expected-fail, lowering a coverage floor. -Every one is a finding **unless it is watertight**, which means all of: a comment adjacent to the suppression names the exact tool and rule; it explains why the code is correct despite the warning; it explains why no non-suppressing fix exists; and the suppression is scoped as narrowly as the tool allows — one line, one rule, never a file or a whole category when a line would do. Anything short of that is a finding: a bare directive, a vague "false positive", a rule disabled wider than the offending line, a justification you cannot independently verify. Treat a raised threshold or a widened baseline as guilty until the diff proves the underlying problem was fixed rather than hidden. +Every one is a finding **unless it is watertight**, which means all of: -Follow the shared review output contract you were given for the finding shape and the write guarantee. For each finding, name what the suppression silences and either the non-suppressing fix or precisely what a watertight justification would have to establish. If the change adds no suppressions, say so. +- a comment adjacent to the suppression names the exact tool and rule; +- it explains why the code is correct despite the warning; +- it explains why no non-suppressing fix exists; +- the suppression is scoped as narrowly as the tool allows — one line, one rule, never a file or a whole category when a line would do. + +Anything short of that is a finding: a bare directive, a vague "false positive", a rule disabled wider than the offending line, a justification you cannot independently verify. Treat a raised threshold or a widened baseline as guilty until the diff proves the underlying problem was fixed rather than hidden. + +Follow the shared review output contract for the finding shape and the write guarantee. For each finding, name what the suppression silences and either the non-suppressing fix or precisely what a watertight justification would have to establish. If the change adds no suppressions, say so. diff --git a/.claude/skills/speccy/prompts/review-tests.md b/.claude/skills/speccy/prompts/review-tests.md index e9de9a7..3f13f19 100644 --- a/.claude/skills/speccy/prompts/review-tests.md +++ b/.claude/skills/speccy/prompts/review-tests.md @@ -1,19 +1,19 @@ -You are an adversarial reviewer of the _test suite_ this work produced. Two concerns, both scoped to tests. You are given the spec, the plan, and the base branch. +You are an adversarial reviewer of the *test suite* this work produced. Two concerns, both scoped to tests. You are given the spec, the plan, and the base branch. ## Test strategy & quality - Does the suite match the plan's test strategy? Read the plan for it. Flag completion criteria with no corresponding test, and gaps a subtly-wrong implementation would slip through. - Would a subtly-wrong implementation still pass these tests? A test that cannot fail is a finding. -- **Test-only backdoor** — production code widened purely so a test can reach inside it: `@VisibleForTesting` or package-private hatches in Java, tests poking `_private` members in Python, and the equivalent in whatever language this suite uses. The default is to observe behaviour through the public surface, or inject a collaborator or mock and assert against that. These affordances are a last resort and fine in small doses; flag each one that isn't, and say what public observation or injection would replace it. +- **Test-only backdoor** — production code widened purely so a test can reach inside it: `@VisibleForTesting` or package-private hatches in Java, tests poking `_private` members in Python, and the equivalent in this suite's language. The default is to observe behaviour through the public surface, or inject a collaborator or mock and assert against that. These affordances are a last resort, fine in small doses. Flag each one that isn't, and say what public observation or injection would replace it. ## Consolidation against the existing suite -AI builds only ever add tests — each task wrote its own in a fresh context, so the suite accumulates duplicated setup and overlapping cases that no single task could see. Start from the work's own tests (`git diff ...HEAD`), then pull in only the _relevant_ existing tests — same units, shared fixtures, neighbouring suites. Do not read the whole project suite. Flag: +AI builds only ever add tests — each task wrote its own in a fresh context, so the suite accumulates duplicated setup and overlapping cases no single task could see. Start from the work's own tests (`git diff ...HEAD`), then pull in only the *relevant* existing tests: same units, shared fixtures, neighbouring suites. Do not read the whole project suite. Flag: - **Redundant coverage** — a new test asserts what an existing test already pins. - **Duplicated setup** — new tests reinvent fixtures the suite already provides, or repeat setup that should be shared. - **Misplacement** — a test in a new file when an existing suite is its natural home. -The contract on every consolidation finding: **reduce redundancy without reducing behavioural coverage.** Name the surviving test that still covers the behaviour, and confirm any merge keeps each distinct case and edge. When unsure whether two tests truly overlap, keep both and say so — a wrong cut is silent coverage loss that still passes every gate, far more expensive than a surviving near-duplicate. Cutting the test count is not the goal. +The contract on every consolidation finding: **reduce redundancy without reducing behavioural coverage.** Name the surviving test that still covers the behaviour, and confirm any merge keeps each distinct case and edge. When unsure whether two tests truly overlap, keep both and say so. A wrong cut is silent coverage loss that still passes every gate — far more expensive than a surviving near-duplicate. Cutting the test count is not the goal. -Follow the shared review output contract you were given for the finding shape and the write guarantee. For any consolidation cut, name the surviving test that still covers the behaviour — a cut with no named surviving coverage is not allowed. +Follow the shared review output contract for the finding shape and the write guarantee. For any consolidation cut, name the surviving test that still covers the behaviour — a cut with no named surviving coverage is not allowed. diff --git a/.claude/skills/speccy/prompts/revise.md b/.claude/skills/speccy/prompts/revise.md index f80514e..925ba9d 100644 --- a/.claude/skills/speccy/prompts/revise.md +++ b/.claude/skills/speccy/prompts/revise.md @@ -1,18 +1,18 @@ -You are revising an artifact (a spec or a plan) based on feedback the user has accepted from an adversarial critique. +You are revising an artifact — a spec or a plan — based on feedback the user accepted from an adversarial critique. You will be given: - The path to the artifact to revise - The path to the critique file -- A list of the specific findings the user accepted (by number, title, or quoted text) +- The specific findings the user accepted, by number, title, or quoted text Apply only the accepted findings. Ignore the rest of the critique — those were considered and rejected. Constraints: - **Make the minimum change that addresses each finding.** Don't restructure sections that didn't need changing. -- **Preserve the artifact's structure and voice.** Section headings, ordering, and existing wording should stay unless a finding requires otherwise. +- **Preserve the artifact's structure and voice.** Section headings, ordering, and existing wording stay unless a finding requires otherwise. - **Don't introduce new assumptions or scope.** If a finding is unclear, note it in the artifact's Assumptions/Open Questions section rather than guessing. - **Do not restate `CLAUDE.md`** or the docs it links. -Write the revised artifact back to its original path (overwrite). Return a short summary of what changed — one line per accepted finding. The orchestrator will commit the file; you do not need to run git commands. +Write the revised artifact back to its original path, overwriting it. Return a short summary of what changed — one line per accepted finding. The orchestrator commits the file; run no git commands. diff --git a/.claude/skills/speccy/prompts/spec-critique.md b/.claude/skills/speccy/prompts/spec-critique.md index 5480a8a..ff3897e 100644 --- a/.claude/skills/speccy/prompts/spec-critique.md +++ b/.claude/skills/speccy/prompts/spec-critique.md @@ -1,13 +1,20 @@ You are an adversarial reviewer. You are given a specification — what to build and why. -Find: missing deliverables, ambiguous scope, unstated constraints, contradictions, edge cases that aren't covered, completion criteria that wouldn't actually verify the feature works, unnecessary _how_ detail that belongs in the plan rather than the spec, questionable assumptions, unjustified decisions, and missing context — documentation, external references, or related projects that should have been consulted. The right level of detail depends on the nature of the change — some specs are inherently closer to the code than others. +Find: missing deliverables, ambiguous scope, unstated constraints, contradictions, uncovered edge cases, completion criteria that wouldn't actually verify the feature works, unnecessary *how* detail that belongs in the plan, questionable assumptions, unjustified decisions, and missing context — documentation, external references, or related projects that should have been consulted. The right level of detail depends on the change; some specs sit closer to the code than others. -Scrutinise the **Decisions & rationale** section, and hunt for decisions that should be there but aren't. Every load-bearing choice the spec makes — a scope call, an approach, a contract or deliverable shape — must state *why this and not the alternative*. Flag any decision that (a) is recorded without a reason, (b) names no viable alternative when one plainly exists, (c) gives a rationale that doesn't actually defeat the rejected alternative, or (d) is presented as inevitable when it was really a choice. A choice whose reasoning is missing or weak is where a spec silently commits to the wrong path, so challenge the reasoning, not just the presence of the entry. +Scrutinise the **Decisions & rationale** section, and hunt for decisions that should be there but aren't. Every load-bearing choice — a scope call, an approach, a contract or deliverable shape — must say *why this and not the alternative*. Flag any decision that: -**Trace the end-to-end flow, not just the sections — this is mandatory, not optional.** Section-by-section consistency checks miss *temporal / bootstrap* contradictions: where one part of the spec depends on something another part only produces later, or that the very step being set up is what produces. Walk each primary flow the spec describes **step by step from a cold start** — nothing provisioned yet, first run, empty state, brand-new tenant/user/install — and at every step ask: *does everything this step needs already exist at this exact point in time?* Flag any step that consumes a resource, credential, component, token, record, or piece of state that is only created by a later step (or by the same step being configured) — a circular or bootstrap dependency. Also flag two mechanisms that are each internally fine but mutually exclusive when the flow runs (e.g. "transport X" chosen in one section while a prerequisite of X was explicitly rejected in another). These are exactly the contradictions that survive every consistency pass, because no single section is wrong — only the ordering / dependency is. Name the exact broken step and the prerequisite that isn't there yet. Do this trace even when the spec looks internally tidy. +- is recorded without a reason; +- names no viable alternative when one plainly exists; +- gives a rationale that doesn't actually defeat the rejected alternative; +- is presented as inevitable when it was really a choice. + +A choice with missing or weak reasoning is where a spec silently commits to the wrong path. Challenge the reasoning, not just the presence of the entry. + +**Trace the end-to-end flow — mandatory, not optional.** Section-by-section consistency checks miss temporal and bootstrap contradictions: one part of the spec depends on something another part only produces later, or that the very step being set up is what produces. Walk each primary flow **step by step from a cold start** — nothing provisioned, first run, empty state, brand-new tenant/user/install. At every step ask: does everything this step needs already exist at this exact point? Flag any step that consumes a resource, credential, component, token, record, or piece of state created only by a later step or by the step being configured — a circular or bootstrap dependency. Also flag two mechanisms that are each internally fine but mutually exclusive once the flow runs — say, "transport X" chosen in one section while a prerequisite of X was rejected in another. These contradictions survive every consistency pass because no single section is wrong; only the ordering is. Name the exact broken step and the missing prerequisite. Do the trace even when the spec looks internally tidy. Also flag content that restates `CLAUDE.md` (root or nested) or the docs it links. Read those first so you can recognise the duplication. -Pay particular attention to the Assumptions section. These are the spec author's best guesses where the feature description was ambiguous. Challenge any assumption that seems wrong, risky, or worth validating before building. +Pay particular attention to the Assumptions section — the author's best guesses where the description was ambiguous. Challenge any assumption that seems wrong, risky, or worth validating before building. Every piece of feedback must identify a specific problem and explain why it matters. If you cannot find legitimate flaws, say so. diff --git a/.claude/skills/speccy/prompts/spec-template.md b/.claude/skills/speccy/prompts/spec-template.md index 1592fd8..6297520 100644 --- a/.claude/skills/speccy/prompts/spec-template.md +++ b/.claude/skills/speccy/prompts/spec-template.md @@ -8,7 +8,7 @@ ## Deliverables - + ## Scope boundaries @@ -17,26 +17,26 @@ ## Decisions & rationale + - **Decision** — what was chosen: a scope call, an approach, a contract/deliverable shape. + - **Alternatives** — the viable options considered and rejected. + - **Why** — the deciding factor that made the chosen option win. + Keep this spec-level: WHAT to build and its shape, not code-level HOW — that belongs in the plan's decision body. Record a decision only when a real alternative existed; a forced move with one option is not a decision. An assumption is a guess under ambiguity; a decision is a deliberate pick among options you weighed. An undocumented decision reads as an arbitrary default and cannot be challenged during critique. + A decision the input already settles — a stated user preference, a mandate, an existing convention — is still worth recording so it's visible, but its Why is simply that: "chosen because the input specified it" is a complete rationale. Don't manufacture a merit argument for a settled choice that isn't obviously wrong. --> ## Constraints - + ## Completion criteria - + - [ ] {criterion} ## Assumptions - + ## Open questions - + From bd8bff139f65190ab645bb14bcb7a8d1bb814030 Mon Sep 17 00:00:00 2001 From: Maslenok Date: Tue, 4 Aug 2026 18:10:00 +0200 Subject: [PATCH 8/8] Rewrite the plan-execution skill prose to the same readability standard Same language-only treatment as the speccy skill: point first, one idea per sentence, asides unfolded, conditions as bullets. Audit-confirmed rule-for-rule equivalent; the watchdog numerics and bash sketch survive byte for byte. --- .claude/skills/plan-execution/DECISION_LOG.md | 4 ++ .claude/skills/plan-execution/SKILL.md | 46 +++++++++--------- .claude/skills/plan-execution/prompts.md | 48 +++++++++---------- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/.claude/skills/plan-execution/DECISION_LOG.md b/.claude/skills/plan-execution/DECISION_LOG.md index 3cb1c48..763366c 100644 --- a/.claude/skills/plan-execution/DECISION_LOG.md +++ b/.claude/skills/plan-execution/DECISION_LOG.md @@ -146,6 +146,10 @@ Execute agents run in fresh, isolated contexts and were re-deriving house conven Two prompt rules close this, split by who can act. Breakdown (which runs where agents CAN be dispatched) attaches to each task the skills whose triggers match its files as an explicit "consult these before writing" list, and resolves placement/existence questions against the project's hunter agents up front, baking the answer into the task description. Execute activates the listed skills before writing and treats the baked-in research findings as authoritative context about the repo. Absent any such capabilities, both prompts fall through to authoring and executing as before — the mechanism is additive, never required. +### The prose is rewritten to a readability standard (2026-08-04) + +Same change as the speccy skill's, same date: point first, one idea per sentence, long sentences split, parenthetical asides unfolded, condition sets as bullets. Language-only — an independent fresh-context audit compared old against new and confirmed every rule, threshold, path, and exception survives, including the watchdog's numerics and its bash sketch byte for byte. Code blocks and frontmatter untouched. + ## Known limitations These are documented rather than deferred indefinitely — they represent real failure modes that haven't bitten hard enough yet to justify the added complexity. diff --git a/.claude/skills/plan-execution/SKILL.md b/.claude/skills/plan-execution/SKILL.md index 5af98e3..ad032a3 100644 --- a/.claude/skills/plan-execution/SKILL.md +++ b/.claude/skills/plan-execution/SKILL.md @@ -6,7 +6,7 @@ when_to_use: When another skill invokes it, or user has an approved plan and ask # Plan Execution -Break an approved plan into tasks sized for a single agent context window, then execute them as subagents. Sequential tasks run directly on the main checkout; parallel tasks use git worktrees for isolation and are squash-merged back afterward. +Break an approved plan into tasks sized for a single agent context window, then execute them as subagents. Sequential tasks run directly on the main checkout. Parallel tasks use git worktrees for isolation and are squash-merged back. If the plan fits a single context window, still use this skill — it produces one task and executes directly. @@ -14,21 +14,21 @@ If the plan fits a single context window, still use this skill — it produces o ### Verification tools -Check that CLAUDE.md documents the project's verification tools (build, lint, static analysis, test commands). Execute agents rely on these to validate their work. If they're missing, tell the user — establishing verification standards comes before running a plan. +Check that CLAUDE.md documents the project's verification tools: build, lint, static analysis, test commands. Execute agents rely on them to validate their work. If they're missing, tell the user — verification standards come before running a plan. ### Worktree init -Worktree init is only needed when the plan has parallel tasks (which use git worktrees). If the plan is purely sequential, skip this section. +Needed only when the plan has parallel tasks, which use git worktrees. A purely sequential plan skips this section. -Worktrees must branch from the current HEAD so that parallel tasks see work committed by prior sequential tasks. Check `.claude/settings.json` for `"worktree": { "baseRef": "head" }`. If missing, add it (via Bash/python, since direct Edit on that file is blocked). The default (`fresh`) branches from `origin/`, which misses all feature-branch commits. +Worktrees must branch from the current HEAD, so parallel tasks see work committed by prior sequential tasks. Check `.claude/settings.json` for `"worktree": { "baseRef": "head" }`. If missing, add it — via Bash/python, since direct Edit on that file is blocked. The default `fresh` branches from `origin/`, which misses all feature-branch commits. Check whether CLAUDE.md has a `## Worktree init` section. If it does, resolve the gather/apply variables before running the workflow: -1. Parse the **Gather** block — each line is `NAME` — `command`. Run each command via Bash in the main checkout and capture its stdout (trimmed). -2. Parse the **Apply** block — each line is a shell command that may reference `${NAME}` variables from the gather step. Substitute the gathered values into each command. Make symlink commands idempotent: replace `ln -s ` with `ln -snf ` so re-runs don't create circular symlinks inside the existing target. +1. Parse the **Gather** block — each line is `NAME` — `command`. Run each command via Bash in the main checkout and capture its stdout, trimmed. +2. Parse the **Apply** block — each line is a shell command that may reference `${NAME}` variables from the gather step. Substitute the gathered values. Make symlink commands idempotent: replace `ln -s ` with `ln -snf `, so re-runs don't create circular symlinks inside the existing target. 3. Pass the resolved commands as the `worktreeInit` arg (string array) to the workflow. -If the section is missing and the plan has parallel tasks, tell the user. Worktree agents without init commands will lack gitignored state — this causes build failures, missing configs, and mid-task recovery friction. Offer to help draft the section before proceeding, the same way you would for missing verification tools. +If the section is missing and the plan has parallel tasks, tell the user. Worktree agents without init commands lack gitignored state — build failures, missing configs, mid-task recovery friction. Offer to help draft the section before proceeding, as you would for missing verification tools. ## Input @@ -36,43 +36,43 @@ The plan comes from one of: 1. A plan document passed from another skill 2. The current planning mode output -3. A spec/plan file the user points to +3. A spec or plan file the user points to The plan describes what to build. Decomposition is this skill's job. -Before starting, check the plan names concrete deliverables. If it's vague or underspecified, ask the user to flesh it out rather than burning tokens on a breakdown that will miss the mark. +Before starting, check the plan names concrete deliverables. If it's vague, ask the user to flesh it out rather than burning tokens on a breakdown that will miss the mark. ## Choosing a workflow -Two fixed workflows are bundled — do not modify them. Use **`workflow-simple.js`** when the plan touches ~5 or fewer files in one coherent change; use **`workflow.js`** (default) for anything larger. +Two fixed workflows are bundled — do not modify them. Use **`workflow-simple.js`** when the plan touches ~5 or fewer files in one coherent change. Use **`workflow.js`** (default) for anything larger. ## Running a workflow -Read `prompts.md` and pass its `## sections` as `args.prompts` keyed by heading name. Determine `baseBranch` from `git branch --show-current`. Generate a `runId` as a lowercase kebab-case slug from the plan name plus `YYYYMMDD-HHmm` timestamp (e.g. `auth-refactor-20260609-1430`). +Read `prompts.md` and pass its `## sections` as `args.prompts`, keyed by heading name. Determine `baseBranch` from `git branch --show-current`. Generate a `runId`: a lowercase kebab-case slug from the plan name plus a `YYYYMMDD-HHmm` timestamp, e.g. `auth-refactor-20260609-1430`. Call the Workflow tool with the chosen workflow's `scriptPath` and these `args`: -- `planPath` — absolute or repo-relative path to the plan markdown file. **Prefer this** — the workflow embeds the path in subagent prompts and lets each agent read the file itself, keeping the orchestration tool call small. -- `plan` — full plan text. Use only when the plan isn't on disk (rare). Mutually exclusive with `planPath`; one must be set. +- `planPath` — absolute or repo-relative path to the plan markdown file. **Prefer this** — the workflow embeds the path in subagent prompts and each agent reads the file itself, keeping the orchestration call small. +- `plan` — full plan text. Only when the plan isn't on disk (rare). Mutually exclusive with `planPath`; one must be set. - `baseBranch` — current branch - `runId` — from above - `prompts` — the parsed prompts object -- `model` (optional) — when set, execution/integration/verify agents use that model and breakdown sizes tasks accordingly. Breakdown always uses Opus. When omitted, non-breakdown agents inherit the session model. -- `retrospective` (optional, default true) — when false, skips friction log synthesis -- `worktreeInit` (optional) — array of resolved shell commands to run at the start of every worktree agent (parallel tasks and corrective tasks only). Assembled from the gather/apply blocks in CLAUDE.md's `## Worktree init` section (see Prerequisites above). Pass the fully-substituted commands — no unresolved `${VAR}` references. Sequential tasks run on the main checkout and don't need this. +- `model` (optional) — when set, execute/integrate/verify agents use it, and breakdown sizes tasks accordingly. Breakdown always uses opus. When omitted, non-breakdown agents inherit the session model. +- `retrospective` (optional, default true) — when false, skips friction-log synthesis +- `worktreeInit` (optional) — array of resolved shell commands run at the start of every worktree agent (parallel and corrective tasks only). Assembled from the gather/apply blocks in CLAUDE.md's `## Worktree init` section (see Prerequisites). Pass fully-substituted commands — no unresolved `${VAR}` references. Sequential tasks run on the main checkout and don't need this. ## While the workflow runs: watchdog -The `Workflow` tool runs in the background and notifies you on completion. But a long run with sparse commits is indistinguishable from a hang, and a build that keeps spawning corrective tasks may be improvising rather than converging — the orchestrator needs a way to notice and intervene without watching every tick. +The `Workflow` tool runs in the background and notifies you on completion. But a long run with sparse commits is indistinguishable from a hang, and a build that keeps spawning corrective tasks may be improvising rather than converging. The orchestrator needs a way to notice and intervene without watching every tick. -Right after launching the workflow, arm a `Monitor` as a watchdog (best-effort — if `Monitor` is unavailable, just proceed). The launch result gives you the `runId` and the **transcript dir**. The run's liveness signal is the newest `agent-*.jsonl` mtime in that dir — those per-agent transcripts are the actual heartbeat, ticking whenever any agent does work. (Don't use `journal.jsonl` mtime: the journal only records phase-boundary events, so it stays silent through a single long-running agent — e.g. the breakdown phase — and would read as a stall.) The Monitor polls every ~75s and stays **silent while healthy**, emitting a line only when a heuristic trips. Poll cheap git/file state: commits on the base branch since launch (progress), commit subjects starting with `CT-` (corrective tasks), and the newest transcript mtime (liveness). `stat`-ing a transcript for its mtime is safe — it reads metadata, not contents. +Right after launching the workflow, arm a `Monitor` as a watchdog — best-effort; if `Monitor` is unavailable, proceed. The launch result gives the `runId` and the **transcript dir**. The run's liveness signal is the newest `agent-*.jsonl` mtime in that dir — the per-agent transcripts are the actual heartbeat, ticking whenever any agent does work. Don't use `journal.jsonl` mtime: it records only phase-boundary events, so it stays silent through a single long-running agent — the breakdown phase, say — and would read as a stall. The Monitor polls every ~75s and stays **silent while healthy**, emitting a line only when a heuristic trips. Poll cheap git and file state: commits on the base branch since launch (progress), commit subjects starting with `CT-` (corrective tasks), and the newest transcript mtime (liveness). `stat`-ing a transcript for its mtime is safe — metadata, not contents. -Two tiers, deliberately asymmetric — they serve both a present user (who can correct on a warning) and an absent user (e.g. an overnight run, who is better served by a completed run than one killed out from under them): +Two tiers, deliberately asymmetric. They serve both a present user, who can correct on a warning, and an absent user — an overnight run — who is better served by a completed run than one killed out from under them: -- **Tier 1 — warn, do NOT stop.** Two triggers, neither stops the run. Corrective-task escalation (**≥2** corrective tasks) fires **once** and may mean the build is struggling; emit it and send a `PushNotification` so an absent user is reached. The soft wall-clock cap is a **recurring health check-in**, firing every **~25 min** the run is still going: not a sign of trouble but a periodic, visible beat that the run is watched and progressing, which a human observer values and which forces the orchestrator to do a real state check each time. A present user can judge and `TaskStop` manually; an absent user gets a finished run. (With the build's read-only and halt-on-impossibility rules, a genuinely stuck build halts itself, so this tier means "slow, many passes, or just long," not "redesigning around the spec.") -- **Tier 2 — auto-stop.** Trips on a hard stall: **no new commit AND no transcript activity (newest `agent-*.jsonl` mtime) for >5 min**. Nothing is being accomplished, so stopping loses no progress whether the user is present or absent. Before stopping, confirm no tool is in flight (see below) — then `TaskStop` the workflow, send a `PushNotification` (an auto-stopped overnight run is exactly when an absent user needs reaching), and report what it was last doing (last commit, journal tail) and where to resume. +- **Tier 1 — warn, do NOT stop.** Two triggers; neither stops the run. Corrective-task escalation (**≥2** corrective tasks) fires **once** and may mean the build is struggling; emit it and send a `PushNotification` so an absent user is reached. The soft wall-clock cap is a **recurring health check-in**, firing every **~25 min** the run is still going. It is not a sign of trouble — it is a periodic, visible beat that the run is watched and progressing, which a human observer values and which forces the orchestrator to do a real state check each time. A present user can judge and `TaskStop` manually; an absent user gets a finished run. With the build's read-only and halt-on-impossibility rules, a genuinely stuck build halts itself — so this tier means "slow, many passes, or just long", not "redesigning around the spec". +- **Tier 2 — auto-stop.** Trips on a hard stall: **no new commit AND no transcript activity (newest `agent-*.jsonl` mtime) for >5 min**. Nothing is being accomplished, so stopping loses no progress whether the user is present or absent. Before stopping, confirm no tool is in flight (below) — then `TaskStop` the workflow, send a `PushNotification` (an auto-stopped overnight run is exactly when an absent user needs reaching), and report what it was last doing — last commit, journal tail — and where to resume. -When any line lands, first confirm before acting — a slow `sf` deploy or test run is not a hang, and transcript mtime only ticks when a tool *returns*, so a single long-running tool call looks identical to a stall. Tail the newest `agent-*.jsonl`: if its last entry is a `tool_use` with no matching `tool_result`, a tool is still running — the build is working, not stalled, so leave it alone. Emit each signal sparingly so the Monitor isn't auto-stopped for noise: the corrective-task warning fires once (a flag); the stall flag re-arms once activity resumes so a confirmed-benign stall doesn't blind the watchdog to a later real one; and the soft-cap health check-in recurs on its ~25-min interval (bump the threshold rather than flag it). The ~25-min interval keeps even a multi-hour run to a handful of beats, well under the noise-stop threshold. `TaskStop` the Monitor once the workflow's completion notification arrives so it doesn't linger. +When any line lands, confirm before acting. A slow deploy or test run is not a hang, and transcript mtime ticks only when a tool *returns* — a single long-running tool call looks identical to a stall. Tail the newest `agent-*.jsonl`: if its last entry is a `tool_use` with no matching `tool_result`, a tool is still running — the build is working, leave it alone. Emit each signal sparingly so the Monitor isn't auto-stopped for noise: the corrective-task warning fires once (a flag); the stall flag re-arms once activity resumes, so a confirmed-benign stall doesn't blind the watchdog to a later real one; the soft-cap check-in recurs on its ~25-min interval — bump the threshold rather than flag it. The ~25-min interval keeps even a multi-hour run to a handful of beats, well under the noise-stop threshold. `TaskStop` the Monitor once the workflow's completion notification arrives, so it doesn't linger. Sketch of the poll loop (adapt paths; `stat -f %m` is macOS, use `-c %Y` on Linux): @@ -100,7 +100,7 @@ Report to the user: 1. Summary — tasks completed, whether verification passed, any remaining gaps 2. Retrospective — if one was produced, present the cross-cutting patterns and suggestions 3. If incomplete — distinguish two cases: - - **Blocked on intent** — a task or the verify step reported a requirement that can't be met as specified (infeasible, self-contradictory, or only closable by changing the agreed design). The reason is usually in the friction logs of a halted task. Surface it and present it as a **decision for the user** — revise the spec or plan and re-run. Do not retry it as-is or improvise a workaround. + - **Blocked on intent** — a task or the verify step reported a requirement that can't be met as specified: infeasible, self-contradictory, or only closable by changing the agreed design. The reason is usually in a halted task's friction log. Surface it and present it as a **decision for the user** — revise the spec or plan and re-run. Do not retry it as-is or improvise a workaround. - **Mechanical gap** — work simply didn't finish. Report what landed and where to pick up (see "Resuming after failure"). Keep it concise. Don't dump raw JSON — synthesize. diff --git a/.claude/skills/plan-execution/prompts.md b/.claude/skills/plan-execution/prompts.md index 9bd4f82..d06256c 100644 --- a/.claude/skills/plan-execution/prompts.md +++ b/.claude/skills/plan-execution/prompts.md @@ -1,6 +1,6 @@ # Subagent Prompts -Prompt templates for each subagent role. The SKILL.md instructs Claude to read this file and pass the prompts via `args.prompts`. The workflow appends task-specific data (plan text, file lists, acceptance criteria, etc.) to each prompt at runtime. +Prompt templates for each subagent role. The SKILL.md instructs Claude to read this file and pass the prompts via `args.prompts`. The workflow appends task-specific data — plan text, file lists, acceptance criteria — to each prompt at runtime. --- @@ -8,29 +8,29 @@ Prompt templates for each subagent role. The SKILL.md instructs Claude to read t Decompose this implementation plan into an ordered list of steps for execution by subagents in separate git worktrees. -Each step contains one or more tasks; tasks within a step run in parallel (isolated worktrees), and steps run in order. Return steps in execution order. +Each step contains one or more tasks. Tasks within a step run in parallel, in isolated worktrees; steps run in order. Return steps in execution order. -**Favour parallelism — optimise for wall-clock.** Put tasks in the same parallel step whenever they have no real dependency on each other; the same work as three parallel batches finishes far sooner than as one sequential chain. Reserve sequential ordering (a step of its own) for a genuine dependency: a task needs a prior task's committed output, or two tasks would write the same files and conflict. +**Favour parallelism — optimise for wall-clock.** Put tasks in the same parallel step whenever they have no real dependency on each other; the same work as three parallel batches finishes far sooner than as one sequential chain. Reserve a sequential step for a genuine dependency: a task needs a prior task's committed output, or two tasks would write the same files and conflict. -**Decide the verification cadence.** The full gate suite (build, lint, static analysis, full test run) is the dominant cost of a large run — run inside every task, it pays the whole suite once per task. Distribute it deliberately: +**Decide the verification cadence.** The full gate suite — build, lint, static analysis, full test run — is the dominant cost of a large run; run inside every task, it pays the whole suite once per task. Distribute it deliberately: -- Mark ordinary feature tasks **scoped**: they run only fast checks (typecheck/compile plus the tests covering what they touched) before committing — enough not to hand broken code downstream. -- Author explicit **verification-checkpoint** tasks — a sequential step whose task runs the full gate suite against the integrated base and fixes any breakage — at natural milestones: after a parallel batch lands, at a layer boundary (e.g. server complete before client begins), and always once at the end. Checkpoint more often on a large multi-batch plan so a regression stays attributable to its batch; a small plan may need only the final one. -- State in each task which level it runs (scoped vs checkpoint). A task with no marking runs the full suite by default, so an un-marked or single-task plan is never under-verified. +- Mark ordinary feature tasks **scoped**: they run only fast checks — a typecheck/compile plus the tests covering what they touched — before committing. Enough not to hand broken code downstream. +- Author explicit **verification-checkpoint** tasks — a sequential step whose task runs the full gate suite against the integrated base and fixes any breakage — at natural milestones: after a parallel batch lands, at a layer boundary (server complete before client begins), and always once at the end. Checkpoint more often on a large multi-batch plan, so a regression stays attributable to its batch; a small plan may need only the final one. +- State in each task which level it runs, scoped or checkpoint. A task with no marking runs the full suite by default, so an un-marked or single-task plan is never under-verified. For each task, write self-contained instructions — a fresh agent with no knowledge of the plan must be able to complete the task from the description alone. Include relevant context about the codebase, conventions, and surrounding code. -**Shared-type edits ripple past the Files list.** When a task edits a type, interface, or fixture that other files consume (a shared schema, a reducer map, a common test fixture), say so in the task: expect literal/fixture updates across the repo, outside the Files list. A downstream file that won't compile against the new shape is a required edit, not scope creep. +**Shared-type edits ripple past the Files list.** When a task edits a type, interface, or fixture that other files consume — a shared schema, a reducer map, a common test fixture — say so in the task: expect literal and fixture updates across the repo, outside the Files list. A downstream file that won't compile against the new shape is a required edit, not scope creep. -**Conform to the target file's convention; don't prescribe one.** When a task names a concrete convention (a metadata element, a field or key name, a file layout), tell it to match what sibling files actually use, not a value asserted here. A prescribed value that differs from the real convention is wrong at worst, dead at best. +**Conform to the target file's convention; don't prescribe one.** When a task names a concrete convention — a metadata element, a field or key name, a file layout — tell it to match what sibling files actually use, not a value asserted here. A prescribed value that differs from the real convention is wrong at worst, dead at best. -**Attach the project's own capabilities to each task.** If a project-capability manifest is provided (or the project's skills and agents are otherwise visible to you), give each task the skills whose triggers match its files as an explicit "consult these before writing" list — the executing agent can invoke a Skill, so naming them makes it apply the house convention instead of re-deriving it. For a task that turns on where-something-belongs or whether-something-already-exists, resolve it *now* against the project's read-only research / hunter agents and bake the answer into the task description: the executing agent runs in an isolated worktree and cannot dispatch an agent of its own. Absent any such capabilities, author the task as usual. +**Attach the project's own capabilities to each task.** If a project-capability manifest is provided, or the project's skills and agents are otherwise visible to you, give each task the skills whose triggers match its files — an explicit "consult these before writing" list. The executing agent can invoke a Skill, so naming them makes it apply the house convention instead of re-deriving it. A task that turns on where-something-belongs or whether-something-already-exists is different: resolve it *now* against the project's read-only research or hunter agents and bake the answer into the task description — the executing agent runs in an isolated worktree and cannot dispatch an agent of its own. Absent any such capabilities, author the task as usual. Read the files referenced in the plan and their immediate dependencies to understand the current state before decomposing. Write each task description to `.tasks/{run-id}/{task-id}.md`, using the run ID provided below. These files are the durable record of the decomposition — they enable resuming after partial failure without re-running breakdown. Ensure `.tasks/` is in `.gitignore`. -When a task's instructions reference its own task file (or another task file), give the **absolute** path: prepend the repository root (`git rev-parse --show-toplevel`) to `.tasks/{run-id}/{task-id}.md`. `.tasks/` is gitignored, so a parallel task's worktree does not contain it. An absolute path lets a worktree agent read its instructions from the main checkout directly, with no discovery step. +When a task's instructions reference its own task file, or another task file, give the **absolute** path: prepend the repository root (`git rev-parse --show-toplevel`) to `.tasks/{run-id}/{task-id}.md`. `.tasks/` is gitignored, so a parallel task's worktree does not contain it. An absolute path lets a worktree agent read its instructions from the main checkout directly, with no discovery step. --- @@ -38,23 +38,23 @@ When a task's instructions reference its own task file (or another task file), g Execute this task in your worktree. Do NOT merge or modify other branches. -**Use the project's own conventions first.** If your task lists project skills to consult, activate them (invoke the Skill) before writing — they carry the house conventions for this kind of work, and following them now avoids a rewrite at review. Treat any research finding baked into the task (where a thing belongs, what already exists) as authoritative context about this repo. +**Use the project's own conventions first.** If your task lists project skills to consult, activate them — invoke the Skill — before writing; they carry the house conventions for this kind of work, and following them now avoids a rewrite at review. Treat any research finding baked into the task — where a thing belongs, what already exists — as authoritative context about this repo. The plan and spec are authoritative — treat them as read-only. Never edit them, and never redesign around them to force your task to pass. If the task is impossible as written — the plan contradicts itself or the spec, an acceptance criterion is technically infeasible, or completing it would require changing the agreed design — stop. Commit nothing, and report plainly what is blocked, why, and what decision is needed. Halting lets a human revise the spec or plan; a silently improvised workaround corrupts both. -Before committing, run the verification level your task specifies. If the task marks itself **scoped**, run only fast checks — a typecheck/compile plus the tests covering what you touched. If it marks itself a **verification checkpoint**, or gives no marking, run the project's full gate suite (build, lint, static analysis, tests) as documented in CLAUDE.md and fix any breakage — a checkpoint's footprint is the whole integrated base, so it may repair regressions wherever they surface, not only in files it introduced. Either way, never hand broken code downstream. If CLAUDE.md documents no verification tools, note this under `suggestions` in your friction log. +Before committing, run the verification level your task specifies. If the task marks itself **scoped**, run only fast checks: a typecheck/compile plus the tests covering what you touched. If it marks itself a **verification checkpoint**, or gives no marking, run the project's full gate suite — build, lint, static analysis, tests — as documented in CLAUDE.md and fix any breakage. A checkpoint's footprint is the whole integrated base, so it may repair regressions wherever they surface, not only in files it introduced. Either way, never hand broken code downstream. If CLAUDE.md documents no verification tools, note this under `suggestions` in your friction log. -When satisfying an enforced completion gate forces violating a softer CLAUDE.md preference, satisfy the gate and log the friction. An enforced gate is a rule whose violation blocks "done" — a failing lint / static-analysis check or a required test. If the only way to clear it conflicts with a CLAUDE.md *style or aesthetic* preference (e.g. a rule requiring doc comments vs. "comment only the non-obvious"), clear the gate and record the trade under `harder_than_expected` in your friction log. This carve-out is for style preferences only: an enforced gate must never override a CLAUDE.md *safety or correctness* rule (e.g. "never log PII") — there, stop and report it as a blocker rather than complying. +When satisfying an enforced completion gate forces violating a softer CLAUDE.md preference, satisfy the gate and log the friction. An enforced gate is a rule whose violation blocks "done": a failing lint or static-analysis check, a required test. If the only way to clear it conflicts with a CLAUDE.md *style or aesthetic* preference — say, a rule requiring doc comments versus "comment only the non-obvious" — clear the gate and record the trade under `harder_than_expected` in your friction log. This carve-out covers style preferences only. An enforced gate must never override a CLAUDE.md *safety or correctness* rule, such as "never log PII" — there, stop and report it as a blocker rather than complying. -Stay within your task's footprint: only create or modify files your task requires. When running a formatter or autofixer, scope it to the files you touched — prefer the project's *verify*/*check* command over a repo-wide *write*. A whole-repo formatter run reformats unrelated files and pollutes the diff; if one does so, revert the unrelated changes before committing. Commit only the files belonging to your task. +Stay within your task's footprint: create or modify only files your task requires. When running a formatter or autofixer, scope it to the files you touched — prefer the project's *verify*/*check* command over a repo-wide *write*. A whole-repo formatter run reformats unrelated files and pollutes the diff; if one does, revert the unrelated changes before committing. Commit only the files belonging to your task. When done, commit all changes. Note your branch name (`git branch --show-current`) and commit hash (`git rev-parse HEAD`). -You do not need to return a structured result — a concise prose report is enough. The orchestrator confirms what landed from git state, so the one thing that matters is that your work is **committed**. Include a friction log in your report with three fields: +You do not need to return a structured result — a concise prose report is enough. The orchestrator confirms what landed from git state, so the one thing that matters is that your work is **committed**. Include a friction log with three fields: - **harder_than_expected** — anything that took more effort or was more complex than the task description suggested - **wrong_turns** — approaches you tried that didn't work, and why -- **suggestions** — what would have made this task easier (better instructions, missing context, tooling gaps) +- **suggestions** — what would have made this task easier: better instructions, missing context, tooling gaps --- @@ -70,7 +70,7 @@ Steps: 4. Verify the project builds 5. `git commit -m ": "` -Do not delete the task branch or remove its worktree — the workflow owns that teardown after the run (it removes the worktree first, then deletes the branch). Running `git branch -D` here while the task's worktree is still live makes git refuse ("cannot delete branch ... used by worktree") and fails the integration. +Do not delete the task branch or remove its worktree — the workflow owns that teardown after the run; it removes the worktree first, then deletes the branch. Running `git branch -D` here while the task's worktree is still live makes git refuse ("cannot delete branch ... used by worktree") and fails the integration. If the build fails after merge, run `git reset --hard HEAD` to restore the base branch, then report failure. @@ -87,12 +87,12 @@ Steps: 3. For each, find concrete evidence: a file, function, test, or config change 4. Deliverables without evidence are gaps 5. Classify each gap before acting on it: - - **Fillable gap** — missing or incomplete work an agent can finish _within the agreed spec and plan_. Define a corrective task with full self-contained instructions. - - **Blocked requirement** — the deliverable cannot be met as specified: the plan contradicts itself or the spec, an acceptance criterion is technically infeasible on this platform, or closing the gap would require changing the agreed design. The execute agents' friction logs are a primary signal (a task that halted as impossible), alongside your own analysis. + - **Fillable gap** — missing or incomplete work an agent can finish *within the agreed spec and plan*. Define a corrective task with full self-contained instructions. + - **Blocked requirement** — the deliverable cannot be met as specified: the plan contradicts itself or the spec, an acceptance criterion is technically infeasible on this platform, or closing the gap would require changing the agreed design. The execute agents' friction logs are a primary signal — a task that halted as impossible — alongside your own analysis. -Corrective tasks may only fill gaps **within the agreed design**. Never author a corrective task that redesigns, "replaces the mechanism," works around the spec, or edits the spec/plan to make a deliverable pass — that is the build improvising around intent, the exact failure this guard prevents. +Corrective tasks may only fill gaps **within the agreed design**. Never author a corrective task that redesigns, "replaces the mechanism", works around the spec, or edits the spec or plan to make a deliverable pass. That is the build improvising around intent — the exact failure this guard prevents. -For a blocked requirement: mark the deliverable a gap, define **no** corrective task for it, and state the blocking reason and the decision the human must make in that deliverable's `evidence`. With no corrective task to run, the loop ends and the run reports incomplete — routing the decision back to a human to revise the spec or plan and re-run. That is the correct outcome; do not manufacture a corrective task to avoid it. +For a blocked requirement: mark the deliverable a gap, define **no** corrective task, and state the blocking reason and the decision the human must make in that deliverable's `evidence`. With no corrective task to run, the loop ends and the run reports incomplete — routing the decision back to a human to revise the spec or plan and re-run. That is the correct outcome; do not manufacture a corrective task to avoid it. This is a gap check, not a quality review. @@ -102,8 +102,8 @@ This is a gap check, not a quality review. Synthesize friction logs from a multi-task execution run into a retrospective. -Focus on cross-cutting patterns: repeated struggles, systemic plan gaps, friction a skill or CLAUDE.md update could eliminate. Note positives too. Individual one-off difficulties: mention briefly. +Focus on cross-cutting patterns: repeated struggles, systemic plan gaps, friction a skill or CLAUDE.md update could eliminate. Note positives too. Mention individual one-off difficulties briefly. -Collect any finding that points at a project-level doc gap (a CLAUDE.md convention worth adding, an ADR worth capturing, a stale reference) under a final `## Repo-doc suggestions (CLAUDE.md / ADR)` heading, so the orchestrator can surface them at wrap-up. +Collect any finding that points at a project-level doc gap — a CLAUDE.md convention worth adding, an ADR worth capturing, a stale reference — under a final `## Repo-doc suggestions (CLAUDE.md / ADR)` heading, so the orchestrator can surface them at wrap-up. Be concise and actionable.