The coupling to Claude Code's built-in run skill (wave 4, order A2, decisions 54 and 64). The plan's "run the thing" step, the executor's End to end part and the plan template each say in one sentence that the app is seen and driven with run, and that the verdict is still the End-to-end: command, because run gives no exit code. The template quotes the name instead of backticking it: every backticked span on a template step bullet is read as a runnable example. R2: lib/skills/routing.mjs keeps a short fixed list of Claude Code's own skills a quiet case may name as owner (BUILTIN_OWNERS, only run, seen in 2.1.303). For such an owner only "not taken" is checked, and the report says so; ROUTING_NEGATIVE_WON stands, and an owner on no list is still ROUTING_UNKNOWN_OWNER. skill-writing-criteria-quiet-2 gets owner=run. The trekplan.md paragraph is reflowed to its old line count so the stats line_ref there does not move (order B edits the same file); the trekexecute Phase 9 line_ref fixture moves by two lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
326 lines
14 KiB
Markdown
326 lines
14 KiB
Markdown
<!--
|
||
Optional YAML frontmatter — include ONLY when the plan was generated from a
|
||
`type: trekreview` input (Handover 6). Lists the 40-char hex IDs of the
|
||
BLOCKER + MAJOR findings consumed from `review.md`. Use block-style YAML;
|
||
the frontmatter parser does not support flow-style arrays.
|
||
|
||
Plans generated from a `type: brief` input omit this block entirely. No
|
||
plan_version bump — the field is additive and backwards compatible.
|
||
|
||
---
|
||
source_findings:
|
||
- 0123456789abcdef0123456789abcdef01234567
|
||
- fedcba9876543210fedcba9876543210fedcba98
|
||
---
|
||
-->
|
||
|
||
# {Task Title}
|
||
|
||
> **Plan quality: {grade}** ({score}/100) — {APPROVE | APPROVE_WITH_NOTES | REVISE | REPLAN}
|
||
>
|
||
> Generated by trekplan v{version} on {YYYY-MM-DD} — `plan_version: 1.9` · `ceremony: {small | bounded | architectural}`
|
||
|
||
## Context
|
||
|
||
Why this change is needed. The problem or need it addresses, what prompted it,
|
||
and the intended outcome. Reference the spec file if one was used.
|
||
|
||
## Global Constraints
|
||
|
||
The brief's Constraints and Non-Functional Requirements that bind more than one
|
||
step, **quoted verbatim** — exact values, never paraphrased. A step that could
|
||
break one quotes it again in its `Review focus:`.
|
||
|
||
- > "{constraint, verbatim from the brief}" — brief § Constraints
|
||
|
||
<!-- ceremony: architectural (or absent) → insert the design part here, from
|
||
templates/design-template.md (## Design). small | bounded → omit it. -->
|
||
|
||
## Architecture Diagram
|
||
|
||
```mermaid
|
||
graph TD
|
||
subgraph "Changes in this plan"
|
||
%% C4-style component diagram showing what the plan touches
|
||
%% Highlight modified components, new components, and connections
|
||
end
|
||
```
|
||
|
||
*Replace with actual Mermaid diagram showing the components this plan modifies,
|
||
their relationships, and the data flow between them.*
|
||
|
||
## Codebase Analysis
|
||
|
||
- **Tech stack:** {languages, frameworks, build tools}
|
||
- **Key patterns:** {architecture patterns, conventions observed}
|
||
- **Relevant files:** {paths to files that will be read or modified}
|
||
- **Reusable code:** {existing functions, utilities, abstractions to leverage}
|
||
- **External tech (researched):** {technologies that were looked up via research-scout}
|
||
- **Recent git activity:** {relevant recent commits, active branches, code ownership}
|
||
|
||
## Research Sources
|
||
|
||
*Omit this section when no external research was conducted.*
|
||
|
||
| Technology | Source | Key Findings | Confidence |
|
||
|-----------|--------|--------------|------------|
|
||
| {name} | {URL} | {summary} | {high/med/low} |
|
||
|
||
## Implementation Plan
|
||
|
||
Each step targets 1–2 files and one focused change, and is a vertical slice:
|
||
a narrow but complete path through every layer it touches, verifiable on its
|
||
own. Preparatory refactoring comes first, as its own steps. Every step has
|
||
`Test first:` (plan_version 1.8 or later requires it), and one step runs the thing
|
||
end to end (`End-to-end:`). The test for a behaviour belongs in the step that
|
||
builds it: a step of only tests for behaviour an earlier step delivered passes
|
||
at its start point and can never be proven red (the validator warns:
|
||
`PLAN_STEP_TESTS_ONLY`). So `End-to-end:` rides on the last step that builds
|
||
behaviour, with its script in that step's `Files:`, not on a step of its own.
|
||
|
||
Optional per-step fields: `Interface in:` (what the step consumes, and which
|
||
earlier step or existing code produces it), `Interface out:` (what it produces
|
||
for later steps), `Review focus:` (inputs the brief implies but no test
|
||
exercises yet, each pinned to a test; and any Global Constraint the step could
|
||
break, quoted verbatim), and `Regression:` (ONE backticked command — usually
|
||
`npm test` — that the executor runs green before the checkpoint, on a step that
|
||
can break existing tests; `Verify:` stays the step's own red-first test).
|
||
Every `Verify:`, `Regression:`, `End-to-end:` and `## Verification` command is
|
||
written by the `voyage:writing-criteria` skill: one command the criteria runner
|
||
accepts, a script under `tests/` for anything more, and able to go red. A field that is present is
|
||
never empty. `On failure:` opens with `revert`, `retry`, `skip` or `escalate`,
|
||
then the specifics.
|
||
|
||
From plan_version 1.9 the rule is the file first on every line: each `Files:`
|
||
entry and each `Test first:` `File:` line opens with its backticked path(s),
|
||
separated only by commas or spaces, and everything after the first other text
|
||
is description that is never read. A 1.9 step always names a file
|
||
(the bare word none or an empty `Files:` is refused). A line that is no list item
|
||
continues the entry above it (a list wrapped after a comma keeps its paths;
|
||
once the entry so far does not end with a comma, the wrapped line is description;
|
||
a `File:` line with nothing after it takes its first wrapped line),
|
||
the `File:` line may open with `1.` or `1)` and any list item ends it, and
|
||
a backticked placeholder (`TBD`, `TODO`, `TBA`, `N/A`, `NA`, `none`, `...`) or a
|
||
mixed-case bare name (`Parser`) is no path, so write `./Name` for such a file. In `Files:`,
|
||
every path stands before any annotation: `` `src/a.mjs`, `src/b.mjs` (new) ``,
|
||
never `` `src/a.mjs` (new), `src/b.mjs` `` (in 1.9 that second path is
|
||
description).
|
||
Several test files share one `File:` line the same way:
|
||
`` File: `a.test.mjs`, `b.test.mjs` *(new)* ``.
|
||
|
||
### Step 1: {description}
|
||
|
||
- **Files:** `path/to/file.ts`
|
||
- **Changes:** {exactly what to modify — no placeholders, no "update as needed"}
|
||
- **Reuses:** {existing function/pattern from codebase, with file path}
|
||
- **Interface out:** `{name(args) → result}` — read by Step 2
|
||
- **Review focus:** {untested input the brief implies} — pinned by `path/to/test.ts`
|
||
- **Test first:**
|
||
- File: `path/to/test.ts` *(existing | new)*
|
||
- Verifies: {what the test checks}
|
||
- Pattern: `path/to/existing-test.ts` *(follow this style)*
|
||
- **Verify:** `{exact command}` → expected: `{output}`
|
||
- **Regression:** `npm test` → expected: exit 0 *(optional)*
|
||
- **On failure:** {revert | retry | skip | escalate} — {specific instructions}
|
||
- **Checkpoint:** `git add {the step's Files and its test files} && git commit -m "{conventional commit message}"`
|
||
- **Manifest:**
|
||
```yaml
|
||
manifest:
|
||
expected_paths:
|
||
- path/to/file.ts
|
||
min_file_count: 1
|
||
commit_message_pattern: "^feat\\(scope\\):"
|
||
bash_syntax_check: []
|
||
forbidden_paths: []
|
||
must_contain: []
|
||
```
|
||
|
||
### Step 2: {description — the "run the thing" step}
|
||
|
||
- **Files:** `path/to/file.ts`
|
||
- **Changes:** {exactly what to modify}
|
||
- **Reuses:** {existing function/pattern}
|
||
- **Interface in:** `{name(args) → result}` from Step 1
|
||
- **Test first:**
|
||
- File: `path/to/test.ts` *(existing | new)*
|
||
- Verifies: {what the test checks}
|
||
- Pattern: `path/to/existing-test.ts`
|
||
- **End-to-end:** `{a script that runs the product the way a user does — the app, the CLI, the simulator; usually bash tests/e2e.sh}` → expected: {what the user sees} *(the same command also stands under ## Verification; to see and drive the app, use Claude Code's built-in "run" skill — the verdict is still the End-to-end: command, because "run" gives no exit code)*
|
||
- **Verify:** `{exact command}` → expected: `{output}`
|
||
- **On failure:** {revert | retry | skip | escalate} — {specific instructions}
|
||
- **Checkpoint:** `git add {the step's Files and its test files} && git commit -m "{conventional commit message}"`
|
||
- **Manifest:**
|
||
```yaml
|
||
manifest:
|
||
expected_paths:
|
||
- path/to/file.ts
|
||
min_file_count: 1
|
||
commit_message_pattern: "^feat\\(scope\\):"
|
||
bash_syntax_check: []
|
||
forbidden_paths: []
|
||
must_contain:
|
||
- path: path/to/file.ts
|
||
pattern: "expected content marker"
|
||
```
|
||
|
||
*A project without tests still gets `Test first:` on every step: the first step
|
||
adds the test runner (or a script under `tests/`) the later steps use. A plan
|
||
without an `End-to-end:` step is invalid at plan_version 1.8 or later — without
|
||
it the result can only be "not verified end to end", never green.*
|
||
|
||
### Manifest — objective completion predicate
|
||
|
||
Every step MUST have a Manifest block. This is the machine-checkable contract
|
||
that trekexecute verifies after the Verify command passes. A step is
|
||
not considered complete until its manifest verifies — regardless of Verify
|
||
command exit code.
|
||
|
||
- **expected_paths** — files that must exist after this step. Existing files
|
||
must be present in repo; new files must be marked `(new file)` in prose.
|
||
- **min_file_count** — minimum number of expected_paths that must exist.
|
||
Typically equal to `len(expected_paths)`.
|
||
- **commit_message_pattern** — regex that MUST match the HEAD commit message
|
||
after Checkpoint runs. Use escaped regex syntax (e.g., `\\(scope\\)`).
|
||
- **bash_syntax_check** — list of `.sh` files that must pass `bash -n`.
|
||
Auto-include any `.sh` in expected_paths.
|
||
- **forbidden_paths** — files this step must NOT modify (defense-in-depth
|
||
beyond Scope Fence).
|
||
- **must_contain** — optional grep assertions: `path` + `pattern` pairs that
|
||
must match in created/modified files.
|
||
|
||
### Failure recovery rules
|
||
|
||
- **On failure: revert** — undo this step's changes (`git checkout -- {files}`), do NOT proceed
|
||
- **On failure: retry** — attempt once more with the alternative approach described, then revert if still failing
|
||
- **On failure: skip** — this step is non-critical; continue to next step and note the skip
|
||
- **On failure: escalate** — stop execution entirely; the issue requires human judgment
|
||
- **Checkpoint** — after each step succeeds, commit changes so subsequent failures cannot corrupt completed work
|
||
|
||
## Alternatives Considered
|
||
|
||
| Approach | Pros | Cons | Why rejected |
|
||
|----------|------|------|--------------|
|
||
| {name} | ... | ... | ... |
|
||
|
||
## Test Strategy
|
||
|
||
- **Framework:** {test framework and runner}
|
||
- **Existing patterns:** {how tests are structured in this codebase}
|
||
- **New tests in this plan:** {N} tests across {N} steps
|
||
|
||
### Tests to write
|
||
|
||
| Type | File | Verifies | Model test |
|
||
|------|------|----------|------------|
|
||
| Unit | `path/to/test` | {what it tests} | `path/to/existing-test` |
|
||
|
||
*For projects without tests: describe manual verification approach instead.*
|
||
|
||
## Risks and Mitigations
|
||
|
||
| Priority | Risk | Location | Impact | Mitigation |
|
||
|----------|------|----------|--------|------------|
|
||
| {Critical/High/Medium/Low} | {description} | `file:line` | {what happens} | {how to handle} |
|
||
|
||
## Assumptions
|
||
|
||
*Things the planner could not verify from codebase or research. Each assumption
|
||
is a risk — review before executing.*
|
||
|
||
| # | Assumption | Why unverifiable | Impact if wrong |
|
||
|---|-----------|-----------------|-----------------|
|
||
| 1 | {what we assumed} | {why we couldn't check} | {what breaks} |
|
||
|
||
*If this list has 3+ items, the plan may need additional investigation
|
||
before execution.*
|
||
|
||
## Verification
|
||
|
||
*Per-step manifest verification runs automatically during execution (every
|
||
step's Manifest block is objectively checked by trekexecute before the
|
||
step is marked passed). This section is for end-to-end integration checks
|
||
that cross step boundaries — complete workflows, system-level behavior.*
|
||
|
||
- [ ] `{exact command}` → expected: `{exact output or behavior}`
|
||
- [ ] `{exact command}` → expected: `{exact output or behavior}`
|
||
|
||
## Estimated Scope
|
||
|
||
- **Files to modify:** {N}
|
||
- **Files to create:** {N}
|
||
- **Complexity:** {low | medium | high}
|
||
|
||
## Execution Strategy
|
||
|
||
*Include this section when the plan has more than 5 implementation steps.
|
||
Omit for small plans (≤ 5 steps) — trekexecute will run them sequentially
|
||
in a single session.*
|
||
|
||
*The execution strategy groups steps into sessions and organizes sessions
|
||
into waves. Sessions in the same wave can run in parallel. Sessions in
|
||
later waves depend on earlier waves completing first.*
|
||
|
||
### Session 1: {title}
|
||
- **Steps:** {step numbers, e.g., 1, 2, 3}
|
||
- **Wave:** {wave number}
|
||
- **Depends on:** {session numbers, or "none"}
|
||
- **Scope fence:**
|
||
- Touch: {files this session may modify}
|
||
- Never touch: {files reserved for other sessions}
|
||
|
||
### Session 2: {title}
|
||
- **Steps:** {step numbers}
|
||
- **Wave:** {wave number}
|
||
- **Depends on:** {session numbers, or "none"}
|
||
- **Scope fence:**
|
||
- Touch: {files}
|
||
- Never touch: {files}
|
||
|
||
### Execution Order
|
||
|
||
- **Wave 1:** {session list} (parallel)
|
||
- **Wave 2:** {session list} (after Wave 1)
|
||
|
||
### Grouping rules applied
|
||
|
||
- Steps sharing files → same session
|
||
- Steps in independent modules → separate sessions (parallelizable)
|
||
- 3–5 steps per session (target)
|
||
- Sessions ordered by dependency, waves by independence
|
||
|
||
## Plan Quality Score
|
||
|
||
| Dimension | Weight | Score | Notes |
|
||
|-----------|--------|-------|-------|
|
||
| Structural integrity | 0.15 | {0–100} | {step ordering, dependencies} |
|
||
| Step quality | 0.20 | {0–100} | {granularity, specificity, TDD} |
|
||
| Coverage completeness | 0.20 | {0–100} | {spec → steps, no gaps} |
|
||
| Specification quality | 0.15 | {0–100} | {no placeholders, clear criteria} |
|
||
| Risk & pre-mortem | 0.15 | {0–100} | {failure modes addressed} |
|
||
| Headless readiness | 0.10 | {0–100} | {On failure + Checkpoint per step} |
|
||
| Manifest quality | 0.05 | {0–100} | {all steps have valid, checkable manifests} |
|
||
| **Weighted total** | **1.00** | **{score}** | **Grade: {A/B/C/D}** |
|
||
|
||
**Adversarial review:**
|
||
- **Plan critic:** {verdict — findings count by severity, key issues}
|
||
- **Scope guardian:** {verdict — ALIGNED / CREEP / GAP / MIXED}
|
||
|
||
## Revisions
|
||
|
||
*Added by adversarial review. Omit if no revisions were needed.*
|
||
|
||
| # | Finding | Severity | Resolution |
|
||
|---|---------|----------|------------|
|
||
| 1 | {what was wrong} | {blocker/major/minor} | {how it was fixed} |
|
||
|
||
<!-- ## Critic Verdict — do NOT write this section. `lib/validators/plan-gate.mjs
|
||
--record` appends it after the first critic round (Phase 9) and replaces it on
|
||
each later round: one fenced json block with round, max_rounds, plan_sha256
|
||
(the plan minus its review log), verdict BLOCK | REVISE | PASS, and the
|
||
deduplicated findings. It may also carry the optional rule-A and rule-B
|
||
fields (DIFF_FIELDS in lib/review/critic-diff.mjs: diff_base, diff_note,
|
||
resolved, and per finding op_line, op_line_end, line_end, rule_keys,
|
||
original_severity, lowered_by, caught_by, lowering_refused, carried_from);
|
||
absent means round-1 behaviour. `plan-gate.mjs <plan>` exits 0 only when the
|
||
plan validates, the block matches the current plan, no BLOCKER is open, and
|
||
every open MAJOR was accepted by the operator. -->
|