From 7c1eb0e31d9e04b9af403145c65f5eb522310445 Mon Sep 17 00:00:00 2001 From: Jose Alekhinne Date: Fri, 3 Jul 2026 18:19:22 -0700 Subject: [PATCH 1/3] add /ctx-task-out: close the spec-to-implement gap in the canonical chain The design-to-implementation chain had an unowned artifact: /ctx-plan disclaims implementation planning, /ctx-spec commits the what/why at spec altitude, and /ctx-implement opens with "use when you have a plan document" that nothing in the chain produced. /ctx-task-out decomposes a committed spec into a per-milestone plan at specs/plans/.md - data model, contracts, invariant test matrix, and commit-sized tasks with falsifiable acceptance criteria - and enforces refusal gates instead of degrading: blocking-TBD, rolling-wave, and milestone boundaries owned by the spec. The plan is the execution ledger; TASKS.md carries epic anchors only. Changes: - new skill (claude + copilot-cli parity), registered in the permissions allowlist and init workflow tips - chain diagrams updated to 5 steps across skills, playbook templates, and docs - /ctx-spec gains the tasking handoff in interactive and --brief flows; /ctx-implement names the plan artifact, redirects bare multi-milestone specs, refuses Status: Blocked plans, and owns plan checkbox updates - project template specs-README lifecycle gains the task-out step - docs: skills reference (including the missing /ctx-plan section and its dead anchor), common-workflows, integrations, recipes Spec: specs/ctx-task-out.md Signed-off-by: Jose Alekhinne --- docs/home/common-workflows.md | 1 + docs/operations/integrations.md | 1 + docs/recipes/design-before-coding.md | 65 ++++-- docs/recipes/index.md | 6 +- docs/recipes/scrutinizing-a-plan.md | 14 +- docs/reference/skills.md | 83 ++++++- .../claude/skills/ctx-implement/SKILL.md | 28 ++- .../assets/claude/skills/ctx-plan/SKILL.md | 7 +- .../assets/claude/skills/ctx-spec/SKILL.md | 20 +- .../claude/skills/ctx-task-out/SKILL.md | 210 ++++++++++++++++++ internal/assets/commands/text/write.yaml | 1 + internal/assets/context/AGENT_PLAYBOOK.md | 4 +- .../assets/context/AGENT_PLAYBOOK_GATE.md | 10 +- .../copilot-cli/skills/ctx-implement/SKILL.md | 28 ++- .../copilot-cli/skills/ctx-spec/SKILL.md | 20 +- .../copilot-cli/skills/ctx-task-out/SKILL.md | 210 ++++++++++++++++++ internal/assets/permissions/allow.txt | 1 + internal/assets/project/specs-README.md | 7 +- specs/ctx-task-out.md | 120 ++++++++++ 19 files changed, 788 insertions(+), 48 deletions(-) create mode 100644 internal/assets/claude/skills/ctx-task-out/SKILL.md create mode 100644 internal/assets/integrations/copilot-cli/skills/ctx-task-out/SKILL.md create mode 100644 specs/ctx-task-out.md diff --git a/docs/home/common-workflows.md b/docs/home/common-workflows.md index 9504843da..e42a1af55 100644 --- a/docs/home/common-workflows.md +++ b/docs/home/common-workflows.md @@ -355,6 +355,7 @@ These have no CLI equivalent. They require the agent's reasoning. | `/ctx-prompt-audit` | Analyze prompting patterns for improvement | | `/ctx-plan` | Stress-test an existing plan through adversarial interview | | `/ctx-plan-import` | Import Claude Code plan files into project specs | +| `/ctx-task-out` | Decompose a committed spec into a per-milestone implementation plan | | `/ctx-implement` | Execute a plan step-by-step with verification | | `/ctx-worktree` | Manage parallel agent worktrees | | `/ctx-journal-enrich` | Add metadata, tags, and summaries to journal entries | diff --git a/docs/operations/integrations.md b/docs/operations/integrations.md index 5dc1a64d1..309c98b5c 100644 --- a/docs/operations/integrations.md +++ b/docs/operations/integrations.md @@ -321,6 +321,7 @@ These are invoked in Claude Code with `/skill-name`. | Skill | Description | |---------------------|--------------------------------------------------| | `/ctx-loop` | Generate a Ralph Loop iteration script | +| `/ctx-task-out` | Decompose a committed spec into a milestone plan | | `/ctx-implement` | Execute a plan step-by-step with checks | | `/ctx-plan-import` | Import Claude Code plan files into project specs | | `/ctx-worktree` | Manage git worktrees for parallel agents | diff --git a/docs/recipes/design-before-coding.md b/docs/recipes/design-before-coding.md index 9826a348d..f19043431 100644 --- a/docs/recipes/design-before-coding.md +++ b/docs/recipes/design-before-coding.md @@ -23,22 +23,25 @@ the next session has no idea why things are shaped this way. ```text /ctx-brainstorm # explore the design space /ctx-spec # write the spec document -/ctx-task-add # break it into tasks +/ctx-task-out # decompose into a milestone plan /ctx-implement # execute step-by-step ``` Four skills, used in sequence. Each produces an artifact that feeds -the next. +the next. For specs small enough to implement in one session, the +spec doubles as the plan: skip `/ctx-task-out` and break the work +into TASKS.md entries with `/ctx-task-add` instead. ## Commands and Skills Used -| Tool | Type | Purpose | -|---------------------|-------|-------------------------------------------------| -| `/ctx-brainstorm` | Skill | Structured design dialogue: explore approaches | -| `/ctx-spec` | Skill | Scaffold and fill out a spec from the template | -| `/ctx-task-add` | Skill | Add implementation tasks to TASKS.md | -| `/ctx-implement` | Skill | Execute a plan step-by-step with verification | -| `/ctx-decision-add` | Skill | Record design choices made during brainstorming | +| Tool | Type | Purpose | +|---------------------|-------|----------------------------------------------------| +| `/ctx-brainstorm` | Skill | Structured design dialogue: explore approaches | +| `/ctx-spec` | Skill | Scaffold and fill out a spec from the template | +| `/ctx-task-out` | Skill | Decompose a spec into `specs/plans/.md` | +| `/ctx-task-add` | Skill | Add implementation tasks to TASKS.md | +| `/ctx-implement` | Skill | Execute a plan step-by-step with verification | +| `/ctx-decision-add` | Skill | Record design choices made during brainstorming | ## The Workflow @@ -109,9 +112,10 @@ and won't accept "none" without a challenge. Sections that don't apply can be skipped. The result is a complete spec at `specs/{feature-name}.md`. -### Step 3: Break into Tasks +### Step 3: Task Out the Work -After the spec is written, the skill offers to create tasks: +After the spec is written, the skill routes by size. A small, +single-session spec gets tasks in TASKS.md directly: ```text Agent: "Spec written to specs/rss-feed.md. Want me to break this @@ -133,11 +137,37 @@ Each task is independently completable and references the spec via You can also invoke `/ctx-task-add` directly at any point to add individual tasks. +A spec that spans multiple milestones (or more than about one +session of implementation) gets `/ctx-task-out` instead: + +```text +You: /ctx-task-out --spec specs/v1-substrate.md --milestone m0a + +Agent: "Open questions check: D-001 (language choice) is blocking + for m0a — three tasks would embed an assumption about its + answer. Resolve it before I decompose." + +You: [resolves D-001 in the spec] + +Agent: [writes specs/plans/m0a.md: data model, contracts, test + matrix, 24 tasks with falsifiable acceptance criteria] + "Plan written. TASKS.md gained 4 epic anchors, each + annotated Plan: specs/plans/m0a.md." +``` + +The plan document owns the fine-grained tasks; TASKS.md carries +epic-level anchors only. Two hard gates apply: decomposition +refuses to run past a blocking open question in the spec, and +milestone N+1 is not tasked out while milestone N's definition of +done is unmet. + ### Step 4: Implement Step-by-Step -Pick up tasks with `/ctx-implement`. The skill loads the spec, breaks -work into atomic steps, and checkpoints after every 3-5 steps with -a build and test verification: +Pick up the work with `/ctx-implement`. The skill loads the plan — +`specs/plans/.md` when `/ctx-task-out` produced one, the +spec itself for small features — breaks it into atomic steps, and +checkpoints after every 3-5 steps with a build and test +verification: ```text You: /ctx-implement (specs/rss-feed.md) @@ -164,7 +194,7 @@ Not every feature needs all four steps. Use your judgment: |----------------------------------------|--------------------| | Vague idea, multiple valid approaches | Step 1: Brainstorm | | Clear approach, need to document it | Step 2: Spec | -| Spec already exists, need to plan work | Step 3: Tasks | +| Spec already exists, need to plan work | Step 3: Task out | | Tasks exist, ready to code | Step 4: Implement | A brainstorm without a spec is fine for small decisions. A spec without @@ -180,6 +210,7 @@ You don't need skill names. Natural language works: | "Let's think through this feature" | `/ctx-brainstorm` | | "Spec this out" | `/ctx-spec` | | "Write a design doc for..." | `/ctx-spec` | +| "Task this out" | `/ctx-task-out` | | "Break this into tasks" | `/ctx-task-add` | | "Implement the spec" | `/ctx-implement` | | "Let's design before we build" | Starts at brainstorm | @@ -209,8 +240,12 @@ You don't need skill names. Natural language works: structured design dialogue * [Skills Reference: /ctx-spec](../reference/skills.md#ctx-spec): spec scaffolding from template +* [Skills Reference: /ctx-task-out](../reference/skills.md#ctx-task-out): + spec decomposition into a per-milestone plan * [Skills Reference: /ctx-implement](../reference/skills.md#ctx-implement): step-by-step execution with verification +* [Scrutinizing a Plan](scrutinizing-a-plan.md): the adversarial + interview that belongs between brainstorm and spec * [Tracking Work Across Sessions](task-management.md): task lifecycle and archival * [Importing Claude Code Plans](import-plans.md): turning ephemeral plans diff --git a/docs/recipes/index.md b/docs/recipes/index.md index a1ddaeae5..746ed752a 100644 --- a/docs/recipes/index.md +++ b/docs/recipes/index.md @@ -355,11 +355,11 @@ optionally create tasks referencing each imported spec. ### [Design Before Coding](design-before-coding.md) Front-load design with a four-skill chain: **brainstorm** the approach, -**spec** the design, **task** the work, **implement** step-by-step. +**spec** the design, **task out** the work, **implement** step-by-step. Each step produces an artifact that feeds the next. -**Uses**: `/ctx-brainstorm`, `/ctx-spec`, `/ctx-task-add`, -`/ctx-implement`, `/ctx-decision-add` +**Uses**: `/ctx-brainstorm`, `/ctx-spec`, `/ctx-task-out`, +`/ctx-task-add`, `/ctx-implement`, `/ctx-decision-add` --- diff --git a/docs/recipes/scrutinizing-a-plan.md b/docs/recipes/scrutinizing-a-plan.md index c5a555819..e4d251359 100644 --- a/docs/recipes/scrutinizing-a-plan.md +++ b/docs/recipes/scrutinizing-a-plan.md @@ -78,10 +78,16 @@ alternatives have a recall trigger. ## Output -`/ctx-plan` produces a clearer plan, not a document. Persist the -deltas via: - -- **`/ctx-spec`** if the conclusions belong in a feature spec. +`/ctx-plan` concludes by offering to write a *debated brief* to +`.context/briefs/-.md`: the bet, the rejections, the +failure modes, the validation route, and the unwind cost, in your +words. It deliberately does **not** produce an implementation plan +or a task list — decomposition happens after the spec, via +`/ctx-task-out`. Feed the interview's conclusions forward via: + +- **`/ctx-spec --brief `** to absorb the brief into a + committed spec; multi-milestone specs then flow to + `/ctx-task-out` for decomposition. - **`/ctx-decision-add`** if a tradeoff resolved into an architectural decision. - **`/ctx-learning-add`** if you discovered a project-specific diff --git a/docs/reference/skills.md b/docs/reference/skills.md index 8e449d756..2dbc4811c 100644 --- a/docs/reference/skills.md +++ b/docs/reference/skills.md @@ -64,7 +64,9 @@ opinionated behavior on top. | [`/ctx-link-check`](#ctx-link-check) | Audit docs for dead internal and external links | user-invocable | | [`/ctx-permission-sanitize`](#ctx-permission-sanitize) | Audit Claude Code permissions for security risks | user-invocable | | [`/ctx-brainstorm`](#ctx-brainstorm) | Structured design dialogue before implementation | user-invocable | +| [`/ctx-plan`](#ctx-plan) | Stress-test a plan through adversarial interview | user-invocable | | [`/ctx-spec`](#ctx-spec) | Scaffold a feature spec from a project template | user-invocable | +| [`/ctx-task-out`](#ctx-task-out) | Decompose a committed spec into a per-milestone plan | user-invocable | | [`/ctx-plan-import`](#ctx-plan-import) | Import Claude Code plan files into project specs | user-invocable | | [`/ctx-implement`](#ctx-implement) | Execute a plan step-by-step with verification | user-invocable | | [`/ctx-loop`](#ctx-loop) | Generate autonomous loop script | user-invocable | @@ -477,6 +479,33 @@ stress-test the chosen approach, and present the detailed design. "before we build", "what approach should we take?" **See also**: +[`/ctx-plan`](#ctx-plan), +[`/ctx-spec`](#ctx-spec) + +--- + +### `/ctx-plan` + +Stress-test a plan through an adversarial interview before it becomes +a spec. Asks one question at a time across scope, failure modes, +rejected alternatives, sequencing, reversibility, and hidden +assumptions — pushing back rather than validating. Stops when the +user can articulate the bet, the rejections, the top failure modes, +the cheapest validation, and the unwind cost. Concludes by offering +to write a *debated brief* to `.context/briefs/-.md`, the +canonical input for `/ctx-spec --brief`. Deliberately does **not** +produce an implementation plan or task list — that happens two steps +later, at [`/ctx-task-out`](#ctx-task-out). + +**Wraps**: reads code and context files; +writes `.context/briefs/-.md` + +**Trigger phrases**: "attack this plan", "poke holes in this", +"stress-test my plan", "scrutinize this before I commit" + +**See also**: +[Scrutinizing a Plan](../recipes/scrutinizing-a-plan.md), +[`/ctx-brainstorm`](#ctx-brainstorm), [`/ctx-spec`](#ctx-spec) --- @@ -517,13 +546,58 @@ filling the gap from inference. If the brief contradicts a frozen contract, the contradiction is surfaced to the user rather than silently followed. +Both flows end with a **tasking handoff**: specs that span +multiple milestones (or more than roughly one session of +implementation) are routed to [`/ctx-task-out`](#ctx-task-out) +for decomposition; small specs go straight to +[`/ctx-implement`](#ctx-implement). + **See also**: [`/ctx-brainstorm`](#ctx-brainstorm), [`/ctx-plan`](#ctx-plan), +[`/ctx-task-out`](#ctx-task-out), [`/ctx-plan-import`](#ctx-plan-import) --- +### `/ctx-task-out` + +Decompose a committed spec into a per-milestone implementation plan +at `specs/plans/.md` — data model, contracts, an +invariant-test matrix, and typically 15-40 tasks, each with a +**falsifiable acceptance criterion** (a command to run, a test that +must pass, an observable behavior). The plan is the document +[`/ctx-implement`](#ctx-implement) executes. The skill is a +decomposer, not a designer: disagreements with the spec route back +through [`/ctx-plan`](#ctx-plan) instead of being relitigated here. + +Two **hard gates** refuse rather than degrade: + +1. **Blocking-TBD gate**: the spec's open questions are classified + as blocking or deferrable for the target milestone; decomposition + refuses to proceed past a blocking TBD (a task that would embed + an assumption about its answer). +2. **Rolling-wave gate**: milestone N+1 is not decomposed while + milestone N's definition of done is unmet, unless the user + overrides explicitly (recorded in the plan header). + +TASKS.md receives **epic-level anchors only**, each annotated +`Plan: specs/plans/.md` — the plan owns the fine-grained +tasks, one-way sync, nothing moved or deleted. Single-session specs +skip this step entirely: the spec *is* the plan. + +**Wraps**: reads the spec, TASKS.md, DECISIONS.md, CONVENTIONS.md; +writes `specs/plans/.md`, appends anchors to TASKS.md + +**Trigger phrases**: "task this out", "break down the spec", +"decompose the spec", "plan out the milestone" + +**See also**: +[`/ctx-spec`](#ctx-spec), +[`/ctx-implement`](#ctx-implement) + +--- + ### `/ctx-plan-import` Import Claude Code plan files (`~/.claude/plans/*.md`) into the project's @@ -543,13 +617,18 @@ optionally chains to `/ctx-task-add` ### `/ctx-implement` Execute a multi-step plan with build and test verification at each -step. Loads a plan from a file or conversation context, breaks it -into atomic steps, and checkpoints after every 3-5 steps. +step. The canonical input is `specs/plans/.md` as written +by [`/ctx-task-out`](#ctx-task-out), but hand-written plan files and +plans from conversation context work too. Breaks the plan into +atomic steps and checkpoints after every 3-5 steps. Handed a bare +multi-milestone spec instead of a plan, it redirects to +`/ctx-task-out` rather than decomposing on the fly. **Wraps**: reads plan file, runs verification commands (`go build`, `go test`, etc.) **See also**: +[`/ctx-task-out`](#ctx-task-out), [Running an Unattended AI Agent](../recipes/autonomous-loops.md) --- diff --git a/internal/assets/claude/skills/ctx-implement/SKILL.md b/internal/assets/claude/skills/ctx-implement/SKILL.md index fc4aa19a0..6351f5e79 100644 --- a/internal/assets/claude/skills/ctx-implement/SKILL.md +++ b/internal/assets/claude/skills/ctx-implement/SKILL.md @@ -1,14 +1,17 @@ --- name: ctx-implement -description: "Execute a plan step-by-step with verification. Use when you have a plan document and need disciplined, checkpointed implementation." +description: "Execute a plan step-by-step with verification. Use when you have a plan document — canonically specs/plans/.md from /ctx-task-out — and need disciplined, checkpointed implementation." --- -Take a plan (inline text, file path, or from the conversation) -and execute it step-by-step with build/test verification between -steps. +Take a plan — canonically `specs/plans/.md` as written +by `/ctx-task-out`, though inline text, another file path, or a +plan from the conversation also work — and execute it +step-by-step with build/test verification between steps. ## When to Use +- After `/ctx-task-out` has decomposed a spec into + `specs/plans/.md` (the canonical input) - When the user provides a plan document or file and says "implement this" - When a multi-step task has been planned and needs disciplined @@ -20,6 +23,9 @@ steps. ## When NOT to Use - For single-step tasks: just do them directly +- When handed a bare multi-milestone spec instead of a plan: + suggest `/ctx-task-out --spec --milestone ` + first; decomposing on the fly is what it exists to prevent - When the plan is vague or incomplete: use `/ctx-brainstorm` first to refine it - When the user wants to explore or discuss, not execute @@ -29,6 +35,7 @@ steps. ```text /ctx-implement +/ctx-implement specs/plans/m0a.md /ctx-implement path/to/plan.md /ctx-implement (the plan from our discussion above) ``` @@ -38,6 +45,14 @@ steps. ### 1. Load the plan - If a file path is provided, read it +- If the file is a multi-milestone spec rather than a plan (no + task breakdown, no acceptance criteria, spans milestones), + redirect: suggest `/ctx-task-out --spec --milestone + ` and stop rather than improvising a decomposition +- If the plan's header shows `Status: Blocked`, stop: a + deferrable TBD graduated to blocking mid-milestone. Route its + resolution (a spec edit or DECISIONS.md entry) and a + `/ctx-task-out` amendment run before executing further tasks - If inline text is provided, use it directly - If neither, look back in the conversation for the most recent plan or approved design @@ -85,6 +100,11 @@ Verify after every individual step before proceeding to the next. After every 3-5 steps (or after a significant milestone): - Summarize what has been completed +- If executing `specs/plans/.md`, check off completed + tasks and DoD items in the plan document — it is the execution + ledger that `/ctx-task-out`'s rolling-wave gate reads. Never + edit a task's acceptance criterion in place; a criterion + change goes back through `/ctx-task-out` (amendment mode) - Note any deviations from the plan - Ask the user if they want to continue, adjust, or stop diff --git a/internal/assets/claude/skills/ctx-plan/SKILL.md b/internal/assets/claude/skills/ctx-plan/SKILL.md index 4f050d468..1d94cdf61 100644 --- a/internal/assets/claude/skills/ctx-plan/SKILL.md +++ b/internal/assets/claude/skills/ctx-plan/SKILL.md @@ -8,8 +8,8 @@ description: "Stress-test a plan through adversarial interview; produces a debat The project's design-to-implementation pipeline is: ```text -/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-implement - (vague) (contested) (committed) (execution) +/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-task-out → /ctx-implement + (vague) (contested) (committed) (decomposed) (execution) ``` `/ctx-plan` is the second step. It takes an idea that is no @@ -17,7 +17,8 @@ longer vague but not yet committed, attacks it, and writes a *debated brief* to `.context/briefs/-.md`. The brief is consumed by `/ctx-spec --brief ` to produce the committed spec. This skill does **not** produce an implementation -plan or a task list; the deliverable is the brief. +plan or a task list; the deliverable is the brief. Decomposition +into tasks happens two steps later, at `/ctx-task-out`. Do not invert the order. A "plan" run after `/ctx-spec` is fixing the foundation while the building is up; run diff --git a/internal/assets/claude/skills/ctx-spec/SKILL.md b/internal/assets/claude/skills/ctx-spec/SKILL.md index 1e39f84cf..4d56ca7e5 100644 --- a/internal/assets/claude/skills/ctx-spec/SKILL.md +++ b/internal/assets/claude/skills/ctx-spec/SKILL.md @@ -11,15 +11,18 @@ each section with the user to produce a complete design document. The project's design-to-implementation pipeline is: ```text -/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-implement - (vague) (contested) (committed) (execution) +/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-task-out → /ctx-implement + (vague) (contested) (committed) (decomposed) (execution) ``` `/ctx-spec` is the third step. It consumes the *debated brief* produced by `/ctx-plan` (via `--brief `) or writes a fresh spec interactively when no brief is needed. Specs are committed artifacts under `specs/`; briefs are working state under -`.context/briefs/` that the spec absorbs. +`.context/briefs/` that the spec absorbs. Downstream, +`/ctx-task-out` decomposes multi-milestone specs into the plan +document `/ctx-implement` executes; small specs go straight to +`/ctx-implement`. Do not invert the order. A spec without a settled bet ahead of it is a wishlist; running `/ctx-plan` after `/ctx-spec` is fixing @@ -89,6 +92,9 @@ follow the brief. 4. Where the brief is silent, write `TBD` rather than inventing. 5. Write the spec to `specs/{feature-name}.md` and surface the `TBD` entries for the user to fill in next. +6. Apply the tasking handoff (step 7 of the interactive flow): + multi-milestone specs get `/ctx-task-out`, small specs go + straight to `/ctx-implement`. ## Process (interactive, when `--brief` is absent) @@ -152,6 +158,14 @@ Write the completed spec to `specs/{feature-name}.md`. - If no tasks exist yet, offer to create them: > "Want me to break this into tasks in TASKS.md?" +### 7. Hand Off to Tasking + +If the spec spans multiple milestones or more than ~one session +of implementation, do not stop at coarse task creation: recommend +`/ctx-task-out --spec specs/.md --milestone ` and +say why (specs stay concise; the plan carries decomposition). For +small specs, suggest `/ctx-implement` directly. + ## Skipping Sections Not every spec needs every section. If a section clearly does not diff --git a/internal/assets/claude/skills/ctx-task-out/SKILL.md b/internal/assets/claude/skills/ctx-task-out/SKILL.md new file mode 100644 index 000000000..64d385c4d --- /dev/null +++ b/internal/assets/claude/skills/ctx-task-out/SKILL.md @@ -0,0 +1,210 @@ +--- +name: ctx-task-out +description: "Decompose a committed spec into a per-milestone implementation plan at specs/plans/.md — data model, contracts, invariant-test matrix, and tasks with falsifiable acceptance criteria — that /ctx-implement consumes. Use after /ctx-spec when a spec is too large to implement in one session." +--- + +## Canonical Chain + +The project's design-to-implementation pipeline is: + +```text +/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-task-out → /ctx-implement + (vague) (contested) (committed) (decomposed) (execution) +``` + +`/ctx-task-out` is the fourth step. It consumes a committed spec +(`--spec `) and produces the *plan document* that +`/ctx-implement` executes. It closes a gap the chain otherwise +leaves unowned: `/ctx-plan` explicitly disclaims implementation +planning, `/ctx-spec` commits the what/why at spec altitude, and +`/ctx-implement` opens with "use when you have a plan document" — +this skill is what produces that document. + +Small specs skip this step. If the whole spec is implementable in +roughly one session, go straight to `/ctx-implement` with the spec +itself. + +## Role + +You decompose; you do not redesign the bet. The spec is +committed; do not relitigate scope, behavior, or the bet here — +disagreements with the spec go back through `/ctx-plan`. +Implementation structure is different: choosing schema shapes, +signatures, and index strategies is exactly the job, because +resolving those decisions *before* execution is the point of +this skill. Make every task falsifiable and every design detail +the implementer needs explicit before execution starts, so no +large decision is made mid-flight. + +Authority boundary: invariants, validation rules, and behavior +come *from the spec*. If decomposition surfaces an invariant the +spec never states, that is a spec gap — surface it and mark it +`TBD`; do not mint it here. + +## When to Use + +- After `/ctx-spec`, when the spec spans milestones/phases or + exceeds ~one session of implementation +- When a TASKS.md phase references a spec but its tasks are coarse + and carry no acceptance criteria +- When `/ctx-implement` is invoked without a plan document + (redirect here first) + +## When NOT to Use + +- Single-session features — the spec *is* the plan +- The spec is not committed yet (`/ctx-spec` first) +- The bet is still contested (`/ctx-plan` first) +- Decomposing milestone N+1 while milestone N's DoD is unmet + (see rolling-wave gate) + +## Usage + +```text +/ctx-task-out --spec specs/v1-substrate.md --milestone m0a +/ctx-task-out --spec specs/rss-feed.md # single-milestone: whole spec +``` + +Without `--milestone`, the plan file takes the spec's basename: +`specs/plans/rss-feed.md`. + +## Preconditions (hard gates — refuse, do not degrade) + +1. **Spec exists.** If `--spec` is missing or the file is absent, + stop and report; no interactive fallback. +2. **Blocking-TBD gate.** Enumerate the spec's Open Questions / + `TBD` entries and classify each as *blocking* or *deferrable* + for the target milestone. A TBD is blocking if any task in the + milestone would embed an assumption about its answer (language + choice, storage engine, schema format…). Refuse to decompose + past a blocking TBD: list the blockers, name who can resolve + them, and stop. Deferrable TBDs do not vanish: carry each into + the plan (Out of scope or Risks), annotated with the milestone + at which it becomes blocking. Resolving a blocking TBD is a + spec edit or a DECISIONS.md entry *first*; the plan only + points at that record. A resolution that exists nowhere but + the plan is minting. +3. **Rolling-wave gate.** If a prior milestone's plan exists and + its DoD is not checked off, refuse to decompose the next + milestone. The user may override explicitly; log the + override in the plan's Amendments section. Tasking distant milestones + produces fiction — the current milestone's measurements are + allowed to reshape everything downstream. + +Milestone boundaries belong to the spec. If decomposition shows +the cut is wrong — one "milestone" hiding several, or a boundary +in the wrong place — stop and route the resize through the spec; +do not mint sub-milestones here. + +## Process + +0. **Detect mode.** If the target plan file already exists, this + is an amendment run, not a fresh decomposition: read the + existing plan, classify the change as obsolete/append, re-run + only the blocking-TBD gate against the delta, and log the + change in the plan's Amendments section. The rolling-wave + gate does not fire when amending the current milestone. + Steps 1–8 below describe a fresh run. + +1. Read the spec in full. Read TASKS.md, DECISIONS.md, and + CONVENTIONS.md from the context directory. +2. Run the blocking-TBD gate; surface the classification to the + user before proceeding. +3. Draft the plan sections (structure below). Lift from the spec + verbatim where it speaks; where it is silent, prefer asking or + marking `TBD` over inventing — same authority discipline as + `/ctx-spec --brief`. +4. Break down tasks: typically 15–40 per milestone. Each task + carries: id, title, dependencies (by id), the files/paths it + is expected to touch, a `[P]` marker when + parallelizable with its siblings, a **falsifiable acceptance + criterion** (a command to run, a test that must pass, an + observable behavior), and a reference to the spec section it + implements. Size each task to roughly one commit — small + enough that a failed acceptance check localizes the fault to + that task. `[P]` is mechanical, not aspirational: no + dependency edge, no file touched by a sibling `[P]` task, no + shared sequence (e.g. migration numbers). File disjointness + is checkable from the files column — which is also how an + amendment run detects a new task colliding with one in + flight. +5. Build the test matrix: every invariant, validation rule, and + edge case the milestone touches × the attempted violation × the + expected failure mode × the task id whose acceptance criterion + exercises it. A matrix row no task exercises is documentation, + not execution. +6. Write `specs/plans/.md` (create `specs/plans/` if + absent). +7. Sync anchors to TASKS.md: **epic-level anchors only** — one per + task cluster, each annotated `Plan: specs/plans/.md`. + One-way sync, plan → TASKS.md. Never duplicate the full task + list into TASKS.md; never move or delete existing entries + (CONSTITUTION). +8. Hand off: report blockers resolved/remaining and suggest + `/ctx-implement` against the plan. + +## Plan Document Structure + +```markdown +# Plan — + +**Spec:** · **Status:** Ready | Blocked +**Blocking TBDs resolved:** + +## Scope & DoD (lifted from the spec's milestone entry) +## Data model & storage (DDL, migrations, indexes) +## Contracts (API signatures, schemas, CLI surface) +## Test matrix (invariant × violation attempt × expected failure × task ref) +## Task breakdown (table: id · task · deps · files · [P] · acceptance criterion · spec ref) +## Risks & measurement gates (results that may reshape later tasks) +## Out of scope (deferred to later milestones, with pointers) +## Amendments (date · what · why — appended by amendment runs) +``` + +The plan is the **execution ledger**: the task table carries +per-task checkbox state, Scope & DoD carries the DoD checkboxes, +and `/ctx-implement` updates both as it executes. DoD is +confirmed by measurement or by the user — never derived from +task completion — and the rolling-wave gate reads the DoD +checkboxes only. No other record of milestone progress exists. +`Status: Blocked` is reachable only by amendment: a fresh run +refuses instead of writing a Blocked plan; the status marks a +deferrable TBD that graduated to blocking mid-milestone. + +## Amendments (Mid-Milestone Changes) + +Plans meet reality; the plan document owns that contact. When a +measurement gate fires or the implementer hits a wall: + +- Tasks may be marked `obsolete` with a one-line reason; never + deleted. +- New tasks are appended with fresh ids; ids are never reused. +- An acceptance criterion is **never edited in place** once its + task has started — weakening the test until it passes is the + failure mode this rule exists to prevent. A criterion change + is a re-invocation of `/ctx-task-out` against the same + milestone: with the plan already present, the skill operates + in amendment mode — read the existing plan, apply the change + as obsolete-and-append, and log date · what · why in the + plan's Amendments section. +- Disagreements with the *spec* discovered mid-flight still + route through `/ctx-plan`; amendments cover implementation + reality, not the bet. + +## Quality Checklist + +Before writing the file, verify: + +- [ ] Every task has a falsifiable acceptance criterion — no + "implement X" without a way to check it happened +- [ ] No task depends on an unresolved blocking TBD +- [ ] Every invariant the milestone touches appears in the test + matrix, and every matrix row is exercised by a task's + acceptance criterion (by id) +- [ ] Task ids admit a topological order — verify by listing + execution waves; `[P]` siblings share no files, edges, or + sequences +- [ ] TASKS.md gained anchors only — nothing moved, nothing deleted +- [ ] The plan is implementable-alone: a fresh agent holding only + the plan and the spec can state the acceptance check for + any task without asking a question diff --git a/internal/assets/commands/text/write.yaml b/internal/assets/commands/text/write.yaml index dd599c339..50f6d9d4a 100644 --- a/internal/assets/commands/text/write.yaml +++ b/internal/assets/commands/text/write.yaml @@ -281,6 +281,7 @@ write.init-workflow-tips: Planning and design: /ctx-brainstorm Structured design dialogue before implementation /ctx-spec Scaffold a feature spec from the project template + /ctx-task-out Decompose a committed spec into a per-milestone plan /ctx-implement Execute a plan step-by-step with checkpointed verification Periodic maintenance: diff --git a/internal/assets/context/AGENT_PLAYBOOK.md b/internal/assets/context/AGENT_PLAYBOOK.md index ab3aab9a7..c5e7a75b5 100644 --- a/internal/assets/context/AGENT_PLAYBOOK.md +++ b/internal/assets/context/AGENT_PLAYBOOK.md @@ -329,7 +329,9 @@ alone. **2. Task it out**: Break the work into individual tasks in TASKS.md under a dedicated Phase section. Each task should be independently completable and -verifiable. +verifiable. For multi-milestone specs, run `/ctx-task-out` instead of +tasking by hand: it writes `specs/plans/.md` with falsifiable +acceptance criteria, and TASKS.md carries epic-level anchors only. **3. Cross-reference**: The Phase header in TASKS.md must reference the spec: `Spec: \`specs/feature-name.md\``. The first task in the phase should diff --git a/internal/assets/context/AGENT_PLAYBOOK_GATE.md b/internal/assets/context/AGENT_PLAYBOOK_GATE.md index 865d50bb4..a1fab82fa 100644 --- a/internal/assets/context/AGENT_PLAYBOOK_GATE.md +++ b/internal/assets/context/AGENT_PLAYBOOK_GATE.md @@ -41,16 +41,18 @@ a spec; no exceptions. Scale the spec to the work. The design-to-implementation chain is: ```text -/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-implement - (vague) (contested) (committed) (execution) +/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-task-out → /ctx-implement + (vague) (contested) (committed) (decomposed) (execution) ``` `/ctx-brainstorm` shapes a vague idea into a bet. `/ctx-plan` attacks the bet and writes a debated brief to `.context/briefs/-.md`. `/ctx-spec` (optionally `--brief `) absorbs the brief into a committed spec under -`specs/`. Skip the predecessors only when the step's input is -already settled. +`specs/`. `/ctx-task-out` decomposes a multi-milestone spec into +a per-milestone plan at `specs/plans/.md`; +single-session specs skip it. Skip the predecessors only when +the step's input is already settled. ## Proactive Persistence diff --git a/internal/assets/integrations/copilot-cli/skills/ctx-implement/SKILL.md b/internal/assets/integrations/copilot-cli/skills/ctx-implement/SKILL.md index fc4aa19a0..6351f5e79 100644 --- a/internal/assets/integrations/copilot-cli/skills/ctx-implement/SKILL.md +++ b/internal/assets/integrations/copilot-cli/skills/ctx-implement/SKILL.md @@ -1,14 +1,17 @@ --- name: ctx-implement -description: "Execute a plan step-by-step with verification. Use when you have a plan document and need disciplined, checkpointed implementation." +description: "Execute a plan step-by-step with verification. Use when you have a plan document — canonically specs/plans/.md from /ctx-task-out — and need disciplined, checkpointed implementation." --- -Take a plan (inline text, file path, or from the conversation) -and execute it step-by-step with build/test verification between -steps. +Take a plan — canonically `specs/plans/.md` as written +by `/ctx-task-out`, though inline text, another file path, or a +plan from the conversation also work — and execute it +step-by-step with build/test verification between steps. ## When to Use +- After `/ctx-task-out` has decomposed a spec into + `specs/plans/.md` (the canonical input) - When the user provides a plan document or file and says "implement this" - When a multi-step task has been planned and needs disciplined @@ -20,6 +23,9 @@ steps. ## When NOT to Use - For single-step tasks: just do them directly +- When handed a bare multi-milestone spec instead of a plan: + suggest `/ctx-task-out --spec --milestone ` + first; decomposing on the fly is what it exists to prevent - When the plan is vague or incomplete: use `/ctx-brainstorm` first to refine it - When the user wants to explore or discuss, not execute @@ -29,6 +35,7 @@ steps. ```text /ctx-implement +/ctx-implement specs/plans/m0a.md /ctx-implement path/to/plan.md /ctx-implement (the plan from our discussion above) ``` @@ -38,6 +45,14 @@ steps. ### 1. Load the plan - If a file path is provided, read it +- If the file is a multi-milestone spec rather than a plan (no + task breakdown, no acceptance criteria, spans milestones), + redirect: suggest `/ctx-task-out --spec --milestone + ` and stop rather than improvising a decomposition +- If the plan's header shows `Status: Blocked`, stop: a + deferrable TBD graduated to blocking mid-milestone. Route its + resolution (a spec edit or DECISIONS.md entry) and a + `/ctx-task-out` amendment run before executing further tasks - If inline text is provided, use it directly - If neither, look back in the conversation for the most recent plan or approved design @@ -85,6 +100,11 @@ Verify after every individual step before proceeding to the next. After every 3-5 steps (or after a significant milestone): - Summarize what has been completed +- If executing `specs/plans/.md`, check off completed + tasks and DoD items in the plan document — it is the execution + ledger that `/ctx-task-out`'s rolling-wave gate reads. Never + edit a task's acceptance criterion in place; a criterion + change goes back through `/ctx-task-out` (amendment mode) - Note any deviations from the plan - Ask the user if they want to continue, adjust, or stop diff --git a/internal/assets/integrations/copilot-cli/skills/ctx-spec/SKILL.md b/internal/assets/integrations/copilot-cli/skills/ctx-spec/SKILL.md index 1e39f84cf..4d56ca7e5 100644 --- a/internal/assets/integrations/copilot-cli/skills/ctx-spec/SKILL.md +++ b/internal/assets/integrations/copilot-cli/skills/ctx-spec/SKILL.md @@ -11,15 +11,18 @@ each section with the user to produce a complete design document. The project's design-to-implementation pipeline is: ```text -/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-implement - (vague) (contested) (committed) (execution) +/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-task-out → /ctx-implement + (vague) (contested) (committed) (decomposed) (execution) ``` `/ctx-spec` is the third step. It consumes the *debated brief* produced by `/ctx-plan` (via `--brief `) or writes a fresh spec interactively when no brief is needed. Specs are committed artifacts under `specs/`; briefs are working state under -`.context/briefs/` that the spec absorbs. +`.context/briefs/` that the spec absorbs. Downstream, +`/ctx-task-out` decomposes multi-milestone specs into the plan +document `/ctx-implement` executes; small specs go straight to +`/ctx-implement`. Do not invert the order. A spec without a settled bet ahead of it is a wishlist; running `/ctx-plan` after `/ctx-spec` is fixing @@ -89,6 +92,9 @@ follow the brief. 4. Where the brief is silent, write `TBD` rather than inventing. 5. Write the spec to `specs/{feature-name}.md` and surface the `TBD` entries for the user to fill in next. +6. Apply the tasking handoff (step 7 of the interactive flow): + multi-milestone specs get `/ctx-task-out`, small specs go + straight to `/ctx-implement`. ## Process (interactive, when `--brief` is absent) @@ -152,6 +158,14 @@ Write the completed spec to `specs/{feature-name}.md`. - If no tasks exist yet, offer to create them: > "Want me to break this into tasks in TASKS.md?" +### 7. Hand Off to Tasking + +If the spec spans multiple milestones or more than ~one session +of implementation, do not stop at coarse task creation: recommend +`/ctx-task-out --spec specs/.md --milestone ` and +say why (specs stay concise; the plan carries decomposition). For +small specs, suggest `/ctx-implement` directly. + ## Skipping Sections Not every spec needs every section. If a section clearly does not diff --git a/internal/assets/integrations/copilot-cli/skills/ctx-task-out/SKILL.md b/internal/assets/integrations/copilot-cli/skills/ctx-task-out/SKILL.md new file mode 100644 index 000000000..64d385c4d --- /dev/null +++ b/internal/assets/integrations/copilot-cli/skills/ctx-task-out/SKILL.md @@ -0,0 +1,210 @@ +--- +name: ctx-task-out +description: "Decompose a committed spec into a per-milestone implementation plan at specs/plans/.md — data model, contracts, invariant-test matrix, and tasks with falsifiable acceptance criteria — that /ctx-implement consumes. Use after /ctx-spec when a spec is too large to implement in one session." +--- + +## Canonical Chain + +The project's design-to-implementation pipeline is: + +```text +/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-task-out → /ctx-implement + (vague) (contested) (committed) (decomposed) (execution) +``` + +`/ctx-task-out` is the fourth step. It consumes a committed spec +(`--spec `) and produces the *plan document* that +`/ctx-implement` executes. It closes a gap the chain otherwise +leaves unowned: `/ctx-plan` explicitly disclaims implementation +planning, `/ctx-spec` commits the what/why at spec altitude, and +`/ctx-implement` opens with "use when you have a plan document" — +this skill is what produces that document. + +Small specs skip this step. If the whole spec is implementable in +roughly one session, go straight to `/ctx-implement` with the spec +itself. + +## Role + +You decompose; you do not redesign the bet. The spec is +committed; do not relitigate scope, behavior, or the bet here — +disagreements with the spec go back through `/ctx-plan`. +Implementation structure is different: choosing schema shapes, +signatures, and index strategies is exactly the job, because +resolving those decisions *before* execution is the point of +this skill. Make every task falsifiable and every design detail +the implementer needs explicit before execution starts, so no +large decision is made mid-flight. + +Authority boundary: invariants, validation rules, and behavior +come *from the spec*. If decomposition surfaces an invariant the +spec never states, that is a spec gap — surface it and mark it +`TBD`; do not mint it here. + +## When to Use + +- After `/ctx-spec`, when the spec spans milestones/phases or + exceeds ~one session of implementation +- When a TASKS.md phase references a spec but its tasks are coarse + and carry no acceptance criteria +- When `/ctx-implement` is invoked without a plan document + (redirect here first) + +## When NOT to Use + +- Single-session features — the spec *is* the plan +- The spec is not committed yet (`/ctx-spec` first) +- The bet is still contested (`/ctx-plan` first) +- Decomposing milestone N+1 while milestone N's DoD is unmet + (see rolling-wave gate) + +## Usage + +```text +/ctx-task-out --spec specs/v1-substrate.md --milestone m0a +/ctx-task-out --spec specs/rss-feed.md # single-milestone: whole spec +``` + +Without `--milestone`, the plan file takes the spec's basename: +`specs/plans/rss-feed.md`. + +## Preconditions (hard gates — refuse, do not degrade) + +1. **Spec exists.** If `--spec` is missing or the file is absent, + stop and report; no interactive fallback. +2. **Blocking-TBD gate.** Enumerate the spec's Open Questions / + `TBD` entries and classify each as *blocking* or *deferrable* + for the target milestone. A TBD is blocking if any task in the + milestone would embed an assumption about its answer (language + choice, storage engine, schema format…). Refuse to decompose + past a blocking TBD: list the blockers, name who can resolve + them, and stop. Deferrable TBDs do not vanish: carry each into + the plan (Out of scope or Risks), annotated with the milestone + at which it becomes blocking. Resolving a blocking TBD is a + spec edit or a DECISIONS.md entry *first*; the plan only + points at that record. A resolution that exists nowhere but + the plan is minting. +3. **Rolling-wave gate.** If a prior milestone's plan exists and + its DoD is not checked off, refuse to decompose the next + milestone. The user may override explicitly; log the + override in the plan's Amendments section. Tasking distant milestones + produces fiction — the current milestone's measurements are + allowed to reshape everything downstream. + +Milestone boundaries belong to the spec. If decomposition shows +the cut is wrong — one "milestone" hiding several, or a boundary +in the wrong place — stop and route the resize through the spec; +do not mint sub-milestones here. + +## Process + +0. **Detect mode.** If the target plan file already exists, this + is an amendment run, not a fresh decomposition: read the + existing plan, classify the change as obsolete/append, re-run + only the blocking-TBD gate against the delta, and log the + change in the plan's Amendments section. The rolling-wave + gate does not fire when amending the current milestone. + Steps 1–8 below describe a fresh run. + +1. Read the spec in full. Read TASKS.md, DECISIONS.md, and + CONVENTIONS.md from the context directory. +2. Run the blocking-TBD gate; surface the classification to the + user before proceeding. +3. Draft the plan sections (structure below). Lift from the spec + verbatim where it speaks; where it is silent, prefer asking or + marking `TBD` over inventing — same authority discipline as + `/ctx-spec --brief`. +4. Break down tasks: typically 15–40 per milestone. Each task + carries: id, title, dependencies (by id), the files/paths it + is expected to touch, a `[P]` marker when + parallelizable with its siblings, a **falsifiable acceptance + criterion** (a command to run, a test that must pass, an + observable behavior), and a reference to the spec section it + implements. Size each task to roughly one commit — small + enough that a failed acceptance check localizes the fault to + that task. `[P]` is mechanical, not aspirational: no + dependency edge, no file touched by a sibling `[P]` task, no + shared sequence (e.g. migration numbers). File disjointness + is checkable from the files column — which is also how an + amendment run detects a new task colliding with one in + flight. +5. Build the test matrix: every invariant, validation rule, and + edge case the milestone touches × the attempted violation × the + expected failure mode × the task id whose acceptance criterion + exercises it. A matrix row no task exercises is documentation, + not execution. +6. Write `specs/plans/.md` (create `specs/plans/` if + absent). +7. Sync anchors to TASKS.md: **epic-level anchors only** — one per + task cluster, each annotated `Plan: specs/plans/.md`. + One-way sync, plan → TASKS.md. Never duplicate the full task + list into TASKS.md; never move or delete existing entries + (CONSTITUTION). +8. Hand off: report blockers resolved/remaining and suggest + `/ctx-implement` against the plan. + +## Plan Document Structure + +```markdown +# Plan — + +**Spec:** · **Status:** Ready | Blocked +**Blocking TBDs resolved:** + +## Scope & DoD (lifted from the spec's milestone entry) +## Data model & storage (DDL, migrations, indexes) +## Contracts (API signatures, schemas, CLI surface) +## Test matrix (invariant × violation attempt × expected failure × task ref) +## Task breakdown (table: id · task · deps · files · [P] · acceptance criterion · spec ref) +## Risks & measurement gates (results that may reshape later tasks) +## Out of scope (deferred to later milestones, with pointers) +## Amendments (date · what · why — appended by amendment runs) +``` + +The plan is the **execution ledger**: the task table carries +per-task checkbox state, Scope & DoD carries the DoD checkboxes, +and `/ctx-implement` updates both as it executes. DoD is +confirmed by measurement or by the user — never derived from +task completion — and the rolling-wave gate reads the DoD +checkboxes only. No other record of milestone progress exists. +`Status: Blocked` is reachable only by amendment: a fresh run +refuses instead of writing a Blocked plan; the status marks a +deferrable TBD that graduated to blocking mid-milestone. + +## Amendments (Mid-Milestone Changes) + +Plans meet reality; the plan document owns that contact. When a +measurement gate fires or the implementer hits a wall: + +- Tasks may be marked `obsolete` with a one-line reason; never + deleted. +- New tasks are appended with fresh ids; ids are never reused. +- An acceptance criterion is **never edited in place** once its + task has started — weakening the test until it passes is the + failure mode this rule exists to prevent. A criterion change + is a re-invocation of `/ctx-task-out` against the same + milestone: with the plan already present, the skill operates + in amendment mode — read the existing plan, apply the change + as obsolete-and-append, and log date · what · why in the + plan's Amendments section. +- Disagreements with the *spec* discovered mid-flight still + route through `/ctx-plan`; amendments cover implementation + reality, not the bet. + +## Quality Checklist + +Before writing the file, verify: + +- [ ] Every task has a falsifiable acceptance criterion — no + "implement X" without a way to check it happened +- [ ] No task depends on an unresolved blocking TBD +- [ ] Every invariant the milestone touches appears in the test + matrix, and every matrix row is exercised by a task's + acceptance criterion (by id) +- [ ] Task ids admit a topological order — verify by listing + execution waves; `[P]` siblings share no files, edges, or + sequences +- [ ] TASKS.md gained anchors only — nothing moved, nothing deleted +- [ ] The plan is implementable-alone: a fresh agent holding only + the plan and the spec can state the acceptance check for + any task without asking a question diff --git a/internal/assets/permissions/allow.txt b/internal/assets/permissions/allow.txt index 4bdb7ee79..c3156de0c 100644 --- a/internal/assets/permissions/allow.txt +++ b/internal/assets/permissions/allow.txt @@ -38,5 +38,6 @@ Skill(ctx-skill-audit) Skill(ctx-skill-create) Skill(ctx-spec) Skill(ctx-status) +Skill(ctx-task-out) Skill(ctx-worktree) Skill(ctx-wrap-up) diff --git a/internal/assets/project/specs-README.md b/internal/assets/project/specs-README.md index 815619d61..1474f1d9d 100644 --- a/internal/assets/project/specs-README.md +++ b/internal/assets/project/specs-README.md @@ -10,8 +10,11 @@ It's complete enough that another session could implement from it alone. 1. **Draft**: write the spec in this directory 2. **Reference**: add a Phase to TASKS.md with `Spec: specs/.md` -3. **Implement**: follow the spec, checking off tasks as you go -4. **Archive**: move to `specs/done/` when all tasks are complete +3. **Task out**: for multi-milestone specs, `/ctx-task-out` writes + `specs/plans/.md`; TASKS.md carries epic anchors only +4. **Implement**: follow the plan (or the spec directly for + single-session features), checking off tasks as you go +5. **Archive**: move to `specs/done/` when all tasks are complete ## Tips diff --git a/specs/ctx-task-out.md b/specs/ctx-task-out.md new file mode 100644 index 000000000..4a705058f --- /dev/null +++ b/specs/ctx-task-out.md @@ -0,0 +1,120 @@ +# ctx-task-out — Close the Spec→Implement Gap + +**Status:** Implemented (session 1306853f, 2026-07-03) — skill at +`internal/assets/claude/skills/ctx-task-out/SKILL.md`, amended after +two review rounds (role-authority split, execution ledger, amendment +mode, files column, matrix task refs, hard-gate refinements). +**Draft skill:** retired after landing (was +`specs/ctx-task-out-SKILL-draft.md`; the installed skill superseded it). +**Origin:** zhc/os session c887a6d4, 2026-07-03 — the gap surfaced in live use. + +## Problem + +The canonical chain has an unowned artifact. `/ctx-plan` explicitly +disclaims implementation planning ("the deliverable is a debated brief, +not a task list"). `/ctx-spec` produces the committed what/why and its +own guidance keeps specs concise ("a page is usually enough"). +`/ctx-implement` opens with "use when you have a plan document" — and +**nothing in the chain produces that document.** + +For single-session features the spec doubles as the plan and nothing is +missing. For multi-milestone specs the conciseness rule and the +implementable-alone rule (`specs/README.md`) become contradictory, and +the missing mass — data model, contracts, test matrix, granular tasks +with acceptance criteria — has no home. In live use this collapsed into +ad-hoc tasking: ten coarse TASKS.md entries with no acceptance criteria +and a blocking open question (language choice) sitting under task #1. +Every artifact with a ceremony came out well; the unceremonied step is +where quality collapsed. + +SpecKit comparison, for orientation: ctx has an adversarial step SpecKit +lacks (`/ctx-plan`); SpecKit has the `/plan` + `/tasks` ladder ctx lacks. +This skill adds the ladder without importing a second framework (which +would create dual sources of truth for specs and tasks). + +## Naming + +**`ctx-task-out`.** Phrasal verb ("task this out"), precedent in +`ctx-wrap-up`, family resonance with `ctx-task-add`. Rejected: +`ctx-tasks` (noun; breaks the verb-suffix convention), `ctx-task` +(reads as noun, collides conceptually with `ctx-task-add`), +`ctx-decompose` (verb but loses the task-family naming), +`ctx-breakdown` (noun). If the implementing agent finds a strong reason +to rename, keep the phrasal-verb constraint. + +## Deliverables + +1. **The skill.** Install `specs/ctx-task-out-SKILL-draft.md` as + `internal/assets/claude/skills/ctx-task-out/SKILL.md`. Mirror to the + copilot-cli integration (see how `ctx-spec` is carried under + `internal/assets/integrations/copilot-cli/skills/`). Register + wherever skills are enumerated (plugin manifest, tests — + `internal/assets/templates_test.go` may assert counts). Follow + `CONTRIBUTING-SKILLS.md`. +2. **Chain diagrams.** The 4-step chain appears in multiple skills + (`ctx-plan`, `ctx-spec`, `ctx-implement`, possibly `ctx-brainstorm`, + plus copilot mirrors, docs/site). Find all: + `grep -rn "ctx-spec → /ctx-implement" internal/ docs/ site/` + Replace with the 5-step chain: + `/ctx-brainstorm → /ctx-plan → /ctx-spec → /ctx-task-out → /ctx-implement` + with stage labels `(vague) (contested) (committed) (decomposed) (execution)`. +3. **`ctx-spec` amendment — the delegation hook.** Add a final process + step after "6. Cross-Reference": + + > ### 7. Hand off to tasking + > If the spec spans multiple milestones or more than ~one session of + > implementation, do not stop at coarse task creation: recommend + > `/ctx-task-out --spec specs/.md --milestone ` and say + > why (specs stay concise; the plan carries decomposition). For + > small specs, suggest `/ctx-implement` directly. + + Also add one line to the `--brief` flow (step 5) so the handoff + fires in non-interactive mode too. +4. **`ctx-implement` amendment.** Its "use when you have a plan + document" wording should name `specs/plans/.md` (the + `/ctx-task-out` output) as the canonical input while still accepting + hand-written plans. Add a redirect: if invoked with only a + multi-milestone spec, suggest `/ctx-task-out` first. +5. **Project template.** `internal/assets/project/specs-README.md` + lifecycle gains a step between Draft/Reference and Implement: + "Task out: for multi-milestone specs, `/ctx-task-out` writes + `specs/plans/.md`; TASKS.md carries epic anchors only." + +## Design constraints (do not weaken) + +- **Hard gates, not warnings.** The blocking-TBD gate and the + rolling-wave gate refuse; they do not proceed-with-caveats. The + chain's signature move is refusing to run ahead of its inputs + (`/ctx-spec` refuses vague ideas; this refuses unresolved specs). +- **One source of truth for tasks.** The plan owns fine-grained tasks; + TASKS.md gets epic-level anchors with a `Plan:` reference, one-way + sync. This is the argument against adopting SpecKit wholesale — do + not reintroduce dual truth here. +- **Decomposer, not designer.** The skill must not relitigate the spec; + disagreements route back to `/ctx-plan`. +- **Falsifiable acceptance criteria** on every task — a command, a + test, or an observable. "Implement X" alone is a checklist failure. + +## Acceptance criteria for this work order + +- [x] Skill installed + copilot parity + registered; the asset tests + pass (full `go test ./...` green) +- [x] All chain diagrams show 5 steps (grep returns no 4-step remnants) +- [x] `/ctx-spec` ends with the tasking handoff in both interactive and + `--brief` flows +- [x] `/ctx-implement` names the plan artifact and redirects when handed + a bare multi-milestone spec (and refuses a `Status: Blocked` plan) +- [ ] A dry run against a real spec (e.g. zhc/os `specs/v1-substrate.md`, + milestone m0a) produces a plan passing the skill's own quality + checklist — including a correct refusal while D-001 (language + choice) is unresolved + *(gate half verified read-only 2026-07-03: D-001 open in the spec + → blocking-TBD refusal fires by construction; the plan-producing + run happens post-reinstall via the originating session)* + +## Review + +After landing, the originating session's agent (zhc/os, session +c887a6d4) reviews: gate behavior first (TBD refusal, rolling-wave +refusal), then plan-document quality on the m0a dry run, then chain-text +consistency. First real consumer: zhc/os `specs/plans/m0a.md`. From 500c4a07a6f8cb746a325addc33b0f0841d95df8 Mon Sep 17 00:00:00 2001 From: Jose Alekhinne Date: Fri, 3 Jul 2026 18:19:40 -0700 Subject: [PATCH 2/3] fix context window detection for Claude 5 family models ModelContextWindow recognized 1M windows only via the [1m] suffix or the opus substring, so claude-fable-5 sessions fell through to the 200k default and every consumer of EffectiveContextWindow - the check-context-size hook, heartbeat, nudges, provenance - computed against the wrong window (a 21%-used 1M session warned "104% full"). Map the always-1M families: fable, mythos, and sonnet-5 (1M as standard per the current model catalog; earlier Sonnets keep the [1m] opt-in path, deliberately unchanged). Spec: specs/model-context-window-fable.md Signed-off-by: Jose Alekhinne --- .../cli/system/core/session/session_token.go | 9 +++- .../system/core/session/session_token_test.go | 15 ++++++ internal/config/claude/claude.go | 10 ++++ internal/config/claude/doc.go | 4 ++ specs/model-context-window-fable.md | 46 +++++++++++++++++++ 5 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 specs/model-context-window-fable.md diff --git a/internal/cli/system/core/session/session_token.go b/internal/cli/system/core/session/session_token.go index 30610fb4f..644baabd5 100644 --- a/internal/cli/system/core/session/session_token.go +++ b/internal/cli/system/core/session/session_token.go @@ -222,11 +222,16 @@ func ModelContextWindow(model string) int { lower := i18n.Fold(model) - // 1M models: explicit [1m] suffix OR Opus 4.6+ (always 1M). + // 1M models: explicit [1m] suffix OR families that are always 1M + // (Opus 4.6+, Sonnet 5+, and the Claude 5 Mythos-class: + // Fable/Mythos). if strings.Contains(lower, claude.ModelSuffix1M) { return claude.ContextWindow1M } - if strings.Contains(lower, claude.ModelOpus) { + if strings.Contains(lower, claude.ModelOpus) || + strings.Contains(lower, claude.ModelFable) || + strings.Contains(lower, claude.ModelMythos) || + strings.Contains(lower, claude.ModelSonnet5) { return claude.ContextWindow1M } diff --git a/internal/cli/system/core/session/session_token_test.go b/internal/cli/system/core/session/session_token_test.go index c8c59f896..67043f558 100644 --- a/internal/cli/system/core/session/session_token_test.go +++ b/internal/cli/system/core/session/session_token_test.go @@ -39,6 +39,21 @@ func TestModelContextWindow(t *testing.T) { model: "claude-sonnet-4-6-20260205", want: rc.DefaultContextWindow, }, + { + name: "claude fable is always 1M", + model: "claude-fable-5", + want: claude.ContextWindow1M, + }, + { + name: "claude mythos is always 1M", + model: "claude-mythos-5", + want: claude.ContextWindow1M, + }, + { + name: "claude sonnet 5 is 1M as standard", + model: "claude-sonnet-5", + want: claude.ContextWindow1M, + }, { name: "claude with 1m suffix", model: "claude-opus-4-6[1m]", diff --git a/internal/config/claude/claude.go b/internal/config/claude/claude.go index efbfbf331..0a82f8058 100644 --- a/internal/config/claude/claude.go +++ b/internal/config/claude/claude.go @@ -38,6 +38,16 @@ const ( const ( // ModelOpus is the substring identifying Opus models (always 1M). ModelOpus = "opus" + // ModelFable is the substring identifying Fable models + // (Claude 5 family, Mythos-class; always 1M). + ModelFable = "fable" + // ModelMythos is the substring identifying Mythos models + // (same underlying model as Fable; always 1M). + ModelMythos = "mythos" + // ModelSonnet5 is the substring identifying Sonnet 5+ models, + // which carry a 1M window as standard (earlier Sonnets gate 1M + // behind the [1m] opt-in, covered by ModelSuffix1M). + ModelSonnet5 = "sonnet-5" ) // Context window sizes. diff --git a/internal/config/claude/doc.go b/internal/config/claude/doc.go index 7de4efa5f..310342e1d 100644 --- a/internal/config/claude/doc.go +++ b/internal/config/claude/doc.go @@ -22,6 +22,10 @@ // context window. // - [ModelOpus] detects Opus-family models, which // always have 1M context. +// - [ModelFable] and [ModelMythos] detect the Claude 5 +// Mythos-class families, which always have 1M context. +// - [ModelSonnet5] detects Sonnet 5+, which carries a 1M +// window as standard. // - [ContextWindow1M] is the numeric window size used // for budget calculations. // diff --git a/specs/model-context-window-fable.md b/specs/model-context-window-fable.md new file mode 100644 index 000000000..1cfbdcb31 --- /dev/null +++ b/specs/model-context-window-fable.md @@ -0,0 +1,46 @@ +# Model Context Window: Claude 5 (Fable/Mythos/Sonnet 5) Detection + +**Status:** Implemented + +## Problem + +`ModelContextWindow` (internal/cli/system/core/session/session_token.go) +recognizes 1M-window models by the explicit `[1m]` suffix or the `opus` +family substring. The Claude 5 Mythos-class models (`claude-fable-5`, +`claude-mythos-5`) match neither, so detection falls through to +`rc.DefaultContextWindow` (200k). Every consumer of +`EffectiveContextWindow` — the check-context-size hook, heartbeat, +nudges, provenance — then computes percentages against 200k on a 1M +session: at ~208k real usage the hook warned "104% full" while the +actual window was 79% free. + +## Fix + +Add `ModelFable` ("fable"), `ModelMythos` ("mythos"), and +`ModelSonnet5` ("sonnet-5") family substrings to +`internal/config/claude` and include them in the always-1M branch +of `ModelContextWindow`, alongside `ModelOpus`. Substring matching +over the folded model ID mirrors the existing Opus detection, so +dated variants (`claude-fable-5-YYYYMMDD`) are covered. Sonnet 5's +1M window is standard per Anthropic's current model catalog +(unlike earlier Sonnets, whose 1M is an explicit `[1m]` opt-in +already handled by `ModelSuffix1M`). "sonnet-5" does not +substring-match `claude-sonnet-4-5`, so legacy Sonnets are +unaffected. + +## Verification + +- `TestModelContextWindow` gains cases: `claude-fable-5`, + `claude-mythos-5`, and `claude-sonnet-5` → + `claude.ContextWindow1M`. +- `go test ./internal/cli/system/core/session/...` passes. + +## Non-Goals + +- Re-mapping `claude-sonnet-4-6` (also 1M at the API level): ctx + deliberately models Claude Code's per-session gating for that + generation — 200k default, 1M via the `[1m]` suffix or settings + opt-in — and the existing test pins that behavior. Revisit only + with session-level evidence. +- A remote model-capability registry; the substring table is the + intended low-maintenance mechanism. From f37fd9fe5b2e401df97a2577315b3db7ebc72a50 Mon Sep 17 00:00:00 2001 From: Jose Alekhinne Date: Fri, 3 Jul 2026 18:19:40 -0700 Subject: [PATCH 3/3] chore: refresh go.work.sum Lockfile hash additions picked up by the Go toolchain; no dependency changes in go.mod/go.work. Spec: specs/meta/chores.md Signed-off-by: Jose Alekhinne --- go.work.sum | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/go.work.sum b/go.work.sum index 64a2b976f..0ad5768dd 100644 --- a/go.work.sum +++ b/go.work.sum @@ -85,12 +85,18 @@ go.opentelemetry.io/contrib/detectors/gcp v1.42.0/go.mod h1:W9zQ439utxymRrXsUOzZ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/telemetry v0.0.0-20260508192327-42602be52be6 h1:HjU6IWBiAgRIdAJ9/y1rwCn+UELEmwV+VsTLzj/W4sE= golang.org/x/telemetry v0.0.0-20260508192327-42602be52be6/go.mod h1:Eqhaxk/wZsWEH8CRxLwj6xzEJbz7k1EFGqx7nyCoabE= +golang.org/x/telemetry v0.0.0-20260610154732-fb80ec83bdd9 h1:FjUup8XrRy7lv+XHONi6KKUSizeF2NnVrTnz/HhbohQ= +golang.org/x/telemetry v0.0.0-20260610154732-fb80ec83bdd9/go.mod h1:3AWMyWHS+caVoiEXpiq6+tzKA40J4vQT3MYr80ZtQpc= golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=