From 21393a1913009e285510006e2b5713b4598107af Mon Sep 17 00:00:00 2001 From: David Abram Date: Mon, 3 Aug 2026 12:22:46 +0200 Subject: [PATCH 1/2] workflows: Add package-local phase references Move phase instructions and persisted-document formats out of phase-based workflow entrypoints while retaining control flow, branching, and waits in each SKILL.md. Render the new package inventory consistently for Claude, OpenCode, and Pi, and enforce resolvable references through generation contracts. Co-authored-by: SCE --- .claude/skills/sce-change-to-plan/SKILL.md | 525 +-- .../references/context-load.md | 89 + .../references/plan-authoring.md | 256 ++ .../references/plan-template.md | 170 + .claude/skills/sce-commit/SKILL.md | 141 +- .../sce-commit/references/atomic-commit.md | 130 + .claude/skills/sce-next-task/SKILL.md | 642 +-- .../sce-next-task/references/context-sync.md | 316 ++ .../sce-next-task/references/plan-review.md | 121 + .../references/task-execution.md | 203 + .claude/skills/sce-validate/SKILL.md | 564 +-- .../sce-validate/references/context-sync.md | 306 ++ .../skills/sce-validate/references/output.md | 6 +- .../references/validation-report.md | 84 + .../sce-validate/references/validation.md | 161 + .opencode/skills/sce-change-to-plan/SKILL.md | 525 +-- .../references/context-load.md | 89 + .../references/plan-authoring.md | 256 ++ .../references/plan-template.md | 170 + .opencode/skills/sce-commit/SKILL.md | 141 +- .../sce-commit/references/atomic-commit.md | 130 + .opencode/skills/sce-next-task/SKILL.md | 642 +-- .../sce-next-task/references/context-sync.md | 316 ++ .../sce-next-task/references/plan-review.md | 121 + .../references/task-execution.md | 203 + .opencode/skills/sce-validate/SKILL.md | 564 +-- .../sce-validate/references/context-sync.md | 306 ++ .../skills/sce-validate/references/output.md | 6 +- .../references/validation-report.md | 84 + .../sce-validate/references/validation.md | 161 + .pi/skills/sce-change-to-plan/SKILL.md | 525 +-- .../references/context-load.md | 89 + .../references/plan-authoring.md | 256 ++ .../references/plan-template.md | 170 + .pi/skills/sce-commit/SKILL.md | 141 +- .../sce-commit/references/atomic-commit.md | 130 + .pi/skills/sce-next-task/SKILL.md | 642 +-- .../sce-next-task/references/context-sync.md | 316 ++ .../sce-next-task/references/plan-review.md | 121 + .../references/task-execution.md | 203 + .pi/skills/sce-validate/SKILL.md | 564 +-- .../sce-validate/references/context-sync.md | 306 ++ .pi/skills/sce-validate/references/output.md | 6 +- .../references/validation-report.md | 84 + .../sce-validate/references/validation.md | 161 + config/pkl/base/workflow-change-to-plan.pkl | 7 + config/pkl/base/workflow-commit.pkl | 5 + config/pkl/base/workflow-content.pkl | 3445 +++++++++++++++++ config/pkl/base/workflow-next-task.pkl | 7 + config/pkl/base/workflow-validate.pkl | 7 + .../renderers/generation-contract-check.pkl | 77 +- .../pkl/renderers/metadata-coverage-check.pkl | 40 +- config/pkl/renderers/workflow-composite.pkl | 88 +- context/architecture.md | 22 +- context/context-map.md | 9 +- ...local-phase-reference-workflow-packages.md | 65 + context/glossary.md | 11 +- context/overview.md | 6 +- context/patterns.md | 12 +- .../canonicalize-workflow-phase-references.md | 99 + context/sce/atomic-commit-workflow.md | 10 +- context/sce/shared-context-code-workflow.md | 8 +- context/sce/shared-context-plan-workflow.md | 5 +- 63 files changed, 9686 insertions(+), 5379 deletions(-) create mode 100644 .claude/skills/sce-change-to-plan/references/context-load.md create mode 100644 .claude/skills/sce-change-to-plan/references/plan-authoring.md create mode 100644 .claude/skills/sce-change-to-plan/references/plan-template.md create mode 100644 .claude/skills/sce-commit/references/atomic-commit.md create mode 100644 .claude/skills/sce-next-task/references/context-sync.md create mode 100644 .claude/skills/sce-next-task/references/plan-review.md create mode 100644 .claude/skills/sce-next-task/references/task-execution.md create mode 100644 .claude/skills/sce-validate/references/context-sync.md create mode 100644 .claude/skills/sce-validate/references/validation-report.md create mode 100644 .claude/skills/sce-validate/references/validation.md create mode 100644 .opencode/skills/sce-change-to-plan/references/context-load.md create mode 100644 .opencode/skills/sce-change-to-plan/references/plan-authoring.md create mode 100644 .opencode/skills/sce-change-to-plan/references/plan-template.md create mode 100644 .opencode/skills/sce-commit/references/atomic-commit.md create mode 100644 .opencode/skills/sce-next-task/references/context-sync.md create mode 100644 .opencode/skills/sce-next-task/references/plan-review.md create mode 100644 .opencode/skills/sce-next-task/references/task-execution.md create mode 100644 .opencode/skills/sce-validate/references/context-sync.md create mode 100644 .opencode/skills/sce-validate/references/validation-report.md create mode 100644 .opencode/skills/sce-validate/references/validation.md create mode 100644 .pi/skills/sce-change-to-plan/references/context-load.md create mode 100644 .pi/skills/sce-change-to-plan/references/plan-authoring.md create mode 100644 .pi/skills/sce-change-to-plan/references/plan-template.md create mode 100644 .pi/skills/sce-commit/references/atomic-commit.md create mode 100644 .pi/skills/sce-next-task/references/context-sync.md create mode 100644 .pi/skills/sce-next-task/references/plan-review.md create mode 100644 .pi/skills/sce-next-task/references/task-execution.md create mode 100644 .pi/skills/sce-validate/references/context-sync.md create mode 100644 .pi/skills/sce-validate/references/validation-report.md create mode 100644 .pi/skills/sce-validate/references/validation.md create mode 100644 context/decisions/2026-08-03-package-local-phase-reference-workflow-packages.md create mode 100644 context/plans/canonicalize-workflow-phase-references.md diff --git a/.claude/skills/sce-change-to-plan/SKILL.md b/.claude/skills/sce-change-to-plan/SKILL.md index b54e23a4..7fbc8c03 100644 --- a/.claude/skills/sce-change-to-plan/SKILL.md +++ b/.claude/skills/sce-change-to-plan/SKILL.md @@ -15,6 +15,25 @@ not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or workflow command. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/context-load.md` | +| 2 and 4 | `references/plan-authoring.md` | + +`references/plan-template.md` defines the plan file written to disk. The plan +authoring phase points to it at the moment a plan is actually written, which never +happens on a `needs_clarification` or `blocked` result. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at the +bootstrap gate never authors a plan, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -47,87 +66,11 @@ Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is ### 1. Load durable context -Run the **Context load phase** with the change request as the focus. +Read `references/context-load.md`, then run the **Context load phase** with the +change request as the focus. `context/` is durable AI-first memory describing current state. Load it before planning so the plan starts from recorded truth. Where context and code disagree, the code is the source of truth. -#### 1.1 Confirm the context root - -When `context/` does not exist, set internal status `bootstrap_required` immediately. Read -nothing further. - -Bootstrapping is the workflow's decision, not this phase's. - -#### 1.2 Read the entry points - -Read, when present: - -- `context/context-map.md` -- `context/overview.md` -- `context/glossary.md` - -Read `context/architecture.md` when the focus touches structure, boundaries, or -data flow. Read `context/patterns.md` when it touches conventions the change -must follow. - -A missing entry point is a gap, not a failure. Record it and continue. - -#### 1.3 Select the relevant domain context - -Consult `context/context-map.md` before any broad exploration. The map's -annotations name what each domain file owns; use them to select files, rather -than globbing or searching `context/`. - -Select only files whose subject overlaps the focus. Follow at most one level of -links out of a selected file, and only when the link is needed to understand the -focus. - -Do not read every domain file. A brief that includes everything has selected -nothing. - -Record focus areas with no matching context file under `gaps`. - -#### 1.4 Check recorded context against the code - -For each selected file, spot-check its central claims against the code it -describes. - -When context and code diverge, the code is the source of truth. Record the -divergence under `drift` with what context says, what the code shows, and the -repair the context needs. - -Do not repair it here. Later phases decide whether repair belongs in the current -work. - -Keep this proportional: check the claims the focus depends on, not every -sentence. - -#### 1.5 Return the brief - -Set exactly one internal state: - -- `loaded` -- `bootstrap_required` - -Report facts the workflow can act on. A brief that only lists file -paths has moved no knowledge. - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Context load boundaries - -Do not: - -- Create, update, move, or delete any file under `context/`. -- Bootstrap `context/`. -- Repair drift or stale context. -- Modify application code or tests. -- Read the entire `context/` tree by default. -- Explore the repository beyond what the focus and the selected context require. -- Ask the user questions. Report gaps and drift, and let the workflow decide. -- Author a plan, select a task, or implement anything. - Branch on `status`: `bootstrap_required` -> `context/` does not exist. Do not create it, and do not plan without it. Render the **Missing context bootstrap gate** layout from `references/output.md`. @@ -140,256 +83,18 @@ Do not read `context/` yourself. Do not repair drift or stale context; the brief ### 2. Author the plan -Run the **Plan authoring phase** with the change request and the complete `loaded` brief from the **Context load phase**. +Read `references/plan-authoring.md`, then run the **Plan authoring phase** with +the change request and the complete `loaded` brief from the **Context load +phase**. Pass the brief verbatim. Do not restate, summarize, or reinterpret it. -The **Plan authoring phase** exclusively owns: - -- Resolving whether the request targets a new or an existing plan. -- The clarification gate. -- Normalizing the change summary, acceptance criteria, constraints, and non-goals. -- Slicing the task stack into one-task/one-atomic-commit units. -- Writing `context/plans/{plan_name}.md`. - -Do not duplicate any of it. Do not write or edit the plan file yourself. - -Use the document format defined in the **Plan template** section embedded in this file. - -The workflow renders that result as the summary defined in: - -`references/output.md` - -The change request may name a plan, describe a change to an existing plan, or -describe entirely new work. Resolving which applies is this phase's -responsibility. - -The context brief is the durable memory this plan starts from. Treat its -`key_facts` as recorded current state, its `gaps` as areas with no durable -context, and its `drift` as context the code has already outrun. - -When no brief is supplied, load the context named by the change request before -authoring, and follow the selection discipline in *Inspect relevant context*. - -Answers the user gave to earlier clarification questions arrive as part of the -change request. Incorporate them into the plan. - -A revision of a plan authored earlier in the session also arrives as the change -request, and it is usually terse: a task boundary the user disagrees with, an -ordering they want changed, work they want added or dropped. Read it against the -existing plan, which supplies the scope, criteria, and terminology it omits. -Terseness is not ambiguity. Do not set internal status `needs_clarification` for detail the -plan already carries; ask only when the revision itself is genuinely undecidable. - -#### 2.1 Resolve the plan target - -Determine whether the request targets a new plan or an existing plan in -`context/plans/`. - -When it targets an existing plan, read that plan before authoring. Preserve its -completed tasks, their recorded evidence, its structure, and its terminology. - -When multiple existing plans match and none can be selected safely, return -`blocked` with the matching candidates. - -When the request targets a new plan, derive `plan_name` as a short kebab-case -slug of the change, and confirm it does not collide with an existing plan. - -Resolve exactly one plan target per invocation. - -#### 2.2 Challenge the change - -Before planning how to build the change, work out whether it is worth building. -A plan is a commitment of someone's time; authoring one for work that should not -happen is worse than authoring none. - -Interrogate the request: - -- What breaks, or stays broken, if this is never built? If the answer is - nothing concrete, say so. -- What problem is it actually solving, as opposed to what it proposes to do? A - request that names only a solution has not stated a problem. -- Does the repository already do this, or most of it? The brief's `key_facts` - are the first place to check. -- Is there a materially smaller version that gets most of the value? Name it. -- What does this cost beyond the tasks: new dependency, new concept in the - glossary, a boundary crossed, a surface that now needs maintaining forever? -- Does the stated justification survive contact with the code, or does the code - show the premise is already false? - -Doubt that survives this is not an implementation detail to be tidied away. It -belongs in the plan's `Open questions` and in `open_questions`, in the plain -words you would use to a colleague. "Is this worth doing at all, given X?" is a -legitimate open question. So is "this looks like it duplicates Y". - -Weigh honestly in both directions. A request that is obviously worth building -gets no manufactured doubt: inventing questions to look rigorous is its own -failure, and it teaches the user to ignore the section. Most changes are fine. -Say nothing when there is nothing to say. - -Keep going regardless. Skepticism shapes the plan and the open questions; it -does not withhold the plan. The only value judgment that stops authoring is -`no_actionable_work`, when the change is already implemented. - -#### 2.3 Run the clarification gate - -Before writing or updating any plan file, check the request for critical -unresolved detail: - -- Scope boundaries and out-of-scope items. -- Acceptance criteria and the checks that prove them. -- Constraints and non-goals. -- Dependency choices, including new libraries or services, versions, and the - integration approach. -- Domain ambiguity, including unclear business rules, terminology, or ownership. -- Architecture concerns, including patterns, interfaces, data flow, migration - strategy, and risk tradeoffs. -- Task ordering assumptions and prerequisite sequencing. - -Set internal status `needs_clarification` with one to three targeted questions when any of -these would materially change the plan. Write no plan file in that case. - -Use repository conventions for ordinary local choices. Do not block on: +This phase challenges whether the change is worth building before planning how to +build it, and it decides on its own whether to stop at the clarification gate. +Both shape what reaches the user, so reach them through the reference rather than +acting from this summary. -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change scope, acceptance criteria, or task ordering. - -Record those choices under `assumptions`. - -Do not silently invent missing requirements. When the user has explicitly -allowed assumptions, record them in the plan's `Assumptions` section instead of -asking. - -A justification that does not survive inspection is itself a critical unresolved -detail. "For consistency", "to make it cleaner", "we will need it later" name no -outcome and prove nothing; ask what the change is actually for before planning -around it. Do not treat confident phrasing as evidence. - -#### 2.4 Inspect relevant context - -Start from the context brief. Read code only where the brief leaves the change -underspecified: - -- Existing behavior the change affects. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests and available verification commands. -- Decisions or specifications connected to the change. - -Where the brief reports `drift`, the code is the source of truth. Plan against -the code, and schedule the context repair as part of the change when it falls -inside scope. - -Where the brief reports `gaps`, the plan may need to establish durable context -the repository does not yet have. - -Do not explore the entire repository by default. - -#### 2.5 Author the acceptance criteria - -State how the finished plan is proven, before slicing tasks. - -Each criterion describes observable behavior of the finished system and names -the check that proves it. Record repository-wide checks once under -`Full validation`, and the durable context the change must be reflected in -under `Context sync`. - -`/validate` runs this section after the last task completes. It is the only -place a plan says how it is validated. - -#### 2.6 Author the task stack - -Slice the work into sequential tasks `T01..T0N` using the task format and the -atomic slicing contract in the **Plan template** section embedded in this file. - -Every executable task must be completable and landable as one coherent commit. -Split any task that would require multiple independent commits. Convert broad -wrappers such as `polish` or `finalize` into specific outcomes with concrete -acceptance checks. - -Order tasks so each one's declared dependencies precede it. - -The last task is an ordinary implementation task. Do not author a trailing -validation-and-cleanup task, or any task whose only purpose is running the full -check suite, verifying durable context, or removing scaffolding. - -Confirm every acceptance criterion is satisfied by at least one task. When one -is not, the task stack is incomplete. - -A finished stack always leaves at least one incomplete task, so the workflow -can always hand off to `/next-task`. When the request resolves to a -plan but produces no incomplete task, because the change is already implemented -or already covered by completed tasks, set internal status `blocked` with category -`no_actionable_work` instead of writing the plan. - -#### 2.7 Write the plan - -Write `context/plans/{plan_name}.md` using the **Plan template** section embedded in this file. - -When updating an existing plan, keep completed tasks and their evidence intact, -and append or renumber new tasks without disturbing recorded history. - -#### 2.8 Return the result - -Set exactly one internal state: - -- `plan_ready` -- `needs_clarification` -- `blocked` - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Plan authoring tone - -Every question and open question this phase writes is read by the user. Write -them the way a senior engineer talks in review: direct, specific, and unbothered -by the possibility of being unwelcome. - -- Ask about the thing that actually worries you, not a safer neighbouring thing. - A question you would not bother asking a colleague is not worth the user's - attention either. -- State a doubt as a doubt. "I do not think this is worth the two tasks it - costs, because X" is useful. "It may be worth considering whether this aligns - with broader goals" is noise. -- Name the alternative you have in mind. A challenge with no proposal behind it - is just friction. -- Do not open with praise, do not close with reassurance, and do not apologize - for asking. Do not pad a doubt with hedges to make it land more gently. -- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not - restate the same doubt in three shapes to give it more weight. -- Being disagreeable is not the goal. Being easy to agree with is the failure - mode. A plan the user waves through without reading has cost them nothing and - bought them nothing. - -When the user overrules a doubt, record it and move on. Do not relitigate a -decision the user has made, and do not smuggle the objection back in as a -constraint, a non-goal, or a task. - -### Plan authoring boundaries - -Do not: - -- Ask the user questions directly. Set internal status `needs_clarification` and let the - workflow present the questions. -- Answer your own clarification questions. -- Write a plan file when returning `needs_clarification` or `blocked`. -- Implement any task in the plan. -- Modify application code or tests. -- Modify any file under `context/` outside `context/plans/`. Plan the context - repair instead of performing it. -- Mark any task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Author a validation, cleanup, or context-verification task. `/validate` owns - that phase. -- Set internal status `plan_ready` for a plan with no incomplete task. -- Create a Git commit. -- Author more than one plan. +Do not write or edit the plan file yourself. Branch on `status`: @@ -442,6 +147,7 @@ Stop. ## Rules - Plan at most one change request per invocation. Revisions to the plan that request produced are part of the same invocation, not a second request. +- Read each phase's reference before running that phase. - Always tell the user the plan can be revised, and always name its assumptions as the first thing worth checking. - Do not gate the handoff on open questions listed in the plan summary. Blocking questions return `needs_clarification` before any plan is written. Offering revision is not the same as demanding it, and inventing doubts to justify a review gate is not allowed. - Do not suppress, soften, or answer an open question or clarification question on the user's behalf. @@ -458,174 +164,3 @@ Stop. - Do not answer the skill's clarification questions on the user's behalf. - Do not execute the continuation returned at the end. - Do not infer success when the **Plan authoring phase** returns a non-`plan_ready` status. - -## Internal persisted-document format: Plan template - -The document format for `context/plans/{plan_name}.md`. This is the plan file -written to disk, not the result returned to the workflow. - -Copy the template below and fill every `{placeholder}`. Omit optional sections -entirely rather than writing them empty. - ---- - -### Template - -```markdown -# Plan: {plan-name} - -## Change summary - -{One or two paragraphs: what changes, where, and why. State whether this -extends existing behavior, replaces it, or preserves work already in progress.} - -## Acceptance criteria - -How this plan is proven complete. Each criterion is observable and names the -check that proves it. `/validate` runs these checks; no task in the stack -performs final validation. - -- [ ] AC1: {observable outcome, stated as behavior rather than as work done} - - Validate: `{command, assertion, or inspection that proves AC1}` -- [ ] AC2: {observable outcome} - - Validate: `{command, assertion, or inspection that proves AC2}` - -### Full validation - -Repository-wide checks `/validate` runs after the last task, regardless of -which criterion they map to. - -- `{full check suite command}` -- `{generated-output or parity check command, when applicable}` - -### Context sync - -- {Durable context files that must describe the change once implemented.} - -## Constraints and non-goals - -- **In scope:** {files, modules, and surfaces this plan may touch} -- **Out of scope:** {adjacent work explicitly excluded} -- **Constraints:** {dependencies, conventions, compatibility, or policy limits} -- **Non-goal:** {tempting generalization this plan deliberately avoids} - -## Assumptions - -{Include only when the user allowed assumptions, or ordinary local choices were -recorded. Remove the section otherwise.} - -- {Assumption, and the convention or decision record it rests on.} - -## Task stack - -- [ ] T01: `{single intent title}` (status:todo) - - Task ID: T01 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: {task IDs, or none} - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -- [ ] T02: `{single intent title}` (status:todo) - - Task ID: T02 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: T01 - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -## Open questions - -{Non-blocking questions only. A question that would change scope, success -criteria, or task ordering blocks authoring instead. Write `None.` with a short -justification when nothing remains.} - -{Unresolved doubt about the change's value belongs here — whether it is worth -building, whether it duplicates behavior the repository already has, whether a -smaller version would do. State it plainly and name the alternative. Do not -invent one: `None.` is the expected answer for a well-specified change.} -``` - ---- - -### Filled-in task example - -```markdown -- [ ] T02: `Add /auth/refresh endpoint` (status:todo) - - Task ID: T02 - - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. - - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. - - Dependencies: T01 - - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. - - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. -``` - -### Acceptance criteria rules - -- Acceptance criteria describe the finished system, not the work. Prefer "the - endpoint returns 401 on an expired token" over "add expiry handling". -- Every criterion carries a `Validate:` line. A criterion nobody can check is - not an acceptance criterion. -- Prefer a runnable command. Fall back to a named inspection only when no - automated check exists, and say exactly what to look at. -- List repository-wide checks once under `Full validation` instead of repeating - them per criterion. -- Task-level `Verification notes` prove one task. Acceptance criteria prove the - plan. Keep them distinct: a task's checks are narrow and local, a criterion's - check is end-to-end. -- The union of the acceptance criteria must cover every success signal in the - change request. If a criterion has no task that could satisfy it, the task - stack is incomplete. - -### Task rules - -- Every task is a checkbox line so progress stays machine-readable: - `- [ ] T01: {title} (status:todo)`. -- Author each executable task as one atomic commit unit by default. -- Scope every task so one contributor can complete it and land it as one - coherent commit without bundling unrelated changes. -- Split any candidate task that would require multiple independent commits, for - example a refactor plus a behavior change plus documentation. -- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of - executable tasks. Convert them into specific outcomes with concrete - acceptance checks. -- Order tasks so each one's declared dependencies precede it. - -### No validation task - -- The last task in the stack is an ordinary implementation task. Do not author a - trailing "validation and cleanup" task. -- Final validation, cleanup, and success-criteria verification are run by - `/validate` from the `Acceptance criteria` section after the last task - completes. -- Do not author a task whose only purpose is running the full check suite, - verifying durable context, or removing scaffolding. -- A task may still create or update durable context when that context is part of - the change itself. - -### Completion records - -When a task completes, the **Task execution phase** appends its evidence and flips the -checkbox and status: - -```markdown -- [x] T01: `{title}` (status:done) - - {authored fields, unchanged} - - Completed: {YYYY-MM-DD} - - Files changed: {paths} - - Evidence: {commands run and their outcomes} - - Notes: {material deviations or approved assumptions} -``` - -`/validate` appends a `## Validation Report` section at the end of the plan. -Do not author either while planning. - -### Updating an existing plan - -- Preserve completed tasks, their `(status:done)` markers, and their recorded - evidence verbatim. -- Preserve the plan's existing structure and terminology. -- Append new tasks after the existing stack. Renumber only when added work must - run earlier, and never renumber a completed task. -- Add acceptance criteria for newly planned outcomes rather than rewriting - criteria already satisfied. diff --git a/.claude/skills/sce-change-to-plan/references/context-load.md b/.claude/skills/sce-change-to-plan/references/context-load.md new file mode 100644 index 00000000..197a28c2 --- /dev/null +++ b/.claude/skills/sce-change-to-plan/references/context-load.md @@ -0,0 +1,89 @@ +# Context load phase + +Run this phase for step 1 of the workflow, with the change request as the focus. + +`context/` is durable AI-first memory describing current state. Load it before +planning so the plan starts from recorded truth. Where context and code disagree, +the code is the source of truth. + +This phase reads and reports; it never writes. + +## 1.1 Confirm the context root + +When `context/` does not exist, set internal status `bootstrap_required` +immediately. Read nothing further. + +Bootstrapping is the workflow's decision, not this phase's. + +## 1.2 Read the entry points + +Read, when present: + +- `context/context-map.md` +- `context/overview.md` +- `context/glossary.md` + +Read `context/architecture.md` when the focus touches structure, boundaries, or +data flow. Read `context/patterns.md` when it touches conventions the change must +follow. + +A missing entry point is a gap, not a failure. Record it and continue. + +## 1.3 Select the relevant domain context + +Consult `context/context-map.md` before any broad exploration. The map's +annotations name what each domain file owns; use them to select files, rather +than globbing or searching `context/`. + +Select only files whose subject overlaps the focus. Follow at most one level of +links out of a selected file, and only when the link is needed to understand the +focus. + +Do not read every domain file. A brief that includes everything has selected +nothing. + +Record focus areas with no matching context file under `gaps`. + +## 1.4 Check recorded context against the code + +For each selected file, spot-check its central claims against the code it +describes. + +When context and code diverge, the code is the source of truth. Record the +divergence under `drift` with what context says, what the code shows, and the +repair the context needs. + +Do not repair it here. Later phases decide whether repair belongs in the current +work. + +Keep this proportional: check the claims the focus depends on, not every +sentence. + +## 1.5 Return the brief + +Set exactly one internal state: + +- `loaded` +- `bootstrap_required` + +Report facts the workflow can act on. A brief that only lists file paths has +moved no knowledge. + +Record only the internal state. Do not add explanatory prose before or after it. + +Step 2 consumes a `loaded` brief verbatim and treats its `key_facts` as recorded +current state, its `gaps` as areas with no durable context, and its `drift` as +context the code has already outrun. + +## Context load boundaries + +Do not: + +- Create, update, move, or delete any file under `context/`. +- Bootstrap `context/`. +- Repair drift or stale context. +- Modify application code or tests. +- Read the entire `context/` tree by default. +- Explore the repository beyond what the focus and the selected context require. +- Ask the user questions. Report gaps and drift, and let the workflow decide. +- Author a plan, select a task, or implement anything. diff --git a/.claude/skills/sce-change-to-plan/references/plan-authoring.md b/.claude/skills/sce-change-to-plan/references/plan-authoring.md new file mode 100644 index 00000000..17e054e2 --- /dev/null +++ b/.claude/skills/sce-change-to-plan/references/plan-authoring.md @@ -0,0 +1,256 @@ +# Plan authoring phase + +Run this phase for step 2 of the workflow, and again for each revision in step 4. + +Input: the change request, and the complete `loaded` brief from the context load +phase. Pass the brief verbatim; do not restate, summarize, or reinterpret it. + +This phase exclusively owns: + +- Resolving whether the request targets a new or an existing plan. +- The clarification gate. +- Normalizing the change summary, acceptance criteria, constraints, and non-goals. +- Slicing the task stack into one-task/one-atomic-commit units. +- Writing `context/plans/{plan_name}.md`. + +Do not duplicate any of it elsewhere in the workflow. + +Use the document format in `references/plan-template.md`. Read it before writing +the plan file. + +The workflow renders this phase's result as the summary defined in +`references/output.md`. + +The change request may name a plan, describe a change to an existing plan, or +describe entirely new work. Resolving which applies is this phase's +responsibility. + +The context brief is the durable memory this plan starts from. Treat its +`key_facts` as recorded current state, its `gaps` as areas with no durable +context, and its `drift` as context the code has already outrun. + +When no brief is supplied, load the context named by the change request before +authoring, and follow the selection discipline in *Inspect relevant context*. + +Answers the user gave to earlier clarification questions arrive as part of the +change request. Incorporate them into the plan. + +A revision of a plan authored earlier in the session also arrives as the change +request, and it is usually terse: a task boundary the user disagrees with, an +ordering they want changed, work they want added or dropped. Read it against the +existing plan, which supplies the scope, criteria, and terminology it omits. +Terseness is not ambiguity. Do not set internal status `needs_clarification` for +detail the plan already carries; ask only when the revision itself is genuinely +undecidable. + +## 2.1 Resolve the plan target + +Determine whether the request targets a new plan or an existing plan in +`context/plans/`. + +When it targets an existing plan, read that plan before authoring. Preserve its +completed tasks, their recorded evidence, its structure, and its terminology. + +When multiple existing plans match and none can be selected safely, return +`blocked` with the matching candidates. + +When the request targets a new plan, derive `plan_name` as a short kebab-case +slug of the change, and confirm it does not collide with an existing plan. + +Resolve exactly one plan target per invocation. + +## 2.2 Challenge the change + +Before planning how to build the change, work out whether it is worth building. A +plan is a commitment of someone's time; authoring one for work that should not +happen is worse than authoring none. + +Interrogate the request: + +- What breaks, or stays broken, if this is never built? If the answer is nothing + concrete, say so. +- What problem is it actually solving, as opposed to what it proposes to do? A + request that names only a solution has not stated a problem. +- Does the repository already do this, or most of it? The brief's `key_facts` are + the first place to check. +- Is there a materially smaller version that gets most of the value? Name it. +- What does this cost beyond the tasks: new dependency, new concept in the + glossary, a boundary crossed, a surface that now needs maintaining forever? +- Does the stated justification survive contact with the code, or does the code + show the premise is already false? + +Doubt that survives this is not an implementation detail to be tidied away. It +belongs in the plan's `Open questions` and in `open_questions`, in the plain +words you would use to a colleague. "Is this worth doing at all, given X?" is a +legitimate open question. So is "this looks like it duplicates Y". + +Weigh honestly in both directions. A request that is obviously worth building +gets no manufactured doubt: inventing questions to look rigorous is its own +failure, and it teaches the user to ignore the section. Most changes are fine. +Say nothing when there is nothing to say. + +Keep going regardless. Skepticism shapes the plan and the open questions; it does +not withhold the plan. The only value judgment that stops authoring is +`no_actionable_work`, when the change is already implemented. + +## 2.3 Run the clarification gate + +Before writing or updating any plan file, check the request for critical +unresolved detail: + +- Scope boundaries and out-of-scope items. +- Acceptance criteria and the checks that prove them. +- Constraints and non-goals. +- Dependency choices, including new libraries or services, versions, and the + integration approach. +- Domain ambiguity, including unclear business rules, terminology, or ownership. +- Architecture concerns, including patterns, interfaces, data flow, migration + strategy, and risk tradeoffs. +- Task ordering assumptions and prerequisite sequencing. + +Set internal status `needs_clarification` with one to three targeted questions +when any of these would materially change the plan. Write no plan file in that +case. + +Use repository conventions for ordinary local choices. Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change scope, acceptance criteria, or task ordering. + +Record those choices under `assumptions`. + +Do not silently invent missing requirements. When the user has explicitly allowed +assumptions, record them in the plan's `Assumptions` section instead of asking. + +A justification that does not survive inspection is itself a critical unresolved +detail. "For consistency", "to make it cleaner", "we will need it later" name no +outcome and prove nothing; ask what the change is actually for before planning +around it. Do not treat confident phrasing as evidence. + +## 2.4 Inspect relevant context + +Start from the context brief. Read code only where the brief leaves the change +underspecified: + +- Existing behavior the change affects. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests and available verification commands. +- Decisions or specifications connected to the change. + +Where the brief reports `drift`, the code is the source of truth. Plan against +the code, and schedule the context repair as part of the change when it falls +inside scope. + +Where the brief reports `gaps`, the plan may need to establish durable context +the repository does not yet have. + +Do not explore the entire repository by default. + +## 2.5 Author the acceptance criteria + +State how the finished plan is proven, before slicing tasks. + +Each criterion describes observable behavior of the finished system and names the +check that proves it. Record repository-wide checks once under `Full validation`, +and the durable context the change must be reflected in under `Context sync`. + +`/validate` runs this section after the last task completes. It is the only place +a plan says how it is validated. + +## 2.6 Author the task stack + +Slice the work into sequential tasks `T01..T0N` using the task format and the +atomic slicing contract in `references/plan-template.md`. + +Every executable task must be completable and landable as one coherent commit. +Split any task that would require multiple independent commits. Convert broad +wrappers such as `polish` or `finalize` into specific outcomes with concrete +acceptance checks. + +Order tasks so each one's declared dependencies precede it. + +The last task is an ordinary implementation task. Do not author a trailing +validation-and-cleanup task, or any task whose only purpose is running the full +check suite, verifying durable context, or removing scaffolding. + +Confirm every acceptance criterion is satisfied by at least one task. When one is +not, the task stack is incomplete. + +A finished stack always leaves at least one incomplete task, so the workflow can +always hand off to `/next-task`. When the request resolves to a plan but produces +no incomplete task, because the change is already implemented or already covered +by completed tasks, set internal status `blocked` with category +`no_actionable_work` instead of writing the plan. + +## 2.7 Write the plan + +Write `context/plans/{plan_name}.md` using `references/plan-template.md`. + +When updating an existing plan, keep completed tasks and their evidence intact, +and append or renumber new tasks without disturbing recorded history. + +## 2.8 Return the result + +Set exactly one internal state: + +- `plan_ready` +- `needs_clarification` +- `blocked` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `plan_ready` result always names the next task in `next_task`, and carries the +`total_tasks` count and any open questions the summary needs. Step 3 renders those +without recomputing them. + +## Plan authoring tone + +Every question and open question this phase writes is read by the user. Write +them the way a senior engineer talks in review: direct, specific, and unbothered +by the possibility of being unwelcome. + +- Ask about the thing that actually worries you, not a safer neighbouring thing. + A question you would not bother asking a colleague is not worth the user's + attention either. +- State a doubt as a doubt. "I do not think this is worth the two tasks it + costs, because X" is useful. "It may be worth considering whether this aligns + with broader goals" is noise. +- Name the alternative you have in mind. A challenge with no proposal behind it + is just friction. +- Do not open with praise, do not close with reassurance, and do not apologize + for asking. Do not pad a doubt with hedges to make it land more gently. +- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not + restate the same doubt in three shapes to give it more weight. +- Being disagreeable is not the goal. Being easy to agree with is the failure + mode. A plan the user waves through without reading has cost them nothing and + bought them nothing. + +When the user overrules a doubt, record it and move on. Do not relitigate a +decision the user has made, and do not smuggle the objection back in as a +constraint, a non-goal, or a task. + +## Plan authoring boundaries + +Do not: + +- Ask the user questions directly. Set internal status `needs_clarification` and let the + workflow present the questions. +- Answer your own clarification questions. +- Write a plan file when returning `needs_clarification` or `blocked`. +- Implement any task in the plan. +- Modify application code or tests. +- Modify any file under `context/` outside `context/plans/`. Plan the context + repair instead of performing it. +- Mark any task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Author a validation, cleanup, or context-verification task. `/validate` owns + that phase. +- Set internal status `plan_ready` for a plan with no incomplete task. +- Create a Git commit. +- Author more than one plan. diff --git a/.claude/skills/sce-change-to-plan/references/plan-template.md b/.claude/skills/sce-change-to-plan/references/plan-template.md new file mode 100644 index 00000000..ac36a72c --- /dev/null +++ b/.claude/skills/sce-change-to-plan/references/plan-template.md @@ -0,0 +1,170 @@ +# Internal persisted-document format: Plan template + +The document format for `context/plans/{plan_name}.md`. This is the plan file +written to disk, not the result returned to the workflow. + +Copy the template below and fill every `{placeholder}`. Omit optional sections +entirely rather than writing them empty. + +--- + +## Template + +```markdown +# Plan: {plan-name} + +## Change summary + +{One or two paragraphs: what changes, where, and why. State whether this +extends existing behavior, replaces it, or preserves work already in progress.} + +## Acceptance criteria + +How this plan is proven complete. Each criterion is observable and names the +check that proves it. `/validate` runs these checks; no task in the stack +performs final validation. + +- [ ] AC1: {observable outcome, stated as behavior rather than as work done} + - Validate: `{command, assertion, or inspection that proves AC1}` +- [ ] AC2: {observable outcome} + - Validate: `{command, assertion, or inspection that proves AC2}` + +### Full validation + +Repository-wide checks `/validate` runs after the last task, regardless of +which criterion they map to. + +- `{full check suite command}` +- `{generated-output or parity check command, when applicable}` + +### Context sync + +- {Durable context files that must describe the change once implemented.} + +## Constraints and non-goals + +- **In scope:** {files, modules, and surfaces this plan may touch} +- **Out of scope:** {adjacent work explicitly excluded} +- **Constraints:** {dependencies, conventions, compatibility, or policy limits} +- **Non-goal:** {tempting generalization this plan deliberately avoids} + +## Assumptions + +{Include only when the user allowed assumptions, or ordinary local choices were +recorded. Remove the section otherwise.} + +- {Assumption, and the convention or decision record it rests on.} + +## Task stack + +- [ ] T01: `{single intent title}` (status:todo) + - Task ID: T01 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: {task IDs, or none} + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +- [ ] T02: `{single intent title}` (status:todo) + - Task ID: T02 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: T01 + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +## Open questions + +{Non-blocking questions only. A question that would change scope, success +criteria, or task ordering blocks authoring instead. Write `None.` with a short +justification when nothing remains.} + +{Unresolved doubt about the change's value belongs here — whether it is worth +building, whether it duplicates behavior the repository already has, whether a +smaller version would do. State it plainly and name the alternative. Do not +invent one: `None.` is the expected answer for a well-specified change.} +``` + +--- + +## Filled-in task example + +```markdown +- [ ] T02: `Add /auth/refresh endpoint` (status:todo) + - Task ID: T02 + - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. + - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. + - Dependencies: T01 + - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. + - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. +``` + +## Acceptance criteria rules + +- Acceptance criteria describe the finished system, not the work. Prefer "the + endpoint returns 401 on an expired token" over "add expiry handling". +- Every criterion carries a `Validate:` line. A criterion nobody can check is + not an acceptance criterion. +- Prefer a runnable command. Fall back to a named inspection only when no + automated check exists, and say exactly what to look at. +- List repository-wide checks once under `Full validation` instead of repeating + them per criterion. +- Task-level `Verification notes` prove one task. Acceptance criteria prove the + plan. Keep them distinct: a task's checks are narrow and local, a criterion's + check is end-to-end. +- The union of the acceptance criteria must cover every success signal in the + change request. If a criterion has no task that could satisfy it, the task + stack is incomplete. + +## Task rules + +- Every task is a checkbox line so progress stays machine-readable: + `- [ ] T01: {title} (status:todo)`. +- Author each executable task as one atomic commit unit by default. +- Scope every task so one contributor can complete it and land it as one + coherent commit without bundling unrelated changes. +- Split any candidate task that would require multiple independent commits, for + example a refactor plus a behavior change plus documentation. +- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of + executable tasks. Convert them into specific outcomes with concrete + acceptance checks. +- Order tasks so each one's declared dependencies precede it. + +## No validation task + +- The last task in the stack is an ordinary implementation task. Do not author a + trailing "validation and cleanup" task. +- Final validation, cleanup, and success-criteria verification are run by + `/validate` from the `Acceptance criteria` section after the last task + completes. +- Do not author a task whose only purpose is running the full check suite, + verifying durable context, or removing scaffolding. +- A task may still create or update durable context when that context is part of + the change itself. + +## Completion records + +When a task completes, the **Task execution phase** appends its evidence and flips the +checkbox and status: + +```markdown +- [x] T01: `{title}` (status:done) + - {authored fields, unchanged} + - Completed: {YYYY-MM-DD} + - Files changed: {paths} + - Evidence: {commands run and their outcomes} + - Notes: {material deviations or approved assumptions} +``` + +`/validate` appends a `## Validation Report` section at the end of the plan. +Do not author either while planning. + +## Updating an existing plan + +- Preserve completed tasks, their `(status:done)` markers, and their recorded + evidence verbatim. +- Preserve the plan's existing structure and terminology. +- Append new tasks after the existing stack. Renumber only when added work must + run earlier, and never renumber a completed task. +- Add acceptance criteria for newly planned outcomes rather than rewriting + criteria already satisfied. diff --git a/.claude/skills/sce-commit/SKILL.md b/.claude/skills/sce-commit/SKILL.md index e0fdcfe6..c8dd2fa5 100644 --- a/.claude/skills/sce-commit/SKILL.md +++ b/.claude/skills/sce-commit/SKILL.md @@ -15,6 +15,17 @@ not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or workflow command. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase reference + +Both paths below dispatch to the same phase, whose steps and boundaries live in +`references/atomic-commit.md`. This document holds the control flow — which path +runs, what the phase receives, and how its result branches — and the reference +holds the phase itself. + +Read `references/atomic-commit.md` before running the phase, not after. A regular +run that stops at the staging gate, and a bypass run that finds nothing staged, +both end without ever needing it. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -71,130 +82,10 @@ not skip this prompt because the working tree looks ready. #### 2. Propose commits -After confirmation, run the **Atomic commit phase** with `mode: regular` and the -commit context. - -The **Atomic commit phase** exclusively owns: - -- Reading and analyzing the staged diff. -- Deciding whether staged changes form one coherent unit or several. -- Classifying staged scope and applying context-file guidance gating. -- Writing every commit message subject and body. -- Applying the plan-citation body rule. - -Do not duplicate any of it. Do not write commit messages yourself. - -The mode is supplied by the workflow from an explicit user-supplied token. -Never infer it, and never switch modes mid-analysis. - -Commit context refines wording only. The staged diff decides what the change -is; context never overrides staged truth, and never adds a claim the diff does -not support. - -Do not accept an unstaged diff, a working-tree summary, or a conversational -description as a substitute for the staged diff. - -##### 2.1 Read the staged diff - -Read the staged changes with `git diff --cached`, and the staged file list with -`git diff --cached --name-status`. - -Read staged file contents only when the diff alone does not explain the change. - -Set internal status `blocked` when nothing is staged. - -##### 2.2 Identify coherent units - -Infer the main reason for the staged change from the diff first. - -A coherent unit is one goal a reviewer would accept as a single commit. Group -staged files by that goal, not by directory. - -In `bypass` mode, stop grouping here: the result is exactly one message -covering all staged files, whether or not the diff is coherent. Do not propose -splits, and do not report split guidance. - -##### 2.3 Choose a scope for each unit - -Use the smallest stable subsystem or module name recognizable in the repository. - -When no such name applies, use the primary directory or package of the unit's -changes. - -##### 2.4 Write each message - -Follow `references/output.md` for the subject pattern, the body -rules, issue references, the plan-citation rule, and the anti-patterns. - -##### 2.5 Apply the plan-citation rule - -When the unit's staged files include `context/plans/*.md`, cite the affected -plan slug and updated task IDs in the body. - -When the staged plan diff does not expose the slug or task ID clearly enough to -cite faithfully: - -- In `regular` mode, set internal status `blocked` and ask for the reference to be stated or - staged explicitly. -- In `bypass` mode, infer the citation when the diff supports it, and otherwise - omit it. Never stop, and never invent a slug or task ID. - -##### 2.6 Apply context-file guidance gating - -This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do -not classify staged scope there. - -Classify the staged diff: - -- Context-only (`context/**`): context-file-focused guidance is allowed. -- Mixed (`context/**` plus non-`context/**`): suppress default context-file - commit reminders and give guidance that reflects the full staged scope. - -##### 2.7 Propose split guidance - -This step applies in `regular` mode only. - -When the units found in step 2 pursue unrelated goals, return one message per -unit, and state why the split is recommended and which staged files belong to -each. - -When the staged changes form one unit, return one message and no split -guidance. Do not split coherent work to appear thorough. - -##### 2.8 Validate the result - -Confirm before returning that: - -- Every message describes its unit faithfully and covers only that unit's files. -- Every staged file belongs to exactly one returned message. -- No plan slug or task ID appears that the staged diff does not support. -- The mode's own constraints hold. - -##### 2.9 Return internal state - -Set exactly one internal state: - -- `proposal` in `regular` mode, with one or more messages. -- `bypass_message` in `bypass` mode, with exactly one message. -- `blocked` when messages cannot be written faithfully. - -Record only the internal state. Do not add explanatory prose before or after it. - -#### Atomic commit boundaries - -Do not: +After confirmation, read `references/atomic-commit.md`, then run the **Atomic +commit phase** with `mode: regular` and the commit context. -- Run `git commit`, or any command that writes to the repository or its index. -- Stage, unstage, or modify files. -- Ask the user to stage or confirm staging. -- Analyze unstaged or untracked changes. -- Return more than one message in `bypass` mode. -- Return split guidance in `bypass` mode. -- Stop for plan-citation ambiguity in `bypass` mode. -- Invent plan slugs, task IDs, or issue references. -- Mention `context/` synchronization activity in a commit message. -- Claim a message was committed. -- Run plan, task, or validation workflows. +Do not write commit messages yourself. Branch on `status`: @@ -222,7 +113,8 @@ Do not stage anything. Do not proceed to the skill. #### 2. Request one commit message -Run the **Atomic commit phase** (described at the Regular path's step 2 above) with `mode: bypass` and the commit context. +Read `references/atomic-commit.md`, then run the **Atomic commit phase** with +`mode: bypass` and the commit context. Bypass mode is the skill's contract for producing exactly one message. Do not restate its overrides here; the **Atomic commit phase** owns them. @@ -254,6 +146,7 @@ fallback commit. - Never commit on the regular path. - Recognize `oneshot` and `skip` only as an exact case-insensitive first token. They are behaviorally identical. +- Read `references/atomic-commit.md` before running the phase. - Do not duplicate the internal instructions of the **Atomic commit phase**. - Do not stage, unstage, restore, or otherwise modify files. - Do not amend, reset, revert, rebase, or push. diff --git a/.claude/skills/sce-commit/references/atomic-commit.md b/.claude/skills/sce-commit/references/atomic-commit.md new file mode 100644 index 00000000..ecdeb3bd --- /dev/null +++ b/.claude/skills/sce-commit/references/atomic-commit.md @@ -0,0 +1,130 @@ +# Atomic commit phase + +Both workflow paths run this phase. The regular path runs it with `mode: regular` +after the staging gate; the bypass path runs it with `mode: bypass` after +confirming staged content exists. + +Input: the mode, supplied by the workflow from an explicit user-supplied token, +and the commit context. + +This phase exclusively owns: + +- Reading and analyzing the staged diff. +- Deciding whether staged changes form one coherent unit or several. +- Classifying staged scope and applying context-file guidance gating. +- Writing every commit message subject and body. +- Applying the plan-citation body rule. + +Do not duplicate any of it elsewhere in the workflow. Do not write commit messages +outside this phase. + +Never infer the mode, and never switch modes mid-analysis. + +Commit context refines wording only. The staged diff decides what the change is; +context never overrides staged truth, and never adds a claim the diff does not +support. + +Do not accept an unstaged diff, a working-tree summary, or a conversational +description as a substitute for the staged diff. + +## 1. Read the staged diff + +Read the staged changes with `git diff --cached`, and the staged file list with +`git diff --cached --name-status`. + +Read staged file contents only when the diff alone does not explain the change. + +Set internal status `blocked` when nothing is staged. + +## 2. Identify coherent units + +Infer the main reason for the staged change from the diff first. + +A coherent unit is one goal a reviewer would accept as a single commit. Group +staged files by that goal, not by directory. + +In `bypass` mode, stop grouping here: the result is exactly one message covering +all staged files, whether or not the diff is coherent. Do not propose splits, and +do not report split guidance. + +## 3. Choose a scope for each unit + +Use the smallest stable subsystem or module name recognizable in the repository. + +When no such name applies, use the primary directory or package of the unit's +changes. + +## 4. Write each message + +Follow `references/output.md` for the subject pattern, the body rules, issue +references, the plan-citation rule, and the anti-patterns. + +## 5. Apply the plan-citation rule + +When the unit's staged files include `context/plans/*.md`, cite the affected plan +slug and updated task IDs in the body. + +When the staged plan diff does not expose the slug or task ID clearly enough to +cite faithfully: + +- In `regular` mode, set internal status `blocked` and ask for the reference to be + stated or staged explicitly. +- In `bypass` mode, infer the citation when the diff supports it, and otherwise + omit it. Never stop, and never invent a slug or task ID. + +## 6. Apply context-file guidance gating + +This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do +not classify staged scope there. + +Classify the staged diff: + +- Context-only (`context/**`): context-file-focused guidance is allowed. +- Mixed (`context/**` plus non-`context/**`): suppress default context-file commit + reminders and give guidance that reflects the full staged scope. + +## 7. Propose split guidance + +This step applies in `regular` mode only. + +When the units found in step 2 pursue unrelated goals, return one message per +unit, and state why the split is recommended and which staged files belong to +each. + +When the staged changes form one unit, return one message and no split guidance. +Do not split coherent work to appear thorough. + +## 8. Validate the result + +Confirm before returning that: + +- Every message describes its unit faithfully and covers only that unit's files. +- Every staged file belongs to exactly one returned message. +- No plan slug or task ID appears that the staged diff does not support. +- The mode's own constraints hold. + +## 9. Return internal state + +Set exactly one internal state: + +- `proposal` in `regular` mode, with one or more messages. +- `bypass_message` in `bypass` mode, with exactly one message. +- `blocked` when messages cannot be written faithfully. + +Record only the internal state. Do not add explanatory prose before or after it. + +## Atomic commit boundaries + +Do not: + +- Run `git commit`, or any command that writes to the repository or its index. +- Stage, unstage, or modify files. +- Ask the user to stage or confirm staging. +- Analyze unstaged or untracked changes. +- Return more than one message in `bypass` mode. +- Return split guidance in `bypass` mode. +- Stop for plan-citation ambiguity in `bypass` mode. +- Invent plan slugs, task IDs, or issue references. +- Mention `context/` synchronization activity in a commit message. +- Claim a message was committed. +- Run plan, task, or validation workflows. diff --git a/.claude/skills/sce-next-task/SKILL.md b/.claude/skills/sce-next-task/SKILL.md index af7e10f3..e510892c 100644 --- a/.claude/skills/sce-next-task/SKILL.md +++ b/.claude/skills/sce-next-task/SKILL.md @@ -16,6 +16,25 @@ workflow command except `sce-decision`, and invoke `sce-decision` only from the successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps, gates, and boundaries +live in a reference file. This document holds the control flow — which phase runs, +what it receives, and how its result branches — and each reference holds the phase +itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/plan-review.md` | +| 2 | `references/task-execution.md` | +| 3 | `references/context-sync.md` | + +Read a step's reference before taking any action for that step, not after. The +references carry gates that must fire before their phase's first side effect, so a +phase begun from this summary alone will already have skipped them. Read only the +reference for the step you have reached: a run that stops at step 1 never needs the +other two, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -53,111 +72,11 @@ Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is ### 1. Review the task -Run the **Plan review phase** with the parsed `plan-name-or-path` and, when present, the parsed `task-id`. +Read `references/plan-review.md`, then run the **Plan review phase** with the +parsed `plan-name-or-path` and, when present, the parsed `task-id`. Do not pass the `auto-approve` token to the **Plan review phase**. -#### 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status `blocked` with -the matching candidates. - -Read the selected plan before exploring the repository. - -#### 1.2 Resolve one task - -When a task ID is supplied, select that task. - -Otherwise, select the first incomplete task in plan order whose declared -dependencies are complete. - -Set internal status `plan_complete` when no incomplete tasks remain. - -Set internal status `blocked` when incomplete tasks remain but none can currently be -executed. - -Review at most one task per invocation. - -#### 1.3 Inspect relevant context - -Start with the task and the files it directly references. - -Inspect only what is needed to understand: - -- Existing behavior. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests. -- Available verification commands. -- Decisions or specifications connected to the task. - -Load root context only when the task affects repository-wide behavior, -architecture, shared terminology, or cross-domain interfaces. - -Do not explore the entire repository by default. - -#### 1.4 Determine readiness - -A task is `ready` when: - -- Its goal is clear. -- Its scope is sufficiently bounded. -- Its dependencies are complete. -- Its done checks are observable. -- A credible verification method exists. -- No unresolved decision would materially change the implementation. - -Use repository conventions for ordinary local choices. - -Do not block on: - -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change observable behavior or scope. - -Record these choices under `assumptions`. - -Set internal status `blocked` when a missing decision materially affects: - -- User-visible behavior. -- Public interfaces. -- Architecture or ownership boundaries. -- Data shape or persistence. -- Security or privacy. -- External dependencies. -- Destructive or difficult-to-reverse behavior. -- The evidence needed to prove completion. - -#### 1.5 Return the result - -Set exactly one internal state: - -- `ready` -- `blocked` -- `plan_complete` - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Plan review boundaries - -Do not: - -- Modify application code. -- Modify tests. -- Update the plan. -- Mark the task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Review more than one task. - Branch on `status`: `blocked` -> Do not run implementation. Render the **Review blocked** layout from `references/output.md`. When `candidates` is present the plan could not be resolved, and each entry is a candidate path for `/next-task {candidate-path}`. `executable_tasks_remaining` true means another task remains executable and `/next-task {plan-path} {task-id}` selects one; false means no task in the plan can proceed until the plan is updated. Do not print the raw result. Stop. @@ -170,7 +89,13 @@ Do not reconstruct, summarize, or reinterpret the reviewed task before passing i ### 2. Execute the task -Run the **Task execution phase** with the complete `ready` result from the **Plan review phase**. +Read `references/task-execution.md`, then run the **Task execution phase** with +the complete `ready` result from the **Plan review phase**. + +This phase always shows an implementation gate before it modifies any file, and it +is the only phase permitted to ask the user for confirmation. Both properties are +load-bearing, so reach them through the reference rather than acting from this +summary. Branch on `auto-approve`: @@ -178,205 +103,8 @@ Branch on `auto-approve`: else -> Do not pass the `approve` flag. The **Task execution phase** shows its implementation gate and waits for the user's decision. -The **Task execution phase** exclusively owns: - -- Presenting the implementation summary. -- Requesting implementation confirmation. -- Implementing the task. -- Running task-level verification. -- Updating the task status and evidence. - Do not present an additional implementation confirmation. -The `approve` flag means the user pre-approved this task when invoking the -workflow. It suppresses the approval question and the wait. It never suppresses -the gate. Only the workflow entrypoint may set it, and only from an explicit -user-supplied approval token. Never infer it. - -The readiness result must identify: - -- One resolved plan. -- Exactly one incomplete task. -- The task goal and scope boundaries. -- Done checks. -- Verification expectations. -- Relevant files and context. -- Review assumptions. - -If required handoff information is absent or stale, still show the gate using -what is known, clearly identify the handoff problem, and do not edit files. -After the user responds, set internal status `blocked`. - -#### 2.1 Validate the handoff without editing - -Confirm that: - -- The readiness status is `ready`. -- Exactly one task is present. -- The plan file exists. -- The selected task is still incomplete. -- The task has not materially changed since review. -- Declared dependencies remain complete. - -Do not reconstruct missing material requirements. - -#### 2.2 Always show the implementation gate - -At the start of the phase, before any file modification, present the task using -`references/output.md`. - -The gate must be shown even when: - -- The task appears straightforward. -- The workflow believes approval was already implied. -- The handoff is stale or incomplete. -- The user is likely to approve. - -When the `approve` flag is absent, end the gate with exactly one approval -question: - -`Continue with implementation now? (yes/no)` - -Stop and wait for the user's answer. Do not return internal state, and make no file -modifications, until the user has answered. - -When the `approve` flag is supplied, show the gate as a summary, omit the -approval question, do not wait, and continue at step 2.4. - -#### 2.3 Handle the user's decision - -Skip this step when the `approve` flag was supplied. - -When the user rejects or cancels, do not modify files and set internal status `declined`. - -When the user does not clearly approve, do not modify files. Ask the same -approval question once more only when the response is genuinely ambiguous. -Otherwise set internal status `blocked`. - -When the user approves, continue with implementation. - -Treat constraints supplied with approval as part of the approved task boundary. -If those constraints materially contradict the reviewed task, set internal status `blocked` -before editing. - -#### 2.4 Prepare the implementation - -Before editing: - -- Read the relevant files supplied by plan review. -- Inspect nearby code and tests when needed. -- Identify the smallest coherent change satisfying the task. -- Follow surrounding naming, structure, error handling, and test style. -- Preserve unrelated behavior. - -Do not create a second plan. - -Do not broaden the reviewed task. - -#### 2.5 Implement one task - -Make the minimum coherent changes required to satisfy the task goal and done -checks. - -Use judgment for ordinary, reversible local implementation choices. - -Stop when implementation requires: - -- Material scope expansion. -- A new external dependency not authorized by the task. -- A public-interface decision not established by the plan. -- A destructive or difficult-to-reverse operation. -- An unresolved security, privacy, or data decision. -- Contradicting the reviewed task or repository architecture. - -When stopped, preserve completed in-scope work unless retaining it would leave -the repository unsafe or invalid. - -#### 2.6 Verify the task - -Run the narrowest authoritative checks that demonstrate the done checks. - -Start with verification supplied by the readiness result. Add nearby or directly -relevant checks only when needed. - -Verification may include: - -- Targeted tests. -- Type checking for affected code. -- Linting affected files. -- Formatting checks. -- A focused build or compile step. -- Direct behavioral inspection when no automated check exists. - -Do not run final plan validation unless the task itself explicitly requires it. - -When a check fails: - -- Determine whether the task caused the failure. -- Fix it when the correction remains in scope. -- Rerun the relevant check. -- Set internal status `incomplete` when a done check remains unsatisfied, or `blocked` when - completing it requires an unapproved decision or scope expansion. - -Never report a check as passed unless it ran successfully. - -#### 2.7 Update the plan - -Only after successful implementation and task-level verification: - -- Mark only the selected task complete. -- Record concise implementation evidence. -- Record verification commands and outcomes. -- Record material deviations or approved assumptions. -- Preserve the plan's existing structure and terminology. - -Do not mark the task complete when returning `declined`, `blocked`, or -`incomplete`. - -#### 2.8 Determine the terminal status - -Set internal status `complete` when the task was implemented, verified, and marked complete -in the plan with evidence. - -Set internal status `incomplete` when in-scope work was completed but one or more done checks -remain unsatisfied. - -Set internal status `declined` when the user rejected implementation. - -Set internal status `blocked` for every other non-successful outcome, including: - -- Missing approval. -- Stale or invalid handoff. -- Material blocker. -- A verification failure that cannot be resolved in scope. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -#### 2.9 Return internal state - -After the phase reaches a terminal state, set exactly one internal state. - -Record only the internal state. Do not add explanatory prose before or after it. - -### Task execution boundaries - -Do not: - -- Edit before approval, whether explicit or pre-supplied. -- Execute more than one task. -- Select or execute the next task. -- Skip the implementation gate. -- Ask for multiple approval gates for the same unchanged task. -- Expand scope without authorization. -- Synchronize durable context. -- Run final plan validation. -- Determine whether the plan is complete. -- Create a Git commit. -- Push changes. -- Modify unrelated files. -- Claim verification that was not performed. - Branch on the execution result. `declined` -> Render the **Declined** layout from `references/output.md`. Do not run context synchronization. Stop. @@ -389,319 +117,16 @@ Branch on the execution result. ### 3. Synchronize context -Run the **Task context synchronization phase** with the complete `complete` result returned by the **Task execution phase**. +Read `references/context-sync.md`, then run the **Task context synchronization +phase** with the complete `complete` result returned by the **Task execution +phase**. Pass that result verbatim. It is the authoritative handoff, and the **Task context synchronization phase** owns reading the plan, task, changed files, verification evidence, and reported context impact out of it. Do not restate, summarize, or reconstruct any part of the execution result. -The execution result must have: - -```text -status: complete -``` - -Treat the execution result as the authoritative handoff for: - -- The resolved plan and completed task. -- Files changed by implementation. -- Implementation summary. -- Verification evidence. -- Done-check evidence. -- Reported context impact. - -This phase must not be run for `declined`, `blocked`, or `incomplete` -execution results. - -Do not reconstruct a missing execution result from conversation history. - -#### 3.1 Validate the execution handoff - -Confirm that: - -- `status` is exactly `complete`. -- A `plan` object with a `path` is present. -- Exactly one completed task is identified. -- Changed files and an implementation summary are present. -- Verification evidence is present. -- Done-check evidence is present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, -do not modify context. Return a `blocked` Markdown report. - -#### 3.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. -Do not create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that the task itself is complete and recorded in the plan, and that -synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -#### 3.3 Discover applicable context - -Start with the execution result: - -- `context_impact.classification` -- `context_impact.affected_areas` -- Changed files. -- Implementation summary. -- Done-check evidence. - -Then inspect existing repository context in this order when present: - -1. `context/context-map.md` -2. Context files for the affected domain or subsystem -3. `context/overview.md` -4. `context/architecture.md` -5. `context/glossary.md` -6. `context/patterns.md` -7. Operational, product, or decision records directly related to the change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -##### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -completed implementation. A file that is absent is a gap; record it in the -report rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization -done while one of them is unchecked. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -#### 3.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in task evidence. -- Speculation or future work not established by the completed implementation. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass. - -- `none`: Make no edits beyond any correction the root pass turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -A change is `root` when it introduces cross-cutting behavior, repository-wide -policy or contracts, an architecture or ownership boundary, or a change to -canonical terminology. A change confined to one feature or domain, with no -repository-wide behavior, architecture, or terminology impact, is `domain` or -`local`: capture its detail in domain files and leave the root files unedited. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -#### 3.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- execution and done-check evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task references, - related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -#### 3.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the implementation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the completed implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the execution result verbatim into context files. -- Do not change application code, tests, or plan state. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -##### Feature existence - -Every feature the completed task implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the task implemented a feature no context file describes, add that -description. A feature that fits no existing domain file gets a new focused -file; do not defer it to a later task. Prefer a small, precise domain file over -overloading `overview.md` with detail. - -This is the one case where documentation is warranted by the change itself -rather than by a gap in durable knowledge. It is not license to narrate the -diff: describe what the feature is and how it behaves, not what was edited. - -##### Glossary - -Add a `context/glossary.md` entry for any domain language the task introduced. -New terminology is durable knowledge whatever the classification is: a `domain` -change that names a new concept still earns its glossary entry. - -##### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it - into focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough - that prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -#### 3.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the completed implementation. -- No edited statement contradicts the code, plan, or execution evidence. -- Every qualifying decision has one written or reused ADR path in the report, - and the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Each feature implemented by the task has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not run full application or plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -#### 3.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` -means existing context was checked and no edit was warranted. `blocked` means -context could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -### Task context synchronization boundaries - -Do not: - -- Accept an execution result whose status is not `complete`. -- Implement or modify application code. -- Modify tests. -- Change task completion status or plan evidence. -- Determine whether the plan is complete. -- Select or execute another task. -- Run full-plan validation. -- Mark the plan validated, closed, or archived. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason - to document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return an execution-style internal state. +This phase verifies the five root context files on every invocation, whatever the +change's reported impact, so it is never correct to skip it as unnecessary. Branch on the synchronization result. @@ -729,6 +154,7 @@ Stop. - Execute at most one plan task per invocation. - Review at most one task. +- Read each phase's reference before running that phase. - Do not duplicate the internal instructions of embedded phases. - The only permitted sibling-skill invocation is `sce-decision`, and only the successful context-synchronization decision gate may invoke it. diff --git a/.claude/skills/sce-next-task/references/context-sync.md b/.claude/skills/sce-next-task/references/context-sync.md new file mode 100644 index 00000000..06413b09 --- /dev/null +++ b/.claude/skills/sce-next-task/references/context-sync.md @@ -0,0 +1,316 @@ +# Task context synchronization phase + +Run this phase for step 3 of the workflow, and only when task execution returned +`complete`. It updates durable repository knowledge in `context/` so the next +session inherits what this task established. It never touches code, tests, or +plan state. + +Input: the complete `complete` result from the task execution phase, passed +verbatim. It is the authoritative handoff, and this phase owns reading the plan, +task, changed files, verification evidence, and reported context impact out of +it. + +Do not restate, summarize, or reconstruct any part of the execution result. Do +not reconstruct a missing execution result from conversation history. + +The execution result must have: + +```text +status: complete +``` + +Treat the execution result as the authoritative handoff for: + +- The resolved plan and completed task. +- Files changed by implementation. +- Implementation summary. +- Verification evidence. +- Done-check evidence. +- Reported context impact. + +This phase must not be run for `declined`, `blocked`, or `incomplete` execution +results. + +## 3.1 Validate the execution handoff + +Confirm that: + +- `status` is exactly `complete`. +- A `plan` object with a `path` is present. +- Exactly one completed task is identified. +- Changed files and an implementation summary are present. +- Verification evidence is present. +- Done-check evidence is present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 3.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that the task itself is complete and recorded in the plan, and that +synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 3.3 Discover applicable context + +Start with the execution result: + +- `context_impact.classification` +- `context_impact.affected_areas` +- Changed files. +- Implementation summary. +- Done-check evidence. + +Then inspect existing repository context in this order when present: + +1. `context/context-map.md` +2. Context files for the affected domain or subsystem +3. `context/overview.md` +4. `context/architecture.md` +5. `context/glossary.md` +6. `context/patterns.md` +7. Operational, product, or decision records directly related to the change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +completed implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +## 3.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in task evidence. +- Speculation or future work not established by the completed implementation. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass. + +- `none`: Make no edits beyond any correction the root pass turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +A change is `root` when it introduces cross-cutting behavior, repository-wide +policy or contracts, an architecture or ownership boundary, or a change to +canonical terminology. A change confined to one feature or domain, with no +repository-wide behavior, architecture, or terminology impact, is `domain` or +`local`: capture its detail in domain files and leave the root files unedited. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 3.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- execution and done-check evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task + references, related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 3.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the implementation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the completed implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the execution result verbatim into context files. +- Do not change application code, tests, or plan state. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the completed task implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the task implemented a feature no context file describes, add that +description. A feature that fits no existing domain file gets a new focused file; +do not defer it to a later task. Prefer a small, precise domain file over +overloading `overview.md` with detail. + +This is the one case where documentation is warranted by the change itself rather +than by a gap in durable knowledge. It is not license to narrate the diff: +describe what the feature is and how it behaves, not what was edited. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the task introduced. +New terminology is durable knowledge whatever the classification is: a `domain` +change that names a new concept still earns its glossary entry. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 3.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the completed implementation. +- No edited statement contradicts the code, plan, or execution evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Each feature implemented by the task has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not run full application or plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 3.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## Task context synchronization boundaries + +Do not: + +- Accept an execution result whose status is not `complete`. +- Implement or modify application code. +- Modify tests. +- Change task completion status or plan evidence. +- Determine whether the plan is complete. +- Select or execute another task. +- Run full-plan validation. +- Mark the plan validated, closed, or archived. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return an execution-style internal state. diff --git a/.claude/skills/sce-next-task/references/plan-review.md b/.claude/skills/sce-next-task/references/plan-review.md new file mode 100644 index 00000000..d08975e3 --- /dev/null +++ b/.claude/skills/sce-next-task/references/plan-review.md @@ -0,0 +1,121 @@ +# Plan review phase + +Run this phase for step 1 of the workflow. It resolves one plan, selects one +task, and decides whether that task can be implemented right now. It reads; it +never writes. + +Inputs: the parsed `plan-name-or-path`, and `task-id` when present. The +`auto-approve` token is not passed here and has no meaning in this phase. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Resolve one task + +When a task ID is supplied, select that task. + +Otherwise, select the first incomplete task in plan order whose declared +dependencies are complete. + +Set internal status `plan_complete` when no incomplete tasks remain. + +Set internal status `blocked` when incomplete tasks remain but none can currently +be executed. + +Review at most one task per invocation. + +## 1.3 Inspect relevant context + +Start with the task and the files it directly references. + +Inspect only what is needed to understand: + +- Existing behavior. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests. +- Available verification commands. +- Decisions or specifications connected to the task. + +Load root context only when the task affects repository-wide behavior, +architecture, shared terminology, or cross-domain interfaces. + +Do not explore the entire repository by default. + +## 1.4 Determine readiness + +A task is `ready` when: + +- Its goal is clear. +- Its scope is sufficiently bounded. +- Its dependencies are complete. +- Its done checks are observable. +- A credible verification method exists. +- No unresolved decision would materially change the implementation. + +Use repository conventions for ordinary local choices. + +Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change observable behavior or scope. + +Record these choices under `assumptions`. + +Set internal status `blocked` when a missing decision materially affects: + +- User-visible behavior. +- Public interfaces. +- Architecture or ownership boundaries. +- Data shape or persistence. +- Security or privacy. +- External dependencies. +- Destructive or difficult-to-reverse behavior. +- The evidence needed to prove completion. + +## 1.5 Return the result + +Set exactly one internal state: + +- `ready` +- `blocked` +- `plan_complete` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `ready` result must identify: + +- One resolved plan. +- Exactly one incomplete task. +- The task goal and scope boundaries. +- Done checks. +- Verification expectations. +- Relevant files and context. +- Review assumptions. + +Step 2 consumes this result verbatim, so anything the execution phase needs has +to be present here. + +## Plan review boundaries + +Do not: + +- Modify application code. +- Modify tests. +- Update the plan. +- Mark the task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Review more than one task. diff --git a/.claude/skills/sce-next-task/references/task-execution.md b/.claude/skills/sce-next-task/references/task-execution.md new file mode 100644 index 00000000..7b049492 --- /dev/null +++ b/.claude/skills/sce-next-task/references/task-execution.md @@ -0,0 +1,203 @@ +# Task execution phase + +Run this phase for step 2 of the workflow. It is the only phase that writes +application code, and the only one that asks the user for anything. + +Input: the complete `ready` result from the plan review phase, plus the `approve` +flag when the user pre-approved this invocation. + +This phase exclusively owns: + +- Presenting the implementation summary. +- Requesting implementation confirmation. +- Implementing the task. +- Running task-level verification. +- Updating the task status and evidence. + +Do not present an additional implementation confirmation anywhere else. + +The `approve` flag means the user pre-approved this task when invoking the +workflow. It suppresses the approval question and the wait. It never suppresses +the gate. Only the workflow entrypoint may set it, and only from an explicit +user-supplied approval token. Never infer it. + +If required handoff information is absent or stale, still show the gate using +what is known, clearly identify the handoff problem, and do not edit files. After +the user responds, set internal status `blocked`. + +## 2.1 Validate the handoff without editing + +Confirm that: + +- The readiness status is `ready`. +- Exactly one task is present. +- The plan file exists. +- The selected task is still incomplete. +- The task has not materially changed since review. +- Declared dependencies remain complete. + +Do not reconstruct missing material requirements. + +## 2.2 Always show the implementation gate + +At the start of the phase, before any file modification, present the task using +`references/output.md`. + +The gate must be shown even when: + +- The task appears straightforward. +- The workflow believes approval was already implied. +- The handoff is stale or incomplete. +- The user is likely to approve. + +When the `approve` flag is absent, end the gate with exactly one approval +question: + +`Continue with implementation now? (yes/no)` + +Stop and wait for the user's answer. Do not return internal state, and make no +file modifications, until the user has answered. + +When the `approve` flag is supplied, show the gate as a summary, omit the +approval question, do not wait, and continue at step 2.4. + +## 2.3 Handle the user's decision + +Skip this step when the `approve` flag was supplied. + +When the user rejects or cancels, do not modify files and set internal status +`declined`. + +When the user does not clearly approve, do not modify files. Ask the same +approval question once more only when the response is genuinely ambiguous. +Otherwise set internal status `blocked`. + +When the user approves, continue with implementation. + +Treat constraints supplied with approval as part of the approved task boundary. +If those constraints materially contradict the reviewed task, set internal status +`blocked` before editing. + +## 2.4 Prepare the implementation + +Before editing: + +- Read the relevant files supplied by plan review. +- Inspect nearby code and tests when needed. +- Identify the smallest coherent change satisfying the task. +- Follow surrounding naming, structure, error handling, and test style. +- Preserve unrelated behavior. + +Do not create a second plan. + +Do not broaden the reviewed task. + +## 2.5 Implement one task + +Make the minimum coherent changes required to satisfy the task goal and done +checks. + +Use judgment for ordinary, reversible local implementation choices. + +Stop when implementation requires: + +- Material scope expansion. +- A new external dependency not authorized by the task. +- A public-interface decision not established by the plan. +- A destructive or difficult-to-reverse operation. +- An unresolved security, privacy, or data decision. +- Contradicting the reviewed task or repository architecture. + +When stopped, preserve completed in-scope work unless retaining it would leave +the repository unsafe or invalid. + +## 2.6 Verify the task + +Run the narrowest authoritative checks that demonstrate the done checks. + +Start with verification supplied by the readiness result. Add nearby or directly +relevant checks only when needed. + +Verification may include: + +- Targeted tests. +- Type checking for affected code. +- Linting affected files. +- Formatting checks. +- A focused build or compile step. +- Direct behavioral inspection when no automated check exists. + +Do not run final plan validation unless the task itself explicitly requires it. + +When a check fails: + +- Determine whether the task caused the failure. +- Fix it when the correction remains in scope. +- Rerun the relevant check. +- Set internal status `incomplete` when a done check remains unsatisfied, or + `blocked` when completing it requires an unapproved decision or scope + expansion. + +Never report a check as passed unless it ran successfully. + +## 2.7 Update the plan + +Only after successful implementation and task-level verification: + +- Mark only the selected task complete. +- Record concise implementation evidence. +- Record verification commands and outcomes. +- Record material deviations or approved assumptions. +- Preserve the plan's existing structure and terminology. + +Do not mark the task complete when returning `declined`, `blocked`, or +`incomplete`. + +## 2.8 Determine the terminal status + +Set internal status `complete` when the task was implemented, verified, and +marked complete in the plan with evidence. + +Set internal status `incomplete` when in-scope work was completed but one or more +done checks remain unsatisfied. + +Set internal status `declined` when the user rejected implementation. + +Set internal status `blocked` for every other non-successful outcome, including: + +- Missing approval. +- Stale or invalid handoff. +- Material blocker. +- A verification failure that cannot be resolved in scope. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## 2.9 Return internal state + +After the phase reaches a terminal state, set exactly one internal state. + +Record only the internal state. Do not add explanatory prose before or after it. + +A `complete` result is the authoritative handoff into step 3, which reads the +plan, completed task, changed files, implementation summary, verification +evidence, done-check evidence, and context-impact classification out of it. Step +3 is forbidden from reconstructing any of that, so it has to be present here. + +## Task execution boundaries + +Do not: + +- Edit before approval, whether explicit or pre-supplied. +- Execute more than one task. +- Select or execute the next task. +- Skip the implementation gate. +- Ask for multiple approval gates for the same unchanged task. +- Expand scope without authorization. +- Synchronize durable context. +- Run final plan validation. +- Determine whether the plan is complete. +- Create a Git commit. +- Push changes. +- Modify unrelated files. +- Claim verification that was not performed. diff --git a/.claude/skills/sce-validate/SKILL.md b/.claude/skills/sce-validate/SKILL.md index 4377fb3b..0ee099f0 100644 --- a/.claude/skills/sce-validate/SKILL.md +++ b/.claude/skills/sce-validate/SKILL.md @@ -16,6 +16,25 @@ workflow command except `sce-decision`, and invoke `sce-decision` only from the successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/validation.md` | +| 2 | `references/context-sync.md` | + +`references/validation-report.md` defines the `## Validation Report` section +written into the plan file. Step 1 points to it at the moment it is needed, on a +`validated` or `failed` outcome only. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at a `blocked` +or `failed` validation never enters step 2, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -54,147 +73,15 @@ candidate path), so every emitted command is directly runnable. ### 1. Validate the plan -Run the **Validation phase** with the plan name or path. - -The **Validation phase** exclusively owns: - -- Resolving one plan. -- Confirming every implementation task is complete. -- Running full validation and acceptance-criteria checks. -- Removing temporary scaffolding. -- Writing the Validation Report into the plan. -- Returning one Markdown validation result. - -Do not duplicate any of it. Do not write the Validation Report yourself. - -#### 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan under -`context/plans/`. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status `blocked` -with the matching candidates. - -Read the selected plan before exploring the repository. - -#### 1.2 Confirm implementation is finished - -Set internal status `blocked` with incomplete tasks listed when any implementation task -remains incomplete. - -Final validation measures finished work. Do not run the full suite against a -partial stack, and do not complete remaining tasks here. - -#### 1.3 Read the validation contract from the plan - -From the plan, collect: - -- Every acceptance criterion and its `Validate:` check. -- The `Full validation` command list. -- The `Context sync` requirements, for the context-impact handoff only. - -Set internal status `blocked` when the plan has no usable acceptance criteria, or when no -validation commands can be determined from the plan or repository conventions. - -Prefer the plan's authored checks. Fall back to repository-primary test, lint, -and format commands only when `Full validation` is absent, and record that -fallback under notes on a `validated` or `failed` result. - -#### 1.4 Remove temporary scaffolding - -Before or while running checks, remove temporary scaffolding introduced during -the change when it is clearly throwaway: - -- Debug-only patches or flags left enabled. -- Temporary files or intermediate artifacts not part of the delivered design. -- Local scaffolding the plan or task notes mark as temporary. - -Do not delete durable product code, tests, configuration, or context files. - -Record every removed path. When nothing temporary remains, report `None.` - -#### 1.5 Run full validation and acceptance checks - -Run the plan's `Full validation` commands. - -Then verify each acceptance criterion using its `Validate:` line. Prefer a -runnable command. Use a named inspection only when the criterion authorizes it, -and say exactly what was inspected. - -When a check fails, record the failure and continue gathering evidence. Do not -modify tests, application code, or configuration to make a check pass. Final -validation measures the finished work; repair belongs to a later work session, -not this skill. - -Never report a check as passed unless it ran successfully or the authorized -inspection confirmed the criterion. - -Do not run task-by-task implementation work for incomplete tasks. That belongs -to `/next-task`. - -#### 1.6 Update the plan +Read `references/validation.md`, then run the **Validation phase** with the plan +name or path. -For `validated` and `failed` outcomes: +This phase measures finished work and never repairs it: it does not modify tests, +application code, or configuration to make a failing check pass. That property is +load-bearing, so reach it through the reference rather than acting from this +summary. -- Mark each acceptance criterion checkbox to match the evidence. -- Append or replace the plan's `## Validation Report` section using - the **Plan-file validation report** section embedded in this file. -- When status is `failed`, the plan-file report must include the retry command - `/validate {plan path}`. - -Do not reopen completed tasks, rewrite task evidence, or change the task stack. - -For `blocked`, leave the plan file unchanged. - -#### 1.7 Determine context impact for the handoff - -On `validated` only, classify the durable context impact of the finished plan -so the **Plan context synchronization phase** can start from the plan's own requirements: - -- Start from the plan's `Context sync` section. -- Inspect what the completed implementation actually changed when needed. -- Report required context paths and affected areas. -- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level - context sync. - -Do not edit context files here. - -On `failed` or `blocked`, omit context impact; context sync will not run. - -#### 1.8 Return the internal state - -Set exactly one internal state: - -- `validated` when every acceptance criterion is met, required full validation - passed, and the Validation Report was written. -- `failed` when evidence was captured but required checks or criteria remain - unsatisfied. Shape it as a session handoff per - `references/output.md`, ending recommended work with - `/validate {plan path}`. -- `blocked` when validation cannot proceed safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. Do not return internal state. - -### Validation boundaries - -Do not: - -- Validate more than one plan. -- Complete remaining implementation tasks. -- Modify tests, application code, or configuration to make a failing check pass. -- Apply lint or format auto-fixes that change product or test files as part of - making validation green. -- Synchronize durable context under `context/` outside the plan file. -- Create the context root. -- Mark the plan archived or delete the plan. -- Create a Git commit or push changes. -- Invent acceptance criteria the plan does not state. -- Claim verification that was not performed. -- Return a internal state. -- Run plan context synchronization. The workflow owns that step. +Do not write the Validation Report yourself. Branch on the report's `Status:`. @@ -219,8 +106,9 @@ passing it. ### 2. Synchronize plan context -Run the **Plan context synchronization phase** only with a `Status: validated` Markdown result -from the **Validation phase**. +Read `references/context-sync.md`, then run the **Plan context synchronization +phase** with the `Status: validated` Markdown result from the **Validation +phase**. Do not run the **Plan context synchronization phase** for `failed` or `blocked`. Those are not success states. @@ -231,311 +119,9 @@ reported context impact out of it. Do not restate, summarize, or reconstruct any part of the validation result. -Task-level context sync may already have run after individual tasks. This phase -is the plan-level final pass: it starts from the plan's `Context sync` -requirements and the validated implementation, and closes gaps that remain. - -The validation result must report: - -```markdown -**Status:** validated -**Plan:** {plan path} -``` - -Treat that Markdown as the authoritative handoff for: - -- The resolved plan path. -- Validation commands and outcomes. -- Acceptance-criteria evidence. -- Scaffolding removals. -- Reported context impact, required context paths, and affected areas. - -This phase must not be run for `failed` or `blocked` validation results. -Those are not success states. Same rule as the **Task context synchronization phase**: context sync -runs only after a successful prior phase. - -Do not reconstruct a missing validation result from conversation history. - -#### 2.1 Validate the validation handoff - -Confirm that: - -- `Status:` is exactly `validated`. -- `Plan:` names an existing plan path. -- Acceptance-criteria evidence is present and every criterion is met. -- Commands run are present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, -do not modify context. Return a `blocked` Markdown report. - -#### 2.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. -Do not create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that validation itself succeeded and is recorded in the plan, and that -plan context synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -#### 2.3 Discover applicable context - -Start with the validated internal state: - -- **Context impact** classification, required context, and affected areas. -- Acceptance-criteria evidence. -- Commands run. - -Then read the plan's `Context sync` section and inspect existing repository -context in this order when present: - -1. Paths named by the plan's `Context sync` section -2. `context/context-map.md` -3. Context files for the affected domain or subsystem -4. `context/overview.md` -5. `context/architecture.md` -6. `context/glossary.md` -7. `context/patterns.md` -8. Operational, product, or decision records directly related to the finished - change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -##### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -finished implementation. A file that is absent is a gap; record it in the -report rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization -done while one of them is unchecked. - -##### Plan context requirements - -Every path or statement listed under the plan's `Context sync` section must be -accounted for in the report as already accurate or updated. A requirement the -finished code still does not satisfy is a blocker, not a note. - -#### 2.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -finished implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in validation evidence. -- Speculation or future work not established by the finished plan. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass or the plan's Context -sync requirements. - -- `none`: Make no edits beyond any correction the root pass or unmet plan - context requirement turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -#### 2.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- acceptance-criteria and validation evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task references, - related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -#### 2.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the validation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the finished implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the validation result verbatim into context files. -- Do not change application code, tests, or plan validation evidence. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -##### Feature existence - -Every feature the finished plan implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the plan delivered a feature no context file describes, add that -description. Prefer a small, precise domain file over overloading -`overview.md` with detail. - -This is not license to narrate the diff: describe what the feature is and how -it behaves, not what was edited during the plan. - -##### Glossary - -Add a `context/glossary.md` entry for any domain language the plan introduced. -New terminology is durable knowledge whatever the classification is. - -##### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it - into focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough - that prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -#### 2.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the finished implementation. -- No edited statement contradicts the code, plan, or validation evidence. -- Every qualifying decision has one written or reused ADR path in the report, - and the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Every plan `Context sync` requirement is met. -- Each feature implemented by the plan has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not rerun full-plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -#### 2.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` -means existing context was checked and no edit was warranted. `blocked` means -context could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. - -### Plan context synchronization boundaries - -Do not: - -- Accept a validation result whose status is not `validated`. -- Accept `failed` or `blocked` validation results. -- Implement or modify application code. -- Modify tests. -- Change task completion status, acceptance-criteria marks, or the Validation - Report. -- Rerun full-plan validation. -- Select or execute an implementation task. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason - to document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return internal state. +This phase verifies the five root context files on every invocation, whatever the +reported impact, and must account for every path in the plan's `Context sync` +section, so it is never correct to skip it as unnecessary. Branch on the synchronization result. @@ -564,6 +150,7 @@ Stop. ## Rules - Validate at most one plan per invocation. +- Read each phase's reference before running that phase. - Do not duplicate the internal instructions of embedded phases. - The only permitted sibling-skill invocation is `sce-decision`, and only the successful context-synchronization decision gate may invoke it. @@ -582,88 +169,3 @@ Stop. - Do not infer success when an embedded phase returns a non-success status. - Preserve validation evidence already written to the plan when context synchronization fails. - -## Internal persisted-document format: Plan-file validation report - -The Markdown section the **Validation phase** appends to the plan file when returning -`validated` or `failed`. Write it at the end of `context/plans/{plan_name}.md` -under exactly one `## Validation Report` heading. - -This is plan-file content. The result returned to the workflow is defined -separately in `references/output.md`. - -Do not author this section while planning. Only `/validate` through the **Validation phase** -writes it. - -### Layout - -```markdown -## Validation Report - -**Status:** {validated | failed} -**Date:** {YYYY-MM-DD} - -### Commands run - -- `{command}` -> exit {code} ({concise outcome summary}) -- `{command}` -> exit {code} ({concise outcome summary}) - -### Scaffolding removed - -- `{path}` — {why it was temporary} -- None. - -### Success-criteria verification - -- [x] AC1: {criterion statement} -> {evidence} -- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} - -### Failed checks and follow-ups - -- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} -- None. - -### Residual risks - -- {risk} -- None identified. - -### Retry - -{Only when Status is failed:} - -After repairs, rerun: - -`/validate {plan path}` -``` - -### Rules - -- Use **Status:** `validated` only when every acceptance criterion is met and - every required full-validation command passed. -- Use **Status:** `failed` when evidence was captured but required checks or - criteria remain unsatisfied. -- List every command that ran under **Commands run**, including ones that - failed. Do not invent exit codes or outcomes. -- Prefer the plan's `Full validation` commands and each criterion's `Validate:` - line over rediscovering project defaults. Fall back to repository conventions - only when the plan omits them. -- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` - section to match the evidence. Do not mark a criterion met unless the check - ran successfully or the inspection named by `Validate:` confirms it. -- Under **Scaffolding removed**, list only temporary debug code, intermediate - artifacts, or throwaway files introduced during the change. Write `None.` when - nothing temporary remained. -- Under **Failed checks and follow-ups**, record the failing check and its - evidence only. Do not describe code or test edits made during validation; - validation does not modify tests or product code to clear failures. Write - `None.` when status is `validated`. -- When status is `failed`, always include **Retry** with the exact - `/validate {plan path}` command. Omit **Retry** when status is `validated`. -- Keep evidence concise and factual. Do not narrate the whole implementation - history. -- Do not claim context synchronization completed. Plan context sync is a later - workflow step and runs only after `validated`. -- Do not rewrite task evidence or reopen completed tasks. -- When a previous `## Validation Report` already exists, replace it with the new - one rather than stacking duplicates. diff --git a/.claude/skills/sce-validate/references/context-sync.md b/.claude/skills/sce-validate/references/context-sync.md new file mode 100644 index 00000000..d6a45d46 --- /dev/null +++ b/.claude/skills/sce-validate/references/context-sync.md @@ -0,0 +1,306 @@ +# Plan context synchronization phase + +Run this phase for step 2 of the workflow, and only with a `Status: validated` +Markdown result from the validation phase. It is the plan-level final context +pass: it starts from the plan's `Context sync` requirements and the validated +implementation, and closes gaps that remain after any task-level syncs already +ran. + +Do not run this phase for `failed` or `blocked`. Those are not success states. +Same rule as the task context synchronization phase: context sync runs only after +a successful prior phase. + +Pass the validated result verbatim. It is the authoritative handoff, and this +phase owns reading the plan path, required context paths, validation evidence, +and reported context impact out of it. + +Do not restate, summarize, or reconstruct any part of the validation result. Do +not reconstruct a missing validation result from conversation history. + +Treat that Markdown as the authoritative handoff for: + +- The resolved plan path. +- Validation commands and outcomes. +- Acceptance-criteria evidence. +- Scaffolding removals. +- Reported context impact, required context paths, and affected areas. + +## 2.1 Validate the validation handoff + +Confirm that: + +- `Status:` is exactly `validated`. +- `Plan:` names an existing plan path. +- Acceptance-criteria evidence is present and every criterion is met. +- Commands run are present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 2.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that validation itself succeeded and is recorded in the plan, and that plan +context synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 2.3 Discover applicable context + +Start with the validated internal state: + +- **Context impact** classification, required context, and affected areas. +- Acceptance-criteria evidence. +- Commands run. + +Then read the plan's `Context sync` section and inspect existing repository +context in this order when present: + +1. Paths named by the plan's `Context sync` section +2. `context/context-map.md` +3. Context files for the affected domain or subsystem +4. `context/overview.md` +5. `context/architecture.md` +6. `context/glossary.md` +7. `context/patterns.md` +8. Operational, product, or decision records directly related to the finished + change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +finished implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +### Plan context requirements + +Every path or statement listed under the plan's `Context sync` section must be +accounted for in the report as already accurate or updated. A requirement the +finished code still does not satisfy is a blocker, not a note. + +## 2.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +finished implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in validation evidence. +- Speculation or future work not established by the finished plan. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass or the plan's Context sync +requirements. + +- `none`: Make no edits beyond any correction the root pass or unmet plan context + requirement turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 2.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- acceptance-criteria and validation evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task references, + related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 2.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the validation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the finished implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the validation result verbatim into context files. +- Do not change application code, tests, or plan validation evidence. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the finished plan implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the plan delivered a feature no context file describes, add that +description. Prefer a small, precise domain file over overloading `overview.md` +with detail. + +This is not license to narrate the diff: describe what the feature is and how it +behaves, not what was edited during the plan. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the plan introduced. +New terminology is durable knowledge whatever the classification is. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 2.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the finished implementation. +- No edited statement contradicts the code, plan, or validation evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Every plan `Context sync` requirement is met. +- Each feature implemented by the plan has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not rerun full-plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 2.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +## Plan context synchronization boundaries + +Do not: + +- Accept a validation result whose status is not `validated`. +- Accept `failed` or `blocked` validation results. +- Implement or modify application code. +- Modify tests. +- Change task completion status, acceptance-criteria marks, or the Validation + Report. +- Rerun full-plan validation. +- Select or execute an implementation task. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return internal state. diff --git a/.claude/skills/sce-validate/references/output.md b/.claude/skills/sce-validate/references/output.md index d2b7b888..88c75575 100644 --- a/.claude/skills/sce-validate/references/output.md +++ b/.claude/skills/sce-validate/references/output.md @@ -36,9 +36,9 @@ The `Status` value must be exactly one of: - `failed` - `blocked` -The plan-file `## Validation Report` section is written separately using the -**Plan-file validation report** section embedded in this file. This layout -carries the validation phase's result into the workflow's own branches. +The plan-file `## Validation Report` section is written separately using +`references/validation-report.md`. This layout carries the validation phase's +result into the workflow's own branches. ## Validated variant diff --git a/.claude/skills/sce-validate/references/validation-report.md b/.claude/skills/sce-validate/references/validation-report.md new file mode 100644 index 00000000..deaa9a0b --- /dev/null +++ b/.claude/skills/sce-validate/references/validation-report.md @@ -0,0 +1,84 @@ +# Internal persisted-document format: Plan-file validation report + +The Markdown section the **Validation phase** appends to the plan file when +returning `validated` or `failed`. Write it at the end of +`context/plans/{plan_name}.md` under exactly one `## Validation Report` heading. + +This is plan-file content. The result returned to the workflow is defined +separately in `references/output.md`. + +Do not author this section while planning. Only `/validate` through the +**Validation phase** writes it. + +## Layout + +```markdown +## Validation Report + +**Status:** {validated | failed} +**Date:** {YYYY-MM-DD} + +### Commands run + +- `{command}` -> exit {code} ({concise outcome summary}) +- `{command}` -> exit {code} ({concise outcome summary}) + +### Scaffolding removed + +- `{path}` — {why it was temporary} +- None. + +### Success-criteria verification + +- [x] AC1: {criterion statement} -> {evidence} +- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} + +### Failed checks and follow-ups + +- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} +- None. + +### Residual risks + +- {risk} +- None identified. + +### Retry + +{Only when Status is failed:} + +After repairs, rerun: + +`/validate {plan path}` +``` + +## Rules + +- Use **Status:** `validated` only when every acceptance criterion is met and + every required full-validation command passed. +- Use **Status:** `failed` when evidence was captured but required checks or + criteria remain unsatisfied. +- List every command that ran under **Commands run**, including ones that failed. + Do not invent exit codes or outcomes. +- Prefer the plan's `Full validation` commands and each criterion's `Validate:` + line over rediscovering project defaults. Fall back to repository conventions + only when the plan omits them. +- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` + section to match the evidence. Do not mark a criterion met unless the check ran + successfully or the inspection named by `Validate:` confirms it. +- Under **Scaffolding removed**, list only temporary debug code, intermediate + artifacts, or throwaway files introduced during the change. Write `None.` when + nothing temporary remained. +- Under **Failed checks and follow-ups**, record the failing check and its + evidence only. Do not describe code or test edits made during validation; + validation does not modify tests or product code to clear failures. Write + `None.` when status is `validated`. +- When status is `failed`, always include **Retry** with the exact + `/validate {plan path}` command. Omit **Retry** when status is `validated`. +- Keep evidence concise and factual. Do not narrate the whole implementation + history. +- Do not claim context synchronization completed. Plan context sync is a later + workflow step and runs only after `validated`. +- Do not rewrite task evidence or reopen completed tasks. +- When a previous `## Validation Report` already exists, replace it with the new + one rather than stacking duplicates. diff --git a/.claude/skills/sce-validate/references/validation.md b/.claude/skills/sce-validate/references/validation.md new file mode 100644 index 00000000..38e8944f --- /dev/null +++ b/.claude/skills/sce-validate/references/validation.md @@ -0,0 +1,161 @@ +# Validation phase + +Run this phase for step 1 of the workflow. It resolves one plan, confirms the +implementation is finished, runs the plan's checks, and records what it found. + +Input: the plan name or path, unmodified. + +This phase exclusively owns: + +- Resolving one plan. +- Confirming every implementation task is complete. +- Running full validation and acceptance-criteria checks. +- Removing temporary scaffolding. +- Writing the Validation Report into the plan. +- Returning one Markdown validation result. + +Do not duplicate any of it elsewhere in the workflow. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan under +`context/plans/`. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Confirm implementation is finished + +Set internal status `blocked` with incomplete tasks listed when any +implementation task remains incomplete. + +Final validation measures finished work. Do not run the full suite against a +partial stack, and do not complete remaining tasks here. + +## 1.3 Read the validation contract from the plan + +From the plan, collect: + +- Every acceptance criterion and its `Validate:` check. +- The `Full validation` command list. +- The `Context sync` requirements, for the context-impact handoff only. + +Set internal status `blocked` when the plan has no usable acceptance criteria, or +when no validation commands can be determined from the plan or repository +conventions. + +Prefer the plan's authored checks. Fall back to repository-primary test, lint, +and format commands only when `Full validation` is absent, and record that +fallback under notes on a `validated` or `failed` result. + +## 1.4 Remove temporary scaffolding + +Before or while running checks, remove temporary scaffolding introduced during +the change when it is clearly throwaway: + +- Debug-only patches or flags left enabled. +- Temporary files or intermediate artifacts not part of the delivered design. +- Local scaffolding the plan or task notes mark as temporary. + +Do not delete durable product code, tests, configuration, or context files. + +Record every removed path. When nothing temporary remains, report `None.` + +## 1.5 Run full validation and acceptance checks + +Run the plan's `Full validation` commands. + +Then verify each acceptance criterion using its `Validate:` line. Prefer a +runnable command. Use a named inspection only when the criterion authorizes it, +and say exactly what was inspected. + +When a check fails, record the failure and continue gathering evidence. Do not +modify tests, application code, or configuration to make a check pass. Final +validation measures the finished work; repair belongs to a later work session, +not this skill. + +Never report a check as passed unless it ran successfully or the authorized +inspection confirmed the criterion. + +Do not run task-by-task implementation work for incomplete tasks. That belongs to +`/next-task`. + +## 1.6 Update the plan + +For `validated` and `failed` outcomes: + +- Mark each acceptance criterion checkbox to match the evidence. +- Append or replace the plan's `## Validation Report` section using + `references/validation-report.md`. Read that file before writing the section. +- When status is `failed`, the plan-file report must include the retry command + `/validate {plan path}`. + +Do not reopen completed tasks, rewrite task evidence, or change the task stack. + +For `blocked`, leave the plan file unchanged. + +## 1.7 Determine context impact for the handoff + +On `validated` only, classify the durable context impact of the finished plan so +the **Plan context synchronization phase** can start from the plan's own +requirements: + +- Start from the plan's `Context sync` section. +- Inspect what the completed implementation actually changed when needed. +- Report required context paths and affected areas. +- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level + context sync. + +Do not edit context files here. + +On `failed` or `blocked`, omit context impact; context sync will not run. + +## 1.8 Return the internal state + +Set exactly one internal state: + +- `validated` when every acceptance criterion is met, required full validation + passed, and the Validation Report was written. +- `failed` when evidence was captured but required checks or criteria remain + unsatisfied. Shape it as a session handoff per `references/output.md`, ending + recommended work with `/validate {plan path}`. +- `blocked` when validation cannot proceed safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. +Do not return internal state. + +A `validated` result is the authoritative handoff into step 2, which reads the +plan path, required context paths, validation evidence, and reported context +impact out of it. It must report: + +```markdown +**Status:** validated +**Plan:** {plan path} +``` + +and must carry the resolved plan path, validation commands and outcomes, +acceptance-criteria evidence, scaffolding removals, and the reported context +impact with required context paths and affected areas. Step 2 is forbidden from +reconstructing any of that, so it has to be present here. + +## Validation boundaries + +Do not: + +- Validate more than one plan. +- Complete remaining implementation tasks. +- Modify tests, application code, or configuration to make a failing check pass. +- Apply lint or format auto-fixes that change product or test files as part of + making validation green. +- Synchronize durable context under `context/` outside the plan file. +- Create the context root. +- Mark the plan archived or delete the plan. +- Create a Git commit or push changes. +- Invent acceptance criteria the plan does not state. +- Claim verification that was not performed. +- Return a internal state. +- Run plan context synchronization. The workflow owns that step. diff --git a/.opencode/skills/sce-change-to-plan/SKILL.md b/.opencode/skills/sce-change-to-plan/SKILL.md index 9616e1b3..e3d9b57b 100644 --- a/.opencode/skills/sce-change-to-plan/SKILL.md +++ b/.opencode/skills/sce-change-to-plan/SKILL.md @@ -15,6 +15,25 @@ not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or workflow command. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/context-load.md` | +| 2 and 4 | `references/plan-authoring.md` | + +`references/plan-template.md` defines the plan file written to disk. The plan +authoring phase points to it at the moment a plan is actually written, which never +happens on a `needs_clarification` or `blocked` result. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at the +bootstrap gate never authors a plan, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -47,87 +66,11 @@ Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is ### 1. Load durable context -Run the **Context load phase** with the change request as the focus. +Read `references/context-load.md`, then run the **Context load phase** with the +change request as the focus. `context/` is durable AI-first memory describing current state. Load it before planning so the plan starts from recorded truth. Where context and code disagree, the code is the source of truth. -#### 1.1 Confirm the context root - -When `context/` does not exist, set internal status `bootstrap_required` immediately. Read -nothing further. - -Bootstrapping is the workflow's decision, not this phase's. - -#### 1.2 Read the entry points - -Read, when present: - -- `context/context-map.md` -- `context/overview.md` -- `context/glossary.md` - -Read `context/architecture.md` when the focus touches structure, boundaries, or -data flow. Read `context/patterns.md` when it touches conventions the change -must follow. - -A missing entry point is a gap, not a failure. Record it and continue. - -#### 1.3 Select the relevant domain context - -Consult `context/context-map.md` before any broad exploration. The map's -annotations name what each domain file owns; use them to select files, rather -than globbing or searching `context/`. - -Select only files whose subject overlaps the focus. Follow at most one level of -links out of a selected file, and only when the link is needed to understand the -focus. - -Do not read every domain file. A brief that includes everything has selected -nothing. - -Record focus areas with no matching context file under `gaps`. - -#### 1.4 Check recorded context against the code - -For each selected file, spot-check its central claims against the code it -describes. - -When context and code diverge, the code is the source of truth. Record the -divergence under `drift` with what context says, what the code shows, and the -repair the context needs. - -Do not repair it here. Later phases decide whether repair belongs in the current -work. - -Keep this proportional: check the claims the focus depends on, not every -sentence. - -#### 1.5 Return the brief - -Set exactly one internal state: - -- `loaded` -- `bootstrap_required` - -Report facts the workflow can act on. A brief that only lists file -paths has moved no knowledge. - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Context load boundaries - -Do not: - -- Create, update, move, or delete any file under `context/`. -- Bootstrap `context/`. -- Repair drift or stale context. -- Modify application code or tests. -- Read the entire `context/` tree by default. -- Explore the repository beyond what the focus and the selected context require. -- Ask the user questions. Report gaps and drift, and let the workflow decide. -- Author a plan, select a task, or implement anything. - Branch on `status`: `bootstrap_required` -> `context/` does not exist. Do not create it, and do not plan without it. Render the **Missing context bootstrap gate** layout from `references/output.md`. @@ -140,256 +83,18 @@ Do not read `context/` yourself. Do not repair drift or stale context; the brief ### 2. Author the plan -Run the **Plan authoring phase** with the change request and the complete `loaded` brief from the **Context load phase**. +Read `references/plan-authoring.md`, then run the **Plan authoring phase** with +the change request and the complete `loaded` brief from the **Context load +phase**. Pass the brief verbatim. Do not restate, summarize, or reinterpret it. -The **Plan authoring phase** exclusively owns: - -- Resolving whether the request targets a new or an existing plan. -- The clarification gate. -- Normalizing the change summary, acceptance criteria, constraints, and non-goals. -- Slicing the task stack into one-task/one-atomic-commit units. -- Writing `context/plans/{plan_name}.md`. - -Do not duplicate any of it. Do not write or edit the plan file yourself. - -Use the document format defined in the **Plan template** section embedded in this file. - -The workflow renders that result as the summary defined in: - -`references/output.md` - -The change request may name a plan, describe a change to an existing plan, or -describe entirely new work. Resolving which applies is this phase's -responsibility. - -The context brief is the durable memory this plan starts from. Treat its -`key_facts` as recorded current state, its `gaps` as areas with no durable -context, and its `drift` as context the code has already outrun. - -When no brief is supplied, load the context named by the change request before -authoring, and follow the selection discipline in *Inspect relevant context*. - -Answers the user gave to earlier clarification questions arrive as part of the -change request. Incorporate them into the plan. - -A revision of a plan authored earlier in the session also arrives as the change -request, and it is usually terse: a task boundary the user disagrees with, an -ordering they want changed, work they want added or dropped. Read it against the -existing plan, which supplies the scope, criteria, and terminology it omits. -Terseness is not ambiguity. Do not set internal status `needs_clarification` for detail the -plan already carries; ask only when the revision itself is genuinely undecidable. - -#### 2.1 Resolve the plan target - -Determine whether the request targets a new plan or an existing plan in -`context/plans/`. - -When it targets an existing plan, read that plan before authoring. Preserve its -completed tasks, their recorded evidence, its structure, and its terminology. - -When multiple existing plans match and none can be selected safely, return -`blocked` with the matching candidates. - -When the request targets a new plan, derive `plan_name` as a short kebab-case -slug of the change, and confirm it does not collide with an existing plan. - -Resolve exactly one plan target per invocation. - -#### 2.2 Challenge the change - -Before planning how to build the change, work out whether it is worth building. -A plan is a commitment of someone's time; authoring one for work that should not -happen is worse than authoring none. - -Interrogate the request: - -- What breaks, or stays broken, if this is never built? If the answer is - nothing concrete, say so. -- What problem is it actually solving, as opposed to what it proposes to do? A - request that names only a solution has not stated a problem. -- Does the repository already do this, or most of it? The brief's `key_facts` - are the first place to check. -- Is there a materially smaller version that gets most of the value? Name it. -- What does this cost beyond the tasks: new dependency, new concept in the - glossary, a boundary crossed, a surface that now needs maintaining forever? -- Does the stated justification survive contact with the code, or does the code - show the premise is already false? - -Doubt that survives this is not an implementation detail to be tidied away. It -belongs in the plan's `Open questions` and in `open_questions`, in the plain -words you would use to a colleague. "Is this worth doing at all, given X?" is a -legitimate open question. So is "this looks like it duplicates Y". - -Weigh honestly in both directions. A request that is obviously worth building -gets no manufactured doubt: inventing questions to look rigorous is its own -failure, and it teaches the user to ignore the section. Most changes are fine. -Say nothing when there is nothing to say. - -Keep going regardless. Skepticism shapes the plan and the open questions; it -does not withhold the plan. The only value judgment that stops authoring is -`no_actionable_work`, when the change is already implemented. - -#### 2.3 Run the clarification gate - -Before writing or updating any plan file, check the request for critical -unresolved detail: - -- Scope boundaries and out-of-scope items. -- Acceptance criteria and the checks that prove them. -- Constraints and non-goals. -- Dependency choices, including new libraries or services, versions, and the - integration approach. -- Domain ambiguity, including unclear business rules, terminology, or ownership. -- Architecture concerns, including patterns, interfaces, data flow, migration - strategy, and risk tradeoffs. -- Task ordering assumptions and prerequisite sequencing. - -Set internal status `needs_clarification` with one to three targeted questions when any of -these would materially change the plan. Write no plan file in that case. - -Use repository conventions for ordinary local choices. Do not block on: +This phase challenges whether the change is worth building before planning how to +build it, and it decides on its own whether to stop at the clarification gate. +Both shape what reaches the user, so reach them through the reference rather than +acting from this summary. -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change scope, acceptance criteria, or task ordering. - -Record those choices under `assumptions`. - -Do not silently invent missing requirements. When the user has explicitly -allowed assumptions, record them in the plan's `Assumptions` section instead of -asking. - -A justification that does not survive inspection is itself a critical unresolved -detail. "For consistency", "to make it cleaner", "we will need it later" name no -outcome and prove nothing; ask what the change is actually for before planning -around it. Do not treat confident phrasing as evidence. - -#### 2.4 Inspect relevant context - -Start from the context brief. Read code only where the brief leaves the change -underspecified: - -- Existing behavior the change affects. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests and available verification commands. -- Decisions or specifications connected to the change. - -Where the brief reports `drift`, the code is the source of truth. Plan against -the code, and schedule the context repair as part of the change when it falls -inside scope. - -Where the brief reports `gaps`, the plan may need to establish durable context -the repository does not yet have. - -Do not explore the entire repository by default. - -#### 2.5 Author the acceptance criteria - -State how the finished plan is proven, before slicing tasks. - -Each criterion describes observable behavior of the finished system and names -the check that proves it. Record repository-wide checks once under -`Full validation`, and the durable context the change must be reflected in -under `Context sync`. - -`/validate` runs this section after the last task completes. It is the only -place a plan says how it is validated. - -#### 2.6 Author the task stack - -Slice the work into sequential tasks `T01..T0N` using the task format and the -atomic slicing contract in the **Plan template** section embedded in this file. - -Every executable task must be completable and landable as one coherent commit. -Split any task that would require multiple independent commits. Convert broad -wrappers such as `polish` or `finalize` into specific outcomes with concrete -acceptance checks. - -Order tasks so each one's declared dependencies precede it. - -The last task is an ordinary implementation task. Do not author a trailing -validation-and-cleanup task, or any task whose only purpose is running the full -check suite, verifying durable context, or removing scaffolding. - -Confirm every acceptance criterion is satisfied by at least one task. When one -is not, the task stack is incomplete. - -A finished stack always leaves at least one incomplete task, so the workflow -can always hand off to `/next-task`. When the request resolves to a -plan but produces no incomplete task, because the change is already implemented -or already covered by completed tasks, set internal status `blocked` with category -`no_actionable_work` instead of writing the plan. - -#### 2.7 Write the plan - -Write `context/plans/{plan_name}.md` using the **Plan template** section embedded in this file. - -When updating an existing plan, keep completed tasks and their evidence intact, -and append or renumber new tasks without disturbing recorded history. - -#### 2.8 Return the result - -Set exactly one internal state: - -- `plan_ready` -- `needs_clarification` -- `blocked` - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Plan authoring tone - -Every question and open question this phase writes is read by the user. Write -them the way a senior engineer talks in review: direct, specific, and unbothered -by the possibility of being unwelcome. - -- Ask about the thing that actually worries you, not a safer neighbouring thing. - A question you would not bother asking a colleague is not worth the user's - attention either. -- State a doubt as a doubt. "I do not think this is worth the two tasks it - costs, because X" is useful. "It may be worth considering whether this aligns - with broader goals" is noise. -- Name the alternative you have in mind. A challenge with no proposal behind it - is just friction. -- Do not open with praise, do not close with reassurance, and do not apologize - for asking. Do not pad a doubt with hedges to make it land more gently. -- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not - restate the same doubt in three shapes to give it more weight. -- Being disagreeable is not the goal. Being easy to agree with is the failure - mode. A plan the user waves through without reading has cost them nothing and - bought them nothing. - -When the user overrules a doubt, record it and move on. Do not relitigate a -decision the user has made, and do not smuggle the objection back in as a -constraint, a non-goal, or a task. - -### Plan authoring boundaries - -Do not: - -- Ask the user questions directly. Set internal status `needs_clarification` and let the - workflow present the questions. -- Answer your own clarification questions. -- Write a plan file when returning `needs_clarification` or `blocked`. -- Implement any task in the plan. -- Modify application code or tests. -- Modify any file under `context/` outside `context/plans/`. Plan the context - repair instead of performing it. -- Mark any task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Author a validation, cleanup, or context-verification task. `/validate` owns - that phase. -- Set internal status `plan_ready` for a plan with no incomplete task. -- Create a Git commit. -- Author more than one plan. +Do not write or edit the plan file yourself. Branch on `status`: @@ -442,6 +147,7 @@ Stop. ## Rules - Plan at most one change request per invocation. Revisions to the plan that request produced are part of the same invocation, not a second request. +- Read each phase's reference before running that phase. - Always tell the user the plan can be revised, and always name its assumptions as the first thing worth checking. - Do not gate the handoff on open questions listed in the plan summary. Blocking questions return `needs_clarification` before any plan is written. Offering revision is not the same as demanding it, and inventing doubts to justify a review gate is not allowed. - Do not suppress, soften, or answer an open question or clarification question on the user's behalf. @@ -458,174 +164,3 @@ Stop. - Do not answer the skill's clarification questions on the user's behalf. - Do not execute the continuation returned at the end. - Do not infer success when the **Plan authoring phase** returns a non-`plan_ready` status. - -## Internal persisted-document format: Plan template - -The document format for `context/plans/{plan_name}.md`. This is the plan file -written to disk, not the result returned to the workflow. - -Copy the template below and fill every `{placeholder}`. Omit optional sections -entirely rather than writing them empty. - ---- - -### Template - -```markdown -# Plan: {plan-name} - -## Change summary - -{One or two paragraphs: what changes, where, and why. State whether this -extends existing behavior, replaces it, or preserves work already in progress.} - -## Acceptance criteria - -How this plan is proven complete. Each criterion is observable and names the -check that proves it. `/validate` runs these checks; no task in the stack -performs final validation. - -- [ ] AC1: {observable outcome, stated as behavior rather than as work done} - - Validate: `{command, assertion, or inspection that proves AC1}` -- [ ] AC2: {observable outcome} - - Validate: `{command, assertion, or inspection that proves AC2}` - -### Full validation - -Repository-wide checks `/validate` runs after the last task, regardless of -which criterion they map to. - -- `{full check suite command}` -- `{generated-output or parity check command, when applicable}` - -### Context sync - -- {Durable context files that must describe the change once implemented.} - -## Constraints and non-goals - -- **In scope:** {files, modules, and surfaces this plan may touch} -- **Out of scope:** {adjacent work explicitly excluded} -- **Constraints:** {dependencies, conventions, compatibility, or policy limits} -- **Non-goal:** {tempting generalization this plan deliberately avoids} - -## Assumptions - -{Include only when the user allowed assumptions, or ordinary local choices were -recorded. Remove the section otherwise.} - -- {Assumption, and the convention or decision record it rests on.} - -## Task stack - -- [ ] T01: `{single intent title}` (status:todo) - - Task ID: T01 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: {task IDs, or none} - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -- [ ] T02: `{single intent title}` (status:todo) - - Task ID: T02 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: T01 - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -## Open questions - -{Non-blocking questions only. A question that would change scope, success -criteria, or task ordering blocks authoring instead. Write `None.` with a short -justification when nothing remains.} - -{Unresolved doubt about the change's value belongs here — whether it is worth -building, whether it duplicates behavior the repository already has, whether a -smaller version would do. State it plainly and name the alternative. Do not -invent one: `None.` is the expected answer for a well-specified change.} -``` - ---- - -### Filled-in task example - -```markdown -- [ ] T02: `Add /auth/refresh endpoint` (status:todo) - - Task ID: T02 - - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. - - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. - - Dependencies: T01 - - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. - - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. -``` - -### Acceptance criteria rules - -- Acceptance criteria describe the finished system, not the work. Prefer "the - endpoint returns 401 on an expired token" over "add expiry handling". -- Every criterion carries a `Validate:` line. A criterion nobody can check is - not an acceptance criterion. -- Prefer a runnable command. Fall back to a named inspection only when no - automated check exists, and say exactly what to look at. -- List repository-wide checks once under `Full validation` instead of repeating - them per criterion. -- Task-level `Verification notes` prove one task. Acceptance criteria prove the - plan. Keep them distinct: a task's checks are narrow and local, a criterion's - check is end-to-end. -- The union of the acceptance criteria must cover every success signal in the - change request. If a criterion has no task that could satisfy it, the task - stack is incomplete. - -### Task rules - -- Every task is a checkbox line so progress stays machine-readable: - `- [ ] T01: {title} (status:todo)`. -- Author each executable task as one atomic commit unit by default. -- Scope every task so one contributor can complete it and land it as one - coherent commit without bundling unrelated changes. -- Split any candidate task that would require multiple independent commits, for - example a refactor plus a behavior change plus documentation. -- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of - executable tasks. Convert them into specific outcomes with concrete - acceptance checks. -- Order tasks so each one's declared dependencies precede it. - -### No validation task - -- The last task in the stack is an ordinary implementation task. Do not author a - trailing "validation and cleanup" task. -- Final validation, cleanup, and success-criteria verification are run by - `/validate` from the `Acceptance criteria` section after the last task - completes. -- Do not author a task whose only purpose is running the full check suite, - verifying durable context, or removing scaffolding. -- A task may still create or update durable context when that context is part of - the change itself. - -### Completion records - -When a task completes, the **Task execution phase** appends its evidence and flips the -checkbox and status: - -```markdown -- [x] T01: `{title}` (status:done) - - {authored fields, unchanged} - - Completed: {YYYY-MM-DD} - - Files changed: {paths} - - Evidence: {commands run and their outcomes} - - Notes: {material deviations or approved assumptions} -``` - -`/validate` appends a `## Validation Report` section at the end of the plan. -Do not author either while planning. - -### Updating an existing plan - -- Preserve completed tasks, their `(status:done)` markers, and their recorded - evidence verbatim. -- Preserve the plan's existing structure and terminology. -- Append new tasks after the existing stack. Renumber only when added work must - run earlier, and never renumber a completed task. -- Add acceptance criteria for newly planned outcomes rather than rewriting - criteria already satisfied. diff --git a/.opencode/skills/sce-change-to-plan/references/context-load.md b/.opencode/skills/sce-change-to-plan/references/context-load.md new file mode 100644 index 00000000..197a28c2 --- /dev/null +++ b/.opencode/skills/sce-change-to-plan/references/context-load.md @@ -0,0 +1,89 @@ +# Context load phase + +Run this phase for step 1 of the workflow, with the change request as the focus. + +`context/` is durable AI-first memory describing current state. Load it before +planning so the plan starts from recorded truth. Where context and code disagree, +the code is the source of truth. + +This phase reads and reports; it never writes. + +## 1.1 Confirm the context root + +When `context/` does not exist, set internal status `bootstrap_required` +immediately. Read nothing further. + +Bootstrapping is the workflow's decision, not this phase's. + +## 1.2 Read the entry points + +Read, when present: + +- `context/context-map.md` +- `context/overview.md` +- `context/glossary.md` + +Read `context/architecture.md` when the focus touches structure, boundaries, or +data flow. Read `context/patterns.md` when it touches conventions the change must +follow. + +A missing entry point is a gap, not a failure. Record it and continue. + +## 1.3 Select the relevant domain context + +Consult `context/context-map.md` before any broad exploration. The map's +annotations name what each domain file owns; use them to select files, rather +than globbing or searching `context/`. + +Select only files whose subject overlaps the focus. Follow at most one level of +links out of a selected file, and only when the link is needed to understand the +focus. + +Do not read every domain file. A brief that includes everything has selected +nothing. + +Record focus areas with no matching context file under `gaps`. + +## 1.4 Check recorded context against the code + +For each selected file, spot-check its central claims against the code it +describes. + +When context and code diverge, the code is the source of truth. Record the +divergence under `drift` with what context says, what the code shows, and the +repair the context needs. + +Do not repair it here. Later phases decide whether repair belongs in the current +work. + +Keep this proportional: check the claims the focus depends on, not every +sentence. + +## 1.5 Return the brief + +Set exactly one internal state: + +- `loaded` +- `bootstrap_required` + +Report facts the workflow can act on. A brief that only lists file paths has +moved no knowledge. + +Record only the internal state. Do not add explanatory prose before or after it. + +Step 2 consumes a `loaded` brief verbatim and treats its `key_facts` as recorded +current state, its `gaps` as areas with no durable context, and its `drift` as +context the code has already outrun. + +## Context load boundaries + +Do not: + +- Create, update, move, or delete any file under `context/`. +- Bootstrap `context/`. +- Repair drift or stale context. +- Modify application code or tests. +- Read the entire `context/` tree by default. +- Explore the repository beyond what the focus and the selected context require. +- Ask the user questions. Report gaps and drift, and let the workflow decide. +- Author a plan, select a task, or implement anything. diff --git a/.opencode/skills/sce-change-to-plan/references/plan-authoring.md b/.opencode/skills/sce-change-to-plan/references/plan-authoring.md new file mode 100644 index 00000000..17e054e2 --- /dev/null +++ b/.opencode/skills/sce-change-to-plan/references/plan-authoring.md @@ -0,0 +1,256 @@ +# Plan authoring phase + +Run this phase for step 2 of the workflow, and again for each revision in step 4. + +Input: the change request, and the complete `loaded` brief from the context load +phase. Pass the brief verbatim; do not restate, summarize, or reinterpret it. + +This phase exclusively owns: + +- Resolving whether the request targets a new or an existing plan. +- The clarification gate. +- Normalizing the change summary, acceptance criteria, constraints, and non-goals. +- Slicing the task stack into one-task/one-atomic-commit units. +- Writing `context/plans/{plan_name}.md`. + +Do not duplicate any of it elsewhere in the workflow. + +Use the document format in `references/plan-template.md`. Read it before writing +the plan file. + +The workflow renders this phase's result as the summary defined in +`references/output.md`. + +The change request may name a plan, describe a change to an existing plan, or +describe entirely new work. Resolving which applies is this phase's +responsibility. + +The context brief is the durable memory this plan starts from. Treat its +`key_facts` as recorded current state, its `gaps` as areas with no durable +context, and its `drift` as context the code has already outrun. + +When no brief is supplied, load the context named by the change request before +authoring, and follow the selection discipline in *Inspect relevant context*. + +Answers the user gave to earlier clarification questions arrive as part of the +change request. Incorporate them into the plan. + +A revision of a plan authored earlier in the session also arrives as the change +request, and it is usually terse: a task boundary the user disagrees with, an +ordering they want changed, work they want added or dropped. Read it against the +existing plan, which supplies the scope, criteria, and terminology it omits. +Terseness is not ambiguity. Do not set internal status `needs_clarification` for +detail the plan already carries; ask only when the revision itself is genuinely +undecidable. + +## 2.1 Resolve the plan target + +Determine whether the request targets a new plan or an existing plan in +`context/plans/`. + +When it targets an existing plan, read that plan before authoring. Preserve its +completed tasks, their recorded evidence, its structure, and its terminology. + +When multiple existing plans match and none can be selected safely, return +`blocked` with the matching candidates. + +When the request targets a new plan, derive `plan_name` as a short kebab-case +slug of the change, and confirm it does not collide with an existing plan. + +Resolve exactly one plan target per invocation. + +## 2.2 Challenge the change + +Before planning how to build the change, work out whether it is worth building. A +plan is a commitment of someone's time; authoring one for work that should not +happen is worse than authoring none. + +Interrogate the request: + +- What breaks, or stays broken, if this is never built? If the answer is nothing + concrete, say so. +- What problem is it actually solving, as opposed to what it proposes to do? A + request that names only a solution has not stated a problem. +- Does the repository already do this, or most of it? The brief's `key_facts` are + the first place to check. +- Is there a materially smaller version that gets most of the value? Name it. +- What does this cost beyond the tasks: new dependency, new concept in the + glossary, a boundary crossed, a surface that now needs maintaining forever? +- Does the stated justification survive contact with the code, or does the code + show the premise is already false? + +Doubt that survives this is not an implementation detail to be tidied away. It +belongs in the plan's `Open questions` and in `open_questions`, in the plain +words you would use to a colleague. "Is this worth doing at all, given X?" is a +legitimate open question. So is "this looks like it duplicates Y". + +Weigh honestly in both directions. A request that is obviously worth building +gets no manufactured doubt: inventing questions to look rigorous is its own +failure, and it teaches the user to ignore the section. Most changes are fine. +Say nothing when there is nothing to say. + +Keep going regardless. Skepticism shapes the plan and the open questions; it does +not withhold the plan. The only value judgment that stops authoring is +`no_actionable_work`, when the change is already implemented. + +## 2.3 Run the clarification gate + +Before writing or updating any plan file, check the request for critical +unresolved detail: + +- Scope boundaries and out-of-scope items. +- Acceptance criteria and the checks that prove them. +- Constraints and non-goals. +- Dependency choices, including new libraries or services, versions, and the + integration approach. +- Domain ambiguity, including unclear business rules, terminology, or ownership. +- Architecture concerns, including patterns, interfaces, data flow, migration + strategy, and risk tradeoffs. +- Task ordering assumptions and prerequisite sequencing. + +Set internal status `needs_clarification` with one to three targeted questions +when any of these would materially change the plan. Write no plan file in that +case. + +Use repository conventions for ordinary local choices. Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change scope, acceptance criteria, or task ordering. + +Record those choices under `assumptions`. + +Do not silently invent missing requirements. When the user has explicitly allowed +assumptions, record them in the plan's `Assumptions` section instead of asking. + +A justification that does not survive inspection is itself a critical unresolved +detail. "For consistency", "to make it cleaner", "we will need it later" name no +outcome and prove nothing; ask what the change is actually for before planning +around it. Do not treat confident phrasing as evidence. + +## 2.4 Inspect relevant context + +Start from the context brief. Read code only where the brief leaves the change +underspecified: + +- Existing behavior the change affects. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests and available verification commands. +- Decisions or specifications connected to the change. + +Where the brief reports `drift`, the code is the source of truth. Plan against +the code, and schedule the context repair as part of the change when it falls +inside scope. + +Where the brief reports `gaps`, the plan may need to establish durable context +the repository does not yet have. + +Do not explore the entire repository by default. + +## 2.5 Author the acceptance criteria + +State how the finished plan is proven, before slicing tasks. + +Each criterion describes observable behavior of the finished system and names the +check that proves it. Record repository-wide checks once under `Full validation`, +and the durable context the change must be reflected in under `Context sync`. + +`/validate` runs this section after the last task completes. It is the only place +a plan says how it is validated. + +## 2.6 Author the task stack + +Slice the work into sequential tasks `T01..T0N` using the task format and the +atomic slicing contract in `references/plan-template.md`. + +Every executable task must be completable and landable as one coherent commit. +Split any task that would require multiple independent commits. Convert broad +wrappers such as `polish` or `finalize` into specific outcomes with concrete +acceptance checks. + +Order tasks so each one's declared dependencies precede it. + +The last task is an ordinary implementation task. Do not author a trailing +validation-and-cleanup task, or any task whose only purpose is running the full +check suite, verifying durable context, or removing scaffolding. + +Confirm every acceptance criterion is satisfied by at least one task. When one is +not, the task stack is incomplete. + +A finished stack always leaves at least one incomplete task, so the workflow can +always hand off to `/next-task`. When the request resolves to a plan but produces +no incomplete task, because the change is already implemented or already covered +by completed tasks, set internal status `blocked` with category +`no_actionable_work` instead of writing the plan. + +## 2.7 Write the plan + +Write `context/plans/{plan_name}.md` using `references/plan-template.md`. + +When updating an existing plan, keep completed tasks and their evidence intact, +and append or renumber new tasks without disturbing recorded history. + +## 2.8 Return the result + +Set exactly one internal state: + +- `plan_ready` +- `needs_clarification` +- `blocked` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `plan_ready` result always names the next task in `next_task`, and carries the +`total_tasks` count and any open questions the summary needs. Step 3 renders those +without recomputing them. + +## Plan authoring tone + +Every question and open question this phase writes is read by the user. Write +them the way a senior engineer talks in review: direct, specific, and unbothered +by the possibility of being unwelcome. + +- Ask about the thing that actually worries you, not a safer neighbouring thing. + A question you would not bother asking a colleague is not worth the user's + attention either. +- State a doubt as a doubt. "I do not think this is worth the two tasks it + costs, because X" is useful. "It may be worth considering whether this aligns + with broader goals" is noise. +- Name the alternative you have in mind. A challenge with no proposal behind it + is just friction. +- Do not open with praise, do not close with reassurance, and do not apologize + for asking. Do not pad a doubt with hedges to make it land more gently. +- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not + restate the same doubt in three shapes to give it more weight. +- Being disagreeable is not the goal. Being easy to agree with is the failure + mode. A plan the user waves through without reading has cost them nothing and + bought them nothing. + +When the user overrules a doubt, record it and move on. Do not relitigate a +decision the user has made, and do not smuggle the objection back in as a +constraint, a non-goal, or a task. + +## Plan authoring boundaries + +Do not: + +- Ask the user questions directly. Set internal status `needs_clarification` and let the + workflow present the questions. +- Answer your own clarification questions. +- Write a plan file when returning `needs_clarification` or `blocked`. +- Implement any task in the plan. +- Modify application code or tests. +- Modify any file under `context/` outside `context/plans/`. Plan the context + repair instead of performing it. +- Mark any task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Author a validation, cleanup, or context-verification task. `/validate` owns + that phase. +- Set internal status `plan_ready` for a plan with no incomplete task. +- Create a Git commit. +- Author more than one plan. diff --git a/.opencode/skills/sce-change-to-plan/references/plan-template.md b/.opencode/skills/sce-change-to-plan/references/plan-template.md new file mode 100644 index 00000000..ac36a72c --- /dev/null +++ b/.opencode/skills/sce-change-to-plan/references/plan-template.md @@ -0,0 +1,170 @@ +# Internal persisted-document format: Plan template + +The document format for `context/plans/{plan_name}.md`. This is the plan file +written to disk, not the result returned to the workflow. + +Copy the template below and fill every `{placeholder}`. Omit optional sections +entirely rather than writing them empty. + +--- + +## Template + +```markdown +# Plan: {plan-name} + +## Change summary + +{One or two paragraphs: what changes, where, and why. State whether this +extends existing behavior, replaces it, or preserves work already in progress.} + +## Acceptance criteria + +How this plan is proven complete. Each criterion is observable and names the +check that proves it. `/validate` runs these checks; no task in the stack +performs final validation. + +- [ ] AC1: {observable outcome, stated as behavior rather than as work done} + - Validate: `{command, assertion, or inspection that proves AC1}` +- [ ] AC2: {observable outcome} + - Validate: `{command, assertion, or inspection that proves AC2}` + +### Full validation + +Repository-wide checks `/validate` runs after the last task, regardless of +which criterion they map to. + +- `{full check suite command}` +- `{generated-output or parity check command, when applicable}` + +### Context sync + +- {Durable context files that must describe the change once implemented.} + +## Constraints and non-goals + +- **In scope:** {files, modules, and surfaces this plan may touch} +- **Out of scope:** {adjacent work explicitly excluded} +- **Constraints:** {dependencies, conventions, compatibility, or policy limits} +- **Non-goal:** {tempting generalization this plan deliberately avoids} + +## Assumptions + +{Include only when the user allowed assumptions, or ordinary local choices were +recorded. Remove the section otherwise.} + +- {Assumption, and the convention or decision record it rests on.} + +## Task stack + +- [ ] T01: `{single intent title}` (status:todo) + - Task ID: T01 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: {task IDs, or none} + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +- [ ] T02: `{single intent title}` (status:todo) + - Task ID: T02 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: T01 + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +## Open questions + +{Non-blocking questions only. A question that would change scope, success +criteria, or task ordering blocks authoring instead. Write `None.` with a short +justification when nothing remains.} + +{Unresolved doubt about the change's value belongs here — whether it is worth +building, whether it duplicates behavior the repository already has, whether a +smaller version would do. State it plainly and name the alternative. Do not +invent one: `None.` is the expected answer for a well-specified change.} +``` + +--- + +## Filled-in task example + +```markdown +- [ ] T02: `Add /auth/refresh endpoint` (status:todo) + - Task ID: T02 + - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. + - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. + - Dependencies: T01 + - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. + - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. +``` + +## Acceptance criteria rules + +- Acceptance criteria describe the finished system, not the work. Prefer "the + endpoint returns 401 on an expired token" over "add expiry handling". +- Every criterion carries a `Validate:` line. A criterion nobody can check is + not an acceptance criterion. +- Prefer a runnable command. Fall back to a named inspection only when no + automated check exists, and say exactly what to look at. +- List repository-wide checks once under `Full validation` instead of repeating + them per criterion. +- Task-level `Verification notes` prove one task. Acceptance criteria prove the + plan. Keep them distinct: a task's checks are narrow and local, a criterion's + check is end-to-end. +- The union of the acceptance criteria must cover every success signal in the + change request. If a criterion has no task that could satisfy it, the task + stack is incomplete. + +## Task rules + +- Every task is a checkbox line so progress stays machine-readable: + `- [ ] T01: {title} (status:todo)`. +- Author each executable task as one atomic commit unit by default. +- Scope every task so one contributor can complete it and land it as one + coherent commit without bundling unrelated changes. +- Split any candidate task that would require multiple independent commits, for + example a refactor plus a behavior change plus documentation. +- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of + executable tasks. Convert them into specific outcomes with concrete + acceptance checks. +- Order tasks so each one's declared dependencies precede it. + +## No validation task + +- The last task in the stack is an ordinary implementation task. Do not author a + trailing "validation and cleanup" task. +- Final validation, cleanup, and success-criteria verification are run by + `/validate` from the `Acceptance criteria` section after the last task + completes. +- Do not author a task whose only purpose is running the full check suite, + verifying durable context, or removing scaffolding. +- A task may still create or update durable context when that context is part of + the change itself. + +## Completion records + +When a task completes, the **Task execution phase** appends its evidence and flips the +checkbox and status: + +```markdown +- [x] T01: `{title}` (status:done) + - {authored fields, unchanged} + - Completed: {YYYY-MM-DD} + - Files changed: {paths} + - Evidence: {commands run and their outcomes} + - Notes: {material deviations or approved assumptions} +``` + +`/validate` appends a `## Validation Report` section at the end of the plan. +Do not author either while planning. + +## Updating an existing plan + +- Preserve completed tasks, their `(status:done)` markers, and their recorded + evidence verbatim. +- Preserve the plan's existing structure and terminology. +- Append new tasks after the existing stack. Renumber only when added work must + run earlier, and never renumber a completed task. +- Add acceptance criteria for newly planned outcomes rather than rewriting + criteria already satisfied. diff --git a/.opencode/skills/sce-commit/SKILL.md b/.opencode/skills/sce-commit/SKILL.md index de4f1c53..91c8a724 100644 --- a/.opencode/skills/sce-commit/SKILL.md +++ b/.opencode/skills/sce-commit/SKILL.md @@ -15,6 +15,17 @@ not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or workflow command. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase reference + +Both paths below dispatch to the same phase, whose steps and boundaries live in +`references/atomic-commit.md`. This document holds the control flow — which path +runs, what the phase receives, and how its result branches — and the reference +holds the phase itself. + +Read `references/atomic-commit.md` before running the phase, not after. A regular +run that stops at the staging gate, and a bypass run that finds nothing staged, +both end without ever needing it. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -71,130 +82,10 @@ not skip this prompt because the working tree looks ready. #### 2. Propose commits -After confirmation, run the **Atomic commit phase** with `mode: regular` and the -commit context. - -The **Atomic commit phase** exclusively owns: - -- Reading and analyzing the staged diff. -- Deciding whether staged changes form one coherent unit or several. -- Classifying staged scope and applying context-file guidance gating. -- Writing every commit message subject and body. -- Applying the plan-citation body rule. - -Do not duplicate any of it. Do not write commit messages yourself. - -The mode is supplied by the workflow from an explicit user-supplied token. -Never infer it, and never switch modes mid-analysis. - -Commit context refines wording only. The staged diff decides what the change -is; context never overrides staged truth, and never adds a claim the diff does -not support. - -Do not accept an unstaged diff, a working-tree summary, or a conversational -description as a substitute for the staged diff. - -##### 2.1 Read the staged diff - -Read the staged changes with `git diff --cached`, and the staged file list with -`git diff --cached --name-status`. - -Read staged file contents only when the diff alone does not explain the change. - -Set internal status `blocked` when nothing is staged. - -##### 2.2 Identify coherent units - -Infer the main reason for the staged change from the diff first. - -A coherent unit is one goal a reviewer would accept as a single commit. Group -staged files by that goal, not by directory. - -In `bypass` mode, stop grouping here: the result is exactly one message -covering all staged files, whether or not the diff is coherent. Do not propose -splits, and do not report split guidance. - -##### 2.3 Choose a scope for each unit - -Use the smallest stable subsystem or module name recognizable in the repository. - -When no such name applies, use the primary directory or package of the unit's -changes. - -##### 2.4 Write each message - -Follow `references/output.md` for the subject pattern, the body -rules, issue references, the plan-citation rule, and the anti-patterns. - -##### 2.5 Apply the plan-citation rule - -When the unit's staged files include `context/plans/*.md`, cite the affected -plan slug and updated task IDs in the body. - -When the staged plan diff does not expose the slug or task ID clearly enough to -cite faithfully: - -- In `regular` mode, set internal status `blocked` and ask for the reference to be stated or - staged explicitly. -- In `bypass` mode, infer the citation when the diff supports it, and otherwise - omit it. Never stop, and never invent a slug or task ID. - -##### 2.6 Apply context-file guidance gating - -This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do -not classify staged scope there. - -Classify the staged diff: - -- Context-only (`context/**`): context-file-focused guidance is allowed. -- Mixed (`context/**` plus non-`context/**`): suppress default context-file - commit reminders and give guidance that reflects the full staged scope. - -##### 2.7 Propose split guidance - -This step applies in `regular` mode only. - -When the units found in step 2 pursue unrelated goals, return one message per -unit, and state why the split is recommended and which staged files belong to -each. - -When the staged changes form one unit, return one message and no split -guidance. Do not split coherent work to appear thorough. - -##### 2.8 Validate the result - -Confirm before returning that: - -- Every message describes its unit faithfully and covers only that unit's files. -- Every staged file belongs to exactly one returned message. -- No plan slug or task ID appears that the staged diff does not support. -- The mode's own constraints hold. - -##### 2.9 Return internal state - -Set exactly one internal state: - -- `proposal` in `regular` mode, with one or more messages. -- `bypass_message` in `bypass` mode, with exactly one message. -- `blocked` when messages cannot be written faithfully. - -Record only the internal state. Do not add explanatory prose before or after it. - -#### Atomic commit boundaries - -Do not: +After confirmation, read `references/atomic-commit.md`, then run the **Atomic +commit phase** with `mode: regular` and the commit context. -- Run `git commit`, or any command that writes to the repository or its index. -- Stage, unstage, or modify files. -- Ask the user to stage or confirm staging. -- Analyze unstaged or untracked changes. -- Return more than one message in `bypass` mode. -- Return split guidance in `bypass` mode. -- Stop for plan-citation ambiguity in `bypass` mode. -- Invent plan slugs, task IDs, or issue references. -- Mention `context/` synchronization activity in a commit message. -- Claim a message was committed. -- Run plan, task, or validation workflows. +Do not write commit messages yourself. Branch on `status`: @@ -222,7 +113,8 @@ Do not stage anything. Do not proceed to the skill. #### 2. Request one commit message -Run the **Atomic commit phase** (described at the Regular path's step 2 above) with `mode: bypass` and the commit context. +Read `references/atomic-commit.md`, then run the **Atomic commit phase** with +`mode: bypass` and the commit context. Bypass mode is the skill's contract for producing exactly one message. Do not restate its overrides here; the **Atomic commit phase** owns them. @@ -254,6 +146,7 @@ fallback commit. - Never commit on the regular path. - Recognize `oneshot` and `skip` only as an exact case-insensitive first token. They are behaviorally identical. +- Read `references/atomic-commit.md` before running the phase. - Do not duplicate the internal instructions of the **Atomic commit phase**. - Do not stage, unstage, restore, or otherwise modify files. - Do not amend, reset, revert, rebase, or push. diff --git a/.opencode/skills/sce-commit/references/atomic-commit.md b/.opencode/skills/sce-commit/references/atomic-commit.md new file mode 100644 index 00000000..ecdeb3bd --- /dev/null +++ b/.opencode/skills/sce-commit/references/atomic-commit.md @@ -0,0 +1,130 @@ +# Atomic commit phase + +Both workflow paths run this phase. The regular path runs it with `mode: regular` +after the staging gate; the bypass path runs it with `mode: bypass` after +confirming staged content exists. + +Input: the mode, supplied by the workflow from an explicit user-supplied token, +and the commit context. + +This phase exclusively owns: + +- Reading and analyzing the staged diff. +- Deciding whether staged changes form one coherent unit or several. +- Classifying staged scope and applying context-file guidance gating. +- Writing every commit message subject and body. +- Applying the plan-citation body rule. + +Do not duplicate any of it elsewhere in the workflow. Do not write commit messages +outside this phase. + +Never infer the mode, and never switch modes mid-analysis. + +Commit context refines wording only. The staged diff decides what the change is; +context never overrides staged truth, and never adds a claim the diff does not +support. + +Do not accept an unstaged diff, a working-tree summary, or a conversational +description as a substitute for the staged diff. + +## 1. Read the staged diff + +Read the staged changes with `git diff --cached`, and the staged file list with +`git diff --cached --name-status`. + +Read staged file contents only when the diff alone does not explain the change. + +Set internal status `blocked` when nothing is staged. + +## 2. Identify coherent units + +Infer the main reason for the staged change from the diff first. + +A coherent unit is one goal a reviewer would accept as a single commit. Group +staged files by that goal, not by directory. + +In `bypass` mode, stop grouping here: the result is exactly one message covering +all staged files, whether or not the diff is coherent. Do not propose splits, and +do not report split guidance. + +## 3. Choose a scope for each unit + +Use the smallest stable subsystem or module name recognizable in the repository. + +When no such name applies, use the primary directory or package of the unit's +changes. + +## 4. Write each message + +Follow `references/output.md` for the subject pattern, the body rules, issue +references, the plan-citation rule, and the anti-patterns. + +## 5. Apply the plan-citation rule + +When the unit's staged files include `context/plans/*.md`, cite the affected plan +slug and updated task IDs in the body. + +When the staged plan diff does not expose the slug or task ID clearly enough to +cite faithfully: + +- In `regular` mode, set internal status `blocked` and ask for the reference to be + stated or staged explicitly. +- In `bypass` mode, infer the citation when the diff supports it, and otherwise + omit it. Never stop, and never invent a slug or task ID. + +## 6. Apply context-file guidance gating + +This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do +not classify staged scope there. + +Classify the staged diff: + +- Context-only (`context/**`): context-file-focused guidance is allowed. +- Mixed (`context/**` plus non-`context/**`): suppress default context-file commit + reminders and give guidance that reflects the full staged scope. + +## 7. Propose split guidance + +This step applies in `regular` mode only. + +When the units found in step 2 pursue unrelated goals, return one message per +unit, and state why the split is recommended and which staged files belong to +each. + +When the staged changes form one unit, return one message and no split guidance. +Do not split coherent work to appear thorough. + +## 8. Validate the result + +Confirm before returning that: + +- Every message describes its unit faithfully and covers only that unit's files. +- Every staged file belongs to exactly one returned message. +- No plan slug or task ID appears that the staged diff does not support. +- The mode's own constraints hold. + +## 9. Return internal state + +Set exactly one internal state: + +- `proposal` in `regular` mode, with one or more messages. +- `bypass_message` in `bypass` mode, with exactly one message. +- `blocked` when messages cannot be written faithfully. + +Record only the internal state. Do not add explanatory prose before or after it. + +## Atomic commit boundaries + +Do not: + +- Run `git commit`, or any command that writes to the repository or its index. +- Stage, unstage, or modify files. +- Ask the user to stage or confirm staging. +- Analyze unstaged or untracked changes. +- Return more than one message in `bypass` mode. +- Return split guidance in `bypass` mode. +- Stop for plan-citation ambiguity in `bypass` mode. +- Invent plan slugs, task IDs, or issue references. +- Mention `context/` synchronization activity in a commit message. +- Claim a message was committed. +- Run plan, task, or validation workflows. diff --git a/.opencode/skills/sce-next-task/SKILL.md b/.opencode/skills/sce-next-task/SKILL.md index 012bce37..06bb58cc 100644 --- a/.opencode/skills/sce-next-task/SKILL.md +++ b/.opencode/skills/sce-next-task/SKILL.md @@ -16,6 +16,25 @@ workflow command except `sce-decision`, and invoke `sce-decision` only from the successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps, gates, and boundaries +live in a reference file. This document holds the control flow — which phase runs, +what it receives, and how its result branches — and each reference holds the phase +itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/plan-review.md` | +| 2 | `references/task-execution.md` | +| 3 | `references/context-sync.md` | + +Read a step's reference before taking any action for that step, not after. The +references carry gates that must fire before their phase's first side effect, so a +phase begun from this summary alone will already have skipped them. Read only the +reference for the step you have reached: a run that stops at step 1 never needs the +other two, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -53,111 +72,11 @@ Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is ### 1. Review the task -Run the **Plan review phase** with the parsed `plan-name-or-path` and, when present, the parsed `task-id`. +Read `references/plan-review.md`, then run the **Plan review phase** with the +parsed `plan-name-or-path` and, when present, the parsed `task-id`. Do not pass the `auto-approve` token to the **Plan review phase**. -#### 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status `blocked` with -the matching candidates. - -Read the selected plan before exploring the repository. - -#### 1.2 Resolve one task - -When a task ID is supplied, select that task. - -Otherwise, select the first incomplete task in plan order whose declared -dependencies are complete. - -Set internal status `plan_complete` when no incomplete tasks remain. - -Set internal status `blocked` when incomplete tasks remain but none can currently be -executed. - -Review at most one task per invocation. - -#### 1.3 Inspect relevant context - -Start with the task and the files it directly references. - -Inspect only what is needed to understand: - -- Existing behavior. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests. -- Available verification commands. -- Decisions or specifications connected to the task. - -Load root context only when the task affects repository-wide behavior, -architecture, shared terminology, or cross-domain interfaces. - -Do not explore the entire repository by default. - -#### 1.4 Determine readiness - -A task is `ready` when: - -- Its goal is clear. -- Its scope is sufficiently bounded. -- Its dependencies are complete. -- Its done checks are observable. -- A credible verification method exists. -- No unresolved decision would materially change the implementation. - -Use repository conventions for ordinary local choices. - -Do not block on: - -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change observable behavior or scope. - -Record these choices under `assumptions`. - -Set internal status `blocked` when a missing decision materially affects: - -- User-visible behavior. -- Public interfaces. -- Architecture or ownership boundaries. -- Data shape or persistence. -- Security or privacy. -- External dependencies. -- Destructive or difficult-to-reverse behavior. -- The evidence needed to prove completion. - -#### 1.5 Return the result - -Set exactly one internal state: - -- `ready` -- `blocked` -- `plan_complete` - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Plan review boundaries - -Do not: - -- Modify application code. -- Modify tests. -- Update the plan. -- Mark the task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Review more than one task. - Branch on `status`: `blocked` -> Do not run implementation. Render the **Review blocked** layout from `references/output.md`. When `candidates` is present the plan could not be resolved, and each entry is a candidate path for `/next-task {candidate-path}`. `executable_tasks_remaining` true means another task remains executable and `/next-task {plan-path} {task-id}` selects one; false means no task in the plan can proceed until the plan is updated. Do not print the raw result. Stop. @@ -170,7 +89,13 @@ Do not reconstruct, summarize, or reinterpret the reviewed task before passing i ### 2. Execute the task -Run the **Task execution phase** with the complete `ready` result from the **Plan review phase**. +Read `references/task-execution.md`, then run the **Task execution phase** with +the complete `ready` result from the **Plan review phase**. + +This phase always shows an implementation gate before it modifies any file, and it +is the only phase permitted to ask the user for confirmation. Both properties are +load-bearing, so reach them through the reference rather than acting from this +summary. Branch on `auto-approve`: @@ -178,205 +103,8 @@ Branch on `auto-approve`: else -> Do not pass the `approve` flag. The **Task execution phase** shows its implementation gate and waits for the user's decision. -The **Task execution phase** exclusively owns: - -- Presenting the implementation summary. -- Requesting implementation confirmation. -- Implementing the task. -- Running task-level verification. -- Updating the task status and evidence. - Do not present an additional implementation confirmation. -The `approve` flag means the user pre-approved this task when invoking the -workflow. It suppresses the approval question and the wait. It never suppresses -the gate. Only the workflow entrypoint may set it, and only from an explicit -user-supplied approval token. Never infer it. - -The readiness result must identify: - -- One resolved plan. -- Exactly one incomplete task. -- The task goal and scope boundaries. -- Done checks. -- Verification expectations. -- Relevant files and context. -- Review assumptions. - -If required handoff information is absent or stale, still show the gate using -what is known, clearly identify the handoff problem, and do not edit files. -After the user responds, set internal status `blocked`. - -#### 2.1 Validate the handoff without editing - -Confirm that: - -- The readiness status is `ready`. -- Exactly one task is present. -- The plan file exists. -- The selected task is still incomplete. -- The task has not materially changed since review. -- Declared dependencies remain complete. - -Do not reconstruct missing material requirements. - -#### 2.2 Always show the implementation gate - -At the start of the phase, before any file modification, present the task using -`references/output.md`. - -The gate must be shown even when: - -- The task appears straightforward. -- The workflow believes approval was already implied. -- The handoff is stale or incomplete. -- The user is likely to approve. - -When the `approve` flag is absent, end the gate with exactly one approval -question: - -`Continue with implementation now? (yes/no)` - -Stop and wait for the user's answer. Do not return internal state, and make no file -modifications, until the user has answered. - -When the `approve` flag is supplied, show the gate as a summary, omit the -approval question, do not wait, and continue at step 2.4. - -#### 2.3 Handle the user's decision - -Skip this step when the `approve` flag was supplied. - -When the user rejects or cancels, do not modify files and set internal status `declined`. - -When the user does not clearly approve, do not modify files. Ask the same -approval question once more only when the response is genuinely ambiguous. -Otherwise set internal status `blocked`. - -When the user approves, continue with implementation. - -Treat constraints supplied with approval as part of the approved task boundary. -If those constraints materially contradict the reviewed task, set internal status `blocked` -before editing. - -#### 2.4 Prepare the implementation - -Before editing: - -- Read the relevant files supplied by plan review. -- Inspect nearby code and tests when needed. -- Identify the smallest coherent change satisfying the task. -- Follow surrounding naming, structure, error handling, and test style. -- Preserve unrelated behavior. - -Do not create a second plan. - -Do not broaden the reviewed task. - -#### 2.5 Implement one task - -Make the minimum coherent changes required to satisfy the task goal and done -checks. - -Use judgment for ordinary, reversible local implementation choices. - -Stop when implementation requires: - -- Material scope expansion. -- A new external dependency not authorized by the task. -- A public-interface decision not established by the plan. -- A destructive or difficult-to-reverse operation. -- An unresolved security, privacy, or data decision. -- Contradicting the reviewed task or repository architecture. - -When stopped, preserve completed in-scope work unless retaining it would leave -the repository unsafe or invalid. - -#### 2.6 Verify the task - -Run the narrowest authoritative checks that demonstrate the done checks. - -Start with verification supplied by the readiness result. Add nearby or directly -relevant checks only when needed. - -Verification may include: - -- Targeted tests. -- Type checking for affected code. -- Linting affected files. -- Formatting checks. -- A focused build or compile step. -- Direct behavioral inspection when no automated check exists. - -Do not run final plan validation unless the task itself explicitly requires it. - -When a check fails: - -- Determine whether the task caused the failure. -- Fix it when the correction remains in scope. -- Rerun the relevant check. -- Set internal status `incomplete` when a done check remains unsatisfied, or `blocked` when - completing it requires an unapproved decision or scope expansion. - -Never report a check as passed unless it ran successfully. - -#### 2.7 Update the plan - -Only after successful implementation and task-level verification: - -- Mark only the selected task complete. -- Record concise implementation evidence. -- Record verification commands and outcomes. -- Record material deviations or approved assumptions. -- Preserve the plan's existing structure and terminology. - -Do not mark the task complete when returning `declined`, `blocked`, or -`incomplete`. - -#### 2.8 Determine the terminal status - -Set internal status `complete` when the task was implemented, verified, and marked complete -in the plan with evidence. - -Set internal status `incomplete` when in-scope work was completed but one or more done checks -remain unsatisfied. - -Set internal status `declined` when the user rejected implementation. - -Set internal status `blocked` for every other non-successful outcome, including: - -- Missing approval. -- Stale or invalid handoff. -- Material blocker. -- A verification failure that cannot be resolved in scope. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -#### 2.9 Return internal state - -After the phase reaches a terminal state, set exactly one internal state. - -Record only the internal state. Do not add explanatory prose before or after it. - -### Task execution boundaries - -Do not: - -- Edit before approval, whether explicit or pre-supplied. -- Execute more than one task. -- Select or execute the next task. -- Skip the implementation gate. -- Ask for multiple approval gates for the same unchanged task. -- Expand scope without authorization. -- Synchronize durable context. -- Run final plan validation. -- Determine whether the plan is complete. -- Create a Git commit. -- Push changes. -- Modify unrelated files. -- Claim verification that was not performed. - Branch on the execution result. `declined` -> Render the **Declined** layout from `references/output.md`. Do not run context synchronization. Stop. @@ -389,319 +117,16 @@ Branch on the execution result. ### 3. Synchronize context -Run the **Task context synchronization phase** with the complete `complete` result returned by the **Task execution phase**. +Read `references/context-sync.md`, then run the **Task context synchronization +phase** with the complete `complete` result returned by the **Task execution +phase**. Pass that result verbatim. It is the authoritative handoff, and the **Task context synchronization phase** owns reading the plan, task, changed files, verification evidence, and reported context impact out of it. Do not restate, summarize, or reconstruct any part of the execution result. -The execution result must have: - -```text -status: complete -``` - -Treat the execution result as the authoritative handoff for: - -- The resolved plan and completed task. -- Files changed by implementation. -- Implementation summary. -- Verification evidence. -- Done-check evidence. -- Reported context impact. - -This phase must not be run for `declined`, `blocked`, or `incomplete` -execution results. - -Do not reconstruct a missing execution result from conversation history. - -#### 3.1 Validate the execution handoff - -Confirm that: - -- `status` is exactly `complete`. -- A `plan` object with a `path` is present. -- Exactly one completed task is identified. -- Changed files and an implementation summary are present. -- Verification evidence is present. -- Done-check evidence is present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, -do not modify context. Return a `blocked` Markdown report. - -#### 3.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. -Do not create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that the task itself is complete and recorded in the plan, and that -synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -#### 3.3 Discover applicable context - -Start with the execution result: - -- `context_impact.classification` -- `context_impact.affected_areas` -- Changed files. -- Implementation summary. -- Done-check evidence. - -Then inspect existing repository context in this order when present: - -1. `context/context-map.md` -2. Context files for the affected domain or subsystem -3. `context/overview.md` -4. `context/architecture.md` -5. `context/glossary.md` -6. `context/patterns.md` -7. Operational, product, or decision records directly related to the change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -##### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -completed implementation. A file that is absent is a gap; record it in the -report rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization -done while one of them is unchecked. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -#### 3.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in task evidence. -- Speculation or future work not established by the completed implementation. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass. - -- `none`: Make no edits beyond any correction the root pass turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -A change is `root` when it introduces cross-cutting behavior, repository-wide -policy or contracts, an architecture or ownership boundary, or a change to -canonical terminology. A change confined to one feature or domain, with no -repository-wide behavior, architecture, or terminology impact, is `domain` or -`local`: capture its detail in domain files and leave the root files unedited. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -#### 3.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- execution and done-check evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task references, - related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -#### 3.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the implementation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the completed implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the execution result verbatim into context files. -- Do not change application code, tests, or plan state. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -##### Feature existence - -Every feature the completed task implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the task implemented a feature no context file describes, add that -description. A feature that fits no existing domain file gets a new focused -file; do not defer it to a later task. Prefer a small, precise domain file over -overloading `overview.md` with detail. - -This is the one case where documentation is warranted by the change itself -rather than by a gap in durable knowledge. It is not license to narrate the -diff: describe what the feature is and how it behaves, not what was edited. - -##### Glossary - -Add a `context/glossary.md` entry for any domain language the task introduced. -New terminology is durable knowledge whatever the classification is: a `domain` -change that names a new concept still earns its glossary entry. - -##### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it - into focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough - that prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -#### 3.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the completed implementation. -- No edited statement contradicts the code, plan, or execution evidence. -- Every qualifying decision has one written or reused ADR path in the report, - and the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Each feature implemented by the task has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not run full application or plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -#### 3.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` -means existing context was checked and no edit was warranted. `blocked` means -context could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -### Task context synchronization boundaries - -Do not: - -- Accept an execution result whose status is not `complete`. -- Implement or modify application code. -- Modify tests. -- Change task completion status or plan evidence. -- Determine whether the plan is complete. -- Select or execute another task. -- Run full-plan validation. -- Mark the plan validated, closed, or archived. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason - to document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return an execution-style internal state. +This phase verifies the five root context files on every invocation, whatever the +change's reported impact, so it is never correct to skip it as unnecessary. Branch on the synchronization result. @@ -729,6 +154,7 @@ Stop. - Execute at most one plan task per invocation. - Review at most one task. +- Read each phase's reference before running that phase. - Do not duplicate the internal instructions of embedded phases. - The only permitted sibling-skill invocation is `sce-decision`, and only the successful context-synchronization decision gate may invoke it. diff --git a/.opencode/skills/sce-next-task/references/context-sync.md b/.opencode/skills/sce-next-task/references/context-sync.md new file mode 100644 index 00000000..06413b09 --- /dev/null +++ b/.opencode/skills/sce-next-task/references/context-sync.md @@ -0,0 +1,316 @@ +# Task context synchronization phase + +Run this phase for step 3 of the workflow, and only when task execution returned +`complete`. It updates durable repository knowledge in `context/` so the next +session inherits what this task established. It never touches code, tests, or +plan state. + +Input: the complete `complete` result from the task execution phase, passed +verbatim. It is the authoritative handoff, and this phase owns reading the plan, +task, changed files, verification evidence, and reported context impact out of +it. + +Do not restate, summarize, or reconstruct any part of the execution result. Do +not reconstruct a missing execution result from conversation history. + +The execution result must have: + +```text +status: complete +``` + +Treat the execution result as the authoritative handoff for: + +- The resolved plan and completed task. +- Files changed by implementation. +- Implementation summary. +- Verification evidence. +- Done-check evidence. +- Reported context impact. + +This phase must not be run for `declined`, `blocked`, or `incomplete` execution +results. + +## 3.1 Validate the execution handoff + +Confirm that: + +- `status` is exactly `complete`. +- A `plan` object with a `path` is present. +- Exactly one completed task is identified. +- Changed files and an implementation summary are present. +- Verification evidence is present. +- Done-check evidence is present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 3.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that the task itself is complete and recorded in the plan, and that +synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 3.3 Discover applicable context + +Start with the execution result: + +- `context_impact.classification` +- `context_impact.affected_areas` +- Changed files. +- Implementation summary. +- Done-check evidence. + +Then inspect existing repository context in this order when present: + +1. `context/context-map.md` +2. Context files for the affected domain or subsystem +3. `context/overview.md` +4. `context/architecture.md` +5. `context/glossary.md` +6. `context/patterns.md` +7. Operational, product, or decision records directly related to the change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +completed implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +## 3.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in task evidence. +- Speculation or future work not established by the completed implementation. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass. + +- `none`: Make no edits beyond any correction the root pass turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +A change is `root` when it introduces cross-cutting behavior, repository-wide +policy or contracts, an architecture or ownership boundary, or a change to +canonical terminology. A change confined to one feature or domain, with no +repository-wide behavior, architecture, or terminology impact, is `domain` or +`local`: capture its detail in domain files and leave the root files unedited. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 3.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- execution and done-check evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task + references, related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 3.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the implementation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the completed implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the execution result verbatim into context files. +- Do not change application code, tests, or plan state. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the completed task implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the task implemented a feature no context file describes, add that +description. A feature that fits no existing domain file gets a new focused file; +do not defer it to a later task. Prefer a small, precise domain file over +overloading `overview.md` with detail. + +This is the one case where documentation is warranted by the change itself rather +than by a gap in durable knowledge. It is not license to narrate the diff: +describe what the feature is and how it behaves, not what was edited. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the task introduced. +New terminology is durable knowledge whatever the classification is: a `domain` +change that names a new concept still earns its glossary entry. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 3.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the completed implementation. +- No edited statement contradicts the code, plan, or execution evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Each feature implemented by the task has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not run full application or plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 3.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## Task context synchronization boundaries + +Do not: + +- Accept an execution result whose status is not `complete`. +- Implement or modify application code. +- Modify tests. +- Change task completion status or plan evidence. +- Determine whether the plan is complete. +- Select or execute another task. +- Run full-plan validation. +- Mark the plan validated, closed, or archived. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return an execution-style internal state. diff --git a/.opencode/skills/sce-next-task/references/plan-review.md b/.opencode/skills/sce-next-task/references/plan-review.md new file mode 100644 index 00000000..d08975e3 --- /dev/null +++ b/.opencode/skills/sce-next-task/references/plan-review.md @@ -0,0 +1,121 @@ +# Plan review phase + +Run this phase for step 1 of the workflow. It resolves one plan, selects one +task, and decides whether that task can be implemented right now. It reads; it +never writes. + +Inputs: the parsed `plan-name-or-path`, and `task-id` when present. The +`auto-approve` token is not passed here and has no meaning in this phase. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Resolve one task + +When a task ID is supplied, select that task. + +Otherwise, select the first incomplete task in plan order whose declared +dependencies are complete. + +Set internal status `plan_complete` when no incomplete tasks remain. + +Set internal status `blocked` when incomplete tasks remain but none can currently +be executed. + +Review at most one task per invocation. + +## 1.3 Inspect relevant context + +Start with the task and the files it directly references. + +Inspect only what is needed to understand: + +- Existing behavior. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests. +- Available verification commands. +- Decisions or specifications connected to the task. + +Load root context only when the task affects repository-wide behavior, +architecture, shared terminology, or cross-domain interfaces. + +Do not explore the entire repository by default. + +## 1.4 Determine readiness + +A task is `ready` when: + +- Its goal is clear. +- Its scope is sufficiently bounded. +- Its dependencies are complete. +- Its done checks are observable. +- A credible verification method exists. +- No unresolved decision would materially change the implementation. + +Use repository conventions for ordinary local choices. + +Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change observable behavior or scope. + +Record these choices under `assumptions`. + +Set internal status `blocked` when a missing decision materially affects: + +- User-visible behavior. +- Public interfaces. +- Architecture or ownership boundaries. +- Data shape or persistence. +- Security or privacy. +- External dependencies. +- Destructive or difficult-to-reverse behavior. +- The evidence needed to prove completion. + +## 1.5 Return the result + +Set exactly one internal state: + +- `ready` +- `blocked` +- `plan_complete` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `ready` result must identify: + +- One resolved plan. +- Exactly one incomplete task. +- The task goal and scope boundaries. +- Done checks. +- Verification expectations. +- Relevant files and context. +- Review assumptions. + +Step 2 consumes this result verbatim, so anything the execution phase needs has +to be present here. + +## Plan review boundaries + +Do not: + +- Modify application code. +- Modify tests. +- Update the plan. +- Mark the task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Review more than one task. diff --git a/.opencode/skills/sce-next-task/references/task-execution.md b/.opencode/skills/sce-next-task/references/task-execution.md new file mode 100644 index 00000000..7b049492 --- /dev/null +++ b/.opencode/skills/sce-next-task/references/task-execution.md @@ -0,0 +1,203 @@ +# Task execution phase + +Run this phase for step 2 of the workflow. It is the only phase that writes +application code, and the only one that asks the user for anything. + +Input: the complete `ready` result from the plan review phase, plus the `approve` +flag when the user pre-approved this invocation. + +This phase exclusively owns: + +- Presenting the implementation summary. +- Requesting implementation confirmation. +- Implementing the task. +- Running task-level verification. +- Updating the task status and evidence. + +Do not present an additional implementation confirmation anywhere else. + +The `approve` flag means the user pre-approved this task when invoking the +workflow. It suppresses the approval question and the wait. It never suppresses +the gate. Only the workflow entrypoint may set it, and only from an explicit +user-supplied approval token. Never infer it. + +If required handoff information is absent or stale, still show the gate using +what is known, clearly identify the handoff problem, and do not edit files. After +the user responds, set internal status `blocked`. + +## 2.1 Validate the handoff without editing + +Confirm that: + +- The readiness status is `ready`. +- Exactly one task is present. +- The plan file exists. +- The selected task is still incomplete. +- The task has not materially changed since review. +- Declared dependencies remain complete. + +Do not reconstruct missing material requirements. + +## 2.2 Always show the implementation gate + +At the start of the phase, before any file modification, present the task using +`references/output.md`. + +The gate must be shown even when: + +- The task appears straightforward. +- The workflow believes approval was already implied. +- The handoff is stale or incomplete. +- The user is likely to approve. + +When the `approve` flag is absent, end the gate with exactly one approval +question: + +`Continue with implementation now? (yes/no)` + +Stop and wait for the user's answer. Do not return internal state, and make no +file modifications, until the user has answered. + +When the `approve` flag is supplied, show the gate as a summary, omit the +approval question, do not wait, and continue at step 2.4. + +## 2.3 Handle the user's decision + +Skip this step when the `approve` flag was supplied. + +When the user rejects or cancels, do not modify files and set internal status +`declined`. + +When the user does not clearly approve, do not modify files. Ask the same +approval question once more only when the response is genuinely ambiguous. +Otherwise set internal status `blocked`. + +When the user approves, continue with implementation. + +Treat constraints supplied with approval as part of the approved task boundary. +If those constraints materially contradict the reviewed task, set internal status +`blocked` before editing. + +## 2.4 Prepare the implementation + +Before editing: + +- Read the relevant files supplied by plan review. +- Inspect nearby code and tests when needed. +- Identify the smallest coherent change satisfying the task. +- Follow surrounding naming, structure, error handling, and test style. +- Preserve unrelated behavior. + +Do not create a second plan. + +Do not broaden the reviewed task. + +## 2.5 Implement one task + +Make the minimum coherent changes required to satisfy the task goal and done +checks. + +Use judgment for ordinary, reversible local implementation choices. + +Stop when implementation requires: + +- Material scope expansion. +- A new external dependency not authorized by the task. +- A public-interface decision not established by the plan. +- A destructive or difficult-to-reverse operation. +- An unresolved security, privacy, or data decision. +- Contradicting the reviewed task or repository architecture. + +When stopped, preserve completed in-scope work unless retaining it would leave +the repository unsafe or invalid. + +## 2.6 Verify the task + +Run the narrowest authoritative checks that demonstrate the done checks. + +Start with verification supplied by the readiness result. Add nearby or directly +relevant checks only when needed. + +Verification may include: + +- Targeted tests. +- Type checking for affected code. +- Linting affected files. +- Formatting checks. +- A focused build or compile step. +- Direct behavioral inspection when no automated check exists. + +Do not run final plan validation unless the task itself explicitly requires it. + +When a check fails: + +- Determine whether the task caused the failure. +- Fix it when the correction remains in scope. +- Rerun the relevant check. +- Set internal status `incomplete` when a done check remains unsatisfied, or + `blocked` when completing it requires an unapproved decision or scope + expansion. + +Never report a check as passed unless it ran successfully. + +## 2.7 Update the plan + +Only after successful implementation and task-level verification: + +- Mark only the selected task complete. +- Record concise implementation evidence. +- Record verification commands and outcomes. +- Record material deviations or approved assumptions. +- Preserve the plan's existing structure and terminology. + +Do not mark the task complete when returning `declined`, `blocked`, or +`incomplete`. + +## 2.8 Determine the terminal status + +Set internal status `complete` when the task was implemented, verified, and +marked complete in the plan with evidence. + +Set internal status `incomplete` when in-scope work was completed but one or more +done checks remain unsatisfied. + +Set internal status `declined` when the user rejected implementation. + +Set internal status `blocked` for every other non-successful outcome, including: + +- Missing approval. +- Stale or invalid handoff. +- Material blocker. +- A verification failure that cannot be resolved in scope. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## 2.9 Return internal state + +After the phase reaches a terminal state, set exactly one internal state. + +Record only the internal state. Do not add explanatory prose before or after it. + +A `complete` result is the authoritative handoff into step 3, which reads the +plan, completed task, changed files, implementation summary, verification +evidence, done-check evidence, and context-impact classification out of it. Step +3 is forbidden from reconstructing any of that, so it has to be present here. + +## Task execution boundaries + +Do not: + +- Edit before approval, whether explicit or pre-supplied. +- Execute more than one task. +- Select or execute the next task. +- Skip the implementation gate. +- Ask for multiple approval gates for the same unchanged task. +- Expand scope without authorization. +- Synchronize durable context. +- Run final plan validation. +- Determine whether the plan is complete. +- Create a Git commit. +- Push changes. +- Modify unrelated files. +- Claim verification that was not performed. diff --git a/.opencode/skills/sce-validate/SKILL.md b/.opencode/skills/sce-validate/SKILL.md index b4ac2d17..898fb185 100644 --- a/.opencode/skills/sce-validate/SKILL.md +++ b/.opencode/skills/sce-validate/SKILL.md @@ -16,6 +16,25 @@ workflow command except `sce-decision`, and invoke `sce-decision` only from the successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/validation.md` | +| 2 | `references/context-sync.md` | + +`references/validation-report.md` defines the `## Validation Report` section +written into the plan file. Step 1 points to it at the moment it is needed, on a +`validated` or `failed` outcome only. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at a `blocked` +or `failed` validation never enters step 2, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -54,147 +73,15 @@ candidate path), so every emitted command is directly runnable. ### 1. Validate the plan -Run the **Validation phase** with the plan name or path. - -The **Validation phase** exclusively owns: - -- Resolving one plan. -- Confirming every implementation task is complete. -- Running full validation and acceptance-criteria checks. -- Removing temporary scaffolding. -- Writing the Validation Report into the plan. -- Returning one Markdown validation result. - -Do not duplicate any of it. Do not write the Validation Report yourself. - -#### 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan under -`context/plans/`. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status `blocked` -with the matching candidates. - -Read the selected plan before exploring the repository. - -#### 1.2 Confirm implementation is finished - -Set internal status `blocked` with incomplete tasks listed when any implementation task -remains incomplete. - -Final validation measures finished work. Do not run the full suite against a -partial stack, and do not complete remaining tasks here. - -#### 1.3 Read the validation contract from the plan - -From the plan, collect: - -- Every acceptance criterion and its `Validate:` check. -- The `Full validation` command list. -- The `Context sync` requirements, for the context-impact handoff only. - -Set internal status `blocked` when the plan has no usable acceptance criteria, or when no -validation commands can be determined from the plan or repository conventions. - -Prefer the plan's authored checks. Fall back to repository-primary test, lint, -and format commands only when `Full validation` is absent, and record that -fallback under notes on a `validated` or `failed` result. - -#### 1.4 Remove temporary scaffolding - -Before or while running checks, remove temporary scaffolding introduced during -the change when it is clearly throwaway: - -- Debug-only patches or flags left enabled. -- Temporary files or intermediate artifacts not part of the delivered design. -- Local scaffolding the plan or task notes mark as temporary. - -Do not delete durable product code, tests, configuration, or context files. - -Record every removed path. When nothing temporary remains, report `None.` - -#### 1.5 Run full validation and acceptance checks - -Run the plan's `Full validation` commands. - -Then verify each acceptance criterion using its `Validate:` line. Prefer a -runnable command. Use a named inspection only when the criterion authorizes it, -and say exactly what was inspected. - -When a check fails, record the failure and continue gathering evidence. Do not -modify tests, application code, or configuration to make a check pass. Final -validation measures the finished work; repair belongs to a later work session, -not this skill. - -Never report a check as passed unless it ran successfully or the authorized -inspection confirmed the criterion. - -Do not run task-by-task implementation work for incomplete tasks. That belongs -to `/next-task`. - -#### 1.6 Update the plan +Read `references/validation.md`, then run the **Validation phase** with the plan +name or path. -For `validated` and `failed` outcomes: +This phase measures finished work and never repairs it: it does not modify tests, +application code, or configuration to make a failing check pass. That property is +load-bearing, so reach it through the reference rather than acting from this +summary. -- Mark each acceptance criterion checkbox to match the evidence. -- Append or replace the plan's `## Validation Report` section using - the **Plan-file validation report** section embedded in this file. -- When status is `failed`, the plan-file report must include the retry command - `/validate {plan path}`. - -Do not reopen completed tasks, rewrite task evidence, or change the task stack. - -For `blocked`, leave the plan file unchanged. - -#### 1.7 Determine context impact for the handoff - -On `validated` only, classify the durable context impact of the finished plan -so the **Plan context synchronization phase** can start from the plan's own requirements: - -- Start from the plan's `Context sync` section. -- Inspect what the completed implementation actually changed when needed. -- Report required context paths and affected areas. -- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level - context sync. - -Do not edit context files here. - -On `failed` or `blocked`, omit context impact; context sync will not run. - -#### 1.8 Return the internal state - -Set exactly one internal state: - -- `validated` when every acceptance criterion is met, required full validation - passed, and the Validation Report was written. -- `failed` when evidence was captured but required checks or criteria remain - unsatisfied. Shape it as a session handoff per - `references/output.md`, ending recommended work with - `/validate {plan path}`. -- `blocked` when validation cannot proceed safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. Do not return internal state. - -### Validation boundaries - -Do not: - -- Validate more than one plan. -- Complete remaining implementation tasks. -- Modify tests, application code, or configuration to make a failing check pass. -- Apply lint or format auto-fixes that change product or test files as part of - making validation green. -- Synchronize durable context under `context/` outside the plan file. -- Create the context root. -- Mark the plan archived or delete the plan. -- Create a Git commit or push changes. -- Invent acceptance criteria the plan does not state. -- Claim verification that was not performed. -- Return a internal state. -- Run plan context synchronization. The workflow owns that step. +Do not write the Validation Report yourself. Branch on the report's `Status:`. @@ -219,8 +106,9 @@ passing it. ### 2. Synchronize plan context -Run the **Plan context synchronization phase** only with a `Status: validated` Markdown result -from the **Validation phase**. +Read `references/context-sync.md`, then run the **Plan context synchronization +phase** with the `Status: validated` Markdown result from the **Validation +phase**. Do not run the **Plan context synchronization phase** for `failed` or `blocked`. Those are not success states. @@ -231,311 +119,9 @@ reported context impact out of it. Do not restate, summarize, or reconstruct any part of the validation result. -Task-level context sync may already have run after individual tasks. This phase -is the plan-level final pass: it starts from the plan's `Context sync` -requirements and the validated implementation, and closes gaps that remain. - -The validation result must report: - -```markdown -**Status:** validated -**Plan:** {plan path} -``` - -Treat that Markdown as the authoritative handoff for: - -- The resolved plan path. -- Validation commands and outcomes. -- Acceptance-criteria evidence. -- Scaffolding removals. -- Reported context impact, required context paths, and affected areas. - -This phase must not be run for `failed` or `blocked` validation results. -Those are not success states. Same rule as the **Task context synchronization phase**: context sync -runs only after a successful prior phase. - -Do not reconstruct a missing validation result from conversation history. - -#### 2.1 Validate the validation handoff - -Confirm that: - -- `Status:` is exactly `validated`. -- `Plan:` names an existing plan path. -- Acceptance-criteria evidence is present and every criterion is met. -- Commands run are present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, -do not modify context. Return a `blocked` Markdown report. - -#### 2.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. -Do not create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that validation itself succeeded and is recorded in the plan, and that -plan context synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -#### 2.3 Discover applicable context - -Start with the validated internal state: - -- **Context impact** classification, required context, and affected areas. -- Acceptance-criteria evidence. -- Commands run. - -Then read the plan's `Context sync` section and inspect existing repository -context in this order when present: - -1. Paths named by the plan's `Context sync` section -2. `context/context-map.md` -3. Context files for the affected domain or subsystem -4. `context/overview.md` -5. `context/architecture.md` -6. `context/glossary.md` -7. `context/patterns.md` -8. Operational, product, or decision records directly related to the finished - change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -##### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -finished implementation. A file that is absent is a gap; record it in the -report rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization -done while one of them is unchecked. - -##### Plan context requirements - -Every path or statement listed under the plan's `Context sync` section must be -accounted for in the report as already accurate or updated. A requirement the -finished code still does not satisfy is a blocker, not a note. - -#### 2.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -finished implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in validation evidence. -- Speculation or future work not established by the finished plan. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass or the plan's Context -sync requirements. - -- `none`: Make no edits beyond any correction the root pass or unmet plan - context requirement turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -#### 2.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- acceptance-criteria and validation evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task references, - related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -#### 2.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the validation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the finished implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the validation result verbatim into context files. -- Do not change application code, tests, or plan validation evidence. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -##### Feature existence - -Every feature the finished plan implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the plan delivered a feature no context file describes, add that -description. Prefer a small, precise domain file over overloading -`overview.md` with detail. - -This is not license to narrate the diff: describe what the feature is and how -it behaves, not what was edited during the plan. - -##### Glossary - -Add a `context/glossary.md` entry for any domain language the plan introduced. -New terminology is durable knowledge whatever the classification is. - -##### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it - into focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough - that prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -#### 2.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the finished implementation. -- No edited statement contradicts the code, plan, or validation evidence. -- Every qualifying decision has one written or reused ADR path in the report, - and the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Every plan `Context sync` requirement is met. -- Each feature implemented by the plan has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not rerun full-plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -#### 2.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` -means existing context was checked and no edit was warranted. `blocked` means -context could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. - -### Plan context synchronization boundaries - -Do not: - -- Accept a validation result whose status is not `validated`. -- Accept `failed` or `blocked` validation results. -- Implement or modify application code. -- Modify tests. -- Change task completion status, acceptance-criteria marks, or the Validation - Report. -- Rerun full-plan validation. -- Select or execute an implementation task. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason - to document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return internal state. +This phase verifies the five root context files on every invocation, whatever the +reported impact, and must account for every path in the plan's `Context sync` +section, so it is never correct to skip it as unnecessary. Branch on the synchronization result. @@ -564,6 +150,7 @@ Stop. ## Rules - Validate at most one plan per invocation. +- Read each phase's reference before running that phase. - Do not duplicate the internal instructions of embedded phases. - The only permitted sibling-skill invocation is `sce-decision`, and only the successful context-synchronization decision gate may invoke it. @@ -582,88 +169,3 @@ Stop. - Do not infer success when an embedded phase returns a non-success status. - Preserve validation evidence already written to the plan when context synchronization fails. - -## Internal persisted-document format: Plan-file validation report - -The Markdown section the **Validation phase** appends to the plan file when returning -`validated` or `failed`. Write it at the end of `context/plans/{plan_name}.md` -under exactly one `## Validation Report` heading. - -This is plan-file content. The result returned to the workflow is defined -separately in `references/output.md`. - -Do not author this section while planning. Only `/validate` through the **Validation phase** -writes it. - -### Layout - -```markdown -## Validation Report - -**Status:** {validated | failed} -**Date:** {YYYY-MM-DD} - -### Commands run - -- `{command}` -> exit {code} ({concise outcome summary}) -- `{command}` -> exit {code} ({concise outcome summary}) - -### Scaffolding removed - -- `{path}` — {why it was temporary} -- None. - -### Success-criteria verification - -- [x] AC1: {criterion statement} -> {evidence} -- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} - -### Failed checks and follow-ups - -- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} -- None. - -### Residual risks - -- {risk} -- None identified. - -### Retry - -{Only when Status is failed:} - -After repairs, rerun: - -`/validate {plan path}` -``` - -### Rules - -- Use **Status:** `validated` only when every acceptance criterion is met and - every required full-validation command passed. -- Use **Status:** `failed` when evidence was captured but required checks or - criteria remain unsatisfied. -- List every command that ran under **Commands run**, including ones that - failed. Do not invent exit codes or outcomes. -- Prefer the plan's `Full validation` commands and each criterion's `Validate:` - line over rediscovering project defaults. Fall back to repository conventions - only when the plan omits them. -- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` - section to match the evidence. Do not mark a criterion met unless the check - ran successfully or the inspection named by `Validate:` confirms it. -- Under **Scaffolding removed**, list only temporary debug code, intermediate - artifacts, or throwaway files introduced during the change. Write `None.` when - nothing temporary remained. -- Under **Failed checks and follow-ups**, record the failing check and its - evidence only. Do not describe code or test edits made during validation; - validation does not modify tests or product code to clear failures. Write - `None.` when status is `validated`. -- When status is `failed`, always include **Retry** with the exact - `/validate {plan path}` command. Omit **Retry** when status is `validated`. -- Keep evidence concise and factual. Do not narrate the whole implementation - history. -- Do not claim context synchronization completed. Plan context sync is a later - workflow step and runs only after `validated`. -- Do not rewrite task evidence or reopen completed tasks. -- When a previous `## Validation Report` already exists, replace it with the new - one rather than stacking duplicates. diff --git a/.opencode/skills/sce-validate/references/context-sync.md b/.opencode/skills/sce-validate/references/context-sync.md new file mode 100644 index 00000000..d6a45d46 --- /dev/null +++ b/.opencode/skills/sce-validate/references/context-sync.md @@ -0,0 +1,306 @@ +# Plan context synchronization phase + +Run this phase for step 2 of the workflow, and only with a `Status: validated` +Markdown result from the validation phase. It is the plan-level final context +pass: it starts from the plan's `Context sync` requirements and the validated +implementation, and closes gaps that remain after any task-level syncs already +ran. + +Do not run this phase for `failed` or `blocked`. Those are not success states. +Same rule as the task context synchronization phase: context sync runs only after +a successful prior phase. + +Pass the validated result verbatim. It is the authoritative handoff, and this +phase owns reading the plan path, required context paths, validation evidence, +and reported context impact out of it. + +Do not restate, summarize, or reconstruct any part of the validation result. Do +not reconstruct a missing validation result from conversation history. + +Treat that Markdown as the authoritative handoff for: + +- The resolved plan path. +- Validation commands and outcomes. +- Acceptance-criteria evidence. +- Scaffolding removals. +- Reported context impact, required context paths, and affected areas. + +## 2.1 Validate the validation handoff + +Confirm that: + +- `Status:` is exactly `validated`. +- `Plan:` names an existing plan path. +- Acceptance-criteria evidence is present and every criterion is met. +- Commands run are present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 2.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that validation itself succeeded and is recorded in the plan, and that plan +context synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 2.3 Discover applicable context + +Start with the validated internal state: + +- **Context impact** classification, required context, and affected areas. +- Acceptance-criteria evidence. +- Commands run. + +Then read the plan's `Context sync` section and inspect existing repository +context in this order when present: + +1. Paths named by the plan's `Context sync` section +2. `context/context-map.md` +3. Context files for the affected domain or subsystem +4. `context/overview.md` +5. `context/architecture.md` +6. `context/glossary.md` +7. `context/patterns.md` +8. Operational, product, or decision records directly related to the finished + change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +finished implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +### Plan context requirements + +Every path or statement listed under the plan's `Context sync` section must be +accounted for in the report as already accurate or updated. A requirement the +finished code still does not satisfy is a blocker, not a note. + +## 2.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +finished implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in validation evidence. +- Speculation or future work not established by the finished plan. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass or the plan's Context sync +requirements. + +- `none`: Make no edits beyond any correction the root pass or unmet plan context + requirement turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 2.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- acceptance-criteria and validation evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task references, + related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 2.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the validation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the finished implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the validation result verbatim into context files. +- Do not change application code, tests, or plan validation evidence. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the finished plan implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the plan delivered a feature no context file describes, add that +description. Prefer a small, precise domain file over overloading `overview.md` +with detail. + +This is not license to narrate the diff: describe what the feature is and how it +behaves, not what was edited during the plan. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the plan introduced. +New terminology is durable knowledge whatever the classification is. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 2.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the finished implementation. +- No edited statement contradicts the code, plan, or validation evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Every plan `Context sync` requirement is met. +- Each feature implemented by the plan has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not rerun full-plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 2.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +## Plan context synchronization boundaries + +Do not: + +- Accept a validation result whose status is not `validated`. +- Accept `failed` or `blocked` validation results. +- Implement or modify application code. +- Modify tests. +- Change task completion status, acceptance-criteria marks, or the Validation + Report. +- Rerun full-plan validation. +- Select or execute an implementation task. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return internal state. diff --git a/.opencode/skills/sce-validate/references/output.md b/.opencode/skills/sce-validate/references/output.md index d2b7b888..88c75575 100644 --- a/.opencode/skills/sce-validate/references/output.md +++ b/.opencode/skills/sce-validate/references/output.md @@ -36,9 +36,9 @@ The `Status` value must be exactly one of: - `failed` - `blocked` -The plan-file `## Validation Report` section is written separately using the -**Plan-file validation report** section embedded in this file. This layout -carries the validation phase's result into the workflow's own branches. +The plan-file `## Validation Report` section is written separately using +`references/validation-report.md`. This layout carries the validation phase's +result into the workflow's own branches. ## Validated variant diff --git a/.opencode/skills/sce-validate/references/validation-report.md b/.opencode/skills/sce-validate/references/validation-report.md new file mode 100644 index 00000000..deaa9a0b --- /dev/null +++ b/.opencode/skills/sce-validate/references/validation-report.md @@ -0,0 +1,84 @@ +# Internal persisted-document format: Plan-file validation report + +The Markdown section the **Validation phase** appends to the plan file when +returning `validated` or `failed`. Write it at the end of +`context/plans/{plan_name}.md` under exactly one `## Validation Report` heading. + +This is plan-file content. The result returned to the workflow is defined +separately in `references/output.md`. + +Do not author this section while planning. Only `/validate` through the +**Validation phase** writes it. + +## Layout + +```markdown +## Validation Report + +**Status:** {validated | failed} +**Date:** {YYYY-MM-DD} + +### Commands run + +- `{command}` -> exit {code} ({concise outcome summary}) +- `{command}` -> exit {code} ({concise outcome summary}) + +### Scaffolding removed + +- `{path}` — {why it was temporary} +- None. + +### Success-criteria verification + +- [x] AC1: {criterion statement} -> {evidence} +- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} + +### Failed checks and follow-ups + +- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} +- None. + +### Residual risks + +- {risk} +- None identified. + +### Retry + +{Only when Status is failed:} + +After repairs, rerun: + +`/validate {plan path}` +``` + +## Rules + +- Use **Status:** `validated` only when every acceptance criterion is met and + every required full-validation command passed. +- Use **Status:** `failed` when evidence was captured but required checks or + criteria remain unsatisfied. +- List every command that ran under **Commands run**, including ones that failed. + Do not invent exit codes or outcomes. +- Prefer the plan's `Full validation` commands and each criterion's `Validate:` + line over rediscovering project defaults. Fall back to repository conventions + only when the plan omits them. +- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` + section to match the evidence. Do not mark a criterion met unless the check ran + successfully or the inspection named by `Validate:` confirms it. +- Under **Scaffolding removed**, list only temporary debug code, intermediate + artifacts, or throwaway files introduced during the change. Write `None.` when + nothing temporary remained. +- Under **Failed checks and follow-ups**, record the failing check and its + evidence only. Do not describe code or test edits made during validation; + validation does not modify tests or product code to clear failures. Write + `None.` when status is `validated`. +- When status is `failed`, always include **Retry** with the exact + `/validate {plan path}` command. Omit **Retry** when status is `validated`. +- Keep evidence concise and factual. Do not narrate the whole implementation + history. +- Do not claim context synchronization completed. Plan context sync is a later + workflow step and runs only after `validated`. +- Do not rewrite task evidence or reopen completed tasks. +- When a previous `## Validation Report` already exists, replace it with the new + one rather than stacking duplicates. diff --git a/.opencode/skills/sce-validate/references/validation.md b/.opencode/skills/sce-validate/references/validation.md new file mode 100644 index 00000000..38e8944f --- /dev/null +++ b/.opencode/skills/sce-validate/references/validation.md @@ -0,0 +1,161 @@ +# Validation phase + +Run this phase for step 1 of the workflow. It resolves one plan, confirms the +implementation is finished, runs the plan's checks, and records what it found. + +Input: the plan name or path, unmodified. + +This phase exclusively owns: + +- Resolving one plan. +- Confirming every implementation task is complete. +- Running full validation and acceptance-criteria checks. +- Removing temporary scaffolding. +- Writing the Validation Report into the plan. +- Returning one Markdown validation result. + +Do not duplicate any of it elsewhere in the workflow. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan under +`context/plans/`. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Confirm implementation is finished + +Set internal status `blocked` with incomplete tasks listed when any +implementation task remains incomplete. + +Final validation measures finished work. Do not run the full suite against a +partial stack, and do not complete remaining tasks here. + +## 1.3 Read the validation contract from the plan + +From the plan, collect: + +- Every acceptance criterion and its `Validate:` check. +- The `Full validation` command list. +- The `Context sync` requirements, for the context-impact handoff only. + +Set internal status `blocked` when the plan has no usable acceptance criteria, or +when no validation commands can be determined from the plan or repository +conventions. + +Prefer the plan's authored checks. Fall back to repository-primary test, lint, +and format commands only when `Full validation` is absent, and record that +fallback under notes on a `validated` or `failed` result. + +## 1.4 Remove temporary scaffolding + +Before or while running checks, remove temporary scaffolding introduced during +the change when it is clearly throwaway: + +- Debug-only patches or flags left enabled. +- Temporary files or intermediate artifacts not part of the delivered design. +- Local scaffolding the plan or task notes mark as temporary. + +Do not delete durable product code, tests, configuration, or context files. + +Record every removed path. When nothing temporary remains, report `None.` + +## 1.5 Run full validation and acceptance checks + +Run the plan's `Full validation` commands. + +Then verify each acceptance criterion using its `Validate:` line. Prefer a +runnable command. Use a named inspection only when the criterion authorizes it, +and say exactly what was inspected. + +When a check fails, record the failure and continue gathering evidence. Do not +modify tests, application code, or configuration to make a check pass. Final +validation measures the finished work; repair belongs to a later work session, +not this skill. + +Never report a check as passed unless it ran successfully or the authorized +inspection confirmed the criterion. + +Do not run task-by-task implementation work for incomplete tasks. That belongs to +`/next-task`. + +## 1.6 Update the plan + +For `validated` and `failed` outcomes: + +- Mark each acceptance criterion checkbox to match the evidence. +- Append or replace the plan's `## Validation Report` section using + `references/validation-report.md`. Read that file before writing the section. +- When status is `failed`, the plan-file report must include the retry command + `/validate {plan path}`. + +Do not reopen completed tasks, rewrite task evidence, or change the task stack. + +For `blocked`, leave the plan file unchanged. + +## 1.7 Determine context impact for the handoff + +On `validated` only, classify the durable context impact of the finished plan so +the **Plan context synchronization phase** can start from the plan's own +requirements: + +- Start from the plan's `Context sync` section. +- Inspect what the completed implementation actually changed when needed. +- Report required context paths and affected areas. +- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level + context sync. + +Do not edit context files here. + +On `failed` or `blocked`, omit context impact; context sync will not run. + +## 1.8 Return the internal state + +Set exactly one internal state: + +- `validated` when every acceptance criterion is met, required full validation + passed, and the Validation Report was written. +- `failed` when evidence was captured but required checks or criteria remain + unsatisfied. Shape it as a session handoff per `references/output.md`, ending + recommended work with `/validate {plan path}`. +- `blocked` when validation cannot proceed safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. +Do not return internal state. + +A `validated` result is the authoritative handoff into step 2, which reads the +plan path, required context paths, validation evidence, and reported context +impact out of it. It must report: + +```markdown +**Status:** validated +**Plan:** {plan path} +``` + +and must carry the resolved plan path, validation commands and outcomes, +acceptance-criteria evidence, scaffolding removals, and the reported context +impact with required context paths and affected areas. Step 2 is forbidden from +reconstructing any of that, so it has to be present here. + +## Validation boundaries + +Do not: + +- Validate more than one plan. +- Complete remaining implementation tasks. +- Modify tests, application code, or configuration to make a failing check pass. +- Apply lint or format auto-fixes that change product or test files as part of + making validation green. +- Synchronize durable context under `context/` outside the plan file. +- Create the context root. +- Mark the plan archived or delete the plan. +- Create a Git commit or push changes. +- Invent acceptance criteria the plan does not state. +- Claim verification that was not performed. +- Return a internal state. +- Run plan context synchronization. The workflow owns that step. diff --git a/.pi/skills/sce-change-to-plan/SKILL.md b/.pi/skills/sce-change-to-plan/SKILL.md index 28c33964..2697e80d 100644 --- a/.pi/skills/sce-change-to-plan/SKILL.md +++ b/.pi/skills/sce-change-to-plan/SKILL.md @@ -14,6 +14,25 @@ not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or workflow command. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/context-load.md` | +| 2 and 4 | `references/plan-authoring.md` | + +`references/plan-template.md` defines the plan file written to disk. The plan +authoring phase points to it at the moment a plan is actually written, which never +happens on a `needs_clarification` or `blocked` result. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at the +bootstrap gate never authors a plan, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -46,87 +65,11 @@ Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is ### 1. Load durable context -Run the **Context load phase** with the change request as the focus. +Read `references/context-load.md`, then run the **Context load phase** with the +change request as the focus. `context/` is durable AI-first memory describing current state. Load it before planning so the plan starts from recorded truth. Where context and code disagree, the code is the source of truth. -#### 1.1 Confirm the context root - -When `context/` does not exist, set internal status `bootstrap_required` immediately. Read -nothing further. - -Bootstrapping is the workflow's decision, not this phase's. - -#### 1.2 Read the entry points - -Read, when present: - -- `context/context-map.md` -- `context/overview.md` -- `context/glossary.md` - -Read `context/architecture.md` when the focus touches structure, boundaries, or -data flow. Read `context/patterns.md` when it touches conventions the change -must follow. - -A missing entry point is a gap, not a failure. Record it and continue. - -#### 1.3 Select the relevant domain context - -Consult `context/context-map.md` before any broad exploration. The map's -annotations name what each domain file owns; use them to select files, rather -than globbing or searching `context/`. - -Select only files whose subject overlaps the focus. Follow at most one level of -links out of a selected file, and only when the link is needed to understand the -focus. - -Do not read every domain file. A brief that includes everything has selected -nothing. - -Record focus areas with no matching context file under `gaps`. - -#### 1.4 Check recorded context against the code - -For each selected file, spot-check its central claims against the code it -describes. - -When context and code diverge, the code is the source of truth. Record the -divergence under `drift` with what context says, what the code shows, and the -repair the context needs. - -Do not repair it here. Later phases decide whether repair belongs in the current -work. - -Keep this proportional: check the claims the focus depends on, not every -sentence. - -#### 1.5 Return the brief - -Set exactly one internal state: - -- `loaded` -- `bootstrap_required` - -Report facts the workflow can act on. A brief that only lists file -paths has moved no knowledge. - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Context load boundaries - -Do not: - -- Create, update, move, or delete any file under `context/`. -- Bootstrap `context/`. -- Repair drift or stale context. -- Modify application code or tests. -- Read the entire `context/` tree by default. -- Explore the repository beyond what the focus and the selected context require. -- Ask the user questions. Report gaps and drift, and let the workflow decide. -- Author a plan, select a task, or implement anything. - Branch on `status`: `bootstrap_required` -> `context/` does not exist. Do not create it, and do not plan without it. Render the **Missing context bootstrap gate** layout from `references/output.md`. @@ -139,256 +82,18 @@ Do not read `context/` yourself. Do not repair drift or stale context; the brief ### 2. Author the plan -Run the **Plan authoring phase** with the change request and the complete `loaded` brief from the **Context load phase**. +Read `references/plan-authoring.md`, then run the **Plan authoring phase** with +the change request and the complete `loaded` brief from the **Context load +phase**. Pass the brief verbatim. Do not restate, summarize, or reinterpret it. -The **Plan authoring phase** exclusively owns: - -- Resolving whether the request targets a new or an existing plan. -- The clarification gate. -- Normalizing the change summary, acceptance criteria, constraints, and non-goals. -- Slicing the task stack into one-task/one-atomic-commit units. -- Writing `context/plans/{plan_name}.md`. - -Do not duplicate any of it. Do not write or edit the plan file yourself. - -Use the document format defined in the **Plan template** section embedded in this file. - -The workflow renders that result as the summary defined in: - -`references/output.md` - -The change request may name a plan, describe a change to an existing plan, or -describe entirely new work. Resolving which applies is this phase's -responsibility. - -The context brief is the durable memory this plan starts from. Treat its -`key_facts` as recorded current state, its `gaps` as areas with no durable -context, and its `drift` as context the code has already outrun. - -When no brief is supplied, load the context named by the change request before -authoring, and follow the selection discipline in *Inspect relevant context*. - -Answers the user gave to earlier clarification questions arrive as part of the -change request. Incorporate them into the plan. - -A revision of a plan authored earlier in the session also arrives as the change -request, and it is usually terse: a task boundary the user disagrees with, an -ordering they want changed, work they want added or dropped. Read it against the -existing plan, which supplies the scope, criteria, and terminology it omits. -Terseness is not ambiguity. Do not set internal status `needs_clarification` for detail the -plan already carries; ask only when the revision itself is genuinely undecidable. - -#### 2.1 Resolve the plan target - -Determine whether the request targets a new plan or an existing plan in -`context/plans/`. - -When it targets an existing plan, read that plan before authoring. Preserve its -completed tasks, their recorded evidence, its structure, and its terminology. - -When multiple existing plans match and none can be selected safely, return -`blocked` with the matching candidates. - -When the request targets a new plan, derive `plan_name` as a short kebab-case -slug of the change, and confirm it does not collide with an existing plan. - -Resolve exactly one plan target per invocation. - -#### 2.2 Challenge the change - -Before planning how to build the change, work out whether it is worth building. -A plan is a commitment of someone's time; authoring one for work that should not -happen is worse than authoring none. - -Interrogate the request: - -- What breaks, or stays broken, if this is never built? If the answer is - nothing concrete, say so. -- What problem is it actually solving, as opposed to what it proposes to do? A - request that names only a solution has not stated a problem. -- Does the repository already do this, or most of it? The brief's `key_facts` - are the first place to check. -- Is there a materially smaller version that gets most of the value? Name it. -- What does this cost beyond the tasks: new dependency, new concept in the - glossary, a boundary crossed, a surface that now needs maintaining forever? -- Does the stated justification survive contact with the code, or does the code - show the premise is already false? - -Doubt that survives this is not an implementation detail to be tidied away. It -belongs in the plan's `Open questions` and in `open_questions`, in the plain -words you would use to a colleague. "Is this worth doing at all, given X?" is a -legitimate open question. So is "this looks like it duplicates Y". - -Weigh honestly in both directions. A request that is obviously worth building -gets no manufactured doubt: inventing questions to look rigorous is its own -failure, and it teaches the user to ignore the section. Most changes are fine. -Say nothing when there is nothing to say. - -Keep going regardless. Skepticism shapes the plan and the open questions; it -does not withhold the plan. The only value judgment that stops authoring is -`no_actionable_work`, when the change is already implemented. - -#### 2.3 Run the clarification gate - -Before writing or updating any plan file, check the request for critical -unresolved detail: - -- Scope boundaries and out-of-scope items. -- Acceptance criteria and the checks that prove them. -- Constraints and non-goals. -- Dependency choices, including new libraries or services, versions, and the - integration approach. -- Domain ambiguity, including unclear business rules, terminology, or ownership. -- Architecture concerns, including patterns, interfaces, data flow, migration - strategy, and risk tradeoffs. -- Task ordering assumptions and prerequisite sequencing. - -Set internal status `needs_clarification` with one to three targeted questions when any of -these would materially change the plan. Write no plan file in that case. - -Use repository conventions for ordinary local choices. Do not block on: +This phase challenges whether the change is worth building before planning how to +build it, and it decides on its own whether to stop at the clarification gate. +Both shape what reaches the user, so reach them through the reference rather than +acting from this summary. -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change scope, acceptance criteria, or task ordering. - -Record those choices under `assumptions`. - -Do not silently invent missing requirements. When the user has explicitly -allowed assumptions, record them in the plan's `Assumptions` section instead of -asking. - -A justification that does not survive inspection is itself a critical unresolved -detail. "For consistency", "to make it cleaner", "we will need it later" name no -outcome and prove nothing; ask what the change is actually for before planning -around it. Do not treat confident phrasing as evidence. - -#### 2.4 Inspect relevant context - -Start from the context brief. Read code only where the brief leaves the change -underspecified: - -- Existing behavior the change affects. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests and available verification commands. -- Decisions or specifications connected to the change. - -Where the brief reports `drift`, the code is the source of truth. Plan against -the code, and schedule the context repair as part of the change when it falls -inside scope. - -Where the brief reports `gaps`, the plan may need to establish durable context -the repository does not yet have. - -Do not explore the entire repository by default. - -#### 2.5 Author the acceptance criteria - -State how the finished plan is proven, before slicing tasks. - -Each criterion describes observable behavior of the finished system and names -the check that proves it. Record repository-wide checks once under -`Full validation`, and the durable context the change must be reflected in -under `Context sync`. - -`/validate` runs this section after the last task completes. It is the only -place a plan says how it is validated. - -#### 2.6 Author the task stack - -Slice the work into sequential tasks `T01..T0N` using the task format and the -atomic slicing contract in the **Plan template** section embedded in this file. - -Every executable task must be completable and landable as one coherent commit. -Split any task that would require multiple independent commits. Convert broad -wrappers such as `polish` or `finalize` into specific outcomes with concrete -acceptance checks. - -Order tasks so each one's declared dependencies precede it. - -The last task is an ordinary implementation task. Do not author a trailing -validation-and-cleanup task, or any task whose only purpose is running the full -check suite, verifying durable context, or removing scaffolding. - -Confirm every acceptance criterion is satisfied by at least one task. When one -is not, the task stack is incomplete. - -A finished stack always leaves at least one incomplete task, so the workflow -can always hand off to `/next-task`. When the request resolves to a -plan but produces no incomplete task, because the change is already implemented -or already covered by completed tasks, set internal status `blocked` with category -`no_actionable_work` instead of writing the plan. - -#### 2.7 Write the plan - -Write `context/plans/{plan_name}.md` using the **Plan template** section embedded in this file. - -When updating an existing plan, keep completed tasks and their evidence intact, -and append or renumber new tasks without disturbing recorded history. - -#### 2.8 Return the result - -Set exactly one internal state: - -- `plan_ready` -- `needs_clarification` -- `blocked` - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Plan authoring tone - -Every question and open question this phase writes is read by the user. Write -them the way a senior engineer talks in review: direct, specific, and unbothered -by the possibility of being unwelcome. - -- Ask about the thing that actually worries you, not a safer neighbouring thing. - A question you would not bother asking a colleague is not worth the user's - attention either. -- State a doubt as a doubt. "I do not think this is worth the two tasks it - costs, because X" is useful. "It may be worth considering whether this aligns - with broader goals" is noise. -- Name the alternative you have in mind. A challenge with no proposal behind it - is just friction. -- Do not open with praise, do not close with reassurance, and do not apologize - for asking. Do not pad a doubt with hedges to make it land more gently. -- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not - restate the same doubt in three shapes to give it more weight. -- Being disagreeable is not the goal. Being easy to agree with is the failure - mode. A plan the user waves through without reading has cost them nothing and - bought them nothing. - -When the user overrules a doubt, record it and move on. Do not relitigate a -decision the user has made, and do not smuggle the objection back in as a -constraint, a non-goal, or a task. - -### Plan authoring boundaries - -Do not: - -- Ask the user questions directly. Set internal status `needs_clarification` and let the - workflow present the questions. -- Answer your own clarification questions. -- Write a plan file when returning `needs_clarification` or `blocked`. -- Implement any task in the plan. -- Modify application code or tests. -- Modify any file under `context/` outside `context/plans/`. Plan the context - repair instead of performing it. -- Mark any task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Author a validation, cleanup, or context-verification task. `/validate` owns - that phase. -- Set internal status `plan_ready` for a plan with no incomplete task. -- Create a Git commit. -- Author more than one plan. +Do not write or edit the plan file yourself. Branch on `status`: @@ -441,6 +146,7 @@ Stop. ## Rules - Plan at most one change request per invocation. Revisions to the plan that request produced are part of the same invocation, not a second request. +- Read each phase's reference before running that phase. - Always tell the user the plan can be revised, and always name its assumptions as the first thing worth checking. - Do not gate the handoff on open questions listed in the plan summary. Blocking questions return `needs_clarification` before any plan is written. Offering revision is not the same as demanding it, and inventing doubts to justify a review gate is not allowed. - Do not suppress, soften, or answer an open question or clarification question on the user's behalf. @@ -457,174 +163,3 @@ Stop. - Do not answer the skill's clarification questions on the user's behalf. - Do not execute the continuation returned at the end. - Do not infer success when the **Plan authoring phase** returns a non-`plan_ready` status. - -## Internal persisted-document format: Plan template - -The document format for `context/plans/{plan_name}.md`. This is the plan file -written to disk, not the result returned to the workflow. - -Copy the template below and fill every `{placeholder}`. Omit optional sections -entirely rather than writing them empty. - ---- - -### Template - -```markdown -# Plan: {plan-name} - -## Change summary - -{One or two paragraphs: what changes, where, and why. State whether this -extends existing behavior, replaces it, or preserves work already in progress.} - -## Acceptance criteria - -How this plan is proven complete. Each criterion is observable and names the -check that proves it. `/validate` runs these checks; no task in the stack -performs final validation. - -- [ ] AC1: {observable outcome, stated as behavior rather than as work done} - - Validate: `{command, assertion, or inspection that proves AC1}` -- [ ] AC2: {observable outcome} - - Validate: `{command, assertion, or inspection that proves AC2}` - -### Full validation - -Repository-wide checks `/validate` runs after the last task, regardless of -which criterion they map to. - -- `{full check suite command}` -- `{generated-output or parity check command, when applicable}` - -### Context sync - -- {Durable context files that must describe the change once implemented.} - -## Constraints and non-goals - -- **In scope:** {files, modules, and surfaces this plan may touch} -- **Out of scope:** {adjacent work explicitly excluded} -- **Constraints:** {dependencies, conventions, compatibility, or policy limits} -- **Non-goal:** {tempting generalization this plan deliberately avoids} - -## Assumptions - -{Include only when the user allowed assumptions, or ordinary local choices were -recorded. Remove the section otherwise.} - -- {Assumption, and the convention or decision record it rests on.} - -## Task stack - -- [ ] T01: `{single intent title}` (status:todo) - - Task ID: T01 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: {task IDs, or none} - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -- [ ] T02: `{single intent title}` (status:todo) - - Task ID: T02 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: T01 - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -## Open questions - -{Non-blocking questions only. A question that would change scope, success -criteria, or task ordering blocks authoring instead. Write `None.` with a short -justification when nothing remains.} - -{Unresolved doubt about the change's value belongs here — whether it is worth -building, whether it duplicates behavior the repository already has, whether a -smaller version would do. State it plainly and name the alternative. Do not -invent one: `None.` is the expected answer for a well-specified change.} -``` - ---- - -### Filled-in task example - -```markdown -- [ ] T02: `Add /auth/refresh endpoint` (status:todo) - - Task ID: T02 - - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. - - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. - - Dependencies: T01 - - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. - - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. -``` - -### Acceptance criteria rules - -- Acceptance criteria describe the finished system, not the work. Prefer "the - endpoint returns 401 on an expired token" over "add expiry handling". -- Every criterion carries a `Validate:` line. A criterion nobody can check is - not an acceptance criterion. -- Prefer a runnable command. Fall back to a named inspection only when no - automated check exists, and say exactly what to look at. -- List repository-wide checks once under `Full validation` instead of repeating - them per criterion. -- Task-level `Verification notes` prove one task. Acceptance criteria prove the - plan. Keep them distinct: a task's checks are narrow and local, a criterion's - check is end-to-end. -- The union of the acceptance criteria must cover every success signal in the - change request. If a criterion has no task that could satisfy it, the task - stack is incomplete. - -### Task rules - -- Every task is a checkbox line so progress stays machine-readable: - `- [ ] T01: {title} (status:todo)`. -- Author each executable task as one atomic commit unit by default. -- Scope every task so one contributor can complete it and land it as one - coherent commit without bundling unrelated changes. -- Split any candidate task that would require multiple independent commits, for - example a refactor plus a behavior change plus documentation. -- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of - executable tasks. Convert them into specific outcomes with concrete - acceptance checks. -- Order tasks so each one's declared dependencies precede it. - -### No validation task - -- The last task in the stack is an ordinary implementation task. Do not author a - trailing "validation and cleanup" task. -- Final validation, cleanup, and success-criteria verification are run by - `/validate` from the `Acceptance criteria` section after the last task - completes. -- Do not author a task whose only purpose is running the full check suite, - verifying durable context, or removing scaffolding. -- A task may still create or update durable context when that context is part of - the change itself. - -### Completion records - -When a task completes, the **Task execution phase** appends its evidence and flips the -checkbox and status: - -```markdown -- [x] T01: `{title}` (status:done) - - {authored fields, unchanged} - - Completed: {YYYY-MM-DD} - - Files changed: {paths} - - Evidence: {commands run and their outcomes} - - Notes: {material deviations or approved assumptions} -``` - -`/validate` appends a `## Validation Report` section at the end of the plan. -Do not author either while planning. - -### Updating an existing plan - -- Preserve completed tasks, their `(status:done)` markers, and their recorded - evidence verbatim. -- Preserve the plan's existing structure and terminology. -- Append new tasks after the existing stack. Renumber only when added work must - run earlier, and never renumber a completed task. -- Add acceptance criteria for newly planned outcomes rather than rewriting - criteria already satisfied. diff --git a/.pi/skills/sce-change-to-plan/references/context-load.md b/.pi/skills/sce-change-to-plan/references/context-load.md new file mode 100644 index 00000000..197a28c2 --- /dev/null +++ b/.pi/skills/sce-change-to-plan/references/context-load.md @@ -0,0 +1,89 @@ +# Context load phase + +Run this phase for step 1 of the workflow, with the change request as the focus. + +`context/` is durable AI-first memory describing current state. Load it before +planning so the plan starts from recorded truth. Where context and code disagree, +the code is the source of truth. + +This phase reads and reports; it never writes. + +## 1.1 Confirm the context root + +When `context/` does not exist, set internal status `bootstrap_required` +immediately. Read nothing further. + +Bootstrapping is the workflow's decision, not this phase's. + +## 1.2 Read the entry points + +Read, when present: + +- `context/context-map.md` +- `context/overview.md` +- `context/glossary.md` + +Read `context/architecture.md` when the focus touches structure, boundaries, or +data flow. Read `context/patterns.md` when it touches conventions the change must +follow. + +A missing entry point is a gap, not a failure. Record it and continue. + +## 1.3 Select the relevant domain context + +Consult `context/context-map.md` before any broad exploration. The map's +annotations name what each domain file owns; use them to select files, rather +than globbing or searching `context/`. + +Select only files whose subject overlaps the focus. Follow at most one level of +links out of a selected file, and only when the link is needed to understand the +focus. + +Do not read every domain file. A brief that includes everything has selected +nothing. + +Record focus areas with no matching context file under `gaps`. + +## 1.4 Check recorded context against the code + +For each selected file, spot-check its central claims against the code it +describes. + +When context and code diverge, the code is the source of truth. Record the +divergence under `drift` with what context says, what the code shows, and the +repair the context needs. + +Do not repair it here. Later phases decide whether repair belongs in the current +work. + +Keep this proportional: check the claims the focus depends on, not every +sentence. + +## 1.5 Return the brief + +Set exactly one internal state: + +- `loaded` +- `bootstrap_required` + +Report facts the workflow can act on. A brief that only lists file paths has +moved no knowledge. + +Record only the internal state. Do not add explanatory prose before or after it. + +Step 2 consumes a `loaded` brief verbatim and treats its `key_facts` as recorded +current state, its `gaps` as areas with no durable context, and its `drift` as +context the code has already outrun. + +## Context load boundaries + +Do not: + +- Create, update, move, or delete any file under `context/`. +- Bootstrap `context/`. +- Repair drift or stale context. +- Modify application code or tests. +- Read the entire `context/` tree by default. +- Explore the repository beyond what the focus and the selected context require. +- Ask the user questions. Report gaps and drift, and let the workflow decide. +- Author a plan, select a task, or implement anything. diff --git a/.pi/skills/sce-change-to-plan/references/plan-authoring.md b/.pi/skills/sce-change-to-plan/references/plan-authoring.md new file mode 100644 index 00000000..17e054e2 --- /dev/null +++ b/.pi/skills/sce-change-to-plan/references/plan-authoring.md @@ -0,0 +1,256 @@ +# Plan authoring phase + +Run this phase for step 2 of the workflow, and again for each revision in step 4. + +Input: the change request, and the complete `loaded` brief from the context load +phase. Pass the brief verbatim; do not restate, summarize, or reinterpret it. + +This phase exclusively owns: + +- Resolving whether the request targets a new or an existing plan. +- The clarification gate. +- Normalizing the change summary, acceptance criteria, constraints, and non-goals. +- Slicing the task stack into one-task/one-atomic-commit units. +- Writing `context/plans/{plan_name}.md`. + +Do not duplicate any of it elsewhere in the workflow. + +Use the document format in `references/plan-template.md`. Read it before writing +the plan file. + +The workflow renders this phase's result as the summary defined in +`references/output.md`. + +The change request may name a plan, describe a change to an existing plan, or +describe entirely new work. Resolving which applies is this phase's +responsibility. + +The context brief is the durable memory this plan starts from. Treat its +`key_facts` as recorded current state, its `gaps` as areas with no durable +context, and its `drift` as context the code has already outrun. + +When no brief is supplied, load the context named by the change request before +authoring, and follow the selection discipline in *Inspect relevant context*. + +Answers the user gave to earlier clarification questions arrive as part of the +change request. Incorporate them into the plan. + +A revision of a plan authored earlier in the session also arrives as the change +request, and it is usually terse: a task boundary the user disagrees with, an +ordering they want changed, work they want added or dropped. Read it against the +existing plan, which supplies the scope, criteria, and terminology it omits. +Terseness is not ambiguity. Do not set internal status `needs_clarification` for +detail the plan already carries; ask only when the revision itself is genuinely +undecidable. + +## 2.1 Resolve the plan target + +Determine whether the request targets a new plan or an existing plan in +`context/plans/`. + +When it targets an existing plan, read that plan before authoring. Preserve its +completed tasks, their recorded evidence, its structure, and its terminology. + +When multiple existing plans match and none can be selected safely, return +`blocked` with the matching candidates. + +When the request targets a new plan, derive `plan_name` as a short kebab-case +slug of the change, and confirm it does not collide with an existing plan. + +Resolve exactly one plan target per invocation. + +## 2.2 Challenge the change + +Before planning how to build the change, work out whether it is worth building. A +plan is a commitment of someone's time; authoring one for work that should not +happen is worse than authoring none. + +Interrogate the request: + +- What breaks, or stays broken, if this is never built? If the answer is nothing + concrete, say so. +- What problem is it actually solving, as opposed to what it proposes to do? A + request that names only a solution has not stated a problem. +- Does the repository already do this, or most of it? The brief's `key_facts` are + the first place to check. +- Is there a materially smaller version that gets most of the value? Name it. +- What does this cost beyond the tasks: new dependency, new concept in the + glossary, a boundary crossed, a surface that now needs maintaining forever? +- Does the stated justification survive contact with the code, or does the code + show the premise is already false? + +Doubt that survives this is not an implementation detail to be tidied away. It +belongs in the plan's `Open questions` and in `open_questions`, in the plain +words you would use to a colleague. "Is this worth doing at all, given X?" is a +legitimate open question. So is "this looks like it duplicates Y". + +Weigh honestly in both directions. A request that is obviously worth building +gets no manufactured doubt: inventing questions to look rigorous is its own +failure, and it teaches the user to ignore the section. Most changes are fine. +Say nothing when there is nothing to say. + +Keep going regardless. Skepticism shapes the plan and the open questions; it does +not withhold the plan. The only value judgment that stops authoring is +`no_actionable_work`, when the change is already implemented. + +## 2.3 Run the clarification gate + +Before writing or updating any plan file, check the request for critical +unresolved detail: + +- Scope boundaries and out-of-scope items. +- Acceptance criteria and the checks that prove them. +- Constraints and non-goals. +- Dependency choices, including new libraries or services, versions, and the + integration approach. +- Domain ambiguity, including unclear business rules, terminology, or ownership. +- Architecture concerns, including patterns, interfaces, data flow, migration + strategy, and risk tradeoffs. +- Task ordering assumptions and prerequisite sequencing. + +Set internal status `needs_clarification` with one to three targeted questions +when any of these would materially change the plan. Write no plan file in that +case. + +Use repository conventions for ordinary local choices. Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change scope, acceptance criteria, or task ordering. + +Record those choices under `assumptions`. + +Do not silently invent missing requirements. When the user has explicitly allowed +assumptions, record them in the plan's `Assumptions` section instead of asking. + +A justification that does not survive inspection is itself a critical unresolved +detail. "For consistency", "to make it cleaner", "we will need it later" name no +outcome and prove nothing; ask what the change is actually for before planning +around it. Do not treat confident phrasing as evidence. + +## 2.4 Inspect relevant context + +Start from the context brief. Read code only where the brief leaves the change +underspecified: + +- Existing behavior the change affects. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests and available verification commands. +- Decisions or specifications connected to the change. + +Where the brief reports `drift`, the code is the source of truth. Plan against +the code, and schedule the context repair as part of the change when it falls +inside scope. + +Where the brief reports `gaps`, the plan may need to establish durable context +the repository does not yet have. + +Do not explore the entire repository by default. + +## 2.5 Author the acceptance criteria + +State how the finished plan is proven, before slicing tasks. + +Each criterion describes observable behavior of the finished system and names the +check that proves it. Record repository-wide checks once under `Full validation`, +and the durable context the change must be reflected in under `Context sync`. + +`/validate` runs this section after the last task completes. It is the only place +a plan says how it is validated. + +## 2.6 Author the task stack + +Slice the work into sequential tasks `T01..T0N` using the task format and the +atomic slicing contract in `references/plan-template.md`. + +Every executable task must be completable and landable as one coherent commit. +Split any task that would require multiple independent commits. Convert broad +wrappers such as `polish` or `finalize` into specific outcomes with concrete +acceptance checks. + +Order tasks so each one's declared dependencies precede it. + +The last task is an ordinary implementation task. Do not author a trailing +validation-and-cleanup task, or any task whose only purpose is running the full +check suite, verifying durable context, or removing scaffolding. + +Confirm every acceptance criterion is satisfied by at least one task. When one is +not, the task stack is incomplete. + +A finished stack always leaves at least one incomplete task, so the workflow can +always hand off to `/next-task`. When the request resolves to a plan but produces +no incomplete task, because the change is already implemented or already covered +by completed tasks, set internal status `blocked` with category +`no_actionable_work` instead of writing the plan. + +## 2.7 Write the plan + +Write `context/plans/{plan_name}.md` using `references/plan-template.md`. + +When updating an existing plan, keep completed tasks and their evidence intact, +and append or renumber new tasks without disturbing recorded history. + +## 2.8 Return the result + +Set exactly one internal state: + +- `plan_ready` +- `needs_clarification` +- `blocked` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `plan_ready` result always names the next task in `next_task`, and carries the +`total_tasks` count and any open questions the summary needs. Step 3 renders those +without recomputing them. + +## Plan authoring tone + +Every question and open question this phase writes is read by the user. Write +them the way a senior engineer talks in review: direct, specific, and unbothered +by the possibility of being unwelcome. + +- Ask about the thing that actually worries you, not a safer neighbouring thing. + A question you would not bother asking a colleague is not worth the user's + attention either. +- State a doubt as a doubt. "I do not think this is worth the two tasks it + costs, because X" is useful. "It may be worth considering whether this aligns + with broader goals" is noise. +- Name the alternative you have in mind. A challenge with no proposal behind it + is just friction. +- Do not open with praise, do not close with reassurance, and do not apologize + for asking. Do not pad a doubt with hedges to make it land more gently. +- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not + restate the same doubt in three shapes to give it more weight. +- Being disagreeable is not the goal. Being easy to agree with is the failure + mode. A plan the user waves through without reading has cost them nothing and + bought them nothing. + +When the user overrules a doubt, record it and move on. Do not relitigate a +decision the user has made, and do not smuggle the objection back in as a +constraint, a non-goal, or a task. + +## Plan authoring boundaries + +Do not: + +- Ask the user questions directly. Set internal status `needs_clarification` and let the + workflow present the questions. +- Answer your own clarification questions. +- Write a plan file when returning `needs_clarification` or `blocked`. +- Implement any task in the plan. +- Modify application code or tests. +- Modify any file under `context/` outside `context/plans/`. Plan the context + repair instead of performing it. +- Mark any task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Author a validation, cleanup, or context-verification task. `/validate` owns + that phase. +- Set internal status `plan_ready` for a plan with no incomplete task. +- Create a Git commit. +- Author more than one plan. diff --git a/.pi/skills/sce-change-to-plan/references/plan-template.md b/.pi/skills/sce-change-to-plan/references/plan-template.md new file mode 100644 index 00000000..ac36a72c --- /dev/null +++ b/.pi/skills/sce-change-to-plan/references/plan-template.md @@ -0,0 +1,170 @@ +# Internal persisted-document format: Plan template + +The document format for `context/plans/{plan_name}.md`. This is the plan file +written to disk, not the result returned to the workflow. + +Copy the template below and fill every `{placeholder}`. Omit optional sections +entirely rather than writing them empty. + +--- + +## Template + +```markdown +# Plan: {plan-name} + +## Change summary + +{One or two paragraphs: what changes, where, and why. State whether this +extends existing behavior, replaces it, or preserves work already in progress.} + +## Acceptance criteria + +How this plan is proven complete. Each criterion is observable and names the +check that proves it. `/validate` runs these checks; no task in the stack +performs final validation. + +- [ ] AC1: {observable outcome, stated as behavior rather than as work done} + - Validate: `{command, assertion, or inspection that proves AC1}` +- [ ] AC2: {observable outcome} + - Validate: `{command, assertion, or inspection that proves AC2}` + +### Full validation + +Repository-wide checks `/validate` runs after the last task, regardless of +which criterion they map to. + +- `{full check suite command}` +- `{generated-output or parity check command, when applicable}` + +### Context sync + +- {Durable context files that must describe the change once implemented.} + +## Constraints and non-goals + +- **In scope:** {files, modules, and surfaces this plan may touch} +- **Out of scope:** {adjacent work explicitly excluded} +- **Constraints:** {dependencies, conventions, compatibility, or policy limits} +- **Non-goal:** {tempting generalization this plan deliberately avoids} + +## Assumptions + +{Include only when the user allowed assumptions, or ordinary local choices were +recorded. Remove the section otherwise.} + +- {Assumption, and the convention or decision record it rests on.} + +## Task stack + +- [ ] T01: `{single intent title}` (status:todo) + - Task ID: T01 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: {task IDs, or none} + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +- [ ] T02: `{single intent title}` (status:todo) + - Task ID: T02 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: T01 + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +## Open questions + +{Non-blocking questions only. A question that would change scope, success +criteria, or task ordering blocks authoring instead. Write `None.` with a short +justification when nothing remains.} + +{Unresolved doubt about the change's value belongs here — whether it is worth +building, whether it duplicates behavior the repository already has, whether a +smaller version would do. State it plainly and name the alternative. Do not +invent one: `None.` is the expected answer for a well-specified change.} +``` + +--- + +## Filled-in task example + +```markdown +- [ ] T02: `Add /auth/refresh endpoint` (status:todo) + - Task ID: T02 + - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. + - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. + - Dependencies: T01 + - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. + - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. +``` + +## Acceptance criteria rules + +- Acceptance criteria describe the finished system, not the work. Prefer "the + endpoint returns 401 on an expired token" over "add expiry handling". +- Every criterion carries a `Validate:` line. A criterion nobody can check is + not an acceptance criterion. +- Prefer a runnable command. Fall back to a named inspection only when no + automated check exists, and say exactly what to look at. +- List repository-wide checks once under `Full validation` instead of repeating + them per criterion. +- Task-level `Verification notes` prove one task. Acceptance criteria prove the + plan. Keep them distinct: a task's checks are narrow and local, a criterion's + check is end-to-end. +- The union of the acceptance criteria must cover every success signal in the + change request. If a criterion has no task that could satisfy it, the task + stack is incomplete. + +## Task rules + +- Every task is a checkbox line so progress stays machine-readable: + `- [ ] T01: {title} (status:todo)`. +- Author each executable task as one atomic commit unit by default. +- Scope every task so one contributor can complete it and land it as one + coherent commit without bundling unrelated changes. +- Split any candidate task that would require multiple independent commits, for + example a refactor plus a behavior change plus documentation. +- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of + executable tasks. Convert them into specific outcomes with concrete + acceptance checks. +- Order tasks so each one's declared dependencies precede it. + +## No validation task + +- The last task in the stack is an ordinary implementation task. Do not author a + trailing "validation and cleanup" task. +- Final validation, cleanup, and success-criteria verification are run by + `/validate` from the `Acceptance criteria` section after the last task + completes. +- Do not author a task whose only purpose is running the full check suite, + verifying durable context, or removing scaffolding. +- A task may still create or update durable context when that context is part of + the change itself. + +## Completion records + +When a task completes, the **Task execution phase** appends its evidence and flips the +checkbox and status: + +```markdown +- [x] T01: `{title}` (status:done) + - {authored fields, unchanged} + - Completed: {YYYY-MM-DD} + - Files changed: {paths} + - Evidence: {commands run and their outcomes} + - Notes: {material deviations or approved assumptions} +``` + +`/validate` appends a `## Validation Report` section at the end of the plan. +Do not author either while planning. + +## Updating an existing plan + +- Preserve completed tasks, their `(status:done)` markers, and their recorded + evidence verbatim. +- Preserve the plan's existing structure and terminology. +- Append new tasks after the existing stack. Renumber only when added work must + run earlier, and never renumber a completed task. +- Add acceptance criteria for newly planned outcomes rather than rewriting + criteria already satisfied. diff --git a/.pi/skills/sce-commit/SKILL.md b/.pi/skills/sce-commit/SKILL.md index ea7209bf..1eeecb78 100644 --- a/.pi/skills/sce-commit/SKILL.md +++ b/.pi/skills/sce-commit/SKILL.md @@ -14,6 +14,17 @@ not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or workflow command. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase reference + +Both paths below dispatch to the same phase, whose steps and boundaries live in +`references/atomic-commit.md`. This document holds the control flow — which path +runs, what the phase receives, and how its result branches — and the reference +holds the phase itself. + +Read `references/atomic-commit.md` before running the phase, not after. A regular +run that stops at the staging gate, and a bypass run that finds nothing staged, +both end without ever needing it. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -70,130 +81,10 @@ not skip this prompt because the working tree looks ready. #### 2. Propose commits -After confirmation, run the **Atomic commit phase** with `mode: regular` and the -commit context. - -The **Atomic commit phase** exclusively owns: - -- Reading and analyzing the staged diff. -- Deciding whether staged changes form one coherent unit or several. -- Classifying staged scope and applying context-file guidance gating. -- Writing every commit message subject and body. -- Applying the plan-citation body rule. - -Do not duplicate any of it. Do not write commit messages yourself. - -The mode is supplied by the workflow from an explicit user-supplied token. -Never infer it, and never switch modes mid-analysis. - -Commit context refines wording only. The staged diff decides what the change -is; context never overrides staged truth, and never adds a claim the diff does -not support. - -Do not accept an unstaged diff, a working-tree summary, or a conversational -description as a substitute for the staged diff. - -##### 2.1 Read the staged diff - -Read the staged changes with `git diff --cached`, and the staged file list with -`git diff --cached --name-status`. - -Read staged file contents only when the diff alone does not explain the change. - -Set internal status `blocked` when nothing is staged. - -##### 2.2 Identify coherent units - -Infer the main reason for the staged change from the diff first. - -A coherent unit is one goal a reviewer would accept as a single commit. Group -staged files by that goal, not by directory. - -In `bypass` mode, stop grouping here: the result is exactly one message -covering all staged files, whether or not the diff is coherent. Do not propose -splits, and do not report split guidance. - -##### 2.3 Choose a scope for each unit - -Use the smallest stable subsystem or module name recognizable in the repository. - -When no such name applies, use the primary directory or package of the unit's -changes. - -##### 2.4 Write each message - -Follow `references/output.md` for the subject pattern, the body -rules, issue references, the plan-citation rule, and the anti-patterns. - -##### 2.5 Apply the plan-citation rule - -When the unit's staged files include `context/plans/*.md`, cite the affected -plan slug and updated task IDs in the body. - -When the staged plan diff does not expose the slug or task ID clearly enough to -cite faithfully: - -- In `regular` mode, set internal status `blocked` and ask for the reference to be stated or - staged explicitly. -- In `bypass` mode, infer the citation when the diff supports it, and otherwise - omit it. Never stop, and never invent a slug or task ID. - -##### 2.6 Apply context-file guidance gating - -This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do -not classify staged scope there. - -Classify the staged diff: - -- Context-only (`context/**`): context-file-focused guidance is allowed. -- Mixed (`context/**` plus non-`context/**`): suppress default context-file - commit reminders and give guidance that reflects the full staged scope. - -##### 2.7 Propose split guidance - -This step applies in `regular` mode only. - -When the units found in step 2 pursue unrelated goals, return one message per -unit, and state why the split is recommended and which staged files belong to -each. - -When the staged changes form one unit, return one message and no split -guidance. Do not split coherent work to appear thorough. - -##### 2.8 Validate the result - -Confirm before returning that: - -- Every message describes its unit faithfully and covers only that unit's files. -- Every staged file belongs to exactly one returned message. -- No plan slug or task ID appears that the staged diff does not support. -- The mode's own constraints hold. - -##### 2.9 Return internal state - -Set exactly one internal state: - -- `proposal` in `regular` mode, with one or more messages. -- `bypass_message` in `bypass` mode, with exactly one message. -- `blocked` when messages cannot be written faithfully. - -Record only the internal state. Do not add explanatory prose before or after it. - -#### Atomic commit boundaries - -Do not: +After confirmation, read `references/atomic-commit.md`, then run the **Atomic +commit phase** with `mode: regular` and the commit context. -- Run `git commit`, or any command that writes to the repository or its index. -- Stage, unstage, or modify files. -- Ask the user to stage or confirm staging. -- Analyze unstaged or untracked changes. -- Return more than one message in `bypass` mode. -- Return split guidance in `bypass` mode. -- Stop for plan-citation ambiguity in `bypass` mode. -- Invent plan slugs, task IDs, or issue references. -- Mention `context/` synchronization activity in a commit message. -- Claim a message was committed. -- Run plan, task, or validation workflows. +Do not write commit messages yourself. Branch on `status`: @@ -221,7 +112,8 @@ Do not stage anything. Do not proceed to the skill. #### 2. Request one commit message -Run the **Atomic commit phase** (described at the Regular path's step 2 above) with `mode: bypass` and the commit context. +Read `references/atomic-commit.md`, then run the **Atomic commit phase** with +`mode: bypass` and the commit context. Bypass mode is the skill's contract for producing exactly one message. Do not restate its overrides here; the **Atomic commit phase** owns them. @@ -253,6 +145,7 @@ fallback commit. - Never commit on the regular path. - Recognize `oneshot` and `skip` only as an exact case-insensitive first token. They are behaviorally identical. +- Read `references/atomic-commit.md` before running the phase. - Do not duplicate the internal instructions of the **Atomic commit phase**. - Do not stage, unstage, restore, or otherwise modify files. - Do not amend, reset, revert, rebase, or push. diff --git a/.pi/skills/sce-commit/references/atomic-commit.md b/.pi/skills/sce-commit/references/atomic-commit.md new file mode 100644 index 00000000..ecdeb3bd --- /dev/null +++ b/.pi/skills/sce-commit/references/atomic-commit.md @@ -0,0 +1,130 @@ +# Atomic commit phase + +Both workflow paths run this phase. The regular path runs it with `mode: regular` +after the staging gate; the bypass path runs it with `mode: bypass` after +confirming staged content exists. + +Input: the mode, supplied by the workflow from an explicit user-supplied token, +and the commit context. + +This phase exclusively owns: + +- Reading and analyzing the staged diff. +- Deciding whether staged changes form one coherent unit or several. +- Classifying staged scope and applying context-file guidance gating. +- Writing every commit message subject and body. +- Applying the plan-citation body rule. + +Do not duplicate any of it elsewhere in the workflow. Do not write commit messages +outside this phase. + +Never infer the mode, and never switch modes mid-analysis. + +Commit context refines wording only. The staged diff decides what the change is; +context never overrides staged truth, and never adds a claim the diff does not +support. + +Do not accept an unstaged diff, a working-tree summary, or a conversational +description as a substitute for the staged diff. + +## 1. Read the staged diff + +Read the staged changes with `git diff --cached`, and the staged file list with +`git diff --cached --name-status`. + +Read staged file contents only when the diff alone does not explain the change. + +Set internal status `blocked` when nothing is staged. + +## 2. Identify coherent units + +Infer the main reason for the staged change from the diff first. + +A coherent unit is one goal a reviewer would accept as a single commit. Group +staged files by that goal, not by directory. + +In `bypass` mode, stop grouping here: the result is exactly one message covering +all staged files, whether or not the diff is coherent. Do not propose splits, and +do not report split guidance. + +## 3. Choose a scope for each unit + +Use the smallest stable subsystem or module name recognizable in the repository. + +When no such name applies, use the primary directory or package of the unit's +changes. + +## 4. Write each message + +Follow `references/output.md` for the subject pattern, the body rules, issue +references, the plan-citation rule, and the anti-patterns. + +## 5. Apply the plan-citation rule + +When the unit's staged files include `context/plans/*.md`, cite the affected plan +slug and updated task IDs in the body. + +When the staged plan diff does not expose the slug or task ID clearly enough to +cite faithfully: + +- In `regular` mode, set internal status `blocked` and ask for the reference to be + stated or staged explicitly. +- In `bypass` mode, infer the citation when the diff supports it, and otherwise + omit it. Never stop, and never invent a slug or task ID. + +## 6. Apply context-file guidance gating + +This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do +not classify staged scope there. + +Classify the staged diff: + +- Context-only (`context/**`): context-file-focused guidance is allowed. +- Mixed (`context/**` plus non-`context/**`): suppress default context-file commit + reminders and give guidance that reflects the full staged scope. + +## 7. Propose split guidance + +This step applies in `regular` mode only. + +When the units found in step 2 pursue unrelated goals, return one message per +unit, and state why the split is recommended and which staged files belong to +each. + +When the staged changes form one unit, return one message and no split guidance. +Do not split coherent work to appear thorough. + +## 8. Validate the result + +Confirm before returning that: + +- Every message describes its unit faithfully and covers only that unit's files. +- Every staged file belongs to exactly one returned message. +- No plan slug or task ID appears that the staged diff does not support. +- The mode's own constraints hold. + +## 9. Return internal state + +Set exactly one internal state: + +- `proposal` in `regular` mode, with one or more messages. +- `bypass_message` in `bypass` mode, with exactly one message. +- `blocked` when messages cannot be written faithfully. + +Record only the internal state. Do not add explanatory prose before or after it. + +## Atomic commit boundaries + +Do not: + +- Run `git commit`, or any command that writes to the repository or its index. +- Stage, unstage, or modify files. +- Ask the user to stage or confirm staging. +- Analyze unstaged or untracked changes. +- Return more than one message in `bypass` mode. +- Return split guidance in `bypass` mode. +- Stop for plan-citation ambiguity in `bypass` mode. +- Invent plan slugs, task IDs, or issue references. +- Mention `context/` synchronization activity in a commit message. +- Claim a message was committed. +- Run plan, task, or validation workflows. diff --git a/.pi/skills/sce-next-task/SKILL.md b/.pi/skills/sce-next-task/SKILL.md index 6e82bdaf..9ba319be 100644 --- a/.pi/skills/sce-next-task/SKILL.md +++ b/.pi/skills/sce-next-task/SKILL.md @@ -15,6 +15,25 @@ workflow command except `sce-decision`, and invoke `sce-decision` only from the successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps, gates, and boundaries +live in a reference file. This document holds the control flow — which phase runs, +what it receives, and how its result branches — and each reference holds the phase +itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/plan-review.md` | +| 2 | `references/task-execution.md` | +| 3 | `references/context-sync.md` | + +Read a step's reference before taking any action for that step, not after. The +references carry gates that must fire before their phase's first side effect, so a +phase begun from this summary alone will already have skipped them. Read only the +reference for the step you have reached: a run that stops at step 1 never needs the +other two, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -52,111 +71,11 @@ Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is ### 1. Review the task -Run the **Plan review phase** with the parsed `plan-name-or-path` and, when present, the parsed `task-id`. +Read `references/plan-review.md`, then run the **Plan review phase** with the +parsed `plan-name-or-path` and, when present, the parsed `task-id`. Do not pass the `auto-approve` token to the **Plan review phase**. -#### 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status `blocked` with -the matching candidates. - -Read the selected plan before exploring the repository. - -#### 1.2 Resolve one task - -When a task ID is supplied, select that task. - -Otherwise, select the first incomplete task in plan order whose declared -dependencies are complete. - -Set internal status `plan_complete` when no incomplete tasks remain. - -Set internal status `blocked` when incomplete tasks remain but none can currently be -executed. - -Review at most one task per invocation. - -#### 1.3 Inspect relevant context - -Start with the task and the files it directly references. - -Inspect only what is needed to understand: - -- Existing behavior. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests. -- Available verification commands. -- Decisions or specifications connected to the task. - -Load root context only when the task affects repository-wide behavior, -architecture, shared terminology, or cross-domain interfaces. - -Do not explore the entire repository by default. - -#### 1.4 Determine readiness - -A task is `ready` when: - -- Its goal is clear. -- Its scope is sufficiently bounded. -- Its dependencies are complete. -- Its done checks are observable. -- A credible verification method exists. -- No unresolved decision would materially change the implementation. - -Use repository conventions for ordinary local choices. - -Do not block on: - -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change observable behavior or scope. - -Record these choices under `assumptions`. - -Set internal status `blocked` when a missing decision materially affects: - -- User-visible behavior. -- Public interfaces. -- Architecture or ownership boundaries. -- Data shape or persistence. -- Security or privacy. -- External dependencies. -- Destructive or difficult-to-reverse behavior. -- The evidence needed to prove completion. - -#### 1.5 Return the result - -Set exactly one internal state: - -- `ready` -- `blocked` -- `plan_complete` - -Record only the internal state. Do not add explanatory prose before or after -it. - -### Plan review boundaries - -Do not: - -- Modify application code. -- Modify tests. -- Update the plan. -- Mark the task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Review more than one task. - Branch on `status`: `blocked` -> Do not run implementation. Render the **Review blocked** layout from `references/output.md`. When `candidates` is present the plan could not be resolved, and each entry is a candidate path for `/next-task {candidate-path}`. `executable_tasks_remaining` true means another task remains executable and `/next-task {plan-path} {task-id}` selects one; false means no task in the plan can proceed until the plan is updated. Do not print the raw result. Stop. @@ -169,7 +88,13 @@ Do not reconstruct, summarize, or reinterpret the reviewed task before passing i ### 2. Execute the task -Run the **Task execution phase** with the complete `ready` result from the **Plan review phase**. +Read `references/task-execution.md`, then run the **Task execution phase** with +the complete `ready` result from the **Plan review phase**. + +This phase always shows an implementation gate before it modifies any file, and it +is the only phase permitted to ask the user for confirmation. Both properties are +load-bearing, so reach them through the reference rather than acting from this +summary. Branch on `auto-approve`: @@ -177,205 +102,8 @@ Branch on `auto-approve`: else -> Do not pass the `approve` flag. The **Task execution phase** shows its implementation gate and waits for the user's decision. -The **Task execution phase** exclusively owns: - -- Presenting the implementation summary. -- Requesting implementation confirmation. -- Implementing the task. -- Running task-level verification. -- Updating the task status and evidence. - Do not present an additional implementation confirmation. -The `approve` flag means the user pre-approved this task when invoking the -workflow. It suppresses the approval question and the wait. It never suppresses -the gate. Only the workflow entrypoint may set it, and only from an explicit -user-supplied approval token. Never infer it. - -The readiness result must identify: - -- One resolved plan. -- Exactly one incomplete task. -- The task goal and scope boundaries. -- Done checks. -- Verification expectations. -- Relevant files and context. -- Review assumptions. - -If required handoff information is absent or stale, still show the gate using -what is known, clearly identify the handoff problem, and do not edit files. -After the user responds, set internal status `blocked`. - -#### 2.1 Validate the handoff without editing - -Confirm that: - -- The readiness status is `ready`. -- Exactly one task is present. -- The plan file exists. -- The selected task is still incomplete. -- The task has not materially changed since review. -- Declared dependencies remain complete. - -Do not reconstruct missing material requirements. - -#### 2.2 Always show the implementation gate - -At the start of the phase, before any file modification, present the task using -`references/output.md`. - -The gate must be shown even when: - -- The task appears straightforward. -- The workflow believes approval was already implied. -- The handoff is stale or incomplete. -- The user is likely to approve. - -When the `approve` flag is absent, end the gate with exactly one approval -question: - -`Continue with implementation now? (yes/no)` - -Stop and wait for the user's answer. Do not return internal state, and make no file -modifications, until the user has answered. - -When the `approve` flag is supplied, show the gate as a summary, omit the -approval question, do not wait, and continue at step 2.4. - -#### 2.3 Handle the user's decision - -Skip this step when the `approve` flag was supplied. - -When the user rejects or cancels, do not modify files and set internal status `declined`. - -When the user does not clearly approve, do not modify files. Ask the same -approval question once more only when the response is genuinely ambiguous. -Otherwise set internal status `blocked`. - -When the user approves, continue with implementation. - -Treat constraints supplied with approval as part of the approved task boundary. -If those constraints materially contradict the reviewed task, set internal status `blocked` -before editing. - -#### 2.4 Prepare the implementation - -Before editing: - -- Read the relevant files supplied by plan review. -- Inspect nearby code and tests when needed. -- Identify the smallest coherent change satisfying the task. -- Follow surrounding naming, structure, error handling, and test style. -- Preserve unrelated behavior. - -Do not create a second plan. - -Do not broaden the reviewed task. - -#### 2.5 Implement one task - -Make the minimum coherent changes required to satisfy the task goal and done -checks. - -Use judgment for ordinary, reversible local implementation choices. - -Stop when implementation requires: - -- Material scope expansion. -- A new external dependency not authorized by the task. -- A public-interface decision not established by the plan. -- A destructive or difficult-to-reverse operation. -- An unresolved security, privacy, or data decision. -- Contradicting the reviewed task or repository architecture. - -When stopped, preserve completed in-scope work unless retaining it would leave -the repository unsafe or invalid. - -#### 2.6 Verify the task - -Run the narrowest authoritative checks that demonstrate the done checks. - -Start with verification supplied by the readiness result. Add nearby or directly -relevant checks only when needed. - -Verification may include: - -- Targeted tests. -- Type checking for affected code. -- Linting affected files. -- Formatting checks. -- A focused build or compile step. -- Direct behavioral inspection when no automated check exists. - -Do not run final plan validation unless the task itself explicitly requires it. - -When a check fails: - -- Determine whether the task caused the failure. -- Fix it when the correction remains in scope. -- Rerun the relevant check. -- Set internal status `incomplete` when a done check remains unsatisfied, or `blocked` when - completing it requires an unapproved decision or scope expansion. - -Never report a check as passed unless it ran successfully. - -#### 2.7 Update the plan - -Only after successful implementation and task-level verification: - -- Mark only the selected task complete. -- Record concise implementation evidence. -- Record verification commands and outcomes. -- Record material deviations or approved assumptions. -- Preserve the plan's existing structure and terminology. - -Do not mark the task complete when returning `declined`, `blocked`, or -`incomplete`. - -#### 2.8 Determine the terminal status - -Set internal status `complete` when the task was implemented, verified, and marked complete -in the plan with evidence. - -Set internal status `incomplete` when in-scope work was completed but one or more done checks -remain unsatisfied. - -Set internal status `declined` when the user rejected implementation. - -Set internal status `blocked` for every other non-successful outcome, including: - -- Missing approval. -- Stale or invalid handoff. -- Material blocker. -- A verification failure that cannot be resolved in scope. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -#### 2.9 Return internal state - -After the phase reaches a terminal state, set exactly one internal state. - -Record only the internal state. Do not add explanatory prose before or after it. - -### Task execution boundaries - -Do not: - -- Edit before approval, whether explicit or pre-supplied. -- Execute more than one task. -- Select or execute the next task. -- Skip the implementation gate. -- Ask for multiple approval gates for the same unchanged task. -- Expand scope without authorization. -- Synchronize durable context. -- Run final plan validation. -- Determine whether the plan is complete. -- Create a Git commit. -- Push changes. -- Modify unrelated files. -- Claim verification that was not performed. - Branch on the execution result. `declined` -> Render the **Declined** layout from `references/output.md`. Do not run context synchronization. Stop. @@ -388,319 +116,16 @@ Branch on the execution result. ### 3. Synchronize context -Run the **Task context synchronization phase** with the complete `complete` result returned by the **Task execution phase**. +Read `references/context-sync.md`, then run the **Task context synchronization +phase** with the complete `complete` result returned by the **Task execution +phase**. Pass that result verbatim. It is the authoritative handoff, and the **Task context synchronization phase** owns reading the plan, task, changed files, verification evidence, and reported context impact out of it. Do not restate, summarize, or reconstruct any part of the execution result. -The execution result must have: - -```text -status: complete -``` - -Treat the execution result as the authoritative handoff for: - -- The resolved plan and completed task. -- Files changed by implementation. -- Implementation summary. -- Verification evidence. -- Done-check evidence. -- Reported context impact. - -This phase must not be run for `declined`, `blocked`, or `incomplete` -execution results. - -Do not reconstruct a missing execution result from conversation history. - -#### 3.1 Validate the execution handoff - -Confirm that: - -- `status` is exactly `complete`. -- A `plan` object with a `path` is present. -- Exactly one completed task is identified. -- Changed files and an implementation summary are present. -- Verification evidence is present. -- Done-check evidence is present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, -do not modify context. Return a `blocked` Markdown report. - -#### 3.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. -Do not create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that the task itself is complete and recorded in the plan, and that -synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -#### 3.3 Discover applicable context - -Start with the execution result: - -- `context_impact.classification` -- `context_impact.affected_areas` -- Changed files. -- Implementation summary. -- Done-check evidence. - -Then inspect existing repository context in this order when present: - -1. `context/context-map.md` -2. Context files for the affected domain or subsystem -3. `context/overview.md` -4. `context/architecture.md` -5. `context/glossary.md` -6. `context/patterns.md` -7. Operational, product, or decision records directly related to the change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -##### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -completed implementation. A file that is absent is a gap; record it in the -report rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization -done while one of them is unchecked. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -#### 3.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in task evidence. -- Speculation or future work not established by the completed implementation. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass. - -- `none`: Make no edits beyond any correction the root pass turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -A change is `root` when it introduces cross-cutting behavior, repository-wide -policy or contracts, an architecture or ownership boundary, or a change to -canonical terminology. A change confined to one feature or domain, with no -repository-wide behavior, architecture, or terminology impact, is `domain` or -`local`: capture its detail in domain files and leave the root files unedited. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -#### 3.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- execution and done-check evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task references, - related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -#### 3.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the implementation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the completed implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the execution result verbatim into context files. -- Do not change application code, tests, or plan state. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -##### Feature existence - -Every feature the completed task implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the task implemented a feature no context file describes, add that -description. A feature that fits no existing domain file gets a new focused -file; do not defer it to a later task. Prefer a small, precise domain file over -overloading `overview.md` with detail. - -This is the one case where documentation is warranted by the change itself -rather than by a gap in durable knowledge. It is not license to narrate the -diff: describe what the feature is and how it behaves, not what was edited. - -##### Glossary - -Add a `context/glossary.md` entry for any domain language the task introduced. -New terminology is durable knowledge whatever the classification is: a `domain` -change that names a new concept still earns its glossary entry. - -##### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it - into focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough - that prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -#### 3.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the completed implementation. -- No edited statement contradicts the code, plan, or execution evidence. -- Every qualifying decision has one written or reused ADR path in the report, - and the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Each feature implemented by the task has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not run full application or plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -#### 3.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` -means existing context was checked and no edit was warranted. `blocked` means -context could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -### Task context synchronization boundaries - -Do not: - -- Accept an execution result whose status is not `complete`. -- Implement or modify application code. -- Modify tests. -- Change task completion status or plan evidence. -- Determine whether the plan is complete. -- Select or execute another task. -- Run full-plan validation. -- Mark the plan validated, closed, or archived. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason - to document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return an execution-style internal state. +This phase verifies the five root context files on every invocation, whatever the +change's reported impact, so it is never correct to skip it as unnecessary. Branch on the synchronization result. @@ -728,6 +153,7 @@ Stop. - Execute at most one plan task per invocation. - Review at most one task. +- Read each phase's reference before running that phase. - Do not duplicate the internal instructions of embedded phases. - The only permitted sibling-skill invocation is `sce-decision`, and only the successful context-synchronization decision gate may invoke it. diff --git a/.pi/skills/sce-next-task/references/context-sync.md b/.pi/skills/sce-next-task/references/context-sync.md new file mode 100644 index 00000000..06413b09 --- /dev/null +++ b/.pi/skills/sce-next-task/references/context-sync.md @@ -0,0 +1,316 @@ +# Task context synchronization phase + +Run this phase for step 3 of the workflow, and only when task execution returned +`complete`. It updates durable repository knowledge in `context/` so the next +session inherits what this task established. It never touches code, tests, or +plan state. + +Input: the complete `complete` result from the task execution phase, passed +verbatim. It is the authoritative handoff, and this phase owns reading the plan, +task, changed files, verification evidence, and reported context impact out of +it. + +Do not restate, summarize, or reconstruct any part of the execution result. Do +not reconstruct a missing execution result from conversation history. + +The execution result must have: + +```text +status: complete +``` + +Treat the execution result as the authoritative handoff for: + +- The resolved plan and completed task. +- Files changed by implementation. +- Implementation summary. +- Verification evidence. +- Done-check evidence. +- Reported context impact. + +This phase must not be run for `declined`, `blocked`, or `incomplete` execution +results. + +## 3.1 Validate the execution handoff + +Confirm that: + +- `status` is exactly `complete`. +- A `plan` object with a `path` is present. +- Exactly one completed task is identified. +- Changed files and an implementation summary are present. +- Verification evidence is present. +- Done-check evidence is present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 3.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that the task itself is complete and recorded in the plan, and that +synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 3.3 Discover applicable context + +Start with the execution result: + +- `context_impact.classification` +- `context_impact.affected_areas` +- Changed files. +- Implementation summary. +- Done-check evidence. + +Then inspect existing repository context in this order when present: + +1. `context/context-map.md` +2. Context files for the affected domain or subsystem +3. `context/overview.md` +4. `context/architecture.md` +5. `context/glossary.md` +6. `context/patterns.md` +7. Operational, product, or decision records directly related to the change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +completed implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +## 3.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in task evidence. +- Speculation or future work not established by the completed implementation. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass. + +- `none`: Make no edits beyond any correction the root pass turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +A change is `root` when it introduces cross-cutting behavior, repository-wide +policy or contracts, an architecture or ownership boundary, or a change to +canonical terminology. A change confined to one feature or domain, with no +repository-wide behavior, architecture, or terminology impact, is `domain` or +`local`: capture its detail in domain files and leave the root files unedited. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 3.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- execution and done-check evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task + references, related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 3.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the implementation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the completed implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the execution result verbatim into context files. +- Do not change application code, tests, or plan state. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the completed task implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the task implemented a feature no context file describes, add that +description. A feature that fits no existing domain file gets a new focused file; +do not defer it to a later task. Prefer a small, precise domain file over +overloading `overview.md` with detail. + +This is the one case where documentation is warranted by the change itself rather +than by a gap in durable knowledge. It is not license to narrate the diff: +describe what the feature is and how it behaves, not what was edited. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the task introduced. +New terminology is durable knowledge whatever the classification is: a `domain` +change that names a new concept still earns its glossary entry. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 3.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the completed implementation. +- No edited statement contradicts the code, plan, or execution evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Each feature implemented by the task has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not run full application or plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 3.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## Task context synchronization boundaries + +Do not: + +- Accept an execution result whose status is not `complete`. +- Implement or modify application code. +- Modify tests. +- Change task completion status or plan evidence. +- Determine whether the plan is complete. +- Select or execute another task. +- Run full-plan validation. +- Mark the plan validated, closed, or archived. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return an execution-style internal state. diff --git a/.pi/skills/sce-next-task/references/plan-review.md b/.pi/skills/sce-next-task/references/plan-review.md new file mode 100644 index 00000000..d08975e3 --- /dev/null +++ b/.pi/skills/sce-next-task/references/plan-review.md @@ -0,0 +1,121 @@ +# Plan review phase + +Run this phase for step 1 of the workflow. It resolves one plan, selects one +task, and decides whether that task can be implemented right now. It reads; it +never writes. + +Inputs: the parsed `plan-name-or-path`, and `task-id` when present. The +`auto-approve` token is not passed here and has no meaning in this phase. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Resolve one task + +When a task ID is supplied, select that task. + +Otherwise, select the first incomplete task in plan order whose declared +dependencies are complete. + +Set internal status `plan_complete` when no incomplete tasks remain. + +Set internal status `blocked` when incomplete tasks remain but none can currently +be executed. + +Review at most one task per invocation. + +## 1.3 Inspect relevant context + +Start with the task and the files it directly references. + +Inspect only what is needed to understand: + +- Existing behavior. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests. +- Available verification commands. +- Decisions or specifications connected to the task. + +Load root context only when the task affects repository-wide behavior, +architecture, shared terminology, or cross-domain interfaces. + +Do not explore the entire repository by default. + +## 1.4 Determine readiness + +A task is `ready` when: + +- Its goal is clear. +- Its scope is sufficiently bounded. +- Its dependencies are complete. +- Its done checks are observable. +- A credible verification method exists. +- No unresolved decision would materially change the implementation. + +Use repository conventions for ordinary local choices. + +Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change observable behavior or scope. + +Record these choices under `assumptions`. + +Set internal status `blocked` when a missing decision materially affects: + +- User-visible behavior. +- Public interfaces. +- Architecture or ownership boundaries. +- Data shape or persistence. +- Security or privacy. +- External dependencies. +- Destructive or difficult-to-reverse behavior. +- The evidence needed to prove completion. + +## 1.5 Return the result + +Set exactly one internal state: + +- `ready` +- `blocked` +- `plan_complete` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `ready` result must identify: + +- One resolved plan. +- Exactly one incomplete task. +- The task goal and scope boundaries. +- Done checks. +- Verification expectations. +- Relevant files and context. +- Review assumptions. + +Step 2 consumes this result verbatim, so anything the execution phase needs has +to be present here. + +## Plan review boundaries + +Do not: + +- Modify application code. +- Modify tests. +- Update the plan. +- Mark the task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Review more than one task. diff --git a/.pi/skills/sce-next-task/references/task-execution.md b/.pi/skills/sce-next-task/references/task-execution.md new file mode 100644 index 00000000..7b049492 --- /dev/null +++ b/.pi/skills/sce-next-task/references/task-execution.md @@ -0,0 +1,203 @@ +# Task execution phase + +Run this phase for step 2 of the workflow. It is the only phase that writes +application code, and the only one that asks the user for anything. + +Input: the complete `ready` result from the plan review phase, plus the `approve` +flag when the user pre-approved this invocation. + +This phase exclusively owns: + +- Presenting the implementation summary. +- Requesting implementation confirmation. +- Implementing the task. +- Running task-level verification. +- Updating the task status and evidence. + +Do not present an additional implementation confirmation anywhere else. + +The `approve` flag means the user pre-approved this task when invoking the +workflow. It suppresses the approval question and the wait. It never suppresses +the gate. Only the workflow entrypoint may set it, and only from an explicit +user-supplied approval token. Never infer it. + +If required handoff information is absent or stale, still show the gate using +what is known, clearly identify the handoff problem, and do not edit files. After +the user responds, set internal status `blocked`. + +## 2.1 Validate the handoff without editing + +Confirm that: + +- The readiness status is `ready`. +- Exactly one task is present. +- The plan file exists. +- The selected task is still incomplete. +- The task has not materially changed since review. +- Declared dependencies remain complete. + +Do not reconstruct missing material requirements. + +## 2.2 Always show the implementation gate + +At the start of the phase, before any file modification, present the task using +`references/output.md`. + +The gate must be shown even when: + +- The task appears straightforward. +- The workflow believes approval was already implied. +- The handoff is stale or incomplete. +- The user is likely to approve. + +When the `approve` flag is absent, end the gate with exactly one approval +question: + +`Continue with implementation now? (yes/no)` + +Stop and wait for the user's answer. Do not return internal state, and make no +file modifications, until the user has answered. + +When the `approve` flag is supplied, show the gate as a summary, omit the +approval question, do not wait, and continue at step 2.4. + +## 2.3 Handle the user's decision + +Skip this step when the `approve` flag was supplied. + +When the user rejects or cancels, do not modify files and set internal status +`declined`. + +When the user does not clearly approve, do not modify files. Ask the same +approval question once more only when the response is genuinely ambiguous. +Otherwise set internal status `blocked`. + +When the user approves, continue with implementation. + +Treat constraints supplied with approval as part of the approved task boundary. +If those constraints materially contradict the reviewed task, set internal status +`blocked` before editing. + +## 2.4 Prepare the implementation + +Before editing: + +- Read the relevant files supplied by plan review. +- Inspect nearby code and tests when needed. +- Identify the smallest coherent change satisfying the task. +- Follow surrounding naming, structure, error handling, and test style. +- Preserve unrelated behavior. + +Do not create a second plan. + +Do not broaden the reviewed task. + +## 2.5 Implement one task + +Make the minimum coherent changes required to satisfy the task goal and done +checks. + +Use judgment for ordinary, reversible local implementation choices. + +Stop when implementation requires: + +- Material scope expansion. +- A new external dependency not authorized by the task. +- A public-interface decision not established by the plan. +- A destructive or difficult-to-reverse operation. +- An unresolved security, privacy, or data decision. +- Contradicting the reviewed task or repository architecture. + +When stopped, preserve completed in-scope work unless retaining it would leave +the repository unsafe or invalid. + +## 2.6 Verify the task + +Run the narrowest authoritative checks that demonstrate the done checks. + +Start with verification supplied by the readiness result. Add nearby or directly +relevant checks only when needed. + +Verification may include: + +- Targeted tests. +- Type checking for affected code. +- Linting affected files. +- Formatting checks. +- A focused build or compile step. +- Direct behavioral inspection when no automated check exists. + +Do not run final plan validation unless the task itself explicitly requires it. + +When a check fails: + +- Determine whether the task caused the failure. +- Fix it when the correction remains in scope. +- Rerun the relevant check. +- Set internal status `incomplete` when a done check remains unsatisfied, or + `blocked` when completing it requires an unapproved decision or scope + expansion. + +Never report a check as passed unless it ran successfully. + +## 2.7 Update the plan + +Only after successful implementation and task-level verification: + +- Mark only the selected task complete. +- Record concise implementation evidence. +- Record verification commands and outcomes. +- Record material deviations or approved assumptions. +- Preserve the plan's existing structure and terminology. + +Do not mark the task complete when returning `declined`, `blocked`, or +`incomplete`. + +## 2.8 Determine the terminal status + +Set internal status `complete` when the task was implemented, verified, and +marked complete in the plan with evidence. + +Set internal status `incomplete` when in-scope work was completed but one or more +done checks remain unsatisfied. + +Set internal status `declined` when the user rejected implementation. + +Set internal status `blocked` for every other non-successful outcome, including: + +- Missing approval. +- Stale or invalid handoff. +- Material blocker. +- A verification failure that cannot be resolved in scope. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## 2.9 Return internal state + +After the phase reaches a terminal state, set exactly one internal state. + +Record only the internal state. Do not add explanatory prose before or after it. + +A `complete` result is the authoritative handoff into step 3, which reads the +plan, completed task, changed files, implementation summary, verification +evidence, done-check evidence, and context-impact classification out of it. Step +3 is forbidden from reconstructing any of that, so it has to be present here. + +## Task execution boundaries + +Do not: + +- Edit before approval, whether explicit or pre-supplied. +- Execute more than one task. +- Select or execute the next task. +- Skip the implementation gate. +- Ask for multiple approval gates for the same unchanged task. +- Expand scope without authorization. +- Synchronize durable context. +- Run final plan validation. +- Determine whether the plan is complete. +- Create a Git commit. +- Push changes. +- Modify unrelated files. +- Claim verification that was not performed. diff --git a/.pi/skills/sce-validate/SKILL.md b/.pi/skills/sce-validate/SKILL.md index 55e5be7b..d109947e 100644 --- a/.pi/skills/sce-validate/SKILL.md +++ b/.pi/skills/sce-validate/SKILL.md @@ -15,6 +15,25 @@ workflow command except `sce-decision`, and invoke `sce-decision` only from the successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/validation.md` | +| 2 | `references/context-sync.md` | + +`references/validation-report.md` defines the `## Validation Report` section +written into the plan file. Step 1 points to it at the moment it is needed, on a +`validated` or `failed` outcome only. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at a `blocked` +or `failed` validation never enters step 2, which is why they are separate files. + ## User-visible output Use `references/output.md` for every gate and terminal response. Render no raw @@ -53,147 +72,15 @@ candidate path), so every emitted command is directly runnable. ### 1. Validate the plan -Run the **Validation phase** with the plan name or path. - -The **Validation phase** exclusively owns: - -- Resolving one plan. -- Confirming every implementation task is complete. -- Running full validation and acceptance-criteria checks. -- Removing temporary scaffolding. -- Writing the Validation Report into the plan. -- Returning one Markdown validation result. - -Do not duplicate any of it. Do not write the Validation Report yourself. - -#### 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan under -`context/plans/`. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status `blocked` -with the matching candidates. - -Read the selected plan before exploring the repository. - -#### 1.2 Confirm implementation is finished - -Set internal status `blocked` with incomplete tasks listed when any implementation task -remains incomplete. - -Final validation measures finished work. Do not run the full suite against a -partial stack, and do not complete remaining tasks here. - -#### 1.3 Read the validation contract from the plan - -From the plan, collect: - -- Every acceptance criterion and its `Validate:` check. -- The `Full validation` command list. -- The `Context sync` requirements, for the context-impact handoff only. - -Set internal status `blocked` when the plan has no usable acceptance criteria, or when no -validation commands can be determined from the plan or repository conventions. - -Prefer the plan's authored checks. Fall back to repository-primary test, lint, -and format commands only when `Full validation` is absent, and record that -fallback under notes on a `validated` or `failed` result. - -#### 1.4 Remove temporary scaffolding - -Before or while running checks, remove temporary scaffolding introduced during -the change when it is clearly throwaway: - -- Debug-only patches or flags left enabled. -- Temporary files or intermediate artifacts not part of the delivered design. -- Local scaffolding the plan or task notes mark as temporary. - -Do not delete durable product code, tests, configuration, or context files. - -Record every removed path. When nothing temporary remains, report `None.` - -#### 1.5 Run full validation and acceptance checks - -Run the plan's `Full validation` commands. - -Then verify each acceptance criterion using its `Validate:` line. Prefer a -runnable command. Use a named inspection only when the criterion authorizes it, -and say exactly what was inspected. - -When a check fails, record the failure and continue gathering evidence. Do not -modify tests, application code, or configuration to make a check pass. Final -validation measures the finished work; repair belongs to a later work session, -not this skill. - -Never report a check as passed unless it ran successfully or the authorized -inspection confirmed the criterion. - -Do not run task-by-task implementation work for incomplete tasks. That belongs -to `/next-task`. - -#### 1.6 Update the plan +Read `references/validation.md`, then run the **Validation phase** with the plan +name or path. -For `validated` and `failed` outcomes: +This phase measures finished work and never repairs it: it does not modify tests, +application code, or configuration to make a failing check pass. That property is +load-bearing, so reach it through the reference rather than acting from this +summary. -- Mark each acceptance criterion checkbox to match the evidence. -- Append or replace the plan's `## Validation Report` section using - the **Plan-file validation report** section embedded in this file. -- When status is `failed`, the plan-file report must include the retry command - `/validate {plan path}`. - -Do not reopen completed tasks, rewrite task evidence, or change the task stack. - -For `blocked`, leave the plan file unchanged. - -#### 1.7 Determine context impact for the handoff - -On `validated` only, classify the durable context impact of the finished plan -so the **Plan context synchronization phase** can start from the plan's own requirements: - -- Start from the plan's `Context sync` section. -- Inspect what the completed implementation actually changed when needed. -- Report required context paths and affected areas. -- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level - context sync. - -Do not edit context files here. - -On `failed` or `blocked`, omit context impact; context sync will not run. - -#### 1.8 Return the internal state - -Set exactly one internal state: - -- `validated` when every acceptance criterion is met, required full validation - passed, and the Validation Report was written. -- `failed` when evidence was captured but required checks or criteria remain - unsatisfied. Shape it as a session handoff per - `references/output.md`, ending recommended work with - `/validate {plan path}`. -- `blocked` when validation cannot proceed safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. Do not return internal state. - -### Validation boundaries - -Do not: - -- Validate more than one plan. -- Complete remaining implementation tasks. -- Modify tests, application code, or configuration to make a failing check pass. -- Apply lint or format auto-fixes that change product or test files as part of - making validation green. -- Synchronize durable context under `context/` outside the plan file. -- Create the context root. -- Mark the plan archived or delete the plan. -- Create a Git commit or push changes. -- Invent acceptance criteria the plan does not state. -- Claim verification that was not performed. -- Return a internal state. -- Run plan context synchronization. The workflow owns that step. +Do not write the Validation Report yourself. Branch on the report's `Status:`. @@ -218,8 +105,9 @@ passing it. ### 2. Synchronize plan context -Run the **Plan context synchronization phase** only with a `Status: validated` Markdown result -from the **Validation phase**. +Read `references/context-sync.md`, then run the **Plan context synchronization +phase** with the `Status: validated` Markdown result from the **Validation +phase**. Do not run the **Plan context synchronization phase** for `failed` or `blocked`. Those are not success states. @@ -230,311 +118,9 @@ reported context impact out of it. Do not restate, summarize, or reconstruct any part of the validation result. -Task-level context sync may already have run after individual tasks. This phase -is the plan-level final pass: it starts from the plan's `Context sync` -requirements and the validated implementation, and closes gaps that remain. - -The validation result must report: - -```markdown -**Status:** validated -**Plan:** {plan path} -``` - -Treat that Markdown as the authoritative handoff for: - -- The resolved plan path. -- Validation commands and outcomes. -- Acceptance-criteria evidence. -- Scaffolding removals. -- Reported context impact, required context paths, and affected areas. - -This phase must not be run for `failed` or `blocked` validation results. -Those are not success states. Same rule as the **Task context synchronization phase**: context sync -runs only after a successful prior phase. - -Do not reconstruct a missing validation result from conversation history. - -#### 2.1 Validate the validation handoff - -Confirm that: - -- `Status:` is exactly `validated`. -- `Plan:` names an existing plan path. -- Acceptance-criteria evidence is present and every criterion is met. -- Commands run are present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, -do not modify context. Return a `blocked` Markdown report. - -#### 2.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. -Do not create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that validation itself succeeded and is recorded in the plan, and that -plan context synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -#### 2.3 Discover applicable context - -Start with the validated internal state: - -- **Context impact** classification, required context, and affected areas. -- Acceptance-criteria evidence. -- Commands run. - -Then read the plan's `Context sync` section and inspect existing repository -context in this order when present: - -1. Paths named by the plan's `Context sync` section -2. `context/context-map.md` -3. Context files for the affected domain or subsystem -4. `context/overview.md` -5. `context/architecture.md` -6. `context/glossary.md` -7. `context/patterns.md` -8. Operational, product, or decision records directly related to the finished - change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -##### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -finished implementation. A file that is absent is a gap; record it in the -report rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization -done while one of them is unchecked. - -##### Plan context requirements - -Every path or statement listed under the plan's `Context sync` section must be -accounted for in the report as already accurate or updated. A requirement the -finished code still does not satisfy is a blocker, not a note. - -#### 2.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -finished implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in validation evidence. -- Speculation or future work not established by the finished plan. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass or the plan's Context -sync requirements. - -- `none`: Make no edits beyond any correction the root pass or unmet plan - context requirement turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -#### 2.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- acceptance-criteria and validation evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task references, - related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -#### 2.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the validation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the finished implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the validation result verbatim into context files. -- Do not change application code, tests, or plan validation evidence. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -##### Feature existence - -Every feature the finished plan implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the plan delivered a feature no context file describes, add that -description. Prefer a small, precise domain file over overloading -`overview.md` with detail. - -This is not license to narrate the diff: describe what the feature is and how -it behaves, not what was edited during the plan. - -##### Glossary - -Add a `context/glossary.md` entry for any domain language the plan introduced. -New terminology is durable knowledge whatever the classification is. - -##### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it - into focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough - that prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -#### 2.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the finished implementation. -- No edited statement contradicts the code, plan, or validation evidence. -- Every qualifying decision has one written or reused ADR path in the report, - and the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Every plan `Context sync` requirement is met. -- Each feature implemented by the plan has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not rerun full-plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -#### 2.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` -means existing context was checked and no edit was warranted. `blocked` means -context could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after -it. - -### Plan context synchronization boundaries - -Do not: - -- Accept a validation result whose status is not `validated`. -- Accept `failed` or `blocked` validation results. -- Implement or modify application code. -- Modify tests. -- Change task completion status, acceptance-criteria marks, or the Validation - Report. -- Rerun full-plan validation. -- Select or execute an implementation task. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason - to document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return internal state. +This phase verifies the five root context files on every invocation, whatever the +reported impact, and must account for every path in the plan's `Context sync` +section, so it is never correct to skip it as unnecessary. Branch on the synchronization result. @@ -563,6 +149,7 @@ Stop. ## Rules - Validate at most one plan per invocation. +- Read each phase's reference before running that phase. - Do not duplicate the internal instructions of embedded phases. - The only permitted sibling-skill invocation is `sce-decision`, and only the successful context-synchronization decision gate may invoke it. @@ -581,88 +168,3 @@ Stop. - Do not infer success when an embedded phase returns a non-success status. - Preserve validation evidence already written to the plan when context synchronization fails. - -## Internal persisted-document format: Plan-file validation report - -The Markdown section the **Validation phase** appends to the plan file when returning -`validated` or `failed`. Write it at the end of `context/plans/{plan_name}.md` -under exactly one `## Validation Report` heading. - -This is plan-file content. The result returned to the workflow is defined -separately in `references/output.md`. - -Do not author this section while planning. Only `/validate` through the **Validation phase** -writes it. - -### Layout - -```markdown -## Validation Report - -**Status:** {validated | failed} -**Date:** {YYYY-MM-DD} - -### Commands run - -- `{command}` -> exit {code} ({concise outcome summary}) -- `{command}` -> exit {code} ({concise outcome summary}) - -### Scaffolding removed - -- `{path}` — {why it was temporary} -- None. - -### Success-criteria verification - -- [x] AC1: {criterion statement} -> {evidence} -- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} - -### Failed checks and follow-ups - -- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} -- None. - -### Residual risks - -- {risk} -- None identified. - -### Retry - -{Only when Status is failed:} - -After repairs, rerun: - -`/validate {plan path}` -``` - -### Rules - -- Use **Status:** `validated` only when every acceptance criterion is met and - every required full-validation command passed. -- Use **Status:** `failed` when evidence was captured but required checks or - criteria remain unsatisfied. -- List every command that ran under **Commands run**, including ones that - failed. Do not invent exit codes or outcomes. -- Prefer the plan's `Full validation` commands and each criterion's `Validate:` - line over rediscovering project defaults. Fall back to repository conventions - only when the plan omits them. -- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` - section to match the evidence. Do not mark a criterion met unless the check - ran successfully or the inspection named by `Validate:` confirms it. -- Under **Scaffolding removed**, list only temporary debug code, intermediate - artifacts, or throwaway files introduced during the change. Write `None.` when - nothing temporary remained. -- Under **Failed checks and follow-ups**, record the failing check and its - evidence only. Do not describe code or test edits made during validation; - validation does not modify tests or product code to clear failures. Write - `None.` when status is `validated`. -- When status is `failed`, always include **Retry** with the exact - `/validate {plan path}` command. Omit **Retry** when status is `validated`. -- Keep evidence concise and factual. Do not narrate the whole implementation - history. -- Do not claim context synchronization completed. Plan context sync is a later - workflow step and runs only after `validated`. -- Do not rewrite task evidence or reopen completed tasks. -- When a previous `## Validation Report` already exists, replace it with the new - one rather than stacking duplicates. diff --git a/.pi/skills/sce-validate/references/context-sync.md b/.pi/skills/sce-validate/references/context-sync.md new file mode 100644 index 00000000..d6a45d46 --- /dev/null +++ b/.pi/skills/sce-validate/references/context-sync.md @@ -0,0 +1,306 @@ +# Plan context synchronization phase + +Run this phase for step 2 of the workflow, and only with a `Status: validated` +Markdown result from the validation phase. It is the plan-level final context +pass: it starts from the plan's `Context sync` requirements and the validated +implementation, and closes gaps that remain after any task-level syncs already +ran. + +Do not run this phase for `failed` or `blocked`. Those are not success states. +Same rule as the task context synchronization phase: context sync runs only after +a successful prior phase. + +Pass the validated result verbatim. It is the authoritative handoff, and this +phase owns reading the plan path, required context paths, validation evidence, +and reported context impact out of it. + +Do not restate, summarize, or reconstruct any part of the validation result. Do +not reconstruct a missing validation result from conversation history. + +Treat that Markdown as the authoritative handoff for: + +- The resolved plan path. +- Validation commands and outcomes. +- Acceptance-criteria evidence. +- Scaffolding removals. +- Reported context impact, required context paths, and affected areas. + +## 2.1 Validate the validation handoff + +Confirm that: + +- `Status:` is exactly `validated`. +- `Plan:` names an existing plan path. +- Acceptance-criteria evidence is present and every criterion is met. +- Commands run are present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 2.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that validation itself succeeded and is recorded in the plan, and that plan +context synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 2.3 Discover applicable context + +Start with the validated internal state: + +- **Context impact** classification, required context, and affected areas. +- Acceptance-criteria evidence. +- Commands run. + +Then read the plan's `Context sync` section and inspect existing repository +context in this order when present: + +1. Paths named by the plan's `Context sync` section +2. `context/context-map.md` +3. Context files for the affected domain or subsystem +4. `context/overview.md` +5. `context/architecture.md` +6. `context/glossary.md` +7. `context/patterns.md` +8. Operational, product, or decision records directly related to the finished + change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +finished implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +### Plan context requirements + +Every path or statement listed under the plan's `Context sync` section must be +accounted for in the report as already accurate or updated. A requirement the +finished code still does not satisfy is a blocker, not a note. + +## 2.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +finished implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in validation evidence. +- Speculation or future work not established by the finished plan. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass or the plan's Context sync +requirements. + +- `none`: Make no edits beyond any correction the root pass or unmet plan context + requirement turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 2.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- acceptance-criteria and validation evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task references, + related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 2.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the validation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the finished implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the validation result verbatim into context files. +- Do not change application code, tests, or plan validation evidence. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the finished plan implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the plan delivered a feature no context file describes, add that +description. Prefer a small, precise domain file over overloading `overview.md` +with detail. + +This is not license to narrate the diff: describe what the feature is and how it +behaves, not what was edited during the plan. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the plan introduced. +New terminology is durable knowledge whatever the classification is. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 2.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the finished implementation. +- No edited statement contradicts the code, plan, or validation evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Every plan `Context sync` requirement is met. +- Each feature implemented by the plan has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not rerun full-plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 2.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +## Plan context synchronization boundaries + +Do not: + +- Accept a validation result whose status is not `validated`. +- Accept `failed` or `blocked` validation results. +- Implement or modify application code. +- Modify tests. +- Change task completion status, acceptance-criteria marks, or the Validation + Report. +- Rerun full-plan validation. +- Select or execute an implementation task. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return internal state. diff --git a/.pi/skills/sce-validate/references/output.md b/.pi/skills/sce-validate/references/output.md index d2b7b888..88c75575 100644 --- a/.pi/skills/sce-validate/references/output.md +++ b/.pi/skills/sce-validate/references/output.md @@ -36,9 +36,9 @@ The `Status` value must be exactly one of: - `failed` - `blocked` -The plan-file `## Validation Report` section is written separately using the -**Plan-file validation report** section embedded in this file. This layout -carries the validation phase's result into the workflow's own branches. +The plan-file `## Validation Report` section is written separately using +`references/validation-report.md`. This layout carries the validation phase's +result into the workflow's own branches. ## Validated variant diff --git a/.pi/skills/sce-validate/references/validation-report.md b/.pi/skills/sce-validate/references/validation-report.md new file mode 100644 index 00000000..deaa9a0b --- /dev/null +++ b/.pi/skills/sce-validate/references/validation-report.md @@ -0,0 +1,84 @@ +# Internal persisted-document format: Plan-file validation report + +The Markdown section the **Validation phase** appends to the plan file when +returning `validated` or `failed`. Write it at the end of +`context/plans/{plan_name}.md` under exactly one `## Validation Report` heading. + +This is plan-file content. The result returned to the workflow is defined +separately in `references/output.md`. + +Do not author this section while planning. Only `/validate` through the +**Validation phase** writes it. + +## Layout + +```markdown +## Validation Report + +**Status:** {validated | failed} +**Date:** {YYYY-MM-DD} + +### Commands run + +- `{command}` -> exit {code} ({concise outcome summary}) +- `{command}` -> exit {code} ({concise outcome summary}) + +### Scaffolding removed + +- `{path}` — {why it was temporary} +- None. + +### Success-criteria verification + +- [x] AC1: {criterion statement} -> {evidence} +- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} + +### Failed checks and follow-ups + +- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} +- None. + +### Residual risks + +- {risk} +- None identified. + +### Retry + +{Only when Status is failed:} + +After repairs, rerun: + +`/validate {plan path}` +``` + +## Rules + +- Use **Status:** `validated` only when every acceptance criterion is met and + every required full-validation command passed. +- Use **Status:** `failed` when evidence was captured but required checks or + criteria remain unsatisfied. +- List every command that ran under **Commands run**, including ones that failed. + Do not invent exit codes or outcomes. +- Prefer the plan's `Full validation` commands and each criterion's `Validate:` + line over rediscovering project defaults. Fall back to repository conventions + only when the plan omits them. +- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` + section to match the evidence. Do not mark a criterion met unless the check ran + successfully or the inspection named by `Validate:` confirms it. +- Under **Scaffolding removed**, list only temporary debug code, intermediate + artifacts, or throwaway files introduced during the change. Write `None.` when + nothing temporary remained. +- Under **Failed checks and follow-ups**, record the failing check and its + evidence only. Do not describe code or test edits made during validation; + validation does not modify tests or product code to clear failures. Write + `None.` when status is `validated`. +- When status is `failed`, always include **Retry** with the exact + `/validate {plan path}` command. Omit **Retry** when status is `validated`. +- Keep evidence concise and factual. Do not narrate the whole implementation + history. +- Do not claim context synchronization completed. Plan context sync is a later + workflow step and runs only after `validated`. +- Do not rewrite task evidence or reopen completed tasks. +- When a previous `## Validation Report` already exists, replace it with the new + one rather than stacking duplicates. diff --git a/.pi/skills/sce-validate/references/validation.md b/.pi/skills/sce-validate/references/validation.md new file mode 100644 index 00000000..38e8944f --- /dev/null +++ b/.pi/skills/sce-validate/references/validation.md @@ -0,0 +1,161 @@ +# Validation phase + +Run this phase for step 1 of the workflow. It resolves one plan, confirms the +implementation is finished, runs the plan's checks, and records what it found. + +Input: the plan name or path, unmodified. + +This phase exclusively owns: + +- Resolving one plan. +- Confirming every implementation task is complete. +- Running full validation and acceptance-criteria checks. +- Removing temporary scaffolding. +- Writing the Validation Report into the plan. +- Returning one Markdown validation result. + +Do not duplicate any of it elsewhere in the workflow. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan under +`context/plans/`. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Confirm implementation is finished + +Set internal status `blocked` with incomplete tasks listed when any +implementation task remains incomplete. + +Final validation measures finished work. Do not run the full suite against a +partial stack, and do not complete remaining tasks here. + +## 1.3 Read the validation contract from the plan + +From the plan, collect: + +- Every acceptance criterion and its `Validate:` check. +- The `Full validation` command list. +- The `Context sync` requirements, for the context-impact handoff only. + +Set internal status `blocked` when the plan has no usable acceptance criteria, or +when no validation commands can be determined from the plan or repository +conventions. + +Prefer the plan's authored checks. Fall back to repository-primary test, lint, +and format commands only when `Full validation` is absent, and record that +fallback under notes on a `validated` or `failed` result. + +## 1.4 Remove temporary scaffolding + +Before or while running checks, remove temporary scaffolding introduced during +the change when it is clearly throwaway: + +- Debug-only patches or flags left enabled. +- Temporary files or intermediate artifacts not part of the delivered design. +- Local scaffolding the plan or task notes mark as temporary. + +Do not delete durable product code, tests, configuration, or context files. + +Record every removed path. When nothing temporary remains, report `None.` + +## 1.5 Run full validation and acceptance checks + +Run the plan's `Full validation` commands. + +Then verify each acceptance criterion using its `Validate:` line. Prefer a +runnable command. Use a named inspection only when the criterion authorizes it, +and say exactly what was inspected. + +When a check fails, record the failure and continue gathering evidence. Do not +modify tests, application code, or configuration to make a check pass. Final +validation measures the finished work; repair belongs to a later work session, +not this skill. + +Never report a check as passed unless it ran successfully or the authorized +inspection confirmed the criterion. + +Do not run task-by-task implementation work for incomplete tasks. That belongs to +`/next-task`. + +## 1.6 Update the plan + +For `validated` and `failed` outcomes: + +- Mark each acceptance criterion checkbox to match the evidence. +- Append or replace the plan's `## Validation Report` section using + `references/validation-report.md`. Read that file before writing the section. +- When status is `failed`, the plan-file report must include the retry command + `/validate {plan path}`. + +Do not reopen completed tasks, rewrite task evidence, or change the task stack. + +For `blocked`, leave the plan file unchanged. + +## 1.7 Determine context impact for the handoff + +On `validated` only, classify the durable context impact of the finished plan so +the **Plan context synchronization phase** can start from the plan's own +requirements: + +- Start from the plan's `Context sync` section. +- Inspect what the completed implementation actually changed when needed. +- Report required context paths and affected areas. +- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level + context sync. + +Do not edit context files here. + +On `failed` or `blocked`, omit context impact; context sync will not run. + +## 1.8 Return the internal state + +Set exactly one internal state: + +- `validated` when every acceptance criterion is met, required full validation + passed, and the Validation Report was written. +- `failed` when evidence was captured but required checks or criteria remain + unsatisfied. Shape it as a session handoff per `references/output.md`, ending + recommended work with `/validate {plan path}`. +- `blocked` when validation cannot proceed safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. +Do not return internal state. + +A `validated` result is the authoritative handoff into step 2, which reads the +plan path, required context paths, validation evidence, and reported context +impact out of it. It must report: + +```markdown +**Status:** validated +**Plan:** {plan path} +``` + +and must carry the resolved plan path, validation commands and outcomes, +acceptance-criteria evidence, scaffolding removals, and the reported context +impact with required context paths and affected areas. Step 2 is forbidden from +reconstructing any of that, so it has to be present here. + +## Validation boundaries + +Do not: + +- Validate more than one plan. +- Complete remaining implementation tasks. +- Modify tests, application code, or configuration to make a failing check pass. +- Apply lint or format auto-fixes that change product or test files as part of + making validation green. +- Synchronize durable context under `context/` outside the plan file. +- Create the context root. +- Mark the plan archived or delete the plan. +- Create a Git commit or push changes. +- Invent acceptance criteria the plan does not state. +- Claim verification that was not performed. +- Return a internal state. +- Run plan context synchronization. The workflow owns that step. diff --git a/config/pkl/base/workflow-change-to-plan.pkl b/config/pkl/base/workflow-change-to-plan.pkl index 66eb18d6..427b35ab 100644 --- a/config/pkl/base/workflow-change-to-plan.pkl +++ b/config/pkl/base/workflow-change-to-plan.pkl @@ -1439,6 +1439,13 @@ local PLAN_SUMMARY = """ structuredComposite = new model.StructuredCompositeSource { command = structuredCommand + compositeSkillBody = model.changeToPlanSkillBody + referenceDocuments = new Listing { + model.makeDocument.apply("references/context-load.md", model.changeToPlanContextLoad) + model.makeDocument.apply("references/plan-authoring.md", model.changeToPlanPlanAuthoring) + model.makeDocument.apply("references/plan-template.md", model.changeToPlanPlanTemplate) + model.makeDocument.apply("references/output.md", model.changeToPlanOutput) + } phases = new Listing {} internalDocuments = new Listing { model.makeDocument.apply("Plan template", renderPlanTemplate.apply("composite")) diff --git a/config/pkl/base/workflow-commit.pkl b/config/pkl/base/workflow-commit.pkl index 6ecca3a6..c6da5699 100644 --- a/config/pkl/base/workflow-commit.pkl +++ b/config/pkl/base/workflow-commit.pkl @@ -703,6 +703,11 @@ local COMMIT_MESSAGE_STYLE = renderCommitMessageStyle.apply("package") structuredComposite = new model.StructuredCompositeSource { command = structuredCommand + compositeSkillBody = model.commitSkillBody + referenceDocuments = new Listing { + model.makeDocument.apply("references/atomic-commit.md", model.commitAtomicCommit) + model.makeDocument.apply("references/output.md", model.commitOutput) + } phases = new Listing {} internalDocuments = new Listing {} outputDocuments = new Listing { diff --git a/config/pkl/base/workflow-content.pkl b/config/pkl/base/workflow-content.pkl index 062646ed..b7c29a0b 100644 --- a/config/pkl/base/workflow-content.pkl +++ b/config/pkl/base/workflow-content.pkl @@ -94,6 +94,15 @@ class StructuredWorkflowDocument { class StructuredCompositeSource { command: StructuredWorkflowDocument + /// Complete workflow body for a phase-reference package. When present, the + /// composite renderer uses this body instead of inlining phase instructions. + compositeSkillBody: String? = null + + /// Package-local documents read only when their owning workflow step runs. + /// Phase-based workflows include output.md here; phase-free workflows keep + /// using outputDocuments for their sole reference. + referenceDocuments: Listing = new Listing {} + /// Phase documents still rendered as a trailing appendix. A module that /// states every phase inside the step that runs it lists none, and composite /// rendering then emits no appendix at all. @@ -159,3 +168,3439 @@ hidden commandBanner = (workflowName: String) -> packageOnlyBlock.apply("\(workf /// rendering states the phase's whole body inside the step. hidden inlinePhaseBody = (phaseBody: WorkflowBody) -> compositeOnlyBlock.apply(phaseBody.render.apply("composite")) + +/// Canonical composite workflow bodies and package-local references for the +/// four phase-based workflows. Target renderers add only supported entrypoint +/// frontmatter; all operational and persisted-document content remains +/// target-neutral. +changeToPlanSkillBody = """ +# SCE Change to Plan + +## Purpose + +Own this workflow from input parsing through its terminal user-visible response. +Execute the phases below directly and in order. Phase statuses are internal state, +not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or +workflow command. Follow the canonical workflow's steps, gates, +and stops exactly as written: never invent, skip, reorder, or merge a step. + +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/context-load.md` | +| 2 and 4 | `references/plan-authoring.md` | + +`references/plan-template.md` defines the plan file written to disk. The plan +authoring phase points to it at the moment a plan is actually written, which never +happens on a `needs_clarification` or `blocked` result. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at the +bootstrap gate never authors a plan, which is why they are separate files. + +## User-visible output + +Use `references/output.md` for every gate and terminal response. Render no raw +internal state. The reference contains only human-visible Markdown layouts. +User-visible output is limited to those layouts: never invent a layout, and never +wrap one in an added preamble, commentary, summary, or extra section. + +## Composite control flow + +Keep phase results as internal state and continue immediately whenever the +canonical workflow says to continue. Stop only at a user wait or terminal branch. +Approval, clarification, revision, failed-validation repair, and bootstrap waits +resume this same skill in the same session. Never expose an internal phase result +as the workflow's final response. + +## Input + +`$ARGUMENTS` is the change request, in free-form prose. + +- The change request is required. +- It may describe a new plan or a change to an existing plan. Do not resolve which one applies; step 2 owns that decision. + +When `$ARGUMENTS` is empty, report that a change request is required, state the expected argument, and stop. Do not infer a change request from the repository state or the conversation. + +Pass the change request to step 2 unmodified. Do not restate, summarize, or pre-scope it. + +Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is the path resolved in step 2 (`plan.path`, or an entry of `candidates`), so every emitted command is directly runnable. + +## Workflow + +### 1. Load durable context + +Read `references/context-load.md`, then run the **Context load phase** with the +change request as the focus. + +`context/` is durable AI-first memory describing current state. Load it before planning so the plan starts from recorded truth. Where context and code disagree, the code is the source of truth. + +Branch on `status`: + +`bootstrap_required` -> `context/` does not exist. Do not create it, and do not plan without it. Render the **Missing context bootstrap gate** layout from `references/output.md`. + +Wait for the user. When they report the command ran, run the **Context load phase** again and continue in this session. Do not restart planning, and do not ask for the change request again. + +`loaded` -> Continue to the next step. + +Do not read `context/` yourself. Do not repair drift or stale context; the brief reports it and the plan may schedule the repair. + +### 2. Author the plan + +Read `references/plan-authoring.md`, then run the **Plan authoring phase** with +the change request and the complete `loaded` brief from the **Context load +phase**. + +Pass the brief verbatim. Do not restate, summarize, or reinterpret it. + +This phase challenges whether the change is worth building before planning how to +build it, and it decides on its own whether to stop at the clarification gate. +Both shape what reaches the user, so reach them through the reference rather than +acting from this summary. + +Do not write or edit the plan file yourself. + +Branch on `status`: + +`needs_clarification` -> No plan was written. Present the result as prose. Do not print the raw result. Render the **Clarification gate** layout from `references/output.md`. + +Render one `##` block per entry in `questions`, in result order. Use the question's `id`, `category`, `question`, and `why_blocking` fields exactly as returned. + +Do not answer the questions. Do not assume answers. Do not write a plan. Stop and wait. + +`blocked` -> No plan was written. Render the **Blocked** layout from `references/output.md`, drawing its issues from `issues` and, when `candidates` is present, its candidate paths from `candidates`. Do not print the raw result. Stop. + +`plan_ready` -> Continue to the next step. + +### 3. Determine the continuation + +Render the `plan_ready` result as the summary defined by the **Plan authoring phase** in `references/output.md`. Follow that layout exactly. Do not print the raw result. + +Take the next task from `next_task`. A `plan_ready` result always names one. Do not evaluate its dependencies; the **Plan review phase** checks them when the emitted command runs and returns `blocked` if they are unmet. + +The continuation invites revision. The plan was written from one prose request, so its assumptions are guesses about what the user meant, its scope is one reading of the request, and its task boundaries are the author's judgement. The user has seen none of it until now, and every one of those is cheaper to correct here than after a task has been built on it. A user who does not know revision is on the table will implement a plan they would have changed. + +Write `task` rather than `tasks` when `total_tasks` is 1. + +Offer revision, but do not gate the handoff on it, do not manufacture concerns, and do not ask the user to confirm the plan. When the summary lists open questions, leave them in the summary only — do not restate them in the continuation, do not answer them, and do not block the handoff on them. Blocking questions belong in `needs_clarification` (step 2), not here. + +Render the **Ready continuation** layout from `references/output.md`. + +Then stop and wait. Do not implement, and do not run the handoff yourself. + +### 4. Revise the plan on request + +When the user answers clarification questions from step 2, answers open questions listed in the summary, or answers with changes to the plan, revise it in this session. Do not ask them to rerun `/change-to-plan`, and do not ask for the original change request again. + +Run the **Plan authoring phase** with their answer or correction and the same `loaded` brief from step 1. The brief still holds; durable context did not change because the user disagreed with a task boundary. Do not reload it. + +An answer that resolves a doubt removes that open question. An answer that does not resolve it leaves the question standing; do not drop it because the user replied to it. If the reply raises a new doubt, the revised plan carries a new open question. + +Pass the correction as written. Do not restate, soften, or pre-scope it. The **Plan authoring phase** owns resolving it against the existing plan, and owns preserving completed tasks and their evidence. + +Branch on `status` exactly as in step 2. A revision may legitimately return `needs_clarification` or `blocked`. + +On `plan_ready`, render the summary again and the continuation exactly as in step 3, replacing `is ready` with `revised` in the heading. + +Revise as many times as the user asks. Each revision is one invocation of the **Plan authoring phase** against the same plan. + +When the user signals the plan is good, or asks to begin, return the handoff without re-authoring the plan. Say so plainly if questions are still open: the user may proceed over an unresolved doubt, and that is their call, but do not record it as resolved. + +Stop. + +## Rules + +- Plan at most one change request per invocation. Revisions to the plan that request produced are part of the same invocation, not a second request. +- Read each phase's reference before running that phase. +- Always tell the user the plan can be revised, and always name its assumptions as the first thing worth checking. +- Do not gate the handoff on open questions listed in the plan summary. Blocking questions return `needs_clarification` before any plan is written. Offering revision is not the same as demanding it, and inventing doubts to justify a review gate is not allowed. +- Do not suppress, soften, or answer an open question or clarification question on the user's behalf. +- Do not defer the user's revision to a rerun of `/change-to-plan`, and do not defer it to the implementation phase. Revise the plan here. +- Do not narrow, expand, or reinterpret a revision the user asked for. Pass it to the **Plan authoring phase** as written. +- Do not duplicate the internal instructions of embedded phases. +- Do not plan before durable context is loaded. +- Do not bootstrap `context/` yourself. `sce setup --bootstrap-context` owns that. +- Do not modify any file under `context/` outside `context/plans/`. +- Do not implement any part of the plan. +- Do not ask for implementation confirmation. +- Do not run task execution, context synchronization, or full-plan validation. +- Do not emit a `/validate` command. This workflow always hands off to `/next-task`. +- Do not answer the skill's clarification questions on the user's behalf. +- Do not execute the continuation returned at the end. +- Do not infer success when the **Plan authoring phase** returns a non-`plan_ready` status. +""" + +changeToPlanContextLoad = """ +# Context load phase + +Run this phase for step 1 of the workflow, with the change request as the focus. + +`context/` is durable AI-first memory describing current state. Load it before +planning so the plan starts from recorded truth. Where context and code disagree, +the code is the source of truth. + +This phase reads and reports; it never writes. + +## 1.1 Confirm the context root + +When `context/` does not exist, set internal status `bootstrap_required` +immediately. Read nothing further. + +Bootstrapping is the workflow's decision, not this phase's. + +## 1.2 Read the entry points + +Read, when present: + +- `context/context-map.md` +- `context/overview.md` +- `context/glossary.md` + +Read `context/architecture.md` when the focus touches structure, boundaries, or +data flow. Read `context/patterns.md` when it touches conventions the change must +follow. + +A missing entry point is a gap, not a failure. Record it and continue. + +## 1.3 Select the relevant domain context + +Consult `context/context-map.md` before any broad exploration. The map's +annotations name what each domain file owns; use them to select files, rather +than globbing or searching `context/`. + +Select only files whose subject overlaps the focus. Follow at most one level of +links out of a selected file, and only when the link is needed to understand the +focus. + +Do not read every domain file. A brief that includes everything has selected +nothing. + +Record focus areas with no matching context file under `gaps`. + +## 1.4 Check recorded context against the code + +For each selected file, spot-check its central claims against the code it +describes. + +When context and code diverge, the code is the source of truth. Record the +divergence under `drift` with what context says, what the code shows, and the +repair the context needs. + +Do not repair it here. Later phases decide whether repair belongs in the current +work. + +Keep this proportional: check the claims the focus depends on, not every +sentence. + +## 1.5 Return the brief + +Set exactly one internal state: + +- `loaded` +- `bootstrap_required` + +Report facts the workflow can act on. A brief that only lists file paths has +moved no knowledge. + +Record only the internal state. Do not add explanatory prose before or after it. + +Step 2 consumes a `loaded` brief verbatim and treats its `key_facts` as recorded +current state, its `gaps` as areas with no durable context, and its `drift` as +context the code has already outrun. + +## Context load boundaries + +Do not: + +- Create, update, move, or delete any file under `context/`. +- Bootstrap `context/`. +- Repair drift or stale context. +- Modify application code or tests. +- Read the entire `context/` tree by default. +- Explore the repository beyond what the focus and the selected context require. +- Ask the user questions. Report gaps and drift, and let the workflow decide. +- Author a plan, select a task, or implement anything. +""" + +changeToPlanPlanAuthoring = """ +# Plan authoring phase + +Run this phase for step 2 of the workflow, and again for each revision in step 4. + +Input: the change request, and the complete `loaded` brief from the context load +phase. Pass the brief verbatim; do not restate, summarize, or reinterpret it. + +This phase exclusively owns: + +- Resolving whether the request targets a new or an existing plan. +- The clarification gate. +- Normalizing the change summary, acceptance criteria, constraints, and non-goals. +- Slicing the task stack into one-task/one-atomic-commit units. +- Writing `context/plans/{plan_name}.md`. + +Do not duplicate any of it elsewhere in the workflow. + +Use the document format in `references/plan-template.md`. Read it before writing +the plan file. + +The workflow renders this phase's result as the summary defined in +`references/output.md`. + +The change request may name a plan, describe a change to an existing plan, or +describe entirely new work. Resolving which applies is this phase's +responsibility. + +The context brief is the durable memory this plan starts from. Treat its +`key_facts` as recorded current state, its `gaps` as areas with no durable +context, and its `drift` as context the code has already outrun. + +When no brief is supplied, load the context named by the change request before +authoring, and follow the selection discipline in *Inspect relevant context*. + +Answers the user gave to earlier clarification questions arrive as part of the +change request. Incorporate them into the plan. + +A revision of a plan authored earlier in the session also arrives as the change +request, and it is usually terse: a task boundary the user disagrees with, an +ordering they want changed, work they want added or dropped. Read it against the +existing plan, which supplies the scope, criteria, and terminology it omits. +Terseness is not ambiguity. Do not set internal status `needs_clarification` for +detail the plan already carries; ask only when the revision itself is genuinely +undecidable. + +## 2.1 Resolve the plan target + +Determine whether the request targets a new plan or an existing plan in +`context/plans/`. + +When it targets an existing plan, read that plan before authoring. Preserve its +completed tasks, their recorded evidence, its structure, and its terminology. + +When multiple existing plans match and none can be selected safely, return +`blocked` with the matching candidates. + +When the request targets a new plan, derive `plan_name` as a short kebab-case +slug of the change, and confirm it does not collide with an existing plan. + +Resolve exactly one plan target per invocation. + +## 2.2 Challenge the change + +Before planning how to build the change, work out whether it is worth building. A +plan is a commitment of someone's time; authoring one for work that should not +happen is worse than authoring none. + +Interrogate the request: + +- What breaks, or stays broken, if this is never built? If the answer is nothing + concrete, say so. +- What problem is it actually solving, as opposed to what it proposes to do? A + request that names only a solution has not stated a problem. +- Does the repository already do this, or most of it? The brief's `key_facts` are + the first place to check. +- Is there a materially smaller version that gets most of the value? Name it. +- What does this cost beyond the tasks: new dependency, new concept in the + glossary, a boundary crossed, a surface that now needs maintaining forever? +- Does the stated justification survive contact with the code, or does the code + show the premise is already false? + +Doubt that survives this is not an implementation detail to be tidied away. It +belongs in the plan's `Open questions` and in `open_questions`, in the plain +words you would use to a colleague. "Is this worth doing at all, given X?" is a +legitimate open question. So is "this looks like it duplicates Y". + +Weigh honestly in both directions. A request that is obviously worth building +gets no manufactured doubt: inventing questions to look rigorous is its own +failure, and it teaches the user to ignore the section. Most changes are fine. +Say nothing when there is nothing to say. + +Keep going regardless. Skepticism shapes the plan and the open questions; it does +not withhold the plan. The only value judgment that stops authoring is +`no_actionable_work`, when the change is already implemented. + +## 2.3 Run the clarification gate + +Before writing or updating any plan file, check the request for critical +unresolved detail: + +- Scope boundaries and out-of-scope items. +- Acceptance criteria and the checks that prove them. +- Constraints and non-goals. +- Dependency choices, including new libraries or services, versions, and the + integration approach. +- Domain ambiguity, including unclear business rules, terminology, or ownership. +- Architecture concerns, including patterns, interfaces, data flow, migration + strategy, and risk tradeoffs. +- Task ordering assumptions and prerequisite sequencing. + +Set internal status `needs_clarification` with one to three targeted questions +when any of these would materially change the plan. Write no plan file in that +case. + +Use repository conventions for ordinary local choices. Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change scope, acceptance criteria, or task ordering. + +Record those choices under `assumptions`. + +Do not silently invent missing requirements. When the user has explicitly allowed +assumptions, record them in the plan's `Assumptions` section instead of asking. + +A justification that does not survive inspection is itself a critical unresolved +detail. "For consistency", "to make it cleaner", "we will need it later" name no +outcome and prove nothing; ask what the change is actually for before planning +around it. Do not treat confident phrasing as evidence. + +## 2.4 Inspect relevant context + +Start from the context brief. Read code only where the brief leaves the change +underspecified: + +- Existing behavior the change affects. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests and available verification commands. +- Decisions or specifications connected to the change. + +Where the brief reports `drift`, the code is the source of truth. Plan against +the code, and schedule the context repair as part of the change when it falls +inside scope. + +Where the brief reports `gaps`, the plan may need to establish durable context +the repository does not yet have. + +Do not explore the entire repository by default. + +## 2.5 Author the acceptance criteria + +State how the finished plan is proven, before slicing tasks. + +Each criterion describes observable behavior of the finished system and names the +check that proves it. Record repository-wide checks once under `Full validation`, +and the durable context the change must be reflected in under `Context sync`. + +`/validate` runs this section after the last task completes. It is the only place +a plan says how it is validated. + +## 2.6 Author the task stack + +Slice the work into sequential tasks `T01..T0N` using the task format and the +atomic slicing contract in `references/plan-template.md`. + +Every executable task must be completable and landable as one coherent commit. +Split any task that would require multiple independent commits. Convert broad +wrappers such as `polish` or `finalize` into specific outcomes with concrete +acceptance checks. + +Order tasks so each one's declared dependencies precede it. + +The last task is an ordinary implementation task. Do not author a trailing +validation-and-cleanup task, or any task whose only purpose is running the full +check suite, verifying durable context, or removing scaffolding. + +Confirm every acceptance criterion is satisfied by at least one task. When one is +not, the task stack is incomplete. + +A finished stack always leaves at least one incomplete task, so the workflow can +always hand off to `/next-task`. When the request resolves to a plan but produces +no incomplete task, because the change is already implemented or already covered +by completed tasks, set internal status `blocked` with category +`no_actionable_work` instead of writing the plan. + +## 2.7 Write the plan + +Write `context/plans/{plan_name}.md` using `references/plan-template.md`. + +When updating an existing plan, keep completed tasks and their evidence intact, +and append or renumber new tasks without disturbing recorded history. + +## 2.8 Return the result + +Set exactly one internal state: + +- `plan_ready` +- `needs_clarification` +- `blocked` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `plan_ready` result always names the next task in `next_task`, and carries the +`total_tasks` count and any open questions the summary needs. Step 3 renders those +without recomputing them. + +## Plan authoring tone + +Every question and open question this phase writes is read by the user. Write +them the way a senior engineer talks in review: direct, specific, and unbothered +by the possibility of being unwelcome. + +- Ask about the thing that actually worries you, not a safer neighbouring thing. + A question you would not bother asking a colleague is not worth the user's + attention either. +- State a doubt as a doubt. "I do not think this is worth the two tasks it + costs, because X" is useful. "It may be worth considering whether this aligns + with broader goals" is noise. +- Name the alternative you have in mind. A challenge with no proposal behind it + is just friction. +- Do not open with praise, do not close with reassurance, and do not apologize + for asking. Do not pad a doubt with hedges to make it land more gently. +- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not + restate the same doubt in three shapes to give it more weight. +- Being disagreeable is not the goal. Being easy to agree with is the failure + mode. A plan the user waves through without reading has cost them nothing and + bought them nothing. + +When the user overrules a doubt, record it and move on. Do not relitigate a +decision the user has made, and do not smuggle the objection back in as a +constraint, a non-goal, or a task. + +## Plan authoring boundaries + +Do not: + +- Ask the user questions directly. Set internal status `needs_clarification` and let the + workflow present the questions. +- Answer your own clarification questions. +- Write a plan file when returning `needs_clarification` or `blocked`. +- Implement any task in the plan. +- Modify application code or tests. +- Modify any file under `context/` outside `context/plans/`. Plan the context + repair instead of performing it. +- Mark any task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Author a validation, cleanup, or context-verification task. `/validate` owns + that phase. +- Set internal status `plan_ready` for a plan with no incomplete task. +- Create a Git commit. +- Author more than one plan. +""" + +changeToPlanPlanTemplate = """ +# Internal persisted-document format: Plan template + +The document format for `context/plans/{plan_name}.md`. This is the plan file +written to disk, not the result returned to the workflow. + +Copy the template below and fill every `{placeholder}`. Omit optional sections +entirely rather than writing them empty. + +--- + +## Template + +```markdown +# Plan: {plan-name} + +## Change summary + +{One or two paragraphs: what changes, where, and why. State whether this +extends existing behavior, replaces it, or preserves work already in progress.} + +## Acceptance criteria + +How this plan is proven complete. Each criterion is observable and names the +check that proves it. `/validate` runs these checks; no task in the stack +performs final validation. + +- [ ] AC1: {observable outcome, stated as behavior rather than as work done} + - Validate: `{command, assertion, or inspection that proves AC1}` +- [ ] AC2: {observable outcome} + - Validate: `{command, assertion, or inspection that proves AC2}` + +### Full validation + +Repository-wide checks `/validate` runs after the last task, regardless of +which criterion they map to. + +- `{full check suite command}` +- `{generated-output or parity check command, when applicable}` + +### Context sync + +- {Durable context files that must describe the change once implemented.} + +## Constraints and non-goals + +- **In scope:** {files, modules, and surfaces this plan may touch} +- **Out of scope:** {adjacent work explicitly excluded} +- **Constraints:** {dependencies, conventions, compatibility, or policy limits} +- **Non-goal:** {tempting generalization this plan deliberately avoids} + +## Assumptions + +{Include only when the user allowed assumptions, or ordinary local choices were +recorded. Remove the section otherwise.} + +- {Assumption, and the convention or decision record it rests on.} + +## Task stack + +- [ ] T01: `{single intent title}` (status:todo) + - Task ID: T01 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: {task IDs, or none} + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +- [ ] T02: `{single intent title}` (status:todo) + - Task ID: T02 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: T01 + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +## Open questions + +{Non-blocking questions only. A question that would change scope, success +criteria, or task ordering blocks authoring instead. Write `None.` with a short +justification when nothing remains.} + +{Unresolved doubt about the change's value belongs here — whether it is worth +building, whether it duplicates behavior the repository already has, whether a +smaller version would do. State it plainly and name the alternative. Do not +invent one: `None.` is the expected answer for a well-specified change.} +``` + +--- + +## Filled-in task example + +```markdown +- [ ] T02: `Add /auth/refresh endpoint` (status:todo) + - Task ID: T02 + - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. + - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. + - Dependencies: T01 + - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. + - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. +``` + +## Acceptance criteria rules + +- Acceptance criteria describe the finished system, not the work. Prefer "the + endpoint returns 401 on an expired token" over "add expiry handling". +- Every criterion carries a `Validate:` line. A criterion nobody can check is + not an acceptance criterion. +- Prefer a runnable command. Fall back to a named inspection only when no + automated check exists, and say exactly what to look at. +- List repository-wide checks once under `Full validation` instead of repeating + them per criterion. +- Task-level `Verification notes` prove one task. Acceptance criteria prove the + plan. Keep them distinct: a task's checks are narrow and local, a criterion's + check is end-to-end. +- The union of the acceptance criteria must cover every success signal in the + change request. If a criterion has no task that could satisfy it, the task + stack is incomplete. + +## Task rules + +- Every task is a checkbox line so progress stays machine-readable: + `- [ ] T01: {title} (status:todo)`. +- Author each executable task as one atomic commit unit by default. +- Scope every task so one contributor can complete it and land it as one + coherent commit without bundling unrelated changes. +- Split any candidate task that would require multiple independent commits, for + example a refactor plus a behavior change plus documentation. +- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of + executable tasks. Convert them into specific outcomes with concrete + acceptance checks. +- Order tasks so each one's declared dependencies precede it. + +## No validation task + +- The last task in the stack is an ordinary implementation task. Do not author a + trailing "validation and cleanup" task. +- Final validation, cleanup, and success-criteria verification are run by + `/validate` from the `Acceptance criteria` section after the last task + completes. +- Do not author a task whose only purpose is running the full check suite, + verifying durable context, or removing scaffolding. +- A task may still create or update durable context when that context is part of + the change itself. + +## Completion records + +When a task completes, the **Task execution phase** appends its evidence and flips the +checkbox and status: + +```markdown +- [x] T01: `{title}` (status:done) + - {authored fields, unchanged} + - Completed: {YYYY-MM-DD} + - Files changed: {paths} + - Evidence: {commands run and their outcomes} + - Notes: {material deviations or approved assumptions} +``` + +`/validate` appends a `## Validation Report` section at the end of the plan. +Do not author either while planning. + +## Updating an existing plan + +- Preserve completed tasks, their `(status:done)` markers, and their recorded + evidence verbatim. +- Preserve the plan's existing structure and terminology. +- Append new tasks after the existing stack. Renumber only when added work must + run earlier, and never renumber a completed task. +- Add acceptance criteria for newly planned outcomes rather than rewriting + criteria already satisfied. +""" + +changeToPlanOutput = """ +# Change-to-plan output layouts + +Use only the applicable layout. Values come from internal workflow state. + +## Missing context bootstrap gate + +```markdown +------------------------------------- + +# This repository has no durable context. + +Bootstrap it, then continue in this session: + +`sce setup --bootstrap-context` +``` + +## Clarification gate + +```markdown +------------------------------------- + +# Clarification needed. + +No plan was written. + +Answer each question below.\(" ") + +## {question-id} · {category} + +{question} + +Why this blocks planning: {why_blocking} +``` + +## Blocked + +Present each issue's problem, impact, and required decision. For ambiguity, list +candidate plan paths and explain that naming one candidate resolves it. + +## Ready continuation + +```markdown +------------------------------------- + +# Plan {plan-name} is ready. + +{total-tasks} {task|tasks} planned. + +This plan is a draft. State a correction and it will be updated. + +Next up: + +{next-task-id} — {next-task-title} + +`/next-task {plan-path} {next-task-id}` +``` + +For revisions, replace `is ready` with `revised`. + +# SCE Plan Summary + +The user-facing summary shown after a plan is written. It is rendered from +the `plan_ready` result, immediately before the continuation block. + +This is chat output, not a file. Nothing here is written to the plan. + +## Layout + +``` +# Plan: {plan.name} + +Path: {plan.path} + +## Summary: +{plan summary} + +## Tasks: +1. {task.id} — {task.title} +2. {task.id} — {task.title} + +## Assumptions: +- {assumption} + +## Open questions: +- {open question} +``` + +## Field mapping + +Every value comes from the `plan_ready` result. Render nothing the result does +not carry. + +- `Plan:` — `plan.name`. Append ` (updated)` when `plan.action` is `updated`. + Render nothing extra when it is `created`. +- `Path:` — `plan.path`, exactly as returned, so it stays runnable. +- `Summary:` — `summary`, as prose. This is the only place the reader learns + what the plan actually does, so never omit it and never replace it with a + restatement of the task titles. +- `Tasks:` — one numbered line per entry in `tasks`, in plan order. Append + ` (done)` to any task whose `status` is `done`. +- `Assumptions:` — one line per entry in `assumptions`. +- `Open questions:` — one line per entry in `open_questions`. + +## Empty sections + +Never drop a section heading. An absent section reads as an oversight; an +explicit `None.` confirms nothing is pending. + +When `assumptions` is empty: + +``` +## Assumptions: +- None. +``` + +When `open_questions` is absent: + +``` +## Open questions: +- None. +``` + +## Rules + +- Render the sections in the order above. +- Keep task titles as authored. Do not reword, expand, or re-scope them. +- Do not restate goals, boundaries, done checks, or verification notes. The plan + file owns task detail; this summary orients the reader. +- Do not print the raw result, and do not wrap the summary in a code fence. +- Do not add commentary, recommendations, or a next step. The continuation block + that follows owns the handoff. + +## Example + +``` +# Plan: red-sce-banner + +Path: context/plans/red-sce-banner.md + +## Summary: +Renders the ASCII-art SCE banner at the top of `sce` help in red instead of the current gradient. Colour-disabled output is unchanged, and no other help surface is affected. + +## Tasks: +1. T01 — Render the SCE banner in red + +## Assumptions: +- "SCE letters" refers to the ASCII-art banner in top-level help. +- Red is uniform terminal red when colors are enabled; plain ASCII remains unchanged otherwise. + +## Open questions: +- None. +``` +""" + +nextTaskSkillBody = """ +# SCE Next Task + +## Purpose + +Own this workflow from input parsing through its terminal user-visible response. +Execute the phases below directly and in order. Phase statuses are internal state, +not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or +workflow command except `sce-decision`, and invoke `sce-decision` only from the +successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, +and stops exactly as written: never invent, skip, reorder, or merge a step. + +## Phase references + +Each numbered step below dispatches to a phase whose steps, gates, and boundaries +live in a reference file. This document holds the control flow — which phase runs, +what it receives, and how its result branches — and each reference holds the phase +itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/plan-review.md` | +| 2 | `references/task-execution.md` | +| 3 | `references/context-sync.md` | + +Read a step's reference before taking any action for that step, not after. The +references carry gates that must fire before their phase's first side effect, so a +phase begun from this summary alone will already have skipped them. Read only the +reference for the step you have reached: a run that stops at step 1 never needs the +other two, which is why they are separate files. + +## User-visible output + +Use `references/output.md` for every gate and terminal response. Render no raw +internal state. The reference contains only human-visible Markdown layouts. +User-visible output is limited to those layouts: never invent a layout, and never +wrap one in an added preamble, commentary, summary, or extra section. + +## Composite control flow + +Keep phase results as internal state and continue immediately whenever the +canonical workflow says to continue. Stop only at a user wait or terminal branch. +Approval, clarification, revision, failed-validation repair, and bootstrap waits +resume this same skill in the same session. Never expose an internal phase result +as the workflow's final response. + +## Input + +Parse `$ARGUMENTS` into three positional parts before invoking any phase: + + [task-id] [auto-approve] + +- `plan-name-or-path` is required. +- `task-id` is optional. It is present only when the token matches a task ID (`T01`, `T02`, ...). +- `auto-approve` is optional. It is present only when the token is exactly `approved`. + +Resolve `auto-approve` even when `task-id` is absent. + +A token matching neither a task ID nor `approved` is an error. Report the unrecognized token and the expected arguments, and stop. Do not guess its meaning. + +Pass each part only to the phase that owns it. Do not forward the raw `$ARGUMENTS` string to a phase. + +Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is the path resolved in step 1 (`plan.path`, or an entry of `candidates`), so every emitted command is directly runnable. + +## Workflow + +### 1. Review the task + +Read `references/plan-review.md`, then run the **Plan review phase** with the +parsed `plan-name-or-path` and, when present, the parsed `task-id`. + +Do not pass the `auto-approve` token to the **Plan review phase**. + +Branch on `status`: + +`blocked` -> Do not run implementation. Render the **Review blocked** layout from `references/output.md`. When `candidates` is present the plan could not be resolved, and each entry is a candidate path for `/next-task {candidate-path}`. `executable_tasks_remaining` true means another task remains executable and `/next-task {plan-path} {task-id}` selects one; false means no task in the plan can proceed until the plan is updated. Do not print the raw result. Stop. + +`plan_complete` -> Render the **Plan already complete** layout from `references/output.md`. Stop. + +`ready` -> Pass the complete readiness result to the **Task execution phase**. + +Do not reconstruct, summarize, or reinterpret the reviewed task before passing it. + +### 2. Execute the task + +Read `references/task-execution.md`, then run the **Task execution phase** with +the complete `ready` result from the **Plan review phase**. + +This phase always shows an implementation gate before it modifies any file, and it +is the only phase permitted to ask the user for confirmation. Both properties are +load-bearing, so reach them through the reference rather than acting from this +summary. + +Branch on `auto-approve`: + +`approved` -> Also pass the `approve` flag. The **Task execution phase** then shows its implementation gate as a summary and proceeds without asking. + +else -> Do not pass the `approve` flag. The **Task execution phase** shows its implementation gate and waits for the user's decision. + +Do not present an additional implementation confirmation. + +Branch on the execution result. + +`declined` -> Render the **Declined** layout from `references/output.md`. Do not run context synchronization. Stop. + +`blocked` -> Render the **Execution blocked or incomplete** layout from `references/output.md`. Do not run context synchronization. Stop. + +`incomplete` -> Render the same **Execution blocked or incomplete** layout. Do not run context synchronization. Do not select another task. Stop. + +`complete` -> continue to the next step. + +### 3. Synchronize context + +Read `references/context-sync.md`, then run the **Task context synchronization +phase** with the complete `complete` result returned by the **Task execution +phase**. + +Pass that result verbatim. It is the authoritative handoff, and the **Task context synchronization phase** owns reading the plan, task, changed files, verification evidence, and reported context impact out of it. + +Do not restate, summarize, or reconstruct any part of the execution result. + +This phase verifies the five root context files on every invocation, whatever the +change's reported impact, so it is never correct to skip it as unnecessary. + +Branch on the synchronization result. + +`blocked` -> The task itself succeeded and is already marked complete in the plan. Render the **Context synchronization blocked** layout from `references/output.md`. Nothing records the skipped synchronization, so it is lost once this session ends. + +Do not select another task. Stop. + +`synced` | `no_context_change` -> Print out the report the **Task context synchronization phase** returned. Continue to the next step. + +### 4. Determine the continuation + +Use `plan.completed_tasks` and `plan.total_tasks` from the execution result to determine which continuation applies. + +Do not execute another task. Return exactly one continuation. + +If incomplete tasks remain, read the plan and name the first unchecked task in plan order. Do not evaluate its dependencies; the **Plan review phase** checks them when the emitted command runs and returns `blocked` if they are unmet. + +Render the **More tasks remain** layout from `references/output.md`. + +If all tasks are completed, render the **All tasks complete** layout instead. + +Stop. + +## Rules + +- Execute at most one plan task per invocation. +- Review at most one task. +- Read each phase's reference before running that phase. +- Do not duplicate the internal instructions of embedded phases. +- The only permitted sibling-skill invocation is `sce-decision`, and only the + successful context-synchronization decision gate may invoke it. +- Do not ask for implementation confirmation outside "Task execution phase". +- Do not run full-plan validation. +- Do not mark the plan complete. +- Do not execute the continuation returned at the end. +- Do not infer success when an embedded phase returns a non-success status. +- Preserve completed work and evidence when a later phase fails. +""" + +nextTaskPlanReview = """ +# Plan review phase + +Run this phase for step 1 of the workflow. It resolves one plan, selects one +task, and decides whether that task can be implemented right now. It reads; it +never writes. + +Inputs: the parsed `plan-name-or-path`, and `task-id` when present. The +`auto-approve` token is not passed here and has no meaning in this phase. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Resolve one task + +When a task ID is supplied, select that task. + +Otherwise, select the first incomplete task in plan order whose declared +dependencies are complete. + +Set internal status `plan_complete` when no incomplete tasks remain. + +Set internal status `blocked` when incomplete tasks remain but none can currently +be executed. + +Review at most one task per invocation. + +## 1.3 Inspect relevant context + +Start with the task and the files it directly references. + +Inspect only what is needed to understand: + +- Existing behavior. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests. +- Available verification commands. +- Decisions or specifications connected to the task. + +Load root context only when the task affects repository-wide behavior, +architecture, shared terminology, or cross-domain interfaces. + +Do not explore the entire repository by default. + +## 1.4 Determine readiness + +A task is `ready` when: + +- Its goal is clear. +- Its scope is sufficiently bounded. +- Its dependencies are complete. +- Its done checks are observable. +- A credible verification method exists. +- No unresolved decision would materially change the implementation. + +Use repository conventions for ordinary local choices. + +Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change observable behavior or scope. + +Record these choices under `assumptions`. + +Set internal status `blocked` when a missing decision materially affects: + +- User-visible behavior. +- Public interfaces. +- Architecture or ownership boundaries. +- Data shape or persistence. +- Security or privacy. +- External dependencies. +- Destructive or difficult-to-reverse behavior. +- The evidence needed to prove completion. + +## 1.5 Return the result + +Set exactly one internal state: + +- `ready` +- `blocked` +- `plan_complete` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `ready` result must identify: + +- One resolved plan. +- Exactly one incomplete task. +- The task goal and scope boundaries. +- Done checks. +- Verification expectations. +- Relevant files and context. +- Review assumptions. + +Step 2 consumes this result verbatim, so anything the execution phase needs has +to be present here. + +## Plan review boundaries + +Do not: + +- Modify application code. +- Modify tests. +- Update the plan. +- Mark the task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Review more than one task. +""" + +nextTaskTaskExecution = """ +# Task execution phase + +Run this phase for step 2 of the workflow. It is the only phase that writes +application code, and the only one that asks the user for anything. + +Input: the complete `ready` result from the plan review phase, plus the `approve` +flag when the user pre-approved this invocation. + +This phase exclusively owns: + +- Presenting the implementation summary. +- Requesting implementation confirmation. +- Implementing the task. +- Running task-level verification. +- Updating the task status and evidence. + +Do not present an additional implementation confirmation anywhere else. + +The `approve` flag means the user pre-approved this task when invoking the +workflow. It suppresses the approval question and the wait. It never suppresses +the gate. Only the workflow entrypoint may set it, and only from an explicit +user-supplied approval token. Never infer it. + +If required handoff information is absent or stale, still show the gate using +what is known, clearly identify the handoff problem, and do not edit files. After +the user responds, set internal status `blocked`. + +## 2.1 Validate the handoff without editing + +Confirm that: + +- The readiness status is `ready`. +- Exactly one task is present. +- The plan file exists. +- The selected task is still incomplete. +- The task has not materially changed since review. +- Declared dependencies remain complete. + +Do not reconstruct missing material requirements. + +## 2.2 Always show the implementation gate + +At the start of the phase, before any file modification, present the task using +`references/output.md`. + +The gate must be shown even when: + +- The task appears straightforward. +- The workflow believes approval was already implied. +- The handoff is stale or incomplete. +- The user is likely to approve. + +When the `approve` flag is absent, end the gate with exactly one approval +question: + +`Continue with implementation now? (yes/no)` + +Stop and wait for the user's answer. Do not return internal state, and make no +file modifications, until the user has answered. + +When the `approve` flag is supplied, show the gate as a summary, omit the +approval question, do not wait, and continue at step 2.4. + +## 2.3 Handle the user's decision + +Skip this step when the `approve` flag was supplied. + +When the user rejects or cancels, do not modify files and set internal status +`declined`. + +When the user does not clearly approve, do not modify files. Ask the same +approval question once more only when the response is genuinely ambiguous. +Otherwise set internal status `blocked`. + +When the user approves, continue with implementation. + +Treat constraints supplied with approval as part of the approved task boundary. +If those constraints materially contradict the reviewed task, set internal status +`blocked` before editing. + +## 2.4 Prepare the implementation + +Before editing: + +- Read the relevant files supplied by plan review. +- Inspect nearby code and tests when needed. +- Identify the smallest coherent change satisfying the task. +- Follow surrounding naming, structure, error handling, and test style. +- Preserve unrelated behavior. + +Do not create a second plan. + +Do not broaden the reviewed task. + +## 2.5 Implement one task + +Make the minimum coherent changes required to satisfy the task goal and done +checks. + +Use judgment for ordinary, reversible local implementation choices. + +Stop when implementation requires: + +- Material scope expansion. +- A new external dependency not authorized by the task. +- A public-interface decision not established by the plan. +- A destructive or difficult-to-reverse operation. +- An unresolved security, privacy, or data decision. +- Contradicting the reviewed task or repository architecture. + +When stopped, preserve completed in-scope work unless retaining it would leave +the repository unsafe or invalid. + +## 2.6 Verify the task + +Run the narrowest authoritative checks that demonstrate the done checks. + +Start with verification supplied by the readiness result. Add nearby or directly +relevant checks only when needed. + +Verification may include: + +- Targeted tests. +- Type checking for affected code. +- Linting affected files. +- Formatting checks. +- A focused build or compile step. +- Direct behavioral inspection when no automated check exists. + +Do not run final plan validation unless the task itself explicitly requires it. + +When a check fails: + +- Determine whether the task caused the failure. +- Fix it when the correction remains in scope. +- Rerun the relevant check. +- Set internal status `incomplete` when a done check remains unsatisfied, or + `blocked` when completing it requires an unapproved decision or scope + expansion. + +Never report a check as passed unless it ran successfully. + +## 2.7 Update the plan + +Only after successful implementation and task-level verification: + +- Mark only the selected task complete. +- Record concise implementation evidence. +- Record verification commands and outcomes. +- Record material deviations or approved assumptions. +- Preserve the plan's existing structure and terminology. + +Do not mark the task complete when returning `declined`, `blocked`, or +`incomplete`. + +## 2.8 Determine the terminal status + +Set internal status `complete` when the task was implemented, verified, and +marked complete in the plan with evidence. + +Set internal status `incomplete` when in-scope work was completed but one or more +done checks remain unsatisfied. + +Set internal status `declined` when the user rejected implementation. + +Set internal status `blocked` for every other non-successful outcome, including: + +- Missing approval. +- Stale or invalid handoff. +- Material blocker. +- A verification failure that cannot be resolved in scope. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## 2.9 Return internal state + +After the phase reaches a terminal state, set exactly one internal state. + +Record only the internal state. Do not add explanatory prose before or after it. + +A `complete` result is the authoritative handoff into step 3, which reads the +plan, completed task, changed files, implementation summary, verification +evidence, done-check evidence, and context-impact classification out of it. Step +3 is forbidden from reconstructing any of that, so it has to be present here. + +## Task execution boundaries + +Do not: + +- Edit before approval, whether explicit or pre-supplied. +- Execute more than one task. +- Select or execute the next task. +- Skip the implementation gate. +- Ask for multiple approval gates for the same unchanged task. +- Expand scope without authorization. +- Synchronize durable context. +- Run final plan validation. +- Determine whether the plan is complete. +- Create a Git commit. +- Push changes. +- Modify unrelated files. +- Claim verification that was not performed. +""" + +nextTaskContextSync = """ +# Task context synchronization phase + +Run this phase for step 3 of the workflow, and only when task execution returned +`complete`. It updates durable repository knowledge in `context/` so the next +session inherits what this task established. It never touches code, tests, or +plan state. + +Input: the complete `complete` result from the task execution phase, passed +verbatim. It is the authoritative handoff, and this phase owns reading the plan, +task, changed files, verification evidence, and reported context impact out of +it. + +Do not restate, summarize, or reconstruct any part of the execution result. Do +not reconstruct a missing execution result from conversation history. + +The execution result must have: + +```text +status: complete +``` + +Treat the execution result as the authoritative handoff for: + +- The resolved plan and completed task. +- Files changed by implementation. +- Implementation summary. +- Verification evidence. +- Done-check evidence. +- Reported context impact. + +This phase must not be run for `declined`, `blocked`, or `incomplete` execution +results. + +## 3.1 Validate the execution handoff + +Confirm that: + +- `status` is exactly `complete`. +- A `plan` object with a `path` is present. +- Exactly one completed task is identified. +- Changed files and an implementation summary are present. +- Verification evidence is present. +- Done-check evidence is present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 3.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that the task itself is complete and recorded in the plan, and that +synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 3.3 Discover applicable context + +Start with the execution result: + +- `context_impact.classification` +- `context_impact.affected_areas` +- Changed files. +- Implementation summary. +- Done-check evidence. + +Then inspect existing repository context in this order when present: + +1. `context/context-map.md` +2. Context files for the affected domain or subsystem +3. `context/overview.md` +4. `context/architecture.md` +5. `context/glossary.md` +6. `context/patterns.md` +7. Operational, product, or decision records directly related to the change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +completed implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +## 3.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in task evidence. +- Speculation or future work not established by the completed implementation. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass. + +- `none`: Make no edits beyond any correction the root pass turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +A change is `root` when it introduces cross-cutting behavior, repository-wide +policy or contracts, an architecture or ownership boundary, or a change to +canonical terminology. A change confined to one feature or domain, with no +repository-wide behavior, architecture, or terminology impact, is `domain` or +`local`: capture its detail in domain files and leave the root files unedited. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 3.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- execution and done-check evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task + references, related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 3.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the implementation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the completed implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the execution result verbatim into context files. +- Do not change application code, tests, or plan state. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the completed task implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the task implemented a feature no context file describes, add that +description. A feature that fits no existing domain file gets a new focused file; +do not defer it to a later task. Prefer a small, precise domain file over +overloading `overview.md` with detail. + +This is the one case where documentation is warranted by the change itself rather +than by a gap in durable knowledge. It is not license to narrate the diff: +describe what the feature is and how it behaves, not what was edited. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the task introduced. +New terminology is durable knowledge whatever the classification is: a `domain` +change that names a new concept still earns its glossary entry. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 3.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the completed implementation. +- No edited statement contradicts the code, plan, or execution evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Each feature implemented by the task has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not run full application or plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 3.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## Task context synchronization boundaries + +Do not: + +- Accept an execution result whose status is not `complete`. +- Implement or modify application code. +- Modify tests. +- Change task completion status or plan evidence. +- Determine whether the plan is complete. +- Select or execute another task. +- Run full-plan validation. +- Mark the plan validated, closed, or archived. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return an execution-style internal state. +""" + +nextTaskOutput = """ +# Next-task output layouts + +Use only the applicable layout. Values come from internal workflow state. + +## Review blocked + +Present the selected task, then each issue's problem, impact, and required +decision. If plan resolution is ambiguous, list candidate paths and +`/next-task {candidate-path}`. State whether another task remains executable. + +## Plan already complete + +```markdown +------------------------------------- + +# Implementation tasks are complete. + +Run the final validation: + +`/validate {plan-path}` +``` + +## Declined + +```markdown +You have declined to proceed with this task +``` + +## Execution blocked or incomplete + +For `blocked`, present the blocker, work completed before it, and the required +decision or action. For `incomplete`, present completed work, verification +evidence, remaining work, and the reason it remains incomplete. + +## Context synchronization blocked + +State that task `{completed-task-id}` was implemented, verified, and recorded; +report the contradiction or synchronization failure, preserved edits, required +action, and retry condition. State that durable context is out of date and must +be synchronized before continuing. + +## More tasks remain + +```markdown +------------------------------------- + +# Task {completed-task-id} completed. + +{completed-tasks} of {total-tasks} tasks complete. + +Next up: + +{next-task-id} — {next-task-title} + +`/next-task {plan-path} {next-task-id}` +``` + +## All tasks complete + +```markdown +------------------------------------- + +# Task {completed-task-id} completed. + +All tasks are complete. + +Run the final validation: + +`/validate {plan-path}` +``` + +# Implementation gate + +Always show this gate at the start of the **Task execution phase**, before editing any +file. + +The gate is user-facing prose. It is never serialized into a YAML result. This +file is the only authority for the gate's content and order. + +## Format + +# `{task.id} - {task.title} - {plan.name}` + +## Goal + +{task.goal} + +## In scope + +- {task.in_scope} + +## Out of scope + +- {task.out_of_scope} + +## Done when + +- {task.done_checks} + +## Expected changes + +- List confirmed files or areas expected to change. +- Label uncertain entries as likely rather than confirmed. + +## Approach + +Describe the smallest coherent implementation approach in 2–5 steps. + +## Assumptions + +- Include material assumptions returned by plan review. +- Omit this section when there are no assumptions. + +## Risks or trade-offs + +- Include only risks relevant to approving this task. +- Omit this section when there are no meaningful risks. + +## Verification + +- {task.verification} + +When the `approve` flag is absent, end with exactly: + +`Continue with implementation now? (yes/no)` + +When the `approve` flag is supplied, omit the question and end after +**Verification**. + +## Rules + +- Show the gate exactly once for an unchanged task. +- Do not modify files before approval. +- Do not add requirements absent from the reviewed task. +- Do not present multiple competing approaches unless a material decision is + required. +- Do not emit YAML while waiting for the user's answer. Stop after the gate and + wait. +- If the handoff is stale or incomplete, show the known task information and + identify the problem under **Risks or trade-offs**. + +# Context Sync Report + +Return only one completed Markdown report using the applicable variant below. +Do not include unused sections, placeholders, YAML, or a fenced code block. + +The `Status` value must be exactly one of: + +- `synced` +- `no_context_change` +- `blocked` + +The input execution status is always `complete` and does not need to be repeated +as a separate workflow state. + +## Synced variant + +# Context Sync Report + +**Status:** synced\(" ") +**Plan:** `{plan path}`\(" ") +**Task:** `{task id} — {task title}` + +## Updated files + +- {List each changed file from the execution handoff except paths under + `context/`; state `None.` when no files remain.} + +## Updated context + +- `{context file}` — {concise description of the durable truth updated} + +## Architecture decisions + +- `{written or reused ADR path}` — {decision and status} +- None qualified. + +## Feature existence + +- `{feature}` — `{context file that canonically describes it}` + +## Verification + +- {How the edited context was checked against implementation and execution evidence.} +- {File hygiene: line counts, relative links, diagrams where structure is complex.} +- {Documentation, link, or formatting checks that were run, when applicable.} + +## Notes + +{Include only non-blocking information worth retaining. +Omit this section when unnecessary.} + +--- + +## No-context-change variant + +# Context Sync Report + +**Status:** no_context_change\(" ") +**Plan:** `{plan path}`\(" ") +**Task:** `{task id} — {task title}` + +## Updated files + +- {List each changed file from the execution handoff except paths under + `context/`; state `None.` when no files remain.} + +## Synchronization result + +{Explain why the completed implementation did not introduce durable, +non-obvious repository knowledge requiring an update.} + +## Context reviewed + +- `{context file or area}` — {what was checked and why it remains accurate} + +## Architecture decisions + +- `{reused ADR path}` — {decision and status} +- None qualified. + +## Feature existence + +- `{feature}` — `{context file that canonically describes it}`, already present. + +## Verification + +- {How existing context was compared with implementation and execution evidence.} + +--- + +## Blocked variant + +# Context Sync Report + +**Status:** blocked\(" ") +**Plan:** `{plan path}`\(" ") +**Task:** `{task id} — {task title}` + +## Updated files + +- {List each changed file from the execution handoff except paths under + `context/`; state `None.` when no files remain.} + +## Blocker + +**Problem:** {specific synchronization blocker}\(" ") +**Impact:** {why context cannot be made authoritative safely}\(" ") +**Required action:** {decision or correction required} + +## Context changes + +- {List safe context edits preserved, or state `No context files were changed.`} + +## Architecture decisions + +- `{ADR path written or reused before the blocker}` — {decision and status} +- None written or reused before the blocker. + +## Retry condition + +{State the concrete condition under which context synchronization should run +again.} + +## Report rules + +- Name exact context files when they were changed or reviewed. +- Under **Architecture decisions**, list every ADR path written or reused during + the decision gate. In a successful report, state `None qualified.` when the + gate skipped invocation. In a blocked report, state + `None written or reused before the blocker.` when applicable. +- Under **Updated files**, list every changed file from the execution handoff + except paths under `context/`. +- Report the missing context root as `blocked`, with `sce setup + --bootstrap-context` as the required action and the existence of `context/` as + the retry condition. +- Omit **Feature existence** only when the task implemented no feature. +- Describe durable truth, not implementation-session chronology. +- Keep evidence concise and factual. +- Do not claim final validation passed. +- Do not determine whether the plan is complete. +- Do not recommend a next implementation task. +""" + +validateSkillBody = """ +# SCE Validate + +## Purpose + +Own this workflow from input parsing through its terminal user-visible response. +Execute the phases below directly and in order. Phase statuses are internal state, +not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or +workflow command except `sce-decision`, and invoke `sce-decision` only from the +successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, +and stops exactly as written: never invent, skip, reorder, or merge a step. + +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/validation.md` | +| 2 | `references/context-sync.md` | + +`references/validation-report.md` defines the `## Validation Report` section +written into the plan file. Step 1 points to it at the moment it is needed, on a +`validated` or `failed` outcome only. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at a `blocked` +or `failed` validation never enters step 2, which is why they are separate files. + +## User-visible output + +Use `references/output.md` for every gate and terminal response. Render no raw +internal state. The reference contains only human-visible Markdown layouts. +User-visible output is limited to those layouts: never invent a layout, and never +wrap one in an added preamble, commentary, summary, or extra section. + +## Composite control flow + +Keep phase results as internal state and continue immediately whenever the +canonical workflow says to continue. Stop only at a user wait or terminal branch. +Approval, clarification, revision, failed-validation repair, and bootstrap waits +resume this same skill in the same session. Never expose an internal phase result +as the workflow's final response. + +## Input + +`$ARGUMENTS` is the plan name or plan path. + +- The plan name or path is required. +- Resolve exactly one plan. Do not invent a plan from the conversation or from + incomplete nearby work. + +When `$ARGUMENTS` is empty, report that a plan name or path is required, state +the expected argument, and stop. Do not infer the plan from repository state or +the conversation. + +Pass the plan name or path to the **Validation phase** unmodified. Do not restate, +summarize, or pre-scope it. + +Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is +the path carried by the **Validation phase** in its Markdown result (`Plan:`, or a +candidate path), so every emitted command is directly runnable. + +## Workflow + +### 1. Validate the plan + +Read `references/validation.md`, then run the **Validation phase** with the plan +name or path. + +This phase measures finished work and never repairs it: it does not modify tests, +application code, or configuration to make a failing check pass. That property is +load-bearing, so reach it through the reference rather than acting from this +summary. + +Do not write the Validation Report yourself. + +Branch on the report's `Status:`. + +`blocked` -> Do not run context synchronization. Print the blocked Markdown +report as returned. Do not rephrase it into a different layout. Stop. + +`failed` -> Do not run context synchronization. Print the failed Markdown +report as returned. It is already a session handoff: self-contained, actionable, +and ending with `/validate {plan-path}` after repairs. + +Do not rewrite it into a shorter summary. Do not drop the retry command. Do not +add an alternate continuation that replaces `/validate`. + +Stop. Do not mark the plan finished. Do not continue to context synchronization. +Do not start the repair work in this workflow unless the user explicitly asks +to continue here; the default is that the handoff can leave this session. + +`validated` -> Pass the complete validated Markdown result to the **Plan context synchronization phase**. + +Do not reconstruct, summarize, or reinterpret the validation result before +passing it. + +### 2. Synchronize plan context + +Read `references/context-sync.md`, then run the **Plan context synchronization +phase** with the `Status: validated` Markdown result from the **Validation +phase**. + +Do not run the **Plan context synchronization phase** for `failed` or `blocked`. Those are not +success states. + +Pass the validated result verbatim. It is the authoritative handoff, and the **Plan context synchronization phase** +owns reading the plan path, required context paths, validation evidence, and +reported context impact out of it. + +Do not restate, summarize, or reconstruct any part of the validation result. + +This phase verifies the five root context files on every invocation, whatever the +reported impact, and must account for every path in the plan's `Context sync` +section, so it is never correct to skip it as unnecessary. + +Branch on the synchronization result. + +`blocked` -> Validation itself succeeded and is already recorded in the plan. +Render the **Context synchronization blocked** layout from +`references/output.md`. Nothing records the skipped synchronization, so it is +lost once this session ends. + +Stop. + +`synced` | `no_context_change` -> Print out the report returned by the **Plan context synchronization phase**. +Continue to the next step. + +### 3. Report completion + +Return exactly one completion block. Do not start another workflow. + +Render the **Completion** layout from `references/output.md`. + +When the synchronization status was `no_context_change`, keep the same +completion block. "Synchronized" here means the final context pass finished +successfully, including the case where no edit was warranted. + +Stop. + +## Rules + +- Validate at most one plan per invocation. +- Read each phase's reference before running that phase. +- Do not duplicate the internal instructions of embedded phases. +- The only permitted sibling-skill invocation is `sce-decision`, and only the + successful context-synchronization decision gate may invoke it. +- Do not run final validation when implementation tasks remain; the **Validation phase** + returns `blocked`, and this workflow stops. +- Run the **Plan context synchronization phase** only when the **Validation phase** returned + `Status: validated`. Do not run it for `failed` or `blocked`. +- On `failed`, print the handoff Markdown as returned and stop. Preserve the + retry `/validate {plan-path}` instruction. Do not synchronize context. +- Do not implement remaining plan tasks from this workflow unless the user + explicitly continues in-session after a failed handoff. +- Do not create a Git commit or push changes. +- Do not mark the plan archived or delete the plan. +- Do not execute a follow-up `/next-task`, `/change-to-plan`, or `/validate` + yourself. +- Do not infer success when an embedded phase returns a non-success status. +- Preserve validation evidence already written to the plan when context + synchronization fails. +""" + +validateValidation = """ +# Validation phase + +Run this phase for step 1 of the workflow. It resolves one plan, confirms the +implementation is finished, runs the plan's checks, and records what it found. + +Input: the plan name or path, unmodified. + +This phase exclusively owns: + +- Resolving one plan. +- Confirming every implementation task is complete. +- Running full validation and acceptance-criteria checks. +- Removing temporary scaffolding. +- Writing the Validation Report into the plan. +- Returning one Markdown validation result. + +Do not duplicate any of it elsewhere in the workflow. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan under +`context/plans/`. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Confirm implementation is finished + +Set internal status `blocked` with incomplete tasks listed when any +implementation task remains incomplete. + +Final validation measures finished work. Do not run the full suite against a +partial stack, and do not complete remaining tasks here. + +## 1.3 Read the validation contract from the plan + +From the plan, collect: + +- Every acceptance criterion and its `Validate:` check. +- The `Full validation` command list. +- The `Context sync` requirements, for the context-impact handoff only. + +Set internal status `blocked` when the plan has no usable acceptance criteria, or +when no validation commands can be determined from the plan or repository +conventions. + +Prefer the plan's authored checks. Fall back to repository-primary test, lint, +and format commands only when `Full validation` is absent, and record that +fallback under notes on a `validated` or `failed` result. + +## 1.4 Remove temporary scaffolding + +Before or while running checks, remove temporary scaffolding introduced during +the change when it is clearly throwaway: + +- Debug-only patches or flags left enabled. +- Temporary files or intermediate artifacts not part of the delivered design. +- Local scaffolding the plan or task notes mark as temporary. + +Do not delete durable product code, tests, configuration, or context files. + +Record every removed path. When nothing temporary remains, report `None.` + +## 1.5 Run full validation and acceptance checks + +Run the plan's `Full validation` commands. + +Then verify each acceptance criterion using its `Validate:` line. Prefer a +runnable command. Use a named inspection only when the criterion authorizes it, +and say exactly what was inspected. + +When a check fails, record the failure and continue gathering evidence. Do not +modify tests, application code, or configuration to make a check pass. Final +validation measures the finished work; repair belongs to a later work session, +not this skill. + +Never report a check as passed unless it ran successfully or the authorized +inspection confirmed the criterion. + +Do not run task-by-task implementation work for incomplete tasks. That belongs to +`/next-task`. + +## 1.6 Update the plan + +For `validated` and `failed` outcomes: + +- Mark each acceptance criterion checkbox to match the evidence. +- Append or replace the plan's `## Validation Report` section using + `references/validation-report.md`. Read that file before writing the section. +- When status is `failed`, the plan-file report must include the retry command + `/validate {plan path}`. + +Do not reopen completed tasks, rewrite task evidence, or change the task stack. + +For `blocked`, leave the plan file unchanged. + +## 1.7 Determine context impact for the handoff + +On `validated` only, classify the durable context impact of the finished plan so +the **Plan context synchronization phase** can start from the plan's own +requirements: + +- Start from the plan's `Context sync` section. +- Inspect what the completed implementation actually changed when needed. +- Report required context paths and affected areas. +- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level + context sync. + +Do not edit context files here. + +On `failed` or `blocked`, omit context impact; context sync will not run. + +## 1.8 Return the internal state + +Set exactly one internal state: + +- `validated` when every acceptance criterion is met, required full validation + passed, and the Validation Report was written. +- `failed` when evidence was captured but required checks or criteria remain + unsatisfied. Shape it as a session handoff per `references/output.md`, ending + recommended work with `/validate {plan path}`. +- `blocked` when validation cannot proceed safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. +Do not return internal state. + +A `validated` result is the authoritative handoff into step 2, which reads the +plan path, required context paths, validation evidence, and reported context +impact out of it. It must report: + +```markdown +**Status:** validated +**Plan:** {plan path} +``` + +and must carry the resolved plan path, validation commands and outcomes, +acceptance-criteria evidence, scaffolding removals, and the reported context +impact with required context paths and affected areas. Step 2 is forbidden from +reconstructing any of that, so it has to be present here. + +## Validation boundaries + +Do not: + +- Validate more than one plan. +- Complete remaining implementation tasks. +- Modify tests, application code, or configuration to make a failing check pass. +- Apply lint or format auto-fixes that change product or test files as part of + making validation green. +- Synchronize durable context under `context/` outside the plan file. +- Create the context root. +- Mark the plan archived or delete the plan. +- Create a Git commit or push changes. +- Invent acceptance criteria the plan does not state. +- Claim verification that was not performed. +- Return a internal state. +- Run plan context synchronization. The workflow owns that step. +""" + +validateContextSync = """ +# Plan context synchronization phase + +Run this phase for step 2 of the workflow, and only with a `Status: validated` +Markdown result from the validation phase. It is the plan-level final context +pass: it starts from the plan's `Context sync` requirements and the validated +implementation, and closes gaps that remain after any task-level syncs already +ran. + +Do not run this phase for `failed` or `blocked`. Those are not success states. +Same rule as the task context synchronization phase: context sync runs only after +a successful prior phase. + +Pass the validated result verbatim. It is the authoritative handoff, and this +phase owns reading the plan path, required context paths, validation evidence, +and reported context impact out of it. + +Do not restate, summarize, or reconstruct any part of the validation result. Do +not reconstruct a missing validation result from conversation history. + +Treat that Markdown as the authoritative handoff for: + +- The resolved plan path. +- Validation commands and outcomes. +- Acceptance-criteria evidence. +- Scaffolding removals. +- Reported context impact, required context paths, and affected areas. + +## 2.1 Validate the validation handoff + +Confirm that: + +- `Status:` is exactly `validated`. +- `Plan:` names an existing plan path. +- Acceptance-criteria evidence is present and every criterion is met. +- Commands run are present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 2.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that validation itself succeeded and is recorded in the plan, and that plan +context synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 2.3 Discover applicable context + +Start with the validated internal state: + +- **Context impact** classification, required context, and affected areas. +- Acceptance-criteria evidence. +- Commands run. + +Then read the plan's `Context sync` section and inspect existing repository +context in this order when present: + +1. Paths named by the plan's `Context sync` section +2. `context/context-map.md` +3. Context files for the affected domain or subsystem +4. `context/overview.md` +5. `context/architecture.md` +6. `context/glossary.md` +7. `context/patterns.md` +8. Operational, product, or decision records directly related to the finished + change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +finished implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +### Plan context requirements + +Every path or statement listed under the plan's `Context sync` section must be +accounted for in the report as already accurate or updated. A requirement the +finished code still does not satisfy is a blocker, not a note. + +## 2.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +finished implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in validation evidence. +- Speculation or future work not established by the finished plan. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass or the plan's Context sync +requirements. + +- `none`: Make no edits beyond any correction the root pass or unmet plan context + requirement turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 2.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- acceptance-criteria and validation evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task references, + related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 2.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the validation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the finished implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the validation result verbatim into context files. +- Do not change application code, tests, or plan validation evidence. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the finished plan implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the plan delivered a feature no context file describes, add that +description. Prefer a small, precise domain file over overloading `overview.md` +with detail. + +This is not license to narrate the diff: describe what the feature is and how it +behaves, not what was edited during the plan. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the plan introduced. +New terminology is durable knowledge whatever the classification is. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 2.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the finished implementation. +- No edited statement contradicts the code, plan, or validation evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Every plan `Context sync` requirement is met. +- Each feature implemented by the plan has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not rerun full-plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 2.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +## Plan context synchronization boundaries + +Do not: + +- Accept a validation result whose status is not `validated`. +- Accept `failed` or `blocked` validation results. +- Implement or modify application code. +- Modify tests. +- Change task completion status, acceptance-criteria marks, or the Validation + Report. +- Rerun full-plan validation. +- Select or execute an implementation task. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return internal state. +""" + +validateValidationReport = """ +# Internal persisted-document format: Plan-file validation report + +The Markdown section the **Validation phase** appends to the plan file when +returning `validated` or `failed`. Write it at the end of +`context/plans/{plan_name}.md` under exactly one `## Validation Report` heading. + +This is plan-file content. The result returned to the workflow is defined +separately in `references/output.md`. + +Do not author this section while planning. Only `/validate` through the +**Validation phase** writes it. + +## Layout + +```markdown +## Validation Report + +**Status:** {validated | failed}\(" ") +**Date:** {YYYY-MM-DD} + +### Commands run + +- `{command}` -> exit {code} ({concise outcome summary}) +- `{command}` -> exit {code} ({concise outcome summary}) + +### Scaffolding removed + +- `{path}` — {why it was temporary} +- None. + +### Success-criteria verification + +- [x] AC1: {criterion statement} -> {evidence} +- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} + +### Failed checks and follow-ups + +- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} +- None. + +### Residual risks + +- {risk} +- None identified. + +### Retry + +{Only when Status is failed:} + +After repairs, rerun: + +`/validate {plan path}` +``` + +## Rules + +- Use **Status:** `validated` only when every acceptance criterion is met and + every required full-validation command passed. +- Use **Status:** `failed` when evidence was captured but required checks or + criteria remain unsatisfied. +- List every command that ran under **Commands run**, including ones that failed. + Do not invent exit codes or outcomes. +- Prefer the plan's `Full validation` commands and each criterion's `Validate:` + line over rediscovering project defaults. Fall back to repository conventions + only when the plan omits them. +- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` + section to match the evidence. Do not mark a criterion met unless the check ran + successfully or the inspection named by `Validate:` confirms it. +- Under **Scaffolding removed**, list only temporary debug code, intermediate + artifacts, or throwaway files introduced during the change. Write `None.` when + nothing temporary remained. +- Under **Failed checks and follow-ups**, record the failing check and its + evidence only. Do not describe code or test edits made during validation; + validation does not modify tests or product code to clear failures. Write + `None.` when status is `validated`. +- When status is `failed`, always include **Retry** with the exact + `/validate {plan path}` command. Omit **Retry** when status is `validated`. +- Keep evidence concise and factual. Do not narrate the whole implementation + history. +- Do not claim context synchronization completed. Plan context sync is a later + workflow step and runs only after `validated`. +- Do not rewrite task evidence or reopen completed tasks. +- When a previous `## Validation Report` already exists, replace it with the new + one rather than stacking duplicates. +""" + +validateOutput = """ +# Validate output layouts + +Use only the applicable layout. Values come from internal workflow state. + +The `blocked` and `failed` layouts are stated once, under **Validation Result** +below. + +## Context synchronization blocked + +State that validation passed and its report is recorded, then report the context +failure, preserved edits, required action, and retry condition. State that durable +context remains out of date and synchronization must finish before closure. + +## Completion + +```markdown +------------------------------------- + +# Plan {plan-name} validated. + +All implementation tasks were already complete. +Final validation passed. +Durable context is synchronized. + +Validation report: {plan-path} +``` + +# Validation Result + +Return only one completed Markdown report using the applicable variant below. +Do not include unused sections, placeholders, YAML, or a fenced code block. + +The `Status` value must be exactly one of: + +- `validated` +- `failed` +- `blocked` + +The plan-file `## Validation Report` section is written separately using +`references/validation-report.md`. This layout carries the validation phase's +result into the workflow's own branches. + +## Validated variant + +# Validation Report + +**Status:** validated\(" ") +**Plan:** `{plan path}`\(" ") +**Name:** `{plan name}`\(" ") +**Tasks:** `{completed}/{total} complete`\(" ") +**Date:** `{YYYY-MM-DD}` + +## Commands run + +- `{command}` -> {passed} — {concise outcome summary} + +## Acceptance criteria + +- [x] AC1: {criterion statement} — {evidence} +- [x] AC2: {criterion statement} — {evidence} + +## Scaffolding removed + +- `{path}` — {why it was temporary} +- None. + +## Residual risks + +- {risk} +- None identified. + +## Context impact + +**Classification:** `{none | local | domain | root}`\(" ") +**Affected areas:** `{comma-separated areas}`\(" ") +**Required context:** + +- `{path or statement from the plan Context sync section}` + +{One or two sentences on why this classification fits the finished plan.} + +## Notes + +{Include only non-blocking information worth retaining. +Omit this section when unnecessary.} + +--- + +## Failed variant + +This variant is a session handoff. Another agent or a later session must be +able to act from it alone. Write it as a prompt the user can paste forward, not +as a summary of the validation run. + +# Validation failed — handoff + +**Status:** failed\(" ") +**Plan:** `{plan path}`\(" ") +**Name:** `{plan name}`\(" ") +**Tasks:** `{completed}/{total} complete`\(" ") +**Date:** `{YYYY-MM-DD}`\(" ") +**Validation report:** written to `{plan path}` + +## Goal for the next session + +Repair the unfinished validation so every acceptance criterion and full +validation command passes. Do not modify tests or product code inside a +`/validate` run to force green results; fix the implementation (or the plan) in +a normal work session, then rerun validation. + +## What failed + +- `{check or AC id}`: {problem} + - Evidence: {command output, exit summary, or inspection finding} + - Required action: {concrete repair or decision} + +## Acceptance criteria + +- [x] AC1: {criterion} — {evidence} +- [ ] AC2: {criterion} — {why unmet} + +## Commands run + +- `{command}` -> {passed | failed | not_run} — {concise outcome summary} + +## Constraints + +- All implementation tasks were already complete when validation ran. +- Validation did not modify tests, application code, or configuration to clear + failures. +- Durable context was not synchronized; plan context sync runs only after + validation succeeds. +- Prefer the plan at `{plan path}` and its Validation Report as the source of + recorded evidence. + +## Residual risks + +- {risk} +- None identified. + +## Recommended work + +1. {First concrete fix, with files or areas when known} +2. {Second concrete fix, or decision the user must make} +3. Rerun final validation after the fixes land: + +`/validate {plan path}` + +Do not stop after the repair. The plan is not finished until `/validate` +returns `validated` and plan context sync completes. + +--- + +## Blocked variant + +# Validation blocked + +**Status:** blocked\(" ") +**Plan:** `{plan path when resolved}`\(" ") +**Name:** `{plan name when resolved}` + +## Issues + +- **{issue id}** ({category}): {problem} + - Impact: {impact} + - Required: {decision or action} + +## Incomplete tasks + +- `{task id}` — {title} +- Omit this section when no incomplete tasks apply. + +## Candidates + +- `{candidate plan path}` +- Omit this section when plan resolution was not ambiguous. + +## Next step + +{Exactly one continuation, matching the blocker:} + +- Incomplete tasks: + +`/next-task {plan path}` + +- Ambiguous plan: + +`/validate {candidate path}` + +- Missing plan content or other blocker: state the decision required. Do not + invent a command. + +--- + +## Report rules + +- Name the exact `Plan:` path so every emitted command is runnable. +- Use **Status:** exactly `validated`, `failed`, or `blocked`. +- Never claim a check passed unless it ran successfully or the authorized + inspection confirmed it. +- Do not modify tests or product code to clear a failure; record it under + **What failed**. +- The failed variant must always end its **Recommended work** with + `/validate {plan path}` as the final step after repairs. +- The failed variant must be self-contained enough to hand to another session + without the original chat. +- Include **Context impact** only on `validated`. Omit it on `failed` and + `blocked`; plan context sync is not run for non-success states. +- Do not include context synchronization results in this report. The invoking + workflow runs the **Plan context synchronization phase** only after `validated`. +- Do not select or describe an unrelated next implementation task when status is + `validated`. +- Omit empty optional sections rather than writing placeholders. + +# Plan Context Sync Report + +Return only one completed Markdown report using the applicable variant below. +Do not include unused sections, placeholders, YAML, or a fenced code block. + +The `Status` value must be exactly one of: + +- `synced` +- `no_context_change` +- `blocked` + +The input validation status is always `validated` and does not need to be +repeated as a separate workflow state. This report is not produced for +`failed` or `blocked` validation results. + +## Synced variant + +# Plan Context Sync Report + +**Status:** synced\(" ") +**Plan:** `{plan path}` + +## Context impact + +**Classification:** `{local | domain | root}`\(" ") +**Affected areas:** `{comma-separated areas}` + +{Explain which durable behavior, architecture, terminology, operation, or +constraint required plan-level synchronization after validation.} + +## Plan context requirements + +- `{required context path or statement from the plan}` — {met by edit | already accurate} + +## Updated context + +- `{context file}` — {concise description of the durable truth updated} + +## Architecture decisions + +- `{written or reused ADR path}` — {decision and status} +- None qualified. + +## Root pass + +- `context/overview.md` — {verified | edited | absent} +- `context/architecture.md` — {verified | edited | absent} +- `context/glossary.md` — {verified | edited | absent} +- `context/patterns.md` — {verified | edited | absent} +- `context/context-map.md` — {verified | edited | absent} + +## Feature existence + +- `{feature}` — `{context file that canonically describes it}` + +## Verification + +- {How the edited context was checked against the finished implementation and validation evidence.} +- {File hygiene: line counts, relative links, diagrams where structure is complex.} +- {Documentation, link, or formatting checks that were run, when applicable.} + +## Notes + +{Include only non-blocking information worth retaining. +Omit this section when unnecessary.} + +--- + +## No-context-change variant + +# Plan Context Sync Report + +**Status:** no_context_change\(" ") +**Plan:** `{plan path}` + +## Context impact + +**Classification:** none + +{Explain why the finished plan introduced no durable, non-obvious repository +knowledge requiring an update, or why existing context already matched.} + +## Plan context requirements + +- `{required context path or statement from the plan}` — already accurate +- None listed by the plan. + +## Context reviewed + +- `{context file or area}` — {what was checked and why it remains accurate} + +## Architecture decisions + +- `{reused ADR path}` — {decision and status} +- None qualified. + +## Root pass + +- `context/overview.md` — {verified | absent} +- `context/architecture.md` — {verified | absent} +- `context/glossary.md` — {verified | absent} +- `context/patterns.md` — {verified | absent} +- `context/context-map.md` — {verified | absent} + +## Feature existence + +- `{feature}` — `{context file that canonically describes it}`, already present. + +## Verification + +- {How existing context was compared with the finished implementation and validation evidence.} + +--- + +## Blocked variant + +# Plan Context Sync Report + +**Status:** blocked\(" ") +**Plan:** `{plan path}` + +## Blocker + +**Problem:** {specific synchronization blocker}\(" ") +**Impact:** {why context cannot be made authoritative safely}\(" ") +**Required action:** {decision or correction required} + +## Context changes + +- {List safe context edits preserved, or state `No context files were changed.`} + +## Architecture decisions + +- `{ADR path written or reused before the blocker}` — {decision and status} +- None written or reused before the blocker. + +## Retry condition + +{State the concrete condition under which plan context synchronization should +run again.} + +## Report rules + +- Name exact context files when they were changed or reviewed. +- Under **Architecture decisions**, list every ADR path written or reused during + the decision gate. In a successful report, state `None qualified.` when the + gate skipped invocation. In a blocked report, state + `None written or reused before the blocker.` when applicable. +- Report every file in the root pass, including any that is absent. +- Report the missing context root as `blocked`, with `sce setup + --bootstrap-context` as the required action and the existence of `context/` as + the retry condition. +- Cover every path or statement listed in the plan's `Context sync` section + under **Plan context requirements**. +- Omit **Feature existence** only when the plan implemented no feature. +- Describe durable truth, not validation-session chronology. +- Keep evidence concise and factual. +- Do not claim implementation tasks remain open. +- Do not reopen validation checks. +- Do not recommend a next implementation task unless context cannot be repaired + without one, and then only as the required action. +""" + +commitSkillBody = """ +# SCE Commit + +## Purpose + +Own this workflow from input parsing through its terminal user-visible response. +Execute the phases below directly and in order. Phase statuses are internal state, +not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or +workflow command. Follow the canonical workflow's steps, gates, +and stops exactly as written: never invent, skip, reorder, or merge a step. + +## Phase reference + +Both paths below dispatch to the same phase, whose steps and boundaries live in +`references/atomic-commit.md`. This document holds the control flow — which path +runs, what the phase receives, and how its result branches — and the reference +holds the phase itself. + +Read `references/atomic-commit.md` before running the phase, not after. A regular +run that stops at the staging gate, and a bypass run that finds nothing staged, +both end without ever needing it. + +## User-visible output + +Use `references/output.md` for every gate and terminal response. Render no raw +internal state. The reference contains only human-visible Markdown layouts. +User-visible output is limited to those layouts: never invent a layout, and never +wrap one in an added preamble, commentary, summary, or extra section. + +## Composite control flow + +Keep phase results as internal state and continue immediately whenever the +canonical workflow says to continue. Stop only at a user wait or terminal branch. +Approval, clarification, revision, failed-validation repair, and bootstrap waits +resume this same skill in the same session. Never expose an internal phase result +as the workflow's final response. + +## Input + +`$ARGUMENTS` is optional. Split it into two parts before invoking the skill: + +`[mode-token] [commit context]` + +- `mode-token` is present only when the first whitespace-separated token is + exactly `oneshot` or `skip`, compared case-insensitively. Any other first + token is not a mode token. +- `commit context` is everything else: free-form prose that refines message + wording only. + +A `mode-token` selects the bypass path. Its absence selects the regular path. +Do not infer the bypass path from anything else — not from the commit context, +not from repository state, and not from the conversation. + +Empty `$ARGUMENTS` is valid. It selects the regular path with no commit +context, and commit intent is inferred from the staged changes alone. + +Pass `commit context` to the **Atomic commit phase** unmodified. Do not restate, +summarize, or pre-scope it. Never pass the `mode-token` as commit context. + +Staged changes are the source of truth for what is being committed. This +command never stages, unstages, or modifies files. + +## Workflow + +Follow exactly one path. + +### Regular path (no mode token) + +#### 1. Confirm staging + +Before running the phase, stop and prompt the user with the **Regular-mode +staging gate** layout from `references/output.md`. + +Wait for the user's confirmation. Do not stage files on their behalf, and do +not skip this prompt because the working tree looks ready. + +#### 2. Propose commits + +After confirmation, read `references/atomic-commit.md`, then run the **Atomic +commit phase** with `mode: regular` and the commit context. + +Do not write commit messages yourself. + +Branch on `status`: + +`blocked` -> Render the **Blocked** layout from `references/output.md`. Stop. + +`proposal` -> Render the **Regular proposal** layout from `references/output.md`, +which covers each proposed commit's message and files, and the split rationale +when more than one commit is proposed. + +Then stop. The regular path is proposal-only. + +Do not run `git commit`. Do not offer to commit on the user's behalf. The user +runs the commits they accept. + +### Bypass path (`oneshot` or `skip`) + +#### 1. Validate that staged content exists + +Run `git diff --cached --quiet`. A zero exit status means nothing is staged. + +When nothing is staged, stop with the **No staged changes** layout from +`references/output.md`. + +Do not stage anything. Do not proceed to the skill. + +#### 2. Request one commit message + +Read `references/atomic-commit.md`, then run the **Atomic commit phase** with +`mode: bypass` and the commit context. + +Bypass mode is the skill's contract for producing exactly one message. Do not +restate its overrides here; the **Atomic commit phase** owns them. + +Branch on `status`: + +`blocked` -> Render the **Blocked** layout from `references/output.md` and stop. Do not commit. + +`bypass_message` -> Continue to the next step. + +The skill never returns `proposal` in bypass mode. Treat a `proposal` result as +a contract violation: report it and stop without committing. + +#### 3. Execute exactly one commit + +Run `git commit` once with the returned message. + +On success, render the **Bypass success** layout from `references/output.md` and +stop. + +On failure, render the **Bypass Git failure** layout from the same file and stop. + +Do not retry, do not amend, do not stage additional files, and do not invent a +fallback commit. + +## Rules + +- Produce at most one commit per invocation, and only on the bypass path. +- Never commit on the regular path. +- Recognize `oneshot` and `skip` only as an exact case-insensitive first token. + They are behaviorally identical. +- Read `references/atomic-commit.md` before running the phase. +- Do not duplicate the internal instructions of the **Atomic commit phase**. +- Do not stage, unstage, restore, or otherwise modify files. +- Do not amend, reset, revert, rebase, or push. +- Do not read unstaged or untracked changes as commit input. +- Do not infer success when the **Atomic commit phase** returns a non-success status. +- Do not proceed past a failed `git commit`. +- Do not run plan, task, or validation workflows from this command. +""" + +commitAtomicCommit = """ +# Atomic commit phase + +Both workflow paths run this phase. The regular path runs it with `mode: regular` +after the staging gate; the bypass path runs it with `mode: bypass` after +confirming staged content exists. + +Input: the mode, supplied by the workflow from an explicit user-supplied token, +and the commit context. + +This phase exclusively owns: + +- Reading and analyzing the staged diff. +- Deciding whether staged changes form one coherent unit or several. +- Classifying staged scope and applying context-file guidance gating. +- Writing every commit message subject and body. +- Applying the plan-citation body rule. + +Do not duplicate any of it elsewhere in the workflow. Do not write commit messages +outside this phase. + +Never infer the mode, and never switch modes mid-analysis. + +Commit context refines wording only. The staged diff decides what the change is; +context never overrides staged truth, and never adds a claim the diff does not +support. + +Do not accept an unstaged diff, a working-tree summary, or a conversational +description as a substitute for the staged diff. + +## 1. Read the staged diff + +Read the staged changes with `git diff --cached`, and the staged file list with +`git diff --cached --name-status`. + +Read staged file contents only when the diff alone does not explain the change. + +Set internal status `blocked` when nothing is staged. + +## 2. Identify coherent units + +Infer the main reason for the staged change from the diff first. + +A coherent unit is one goal a reviewer would accept as a single commit. Group +staged files by that goal, not by directory. + +In `bypass` mode, stop grouping here: the result is exactly one message covering +all staged files, whether or not the diff is coherent. Do not propose splits, and +do not report split guidance. + +## 3. Choose a scope for each unit + +Use the smallest stable subsystem or module name recognizable in the repository. + +When no such name applies, use the primary directory or package of the unit's +changes. + +## 4. Write each message + +Follow `references/output.md` for the subject pattern, the body rules, issue +references, the plan-citation rule, and the anti-patterns. + +## 5. Apply the plan-citation rule + +When the unit's staged files include `context/plans/*.md`, cite the affected plan +slug and updated task IDs in the body. + +When the staged plan diff does not expose the slug or task ID clearly enough to +cite faithfully: + +- In `regular` mode, set internal status `blocked` and ask for the reference to be + stated or staged explicitly. +- In `bypass` mode, infer the citation when the diff supports it, and otherwise + omit it. Never stop, and never invent a slug or task ID. + +## 6. Apply context-file guidance gating + +This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do +not classify staged scope there. + +Classify the staged diff: + +- Context-only (`context/**`): context-file-focused guidance is allowed. +- Mixed (`context/**` plus non-`context/**`): suppress default context-file commit + reminders and give guidance that reflects the full staged scope. + +## 7. Propose split guidance + +This step applies in `regular` mode only. + +When the units found in step 2 pursue unrelated goals, return one message per +unit, and state why the split is recommended and which staged files belong to +each. + +When the staged changes form one unit, return one message and no split guidance. +Do not split coherent work to appear thorough. + +## 8. Validate the result + +Confirm before returning that: + +- Every message describes its unit faithfully and covers only that unit's files. +- Every staged file belongs to exactly one returned message. +- No plan slug or task ID appears that the staged diff does not support. +- The mode's own constraints hold. + +## 9. Return internal state + +Set exactly one internal state: + +- `proposal` in `regular` mode, with one or more messages. +- `bypass_message` in `bypass` mode, with exactly one message. +- `blocked` when messages cannot be written faithfully. + +Record only the internal state. Do not add explanatory prose before or after it. + +## Atomic commit boundaries + +Do not: + +- Run `git commit`, or any command that writes to the repository or its index. +- Stage, unstage, or modify files. +- Ask the user to stage or confirm staging. +- Analyze unstaged or untracked changes. +- Return more than one message in `bypass` mode. +- Return split guidance in `bypass` mode. +- Stop for plan-citation ambiguity in `bypass` mode. +- Invent plan slugs, task IDs, or issue references. +- Mention `context/` synchronization activity in a commit message. +- Claim a message was committed. +- Run plan, task, or validation workflows. +""" + +commitOutput = """ +# Commit output layouts + +Use only the applicable layout. Values come from staged truth and internal +workflow state. + +## Regular-mode staging gate + +```markdown +Please run `git add ` for all changes you want included in this commit. +Atomic commits should only include intentionally staged changes. +Confirm once staging is complete. +``` + +## No staged changes + +```markdown +No staged changes. Stage changes before commit. +``` + +## Regular proposal + +For each proposal, present the complete commit message and covered files. When +more than one commit is proposed, also present the split rationale. Do not claim a +commit was created. + +## Blocked + +Present every issue's problem, impact, and required decision. Do not commit. + +## Bypass success + +```markdown +Committed {commit-hash} +``` + +## Bypass Git failure + +Present Git's failure unchanged and stop without retrying. + +# Commit message style + +The wording rules for every message the **Atomic commit phase** returns, in either +mode. This file is the only authority for message content and shape. + +Messages are carried in the result's `message` field, subject first, then one +blank line, then the body. + +## Subject + +Pattern: + +`: ` + +- Scope is the smallest stable subsystem or module name recognizable in the + repository. When no such name applies, use the primary directory or package + of the change. +- Start the summary with an imperative verb: Fix, Add, Remove, Implement, + Refactor, Simplify, Rename, Update, Ensure, Allow. +- Capitalize the verb. Do not end the subject with a period. +- Keep it concrete and technical. Name what changed, not how it felt. + +## Body + +Include a body whenever the subject alone leaves the change unexplained. Omit +it for changes whose subject is self-evident. + +A body says what was wrong or missing, why it mattered, what changed +conceptually, and the impact. It does not restate the subject in longer words, +and it does not narrate the editing process. + +Wrap the body at a readable width and separate paragraphs with a blank line. + +## Issue references + +Put each issue reference on its own line at the end of the body, for example +`Fixes #123`. + +Reference only issues the staged diff or the supplied commit context names. Do +not infer an issue number from a branch name. + +## Plan citations + +When a commit's staged files include `context/plans/*.md`, the body must also +cite: + +- The affected plan slug. +- Every updated task ID (`T0X`). + +Cite only what the staged plan diff shows. When the diff does not expose the +slug or task IDs clearly enough to cite faithfully, the skill's mode decides +what happens — the ambiguity is not resolved here by guessing. + +## Anti-patterns + +- Vague subjects: "cleanup", "updates", "various fixes". +- A body that repeats the subject without adding why or impact. +- Playful tone in a fix, security change, or architectural change. +- Mentioning `context/` synchronization activity. +- Inventing plan slugs, task IDs, or issue references. +- Splitting changes that already form one coherent unit. +- Forcing unrelated goals into a single commit. +- Describing intent the staged diff does not support. +""" diff --git a/config/pkl/base/workflow-next-task.pkl b/config/pkl/base/workflow-next-task.pkl index 7ab33ccc..b8755a1b 100644 --- a/config/pkl/base/workflow-next-task.pkl +++ b/config/pkl/base/workflow-next-task.pkl @@ -1409,6 +1409,13 @@ local IMPLEMENTATION_GATE = renderImplementationGate.apply("package") structuredComposite = new model.StructuredCompositeSource { command = structuredCommand + compositeSkillBody = model.nextTaskSkillBody + referenceDocuments = new Listing { + model.makeDocument.apply("references/plan-review.md", model.nextTaskPlanReview) + model.makeDocument.apply("references/task-execution.md", model.nextTaskTaskExecution) + model.makeDocument.apply("references/context-sync.md", model.nextTaskContextSync) + model.makeDocument.apply("references/output.md", model.nextTaskOutput) + } phases = new Listing {} internalDocuments = new Listing {} outputDocuments = new Listing { diff --git a/config/pkl/base/workflow-validate.pkl b/config/pkl/base/workflow-validate.pkl index ca19b26b..4ecb3a5d 100644 --- a/config/pkl/base/workflow-validate.pkl +++ b/config/pkl/base/workflow-validate.pkl @@ -722,6 +722,13 @@ local VALIDATION_RESULT = renderValidationResult.apply("package") structuredComposite = new model.StructuredCompositeSource { command = structuredCommand + compositeSkillBody = model.validateSkillBody + referenceDocuments = new Listing { + model.makeDocument.apply("references/validation.md", model.validateValidation) + model.makeDocument.apply("references/context-sync.md", model.validateContextSync) + model.makeDocument.apply("references/validation-report.md", model.validateValidationReport) + model.makeDocument.apply("references/output.md", model.validateOutput) + } phases = new Listing {} internalDocuments = new Listing { model.makeDocument.apply("Plan-file validation report", renderValidationReport.apply("composite")) diff --git a/config/pkl/renderers/generation-contract-check.pkl b/config/pkl/renderers/generation-contract-check.pkl index 6790c914..6450b694 100644 --- a/config/pkl/renderers/generation-contract-check.pkl +++ b/config/pkl/renderers/generation-contract-check.pkl @@ -93,12 +93,17 @@ local brownfieldSkillDocuments = new Mapping { } } -local decisionInvokingWorkflowPaths = new Mapping { - for (target in new Listing { ".opencode"; ".claude"; ".pi" }) { - ["config/\(target)/skills/sce-next-task/SKILL.md"] = true - ["config/\(target)/skills/sce-validate/SKILL.md"] = true - } -} +local isDecisionInvokingWorkflowDocument = (path: String) -> + path.contains("/skills/sce-next-task/") || path.contains("/skills/sce-validate/") + +local decisionWorkflowText = (documents: Mapping, workflowSlug: String) -> + new Listing { + for (path, text in documents) { + when (path.contains("/skills/\(workflowSlug)/")) { + text + } + } + }.join("\n") local expectedDecisionDocumentPaths = new Mapping { for (target in new Listing { ".opencode"; ".claude"; ".pi" }) { @@ -181,6 +186,31 @@ local requiredBrownfieldSkillTokens = new Listing { "When the literal `rebuild` token was supplied, rewrite authority extends to" } +local requiredPhaseReferencesBySkill = new Mapping { + ["sce-change-to-plan"] = new Listing { + "references/context-load.md" + "references/plan-authoring.md" + "references/plan-template.md" + "references/output.md" + } + ["sce-next-task"] = new Listing { + "references/plan-review.md" + "references/task-execution.md" + "references/context-sync.md" + "references/output.md" + } + ["sce-validate"] = new Listing { + "references/validation.md" + "references/context-sync.md" + "references/validation-report.md" + "references/output.md" + } + ["sce-commit"] = new Listing { + "references/atomic-commit.md" + "references/output.md" + } +} + local requiredDecisionTemplateTokens = new Listing { "## Context" "## Decision" @@ -214,11 +244,11 @@ local forbiddenWorkflowReferenceTokens = new Listing { "references/commit-message-style.md" } -/// Six cross-target workflow packages at nine artifacts each, plus the decision -/// package and the retained non-workflow assets. Stating the total as a literal -/// makes an unintended inventory change fail here instead of silently becoming -/// the new expectation. -local expectedArtifactPathCount = 71 +/// Six cross-target workflow packages, with package-local phase references on +/// the four phase-based workflows, plus the decision package and retained +/// non-workflow assets. Stating the total as a literal makes an unintended +/// inventory change fail here instead of silently becoming the new expectation. +local expectedArtifactPathCount = 101 local assertExactArtifactPaths = (actual: Mapping) -> if ( @@ -239,10 +269,11 @@ local assertWorkflowReferences = (documents: Mapping) -> local assertDecisionWorkflowReferences = (documents: Mapping) -> if ( documents.every((path, text) -> - if (decisionInvokingWorkflowPaths.containsKey(path)) - requiredDecisionWorkflowTokens.every((token) -> text.contains(token)) - else - !text.contains("`sce-decision`") + isDecisionInvokingWorkflowDocument.apply(path) || !text.contains("`sce-decision`") + ) + && requiredDecisionWorkflowTokens.every((token) -> + decisionWorkflowText.apply(documents, "sce-next-task").contains(token) + && decisionWorkflowText.apply(documents, "sce-validate").contains(token) ) ) "generated decision invocation: synchronization-only" else error("generated workflow document violates the synchronization-only sce-decision exception") @@ -263,6 +294,21 @@ local assertDecisionDocumentPaths = (documents: Mapping) -> ) "generated decision package inventory: complete" else error("generated decision package inventory does not match the exact cross-target path contract") +hidden assertPhaseReferenceContract = (documents: Mapping) -> + if ( + new Listing { ".opencode"; ".claude"; ".pi" }.every((target) -> + requiredPhaseReferencesBySkill.every((skillSlug, references) -> + let (skillPath = "config/\(target)/skills/\(skillSlug)/SKILL.md") + documents.containsKey(skillPath) + && references.every((referencePath) -> + documents.containsKey("config/\(target)/skills/\(skillSlug)/\(referencePath)") + && documents[skillPath].contains("`\(referencePath)`") + ) + ) + ) + ) "generated phase references: complete and resolvable" + else error("generated workflow package has a missing or unresolved phase reference") + local assertDecisionContent = (documents: Mapping) -> if ( documents.every((path, text) -> @@ -346,6 +392,7 @@ contractChecks { ["artifact-paths"] = assertExactArtifactPaths.apply(generatedArtifacts) ["optional-workflow-manifest"] = assertOptionalWorkflowManifest.apply(generatedArtifacts) ["workflow-references"] = assertWorkflowReferences.apply(workflowDocuments) + ["phase-reference-contract"] = assertPhaseReferenceContract.apply(workflowDocuments) ["decision-invocation"] = assertDecisionWorkflowReferences.apply(compositeWorkflowDocuments) ["opencode-decision-permission"] = assertOpenCodeDecisionPermission.apply(opencode.agents) ["decision-package-paths"] = assertDecisionDocumentPaths.apply(decisionSkillDocuments) diff --git a/config/pkl/renderers/metadata-coverage-check.pkl b/config/pkl/renderers/metadata-coverage-check.pkl index 92a3cf7e..660898d8 100644 --- a/config/pkl/renderers/metadata-coverage-check.pkl +++ b/config/pkl/renderers/metadata-coverage-check.pkl @@ -20,14 +20,42 @@ local expectedWorkflowSkillByCommand = new Mapping { } } -/// A collapsed target renders each workflow as one package with one entrypoint -/// and one user-visible Markdown output reference. The standalone decision -/// package has no command and carries its ADR template as its sole reference. -/// Exact coverage rejects stale phase packages and unexpected references. +/// Phase-based workflows render package-local phase references. Phase-free +/// workflows retain only output.md, and the standalone decision package retains +/// only its ADR template. Exact coverage rejects stale or missing references. +local phaseReferencePathsByWorkflow = new Mapping { + ["change-to-plan"] = new Listing { + "references/context-load.md" + "references/plan-authoring.md" + "references/plan-template.md" + "references/output.md" + } + ["next-task"] = new Listing { + "references/plan-review.md" + "references/task-execution.md" + "references/context-sync.md" + "references/output.md" + } + ["validate"] = new Listing { + "references/validation.md" + "references/context-sync.md" + "references/validation-report.md" + "references/output.md" + } + ["commit"] = new Listing { + "references/atomic-commit.md" + "references/output.md" + } + ["handover"] = new Listing { "references/output.md" } + ["brownfield"] = new Listing { "references/output.md" } +} + local expectedSkillDocumentPaths = new Mapping { - for (_, workflow in catalog.workflows) { + for (slug, workflow in catalog.workflows) { ["\(workflow.skillSlug)/SKILL.md"] = true - ["\(workflow.skillSlug)/references/output.md"] = true + for (path in phaseReferencePathsByWorkflow[slug]) { + ["\(workflow.skillSlug)/\(path)"] = true + } } ["sce-decision/SKILL.md"] = true ["sce-decision/references/adr-template.md"] = true diff --git a/config/pkl/renderers/workflow-composite.pkl b/config/pkl/renderers/workflow-composite.pkl index 96d4c514..256faabd 100644 --- a/config/pkl/renderers/workflow-composite.pkl +++ b/config/pkl/renderers/workflow-composite.pkl @@ -80,7 +80,7 @@ local renderInternalDocuments = (workflow: CompositeWorkflow) -> /// the step that runs it, the listing is empty and no appendix heading renders. local renderSkill = (workflow: CompositeWorkflow, extraFrontmatterLines: String) -> new model.WorkflowDocument { path = "SKILL.md" - text = new Listing { + text = if (workflow.structuredSource.compositeSkillBody != null) """ --- name: \(workflow.skillSlug) @@ -88,38 +88,49 @@ local renderSkill = (workflow: CompositeWorkflow, extraFrontmatterLines: String) \(workflow.description) \(extraFrontmatterLines)--- - # \(workflow.title) - - ## Purpose - - Own this workflow from input parsing through its terminal user-visible response. - Execute the phases below directly and in order. Phase statuses are internal state, - \(siblingSkillRule.apply(workflow)) Follow the canonical workflow's steps, gates, - and stops exactly as written: never invent, skip, reorder, or merge a step. - - ## User-visible output - - Use `references/output.md` for every gate and terminal response. Render no raw - internal state. The reference contains only human-visible Markdown layouts. - User-visible output is limited to those layouts: never invent a layout, and never - wrap one in an added preamble, commentary, summary, or extra section. - - ## Composite control flow - - Keep phase results as internal state and continue immediately whenever the - canonical workflow says to continue. Stop only at a user wait or terminal branch. - Approval, clarification, revision, failed-validation repair, and bootstrap waits - resume this same skill in the same session. Never expose an internal phase result - as the workflow's final response. + \(workflow.structuredSource.compositeSkillBody) """ - renderCanonicalWorkflow.apply(workflow) - when (workflow.structuredSource.phases.length > 0) { - "## Embedded phase behavior\n\n" + renderPhases.apply(workflow) - } - when (workflow.structuredSource.internalDocuments.length > 0) { - renderInternalDocuments.apply(workflow) - } - }.join("\n\n") + else + new Listing { + """ + --- + name: \(workflow.skillSlug) + description: > + \(workflow.description) + \(extraFrontmatterLines)--- + + # \(workflow.title) + + ## Purpose + + Own this workflow from input parsing through its terminal user-visible response. + Execute the phases below directly and in order. Phase statuses are internal state, + \(siblingSkillRule.apply(workflow)) Follow the canonical workflow's steps, gates, + and stops exactly as written: never invent, skip, reorder, or merge a step. + + ## User-visible output + + Use `references/output.md` for every gate and terminal response. Render no raw + internal state. The reference contains only human-visible Markdown layouts. + User-visible output is limited to those layouts: never invent a layout, and never + wrap one in an added preamble, commentary, summary, or extra section. + + ## Composite control flow + + Keep phase results as internal state and continue immediately whenever the + canonical workflow says to continue. Stop only at a user wait or terminal branch. + Approval, clarification, revision, failed-validation repair, and bootstrap waits + resume this same skill in the same session. Never expose an internal phase result + as the workflow's final response. + """ + renderCanonicalWorkflow.apply(workflow) + when (workflow.structuredSource.phases.length > 0) { + "## Embedded phase behavior\n\n" + renderPhases.apply(workflow) + } + when (workflow.structuredSource.internalDocuments.length > 0) { + renderInternalDocuments.apply(workflow) + } + }.join("\n\n") } /// `extraFrontmatterLines` carries the target-specific routing frontmatter a @@ -428,14 +439,19 @@ workflows = new Mapping { [brownfieldWorkflow.slug] = brownfieldWorkflow } -/// Each target renders the same two documents per workflow package and differs +/// Each target renders the same package-relative workflow documents and differs /// only in the frontmatter its skill entrypoint carries. hidden skillDocuments = (extraSkillFrontmatterLines: String) -> new Mapping { for (_, workflow in workflows) { ["\(workflow.skillSlug)/SKILL.md"] = renderSkill.apply(workflow, extraSkillFrontmatterLines) - ["\(workflow.skillSlug)/references/output.md"] = new model.WorkflowDocument { - path = "references/output.md" - text = workflow.outputText + when (workflow.structuredSource.referenceDocuments.length == 0) { + ["\(workflow.skillSlug)/references/output.md"] = new model.WorkflowDocument { + path = "references/output.md" + text = workflow.outputText + } + } + for (document in workflow.structuredSource.referenceDocuments) { + ["\(workflow.skillSlug)/\(document.path)"] = document } } } diff --git a/context/architecture.md b/context/architecture.md index 806451e3..89eb9d34 100644 --- a/context/architecture.md +++ b/context/architecture.md @@ -8,14 +8,14 @@ Authored config content is standardized around one canonical Pkl source model wi Current location for canonical workflow content primitives: -- `config/pkl/base/workflow-content.pkl` (workflow command and self-contained skill-package document model, including shared document/package constructors plus typed package-vs-composite render modes, frontmatter, bodies, semantic references, structured documents, and structured composite sources whose `phases` listing defaults to empty; it also owns the mode-aware layout primitives — `headingMarker`, the `PhaseHeadings` heading-scale and step-numbering class, the separator-owning `packageOnlyBlock` / `compositeOnlyBlock` helpers, and the `commandBanner` and `inlinePhaseBody` values built on them) +- `config/pkl/base/workflow-content.pkl` (workflow command and self-contained skill-package document model, including structured composite sources with optional canonical `compositeSkillBody` plus deterministic `referenceDocuments`; it also owns the target-neutral workflow bodies and package-local phase/persisted-document Markdown for the four phase-based workflows, alongside the typed package/composite rendering primitives retained by canonical package authoring) - `config/pkl/base/workflow-catalog.pkl` (typed six-workflow catalog owning command and skill slugs, titles, descriptions, argument hints, OpenCode routing roles, Claude allowed-tool metadata, and the per-workflow `optional` flag that defaults to `false` and is `true` only for `brownfield`) - `config/pkl/base/optional-workflow-manifest.pkl` (install-time projection of the catalog's optional records into the generated `config/optional-workflows.json` manifest — `schemaVersion` plus one entry per optional workflow carrying `id`, `title`, `description`, `commandSlug`, and `skillSlug`. Optionality never affects generation: all six workflows are still generated for all three targets, so the manifest exists solely to carry optional-workflow identity out of Pkl for install-time and doctor-time consumers) - `config/pkl/base/decision-skill.pkl` (canonical standalone `sce-decision` package outside the workflow catalog; renders its decision gate, one-record and immutable-accepted-ADR rules, deterministic written-or-blocked handoff, and `references/adr-template.md` for all three targets without creating a command or prompt) -- `config/pkl/base/workflow-change-to-plan.pkl` (canonical `/change-to-plan` package with the command plus self-contained `sce-context-load` and `sce-plan-authoring` skill/reference documents mirrored from the project-root `.pi/` baseline; its structured composite source renders both phase bodies directly inside workflow steps 1 and 2 with dotted step numbering, lists no trailing phases, and retains the scaled plan-template appendix plus output references) -- `config/pkl/base/workflow-next-task.pkl` (canonical `/next-task` package with self-contained `sce-plan-review` and `sce-task-execution` documents plus the task instance from the shared context-sync skeleton; its structured composite source renders all three phase bodies directly inside workflow steps 1–3 with dotted step numbering, lists no trailing phases, and retains the implementation-gate and output references) -- `config/pkl/base/workflow-validate.pkl` (canonical `/validate` package with the self-contained `sce-validation` documents plus the plan instance from the shared context-sync skeleton; its structured composite source renders both phase bodies directly inside workflow steps 1 and 2 with dotted step numbering, lists no trailing phases, and retains the scaled plan-file validation-report appendix plus failed-validation and output references) -- `config/pkl/base/workflow-commit.pkl` (canonical `/commit` package with the self-contained `sce-atomic-commit` skill and references; its structured composite source renders the atomic-commit phase body directly inside the regular path's proposing step with dotted step numbering, lists no trailing phases, and retains internal-state vocabulary plus message-style output references. The regular path is stated before the bypass path so the bypass path's reference to the same phase — which the composite states once rather than inlining twice — always points back at an already-stated description) +- `config/pkl/base/workflow-change-to-plan.pkl` (canonical `/change-to-plan` package registering the target-neutral `SKILL.md` body plus `context-load.md`, `plan-authoring.md`, `plan-template.md`, and `output.md` package references) +- `config/pkl/base/workflow-next-task.pkl` (canonical `/next-task` package registering the target-neutral `SKILL.md` body plus `plan-review.md`, `task-execution.md`, `context-sync.md`, and `output.md` package references) +- `config/pkl/base/workflow-validate.pkl` (canonical `/validate` package registering the target-neutral `SKILL.md` body plus `validation.md`, `context-sync.md`, `validation-report.md`, and `output.md` package references) +- `config/pkl/base/workflow-commit.pkl` (canonical `/commit` package registering the target-neutral `SKILL.md` body plus `atomic-commit.md` and `output.md` package references; both regular and bypass paths read the same phase reference only after their pre-phase gate) - `config/pkl/base/workflow-context-sync.pkl` (one role-parameterized source that renders exact, self-contained task and plan context-sync skills in named semantic section order, gives each lifecycle role its own composite step heading scale, renders their synced, no-context-change, and blocked report layouts through shared named section renderers from typed role data, and exposes both skills as mode-aware structured phases for next-task and validate composition) - `config/pkl/base/workflow-handover.pkl` (canonical `/handover` package with the self-contained, phase-free `sce-handover` skill; its structured composite source has no phases and exposes one mode-invariant `references/output.md` as its sole output document, so composite rendering differs from its package-mode form only by the generic composite preamble the shared renderer supplies) - `config/pkl/base/workflow-brownfield.pkl` (canonical `/brownfield` package with the self-contained, phase-free `sce-brownfield` skill; like `workflow-handover.pkl` its structured composite source has no phases and exposes one `references/output.md` as its sole output document, and its preamble is a semantic reference so composite rendering keeps the workflow's cold-start and gap-fill scope statement the shared renderer has no generic equivalent for. It is the sixth catalog-registered workflow, composed by `workflow-composite.pkl` and generated for all three targets) @@ -26,7 +26,7 @@ Current target renderer helper modules: - `config/pkl/renderers/opencode-content.pkl` - `config/pkl/renderers/claude-content.pkl` -- `config/pkl/renderers/workflow-composite.pkl` (target-neutral composition of canonical phases into six workflow-level skills and their single `references/output.md` presentation documents; requires and consumes structured composite sources directly without prose-wide rewriting) +- `config/pkl/renderers/workflow-composite.pkl` (target-neutral composition of six workflow-level skills and deterministic package-local references; phase-based packages render named phase and persisted-document references, phase-free packages retain only `references/output.md`, and target differences remain frontmatter-only) - `config/pkl/renderers/pi-content.pkl` - `config/pkl/renderers/common.pkl` - `config/pkl/renderers/opencode-metadata.pkl` @@ -44,17 +44,17 @@ The scaffold provides stable canonical content-unit identifiers and reusable tar Renderer modules apply target-specific metadata/frontmatter rules while reusing canonical content bodies: -- All three renderers consume the six canonical workflow packages as behavior sources and emit the same six command-routed workflow packages: `sce-change-to-plan`, `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, and `sce-brownfield`. Each renderer also consumes `decision-skill.pkl` directly and emits the standalone internal `sce-decision` package with `SKILL.md` plus `references/adr-template.md`; it stays outside workflow composition and has no command or prompt. `workflow-composite.pkl` embeds the canonical phase behavior, status branches, waits, same-session resume rules, and persisted-document formats into that workflow's `SKILL.md`; phase statuses remain internal. The only sibling handoff is from the successful task/plan synchronization decision gate to `sce-decision`, once per qualifying system-wide decision, with matching ADR reuse and blocker propagation before current-state context edits. Embedding carries body text only, so the composed `SKILL.md` has exactly one frontmatter block — its own. The workflow's own `## Input`, `## Workflow`, and `## Rules` sit directly under the skill title with no wrapper section between the preamble and the first instruction, and the package-mode `SCE {WORKFLOW} $ARGUMENTS` banner is a package-only block that composite mode does not emit. A phase the workflow has not yet stated at the step that runs it renders in a trailing `## Embedded phase behavior` appendix under an `## Internal phase:` heading followed directly by that document's opening line; the appendix is emitted only while a module still lists phases, so a module that lists none renders no appendix heading at all. `/change-to-plan` inlines context load and plan authoring under steps 1 and 2 and retains its scaled plan-template appendix after `## Rules`; `/next-task` inlines plan review, task execution, and task context synchronization under steps 1–3 and emits no phase appendix. No sentence in a composed `SKILL.md` names a document that package does not contain: references to package-mode contract or format files are dropped in composite mode, and the only files a workflow document names are its own `references/output.md` and sections embedded beside it. Every package has exactly one additional file, `references/output.md`, which defines all human-visible gates and terminal Markdown for that workflow, and each `SKILL.md` branch that produces output names the `output.md` section it renders instead of restating the layout. Each thin command or prompt invokes exactly one corresponding workflow skill. +- All three renderers consume the six canonical workflow packages as behavior sources and emit the same six command-routed workflow packages: `sce-change-to-plan`, `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, and `sce-brownfield`. Each renderer also emits the standalone internal `sce-decision` package with `SKILL.md` plus `references/adr-template.md`; it stays outside workflow composition and has no command or prompt. For the four phase-based workflows, `workflow-composite.pkl` renders one `SKILL.md` that owns input parsing, phase order, branching, waits, and same-session resume, plus package-local references for each phase and persisted-document format. The applicable reference must be read before its phase runs. `references/output.md` remains the sole owner of human-visible gates and terminal layouts. Phase statuses remain internal, commands and prompts still invoke exactly one workflow skill, and the only sibling handoff remains the successful synchronization gate's bounded `sce-decision` invocation. `sce-handover` and `sce-brownfield` are phase-free and retain their two-file package shape. OpenCode, Claude, and Pi render identical package-relative inventories and document bodies for each workflow, apart from supported target frontmatter. - Per-target differences are confined to frontmatter and the surrounding non-workflow outputs. The manual OpenCode renderer adds `agent`, `entry-skill`, and a one-entry `skills` list to command frontmatter, adds `compatibility: opencode` to package entrypoints, and emits two thin routing agents. Catalog-derived workflow permissions remain role-specific; only the Code agent also allows `sce-decision` for the synchronization exception. The Claude renderer adds `compatibility: claude` plus command `allowed-tools:` and emits no agents; Claude settings and the hook helper remain separate retained outputs. The Pi renderer adds no frontmatter to either prompts or skills. -- Pi renderer consumes the same shared workflow composition as OpenCode and Claude. It emits exactly six thin prompts to `config/.pi/prompts/{slug}.md`, each routing to exactly one workflow skill, six workflow packages under `config/.pi/skills/{slug}/` containing only `SKILL.md` and `references/output.md`, and the standalone `sce-decision` package beside them. Pi prompts and skills carry no target-specific frontmatter beyond the shared description and argument hint, so Pi passes the empty extra-frontmatter string to both package render paths. It emits no Pi agent-role prompts. Pi has no settings/plugin manifest; runtime integration remains the project-local extension emitted verbatim from `config/lib/pi-plugin/sce-pi-extension.ts` to `config/.pi/extensions/sce/index.ts` (auto-discovered by Pi, no registration manifest; see `context/sce/pi-extension-runtime.md`). +- Pi renderer consumes the same shared workflow composition as OpenCode and Claude. It emits exactly six thin prompts to `config/.pi/prompts/{slug}.md`, each routing to exactly one workflow skill, four phase-reference workflow packages plus two phase-free two-file packages under `config/.pi/skills/{slug}/`, and the standalone `sce-decision` package beside them. Pi prompts and skills carry no target-specific frontmatter beyond the shared description and argument hint, so Pi passes the empty extra-frontmatter string to both package render paths. It emits no Pi agent-role prompts. Pi has no settings/plugin manifest; runtime integration remains the project-local extension emitted verbatim from `config/lib/pi-plugin/sce-pi-extension.ts` to `config/.pi/extensions/sce/index.ts` (auto-discovered by Pi, no registration manifest; see `context/sce/pi-extension-runtime.md`). - Workflow composition itself is shared rather than per target. `config/pkl/renderers/workflow-composite.pkl` owns the six composite workflow definitions and output layouts, while each composite looks up its typed identity in `config/pkl/base/workflow-catalog.pkl`. Every workflow supplies a required `StructuredCompositeSource`, so commands, phase documents, persisted-document formats, and output references render in package or composite mode before Markdown assembly. The renderer has no nullable legacy adapter, frontmatter stripping, or prose-wide replacement chain. Its `renderSkill`, `renderCommand`, and `skillDocuments` entrypoints take a newline-terminated `extraFrontmatterLines` string carrying only the frontmatter a target supports; a target that adds none passes the empty string. `renderSkill` assembles the document as an ordered section list — preamble (purpose, user-visible output, and the composite control-flow rules, all stated before the workflow's `## Input`), then the workflow body, then the phase appendix and any persisted-document formats, each emitted only when its listing is non-empty. Claude passes `compatibility: claude` for skills and a catalog-derived `allowed-tools` line for commands. The `renderSkill` preamble also carries the no-improvisation rule that every generated workflow `SKILL.md` states on every target: the executing agent follows the canonical workflow's steps, gates, and stops exactly as written and never invents, skips, reorders, or merges a step, and its user-visible output is limited to the `references/output.md` layouts with no invented layout and no added preamble, commentary, summary, or extra section. The rule is prose instruction only; the generation contract checks assert paths and metadata, not agent behavior. - Shared renderer document types and OpenCode plugin-registration helpers live in `config/pkl/renderers/common.pkl`. - The canonical OpenCode plugin-registration source for generated SCE plugins lives in `config/pkl/base/opencode.pkl`; `config/pkl/renderers/common.pkl` re-exports the shared plugin list and JSON-ready paths for OpenCode renderers, and the current generated registration scope is limited to SCE-managed plugins emitted by this repo (`sce-bash-policy` and `sce-agent-trace`). - Target renderers remain responsible for formatting target-supported metadata. OpenCode metadata owns thin-agent presentation and compatibility while deriving workflow permission lines from catalog role assignments; OpenCode command routing derives the same role and skill identity from the catalog. Claude metadata derives command tools from catalog records. Pi has no metadata module because it adds no target-specific frontmatter. -- `config/pkl/renderers/metadata-coverage-check.pkl` derives command and two-file workflow-package expectations from the typed catalog, adds the two-file standalone decision-package expectation explicitly, asserts each target's exact current inventory—six commands (Pi: prompts), seven two-file skill packages per target, and two OpenCode agents—then verifies every command's one-to-one workflow-skill route for all three targets through the target-labelled `assertCommandRoute(target, slug, document)`, and forces every rendered document and target metadata lookup to evaluate. -- `config/pkl/renderers/generation-contract-check.pkl` independently derives the complete expected artifact paths from those target document inventories plus explicitly retained non-workflow assets, compares them with `generate.pkl`'s `output.files`, and requires exactly 71 paths — stated as a literal `expectedArtifactPathCount` inside the same assertion so an unintended inventory change fails rather than redefining the expectation. It asserts the generated `config/optional-workflows.json` against the catalog (`optional-workflow-manifest`): every optional workflow appears with its catalog title and both slugs, no core workflow id appears, and `schemaVersion` is present. It also scans every generated skill-package document for stale phase-skill slugs and unresolved package-local reference tokens, asserts the exact cross-target `sce-decision` paths plus its required gate, status, immutability, handoff, and ADR-template content, permits `sce-decision` references only in `sce-next-task` and `sce-validate`, verifies the Code-only OpenCode decision permission, asserts the generated `sce-handover` `SKILL.md` covers both writer- and loader-mode content on all three targets, asserts the generated `sce-brownfield` `SKILL.md` still carries the bootstrap gate, documentation-discovery sweep, no-network rule, sub-`50` blocking threshold, always-disclosed contradiction contract, and additive-vs-`rebuild` write rule on all three targets, rejects two or more consecutive blank lines in any generated workflow document (`no-blank-line-runs`), and rejects any generated `SKILL.md` that reproduces one of its sibling `references/output.md` fenced layouts verbatim (`output-dedup`, matched fence markers included). Checked-in negative fixtures prove that deterministic extra and missing artifacts, a forbidden workflow reference, a blank-line run, and a duplicated output layout each fail the contract. +- `config/pkl/renderers/metadata-coverage-check.pkl` derives commands and exact package-relative workflow-document expectations from the typed catalog and the four phase-reference inventories, adds the unchanged phase-free and decision-package expectations, verifies every command's one-to-one workflow-skill route for all three targets, and forces every rendered document and target metadata lookup to evaluate. +- `config/pkl/renderers/generation-contract-check.pkl` independently derives the complete expected artifact paths from those target document inventories plus explicitly retained non-workflow assets, compares them with `generate.pkl`'s `output.files`, and requires exactly 101 paths — stated as a literal `expectedArtifactPathCount` inside the same assertion so an unintended inventory change fails rather than redefining the expectation. It asserts the generated `config/optional-workflows.json` against the catalog (`optional-workflow-manifest`): every optional workflow appears with its catalog title and both slugs, no core workflow id appears, and `schemaVersion` is present. It also verifies that every required phase reference exists and is cited by its owning `SKILL.md`, scans every generated skill-package document for stale phase-skill slugs and unresolved package-local reference tokens, asserts the exact cross-target `sce-decision` paths plus its required gate, status, immutability, handoff, and ADR-template content, permits `sce-decision` references only in `sce-next-task` and `sce-validate`, verifies the Code-only OpenCode decision permission, asserts the generated `sce-handover` `SKILL.md` covers both writer- and loader-mode content on all three targets, asserts the generated `sce-brownfield` `SKILL.md` still carries the bootstrap gate, documentation-discovery sweep, no-network rule, sub-`50` blocking threshold, always-disclosed contradiction contract, and additive-vs-`rebuild` write rule on all three targets, rejects two or more consecutive blank lines in any generated workflow document (`no-blank-line-runs`), and rejects any generated `SKILL.md` that reproduces one of its sibling `references/output.md` fenced layouts verbatim (`output-dedup`, matched fence markers included). Checked-in negative fixtures prove that deterministic extra and missing artifacts, a forbidden workflow reference, a blank-line run, and a duplicated output layout each fail the contract. - OpenCode, Claude, and Pi renderers expose command documents plus flattened `{skill slug}/{package-relative path}` skill documents consumed by `config/pkl/generate.pkl`; every target's flattened inventory contains `SKILL.md` and `references/output.md` for each workflow slug plus `sce-decision/SKILL.md` and `sce-decision/references/adr-template.md`. -- `config/pkl/generate.pkl` emits deterministic `output.files` mappings for all authored generated targets: OpenCode's six workflow commands, six two-file workflow skill packages, standalone two-file decision package, and two thin routing agents; Claude's six thin commands, six two-file workflow skill packages, and standalone decision package with no agents; Claude project settings and hook helper; shared bash-policy preset assets; OpenCode plugin entrypoints (`sce-bash-policy.ts` and `sce-agent-trace.ts`); generated OpenCode `opencode.json`; the Pi target tree (six thin workflow prompts, six two-file workflow skill packages, the standalone two-file decision package, and the extension emitted verbatim from `config/lib/pi-plugin/sce-pi-extension.ts`); the generated `sce/config.json` schema artifact; and the optional-workflow manifest at `config/optional-workflows.json`. The removed `config/automated/.opencode` profile has no generator ownership or output mappings. +- `config/pkl/generate.pkl` emits deterministic `output.files` mappings for all authored generated targets: OpenCode's six workflow commands, four phase-reference workflow packages, two phase-free workflow packages, standalone two-file decision package, and two thin routing agents; Claude's six thin commands, the same workflow-package inventories, and standalone decision package with no agents; Claude project settings and hook helper; shared bash-policy preset assets; OpenCode plugin entrypoints (`sce-bash-policy.ts` and `sce-agent-trace.ts`); generated OpenCode `opencode.json`; the Pi target tree (six thin workflow prompts, the same four phase-reference and two phase-free workflow packages, the standalone two-file decision package, and the extension emitted verbatim from `config/lib/pi-plugin/sce-pi-extension.ts`); the generated `sce/config.json` schema artifact; and the optional-workflow manifest at `config/optional-workflows.json`. The removed `config/automated/.opencode` profile has no generator ownership or output mappings. - Generated-file warning markers are not injected by the generator: Markdown outputs render deterministic frontmatter + body, and shared library outputs are emitted without a leading generated warning header. - `config/pkl/check-generated.sh` is intentionally dev-shell scoped (`nix develop -c ...`): it requires `IN_NIX_SHELL`, rejects the repository-local `config/pkl/rendered` evaluation artifact before generation, rejects committed target trees, the generated SCE schema, and `cli/assets/generated`, evaluates exact metadata and generation contracts, confirms the extra/missing/reference/blank-line-run/output-dedup negative fixtures fail with their contract diagnostics, then delegates two-pass generation, input checks, and payload inventories to `scripts/produce-cli-generated-input.sh`. It projects the producer inventory only to preserve the established report digest path format; it does not rehash generated files. Required-path checks remain fast surface diagnostics, the Pkl contract owns exact complete-path coverage, and forbidden-output checks reject removed generator surfaces. diff --git a/context/context-map.md b/context/context-map.md index 24bf03db..2a1d1f1c 100644 --- a/context/context-map.md +++ b/context/context-map.md @@ -29,12 +29,12 @@ Feature/domain context: - `context/sce/cli-shell-completion-contract.md` (implemented `sce completion` contract for deterministic Bash/Zsh/Fish completion script generation) - `context/sce/claude-raw-hook-capture.md` (removed feature: the former `sce hooks claude-capture` raw-capture route and its supporting types, replaced by the active `diff-trace` and `conversation-trace` intakes) - `context/sce/cli-observability-contract.md` (implemented config-backed runtime observability contract for the flat logging config-file shape with `log_dir` / `SCE_LOG_DIR` env-over-config-over-`/sce/logs` fallback, append-only local-date/session log file routing with a one-time complete-record `-v2.log` fallback on primary open/append/flush failure, creation-triggered retention of direct regular `*.log` files to 10 entries, reliable producer-native diff-trace/conversation-trace session routing and hook-specific non-duplicated Agent Trace DB-open error events, deterministic session filename sanitization, concrete logger/telemetry runtime behavior plus logger and object-safe telemetry trait boundaries, AppContext observability wiring, generic `RunOutcome` final rendering, runtime-classified repeated telemetry action protection, operator-facing `sce config show` observability reporting, and the trimmed `sce config validate` status-only validation surface) -- `context/sce/shared-context-code-workflow.md` (canonical `/next-task` and `/validate` lifecycles, internal phase ownership, cross-target single-skill composition, and the sole synchronization-scoped `sce-decision` sibling invocation with ADR reuse/blocker propagation) -- `context/sce/shared-context-plan-workflow.md` (canonical `/change-to-plan` workflow, clarification/readiness gate contract, one-task/one-atomic-commit task slicing, and cross-target `sce-change-to-plan` ownership) +- `context/sce/shared-context-code-workflow.md` (canonical `/next-task` and `/validate` lifecycles, package-local phase references with single-skill control flow, and the sole synchronization-scoped `sce-decision` sibling invocation with ADR reuse/blocker propagation) +- `context/sce/shared-context-plan-workflow.md` (canonical `/change-to-plan` workflow, package-local context-load/plan-authoring/template references, clarification/readiness gate contract, and one-task/one-atomic-commit task slicing) - [Context workflow rules](sce/context-workflow-rules.md) (canonical bootstrap, ongoing context maintenance, task synchronization, plan synchronization, hygiene, discoverability, and feature-existence rules) - `context/sce/plan-code-overlap-map.md` (overlap matrix for thin OpenCode Plan/Code routing agents and workflow phase ownership; its original three-workflow inventory predates the generated `/commit` package) - `context/sce/dedup-ownership-table.md` (canonical owner-vs-consumer boundaries for workflow packages, canonical phase modules, the shared sync skeleton, and thin OpenCode agents; its original three-workflow/seven-skill inventory predates generated `/commit` and `sce-atomic-commit`) -- [Atomic commit workflow](sce/atomic-commit-workflow.md) (`/commit` regular proposal-only mode vs `oneshot`/`skip` bypass mode, staged-truth and plan-citation rules, canonical `sce-atomic-commit` phase ownership, and the cross-target composite `sce-commit` package) +- [Atomic commit workflow](sce/atomic-commit-workflow.md) (`/commit` regular proposal-only mode vs `oneshot`/`skip` bypass mode, staged-truth and plan-citation rules, and the cross-target `sce-commit` package with package-local atomic-commit instructions) - [Brownfield workflow](sce/brownfield-workflow.md) (`/brownfield`, the sixth canonical SCE workflow, generated for OpenCode, Claude, and Pi from `config/pkl/base/workflow-brownfield.pkl`: the `[rebuild] [path ...]` argument contract, bootstrap gate, local-only evidence priority order with documentation sweep and three-month history floor, the `1`–`100` confidence model with its sub-`50` blocking clarification gate, always-disclosed contradiction handling, the additive-by-default writing contract whose sole rewrite path is `rebuild`, and its opt-in install status as the only optional workflow) - [Handover workflow](sce/handover-workflow.md) (`/handover`, the fifth canonical SCE workflow, generated for OpenCode, Claude, and Pi from `config/pkl/base/workflow-handover.pkl`: dual writer/loader mode routing, the phase-free `sce-handover` two-file package, active-task-or-timestamped writer naming, the four-section persisted handover document, and the read-only loader contract) - `context/sce/automated-profile-contract.md` (deterministic gate policy for automated OpenCode profile, including 10 gate categories, permission mappings, automated `/commit` single-commit execution behavior, and automated profile constraints) @@ -100,7 +100,8 @@ Recent decision records: - `context/decisions/2026-07-31-brownfield-sixth-cross-target-workflow.md` (registers `/brownfield` as the sixth catalog-registered, phase-free cross-target workflow and authorizes it as a bounded second writer of durable `context/` outside the synchronization lifecycle, additive by default with an explicit `rebuild` token as its sole rewrite path) - `context/decisions/2026-07-31-install-time-optional-workflows.md` (makes workflow optionality an install-time concern only: a catalog `optional` flag carried through the generated `config/optional-workflows.json` manifest into a build-generated Rust catalog, a per-repository `integrations.optional_workflows` selection with reuse-when-absent precedence, and one shared install/doctor asset filter; generation stays unconditional and `/brownfield` becomes opt-in) - `context/decisions/2026-07-29-claude-workflow-skill-packages.md` (the four command-to-workflow-skill routes, two-file package rule, and internal phase state, first established for Claude; its Claude-only scoping and Pi/OpenCode preservation clauses are superseded) -- `context/decisions/2026-07-29-cross-target-workflow-skill-packages.md` (accepted history for the cross-target four-workflow composition model; canonical phase modules remain authoring inputs only, while its exact-package-inventory and no-sibling-invocation scope is superseded) +- `context/decisions/2026-07-29-cross-target-workflow-skill-packages.md` (accepted history for the cross-target four-workflow single-skill model; its exact two-file phase-based package inventory is superseded, while single-skill control flow and internal phase state remain in force) +- `context/decisions/2026-08-03-package-local-phase-reference-workflow-packages.md` (supersedes the two-file clause for phase-based workflow packages: `SKILL.md` retains control flow while package-local references own phase instructions and persisted-document formats on all three targets) - `context/decisions/2026-07-30-synchronization-scoped-decision-writing.md` (accepted standalone `sce-decision` package, synchronization-only sibling invocation, decision threshold, default status, and immutable accepted-ADR policy) - `context/decisions/2026-07-27-ephemeral-pkl-build-generation.md` (removes committed generated targets; establishes pre-Cargo generation, validated copying into Cargo `OUT_DIR`, and crates.io/Flatpak packaging fallbacks) - `context/decisions/2026-03-09-migrate-lexopt-to-clap.md` (CLI argument parsing migration from lexopt to clap derive macros) diff --git a/context/decisions/2026-08-03-package-local-phase-reference-workflow-packages.md b/context/decisions/2026-08-03-package-local-phase-reference-workflow-packages.md new file mode 100644 index 00000000..9d28caa5 --- /dev/null +++ b/context/decisions/2026-08-03-package-local-phase-reference-workflow-packages.md @@ -0,0 +1,65 @@ +# Decision: Use Package-Local Phase References in Phase-Based Workflow Packages + +Date: 2026-08-03 +Status: Accepted +Plan: `context/plans/canonicalize-workflow-phase-references.md` +Task: `T01` +Supersedes in part: `context/decisions/2026-07-29-cross-target-workflow-skill-packages.md` + +## Context + +The single-skill workflow package model prevents unreliable inter-skill phase-result transport, but placing every phase instruction and persisted-document format directly in `SKILL.md` forces the agent to load the complete lifecycle before it reaches later phases. The staged Claude package refactor demonstrated a package-relative shape that preserves one invocation and internal phase state while allowing each phase document to be read only when its workflow step is reached. + +OpenCode, Claude, and Pi must continue to receive the same workflow behavior and package-relative inventory, with target differences limited to supported frontmatter. Human-visible gates and terminal layouts must remain owned only by `references/output.md`. + +## Decision + +Every phase-based generated workflow package uses one `SKILL.md` for control flow and package-local Markdown references for phase instructions and persisted-document formats. `SKILL.md` parses input, orders phases, branches on internal state, owns waits and same-session resume, and requires the applicable reference to be read before that phase runs. OpenCode, Claude, and Pi render the same reference inventory and document bodies, apart from supported target frontmatter. + +Phase-free workflows retain their existing two-file package shape. The standalone decision package remains unchanged. + +## Rationale + +This keeps the single-skill execution boundary that solved phase-result transport failures while reducing initial instruction loading and making phase ownership explicit. Package-relative references preserve self-containment: no command invokes a phase skill, no phase state crosses package boundaries, and every referenced instruction ships beside its workflow entrypoint. + +## Alternatives considered + +- **Keep all phase instructions inline in `SKILL.md`** — This preserves single-file loading but requires every run to load phases it may never reach and obscures phase-specific ownership. +- **Restore generated phase-skill packages** — This would recreate the unreliable inter-skill transport boundary the single-skill model removed. +- **Apply the reference split only to Claude** — This would reintroduce target-specific workflow composition and inventory drift. + +## Compatibility and risks + +- Existing installed workflow package inventories change for the four phase-based workflows; setup's remove-and-replace installation policy handles stale files. +- A missing, stale, or unresolved reference could omit load-bearing behavior. Exact metadata and generation contracts therefore check package inventories, resolvable phase references, output-layout deduplication, and forbidden sibling-package references. +- Workflow gates, statuses, waits, branches, routing, and user-visible layouts remain behaviorally compatible. + +## Guardrails + +- Commands and prompts invoke exactly one workflow skill and never sequence phase skills. +- `SKILL.md` remains the sole owner of phase ordering, branching, waits, and same-session resume. +- A phase reference is read before its phase takes action; references are package-local. +- `references/output.md` remains the sole owner of human-visible gates and terminal layouts. +- Phase-free workflows and the decision package do not gain empty phase references. +- Target-specific differences remain limited to supported frontmatter. + +## Consequences + +- The exact two-file clause for phase-based packages in the superseded decision no longer applies; those packages contain `SKILL.md`, `references/output.md`, and their named phase or persisted-document references. +- Canonical Pkl owns the workflow body and complete package-relative document inventory for all three targets. +- Phase behavior remains internal to one skill invocation and no serialized phase-result contract is reintroduced. +- The generated artifact contract increases from 71 to 101 paths. + +## Follow-up + +- None. + +## References + +- Plan: [`canonicalize-workflow-phase-references`](../plans/canonicalize-workflow-phase-references.md) +- Task: `T01` +- Current-state context: [`Architecture`](../architecture.md) +- Current-state context: [`Patterns`](../patterns.md) +- Evidence: [`Canonical workflow content`](../../config/pkl/base/workflow-content.pkl) +- Evidence: [`Generation contract`](../../config/pkl/renderers/generation-contract-check.pkl) +- Related decision: [`Render Every Target's Workflows as Single-Skill Packages`](2026-07-29-cross-target-workflow-skill-packages.md) diff --git a/context/glossary.md b/context/glossary.md index da17bdd0..f070a991 100644 --- a/context/glossary.md +++ b/context/glossary.md @@ -1,6 +1,6 @@ # Glossary -- `pkl-check-generated`: Flake app exposed as `nix run .#pkl-check-generated`; canonical ephemeral-generation check that rejects committed target/schema/mirror outputs, evaluates exact workflow metadata, the complete 71-path generated artifact contract, and the optional-workflow manifest's content against the catalog, rejects stale sibling-package references or unresolved internalization tokens, proves extra/missing/reference failures through negative fixtures, and delegates deterministic generation plus payload/input inventories to the generated-input producer while preserving its established inventory report. +- `pkl-check-generated`: Flake app exposed as `nix run .#pkl-check-generated`; canonical ephemeral-generation check that rejects committed target/schema/mirror outputs, evaluates exact workflow metadata, the complete 101-path generated artifact contract, and the optional-workflow manifest's content against the catalog, rejects stale sibling-package references or unresolved internalization tokens, proves extra/missing/reference failures through negative fixtures, and delegates deterministic generation plus payload/input inventories to the generated-input producer while preserving its established inventory report. - `repo-level verification preference`: Current repository guidance that contributor-facing validation/check flows should prefer `nix flake check`; direct Cargo verification commands are secondary and used only when explicitly requested or for narrow targeted debugging, while `cargo fmt` remains the explicit autofix path. - lightweight post-task verification baseline: Required quick checks after each completed task in this repo: `nix run .#pkl-check-generated` and `nix flake check`. - disposable plan lifecycle: Policy where `context/plans/` holds active execution artifacts only; completed plans are disposable and durable outcomes must be reflected in current-state context files and/or `context/decisions/`. @@ -9,8 +9,8 @@ - ephemeral generated payload: Files materialized by `config/pkl/generate.pkl` using payload-relative `config/.opencode/**`, `config/.claude/**`, `config/.pi/**`, and `config/schema/sce-config.schema.json` paths beneath Cargo `OUT_DIR`, temporary previews, or packaging fallbacks. These layouts are installed by `sce setup` but are never committed as repository target trees; `config/automated/.opencode/**` remains a forbidden generator surface. - `CLI generated-input handoff`: Repository-build contract rooted at the temporary directory named by `SCE_CLI_GENERATED_INPUT_DIR`. `config/pkl/generator-inputs.txt` declares the canonical `config/pkl` and referenced `config/lib` inputs; `scripts/produce-cli-generated-input.sh` discovers those files, generates Pkl twice, rejects nondeterminism and in-flight input mutation, and atomically places `pkl-generated/`, its exact `SHA256SUMS`, and `INPUTS.SHA256SUMS` there. `scripts/run-cli-cargo.sh` delegates production and removes its temporary handoff after Cargo exits. `cli/build.rs` verifies payload integrity and input freshness before copying `pkl-generated/` into Cargo `OUT_DIR`; missing, incomplete, modified, or stale handoffs fail rather than invoking Pkl or falling back to packaged assets. - `generated-input producer`: Repository-owned `scripts/produce-cli-generated-input.sh` contract driven by `config/pkl/generator-inputs.txt`. It is the canonical owner for expanding repository-relative generator inputs, snapshotting their inventory, two-pass Pkl evaluation, byte-tree determinism comparison, payload and canonical-input SHA-256 inventories, input-mutation rejection, atomic output publication, and private staging cleanup. The repository Cargo wrapper, generated-output check, package-fallback preparation, and Nix `cliGeneratedInput` derivation all consume it. -- `Pi workflow package`: Generated Pi workflow surface consisting of one thin prompt in `config/.pi/prompts/` plus the one workflow skill package under `config/.pi/skills/` that the prompt routes to, containing exactly `SKILL.md` and `references/output.md`. Pi currently receives `/change-to-plan`, `/next-task`, `/validate`, `/commit`, `/handover`, and `/brownfield` this way and has no generated agent-role prompts. -- `workflow skill package`: One of the six renderer-composed packages (`sce-change-to-plan`, `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, `sce-brownfield`) emitted for every target. Its `SKILL.md` directly owns the complete canonical phase sequence (empty for `sce-handover` and `sce-brownfield`, which have none), internal status branching, user waits and same-session resume behavior, writes, and continuation; it invokes no phase skill. The sole sibling exception lets successful `sce-next-task` and `sce-validate` synchronization invoke `sce-decision` for one qualifying system-wide decision. Its only other file is `references/output.md`. The canonical phase modules remain authoring inputs to composition and are not generated as packages for any target. +- `Pi workflow package`: Generated Pi workflow surface consisting of one thin prompt in `config/.pi/prompts/` plus the one workflow skill package under `config/.pi/skills/` that the prompt routes to. Phase-based workflows include `SKILL.md`, `references/output.md`, and named phase or persisted-document references; phase-free workflows contain the two core files only. Pi currently receives `/change-to-plan`, `/next-task`, `/validate`, `/commit`, `/handover`, and `/brownfield` this way and has no generated agent-role prompts. +- `workflow skill package`: One of the six renderer-composed packages (`sce-change-to-plan`, `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, `sce-brownfield`) emitted for every target. Its `SKILL.md` owns the canonical phase sequence, internal status branching, user waits and same-session resume behavior, and continuation; each phase-based workflow reads package-local phase references before acting, while `sce-handover` and `sce-brownfield` have no phases and retain two-file packages. The sole sibling exception lets successful `sce-next-task` and `sce-validate` synchronization invoke `sce-decision` for one qualifying system-wide decision. `references/output.md` remains the sole owner of human-visible layouts. The canonical phase modules remain authoring inputs to composition and are not generated as packages for any target. - `decision skill package`: Standalone internal `sce-decision` package emitted for OpenCode, Claude, and Pi from `config/pkl/base/decision-skill.pkl`, outside the command workflow catalog. Its `SKILL.md` accepts one qualifying system-wide decision from successful task or plan synchronization, enforces one dated ADR with allowed status vocabulary and `Accepted` default, never edits an accepted ADR, and returns a deterministic written-or-blocked handoff. Its only other file is `references/adr-template.md`; no user-facing command or prompt routes to it, and no workflow invokes it outside the synchronization decision gate. - `workflow catalog`: The typed mapping in `config/pkl/base/workflow-catalog.pkl` that declares each of the six workflows once and owns its command slug, skill slug, title, description, argument hint, OpenCode routing role, Claude allowed tools, and its `optional` flag. Composite identity, OpenCode routing/permissions, Claude tool frontmatter, and metadata coverage derive from these records; behavior remains in canonical phase modules and formatting remains renderer-owned. - `optional workflow`: A catalog workflow whose `WorkflowRecord.optional` flag is `true`. Optionality is an install-time concern only: the workflow is still authored, composed, and generated for OpenCode, Claude, and Pi exactly like a core workflow, and its generated files remain part of the ephemeral payload and the generation contract. `brownfield` is the only optional workflow; the other five leave the flag at its `false` default. @@ -24,11 +24,12 @@ - brownfield confidence model: The internal `1`–`100` score `sce-brownfield` assigns to every fact it would write as durable truth, banded as `Verified` (`90`–`100`), `Strongly supported` (`70`–`89`), `Inferred` (`50`–`69`), and `Clarification required` (`1`–`49`), plus `Contradiction resolved` for a fact scored after conflicting evidence was resolved. Anything below `50` blocks with grouped clarification questions and is never written as truth. Scores are internal state and chat evidence only; no score is written under `context/`. - brownfield `rebuild` mode: The mode `sce-brownfield` enters when the literal token `rebuild` is the first argument, and the only thing that grants it rewrite authority over existing context files. Writes are otherwise additive — missing files and missing domains only. Even in `rebuild` mode no context file is deleted, `context/plans/`, `context/handovers/`, `context/decisions/`, and `context/tmp/` are untouched, and a file with uncommitted changes is not modified. The mode is never inferred from conversation content or repository state. - handover document: The four-required-section Markdown file (`Current Task State`, `Decisions Made`, `Open Questions / Blockers`, `Next Recommended Step`, plus a trailing `Assumptions` section) that `sce-handover` writer mode persists under `context/handovers/`, named by the active plan task or a collision-safe timestamp when no single task is unambiguous. -- `workflow composite renderer`: The shared, target-neutral Pkl module at `config/pkl/renderers/workflow-composite.pkl` that composes a canonical workflow command, its phase skills, and its persisted-document formats into one workflow-level `SKILL.md` plus that package's `references/output.md`. It requires structured composite sources for all six workflows and performs no frontmatter stripping or prose-wide internalization. All three targets render through it, parameterized only by the extra frontmatter each supports. +- `workflow composite renderer`: The shared, target-neutral Pkl module at `config/pkl/renderers/workflow-composite.pkl` that renders each canonical workflow as one workflow-level `SKILL.md` plus deterministic package-local documents. The four phase-based workflows emit named phase and persisted-document references; phase-free workflows emit only `references/output.md` beside the entrypoint. It requires structured composite sources for all six workflows and performs no frontmatter stripping or prose-wide internalization. All three targets render through it, parameterized only by the extra frontmatter each supports. - `structured workflow rendering`: Canonical Pkl representation in `workflow-content.pkl` where package-vs-composite mode is selected through typed frontmatter, body, semantic-reference, structured-document, composite-source, heading-scale (`PhaseHeadings`), and single-mode block values before Markdown assembly. All six workflows render their commands, internal phases, persisted-document formats where applicable, and output references directly in both modes without frontmatter stripping or prose-wide replacement. - `canonical phase module`: One of the eight phase definitions in `config/pkl/base/workflow-*.pkl` (`sce-context-load`, `sce-plan-authoring`, `sce-plan-review`, `sce-task-execution`, `sce-task-context-sync`, `sce-validation`, `sce-plan-context-sync`, `sce-atomic-commit`). Each is the single behavioral source for its phase and an authoring input to the composite renderer. Since 2026-07-29 no target generates them as installable skill packages; the names denote canonical source and the internal phases inside a composed `SKILL.md`. - `extra frontmatter lines`: The newline-terminated string a target passes to the workflow composite renderer carrying only the frontmatter its skills or commands support (for example `compatibility: claude`, or an `allowed-tools:` line). It is the sole per-target parameter of composition; a target that adds no frontmatter passes the empty string. -- `workflow output reference`: The required `references/output.md` in every workflow skill package. It is the package's only reference file and defines all and only that workflow's human-visible Markdown gates, reports, and terminal layouts; operational instructions and persisted-file formats remain in `SKILL.md`. It is also the single statement of each layout: a `SKILL.md` branch that produces output cites the section it renders by heading rather than reproducing it. +- `workflow phase reference`: A package-local Markdown document emitted for one phase-based workflow step, such as `references/plan-review.md` or `references/context-sync.md`. It owns that phase's operational steps and boundaries and is read before the phase takes action; it does not create a sibling skill or transport phase state. +- `workflow output reference`: The required `references/output.md` in every workflow skill package. It defines all and only that workflow's human-visible Markdown gates, reports, and terminal layouts. Phase-based packages also carry operational phase and persisted-document references, but those never own user-visible layouts. It is also the single statement of each layout: a `SKILL.md` branch that produces output cites the section it renders by heading rather than reproducing it. - `no-improvisation rule`: The agent-behavior policy stated by the shared `renderSkill` preamble in every generated workflow `SKILL.md`, on every target. Its process half forbids inventing, skipping, reordering, or merging the canonical workflow's steps, gates, and stops; its output half limits user-visible output to the `references/output.md` layouts, forbidding invented layouts and any added preamble, commentary, summary, or extra section around them. It is prose instruction, not a machine-checked contract. See `context/architecture.md`. - `atomic commit bypass mode`: The `/commit` mode selected when the exact first argument token is `oneshot` or `skip` (case-insensitive; the two aliases are behaviorally identical). It skips the staging-confirmation prompt and the context-file guidance gate, requires exactly one commit message covering all staged files with no split proposals, makes plan citations best-effort instead of blocking, and lets the command run exactly one `git commit`. Any other first token selects proposal-only regular mode. See `context/sce/atomic-commit-workflow.md`. - `canonical OpenCode plugin registration source`: Shared Pkl-authored plugin-registration definition in `config/pkl/base/opencode.pkl`, re-exported from `config/pkl/renderers/common.pkl` as the canonical plugin list/path JSON consumed by OpenCode renderers before they emit generated `opencode.json` manifests; the current entries are `sce-bash-policy` and `sce-agent-trace`. diff --git a/context/overview.md b/context/overview.md index 7008b7cf..5f066d29 100644 --- a/context/overview.md +++ b/context/overview.md @@ -1,6 +1,6 @@ # Overview -This repository maintains shared assistant configuration for OpenCode, Claude, and Pi from a single canonical Pkl authoring source. One typed workflow catalog owns the six workflows' shared identity and target routing metadata, while canonical phase modules own behavior and target renderers own formatting. Generated target layouts are ephemeral: repository builds consume a pre-Cargo generated payload through `SCE_CLI_GENERATED_INPUT_DIR`, crates.io and Flatpak stage packaging-only fallbacks, and `config/.opencode`, `config/.claude`, `config/.pi`, and the generated SCE config schema are not committed. The catalog also marks a workflow `optional` — currently only `brownfield` — which changes nothing about generation and is projected into a generated `config/optional-workflows.json` manifest for install-time consumers. `nix run .#pkl-check-generated` preserves its exact 71-path artifact, metadata/package, internal-reference, optional-workflow-manifest, required-path, and forbidden-path checks while delegating deterministic payload production and inventories to the shared generated-input producer; `nix flake check` runs the same contract. The target matrix contains one manual OpenCode profile plus Claude and Pi; the former automated OpenCode profile has been removed. +This repository maintains shared assistant configuration for OpenCode, Claude, and Pi from a single canonical Pkl authoring source. One typed workflow catalog owns the six workflows' shared identity and target routing metadata, while canonical phase modules own behavior and target renderers own formatting. Generated target layouts are ephemeral: repository builds consume a pre-Cargo generated payload through `SCE_CLI_GENERATED_INPUT_DIR`, crates.io and Flatpak stage packaging-only fallbacks, and `config/.opencode`, `config/.claude`, `config/.pi`, and the generated SCE config schema are not committed. The catalog also marks a workflow `optional` — currently only `brownfield` — which changes nothing about generation and is projected into a generated `config/optional-workflows.json` manifest for install-time consumers. `nix run .#pkl-check-generated` preserves its exact 101-path artifact, metadata/package, phase-reference, internal-reference, optional-workflow-manifest, required-path, and forbidden-path checks while delegating deterministic payload production and inventories to the shared generated-input producer; `nix flake check` runs the same contract. The target matrix contains one manual OpenCode profile plus Claude and Pi; the former automated OpenCode profile has been removed. It also includes a Rust CLI (`sce`) for Shared Context Engineering workflows: auth, config inspection, setup, doctor, agent-trace hooks, bash-policy evaluation, and trace database inspection. See `context/architecture.md` for module-level boundaries and `context/context-map.md` for the full domain file index. @@ -56,7 +56,7 @@ The repository root now also owns the canonical Biome contract for the current J Flatpak validation/build orchestration is reduced to a minimal app surface: Linux flake apps expose the umbrella `sce-flatpak` (`nix run .#sce-flatpak -- ` for `validate`, `prepare-local-manifest`, etc.) plus `release-flatpak-package`, `release-flatpak-bundle`, and the `regenerate-flatpak-manifest` / `regenerate-cargo-sources` helpers; the previously separate `flatpak-validate`, `flatpak-local-manifest`, and `flatpak-build` wrapper apps are removed. Default `nix flake check` keeps the lightweight Nix-built static/AppStream validator plus the parity checks (`flatpak-manifest-parity`, `cargo-sources-parity`) and does not run a network-heavy Flatpak build. The former standalone install-channel integration runner and `install-channel-integration-tests` flake app are not active current-state surfaces. Shared Context Plan and Shared Context Code remain separate OpenCode routing roles: the generated Plan agent routes only to `/change-to-plan`, while the generated Code agent routes to `/next-task`, `/validate`, `/commit`, `/handover`, and `/brownfield`. Workflow behavior lives in the six workflow entrypoints and their six skill packages rather than in agent bodies. `config/pkl/base/workflow-catalog.pkl` assigns each workflow to its role, and OpenCode command routing plus each agent's `skill:` permission allowlist derive from those records: `sce-change-to-plan` for Plan; `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, and `sce-brownfield` for Code. The canonical workflow definitions remain phase-decomposed as authoring source: `/change-to-plan` sequences `sce-context-load` then `sce-plan-authoring`; `/next-task` sequences `sce-plan-review`, `sce-task-execution`, and `sce-task-context-sync`; `/validate` sequences `sce-validation` then `sce-plan-context-sync`; `/commit` delegates staged-diff analysis and message generation to `sce-atomic-commit`; `/handover` has no phases, since writer and loader mode never invoke a sibling or wait mid-run; `/brownfield` likewise has none, since its single skill owns investigation, the blocking clarification gate, writing, and reporting itself. No target generates those phase modules as packages. All three consume them as inputs to the shared `workflow-composite.pkl` renderer, which composes each workflow into one skill package. Every workflow supplies typed package/composite render values for frontmatter, bodies, semantic references, phases, persisted-document formats where applicable, and output references; the composite renderer performs no prose-wide internalization or frontmatter stripping. -Every target preserves the same gates and lifecycle semantics through six renderer-composed workflow packages: `sce-change-to-plan`, `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, and `sce-brownfield`. Each thin command or Pi prompt invokes exactly one corresponding skill, and OpenCode command frontmatter names that single skill as both `entry-skill` and the whole `skills` chain. Each package contains only `SKILL.md`, which owns all canonical phase behavior and internal status branching, plus `references/output.md`, which is the sole definition of that workflow's human-visible gates and terminal Markdown. No target emits phase-skill packages or inter-skill machine contracts; phase statuses stay internal to one skill invocation. +Every target preserves the same gates and lifecycle semantics through six renderer-composed workflow packages: `sce-change-to-plan`, `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, and `sce-brownfield`. Each thin command or Pi prompt invokes exactly one corresponding skill, and OpenCode command frontmatter names that single skill as both `entry-skill` and the whole `skills` chain. Each phase-based package keeps control flow, internal status branching, waits, and same-session resume in `SKILL.md`, while package-local Markdown references own phase instructions and persisted-document formats; `references/output.md` remains the sole definition of human-visible gates and terminal Markdown. Phase-free workflows retain `SKILL.md` plus `references/output.md`. No target emits phase-skill packages or inter-skill machine contracts; phase statuses stay internal to one skill invocation. Context sync uses an important-change gate: cross-cutting/policy/architecture/terminology changes require root shared-file edits, while localized tasks run verify-only root checks without default churn. OpenCode and Claude no longer generate legacy bootstrap or context-sync skills; `/commit` and `/handover` are generated only as catalog-registered composite workflow packages. OpenCode retains only thin routing agents, while Claude emits no agents. The superseded grouped Markdown catalog and automated OpenCode profile have been removed from Pkl ownership and generated outputs. The prior no-git-wrapper Agent Trace design artifacts under `context/sce/agent-trace-*.md` are retained only as historical reference; the current CLI runtime no longer wires the removed Agent Trace schema adaptation, payload building, retry replay, or rewrite handling paths into local hook execution. @@ -102,7 +102,7 @@ Lightweight post-task verification baseline (required after each completed task) ## Cross-target parity -- OpenCode, Claude, and Pi are generated from canonical Pkl content with per-target capability mapping. All three receive the same six command-routed workflow packages plus a standalone internal `sce-decision` package. The decision package contains `SKILL.md` and `references/adr-template.md`, defines one qualifying system-wide decision per immutable dated ADR, defaults new records to `Accepted`, and returns a written-or-blocked internal handoff. It has no user-facing command or prompt and is not part of the workflow catalog. Successful task and plan synchronization apply the system-wide decision gate before current-state context edits, reuse existing ADRs, and invoke `sce-decision` only for qualifying decisions; this is the sole sibling-skill exception. Pi consumes exactly six thin prompts with no agent-role prompts and no added frontmatter. Manual OpenCode consumes exactly six commands plus two thin routing agents, and its Code agent alone allows internal `sce-decision` invocation. Claude consumes exactly six thin commands with no generated agents; its generated settings and hook helper remain. Every command-routed workflow package still contains only `SKILL.md` and `references/output.md`. +- OpenCode, Claude, and Pi are generated from canonical Pkl content with per-target capability mapping. All three receive the same six command-routed workflow packages plus a standalone internal `sce-decision` package. The decision package contains `SKILL.md` and `references/adr-template.md`, defines one qualifying system-wide decision per immutable dated ADR, defaults new records to `Accepted`, and returns a written-or-blocked internal handoff. It has no user-facing command or prompt and is not part of the workflow catalog. Successful task and plan synchronization apply the system-wide decision gate before current-state context edits, reuse existing ADRs, and invoke `sce-decision` only for qualifying decisions; this is the sole sibling-skill exception. Pi consumes exactly six thin prompts with no agent-role prompts and no added frontmatter. Manual OpenCode consumes exactly six commands plus two thin routing agents, and its Code agent alone allows internal `sce-decision` invocation. Claude consumes exactly six thin commands with no generated agents; its generated settings and hook helper remain. The four phase-based command-routed packages add package-local phase and persisted-document references beside `SKILL.md` and `references/output.md`; the two phase-free workflows retain their two-file packages. - When capabilities differ, parity is implemented by supported target-specific behavior rather than forcing unsupported fields. ## Context navigation diff --git a/context/patterns.md b/context/patterns.md index 713e6f07..3f06b00b 100644 --- a/context/patterns.md +++ b/context/patterns.md @@ -70,17 +70,17 @@ - Use the project-root `.pi/` workflows as the behavioral baseline for canonical workflow packages; do not use generated target Markdown as an authoring source. - Keep OpenCode agents as thin routing surfaces when canonical workflow commands and skills own the behavior; do not duplicate workflow doctrine in agent bodies. - Implement target-specific formatting in dedicated renderer modules under `config/pkl/renderers/`, but keep workflow composition itself in the shared `workflow-composite.pkl`. Every canonical workflow must choose package-vs-composite wording through typed semantic references before Markdown assembly, not by stripping frontmatter or post-processing prose. Require a structured composite source for each workflow and do not reintroduce a legacy rewrite path. A target parameterizes composition only through the frontmatter lines it supports, never by forking the composition logic. -- Compose each canonical workflow into one workflow-level skill package for every generated target; keep phase status handling internal to `SKILL.md`, emit no phase-skill package, and emit exactly one `references/output.md` containing that workflow's human-visible Markdown layouts. The canonical phase packages under `config/pkl/base/` remain authoring inputs to that composition, not a generated output surface for any target. +- Compose each canonical workflow into one workflow-level skill package for every generated target; keep phase status handling internal to `SKILL.md`, emit no phase-skill package, and emit exactly one `references/output.md` containing that workflow's human-visible Markdown layouts. For the four phase-based workflows, emit named package-local phase and persisted-document references and require `SKILL.md` to read each reference before its phase runs. Phase-free workflows retain their two-file package shape. - Keep cross-workflow agent-behavior policy such as the no-improvisation rule in the shared `renderSkill` preamble of `workflow-composite.pkl`, which every workflow and target already composes through. Do not copy the same prose into the four canonical `workflow-*.pkl` modules or into per-workflow `references/output.md` bodies, and do not add a strictness knob or per-workflow override for it. - Keep shared renderer document and plugin-registration contracts in `config/pkl/renderers/common.pkl`; workflow identity metadata belongs in the typed workflow catalog rather than renderer-local description or routing maps. - Keep only actively consumed target metadata in dedicated modules (`opencode-metadata.pkl` and `claude-metadata.pkl`); Pi needs no metadata module because it adds no target-specific frontmatter. - Add OpenCode machine-readable orchestration metadata in `config/pkl/renderers/opencode-content.pkl`: catalog-derived `agent`, `entry-skill`, and a `skills` chain naming that command's single workflow skill. Derive workflow permissions from catalog role assignments, and derive the additional `sce-decision` permission only for the Code agent. - Keep `config/pkl/renderers/metadata-coverage-check.pkl` as a fail-fast exact-inventory guard deriving command slugs, skill entrypoints, and package-local workflow paths from the typed catalog, while independently retaining the expected OpenCode agent inventory and per-target one-to-one command-to-workflow-skill route assertions; run it whenever workflow documents or target metadata change. -- Keep `config/pkl/renderers/generation-contract-check.pkl` independent of `generate.pkl` output assembly when deriving expected paths: build the exact target paths from renderer document inventories, name retained non-workflow assets explicitly, compare against all `output.files`, and reject stale phase-skill slugs or package-local reference tokens in generated workflow documents. It also rejects two or more consecutive blank lines in any generated workflow document (`no-blank-line-runs`) and any `SKILL.md` that reproduces a sibling `references/output.md` fenced layout verbatim (`output-dedup`). Preserve controlled negative fixtures for extra paths, missing paths, forbidden references, blank-line runs, and duplicated output layouts. +- Keep `config/pkl/renderers/generation-contract-check.pkl` independent of `generate.pkl` output assembly when deriving expected paths: build the exact target paths from renderer document inventories, name retained non-workflow assets explicitly, compare against all `output.files`, require every phase-based `SKILL.md` to cite each emitted phase reference, and reject stale phase-skill slugs or unresolved package-local reference tokens in generated workflow documents. It also rejects two or more consecutive blank lines in any generated workflow document (`no-blank-line-runs`) and any `SKILL.md` that reproduces a sibling `references/output.md` fenced layout verbatim (`output-dedup`). Preserve controlled negative fixtures for extra paths, missing paths, forbidden references, blank-line runs, and duplicated output layouts. - Workflow renderers may extend canonical frontmatter only with target-supported metadata, must preserve behavior, and append only the required final newline at the output mapping. Structured composition renders semantic package/composite differences at their source while preserving one owner for every canonical gate, branch, write, and continuation. Composite mode emits a document's body only: frontmatter is a package-mode concern, so an embedded command or phase contributes no `name:`, `description:`, or `argument-hint:` line to the composed `SKILL.md`. Suppression happens in the typed model, never by parsing or stripping Markdown markers. Every reference a rendered document states must resolve in the mode that states it: composite text may name a section embedded in the same `SKILL.md` or the sibling `references/output.md`, but a sentence whose only target is a package-mode file — a `references/*-contract.yaml`, a removed `.md`, or the composed workflow itself — is package-only and its composite spelling drops the sentence rather than pointing at nothing. A phase's terminal internal states are named by its own steps, so dropping such a pointer removes no instruction. Migrate one workflow at a time and compare its OpenCode, Claude, and Pi paths against a retained pre-task root. Byte-identical generated payload is the regression guard for refactors that must preserve output; when a change intentionally alters generated text, the guard becomes the reviewed diff against that retained root, showing only the intended additions and removals. -- Every target's commands (Pi: prompts) must stay thin and invoke exactly one corresponding workflow skill (`sce-change-to-plan`, `sce-next-task`, `sce-validate`, or `sce-commit`). They must not sequence phase skills. The workflow skill executes embedded phases directly and keeps phase statuses as internal state. Only the successful task/plan synchronization decision gate may invoke sibling `sce-decision`; preserve that exception as exact rather than general sibling orchestration. -- A workflow package contains exactly two files: `SKILL.md` and `references/output.md`. Put operational phase instructions and persisted-file templates in `SKILL.md`; put every and only human-visible gate, report, and terminal response layout in `output.md`. State each layout exactly once inside `output.md`: when a phase's return-value layout and a workflow branch's layout describe the same output, keep the fuller statement (the one carrying every status variant, field, and report rule) and let the other place point at that section by heading instead of restating it. An `output.md` section must not reference a document outside its own package; a mode-aware semantic reference is how composite text names the embedded section that replaced a package-mode file. A composed `SKILL.md` states no layout of its own: a branch that produces user-visible output names the `output.md` section it renders (`Render the **{Section}** layout from `references/output.md`.`) and keeps only what `output.md` does not carry — the branch condition, the field mapping that fills the layout, the wait, and every prohibition. Model this per layout as a mode-aware semantic reference whose package spelling is the inline block a standalone command file still owns and whose composite spelling is the citation; do not achieve it by deleting text the sibling `output.md` never states. Wait points such as bootstrap, clarification, revision, implementation approval, and failed-validation repair remain real same-session turn boundaries owned by the composite skill. -- A composed workflow `SKILL.md` is one document that reads top to bottom. The workflow's own `## Input`, `## Workflow`, and `## Rules` are the only sections at that level under the skill title; the composite control-flow rules belong in the preamble with the rest of the cross-workflow policy, ahead of `## Input`, not after the appendices. A phase body belongs inside the numbered workflow step that runs it, and the trailing `## Embedded phase behavior` appendix holds only phases a module still lists — `renderSkill` emits no appendix heading for a module that lists none, and `StructuredCompositeSource.phases` defaults to empty so migrating a module means deleting its listing. Express heading depth and inline-versus-name placement as typed mode-aware values from `workflow-content.pkl` — `PhaseHeadings` for heading scale and `{step}.{n}` phase-step numbering, `packageOnlyBlock` / `compositeOnlyBlock` for text one mode emits (the `SCE {WORKFLOW} $ARGUMENTS` banner and an inlined phase body), each helper owning the blank line that separates it from what follows so no call site strips a stray separator. Never construct heading depth as a literal run of `#` a later pass would rewrite, and never achieve placement by parsing Markdown. `PhaseHeadings.compositeShift` defaults to one heading level below its invoking step, but a workflow whose invoking step already sits deeper than the plain `### N.` top-level numbering (for example a mode-specific sub-step nested under a grouping heading) may override it so the phase's dotted steps still land one level beneath that step. When a phase is invoked from more than one step, inline its body once, at whichever invocation is stated first in reading order, and let every other invocation reference it by name — a name-only phase reference must never point forward at a step that appears later in the same document. +- Every target's commands (Pi: prompts) must stay thin and invoke exactly one corresponding workflow skill (`sce-change-to-plan`, `sce-next-task`, `sce-validate`, or `sce-commit`). They must not sequence phase skills. The workflow skill executes package-local phases directly, after reading the applicable reference, and keeps phase statuses as internal state. Only the successful task/plan synchronization decision gate may invoke sibling `sce-decision`; preserve that exception as exact rather than general sibling orchestration. +- A phase-based workflow package contains `SKILL.md`, `references/output.md`, and named package-local references for its phase instructions and persisted-file templates. `SKILL.md` alone owns ordering, branching, waits, and same-session resume; it reads the applicable reference before phase side effects. Phase-free workflows contain exactly `SKILL.md` and `references/output.md`. Put every and only human-visible gate, report, and terminal response layout in `output.md`. State each layout exactly once inside `output.md`: when a phase's return-value layout and a workflow branch's layout describe the same output, keep the fuller statement (the one carrying every status variant, field, and report rule) and let the other place point at that section by heading instead of restating it. An `output.md` section must not reference a document outside its own package; a mode-aware semantic reference is how composite text names the embedded section that replaced a package-mode file. A composed `SKILL.md` states no layout of its own: a branch that produces user-visible output names the `output.md` section it renders (`Render the **{Section}** layout from `references/output.md`.`) and keeps only what `output.md` does not carry — the branch condition, the field mapping that fills the layout, the wait, and every prohibition. Model this per layout as a mode-aware semantic reference whose package spelling is the inline block a standalone command file still owns and whose composite spelling is the citation; do not achieve it by deleting text the sibling `output.md` never states. Wait points such as bootstrap, clarification, revision, implementation approval, and failed-validation repair remain real same-session turn boundaries owned by the composite skill. +- A phase-based workflow `SKILL.md` reads top to bottom as the control-flow document. Keep the phase-reference inventory ahead of `## Input`; state which reference each numbered workflow step reads before running; keep phase instructions and persisted-document formats in those named references rather than duplicating them in `SKILL.md`. A workflow that reaches the same phase from more than one step reuses one reference. Phase-free workflow rendering continues through the generic composite body path. - Keep the Markdown renderer contract in `config/pkl/renderers/common.pkl` limited to deterministic `frontmatter + body` assembly without injected generated-file marker text. - Validate each renderer module directly with `nix develop -c pkl eval ` before wiring output emission. @@ -95,7 +95,7 @@ - Use `config/pkl/generate.pkl` as the single generation module for authored config outputs. Flatten self-contained workflow skill documents as `{skill slug}/{package-relative path}` so nested references are emitted deterministically without sibling-package dependencies. - Use `config/pkl/README.md` as the contributor-facing runbook for prerequisites, ownership boundaries, regeneration steps, and troubleshooting. - Run multi-file generation only into an explicit temporary output root, for example `nix run .#pkl-generate -- "$(mktemp -d)"`; never evaluate with `-m .`. -- Run ephemeral generation validation through `nix run .#pkl-check-generated`; it wraps the dev-shell script, rejects committed target/schema/mirror outputs, evaluates exact metadata plus the complete 71-path artifact/reference contract, the optional-workflow manifest assertion, and its negative fixtures, requires all supported target roots, and delegates canonical input discovery, two-pass generation, and inventories to `scripts/produce-cli-generated-input.sh`. +- Run ephemeral generation validation through `nix run .#pkl-check-generated`; it wraps the dev-shell script, rejects committed target/schema/mirror outputs, evaluates exact metadata plus the complete 101-path artifact/reference contract, the optional-workflow manifest assertion, and its negative fixtures, requires all supported target roots, and delegates canonical input discovery, two-pass generation, and inventories to `scripts/produce-cli-generated-input.sh`. - Keep this contract anchored to the root `nix flake check` `pkl-generated` derivation. Removed target paths are forbidden repository artifacts even though the same path names remain valid inside temporary payload roots. - Treat `nix run .#pkl-check-generated` and `nix flake check` as the lightweight post-task verification baseline and run both after each completed task. - Keep `output.files` limited to payload-relative paths (`config/.opencode/{agent,command,skills,lib,plugins,opencode.json}`, `config/.claude/{commands,skills,hooks,settings.json}` with no Claude agents, `config/.pi/{prompts,skills,extensions}`, and the generated schema). Do not emit `config/automated/.opencode`. diff --git a/context/plans/canonicalize-workflow-phase-references.md b/context/plans/canonicalize-workflow-phase-references.md new file mode 100644 index 00000000..141e675d --- /dev/null +++ b/context/plans/canonicalize-workflow-phase-references.md @@ -0,0 +1,99 @@ +# Plan: canonicalize-workflow-phase-references + +## Change summary + +Promote the current staged `.claude/skills` refactor into the canonical Pkl workflow model, then render the same package-relative phase-reference shape for Claude, Pi, and OpenCode. The four phase-based workflow skills keep control flow in `SKILL.md` while moving phase instructions and persisted-document formats into package-local Markdown references that are read only when their workflow step is reached. + +This revises the current two-file workflow-package contract without restoring sibling phase skills or inter-skill result transport: each workflow remains one skill invocation with internal phase state and same-session waits. Phase-free workflows remain unchanged, and `references/output.md` remains the sole owner of human-visible gates and terminal layouts. + +## Acceptance criteria + +- [x] AC1: The staged Claude package shape for `sce-change-to-plan`, `sce-next-task`, `sce-validate`, and `sce-commit` is produced from canonical Pkl rather than maintained as Claude-only hand edits. + - Validate: generate into a temporary root with `nix run .#pkl-generate -- "$(mktemp -d -t sce-gen-XXXX)"` and compare the four generated `config/.claude/skills/` packages with the intended staged `.claude/skills/` package-relative files and contents. +- [x] AC2: OpenCode, Claude, and Pi emit the same package-relative phase-reference inventory for each phase-based workflow, with only supported target frontmatter differing. + - Validate: inspect the temporary payload and compare the relative file sets plus normalized document bodies under `config/.{opencode,claude,pi}/skills/{sce-change-to-plan,sce-next-task,sce-validate,sce-commit}/`. +- [x] AC3: Each workflow remains one self-contained skill invocation: `SKILL.md` owns phase ordering, branching, waits, and same-session resume; each phase reference is read before that phase runs; no command invokes a phase skill or transports phase state between packages. + - Validate: inspect generated commands/prompts and the four generated workflow skills on all three targets; run the metadata and generation contract checks through `nix run .#pkl-check-generated`. +- [x] AC4: Package-local document ownership is unambiguous: phase instructions and persisted-file templates live in their named reference files, `references/output.md` alone defines user-visible layouts, and phase-free workflow plus decision-package inventories are unchanged. + - Validate: inspect generated reference inventories and confirm the generation contract rejects stale or missing phase references, duplicated output layouts, unresolved references, and unintended changes to `sce-handover`, `sce-brownfield`, or `sce-decision`. + +### Full validation + +- `nix run .#pkl-check-generated` +- `nix flake check` + +### Context sync + +- `context/overview.md` +- `context/architecture.md` +- `context/patterns.md` +- `context/glossary.md` +- `context/sce/shared-context-plan-workflow.md` +- `context/sce/shared-context-code-workflow.md` +- `context/sce/atomic-commit-workflow.md` +- `context/context-map.md` +- A new ADR superseding the accepted two-file-package clauses in `context/decisions/2026-07-29-cross-target-workflow-skill-packages.md`, while preserving single-skill control flow and internal phase state. + +## Constraints and non-goals + +- **In scope:** the current staged `.claude/skills` phase-reference design; canonical workflow/Pkl models and renderers; exact metadata and generated-artifact contract checks; and matching root `.claude/skills`, `.pi/skills`, and `.opencode/skills` workflow packages. +- **Out of scope:** restoring generated phase-skill packages; changing command-to-workflow routing; changing workflow status semantics, gates, waits, or user-visible layouts; altering `sce-handover`, `sce-brownfield`, or `sce-decision` package shapes; Rust CLI behavior; and non-workflow plugins, hooks, or extensions. +- **Constraints:** preserve the current staged Claude behavior and wording unless canonical generation requires a target-neutral path/frontmatter adaptation; keep phase references package-local; read each reference before phase side effects; preserve the no-improvisation rule and output-layout deduplication guard; use canonical Pkl as the source of truth for all three targets. +- **Non-goal:** reducing total generated Markdown size. The change moves phase material out of the initially loaded `SKILL.md`; it does not delete phase behavior. + +## Assumptions + +- “Same shape” applies to the four phase-based workflow packages currently changed under `.claude/skills`; phase-free `sce-handover` and `sce-brownfield` do not gain empty phase references. +- The current staged Claude filenames and phase boundaries are the intended baseline: `context-load.md`, `plan-authoring.md`, `plan-template.md`, `plan-review.md`, `task-execution.md`, `context-sync.md`, `validation.md`, `validation-report.md`, and `atomic-commit.md` in their owning packages. +- Root `.claude/skills`, `.pi/skills`, and `.opencode/skills` are synchronized installed/configuration surfaces for this repository and should match the canonical generated payload for the affected packages. + +## Task stack + +- [x] T01: `Canonicalize and propagate phase-reference workflow packages` (status:done) + - Task ID: T01 + - Goal: Make the staged Claude phase-reference package design canonical in Pkl and render the same affected workflow package shape for Claude, Pi, and OpenCode. + - Boundaries (in/out of scope): In — `config/pkl/base/workflow-content.pkl`, the phase-based `workflow-{change-to-plan,next-task,validate,commit}.pkl` modules and shared `workflow-context-sync.pkl` as needed, `config/pkl/renderers/workflow-composite.pkl`, metadata/generation contract checks, and affected root target skill packages. Out — phase-free workflows, decision-package behavior, routing metadata semantics, Rust code, and non-workflow target assets. + - Dependencies: none + - Done when: canonical generation reproduces the intended staged Claude packages; all three targets have matching package-relative phase references and control-flow shape; exact artifact inventories and reference guards reflect the new contract; no phase behavior, gate, wait, branch, or output layout is lost; targeted generation validation passes. + - Verification notes (commands or checks): generate pre/post temporary payloads and review package diffs; compare generated Claude output to the staged baseline; compare package-relative inventories and normalized bodies across all three targets; `nix run .#pkl-check-generated`; `nix flake check`. + - Completed: 2026-08-03 + - Files changed: `config/pkl/base/workflow-content.pkl`, affected phase-based workflow modules, `config/pkl/renderers/{workflow-composite,metadata-coverage-check,generation-contract-check}.pkl`, and affected root `.claude`, `.pi`, and `.opencode` skill packages. + - Evidence: Temporary generation reproduced the staged Claude package bytes and produced matching cross-target inventories and normalized bodies; `nix run .#pkl-check-generated` passed with 101 artifacts; `nix flake check` passed. + - Notes: Phase-free workflows, the decision package, routing semantics, Rust code, and non-workflow assets were unchanged. The generated artifact contract increased intentionally from 71 to 101 paths. + +## Open questions + +None. The staged Claude files define the intended phase boundaries and filenames, and the request explicitly requires Pkl ownership plus cross-target parity. + +## Validation Report + +**Status:** validated +**Date:** 2026-08-03 + +### Commands run + +- `nix run .#pkl-generate -- "$(mktemp -d -t sce-gen-XXXXXX)"` plus four-package Claude diffs -> exit 0 (temporary generation matched all intended staged Claude workflow packages byte-for-byte). +- Cross-target inventory/body comparison with fixed-offset frontmatter stripping -> exit 1 (the inspection harness used different target frontmatter lengths; no generated-content mismatch was established). +- Cross-target inventory/body comparison with delimiter-based frontmatter normalization -> exit 0 (all four workflow inventories and normalized bodies matched across OpenCode, Claude, and Pi). +- Generated-to-root package diffs plus routing/reference inspection -> exit 0 (affected workflows matched installed surfaces; phase-free and decision packages were unchanged; commands route once to composite workflow skills and skills require phase references before execution). +- `nix run .#pkl-check-generated` -> exit 0 (ephemeral generation and contract checks passed for 101 artifacts; inventory SHA-256 `c29f4c0dfa028cff8aa23f69e17f4320ad3ae7fb07d2bf2a46312d43db7946df`). +- `nix flake check` -> exit 0 (all evaluated checks passed on `x86_64-linux`; zero checks required rebuilding). + +### Scaffolding removed + +- None. + +### Success-criteria verification + +- [x] AC1: The staged Claude package shape is canonical Pkl output -> temporary generation matched the four staged `.claude/skills/` packages byte-for-byte. +- [x] AC2: OpenCode, Claude, and Pi emit the same package-relative inventory and normalized bodies -> delimiter-normalized cross-target comparisons passed for all four workflows and all references. +- [x] AC3: Each workflow remains one self-contained invocation with internal phase control -> generated routing invokes only each composite workflow skill, generated skills retain same-session state and require references before phase execution, and `nix run .#pkl-check-generated` passed. +- [x] AC4: Reference ownership and unaffected package inventories remain correct -> generated packages matched root surfaces, phase-free and decision packages were unchanged, and the generation contract passed its 101-artifact inventory and ownership guards. + +### Failed checks and follow-ups + +- None. + +### Residual risks + +- Cross-system flake outputs for `aarch64-darwin`, `aarch64-linux`, and `x86_64-darwin` were not evaluated by the host-specific `nix flake check`. diff --git a/context/sce/atomic-commit-workflow.md b/context/sce/atomic-commit-workflow.md index f108a1fe..ae220ed6 100644 --- a/context/sce/atomic-commit-workflow.md +++ b/context/sce/atomic-commit-workflow.md @@ -8,11 +8,11 @@ Canonical behavior is authored in `config/pkl/base/workflow-commit.pkl` from the project-root `.pi/` baseline and generated for OpenCode, Claude, and Pi. Every target emits one thin command (Pi: prompt) invoking `sce-commit`. The -composite package contains only `SKILL.md`, which owns mode routing, staged-diff -analysis, proposal/commit behavior, and internal statuses, plus -`references/output.md`, which owns all human-visible prompts and result layouts. -The commit-message style reference is composed into those two files rather than -emitted separately. +package contains `SKILL.md`, which owns mode routing, proposal/commit control +flow, and internal statuses; `references/atomic-commit.md`, which owns staged-diff +analysis and message construction; and `references/output.md`, which owns all +human-visible prompts, result layouts, and commit-message style rules. The phase +reference is read only after the selected path clears its pre-phase gate. No target emits an `sce-atomic-commit` package or invokes it as a sibling skill; each `sce-commit` package embeds the canonical phase behavior directly. diff --git a/context/sce/shared-context-code-workflow.md b/context/sce/shared-context-code-workflow.md index da412fa3..c4ae1607 100644 --- a/context/sce/shared-context-code-workflow.md +++ b/context/sce/shared-context-code-workflow.md @@ -2,7 +2,7 @@ ## Purpose -The implementation lifecycle executes at most one reviewed task per `/next-task` invocation, synchronizes durable context only after successful task execution, and runs final plan validation separately through `/validate`. The generated OpenCode Code agent only routes to these commands. Every target embeds each complete lifecycle in `sce-next-task` or `sce-validate`; the phases below are canonical authoring source and internal phases of those skills, not separate generated packages. +The implementation lifecycle executes at most one reviewed task per `/next-task` invocation, synchronizes durable context only after successful task execution, and runs final plan validation separately through `/validate`. The generated OpenCode Code agent only routes to these commands. Every target keeps each complete lifecycle in `sce-next-task` or `sce-validate`; each `SKILL.md` owns control flow and reads a package-local reference before running the applicable phase. The phases below are internal to those skills, not separate generated packages. ## `/next-task` entrypoint @@ -53,7 +53,7 @@ A context-sync blocker does not undo successful implementation: the task remains 2. Failed or blocked validation ends the session without repair edits; retry uses `/validate {plan-path}`. 3. `sce-plan-context-sync` runs only from a successful `Status: validated` handoff, applies the same decision gate before current-state edits, and reconciles the completed plan with durable repository context. ADR paths already written during task synchronization are reused for the same decision. -On every target, those validation and plan-sync phase bodies appear directly inside workflow steps 1 and 2 of one `sce-validate` skill, while the plan-file Validation Report format remains a trailing appendix after the workflow rules. Failed and blocked statuses stop before synchronization exactly as in the canonical flow. Final validation never runs from an individual implementation task. +On every target, `sce-validate/SKILL.md` dispatches workflow steps 1 and 2 through `references/validation.md` and `references/context-sync.md`, while `references/validation-report.md` owns the plan-file Validation Report format. Failed and blocked statuses stop before synchronization exactly as in the canonical flow. Final validation never runs from an individual implementation task. ## Flow @@ -80,7 +80,9 @@ flowchart TD ## Target ownership -- OpenCode, Claude, and Pi: thin commands (Pi: prompts) invoking `sce-next-task` or `sce-validate`; each package contains only `SKILL.md` and `references/output.md`. +- OpenCode, Claude, and Pi: thin commands (Pi: prompts) invoking `sce-next-task` or `sce-validate`. +- `sce-next-task` packages contain `SKILL.md`, `references/{plan-review,task-execution,context-sync,output}.md`. +- `sce-validate` packages contain `SKILL.md`, `references/{validation,context-sync,validation-report,output}.md`. - OpenCode adds `entry-skill` and a one-entry `skills` list naming that skill. Its Code routing agent allows `sce-next-task`, `sce-validate`, and `sce-commit`, plus internal `sce-decision` invocation; the Plan agent does not allow `sce-decision`. ## Canonical sources diff --git a/context/sce/shared-context-plan-workflow.md b/context/sce/shared-context-plan-workflow.md index 4e7d6ddb..2e24dc73 100644 --- a/context/sce/shared-context-plan-workflow.md +++ b/context/sce/shared-context-plan-workflow.md @@ -2,7 +2,7 @@ ## Purpose -`/change-to-plan` turns one change request into one scoped implementation plan under `context/plans/`. The generated OpenCode Plan agent is only a routing surface. Every target renders the same behavior into the single `sce-change-to-plan` workflow skill; the two phases below are canonical authoring source and internal phases of that skill, not separate generated packages. +`/change-to-plan` turns one change request into one scoped implementation plan under `context/plans/`. The generated OpenCode Plan agent is only a routing surface. Every target renders the same behavior into the single `sce-change-to-plan` workflow skill. `SKILL.md` owns ordering, branching, and same-session waits; package-local `context-load.md` and `plan-authoring.md` references own the two phases below, and `plan-template.md` owns the persisted plan format. They are not separate generated skill packages. ## Command entrypoint @@ -60,7 +60,8 @@ flowchart TD ## Target ownership -- OpenCode, Claude, and Pi: one thin command (Pi: prompt) invoking `sce-change-to-plan`; package files are `SKILL.md` and `references/output.md`. +- OpenCode, Claude, and Pi: one thin command (Pi: prompt) invoking `sce-change-to-plan`; package files are `SKILL.md`, `references/context-load.md`, `references/plan-authoring.md`, `references/plan-template.md`, and `references/output.md`. +- `SKILL.md` reads the applicable phase reference before running that phase; a bootstrap stop never loads plan authoring. - OpenCode adds `entry-skill` and a one-entry `skills` list naming that skill, and its Plan routing agent allows exactly `sce-change-to-plan`. ## Canonical sources From 66ec71eef5742595bd03e40bd0850929759ecb47 Mon Sep 17 00:00:00 2001 From: David Abram Date: Mon, 3 Aug 2026 14:07:40 +0200 Subject: [PATCH 2/2] pkl: Consolidate workflow reference rendering Move phase, persisted-document, and output rendering ownership into canonical workflow modules instead of duplicated snapshots. Preserve generated artifacts and strengthen generation-contract validation. Co-authored-by: SCE --- config/pkl/base/workflow-change-to-plan.pkl | 866 +++- config/pkl/base/workflow-commit.pkl | 199 +- config/pkl/base/workflow-content.pkl | 3487 +---------------- config/pkl/base/workflow-context-sync.pkl | 319 ++ config/pkl/base/workflow-next-task.pkl | 623 ++- config/pkl/base/workflow-validate.pkl | 8 +- .../renderers/generation-contract-check.pkl | 33 +- config/pkl/renderers/workflow-composite.pkl | 228 +- context/architecture.md | 8 +- context/glossary.md | 4 +- context/overview.md | 2 +- context/patterns.md | 6 +- .../plans/deduplicate-phase-reference-pkl.md | 149 + 13 files changed, 2366 insertions(+), 3566 deletions(-) create mode 100644 context/plans/deduplicate-phase-reference-pkl.md diff --git a/config/pkl/base/workflow-change-to-plan.pkl b/config/pkl/base/workflow-change-to-plan.pkl index 427b35ab..f76222db 100644 --- a/config/pkl/base/workflow-change-to-plan.pkl +++ b/config/pkl/base/workflow-change-to-plan.pkl @@ -1,5 +1,853 @@ import "workflow-content.pkl" as model +changeToPlanSkillBody = """ +# SCE Change to Plan + +## Purpose + +Own this workflow from input parsing through its terminal user-visible response. +Execute the phases below directly and in order. Phase statuses are internal state, +not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or +workflow command. Follow the canonical workflow's steps, gates, +and stops exactly as written: never invent, skip, reorder, or merge a step. + +## Phase references + +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. + +| Step | Read before running the phase | +|---|---| +| 1 | `references/context-load.md` | +| 2 and 4 | `references/plan-authoring.md` | + +`references/plan-template.md` defines the plan file written to disk. The plan +authoring phase points to it at the moment a plan is actually written, which never +happens on a `needs_clarification` or `blocked` result. + +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at the +bootstrap gate never authors a plan, which is why they are separate files. + +## User-visible output + +Use `references/output.md` for every gate and terminal response. Render no raw +internal state. The reference contains only human-visible Markdown layouts. +User-visible output is limited to those layouts: never invent a layout, and never +wrap one in an added preamble, commentary, summary, or extra section. + +## Composite control flow + +Keep phase results as internal state and continue immediately whenever the +canonical workflow says to continue. Stop only at a user wait or terminal branch. +Approval, clarification, revision, failed-validation repair, and bootstrap waits +resume this same skill in the same session. Never expose an internal phase result +as the workflow's final response. + +## Input + +`$ARGUMENTS` is the change request, in free-form prose. + +- The change request is required. +- It may describe a new plan or a change to an existing plan. Do not resolve which one applies; step 2 owns that decision. + +When `$ARGUMENTS` is empty, report that a change request is required, state the expected argument, and stop. Do not infer a change request from the repository state or the conversation. + +Pass the change request to step 2 unmodified. Do not restate, summarize, or pre-scope it. + +Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is the path resolved in step 2 (`plan.path`, or an entry of `candidates`), so every emitted command is directly runnable. + +## Workflow + +### 1. Load durable context + +Read `references/context-load.md`, then run the **Context load phase** with the +change request as the focus. + +`context/` is durable AI-first memory describing current state. Load it before planning so the plan starts from recorded truth. Where context and code disagree, the code is the source of truth. + +Branch on `status`: + +`bootstrap_required` -> `context/` does not exist. Do not create it, and do not plan without it. Render the **Missing context bootstrap gate** layout from `references/output.md`. + +Wait for the user. When they report the command ran, run the **Context load phase** again and continue in this session. Do not restart planning, and do not ask for the change request again. + +`loaded` -> Continue to the next step. + +Do not read `context/` yourself. Do not repair drift or stale context; the brief reports it and the plan may schedule the repair. + +### 2. Author the plan + +Read `references/plan-authoring.md`, then run the **Plan authoring phase** with +the change request and the complete `loaded` brief from the **Context load +phase**. + +Pass the brief verbatim. Do not restate, summarize, or reinterpret it. + +This phase challenges whether the change is worth building before planning how to +build it, and it decides on its own whether to stop at the clarification gate. +Both shape what reaches the user, so reach them through the reference rather than +acting from this summary. + +Do not write or edit the plan file yourself. + +Branch on `status`: + +`needs_clarification` -> No plan was written. Present the result as prose. Do not print the raw result. Render the **Clarification gate** layout from `references/output.md`. + +Render one `##` block per entry in `questions`, in result order. Use the question's `id`, `category`, `question`, and `why_blocking` fields exactly as returned. + +Do not answer the questions. Do not assume answers. Do not write a plan. Stop and wait. + +`blocked` -> No plan was written. Render the **Blocked** layout from `references/output.md`, drawing its issues from `issues` and, when `candidates` is present, its candidate paths from `candidates`. Do not print the raw result. Stop. + +`plan_ready` -> Continue to the next step. + +### 3. Determine the continuation + +Render the `plan_ready` result as the summary defined by the **Plan authoring phase** in `references/output.md`. Follow that layout exactly. Do not print the raw result. + +Take the next task from `next_task`. A `plan_ready` result always names one. Do not evaluate its dependencies; the **Plan review phase** checks them when the emitted command runs and returns `blocked` if they are unmet. + +The continuation invites revision. The plan was written from one prose request, so its assumptions are guesses about what the user meant, its scope is one reading of the request, and its task boundaries are the author's judgement. The user has seen none of it until now, and every one of those is cheaper to correct here than after a task has been built on it. A user who does not know revision is on the table will implement a plan they would have changed. + +Write `task` rather than `tasks` when `total_tasks` is 1. + +Offer revision, but do not gate the handoff on it, do not manufacture concerns, and do not ask the user to confirm the plan. When the summary lists open questions, leave them in the summary only — do not restate them in the continuation, do not answer them, and do not block the handoff on them. Blocking questions belong in `needs_clarification` (step 2), not here. + +Render the **Ready continuation** layout from `references/output.md`. + +Then stop and wait. Do not implement, and do not run the handoff yourself. + +### 4. Revise the plan on request + +When the user answers clarification questions from step 2, answers open questions listed in the summary, or answers with changes to the plan, revise it in this session. Do not ask them to rerun `/change-to-plan`, and do not ask for the original change request again. + +Run the **Plan authoring phase** with their answer or correction and the same `loaded` brief from step 1. The brief still holds; durable context did not change because the user disagreed with a task boundary. Do not reload it. + +An answer that resolves a doubt removes that open question. An answer that does not resolve it leaves the question standing; do not drop it because the user replied to it. If the reply raises a new doubt, the revised plan carries a new open question. + +Pass the correction as written. Do not restate, soften, or pre-scope it. The **Plan authoring phase** owns resolving it against the existing plan, and owns preserving completed tasks and their evidence. + +Branch on `status` exactly as in step 2. A revision may legitimately return `needs_clarification` or `blocked`. + +On `plan_ready`, render the summary again and the continuation exactly as in step 3, replacing `is ready` with `revised` in the heading. + +Revise as many times as the user asks. Each revision is one invocation of the **Plan authoring phase** against the same plan. + +When the user signals the plan is good, or asks to begin, return the handoff without re-authoring the plan. Say so plainly if questions are still open: the user may proceed over an unresolved doubt, and that is their call, but do not record it as resolved. + +Stop. + +## Rules + +- Plan at most one change request per invocation. Revisions to the plan that request produced are part of the same invocation, not a second request. +- Read each phase's reference before running that phase. +- Always tell the user the plan can be revised, and always name its assumptions as the first thing worth checking. +- Do not gate the handoff on open questions listed in the plan summary. Blocking questions return `needs_clarification` before any plan is written. Offering revision is not the same as demanding it, and inventing doubts to justify a review gate is not allowed. +- Do not suppress, soften, or answer an open question or clarification question on the user's behalf. +- Do not defer the user's revision to a rerun of `/change-to-plan`, and do not defer it to the implementation phase. Revise the plan here. +- Do not narrow, expand, or reinterpret a revision the user asked for. Pass it to the **Plan authoring phase** as written. +- Do not duplicate the internal instructions of embedded phases. +- Do not plan before durable context is loaded. +- Do not bootstrap `context/` yourself. `sce setup --bootstrap-context` owns that. +- Do not modify any file under `context/` outside `context/plans/`. +- Do not implement any part of the plan. +- Do not ask for implementation confirmation. +- Do not run task execution, context synchronization, or full-plan validation. +- Do not emit a `/validate` command. This workflow always hands off to `/next-task`. +- Do not answer the skill's clarification questions on the user's behalf. +- Do not execute the continuation returned at the end. +- Do not infer success when the **Plan authoring phase** returns a non-`plan_ready` status. +""" + +changeToPlanContextLoad = """ +# Context load phase + +Run this phase for step 1 of the workflow, with the change request as the focus. + +`context/` is durable AI-first memory describing current state. Load it before +planning so the plan starts from recorded truth. Where context and code disagree, +the code is the source of truth. + +This phase reads and reports; it never writes. + +## 1.1 Confirm the context root + +When `context/` does not exist, set internal status `bootstrap_required` +immediately. Read nothing further. + +Bootstrapping is the workflow's decision, not this phase's. + +## 1.2 Read the entry points + +Read, when present: + +- `context/context-map.md` +- `context/overview.md` +- `context/glossary.md` + +Read `context/architecture.md` when the focus touches structure, boundaries, or +data flow. Read `context/patterns.md` when it touches conventions the change must +follow. + +A missing entry point is a gap, not a failure. Record it and continue. + +## 1.3 Select the relevant domain context + +Consult `context/context-map.md` before any broad exploration. The map's +annotations name what each domain file owns; use them to select files, rather +than globbing or searching `context/`. + +Select only files whose subject overlaps the focus. Follow at most one level of +links out of a selected file, and only when the link is needed to understand the +focus. + +Do not read every domain file. A brief that includes everything has selected +nothing. + +Record focus areas with no matching context file under `gaps`. + +## 1.4 Check recorded context against the code + +For each selected file, spot-check its central claims against the code it +describes. + +When context and code diverge, the code is the source of truth. Record the +divergence under `drift` with what context says, what the code shows, and the +repair the context needs. + +Do not repair it here. Later phases decide whether repair belongs in the current +work. + +Keep this proportional: check the claims the focus depends on, not every +sentence. + +## 1.5 Return the brief + +Set exactly one internal state: + +- `loaded` +- `bootstrap_required` + +Report facts the workflow can act on. A brief that only lists file paths has +moved no knowledge. + +Record only the internal state. Do not add explanatory prose before or after it. + +Step 2 consumes a `loaded` brief verbatim and treats its `key_facts` as recorded +current state, its `gaps` as areas with no durable context, and its `drift` as +context the code has already outrun. + +## Context load boundaries + +Do not: + +- Create, update, move, or delete any file under `context/`. +- Bootstrap `context/`. +- Repair drift or stale context. +- Modify application code or tests. +- Read the entire `context/` tree by default. +- Explore the repository beyond what the focus and the selected context require. +- Ask the user questions. Report gaps and drift, and let the workflow decide. +- Author a plan, select a task, or implement anything. +""" + + + +changeToPlanPlanAuthoring = """ +# Plan authoring phase + +Run this phase for step 2 of the workflow, and again for each revision in step 4. + +Input: the change request, and the complete `loaded` brief from the context load +phase. Pass the brief verbatim; do not restate, summarize, or reinterpret it. + +This phase exclusively owns: + +- Resolving whether the request targets a new or an existing plan. +- The clarification gate. +- Normalizing the change summary, acceptance criteria, constraints, and non-goals. +- Slicing the task stack into one-task/one-atomic-commit units. +- Writing `context/plans/{plan_name}.md`. + +Do not duplicate any of it elsewhere in the workflow. + +Use the document format in `references/plan-template.md`. Read it before writing +the plan file. + +The workflow renders this phase's result as the summary defined in +`references/output.md`. + +The change request may name a plan, describe a change to an existing plan, or +describe entirely new work. Resolving which applies is this phase's +responsibility. + +The context brief is the durable memory this plan starts from. Treat its +`key_facts` as recorded current state, its `gaps` as areas with no durable +context, and its `drift` as context the code has already outrun. + +When no brief is supplied, load the context named by the change request before +authoring, and follow the selection discipline in *Inspect relevant context*. + +Answers the user gave to earlier clarification questions arrive as part of the +change request. Incorporate them into the plan. + +A revision of a plan authored earlier in the session also arrives as the change +request, and it is usually terse: a task boundary the user disagrees with, an +ordering they want changed, work they want added or dropped. Read it against the +existing plan, which supplies the scope, criteria, and terminology it omits. +Terseness is not ambiguity. Do not set internal status `needs_clarification` for +detail the plan already carries; ask only when the revision itself is genuinely +undecidable. + +## 2.1 Resolve the plan target + +Determine whether the request targets a new plan or an existing plan in +`context/plans/`. + +When it targets an existing plan, read that plan before authoring. Preserve its +completed tasks, their recorded evidence, its structure, and its terminology. + +When multiple existing plans match and none can be selected safely, return +`blocked` with the matching candidates. + +When the request targets a new plan, derive `plan_name` as a short kebab-case +slug of the change, and confirm it does not collide with an existing plan. + +Resolve exactly one plan target per invocation. + +## 2.2 Challenge the change + +Before planning how to build the change, work out whether it is worth building. A +plan is a commitment of someone's time; authoring one for work that should not +happen is worse than authoring none. + +Interrogate the request: + +- What breaks, or stays broken, if this is never built? If the answer is nothing + concrete, say so. +- What problem is it actually solving, as opposed to what it proposes to do? A + request that names only a solution has not stated a problem. +- Does the repository already do this, or most of it? The brief's `key_facts` are + the first place to check. +- Is there a materially smaller version that gets most of the value? Name it. +- What does this cost beyond the tasks: new dependency, new concept in the + glossary, a boundary crossed, a surface that now needs maintaining forever? +- Does the stated justification survive contact with the code, or does the code + show the premise is already false? + +Doubt that survives this is not an implementation detail to be tidied away. It +belongs in the plan's `Open questions` and in `open_questions`, in the plain +words you would use to a colleague. "Is this worth doing at all, given X?" is a +legitimate open question. So is "this looks like it duplicates Y". + +Weigh honestly in both directions. A request that is obviously worth building +gets no manufactured doubt: inventing questions to look rigorous is its own +failure, and it teaches the user to ignore the section. Most changes are fine. +Say nothing when there is nothing to say. + +Keep going regardless. Skepticism shapes the plan and the open questions; it does +not withhold the plan. The only value judgment that stops authoring is +`no_actionable_work`, when the change is already implemented. + +## 2.3 Run the clarification gate + +Before writing or updating any plan file, check the request for critical +unresolved detail: + +- Scope boundaries and out-of-scope items. +- Acceptance criteria and the checks that prove them. +- Constraints and non-goals. +- Dependency choices, including new libraries or services, versions, and the + integration approach. +- Domain ambiguity, including unclear business rules, terminology, or ownership. +- Architecture concerns, including patterns, interfaces, data flow, migration + strategy, and risk tradeoffs. +- Task ordering assumptions and prerequisite sequencing. + +Set internal status `needs_clarification` with one to three targeted questions +when any of these would materially change the plan. Write no plan file in that +case. + +Use repository conventions for ordinary local choices. Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change scope, acceptance criteria, or task ordering. + +Record those choices under `assumptions`. + +Do not silently invent missing requirements. When the user has explicitly allowed +assumptions, record them in the plan's `Assumptions` section instead of asking. + +A justification that does not survive inspection is itself a critical unresolved +detail. "For consistency", "to make it cleaner", "we will need it later" name no +outcome and prove nothing; ask what the change is actually for before planning +around it. Do not treat confident phrasing as evidence. + +## 2.4 Inspect relevant context + +Start from the context brief. Read code only where the brief leaves the change +underspecified: + +- Existing behavior the change affects. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests and available verification commands. +- Decisions or specifications connected to the change. + +Where the brief reports `drift`, the code is the source of truth. Plan against +the code, and schedule the context repair as part of the change when it falls +inside scope. + +Where the brief reports `gaps`, the plan may need to establish durable context +the repository does not yet have. + +Do not explore the entire repository by default. + +## 2.5 Author the acceptance criteria + +State how the finished plan is proven, before slicing tasks. + +Each criterion describes observable behavior of the finished system and names the +check that proves it. Record repository-wide checks once under `Full validation`, +and the durable context the change must be reflected in under `Context sync`. + +`/validate` runs this section after the last task completes. It is the only place +a plan says how it is validated. + +## 2.6 Author the task stack + +Slice the work into sequential tasks `T01..T0N` using the task format and the +atomic slicing contract in `references/plan-template.md`. + +Every executable task must be completable and landable as one coherent commit. +Split any task that would require multiple independent commits. Convert broad +wrappers such as `polish` or `finalize` into specific outcomes with concrete +acceptance checks. + +Order tasks so each one's declared dependencies precede it. + +The last task is an ordinary implementation task. Do not author a trailing +validation-and-cleanup task, or any task whose only purpose is running the full +check suite, verifying durable context, or removing scaffolding. + +Confirm every acceptance criterion is satisfied by at least one task. When one is +not, the task stack is incomplete. + +A finished stack always leaves at least one incomplete task, so the workflow can +always hand off to `/next-task`. When the request resolves to a plan but produces +no incomplete task, because the change is already implemented or already covered +by completed tasks, set internal status `blocked` with category +`no_actionable_work` instead of writing the plan. + +## 2.7 Write the plan + +Write `context/plans/{plan_name}.md` using `references/plan-template.md`. + +When updating an existing plan, keep completed tasks and their evidence intact, +and append or renumber new tasks without disturbing recorded history. + +## 2.8 Return the result + +Set exactly one internal state: + +- `plan_ready` +- `needs_clarification` +- `blocked` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `plan_ready` result always names the next task in `next_task`, and carries the +`total_tasks` count and any open questions the summary needs. Step 3 renders those +without recomputing them. + +## Plan authoring tone + +Every question and open question this phase writes is read by the user. Write +them the way a senior engineer talks in review: direct, specific, and unbothered +by the possibility of being unwelcome. + +- Ask about the thing that actually worries you, not a safer neighbouring thing. + A question you would not bother asking a colleague is not worth the user's + attention either. +- State a doubt as a doubt. "I do not think this is worth the two tasks it + costs, because X" is useful. "It may be worth considering whether this aligns + with broader goals" is noise. +- Name the alternative you have in mind. A challenge with no proposal behind it + is just friction. +- Do not open with praise, do not close with reassurance, and do not apologize + for asking. Do not pad a doubt with hedges to make it land more gently. +- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not + restate the same doubt in three shapes to give it more weight. +- Being disagreeable is not the goal. Being easy to agree with is the failure + mode. A plan the user waves through without reading has cost them nothing and + bought them nothing. + +When the user overrules a doubt, record it and move on. Do not relitigate a +decision the user has made, and do not smuggle the objection back in as a +constraint, a non-goal, or a task. + +## Plan authoring boundaries + +Do not: + +- Ask the user questions directly. Set internal status `needs_clarification` and let the + workflow present the questions. +- Answer your own clarification questions. +- Write a plan file when returning `needs_clarification` or `blocked`. +- Implement any task in the plan. +- Modify application code or tests. +- Modify any file under `context/` outside `context/plans/`. Plan the context + repair instead of performing it. +- Mark any task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Author a validation, cleanup, or context-verification task. `/validate` owns + that phase. +- Set internal status `plan_ready` for a plan with no incomplete task. +- Create a Git commit. +- Author more than one plan. +""" + + + +changeToPlanPlanTemplate = """ +# Internal persisted-document format: Plan template + +The document format for `context/plans/{plan_name}.md`. This is the plan file +written to disk, not the result returned to the workflow. + +Copy the template below and fill every `{placeholder}`. Omit optional sections +entirely rather than writing them empty. + +--- + +## Template + +```markdown +# Plan: {plan-name} + +## Change summary + +{One or two paragraphs: what changes, where, and why. State whether this +extends existing behavior, replaces it, or preserves work already in progress.} + +## Acceptance criteria + +How this plan is proven complete. Each criterion is observable and names the +check that proves it. `/validate` runs these checks; no task in the stack +performs final validation. + +- [ ] AC1: {observable outcome, stated as behavior rather than as work done} + - Validate: `{command, assertion, or inspection that proves AC1}` +- [ ] AC2: {observable outcome} + - Validate: `{command, assertion, or inspection that proves AC2}` + +### Full validation + +Repository-wide checks `/validate` runs after the last task, regardless of +which criterion they map to. + +- `{full check suite command}` +- `{generated-output or parity check command, when applicable}` + +### Context sync + +- {Durable context files that must describe the change once implemented.} + +## Constraints and non-goals + +- **In scope:** {files, modules, and surfaces this plan may touch} +- **Out of scope:** {adjacent work explicitly excluded} +- **Constraints:** {dependencies, conventions, compatibility, or policy limits} +- **Non-goal:** {tempting generalization this plan deliberately avoids} + +## Assumptions + +{Include only when the user allowed assumptions, or ordinary local choices were +recorded. Remove the section otherwise.} + +- {Assumption, and the convention or decision record it rests on.} + +## Task stack + +- [ ] T01: `{single intent title}` (status:todo) + - Task ID: T01 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: {task IDs, or none} + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +- [ ] T02: `{single intent title}` (status:todo) + - Task ID: T02 + - Goal: {one outcome} + - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. + - Dependencies: T01 + - Done when: {clear acceptance for one coherent change} + - Verification notes (commands or checks): {targeted checks for this change} + +## Open questions + +{Non-blocking questions only. A question that would change scope, success +criteria, or task ordering blocks authoring instead. Write `None.` with a short +justification when nothing remains.} + +{Unresolved doubt about the change's value belongs here — whether it is worth +building, whether it duplicates behavior the repository already has, whether a +smaller version would do. State it plainly and name the alternative. Do not +invent one: `None.` is the expected answer for a well-specified change.} +``` + +--- + +## Filled-in task example + +```markdown +- [ ] T02: `Add /auth/refresh endpoint` (status:todo) + - Task ID: T02 + - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. + - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. + - Dependencies: T01 + - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. + - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. +``` + +## Acceptance criteria rules + +- Acceptance criteria describe the finished system, not the work. Prefer "the + endpoint returns 401 on an expired token" over "add expiry handling". +- Every criterion carries a `Validate:` line. A criterion nobody can check is + not an acceptance criterion. +- Prefer a runnable command. Fall back to a named inspection only when no + automated check exists, and say exactly what to look at. +- List repository-wide checks once under `Full validation` instead of repeating + them per criterion. +- Task-level `Verification notes` prove one task. Acceptance criteria prove the + plan. Keep them distinct: a task's checks are narrow and local, a criterion's + check is end-to-end. +- The union of the acceptance criteria must cover every success signal in the + change request. If a criterion has no task that could satisfy it, the task + stack is incomplete. + +## Task rules + +- Every task is a checkbox line so progress stays machine-readable: + `- [ ] T01: {title} (status:todo)`. +- Author each executable task as one atomic commit unit by default. +- Scope every task so one contributor can complete it and land it as one + coherent commit without bundling unrelated changes. +- Split any candidate task that would require multiple independent commits, for + example a refactor plus a behavior change plus documentation. +- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of + executable tasks. Convert them into specific outcomes with concrete + acceptance checks. +- Order tasks so each one's declared dependencies precede it. + +## No validation task + +- The last task in the stack is an ordinary implementation task. Do not author a + trailing "validation and cleanup" task. +- Final validation, cleanup, and success-criteria verification are run by + `/validate` from the `Acceptance criteria` section after the last task + completes. +- Do not author a task whose only purpose is running the full check suite, + verifying durable context, or removing scaffolding. +- A task may still create or update durable context when that context is part of + the change itself. + +## Completion records + +When a task completes, the **Task execution phase** appends its evidence and flips the +checkbox and status: + +```markdown +- [x] T01: `{title}` (status:done) + - {authored fields, unchanged} + - Completed: {YYYY-MM-DD} + - Files changed: {paths} + - Evidence: {commands run and their outcomes} + - Notes: {material deviations or approved assumptions} +``` + +`/validate` appends a `## Validation Report` section at the end of the plan. +Do not author either while planning. + +## Updating an existing plan + +- Preserve completed tasks, their `(status:done)` markers, and their recorded + evidence verbatim. +- Preserve the plan's existing structure and terminology. +- Append new tasks after the existing stack. Renumber only when added work must + run earlier, and never renumber a completed task. +- Add acceptance criteria for newly planned outcomes rather than rewriting + criteria already satisfied. +""" + + + +changeToPlanOutput = """ +# Change-to-plan output layouts + +Use only the applicable layout. Values come from internal workflow state. + +## Missing context bootstrap gate + +```markdown +------------------------------------- + +# This repository has no durable context. + +Bootstrap it, then continue in this session: + +`sce setup --bootstrap-context` +``` + +## Clarification gate + +```markdown +------------------------------------- + +# Clarification needed. + +No plan was written. + +Answer each question below.\(" ") + +## {question-id} · {category} + +{question} + +Why this blocks planning: {why_blocking} +``` + +## Blocked + +Present each issue's problem, impact, and required decision. For ambiguity, list +candidate plan paths and explain that naming one candidate resolves it. + +## Ready continuation + +```markdown +------------------------------------- + +# Plan {plan-name} is ready. + +{total-tasks} {task|tasks} planned. + +This plan is a draft. State a correction and it will be updated. + +Next up: + +{next-task-id} — {next-task-title} + +`/next-task {plan-path} {next-task-id}` +``` + +For revisions, replace `is ready` with `revised`. + +# SCE Plan Summary + +The user-facing summary shown after a plan is written. It is rendered from +the `plan_ready` result, immediately before the continuation block. + +This is chat output, not a file. Nothing here is written to the plan. + +## Layout + +``` +# Plan: {plan.name} + +Path: {plan.path} + +## Summary: +{plan summary} + +## Tasks: +1. {task.id} — {task.title} +2. {task.id} — {task.title} + +## Assumptions: +- {assumption} + +## Open questions: +- {open question} +``` + +## Field mapping + +Every value comes from the `plan_ready` result. Render nothing the result does +not carry. + +- `Plan:` — `plan.name`. Append ` (updated)` when `plan.action` is `updated`. + Render nothing extra when it is `created`. +- `Path:` — `plan.path`, exactly as returned, so it stays runnable. +- `Summary:` — `summary`, as prose. This is the only place the reader learns + what the plan actually does, so never omit it and never replace it with a + restatement of the task titles. +- `Tasks:` — one numbered line per entry in `tasks`, in plan order. Append + ` (done)` to any task whose `status` is `done`. +- `Assumptions:` — one line per entry in `assumptions`. +- `Open questions:` — one line per entry in `open_questions`. + +## Empty sections + +Never drop a section heading. An absent section reads as an oversight; an +explicit `None.` confirms nothing is pending. + +When `assumptions` is empty: + +``` +## Assumptions: +- None. +``` + +When `open_questions` is absent: + +``` +## Open questions: +- None. +``` + +## Rules + +- Render the sections in the order above. +- Keep task titles as authored. Do not reword, expand, or re-scope them. +- Do not restate goals, boundaries, done checks, or verification notes. The plan + file owns task detail; this summary orients the reader. +- Do not print the raw result, and do not wrap the summary in a code fence. +- Do not add commentary, recommendations, or a next step. The continuation block + that follows owns the handoff. + +## Example + +``` +# Plan: red-sce-banner + +Path: context/plans/red-sce-banner.md + +## Summary: +Renders the ASCII-art SCE banner at the top of `sce` help in red instead of the current gradient. Colour-disabled output is unchanged, and no other help surface is affected. + +## Tasks: +1. T01 — Render the SCE banner in red + +## Assumptions: +- "SCE letters" refers to the ASCII-art banner in top-level help. +- Red is uniform terminal red when colors are enabled; plain ASCII remains unchanged otherwise. + +## Open questions: +- None. +``` +""" + + local contextLoad = model.semanticReference.apply("`sce-context-load`", "the **Context load phase**") local contextLoadName = model.semanticReference.apply("sce-context-load", "Context load phase") local planAuthoring = model.semanticReference.apply("`sce-plan-authoring`", "the **Plan authoring phase**") @@ -1439,20 +2287,16 @@ local PLAN_SUMMARY = """ structuredComposite = new model.StructuredCompositeSource { command = structuredCommand - compositeSkillBody = model.changeToPlanSkillBody + compositeSkillBody = changeToPlanSkillBody referenceDocuments = new Listing { - model.makeDocument.apply("references/context-load.md", model.changeToPlanContextLoad) - model.makeDocument.apply("references/plan-authoring.md", model.changeToPlanPlanAuthoring) - model.makeDocument.apply("references/plan-template.md", model.changeToPlanPlanTemplate) - model.makeDocument.apply("references/output.md", model.changeToPlanOutput) + model.makeDocument.apply("references/context-load.md", changeToPlanContextLoad) + model.makeDocument.apply("references/plan-authoring.md", changeToPlanPlanAuthoring) + model.makeDocument.apply("references/plan-template.md", changeToPlanPlanTemplate) + model.makeDocument.apply("references/output.md", changeToPlanOutput) } phases = new Listing {} - internalDocuments = new Listing { - model.makeDocument.apply("Plan template", renderPlanTemplate.apply("composite")) - } - outputDocuments = new Listing { - model.makeDocument.apply("Plan summary", PLAN_SUMMARY) - } + internalDocuments = new Listing {} + outputDocuments = new Listing {} } workflow = new model.WorkflowPackage { diff --git a/config/pkl/base/workflow-commit.pkl b/config/pkl/base/workflow-commit.pkl index c6da5699..8db36282 100644 --- a/config/pkl/base/workflow-commit.pkl +++ b/config/pkl/base/workflow-commit.pkl @@ -701,12 +701,205 @@ local renderCommitMessageStyle = (mode: model.WorkflowRenderMode) -> """ local COMMIT_MESSAGE_STYLE = renderCommitMessageStyle.apply("package") +local commitSkillBody = """ +# SCE Commit + +## Purpose + +Own this workflow from input parsing through its terminal user-visible response. +Execute the phases below directly and in order. Phase statuses are internal state, +not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or +workflow command. Follow the canonical workflow's steps, gates, +and stops exactly as written: never invent, skip, reorder, or merge a step. + +## Phase reference + +Both paths below dispatch to the same phase, whose steps and boundaries live in +`references/atomic-commit.md`. This document holds the control flow — which path +runs, what the phase receives, and how its result branches — and the reference +holds the phase itself. + +Read `references/atomic-commit.md` before running the phase, not after. A regular +run that stops at the staging gate, and a bypass run that finds nothing staged, +both end without ever needing it. + +## User-visible output + +Use `references/output.md` for every gate and terminal response. Render no raw +internal state. The reference contains only human-visible Markdown layouts. +User-visible output is limited to those layouts: never invent a layout, and never +wrap one in an added preamble, commentary, summary, or extra section. + +## Composite control flow + +Keep phase results as internal state and continue immediately whenever the +canonical workflow says to continue. Stop only at a user wait or terminal branch. +Approval, clarification, revision, failed-validation repair, and bootstrap waits +resume this same skill in the same session. Never expose an internal phase result +as the workflow's final response. + +## Input + +`$ARGUMENTS` is optional. Split it into two parts before invoking the skill: + +`[mode-token] [commit context]` + +- `mode-token` is present only when the first whitespace-separated token is + exactly `oneshot` or `skip`, compared case-insensitively. Any other first + token is not a mode token. +- `commit context` is everything else: free-form prose that refines message + wording only. + +A `mode-token` selects the bypass path. Its absence selects the regular path. +Do not infer the bypass path from anything else — not from the commit context, +not from repository state, and not from the conversation. + +Empty `$ARGUMENTS` is valid. It selects the regular path with no commit +context, and commit intent is inferred from the staged changes alone. + +Pass `commit context` to the **Atomic commit phase** unmodified. Do not restate, +summarize, or pre-scope it. Never pass the `mode-token` as commit context. + +Staged changes are the source of truth for what is being committed. This +command never stages, unstages, or modifies files. + +## Workflow + +Follow exactly one path. + +### Regular path (no mode token) + +#### 1. Confirm staging + +Before running the phase, stop and prompt the user with the **Regular-mode +staging gate** layout from `references/output.md`. + +Wait for the user's confirmation. Do not stage files on their behalf, and do +not skip this prompt because the working tree looks ready. + +#### 2. Propose commits + +After confirmation, read `references/atomic-commit.md`, then run the **Atomic +commit phase** with `mode: regular` and the commit context. + +Do not write commit messages yourself. + +Branch on `status`: + +`blocked` -> Render the **Blocked** layout from `references/output.md`. Stop. + +`proposal` -> Render the **Regular proposal** layout from `references/output.md`, +which covers each proposed commit's message and files, and the split rationale +when more than one commit is proposed. + +Then stop. The regular path is proposal-only. + +Do not run `git commit`. Do not offer to commit on the user's behalf. The user +runs the commits they accept. + +### Bypass path (`oneshot` or `skip`) + +#### 1. Validate that staged content exists + +Run `git diff --cached --quiet`. A zero exit status means nothing is staged. + +When nothing is staged, stop with the **No staged changes** layout from +`references/output.md`. + +Do not stage anything. Do not proceed to the skill. + +#### 2. Request one commit message + +Read `references/atomic-commit.md`, then run the **Atomic commit phase** with +`mode: bypass` and the commit context. + +Bypass mode is the skill's contract for producing exactly one message. Do not +restate its overrides here; the **Atomic commit phase** owns them. + +Branch on `status`: + +`blocked` -> Render the **Blocked** layout from `references/output.md` and stop. Do not commit. + +`bypass_message` -> Continue to the next step. + +The skill never returns `proposal` in bypass mode. Treat a `proposal` result as +a contract violation: report it and stop without committing. + +#### 3. Execute exactly one commit + +Run `git commit` once with the returned message. + +On success, render the **Bypass success** layout from `references/output.md` and +stop. + +On failure, render the **Bypass Git failure** layout from the same file and stop. + +Do not retry, do not amend, do not stage additional files, and do not invent a +fallback commit. + +## Rules + +- Produce at most one commit per invocation, and only on the bypass path. +- Never commit on the regular path. +- Recognize `oneshot` and `skip` only as an exact case-insensitive first token. + They are behaviorally identical. +- Read `references/atomic-commit.md` before running the phase. +- Do not duplicate the internal instructions of the **Atomic commit phase**. +- Do not stage, unstage, restore, or otherwise modify files. +- Do not amend, reset, revert, rebase, or push. +- Do not read unstaged or untracked changes as commit input. +- Do not infer success when the **Atomic commit phase** returns a non-success status. +- Do not proceed past a failed `git commit`. +- Do not run plan, task, or validation workflows from this command. +""" + +local renderCommitOutput = (mode: model.WorkflowRenderMode) -> """ +# Commit output layouts + +Use only the applicable layout. Values come from staged truth and internal +workflow state. + +## Regular-mode staging gate + +```markdown +Please run `git add ` for all changes you want included in this commit. +Atomic commits should only include intentionally staged changes. +Confirm once staging is complete. +``` + +## No staged changes + +```markdown +No staged changes. Stage changes before commit. +``` + +## Regular proposal + +For each proposal, present the complete commit message and covered files. When +more than one commit is proposed, also present the split rationale. Do not claim a +commit was created. + +## Blocked + +Present every issue's problem, impact, and required decision. Do not commit. + +## Bypass success + +```markdown +Committed {commit-hash} +``` + +## Bypass Git failure + +Present Git's failure unchanged and stop without retrying. +""" + structuredComposite = new model.StructuredCompositeSource { command = structuredCommand - compositeSkillBody = model.commitSkillBody + compositeSkillBody = commitSkillBody referenceDocuments = new Listing { - model.makeDocument.apply("references/atomic-commit.md", model.commitAtomicCommit) - model.makeDocument.apply("references/output.md", model.commitOutput) + model.makeDocument.apply("references/atomic-commit.md", renderAtomicCommitSkillBody.apply("package")) + model.makeDocument.apply("references/output.md", renderCommitOutput.apply("package")) } phases = new Listing {} internalDocuments = new Listing {} diff --git a/config/pkl/base/workflow-content.pkl b/config/pkl/base/workflow-content.pkl index b7c29a0b..d9f682e7 100644 --- a/config/pkl/base/workflow-content.pkl +++ b/config/pkl/base/workflow-content.pkl @@ -173,35 +173,36 @@ hidden inlinePhaseBody = (phaseBody: WorkflowBody) -> /// four phase-based workflows. Target renderers add only supported entrypoint /// frontmatter; all operational and persisted-document content remains /// target-neutral. -changeToPlanSkillBody = """ -# SCE Change to Plan +nextTaskSkillBody = """ +# SCE Next Task ## Purpose Own this workflow from input parsing through its terminal user-visible response. Execute the phases below directly and in order. Phase statuses are internal state, not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or -workflow command. Follow the canonical workflow's steps, gates, +workflow command except `sce-decision`, and invoke `sce-decision` only from the +successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, and stops exactly as written: never invent, skip, reorder, or merge a step. ## Phase references -Each numbered step below dispatches to a phase whose steps and boundaries live in -a reference file. This document holds the control flow — which phase runs, what it -receives, and how its result branches — and each reference holds the phase itself. +Each numbered step below dispatches to a phase whose steps, gates, and boundaries +live in a reference file. This document holds the control flow — which phase runs, +what it receives, and how its result branches — and each reference holds the phase +itself. | Step | Read before running the phase | |---|---| -| 1 | `references/context-load.md` | -| 2 and 4 | `references/plan-authoring.md` | - -`references/plan-template.md` defines the plan file written to disk. The plan -authoring phase points to it at the moment a plan is actually written, which never -happens on a `needs_clarification` or `blocked` result. +| 1 | `references/plan-review.md` | +| 2 | `references/task-execution.md` | +| 3 | `references/context-sync.md` | -Read a step's reference before taking any action for that step, not after. Read -only the reference for the step you have reached: a run that stops at the -bootstrap gate never authors a plan, which is why they are separate files. +Read a step's reference before taking any action for that step, not after. The +references carry gates that must fire before their phase's first side effect, so a +phase begun from this summary alone will already have skipped them. Read only the +reference for the step you have reached: a run that stops at step 1 never needs the +other two, which is why they are separate files. ## User-visible output @@ -220,3387 +221,283 @@ as the workflow's final response. ## Input -`$ARGUMENTS` is the change request, in free-form prose. +Parse `$ARGUMENTS` into three positional parts before invoking any phase: + + [task-id] [auto-approve] + +- `plan-name-or-path` is required. +- `task-id` is optional. It is present only when the token matches a task ID (`T01`, `T02`, ...). +- `auto-approve` is optional. It is present only when the token is exactly `approved`. -- The change request is required. -- It may describe a new plan or a change to an existing plan. Do not resolve which one applies; step 2 owns that decision. +Resolve `auto-approve` even when `task-id` is absent. -When `$ARGUMENTS` is empty, report that a change request is required, state the expected argument, and stop. Do not infer a change request from the repository state or the conversation. +A token matching neither a task ID nor `approved` is an error. Report the unrecognized token and the expected arguments, and stop. Do not guess its meaning. -Pass the change request to step 2 unmodified. Do not restate, summarize, or pre-scope it. +Pass each part only to the phase that owns it. Do not forward the raw `$ARGUMENTS` string to a phase. -Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is the path resolved in step 2 (`plan.path`, or an entry of `candidates`), so every emitted command is directly runnable. +Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is the path resolved in step 1 (`plan.path`, or an entry of `candidates`), so every emitted command is directly runnable. ## Workflow -### 1. Load durable context +### 1. Review the task -Read `references/context-load.md`, then run the **Context load phase** with the -change request as the focus. +Read `references/plan-review.md`, then run the **Plan review phase** with the +parsed `plan-name-or-path` and, when present, the parsed `task-id`. -`context/` is durable AI-first memory describing current state. Load it before planning so the plan starts from recorded truth. Where context and code disagree, the code is the source of truth. +Do not pass the `auto-approve` token to the **Plan review phase**. Branch on `status`: -`bootstrap_required` -> `context/` does not exist. Do not create it, and do not plan without it. Render the **Missing context bootstrap gate** layout from `references/output.md`. - -Wait for the user. When they report the command ran, run the **Context load phase** again and continue in this session. Do not restart planning, and do not ask for the change request again. +`blocked` -> Do not run implementation. Render the **Review blocked** layout from `references/output.md`. When `candidates` is present the plan could not be resolved, and each entry is a candidate path for `/next-task {candidate-path}`. `executable_tasks_remaining` true means another task remains executable and `/next-task {plan-path} {task-id}` selects one; false means no task in the plan can proceed until the plan is updated. Do not print the raw result. Stop. -`loaded` -> Continue to the next step. +`plan_complete` -> Render the **Plan already complete** layout from `references/output.md`. Stop. -Do not read `context/` yourself. Do not repair drift or stale context; the brief reports it and the plan may schedule the repair. +`ready` -> Pass the complete readiness result to the **Task execution phase**. -### 2. Author the plan +Do not reconstruct, summarize, or reinterpret the reviewed task before passing it. -Read `references/plan-authoring.md`, then run the **Plan authoring phase** with -the change request and the complete `loaded` brief from the **Context load -phase**. +### 2. Execute the task -Pass the brief verbatim. Do not restate, summarize, or reinterpret it. +Read `references/task-execution.md`, then run the **Task execution phase** with +the complete `ready` result from the **Plan review phase**. -This phase challenges whether the change is worth building before planning how to -build it, and it decides on its own whether to stop at the clarification gate. -Both shape what reaches the user, so reach them through the reference rather than -acting from this summary. +This phase always shows an implementation gate before it modifies any file, and it +is the only phase permitted to ask the user for confirmation. Both properties are +load-bearing, so reach them through the reference rather than acting from this +summary. -Do not write or edit the plan file yourself. +Branch on `auto-approve`: -Branch on `status`: +`approved` -> Also pass the `approve` flag. The **Task execution phase** then shows its implementation gate as a summary and proceeds without asking. -`needs_clarification` -> No plan was written. Present the result as prose. Do not print the raw result. Render the **Clarification gate** layout from `references/output.md`. +else -> Do not pass the `approve` flag. The **Task execution phase** shows its implementation gate and waits for the user's decision. -Render one `##` block per entry in `questions`, in result order. Use the question's `id`, `category`, `question`, and `why_blocking` fields exactly as returned. +Do not present an additional implementation confirmation. -Do not answer the questions. Do not assume answers. Do not write a plan. Stop and wait. +Branch on the execution result. -`blocked` -> No plan was written. Render the **Blocked** layout from `references/output.md`, drawing its issues from `issues` and, when `candidates` is present, its candidate paths from `candidates`. Do not print the raw result. Stop. +`declined` -> Render the **Declined** layout from `references/output.md`. Do not run context synchronization. Stop. -`plan_ready` -> Continue to the next step. +`blocked` -> Render the **Execution blocked or incomplete** layout from `references/output.md`. Do not run context synchronization. Stop. -### 3. Determine the continuation +`incomplete` -> Render the same **Execution blocked or incomplete** layout. Do not run context synchronization. Do not select another task. Stop. -Render the `plan_ready` result as the summary defined by the **Plan authoring phase** in `references/output.md`. Follow that layout exactly. Do not print the raw result. +`complete` -> continue to the next step. -Take the next task from `next_task`. A `plan_ready` result always names one. Do not evaluate its dependencies; the **Plan review phase** checks them when the emitted command runs and returns `blocked` if they are unmet. +### 3. Synchronize context -The continuation invites revision. The plan was written from one prose request, so its assumptions are guesses about what the user meant, its scope is one reading of the request, and its task boundaries are the author's judgement. The user has seen none of it until now, and every one of those is cheaper to correct here than after a task has been built on it. A user who does not know revision is on the table will implement a plan they would have changed. +Read `references/context-sync.md`, then run the **Task context synchronization +phase** with the complete `complete` result returned by the **Task execution +phase**. -Write `task` rather than `tasks` when `total_tasks` is 1. +Pass that result verbatim. It is the authoritative handoff, and the **Task context synchronization phase** owns reading the plan, task, changed files, verification evidence, and reported context impact out of it. -Offer revision, but do not gate the handoff on it, do not manufacture concerns, and do not ask the user to confirm the plan. When the summary lists open questions, leave them in the summary only — do not restate them in the continuation, do not answer them, and do not block the handoff on them. Blocking questions belong in `needs_clarification` (step 2), not here. +Do not restate, summarize, or reconstruct any part of the execution result. -Render the **Ready continuation** layout from `references/output.md`. +This phase verifies the five root context files on every invocation, whatever the +change's reported impact, so it is never correct to skip it as unnecessary. -Then stop and wait. Do not implement, and do not run the handoff yourself. +Branch on the synchronization result. -### 4. Revise the plan on request +`blocked` -> The task itself succeeded and is already marked complete in the plan. Render the **Context synchronization blocked** layout from `references/output.md`. Nothing records the skipped synchronization, so it is lost once this session ends. -When the user answers clarification questions from step 2, answers open questions listed in the summary, or answers with changes to the plan, revise it in this session. Do not ask them to rerun `/change-to-plan`, and do not ask for the original change request again. +Do not select another task. Stop. -Run the **Plan authoring phase** with their answer or correction and the same `loaded` brief from step 1. The brief still holds; durable context did not change because the user disagreed with a task boundary. Do not reload it. +`synced` | `no_context_change` -> Print out the report the **Task context synchronization phase** returned. Continue to the next step. -An answer that resolves a doubt removes that open question. An answer that does not resolve it leaves the question standing; do not drop it because the user replied to it. If the reply raises a new doubt, the revised plan carries a new open question. +### 4. Determine the continuation -Pass the correction as written. Do not restate, soften, or pre-scope it. The **Plan authoring phase** owns resolving it against the existing plan, and owns preserving completed tasks and their evidence. +Use `plan.completed_tasks` and `plan.total_tasks` from the execution result to determine which continuation applies. -Branch on `status` exactly as in step 2. A revision may legitimately return `needs_clarification` or `blocked`. +Do not execute another task. Return exactly one continuation. -On `plan_ready`, render the summary again and the continuation exactly as in step 3, replacing `is ready` with `revised` in the heading. +If incomplete tasks remain, read the plan and name the first unchecked task in plan order. Do not evaluate its dependencies; the **Plan review phase** checks them when the emitted command runs and returns `blocked` if they are unmet. -Revise as many times as the user asks. Each revision is one invocation of the **Plan authoring phase** against the same plan. +Render the **More tasks remain** layout from `references/output.md`. -When the user signals the plan is good, or asks to begin, return the handoff without re-authoring the plan. Say so plainly if questions are still open: the user may proceed over an unresolved doubt, and that is their call, but do not record it as resolved. +If all tasks are completed, render the **All tasks complete** layout instead. Stop. ## Rules -- Plan at most one change request per invocation. Revisions to the plan that request produced are part of the same invocation, not a second request. +- Execute at most one plan task per invocation. +- Review at most one task. - Read each phase's reference before running that phase. -- Always tell the user the plan can be revised, and always name its assumptions as the first thing worth checking. -- Do not gate the handoff on open questions listed in the plan summary. Blocking questions return `needs_clarification` before any plan is written. Offering revision is not the same as demanding it, and inventing doubts to justify a review gate is not allowed. -- Do not suppress, soften, or answer an open question or clarification question on the user's behalf. -- Do not defer the user's revision to a rerun of `/change-to-plan`, and do not defer it to the implementation phase. Revise the plan here. -- Do not narrow, expand, or reinterpret a revision the user asked for. Pass it to the **Plan authoring phase** as written. - Do not duplicate the internal instructions of embedded phases. -- Do not plan before durable context is loaded. -- Do not bootstrap `context/` yourself. `sce setup --bootstrap-context` owns that. -- Do not modify any file under `context/` outside `context/plans/`. -- Do not implement any part of the plan. -- Do not ask for implementation confirmation. -- Do not run task execution, context synchronization, or full-plan validation. -- Do not emit a `/validate` command. This workflow always hands off to `/next-task`. -- Do not answer the skill's clarification questions on the user's behalf. +- The only permitted sibling-skill invocation is `sce-decision`, and only the + successful context-synchronization decision gate may invoke it. +- Do not ask for implementation confirmation outside "Task execution phase". +- Do not run full-plan validation. +- Do not mark the plan complete. - Do not execute the continuation returned at the end. -- Do not infer success when the **Plan authoring phase** returns a non-`plan_ready` status. -""" - -changeToPlanContextLoad = """ -# Context load phase - -Run this phase for step 1 of the workflow, with the change request as the focus. - -`context/` is durable AI-first memory describing current state. Load it before -planning so the plan starts from recorded truth. Where context and code disagree, -the code is the source of truth. - -This phase reads and reports; it never writes. - -## 1.1 Confirm the context root - -When `context/` does not exist, set internal status `bootstrap_required` -immediately. Read nothing further. - -Bootstrapping is the workflow's decision, not this phase's. - -## 1.2 Read the entry points - -Read, when present: - -- `context/context-map.md` -- `context/overview.md` -- `context/glossary.md` - -Read `context/architecture.md` when the focus touches structure, boundaries, or -data flow. Read `context/patterns.md` when it touches conventions the change must -follow. - -A missing entry point is a gap, not a failure. Record it and continue. - -## 1.3 Select the relevant domain context - -Consult `context/context-map.md` before any broad exploration. The map's -annotations name what each domain file owns; use them to select files, rather -than globbing or searching `context/`. - -Select only files whose subject overlaps the focus. Follow at most one level of -links out of a selected file, and only when the link is needed to understand the -focus. - -Do not read every domain file. A brief that includes everything has selected -nothing. - -Record focus areas with no matching context file under `gaps`. - -## 1.4 Check recorded context against the code - -For each selected file, spot-check its central claims against the code it -describes. - -When context and code diverge, the code is the source of truth. Record the -divergence under `drift` with what context says, what the code shows, and the -repair the context needs. - -Do not repair it here. Later phases decide whether repair belongs in the current -work. - -Keep this proportional: check the claims the focus depends on, not every -sentence. - -## 1.5 Return the brief - -Set exactly one internal state: - -- `loaded` -- `bootstrap_required` - -Report facts the workflow can act on. A brief that only lists file paths has -moved no knowledge. - -Record only the internal state. Do not add explanatory prose before or after it. - -Step 2 consumes a `loaded` brief verbatim and treats its `key_facts` as recorded -current state, its `gaps` as areas with no durable context, and its `drift` as -context the code has already outrun. - -## Context load boundaries - -Do not: - -- Create, update, move, or delete any file under `context/`. -- Bootstrap `context/`. -- Repair drift or stale context. -- Modify application code or tests. -- Read the entire `context/` tree by default. -- Explore the repository beyond what the focus and the selected context require. -- Ask the user questions. Report gaps and drift, and let the workflow decide. -- Author a plan, select a task, or implement anything. +- Do not infer success when an embedded phase returns a non-success status. +- Preserve completed work and evidence when a later phase fails. """ -changeToPlanPlanAuthoring = """ -# Plan authoring phase - -Run this phase for step 2 of the workflow, and again for each revision in step 4. - -Input: the change request, and the complete `loaded` brief from the context load -phase. Pass the brief verbatim; do not restate, summarize, or reinterpret it. - -This phase exclusively owns: - -- Resolving whether the request targets a new or an existing plan. -- The clarification gate. -- Normalizing the change summary, acceptance criteria, constraints, and non-goals. -- Slicing the task stack into one-task/one-atomic-commit units. -- Writing `context/plans/{plan_name}.md`. - -Do not duplicate any of it elsewhere in the workflow. - -Use the document format in `references/plan-template.md`. Read it before writing -the plan file. - -The workflow renders this phase's result as the summary defined in -`references/output.md`. - -The change request may name a plan, describe a change to an existing plan, or -describe entirely new work. Resolving which applies is this phase's -responsibility. - -The context brief is the durable memory this plan starts from. Treat its -`key_facts` as recorded current state, its `gaps` as areas with no durable -context, and its `drift` as context the code has already outrun. - -When no brief is supplied, load the context named by the change request before -authoring, and follow the selection discipline in *Inspect relevant context*. - -Answers the user gave to earlier clarification questions arrive as part of the -change request. Incorporate them into the plan. - -A revision of a plan authored earlier in the session also arrives as the change -request, and it is usually terse: a task boundary the user disagrees with, an -ordering they want changed, work they want added or dropped. Read it against the -existing plan, which supplies the scope, criteria, and terminology it omits. -Terseness is not ambiguity. Do not set internal status `needs_clarification` for -detail the plan already carries; ask only when the revision itself is genuinely -undecidable. - -## 2.1 Resolve the plan target - -Determine whether the request targets a new plan or an existing plan in -`context/plans/`. - -When it targets an existing plan, read that plan before authoring. Preserve its -completed tasks, their recorded evidence, its structure, and its terminology. - -When multiple existing plans match and none can be selected safely, return -`blocked` with the matching candidates. - -When the request targets a new plan, derive `plan_name` as a short kebab-case -slug of the change, and confirm it does not collide with an existing plan. - -Resolve exactly one plan target per invocation. - -## 2.2 Challenge the change - -Before planning how to build the change, work out whether it is worth building. A -plan is a commitment of someone's time; authoring one for work that should not -happen is worse than authoring none. - -Interrogate the request: - -- What breaks, or stays broken, if this is never built? If the answer is nothing - concrete, say so. -- What problem is it actually solving, as opposed to what it proposes to do? A - request that names only a solution has not stated a problem. -- Does the repository already do this, or most of it? The brief's `key_facts` are - the first place to check. -- Is there a materially smaller version that gets most of the value? Name it. -- What does this cost beyond the tasks: new dependency, new concept in the - glossary, a boundary crossed, a surface that now needs maintaining forever? -- Does the stated justification survive contact with the code, or does the code - show the premise is already false? - -Doubt that survives this is not an implementation detail to be tidied away. It -belongs in the plan's `Open questions` and in `open_questions`, in the plain -words you would use to a colleague. "Is this worth doing at all, given X?" is a -legitimate open question. So is "this looks like it duplicates Y". - -Weigh honestly in both directions. A request that is obviously worth building -gets no manufactured doubt: inventing questions to look rigorous is its own -failure, and it teaches the user to ignore the section. Most changes are fine. -Say nothing when there is nothing to say. - -Keep going regardless. Skepticism shapes the plan and the open questions; it does -not withhold the plan. The only value judgment that stops authoring is -`no_actionable_work`, when the change is already implemented. - -## 2.3 Run the clarification gate - -Before writing or updating any plan file, check the request for critical -unresolved detail: - -- Scope boundaries and out-of-scope items. -- Acceptance criteria and the checks that prove them. -- Constraints and non-goals. -- Dependency choices, including new libraries or services, versions, and the - integration approach. -- Domain ambiguity, including unclear business rules, terminology, or ownership. -- Architecture concerns, including patterns, interfaces, data flow, migration - strategy, and risk tradeoffs. -- Task ordering assumptions and prerequisite sequencing. - -Set internal status `needs_clarification` with one to three targeted questions -when any of these would materially change the plan. Write no plan file in that -case. - -Use repository conventions for ordinary local choices. Do not block on: - -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change scope, acceptance criteria, or task ordering. - -Record those choices under `assumptions`. - -Do not silently invent missing requirements. When the user has explicitly allowed -assumptions, record them in the plan's `Assumptions` section instead of asking. - -A justification that does not survive inspection is itself a critical unresolved -detail. "For consistency", "to make it cleaner", "we will need it later" name no -outcome and prove nothing; ask what the change is actually for before planning -around it. Do not treat confident phrasing as evidence. - -## 2.4 Inspect relevant context - -Start from the context brief. Read code only where the brief leaves the change -underspecified: - -- Existing behavior the change affects. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests and available verification commands. -- Decisions or specifications connected to the change. - -Where the brief reports `drift`, the code is the source of truth. Plan against -the code, and schedule the context repair as part of the change when it falls -inside scope. +validateSkillBody = """ +# SCE Validate -Where the brief reports `gaps`, the plan may need to establish durable context -the repository does not yet have. +## Purpose -Do not explore the entire repository by default. +Own this workflow from input parsing through its terminal user-visible response. +Execute the phases below directly and in order. Phase statuses are internal state, +not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or +workflow command except `sce-decision`, and invoke `sce-decision` only from the +successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, +and stops exactly as written: never invent, skip, reorder, or merge a step. -## 2.5 Author the acceptance criteria +## Phase references -State how the finished plan is proven, before slicing tasks. +Each numbered step below dispatches to a phase whose steps and boundaries live in +a reference file. This document holds the control flow — which phase runs, what it +receives, and how its result branches — and each reference holds the phase itself. -Each criterion describes observable behavior of the finished system and names the -check that proves it. Record repository-wide checks once under `Full validation`, -and the durable context the change must be reflected in under `Context sync`. +| Step | Read before running the phase | +|---|---| +| 1 | `references/validation.md` | +| 2 | `references/context-sync.md` | -`/validate` runs this section after the last task completes. It is the only place -a plan says how it is validated. - -## 2.6 Author the task stack - -Slice the work into sequential tasks `T01..T0N` using the task format and the -atomic slicing contract in `references/plan-template.md`. - -Every executable task must be completable and landable as one coherent commit. -Split any task that would require multiple independent commits. Convert broad -wrappers such as `polish` or `finalize` into specific outcomes with concrete -acceptance checks. - -Order tasks so each one's declared dependencies precede it. - -The last task is an ordinary implementation task. Do not author a trailing -validation-and-cleanup task, or any task whose only purpose is running the full -check suite, verifying durable context, or removing scaffolding. +`references/validation-report.md` defines the `## Validation Report` section +written into the plan file. Step 1 points to it at the moment it is needed, on a +`validated` or `failed` outcome only. -Confirm every acceptance criterion is satisfied by at least one task. When one is -not, the task stack is incomplete. +Read a step's reference before taking any action for that step, not after. Read +only the reference for the step you have reached: a run that stops at a `blocked` +or `failed` validation never enters step 2, which is why they are separate files. -A finished stack always leaves at least one incomplete task, so the workflow can -always hand off to `/next-task`. When the request resolves to a plan but produces -no incomplete task, because the change is already implemented or already covered -by completed tasks, set internal status `blocked` with category -`no_actionable_work` instead of writing the plan. +## User-visible output -## 2.7 Write the plan +Use `references/output.md` for every gate and terminal response. Render no raw +internal state. The reference contains only human-visible Markdown layouts. +User-visible output is limited to those layouts: never invent a layout, and never +wrap one in an added preamble, commentary, summary, or extra section. -Write `context/plans/{plan_name}.md` using `references/plan-template.md`. +## Composite control flow -When updating an existing plan, keep completed tasks and their evidence intact, -and append or renumber new tasks without disturbing recorded history. +Keep phase results as internal state and continue immediately whenever the +canonical workflow says to continue. Stop only at a user wait or terminal branch. +Approval, clarification, revision, failed-validation repair, and bootstrap waits +resume this same skill in the same session. Never expose an internal phase result +as the workflow's final response. -## 2.8 Return the result +## Input -Set exactly one internal state: +`$ARGUMENTS` is the plan name or plan path. -- `plan_ready` -- `needs_clarification` -- `blocked` +- The plan name or path is required. +- Resolve exactly one plan. Do not invent a plan from the conversation or from + incomplete nearby work. -Record only the internal state. Do not add explanatory prose before or after it. +When `$ARGUMENTS` is empty, report that a plan name or path is required, state +the expected argument, and stop. Do not infer the plan from repository state or +the conversation. -A `plan_ready` result always names the next task in `next_task`, and carries the -`total_tasks` count and any open questions the summary needs. Step 3 renders those -without recomputing them. +Pass the plan name or path to the **Validation phase** unmodified. Do not restate, +summarize, or pre-scope it. -## Plan authoring tone +Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is +the path carried by the **Validation phase** in its Markdown result (`Plan:`, or a +candidate path), so every emitted command is directly runnable. -Every question and open question this phase writes is read by the user. Write -them the way a senior engineer talks in review: direct, specific, and unbothered -by the possibility of being unwelcome. +## Workflow -- Ask about the thing that actually worries you, not a safer neighbouring thing. - A question you would not bother asking a colleague is not worth the user's - attention either. -- State a doubt as a doubt. "I do not think this is worth the two tasks it - costs, because X" is useful. "It may be worth considering whether this aligns - with broader goals" is noise. -- Name the alternative you have in mind. A challenge with no proposal behind it - is just friction. -- Do not open with praise, do not close with reassurance, and do not apologize - for asking. Do not pad a doubt with hedges to make it land more gently. -- Be persistent, not repetitive. Ask once, plainly, and let it stand; do not - restate the same doubt in three shapes to give it more weight. -- Being disagreeable is not the goal. Being easy to agree with is the failure - mode. A plan the user waves through without reading has cost them nothing and - bought them nothing. +### 1. Validate the plan -When the user overrules a doubt, record it and move on. Do not relitigate a -decision the user has made, and do not smuggle the objection back in as a -constraint, a non-goal, or a task. +Read `references/validation.md`, then run the **Validation phase** with the plan +name or path. -## Plan authoring boundaries +This phase measures finished work and never repairs it: it does not modify tests, +application code, or configuration to make a failing check pass. That property is +load-bearing, so reach it through the reference rather than acting from this +summary. -Do not: +Do not write the Validation Report yourself. -- Ask the user questions directly. Set internal status `needs_clarification` and let the - workflow present the questions. -- Answer your own clarification questions. -- Write a plan file when returning `needs_clarification` or `blocked`. -- Implement any task in the plan. -- Modify application code or tests. -- Modify any file under `context/` outside `context/plans/`. Plan the context - repair instead of performing it. -- Mark any task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Author a validation, cleanup, or context-verification task. `/validate` owns - that phase. -- Set internal status `plan_ready` for a plan with no incomplete task. -- Create a Git commit. -- Author more than one plan. -""" +Branch on the report's `Status:`. -changeToPlanPlanTemplate = """ -# Internal persisted-document format: Plan template +`blocked` -> Do not run context synchronization. Print the blocked Markdown +report as returned. Do not rephrase it into a different layout. Stop. -The document format for `context/plans/{plan_name}.md`. This is the plan file -written to disk, not the result returned to the workflow. +`failed` -> Do not run context synchronization. Print the failed Markdown +report as returned. It is already a session handoff: self-contained, actionable, +and ending with `/validate {plan-path}` after repairs. -Copy the template below and fill every `{placeholder}`. Omit optional sections -entirely rather than writing them empty. +Do not rewrite it into a shorter summary. Do not drop the retry command. Do not +add an alternate continuation that replaces `/validate`. ---- +Stop. Do not mark the plan finished. Do not continue to context synchronization. +Do not start the repair work in this workflow unless the user explicitly asks +to continue here; the default is that the handoff can leave this session. -## Template +`validated` -> Pass the complete validated Markdown result to the **Plan context synchronization phase**. -```markdown -# Plan: {plan-name} +Do not reconstruct, summarize, or reinterpret the validation result before +passing it. -## Change summary +### 2. Synchronize plan context -{One or two paragraphs: what changes, where, and why. State whether this -extends existing behavior, replaces it, or preserves work already in progress.} +Read `references/context-sync.md`, then run the **Plan context synchronization +phase** with the `Status: validated` Markdown result from the **Validation +phase**. -## Acceptance criteria +Do not run the **Plan context synchronization phase** for `failed` or `blocked`. Those are not +success states. -How this plan is proven complete. Each criterion is observable and names the -check that proves it. `/validate` runs these checks; no task in the stack -performs final validation. +Pass the validated result verbatim. It is the authoritative handoff, and the **Plan context synchronization phase** +owns reading the plan path, required context paths, validation evidence, and +reported context impact out of it. -- [ ] AC1: {observable outcome, stated as behavior rather than as work done} - - Validate: `{command, assertion, or inspection that proves AC1}` -- [ ] AC2: {observable outcome} - - Validate: `{command, assertion, or inspection that proves AC2}` +Do not restate, summarize, or reconstruct any part of the validation result. -### Full validation +This phase verifies the five root context files on every invocation, whatever the +reported impact, and must account for every path in the plan's `Context sync` +section, so it is never correct to skip it as unnecessary. -Repository-wide checks `/validate` runs after the last task, regardless of -which criterion they map to. +Branch on the synchronization result. -- `{full check suite command}` -- `{generated-output or parity check command, when applicable}` +`blocked` -> Validation itself succeeded and is already recorded in the plan. +Render the **Context synchronization blocked** layout from +`references/output.md`. Nothing records the skipped synchronization, so it is +lost once this session ends. -### Context sync +Stop. -- {Durable context files that must describe the change once implemented.} +`synced` | `no_context_change` -> Print out the report returned by the **Plan context synchronization phase**. +Continue to the next step. -## Constraints and non-goals +### 3. Report completion -- **In scope:** {files, modules, and surfaces this plan may touch} -- **Out of scope:** {adjacent work explicitly excluded} -- **Constraints:** {dependencies, conventions, compatibility, or policy limits} -- **Non-goal:** {tempting generalization this plan deliberately avoids} +Return exactly one completion block. Do not start another workflow. -## Assumptions +Render the **Completion** layout from `references/output.md`. -{Include only when the user allowed assumptions, or ordinary local choices were -recorded. Remove the section otherwise.} +When the synchronization status was `no_context_change`, keep the same +completion block. "Synchronized" here means the final context pass finished +successfully, including the case where no edit was warranted. -- {Assumption, and the convention or decision record it rests on.} +Stop. -## Task stack +## Rules -- [ ] T01: `{single intent title}` (status:todo) - - Task ID: T01 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: {task IDs, or none} - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -- [ ] T02: `{single intent title}` (status:todo) - - Task ID: T02 - - Goal: {one outcome} - - Boundaries (in/out of scope): In — {tight scope}. Out — {excluded work}. - - Dependencies: T01 - - Done when: {clear acceptance for one coherent change} - - Verification notes (commands or checks): {targeted checks for this change} - -## Open questions - -{Non-blocking questions only. A question that would change scope, success -criteria, or task ordering blocks authoring instead. Write `None.` with a short -justification when nothing remains.} - -{Unresolved doubt about the change's value belongs here — whether it is worth -building, whether it duplicates behavior the repository already has, whether a -smaller version would do. State it plainly and name the alternative. Do not -invent one: `None.` is the expected answer for a well-specified change.} -``` - ---- - -## Filled-in task example - -```markdown -- [ ] T02: `Add /auth/refresh endpoint` (status:todo) - - Task ID: T02 - - Goal: Implement a POST `/auth/refresh` endpoint that exchanges a valid refresh token for a new access token. - - Boundaries (in/out of scope): In — route handler, token validation logic, response schema. Out — refresh token rotation policy (covered in T03), client-side storage changes. - - Dependencies: T01 - - Done when: `POST /auth/refresh` returns a signed JWT on valid input and 401 on expired or invalid token; targeted tests pass; OpenAPI spec updated. - - Verification notes (commands or checks): `pnpm test src/auth/refresh.test.ts`; `curl -X POST localhost:3000/auth/refresh -d '{"token":"..."}' -w "%{http_code}"`. -``` - -## Acceptance criteria rules - -- Acceptance criteria describe the finished system, not the work. Prefer "the - endpoint returns 401 on an expired token" over "add expiry handling". -- Every criterion carries a `Validate:` line. A criterion nobody can check is - not an acceptance criterion. -- Prefer a runnable command. Fall back to a named inspection only when no - automated check exists, and say exactly what to look at. -- List repository-wide checks once under `Full validation` instead of repeating - them per criterion. -- Task-level `Verification notes` prove one task. Acceptance criteria prove the - plan. Keep them distinct: a task's checks are narrow and local, a criterion's - check is end-to-end. -- The union of the acceptance criteria must cover every success signal in the - change request. If a criterion has no task that could satisfy it, the task - stack is incomplete. - -## Task rules - -- Every task is a checkbox line so progress stays machine-readable: - `- [ ] T01: {title} (status:todo)`. -- Author each executable task as one atomic commit unit by default. -- Scope every task so one contributor can complete it and land it as one - coherent commit without bundling unrelated changes. -- Split any candidate task that would require multiple independent commits, for - example a refactor plus a behavior change plus documentation. -- Keep broad wrappers such as `polish`, `finalize`, or `misc updates` out of - executable tasks. Convert them into specific outcomes with concrete - acceptance checks. -- Order tasks so each one's declared dependencies precede it. - -## No validation task - -- The last task in the stack is an ordinary implementation task. Do not author a - trailing "validation and cleanup" task. -- Final validation, cleanup, and success-criteria verification are run by - `/validate` from the `Acceptance criteria` section after the last task - completes. -- Do not author a task whose only purpose is running the full check suite, - verifying durable context, or removing scaffolding. -- A task may still create or update durable context when that context is part of - the change itself. - -## Completion records - -When a task completes, the **Task execution phase** appends its evidence and flips the -checkbox and status: - -```markdown -- [x] T01: `{title}` (status:done) - - {authored fields, unchanged} - - Completed: {YYYY-MM-DD} - - Files changed: {paths} - - Evidence: {commands run and their outcomes} - - Notes: {material deviations or approved assumptions} -``` - -`/validate` appends a `## Validation Report` section at the end of the plan. -Do not author either while planning. - -## Updating an existing plan - -- Preserve completed tasks, their `(status:done)` markers, and their recorded - evidence verbatim. -- Preserve the plan's existing structure and terminology. -- Append new tasks after the existing stack. Renumber only when added work must - run earlier, and never renumber a completed task. -- Add acceptance criteria for newly planned outcomes rather than rewriting - criteria already satisfied. -""" - -changeToPlanOutput = """ -# Change-to-plan output layouts - -Use only the applicable layout. Values come from internal workflow state. - -## Missing context bootstrap gate - -```markdown -------------------------------------- - -# This repository has no durable context. - -Bootstrap it, then continue in this session: - -`sce setup --bootstrap-context` -``` - -## Clarification gate - -```markdown -------------------------------------- - -# Clarification needed. - -No plan was written. - -Answer each question below.\(" ") - -## {question-id} · {category} - -{question} - -Why this blocks planning: {why_blocking} -``` - -## Blocked - -Present each issue's problem, impact, and required decision. For ambiguity, list -candidate plan paths and explain that naming one candidate resolves it. - -## Ready continuation - -```markdown -------------------------------------- - -# Plan {plan-name} is ready. - -{total-tasks} {task|tasks} planned. - -This plan is a draft. State a correction and it will be updated. - -Next up: - -{next-task-id} — {next-task-title} - -`/next-task {plan-path} {next-task-id}` -``` - -For revisions, replace `is ready` with `revised`. - -# SCE Plan Summary - -The user-facing summary shown after a plan is written. It is rendered from -the `plan_ready` result, immediately before the continuation block. - -This is chat output, not a file. Nothing here is written to the plan. - -## Layout - -``` -# Plan: {plan.name} - -Path: {plan.path} - -## Summary: -{plan summary} - -## Tasks: -1. {task.id} — {task.title} -2. {task.id} — {task.title} - -## Assumptions: -- {assumption} - -## Open questions: -- {open question} -``` - -## Field mapping - -Every value comes from the `plan_ready` result. Render nothing the result does -not carry. - -- `Plan:` — `plan.name`. Append ` (updated)` when `plan.action` is `updated`. - Render nothing extra when it is `created`. -- `Path:` — `plan.path`, exactly as returned, so it stays runnable. -- `Summary:` — `summary`, as prose. This is the only place the reader learns - what the plan actually does, so never omit it and never replace it with a - restatement of the task titles. -- `Tasks:` — one numbered line per entry in `tasks`, in plan order. Append - ` (done)` to any task whose `status` is `done`. -- `Assumptions:` — one line per entry in `assumptions`. -- `Open questions:` — one line per entry in `open_questions`. - -## Empty sections - -Never drop a section heading. An absent section reads as an oversight; an -explicit `None.` confirms nothing is pending. - -When `assumptions` is empty: - -``` -## Assumptions: -- None. -``` - -When `open_questions` is absent: - -``` -## Open questions: -- None. -``` - -## Rules - -- Render the sections in the order above. -- Keep task titles as authored. Do not reword, expand, or re-scope them. -- Do not restate goals, boundaries, done checks, or verification notes. The plan - file owns task detail; this summary orients the reader. -- Do not print the raw result, and do not wrap the summary in a code fence. -- Do not add commentary, recommendations, or a next step. The continuation block - that follows owns the handoff. - -## Example - -``` -# Plan: red-sce-banner - -Path: context/plans/red-sce-banner.md - -## Summary: -Renders the ASCII-art SCE banner at the top of `sce` help in red instead of the current gradient. Colour-disabled output is unchanged, and no other help surface is affected. - -## Tasks: -1. T01 — Render the SCE banner in red - -## Assumptions: -- "SCE letters" refers to the ASCII-art banner in top-level help. -- Red is uniform terminal red when colors are enabled; plain ASCII remains unchanged otherwise. - -## Open questions: -- None. -``` -""" - -nextTaskSkillBody = """ -# SCE Next Task - -## Purpose - -Own this workflow from input parsing through its terminal user-visible response. -Execute the phases below directly and in order. Phase statuses are internal state, -not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or -workflow command except `sce-decision`, and invoke `sce-decision` only from the -successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, -and stops exactly as written: never invent, skip, reorder, or merge a step. - -## Phase references - -Each numbered step below dispatches to a phase whose steps, gates, and boundaries -live in a reference file. This document holds the control flow — which phase runs, -what it receives, and how its result branches — and each reference holds the phase -itself. - -| Step | Read before running the phase | -|---|---| -| 1 | `references/plan-review.md` | -| 2 | `references/task-execution.md` | -| 3 | `references/context-sync.md` | - -Read a step's reference before taking any action for that step, not after. The -references carry gates that must fire before their phase's first side effect, so a -phase begun from this summary alone will already have skipped them. Read only the -reference for the step you have reached: a run that stops at step 1 never needs the -other two, which is why they are separate files. - -## User-visible output - -Use `references/output.md` for every gate and terminal response. Render no raw -internal state. The reference contains only human-visible Markdown layouts. -User-visible output is limited to those layouts: never invent a layout, and never -wrap one in an added preamble, commentary, summary, or extra section. - -## Composite control flow - -Keep phase results as internal state and continue immediately whenever the -canonical workflow says to continue. Stop only at a user wait or terminal branch. -Approval, clarification, revision, failed-validation repair, and bootstrap waits -resume this same skill in the same session. Never expose an internal phase result -as the workflow's final response. - -## Input - -Parse `$ARGUMENTS` into three positional parts before invoking any phase: - - [task-id] [auto-approve] - -- `plan-name-or-path` is required. -- `task-id` is optional. It is present only when the token matches a task ID (`T01`, `T02`, ...). -- `auto-approve` is optional. It is present only when the token is exactly `approved`. - -Resolve `auto-approve` even when `task-id` is absent. - -A token matching neither a task ID nor `approved` is an error. Report the unrecognized token and the expected arguments, and stop. Do not guess its meaning. - -Pass each part only to the phase that owns it. Do not forward the raw `$ARGUMENTS` string to a phase. - -Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is the path resolved in step 1 (`plan.path`, or an entry of `candidates`), so every emitted command is directly runnable. - -## Workflow - -### 1. Review the task - -Read `references/plan-review.md`, then run the **Plan review phase** with the -parsed `plan-name-or-path` and, when present, the parsed `task-id`. - -Do not pass the `auto-approve` token to the **Plan review phase**. - -Branch on `status`: - -`blocked` -> Do not run implementation. Render the **Review blocked** layout from `references/output.md`. When `candidates` is present the plan could not be resolved, and each entry is a candidate path for `/next-task {candidate-path}`. `executable_tasks_remaining` true means another task remains executable and `/next-task {plan-path} {task-id}` selects one; false means no task in the plan can proceed until the plan is updated. Do not print the raw result. Stop. - -`plan_complete` -> Render the **Plan already complete** layout from `references/output.md`. Stop. - -`ready` -> Pass the complete readiness result to the **Task execution phase**. - -Do not reconstruct, summarize, or reinterpret the reviewed task before passing it. - -### 2. Execute the task - -Read `references/task-execution.md`, then run the **Task execution phase** with -the complete `ready` result from the **Plan review phase**. - -This phase always shows an implementation gate before it modifies any file, and it -is the only phase permitted to ask the user for confirmation. Both properties are -load-bearing, so reach them through the reference rather than acting from this -summary. - -Branch on `auto-approve`: - -`approved` -> Also pass the `approve` flag. The **Task execution phase** then shows its implementation gate as a summary and proceeds without asking. - -else -> Do not pass the `approve` flag. The **Task execution phase** shows its implementation gate and waits for the user's decision. - -Do not present an additional implementation confirmation. - -Branch on the execution result. - -`declined` -> Render the **Declined** layout from `references/output.md`. Do not run context synchronization. Stop. - -`blocked` -> Render the **Execution blocked or incomplete** layout from `references/output.md`. Do not run context synchronization. Stop. - -`incomplete` -> Render the same **Execution blocked or incomplete** layout. Do not run context synchronization. Do not select another task. Stop. - -`complete` -> continue to the next step. - -### 3. Synchronize context - -Read `references/context-sync.md`, then run the **Task context synchronization -phase** with the complete `complete` result returned by the **Task execution -phase**. - -Pass that result verbatim. It is the authoritative handoff, and the **Task context synchronization phase** owns reading the plan, task, changed files, verification evidence, and reported context impact out of it. - -Do not restate, summarize, or reconstruct any part of the execution result. - -This phase verifies the five root context files on every invocation, whatever the -change's reported impact, so it is never correct to skip it as unnecessary. - -Branch on the synchronization result. - -`blocked` -> The task itself succeeded and is already marked complete in the plan. Render the **Context synchronization blocked** layout from `references/output.md`. Nothing records the skipped synchronization, so it is lost once this session ends. - -Do not select another task. Stop. - -`synced` | `no_context_change` -> Print out the report the **Task context synchronization phase** returned. Continue to the next step. - -### 4. Determine the continuation - -Use `plan.completed_tasks` and `plan.total_tasks` from the execution result to determine which continuation applies. - -Do not execute another task. Return exactly one continuation. - -If incomplete tasks remain, read the plan and name the first unchecked task in plan order. Do not evaluate its dependencies; the **Plan review phase** checks them when the emitted command runs and returns `blocked` if they are unmet. - -Render the **More tasks remain** layout from `references/output.md`. - -If all tasks are completed, render the **All tasks complete** layout instead. - -Stop. - -## Rules - -- Execute at most one plan task per invocation. -- Review at most one task. +- Validate at most one plan per invocation. - Read each phase's reference before running that phase. - Do not duplicate the internal instructions of embedded phases. - The only permitted sibling-skill invocation is `sce-decision`, and only the successful context-synchronization decision gate may invoke it. -- Do not ask for implementation confirmation outside "Task execution phase". -- Do not run full-plan validation. -- Do not mark the plan complete. -- Do not execute the continuation returned at the end. +- Do not run final validation when implementation tasks remain; the **Validation phase** + returns `blocked`, and this workflow stops. +- Run the **Plan context synchronization phase** only when the **Validation phase** returned + `Status: validated`. Do not run it for `failed` or `blocked`. +- On `failed`, print the handoff Markdown as returned and stop. Preserve the + retry `/validate {plan-path}` instruction. Do not synchronize context. +- Do not implement remaining plan tasks from this workflow unless the user + explicitly continues in-session after a failed handoff. +- Do not create a Git commit or push changes. +- Do not mark the plan archived or delete the plan. +- Do not execute a follow-up `/next-task`, `/change-to-plan`, or `/validate` + yourself. - Do not infer success when an embedded phase returns a non-success status. -- Preserve completed work and evidence when a later phase fails. -""" - -nextTaskPlanReview = """ -# Plan review phase - -Run this phase for step 1 of the workflow. It resolves one plan, selects one -task, and decides whether that task can be implemented right now. It reads; it -never writes. - -Inputs: the parsed `plan-name-or-path`, and `task-id` when present. The -`auto-approve` token is not passed here and has no meaning in this phase. - -## 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status -`blocked` with the matching candidates. - -Read the selected plan before exploring the repository. - -## 1.2 Resolve one task - -When a task ID is supplied, select that task. - -Otherwise, select the first incomplete task in plan order whose declared -dependencies are complete. - -Set internal status `plan_complete` when no incomplete tasks remain. - -Set internal status `blocked` when incomplete tasks remain but none can currently -be executed. - -Review at most one task per invocation. - -## 1.3 Inspect relevant context - -Start with the task and the files it directly references. - -Inspect only what is needed to understand: - -- Existing behavior. -- Applicable repository conventions. -- Architectural boundaries. -- Relevant tests. -- Available verification commands. -- Decisions or specifications connected to the task. - -Load root context only when the task affects repository-wide behavior, -architecture, shared terminology, or cross-domain interfaces. - -Do not explore the entire repository by default. - -## 1.4 Determine readiness - -A task is `ready` when: - -- Its goal is clear. -- Its scope is sufficiently bounded. -- Its dependencies are complete. -- Its done checks are observable. -- A credible verification method exists. -- No unresolved decision would materially change the implementation. - -Use repository conventions for ordinary local choices. - -Do not block on: - -- Naming inferable from surrounding code. -- Established formatting or style. -- Reversible local implementation details. -- Details that do not change observable behavior or scope. - -Record these choices under `assumptions`. - -Set internal status `blocked` when a missing decision materially affects: - -- User-visible behavior. -- Public interfaces. -- Architecture or ownership boundaries. -- Data shape or persistence. -- Security or privacy. -- External dependencies. -- Destructive or difficult-to-reverse behavior. -- The evidence needed to prove completion. - -## 1.5 Return the result - -Set exactly one internal state: - -- `ready` -- `blocked` -- `plan_complete` - -Record only the internal state. Do not add explanatory prose before or after it. - -A `ready` result must identify: - -- One resolved plan. -- Exactly one incomplete task. -- The task goal and scope boundaries. -- Done checks. -- Verification expectations. -- Relevant files and context. -- Review assumptions. - -Step 2 consumes this result verbatim, so anything the execution phase needs has -to be present here. - -## Plan review boundaries - -Do not: - -- Modify application code. -- Modify tests. -- Update the plan. -- Mark the task complete. -- Request implementation confirmation. -- Run task execution. -- Synchronize context. -- Run final validation. -- Review more than one task. -""" - -nextTaskTaskExecution = """ -# Task execution phase - -Run this phase for step 2 of the workflow. It is the only phase that writes -application code, and the only one that asks the user for anything. - -Input: the complete `ready` result from the plan review phase, plus the `approve` -flag when the user pre-approved this invocation. - -This phase exclusively owns: - -- Presenting the implementation summary. -- Requesting implementation confirmation. -- Implementing the task. -- Running task-level verification. -- Updating the task status and evidence. - -Do not present an additional implementation confirmation anywhere else. - -The `approve` flag means the user pre-approved this task when invoking the -workflow. It suppresses the approval question and the wait. It never suppresses -the gate. Only the workflow entrypoint may set it, and only from an explicit -user-supplied approval token. Never infer it. - -If required handoff information is absent or stale, still show the gate using -what is known, clearly identify the handoff problem, and do not edit files. After -the user responds, set internal status `blocked`. - -## 2.1 Validate the handoff without editing - -Confirm that: - -- The readiness status is `ready`. -- Exactly one task is present. -- The plan file exists. -- The selected task is still incomplete. -- The task has not materially changed since review. -- Declared dependencies remain complete. - -Do not reconstruct missing material requirements. - -## 2.2 Always show the implementation gate - -At the start of the phase, before any file modification, present the task using -`references/output.md`. - -The gate must be shown even when: - -- The task appears straightforward. -- The workflow believes approval was already implied. -- The handoff is stale or incomplete. -- The user is likely to approve. - -When the `approve` flag is absent, end the gate with exactly one approval -question: - -`Continue with implementation now? (yes/no)` - -Stop and wait for the user's answer. Do not return internal state, and make no -file modifications, until the user has answered. - -When the `approve` flag is supplied, show the gate as a summary, omit the -approval question, do not wait, and continue at step 2.4. - -## 2.3 Handle the user's decision - -Skip this step when the `approve` flag was supplied. - -When the user rejects or cancels, do not modify files and set internal status -`declined`. - -When the user does not clearly approve, do not modify files. Ask the same -approval question once more only when the response is genuinely ambiguous. -Otherwise set internal status `blocked`. - -When the user approves, continue with implementation. - -Treat constraints supplied with approval as part of the approved task boundary. -If those constraints materially contradict the reviewed task, set internal status -`blocked` before editing. - -## 2.4 Prepare the implementation - -Before editing: - -- Read the relevant files supplied by plan review. -- Inspect nearby code and tests when needed. -- Identify the smallest coherent change satisfying the task. -- Follow surrounding naming, structure, error handling, and test style. -- Preserve unrelated behavior. - -Do not create a second plan. - -Do not broaden the reviewed task. - -## 2.5 Implement one task - -Make the minimum coherent changes required to satisfy the task goal and done -checks. - -Use judgment for ordinary, reversible local implementation choices. - -Stop when implementation requires: - -- Material scope expansion. -- A new external dependency not authorized by the task. -- A public-interface decision not established by the plan. -- A destructive or difficult-to-reverse operation. -- An unresolved security, privacy, or data decision. -- Contradicting the reviewed task or repository architecture. - -When stopped, preserve completed in-scope work unless retaining it would leave -the repository unsafe or invalid. - -## 2.6 Verify the task - -Run the narrowest authoritative checks that demonstrate the done checks. - -Start with verification supplied by the readiness result. Add nearby or directly -relevant checks only when needed. - -Verification may include: - -- Targeted tests. -- Type checking for affected code. -- Linting affected files. -- Formatting checks. -- A focused build or compile step. -- Direct behavioral inspection when no automated check exists. - -Do not run final plan validation unless the task itself explicitly requires it. - -When a check fails: - -- Determine whether the task caused the failure. -- Fix it when the correction remains in scope. -- Rerun the relevant check. -- Set internal status `incomplete` when a done check remains unsatisfied, or - `blocked` when completing it requires an unapproved decision or scope - expansion. - -Never report a check as passed unless it ran successfully. - -## 2.7 Update the plan - -Only after successful implementation and task-level verification: - -- Mark only the selected task complete. -- Record concise implementation evidence. -- Record verification commands and outcomes. -- Record material deviations or approved assumptions. -- Preserve the plan's existing structure and terminology. - -Do not mark the task complete when returning `declined`, `blocked`, or -`incomplete`. - -## 2.8 Determine the terminal status - -Set internal status `complete` when the task was implemented, verified, and -marked complete in the plan with evidence. - -Set internal status `incomplete` when in-scope work was completed but one or more -done checks remain unsatisfied. - -Set internal status `declined` when the user rejected implementation. - -Set internal status `blocked` for every other non-successful outcome, including: - -- Missing approval. -- Stale or invalid handoff. -- Material blocker. -- A verification failure that cannot be resolved in scope. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -## 2.9 Return internal state - -After the phase reaches a terminal state, set exactly one internal state. - -Record only the internal state. Do not add explanatory prose before or after it. - -A `complete` result is the authoritative handoff into step 3, which reads the -plan, completed task, changed files, implementation summary, verification -evidence, done-check evidence, and context-impact classification out of it. Step -3 is forbidden from reconstructing any of that, so it has to be present here. - -## Task execution boundaries - -Do not: - -- Edit before approval, whether explicit or pre-supplied. -- Execute more than one task. -- Select or execute the next task. -- Skip the implementation gate. -- Ask for multiple approval gates for the same unchanged task. -- Expand scope without authorization. -- Synchronize durable context. -- Run final plan validation. -- Determine whether the plan is complete. -- Create a Git commit. -- Push changes. -- Modify unrelated files. -- Claim verification that was not performed. -""" - -nextTaskContextSync = """ -# Task context synchronization phase - -Run this phase for step 3 of the workflow, and only when task execution returned -`complete`. It updates durable repository knowledge in `context/` so the next -session inherits what this task established. It never touches code, tests, or -plan state. - -Input: the complete `complete` result from the task execution phase, passed -verbatim. It is the authoritative handoff, and this phase owns reading the plan, -task, changed files, verification evidence, and reported context impact out of -it. - -Do not restate, summarize, or reconstruct any part of the execution result. Do -not reconstruct a missing execution result from conversation history. - -The execution result must have: - -```text -status: complete -``` - -Treat the execution result as the authoritative handoff for: - -- The resolved plan and completed task. -- Files changed by implementation. -- Implementation summary. -- Verification evidence. -- Done-check evidence. -- Reported context impact. - -This phase must not be run for `declined`, `blocked`, or `incomplete` execution -results. - -## 3.1 Validate the execution handoff - -Confirm that: - -- `status` is exactly `complete`. -- A `plan` object with a `path` is present. -- Exactly one completed task is identified. -- Changed files and an implementation summary are present. -- Verification evidence is present. -- Done-check evidence is present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, do -not modify context. Return a `blocked` Markdown report. - -## 3.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. Do not -create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that the task itself is complete and recorded in the plan, and that -synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -## 3.3 Discover applicable context - -Start with the execution result: - -- `context_impact.classification` -- `context_impact.affected_areas` -- Changed files. -- Implementation summary. -- Done-check evidence. - -Then inspect existing repository context in this order when present: - -1. `context/context-map.md` -2. Context files for the affected domain or subsystem -3. `context/overview.md` -4. `context/architecture.md` -5. `context/glossary.md` -6. `context/patterns.md` -7. Operational, product, or decision records directly related to the change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -completed implementation. A file that is absent is a gap; record it in the report -rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization done -while one of them is unchecked. - -## 3.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in task evidence. -- Speculation or future work not established by the completed implementation. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass. - -- `none`: Make no edits beyond any correction the root pass turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -A change is `root` when it introduces cross-cutting behavior, repository-wide -policy or contracts, an architecture or ownership boundary, or a change to -canonical terminology. A change confined to one feature or domain, with no -repository-wide behavior, architecture, or terminology impact, is `domain` or -`local`: capture its detail in domain files and leave the root files unedited. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -## 3.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- execution and done-check evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task - references, related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -## 3.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the implementation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the completed implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the execution result verbatim into context files. -- Do not change application code, tests, or plan state. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -### Feature existence - -Every feature the completed task implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the task implemented a feature no context file describes, add that -description. A feature that fits no existing domain file gets a new focused file; -do not defer it to a later task. Prefer a small, precise domain file over -overloading `overview.md` with detail. - -This is the one case where documentation is warranted by the change itself rather -than by a gap in durable knowledge. It is not license to narrate the diff: -describe what the feature is and how it behaves, not what was edited. - -### Glossary - -Add a `context/glossary.md` entry for any domain language the task introduced. -New terminology is durable knowledge whatever the classification is: a `domain` -change that names a new concept still earns its glossary entry. - -### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it into - focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough that - prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -## 3.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the completed implementation. -- No edited statement contradicts the code, plan, or execution evidence. -- Every qualifying decision has one written or reused ADR path in the report, and - the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Each feature implemented by the task has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not run full application or plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -## 3.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` means -existing context was checked and no edit was warranted. `blocked` means context -could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after it. - -Do not determine whether the plan is complete. The `/next-task` workflow owns -that decision after context synchronization. - -## Task context synchronization boundaries - -Do not: - -- Accept an execution result whose status is not `complete`. -- Implement or modify application code. -- Modify tests. -- Change task completion status or plan evidence. -- Determine whether the plan is complete. -- Select or execute another task. -- Run full-plan validation. -- Mark the plan validated, closed, or archived. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason to - document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return an execution-style internal state. -""" - -nextTaskOutput = """ -# Next-task output layouts - -Use only the applicable layout. Values come from internal workflow state. - -## Review blocked - -Present the selected task, then each issue's problem, impact, and required -decision. If plan resolution is ambiguous, list candidate paths and -`/next-task {candidate-path}`. State whether another task remains executable. - -## Plan already complete - -```markdown -------------------------------------- - -# Implementation tasks are complete. - -Run the final validation: - -`/validate {plan-path}` -``` - -## Declined - -```markdown -You have declined to proceed with this task -``` - -## Execution blocked or incomplete - -For `blocked`, present the blocker, work completed before it, and the required -decision or action. For `incomplete`, present completed work, verification -evidence, remaining work, and the reason it remains incomplete. - -## Context synchronization blocked - -State that task `{completed-task-id}` was implemented, verified, and recorded; -report the contradiction or synchronization failure, preserved edits, required -action, and retry condition. State that durable context is out of date and must -be synchronized before continuing. - -## More tasks remain - -```markdown -------------------------------------- - -# Task {completed-task-id} completed. - -{completed-tasks} of {total-tasks} tasks complete. - -Next up: - -{next-task-id} — {next-task-title} - -`/next-task {plan-path} {next-task-id}` -``` - -## All tasks complete - -```markdown -------------------------------------- - -# Task {completed-task-id} completed. - -All tasks are complete. - -Run the final validation: - -`/validate {plan-path}` -``` - -# Implementation gate - -Always show this gate at the start of the **Task execution phase**, before editing any -file. - -The gate is user-facing prose. It is never serialized into a YAML result. This -file is the only authority for the gate's content and order. - -## Format - -# `{task.id} - {task.title} - {plan.name}` - -## Goal - -{task.goal} - -## In scope - -- {task.in_scope} - -## Out of scope - -- {task.out_of_scope} - -## Done when - -- {task.done_checks} - -## Expected changes - -- List confirmed files or areas expected to change. -- Label uncertain entries as likely rather than confirmed. - -## Approach - -Describe the smallest coherent implementation approach in 2–5 steps. - -## Assumptions - -- Include material assumptions returned by plan review. -- Omit this section when there are no assumptions. - -## Risks or trade-offs - -- Include only risks relevant to approving this task. -- Omit this section when there are no meaningful risks. - -## Verification - -- {task.verification} - -When the `approve` flag is absent, end with exactly: - -`Continue with implementation now? (yes/no)` - -When the `approve` flag is supplied, omit the question and end after -**Verification**. - -## Rules - -- Show the gate exactly once for an unchanged task. -- Do not modify files before approval. -- Do not add requirements absent from the reviewed task. -- Do not present multiple competing approaches unless a material decision is - required. -- Do not emit YAML while waiting for the user's answer. Stop after the gate and - wait. -- If the handoff is stale or incomplete, show the known task information and - identify the problem under **Risks or trade-offs**. - -# Context Sync Report - -Return only one completed Markdown report using the applicable variant below. -Do not include unused sections, placeholders, YAML, or a fenced code block. - -The `Status` value must be exactly one of: - -- `synced` -- `no_context_change` -- `blocked` - -The input execution status is always `complete` and does not need to be repeated -as a separate workflow state. - -## Synced variant - -# Context Sync Report - -**Status:** synced\(" ") -**Plan:** `{plan path}`\(" ") -**Task:** `{task id} — {task title}` - -## Updated files - -- {List each changed file from the execution handoff except paths under - `context/`; state `None.` when no files remain.} - -## Updated context - -- `{context file}` — {concise description of the durable truth updated} - -## Architecture decisions - -- `{written or reused ADR path}` — {decision and status} -- None qualified. - -## Feature existence - -- `{feature}` — `{context file that canonically describes it}` - -## Verification - -- {How the edited context was checked against implementation and execution evidence.} -- {File hygiene: line counts, relative links, diagrams where structure is complex.} -- {Documentation, link, or formatting checks that were run, when applicable.} - -## Notes - -{Include only non-blocking information worth retaining. -Omit this section when unnecessary.} - ---- - -## No-context-change variant - -# Context Sync Report - -**Status:** no_context_change\(" ") -**Plan:** `{plan path}`\(" ") -**Task:** `{task id} — {task title}` - -## Updated files - -- {List each changed file from the execution handoff except paths under - `context/`; state `None.` when no files remain.} - -## Synchronization result - -{Explain why the completed implementation did not introduce durable, -non-obvious repository knowledge requiring an update.} - -## Context reviewed - -- `{context file or area}` — {what was checked and why it remains accurate} - -## Architecture decisions - -- `{reused ADR path}` — {decision and status} -- None qualified. - -## Feature existence - -- `{feature}` — `{context file that canonically describes it}`, already present. - -## Verification - -- {How existing context was compared with implementation and execution evidence.} - ---- - -## Blocked variant - -# Context Sync Report - -**Status:** blocked\(" ") -**Plan:** `{plan path}`\(" ") -**Task:** `{task id} — {task title}` - -## Updated files - -- {List each changed file from the execution handoff except paths under - `context/`; state `None.` when no files remain.} - -## Blocker - -**Problem:** {specific synchronization blocker}\(" ") -**Impact:** {why context cannot be made authoritative safely}\(" ") -**Required action:** {decision or correction required} - -## Context changes - -- {List safe context edits preserved, or state `No context files were changed.`} - -## Architecture decisions - -- `{ADR path written or reused before the blocker}` — {decision and status} -- None written or reused before the blocker. - -## Retry condition - -{State the concrete condition under which context synchronization should run -again.} - -## Report rules - -- Name exact context files when they were changed or reviewed. -- Under **Architecture decisions**, list every ADR path written or reused during - the decision gate. In a successful report, state `None qualified.` when the - gate skipped invocation. In a blocked report, state - `None written or reused before the blocker.` when applicable. -- Under **Updated files**, list every changed file from the execution handoff - except paths under `context/`. -- Report the missing context root as `blocked`, with `sce setup - --bootstrap-context` as the required action and the existence of `context/` as - the retry condition. -- Omit **Feature existence** only when the task implemented no feature. -- Describe durable truth, not implementation-session chronology. -- Keep evidence concise and factual. -- Do not claim final validation passed. -- Do not determine whether the plan is complete. -- Do not recommend a next implementation task. -""" - -validateSkillBody = """ -# SCE Validate - -## Purpose - -Own this workflow from input parsing through its terminal user-visible response. -Execute the phases below directly and in order. Phase statuses are internal state, -not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or -workflow command except `sce-decision`, and invoke `sce-decision` only from the -successful context-synchronization decision gate. Follow the canonical workflow's steps, gates, -and stops exactly as written: never invent, skip, reorder, or merge a step. - -## Phase references - -Each numbered step below dispatches to a phase whose steps and boundaries live in -a reference file. This document holds the control flow — which phase runs, what it -receives, and how its result branches — and each reference holds the phase itself. - -| Step | Read before running the phase | -|---|---| -| 1 | `references/validation.md` | -| 2 | `references/context-sync.md` | - -`references/validation-report.md` defines the `## Validation Report` section -written into the plan file. Step 1 points to it at the moment it is needed, on a -`validated` or `failed` outcome only. - -Read a step's reference before taking any action for that step, not after. Read -only the reference for the step you have reached: a run that stops at a `blocked` -or `failed` validation never enters step 2, which is why they are separate files. - -## User-visible output - -Use `references/output.md` for every gate and terminal response. Render no raw -internal state. The reference contains only human-visible Markdown layouts. -User-visible output is limited to those layouts: never invent a layout, and never -wrap one in an added preamble, commentary, summary, or extra section. - -## Composite control flow - -Keep phase results as internal state and continue immediately whenever the -canonical workflow says to continue. Stop only at a user wait or terminal branch. -Approval, clarification, revision, failed-validation repair, and bootstrap waits -resume this same skill in the same session. Never expose an internal phase result -as the workflow's final response. - -## Input - -`$ARGUMENTS` is the plan name or plan path. - -- The plan name or path is required. -- Resolve exactly one plan. Do not invent a plan from the conversation or from - incomplete nearby work. - -When `$ARGUMENTS` is empty, report that a plan name or path is required, state -the expected argument, and stop. Do not infer the plan from repository state or -the conversation. - -Pass the plan name or path to the **Validation phase** unmodified. Do not restate, -summarize, or pre-scope it. - -Every `{plan-path}` and `{candidate-path}` emitted anywhere in this workflow is -the path carried by the **Validation phase** in its Markdown result (`Plan:`, or a -candidate path), so every emitted command is directly runnable. - -## Workflow - -### 1. Validate the plan - -Read `references/validation.md`, then run the **Validation phase** with the plan -name or path. - -This phase measures finished work and never repairs it: it does not modify tests, -application code, or configuration to make a failing check pass. That property is -load-bearing, so reach it through the reference rather than acting from this -summary. - -Do not write the Validation Report yourself. - -Branch on the report's `Status:`. - -`blocked` -> Do not run context synchronization. Print the blocked Markdown -report as returned. Do not rephrase it into a different layout. Stop. - -`failed` -> Do not run context synchronization. Print the failed Markdown -report as returned. It is already a session handoff: self-contained, actionable, -and ending with `/validate {plan-path}` after repairs. - -Do not rewrite it into a shorter summary. Do not drop the retry command. Do not -add an alternate continuation that replaces `/validate`. - -Stop. Do not mark the plan finished. Do not continue to context synchronization. -Do not start the repair work in this workflow unless the user explicitly asks -to continue here; the default is that the handoff can leave this session. - -`validated` -> Pass the complete validated Markdown result to the **Plan context synchronization phase**. - -Do not reconstruct, summarize, or reinterpret the validation result before -passing it. - -### 2. Synchronize plan context - -Read `references/context-sync.md`, then run the **Plan context synchronization -phase** with the `Status: validated` Markdown result from the **Validation -phase**. - -Do not run the **Plan context synchronization phase** for `failed` or `blocked`. Those are not -success states. - -Pass the validated result verbatim. It is the authoritative handoff, and the **Plan context synchronization phase** -owns reading the plan path, required context paths, validation evidence, and -reported context impact out of it. - -Do not restate, summarize, or reconstruct any part of the validation result. - -This phase verifies the five root context files on every invocation, whatever the -reported impact, and must account for every path in the plan's `Context sync` -section, so it is never correct to skip it as unnecessary. - -Branch on the synchronization result. - -`blocked` -> Validation itself succeeded and is already recorded in the plan. -Render the **Context synchronization blocked** layout from -`references/output.md`. Nothing records the skipped synchronization, so it is -lost once this session ends. - -Stop. - -`synced` | `no_context_change` -> Print out the report returned by the **Plan context synchronization phase**. -Continue to the next step. - -### 3. Report completion - -Return exactly one completion block. Do not start another workflow. - -Render the **Completion** layout from `references/output.md`. - -When the synchronization status was `no_context_change`, keep the same -completion block. "Synchronized" here means the final context pass finished -successfully, including the case where no edit was warranted. - -Stop. - -## Rules - -- Validate at most one plan per invocation. -- Read each phase's reference before running that phase. -- Do not duplicate the internal instructions of embedded phases. -- The only permitted sibling-skill invocation is `sce-decision`, and only the - successful context-synchronization decision gate may invoke it. -- Do not run final validation when implementation tasks remain; the **Validation phase** - returns `blocked`, and this workflow stops. -- Run the **Plan context synchronization phase** only when the **Validation phase** returned - `Status: validated`. Do not run it for `failed` or `blocked`. -- On `failed`, print the handoff Markdown as returned and stop. Preserve the - retry `/validate {plan-path}` instruction. Do not synchronize context. -- Do not implement remaining plan tasks from this workflow unless the user - explicitly continues in-session after a failed handoff. -- Do not create a Git commit or push changes. -- Do not mark the plan archived or delete the plan. -- Do not execute a follow-up `/next-task`, `/change-to-plan`, or `/validate` - yourself. -- Do not infer success when an embedded phase returns a non-success status. -- Preserve validation evidence already written to the plan when context - synchronization fails. -""" - -validateValidation = """ -# Validation phase - -Run this phase for step 1 of the workflow. It resolves one plan, confirms the -implementation is finished, runs the plan's checks, and records what it found. - -Input: the plan name or path, unmodified. - -This phase exclusively owns: - -- Resolving one plan. -- Confirming every implementation task is complete. -- Running full validation and acceptance-criteria checks. -- Removing temporary scaffolding. -- Writing the Validation Report into the plan. -- Returning one Markdown validation result. - -Do not duplicate any of it elsewhere in the workflow. - -## 1.1 Resolve the plan - -Resolve the supplied plan name or path to exactly one existing plan under -`context/plans/`. - -When no plan can be found, set internal status `blocked`. - -When multiple plans match and none can be selected safely, set internal status -`blocked` with the matching candidates. - -Read the selected plan before exploring the repository. - -## 1.2 Confirm implementation is finished - -Set internal status `blocked` with incomplete tasks listed when any -implementation task remains incomplete. - -Final validation measures finished work. Do not run the full suite against a -partial stack, and do not complete remaining tasks here. - -## 1.3 Read the validation contract from the plan - -From the plan, collect: - -- Every acceptance criterion and its `Validate:` check. -- The `Full validation` command list. -- The `Context sync` requirements, for the context-impact handoff only. - -Set internal status `blocked` when the plan has no usable acceptance criteria, or -when no validation commands can be determined from the plan or repository -conventions. - -Prefer the plan's authored checks. Fall back to repository-primary test, lint, -and format commands only when `Full validation` is absent, and record that -fallback under notes on a `validated` or `failed` result. - -## 1.4 Remove temporary scaffolding - -Before or while running checks, remove temporary scaffolding introduced during -the change when it is clearly throwaway: - -- Debug-only patches or flags left enabled. -- Temporary files or intermediate artifacts not part of the delivered design. -- Local scaffolding the plan or task notes mark as temporary. - -Do not delete durable product code, tests, configuration, or context files. - -Record every removed path. When nothing temporary remains, report `None.` - -## 1.5 Run full validation and acceptance checks - -Run the plan's `Full validation` commands. - -Then verify each acceptance criterion using its `Validate:` line. Prefer a -runnable command. Use a named inspection only when the criterion authorizes it, -and say exactly what was inspected. - -When a check fails, record the failure and continue gathering evidence. Do not -modify tests, application code, or configuration to make a check pass. Final -validation measures the finished work; repair belongs to a later work session, -not this skill. - -Never report a check as passed unless it ran successfully or the authorized -inspection confirmed the criterion. - -Do not run task-by-task implementation work for incomplete tasks. That belongs to -`/next-task`. - -## 1.6 Update the plan - -For `validated` and `failed` outcomes: - -- Mark each acceptance criterion checkbox to match the evidence. -- Append or replace the plan's `## Validation Report` section using - `references/validation-report.md`. Read that file before writing the section. -- When status is `failed`, the plan-file report must include the retry command - `/validate {plan path}`. - -Do not reopen completed tasks, rewrite task evidence, or change the task stack. - -For `blocked`, leave the plan file unchanged. - -## 1.7 Determine context impact for the handoff - -On `validated` only, classify the durable context impact of the finished plan so -the **Plan context synchronization phase** can start from the plan's own -requirements: - -- Start from the plan's `Context sync` section. -- Inspect what the completed implementation actually changed when needed. -- Report required context paths and affected areas. -- Use `none`, `local`, `domain`, or `root` with the same meanings as task-level - context sync. - -Do not edit context files here. - -On `failed` or `blocked`, omit context impact; context sync will not run. - -## 1.8 Return the internal state - -Set exactly one internal state: - -- `validated` when every acceptance criterion is met, required full validation - passed, and the Validation Report was written. -- `failed` when evidence was captured but required checks or criteria remain - unsatisfied. Shape it as a session handoff per `references/output.md`, ending - recommended work with `/validate {plan path}`. -- `blocked` when validation cannot proceed safely. - -Record only the Markdown report. Do not add explanatory prose before or after it. -Do not return internal state. - -A `validated` result is the authoritative handoff into step 2, which reads the -plan path, required context paths, validation evidence, and reported context -impact out of it. It must report: - -```markdown -**Status:** validated -**Plan:** {plan path} -``` - -and must carry the resolved plan path, validation commands and outcomes, -acceptance-criteria evidence, scaffolding removals, and the reported context -impact with required context paths and affected areas. Step 2 is forbidden from -reconstructing any of that, so it has to be present here. - -## Validation boundaries - -Do not: - -- Validate more than one plan. -- Complete remaining implementation tasks. -- Modify tests, application code, or configuration to make a failing check pass. -- Apply lint or format auto-fixes that change product or test files as part of - making validation green. -- Synchronize durable context under `context/` outside the plan file. -- Create the context root. -- Mark the plan archived or delete the plan. -- Create a Git commit or push changes. -- Invent acceptance criteria the plan does not state. -- Claim verification that was not performed. -- Return a internal state. -- Run plan context synchronization. The workflow owns that step. -""" - -validateContextSync = """ -# Plan context synchronization phase - -Run this phase for step 2 of the workflow, and only with a `Status: validated` -Markdown result from the validation phase. It is the plan-level final context -pass: it starts from the plan's `Context sync` requirements and the validated -implementation, and closes gaps that remain after any task-level syncs already -ran. - -Do not run this phase for `failed` or `blocked`. Those are not success states. -Same rule as the task context synchronization phase: context sync runs only after -a successful prior phase. - -Pass the validated result verbatim. It is the authoritative handoff, and this -phase owns reading the plan path, required context paths, validation evidence, -and reported context impact out of it. - -Do not restate, summarize, or reconstruct any part of the validation result. Do -not reconstruct a missing validation result from conversation history. - -Treat that Markdown as the authoritative handoff for: - -- The resolved plan path. -- Validation commands and outcomes. -- Acceptance-criteria evidence. -- Scaffolding removals. -- Reported context impact, required context paths, and affected areas. - -## 2.1 Validate the validation handoff - -Confirm that: - -- `Status:` is exactly `validated`. -- `Plan:` names an existing plan path. -- Acceptance-criteria evidence is present and every criterion is met. -- Commands run are present. -- A context-impact classification is present. - -If the handoff is missing required information or is internally contradictory, do -not modify context. Return a `blocked` Markdown report. - -## 2.2 Confirm the context root - -When `context/` does not exist, there is no durable memory to synchronize. Do not -create it, and do not write context files outside it. - -Return a `blocked` report whose required action is: - -`sce setup --bootstrap-context` - -State that validation itself succeeded and is recorded in the plan, and that plan -context synchronization should run again once the context root exists. - -Bootstrapping is the user's action, not this phase's. - -## 2.3 Discover applicable context - -Start with the validated internal state: - -- **Context impact** classification, required context, and affected areas. -- Acceptance-criteria evidence. -- Commands run. - -Then read the plan's `Context sync` section and inspect existing repository -context in this order when present: - -1. Paths named by the plan's `Context sync` section -2. `context/context-map.md` -3. Context files for the affected domain or subsystem -4. `context/overview.md` -5. `context/architecture.md` -6. `context/glossary.md` -7. `context/patterns.md` -8. Operational, product, or decision records directly related to the finished - change - -Use the context map and existing links to locate authoritative files. - -Do not scan or rewrite the entire `context/` tree by default. - -Do not create a new context file when an existing authoritative file can be -updated coherently. - -### The mandatory root pass - -Every invocation verifies these five files against code truth, whatever the -reported classification is: - -- `context/overview.md` -- `context/architecture.md` -- `context/glossary.md` -- `context/patterns.md` -- `context/context-map.md` - -Verifying is not editing. A classification that warrants no root edit still -requires reading each of these and confirming it is not contradicted by the -finished implementation. A file that is absent is a gap; record it in the report -rather than creating it to satisfy the pass. - -Report each of the five as verified or edited. Never declare synchronization done -while one of them is unchecked. - -### Plan context requirements - -Every path or statement listed under the plan's `Context sync` section must be -accounted for in the report as already accurate or updated. A requirement the -finished code still does not satisfy is a blocker, not a note. - -## 2.4 Determine whether durable context changed - -Use the reported context impact as a strong hint, then verify it against the -finished implementation and existing context. - -Durable context includes non-obvious repository knowledge such as: - -- User-visible or externally observable behavior. -- Architecture, boundaries, ownership, and dependency direction. -- Public interfaces, data contracts, and persistence behavior. -- Operational procedures and important failure modes. -- Security or privacy behavior. -- Shared terminology. -- Intentional limitations and meaningful design decisions. - -Do not document: - -- Details already obvious from the implementation. -- Temporary debugging information. -- A file-by-file narration of the change. -- Test output that belongs only in validation evidence. -- Speculation or future work not established by the finished plan. -- Generic engineering practices. - -Interpret impact classifications as follows. Each governs which files are -*edited*; none of them waives the mandatory root pass or the plan's Context sync -requirements. - -- `none`: Make no edits beyond any correction the root pass or unmet plan context - requirement turns up. -- `local`: Update the nearest existing authoritative context only when the new - behavior is not reliably discoverable from code. -- `domain`: Update affected domain context and the context map when its links or - summaries changed. -- `root`: Update the relevant root context and any affected domain context. - -If the reported classification is inconsistent with the actual change, use the -verified classification and explain the difference in the report. - -## 2.5 Record qualifying architecture decisions - -During this successful synchronization, determine whether the completed change -establishes or changes a system-wide important constraint involving one or more -of: - -- System boundaries or ownership. -- Public or cross-domain interfaces. -- Data models or persistence. -- Compatibility contracts. -- Security posture. -- Deployment or distribution strategy. -- A major dependency. -- A similarly durable constraint that is costly or risky to reverse. - -Routine implementation details, local refactors, naming and formatting choices, -temporary experiments, and easily reversible choices do not qualify. Do not -invoke a decision skill for them. - -Use the discovered context, existing decision records, and this evidence: - -- acceptance-criteria and validation evidence. - -Identify each qualifying decision, then handle qualifying decisions in -deterministic order: - -1. Reuse a written ADR path already returned during this plan when it records the - same decision. -2. Otherwise invoke `sce-decision` once with exactly one structured decision - request containing the decision, qualifying evidence, plan and task references, - related context and ADR paths, and any user-requested status. -3. On `written`, retain the returned `adr_path` as synchronization evidence and - make it available for current-state context links before synchronization - completes. Reuse is valid evidence; do not create a duplicate ADR. -4. On `blocked`, stop before current-state context edits and return a `blocked` - synchronization report carrying the decision-writing problem, impact, required - action, and retry condition. - -Invoke `sce-decision` only here, after a successful execution or validation -handoff and during context synchronization. Do not invoke it from a non-success -branch or for any non-decision purpose. When no decision qualifies, continue -without invoking it and record that outcome in synchronization evidence. - -## 2.6 Synchronize context - -Make the smallest coherent documentation change that preserves repository truth. - -When editing context: - -- Describe the resulting behavior, not the validation session. -- Preserve repository terminology and document structure. -- Remove or correct statements contradicted by the finished implementation. -- Update cross-references when files are added, moved, renamed, or superseded. -- Keep one authoritative statement for each durable fact. -- Avoid copying the validation result verbatim into context files. -- Do not change application code, tests, or plan validation evidence. - -Create a new context file only when: - -- The knowledge is durable and non-obvious. -- No existing file owns it coherently. -- The new file has a clear place in the context map. - -### Feature existence - -Every feature the finished plan implemented must have at least one durable -canonical description discoverable from `context/`, in a domain file under -`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. - -When the plan delivered a feature no context file describes, add that -description. Prefer a small, precise domain file over overloading `overview.md` -with detail. - -This is not license to narrate the diff: describe what the feature is and how it -behaves, not what was edited during the plan. - -### Glossary - -Add a `context/glossary.md` entry for any domain language the plan introduced. -New terminology is durable knowledge whatever the classification is. - -### File hygiene - -Every context file this phase writes must satisfy: - -- One topic per file. -- At most 250 lines. When an edit would push a file past 250 lines, split it into - focused files and link them rather than letting it grow. -- Relative paths in every link to another context file. -- A Mermaid diagram where structure, boundaries, or flows are complex enough that - prose alone would not carry them. -- Concrete code examples only where they clarify non-trivial behavior. - -When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a -concise pointer behind, and link the new file from `context/context-map.md`. - -## 2.7 Verify synchronization - -After edits, verify: - -- Every changed context file accurately reflects the finished implementation. -- No edited statement contradicts the code, plan, or validation evidence. -- Every qualifying decision has one written or reused ADR path in the report, and - the report states when no decision qualified. -- Every file in the mandatory root pass was read and confirmed against code - truth, whether or not it was edited. -- Every plan `Context sync` requirement is met. -- Each feature implemented by the plan has a durable canonical description - reachable from `context/`. -- Every changed file is at or below 250 lines, covers one topic, and links other - context files by relative path. -- Diagrams are present where structure, boundaries, or flows are complex. -- Links and referenced paths resolve when practical to check. -- New context files are reachable from the context map or another authoritative - index. -- Root context remains concise and delegates details to domain files. -- Unrelated context was not changed. - -Use focused documentation, link, or formatting checks when available. - -Do not rerun full-plan validation. - -If synchronization cannot be completed without inventing facts or resolving a -material contradiction, preserve safe edits when appropriate and return a -`blocked` report. - -## 2.8 Return the Markdown report - -Set exactly one report status: - -- `synced` -- `no_context_change` -- `blocked` - -`synced` means context files were updated and verified. `no_context_change` means -existing context was checked and no edit was warranted. `blocked` means context -could not be synchronized safely. - -Record only the Markdown report. Do not add explanatory prose before or after it. - -## Plan context synchronization boundaries - -Do not: - -- Accept a validation result whose status is not `validated`. -- Accept `failed` or `blocked` validation results. -- Implement or modify application code. -- Modify tests. -- Change task completion status, acceptance-criteria marks, or the Validation - Report. -- Rerun full-plan validation. -- Select or execute an implementation task. -- Create a Git commit or push changes. -- Create the context root. `sce setup --bootstrap-context` owns that. -- Narrate changed files as documentation. Feature existence is the only reason to - document a change that introduced no other durable knowledge. -- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` - outside the decision gate in successful context synchronization. -- Delete a context file that has uncommitted changes. -- Return internal state. -""" - -validateValidationReport = """ -# Internal persisted-document format: Plan-file validation report - -The Markdown section the **Validation phase** appends to the plan file when -returning `validated` or `failed`. Write it at the end of -`context/plans/{plan_name}.md` under exactly one `## Validation Report` heading. - -This is plan-file content. The result returned to the workflow is defined -separately in `references/output.md`. - -Do not author this section while planning. Only `/validate` through the -**Validation phase** writes it. - -## Layout - -```markdown -## Validation Report - -**Status:** {validated | failed}\(" ") -**Date:** {YYYY-MM-DD} - -### Commands run - -- `{command}` -> exit {code} ({concise outcome summary}) -- `{command}` -> exit {code} ({concise outcome summary}) - -### Scaffolding removed - -- `{path}` — {why it was temporary} -- None. - -### Success-criteria verification - -- [x] AC1: {criterion statement} -> {evidence} -- [ ] AC2: {criterion statement} -> {evidence of failure or not checked} - -### Failed checks and follow-ups - -- {check}: {problem}; evidence: {command output or inspection}; required: {decision or next action} -- None. - -### Residual risks - -- {risk} -- None identified. - -### Retry - -{Only when Status is failed:} - -After repairs, rerun: - -`/validate {plan path}` -``` - -## Rules - -- Use **Status:** `validated` only when every acceptance criterion is met and - every required full-validation command passed. -- Use **Status:** `failed` when evidence was captured but required checks or - criteria remain unsatisfied. -- List every command that ran under **Commands run**, including ones that failed. - Do not invent exit codes or outcomes. -- Prefer the plan's `Full validation` commands and each criterion's `Validate:` - line over rediscovering project defaults. Fall back to repository conventions - only when the plan omits them. -- Mark each acceptance criterion checkbox in the plan's `## Acceptance criteria` - section to match the evidence. Do not mark a criterion met unless the check ran - successfully or the inspection named by `Validate:` confirms it. -- Under **Scaffolding removed**, list only temporary debug code, intermediate - artifacts, or throwaway files introduced during the change. Write `None.` when - nothing temporary remained. -- Under **Failed checks and follow-ups**, record the failing check and its - evidence only. Do not describe code or test edits made during validation; - validation does not modify tests or product code to clear failures. Write - `None.` when status is `validated`. -- When status is `failed`, always include **Retry** with the exact - `/validate {plan path}` command. Omit **Retry** when status is `validated`. -- Keep evidence concise and factual. Do not narrate the whole implementation - history. -- Do not claim context synchronization completed. Plan context sync is a later - workflow step and runs only after `validated`. -- Do not rewrite task evidence or reopen completed tasks. -- When a previous `## Validation Report` already exists, replace it with the new - one rather than stacking duplicates. -""" - -validateOutput = """ -# Validate output layouts - -Use only the applicable layout. Values come from internal workflow state. - -The `blocked` and `failed` layouts are stated once, under **Validation Result** -below. - -## Context synchronization blocked - -State that validation passed and its report is recorded, then report the context -failure, preserved edits, required action, and retry condition. State that durable -context remains out of date and synchronization must finish before closure. - -## Completion - -```markdown -------------------------------------- - -# Plan {plan-name} validated. - -All implementation tasks were already complete. -Final validation passed. -Durable context is synchronized. - -Validation report: {plan-path} -``` - -# Validation Result - -Return only one completed Markdown report using the applicable variant below. -Do not include unused sections, placeholders, YAML, or a fenced code block. - -The `Status` value must be exactly one of: - -- `validated` -- `failed` -- `blocked` - -The plan-file `## Validation Report` section is written separately using -`references/validation-report.md`. This layout carries the validation phase's -result into the workflow's own branches. - -## Validated variant - -# Validation Report - -**Status:** validated\(" ") -**Plan:** `{plan path}`\(" ") -**Name:** `{plan name}`\(" ") -**Tasks:** `{completed}/{total} complete`\(" ") -**Date:** `{YYYY-MM-DD}` - -## Commands run - -- `{command}` -> {passed} — {concise outcome summary} - -## Acceptance criteria - -- [x] AC1: {criterion statement} — {evidence} -- [x] AC2: {criterion statement} — {evidence} - -## Scaffolding removed - -- `{path}` — {why it was temporary} -- None. - -## Residual risks - -- {risk} -- None identified. - -## Context impact - -**Classification:** `{none | local | domain | root}`\(" ") -**Affected areas:** `{comma-separated areas}`\(" ") -**Required context:** - -- `{path or statement from the plan Context sync section}` - -{One or two sentences on why this classification fits the finished plan.} - -## Notes - -{Include only non-blocking information worth retaining. -Omit this section when unnecessary.} - ---- - -## Failed variant - -This variant is a session handoff. Another agent or a later session must be -able to act from it alone. Write it as a prompt the user can paste forward, not -as a summary of the validation run. - -# Validation failed — handoff - -**Status:** failed\(" ") -**Plan:** `{plan path}`\(" ") -**Name:** `{plan name}`\(" ") -**Tasks:** `{completed}/{total} complete`\(" ") -**Date:** `{YYYY-MM-DD}`\(" ") -**Validation report:** written to `{plan path}` - -## Goal for the next session - -Repair the unfinished validation so every acceptance criterion and full -validation command passes. Do not modify tests or product code inside a -`/validate` run to force green results; fix the implementation (or the plan) in -a normal work session, then rerun validation. - -## What failed - -- `{check or AC id}`: {problem} - - Evidence: {command output, exit summary, or inspection finding} - - Required action: {concrete repair or decision} - -## Acceptance criteria - -- [x] AC1: {criterion} — {evidence} -- [ ] AC2: {criterion} — {why unmet} - -## Commands run - -- `{command}` -> {passed | failed | not_run} — {concise outcome summary} - -## Constraints - -- All implementation tasks were already complete when validation ran. -- Validation did not modify tests, application code, or configuration to clear - failures. -- Durable context was not synchronized; plan context sync runs only after - validation succeeds. -- Prefer the plan at `{plan path}` and its Validation Report as the source of - recorded evidence. - -## Residual risks - -- {risk} -- None identified. - -## Recommended work - -1. {First concrete fix, with files or areas when known} -2. {Second concrete fix, or decision the user must make} -3. Rerun final validation after the fixes land: - -`/validate {plan path}` - -Do not stop after the repair. The plan is not finished until `/validate` -returns `validated` and plan context sync completes. - ---- - -## Blocked variant - -# Validation blocked - -**Status:** blocked\(" ") -**Plan:** `{plan path when resolved}`\(" ") -**Name:** `{plan name when resolved}` - -## Issues - -- **{issue id}** ({category}): {problem} - - Impact: {impact} - - Required: {decision or action} - -## Incomplete tasks - -- `{task id}` — {title} -- Omit this section when no incomplete tasks apply. - -## Candidates - -- `{candidate plan path}` -- Omit this section when plan resolution was not ambiguous. - -## Next step - -{Exactly one continuation, matching the blocker:} - -- Incomplete tasks: - -`/next-task {plan path}` - -- Ambiguous plan: - -`/validate {candidate path}` - -- Missing plan content or other blocker: state the decision required. Do not - invent a command. - ---- - -## Report rules - -- Name the exact `Plan:` path so every emitted command is runnable. -- Use **Status:** exactly `validated`, `failed`, or `blocked`. -- Never claim a check passed unless it ran successfully or the authorized - inspection confirmed it. -- Do not modify tests or product code to clear a failure; record it under - **What failed**. -- The failed variant must always end its **Recommended work** with - `/validate {plan path}` as the final step after repairs. -- The failed variant must be self-contained enough to hand to another session - without the original chat. -- Include **Context impact** only on `validated`. Omit it on `failed` and - `blocked`; plan context sync is not run for non-success states. -- Do not include context synchronization results in this report. The invoking - workflow runs the **Plan context synchronization phase** only after `validated`. -- Do not select or describe an unrelated next implementation task when status is - `validated`. -- Omit empty optional sections rather than writing placeholders. - -# Plan Context Sync Report - -Return only one completed Markdown report using the applicable variant below. -Do not include unused sections, placeholders, YAML, or a fenced code block. - -The `Status` value must be exactly one of: - -- `synced` -- `no_context_change` -- `blocked` - -The input validation status is always `validated` and does not need to be -repeated as a separate workflow state. This report is not produced for -`failed` or `blocked` validation results. - -## Synced variant - -# Plan Context Sync Report - -**Status:** synced\(" ") -**Plan:** `{plan path}` - -## Context impact - -**Classification:** `{local | domain | root}`\(" ") -**Affected areas:** `{comma-separated areas}` - -{Explain which durable behavior, architecture, terminology, operation, or -constraint required plan-level synchronization after validation.} - -## Plan context requirements - -- `{required context path or statement from the plan}` — {met by edit | already accurate} - -## Updated context - -- `{context file}` — {concise description of the durable truth updated} - -## Architecture decisions - -- `{written or reused ADR path}` — {decision and status} -- None qualified. - -## Root pass - -- `context/overview.md` — {verified | edited | absent} -- `context/architecture.md` — {verified | edited | absent} -- `context/glossary.md` — {verified | edited | absent} -- `context/patterns.md` — {verified | edited | absent} -- `context/context-map.md` — {verified | edited | absent} - -## Feature existence - -- `{feature}` — `{context file that canonically describes it}` - -## Verification - -- {How the edited context was checked against the finished implementation and validation evidence.} -- {File hygiene: line counts, relative links, diagrams where structure is complex.} -- {Documentation, link, or formatting checks that were run, when applicable.} - -## Notes - -{Include only non-blocking information worth retaining. -Omit this section when unnecessary.} - ---- - -## No-context-change variant - -# Plan Context Sync Report - -**Status:** no_context_change\(" ") -**Plan:** `{plan path}` - -## Context impact - -**Classification:** none - -{Explain why the finished plan introduced no durable, non-obvious repository -knowledge requiring an update, or why existing context already matched.} - -## Plan context requirements - -- `{required context path or statement from the plan}` — already accurate -- None listed by the plan. - -## Context reviewed - -- `{context file or area}` — {what was checked and why it remains accurate} - -## Architecture decisions - -- `{reused ADR path}` — {decision and status} -- None qualified. - -## Root pass - -- `context/overview.md` — {verified | absent} -- `context/architecture.md` — {verified | absent} -- `context/glossary.md` — {verified | absent} -- `context/patterns.md` — {verified | absent} -- `context/context-map.md` — {verified | absent} - -## Feature existence - -- `{feature}` — `{context file that canonically describes it}`, already present. - -## Verification - -- {How existing context was compared with the finished implementation and validation evidence.} - ---- - -## Blocked variant - -# Plan Context Sync Report - -**Status:** blocked\(" ") -**Plan:** `{plan path}` - -## Blocker - -**Problem:** {specific synchronization blocker}\(" ") -**Impact:** {why context cannot be made authoritative safely}\(" ") -**Required action:** {decision or correction required} - -## Context changes - -- {List safe context edits preserved, or state `No context files were changed.`} - -## Architecture decisions - -- `{ADR path written or reused before the blocker}` — {decision and status} -- None written or reused before the blocker. - -## Retry condition - -{State the concrete condition under which plan context synchronization should -run again.} - -## Report rules - -- Name exact context files when they were changed or reviewed. -- Under **Architecture decisions**, list every ADR path written or reused during - the decision gate. In a successful report, state `None qualified.` when the - gate skipped invocation. In a blocked report, state - `None written or reused before the blocker.` when applicable. -- Report every file in the root pass, including any that is absent. -- Report the missing context root as `blocked`, with `sce setup - --bootstrap-context` as the required action and the existence of `context/` as - the retry condition. -- Cover every path or statement listed in the plan's `Context sync` section - under **Plan context requirements**. -- Omit **Feature existence** only when the plan implemented no feature. -- Describe durable truth, not validation-session chronology. -- Keep evidence concise and factual. -- Do not claim implementation tasks remain open. -- Do not reopen validation checks. -- Do not recommend a next implementation task unless context cannot be repaired - without one, and then only as the required action. -""" - -commitSkillBody = """ -# SCE Commit - -## Purpose - -Own this workflow from input parsing through its terminal user-visible response. -Execute the phases below directly and in order. Phase statuses are internal state, -not inter-skill handoffs. Do not invoke another SCE skill, sibling package, or -workflow command. Follow the canonical workflow's steps, gates, -and stops exactly as written: never invent, skip, reorder, or merge a step. - -## Phase reference - -Both paths below dispatch to the same phase, whose steps and boundaries live in -`references/atomic-commit.md`. This document holds the control flow — which path -runs, what the phase receives, and how its result branches — and the reference -holds the phase itself. - -Read `references/atomic-commit.md` before running the phase, not after. A regular -run that stops at the staging gate, and a bypass run that finds nothing staged, -both end without ever needing it. - -## User-visible output - -Use `references/output.md` for every gate and terminal response. Render no raw -internal state. The reference contains only human-visible Markdown layouts. -User-visible output is limited to those layouts: never invent a layout, and never -wrap one in an added preamble, commentary, summary, or extra section. - -## Composite control flow - -Keep phase results as internal state and continue immediately whenever the -canonical workflow says to continue. Stop only at a user wait or terminal branch. -Approval, clarification, revision, failed-validation repair, and bootstrap waits -resume this same skill in the same session. Never expose an internal phase result -as the workflow's final response. - -## Input - -`$ARGUMENTS` is optional. Split it into two parts before invoking the skill: - -`[mode-token] [commit context]` - -- `mode-token` is present only when the first whitespace-separated token is - exactly `oneshot` or `skip`, compared case-insensitively. Any other first - token is not a mode token. -- `commit context` is everything else: free-form prose that refines message - wording only. - -A `mode-token` selects the bypass path. Its absence selects the regular path. -Do not infer the bypass path from anything else — not from the commit context, -not from repository state, and not from the conversation. - -Empty `$ARGUMENTS` is valid. It selects the regular path with no commit -context, and commit intent is inferred from the staged changes alone. - -Pass `commit context` to the **Atomic commit phase** unmodified. Do not restate, -summarize, or pre-scope it. Never pass the `mode-token` as commit context. - -Staged changes are the source of truth for what is being committed. This -command never stages, unstages, or modifies files. - -## Workflow - -Follow exactly one path. - -### Regular path (no mode token) - -#### 1. Confirm staging - -Before running the phase, stop and prompt the user with the **Regular-mode -staging gate** layout from `references/output.md`. - -Wait for the user's confirmation. Do not stage files on their behalf, and do -not skip this prompt because the working tree looks ready. - -#### 2. Propose commits - -After confirmation, read `references/atomic-commit.md`, then run the **Atomic -commit phase** with `mode: regular` and the commit context. - -Do not write commit messages yourself. - -Branch on `status`: - -`blocked` -> Render the **Blocked** layout from `references/output.md`. Stop. - -`proposal` -> Render the **Regular proposal** layout from `references/output.md`, -which covers each proposed commit's message and files, and the split rationale -when more than one commit is proposed. - -Then stop. The regular path is proposal-only. - -Do not run `git commit`. Do not offer to commit on the user's behalf. The user -runs the commits they accept. - -### Bypass path (`oneshot` or `skip`) - -#### 1. Validate that staged content exists - -Run `git diff --cached --quiet`. A zero exit status means nothing is staged. - -When nothing is staged, stop with the **No staged changes** layout from -`references/output.md`. - -Do not stage anything. Do not proceed to the skill. - -#### 2. Request one commit message - -Read `references/atomic-commit.md`, then run the **Atomic commit phase** with -`mode: bypass` and the commit context. - -Bypass mode is the skill's contract for producing exactly one message. Do not -restate its overrides here; the **Atomic commit phase** owns them. - -Branch on `status`: - -`blocked` -> Render the **Blocked** layout from `references/output.md` and stop. Do not commit. - -`bypass_message` -> Continue to the next step. - -The skill never returns `proposal` in bypass mode. Treat a `proposal` result as -a contract violation: report it and stop without committing. - -#### 3. Execute exactly one commit - -Run `git commit` once with the returned message. - -On success, render the **Bypass success** layout from `references/output.md` and -stop. - -On failure, render the **Bypass Git failure** layout from the same file and stop. - -Do not retry, do not amend, do not stage additional files, and do not invent a -fallback commit. - -## Rules - -- Produce at most one commit per invocation, and only on the bypass path. -- Never commit on the regular path. -- Recognize `oneshot` and `skip` only as an exact case-insensitive first token. - They are behaviorally identical. -- Read `references/atomic-commit.md` before running the phase. -- Do not duplicate the internal instructions of the **Atomic commit phase**. -- Do not stage, unstage, restore, or otherwise modify files. -- Do not amend, reset, revert, rebase, or push. -- Do not read unstaged or untracked changes as commit input. -- Do not infer success when the **Atomic commit phase** returns a non-success status. -- Do not proceed past a failed `git commit`. -- Do not run plan, task, or validation workflows from this command. -""" - -commitAtomicCommit = """ -# Atomic commit phase - -Both workflow paths run this phase. The regular path runs it with `mode: regular` -after the staging gate; the bypass path runs it with `mode: bypass` after -confirming staged content exists. - -Input: the mode, supplied by the workflow from an explicit user-supplied token, -and the commit context. - -This phase exclusively owns: - -- Reading and analyzing the staged diff. -- Deciding whether staged changes form one coherent unit or several. -- Classifying staged scope and applying context-file guidance gating. -- Writing every commit message subject and body. -- Applying the plan-citation body rule. - -Do not duplicate any of it elsewhere in the workflow. Do not write commit messages -outside this phase. - -Never infer the mode, and never switch modes mid-analysis. - -Commit context refines wording only. The staged diff decides what the change is; -context never overrides staged truth, and never adds a claim the diff does not -support. - -Do not accept an unstaged diff, a working-tree summary, or a conversational -description as a substitute for the staged diff. - -## 1. Read the staged diff - -Read the staged changes with `git diff --cached`, and the staged file list with -`git diff --cached --name-status`. - -Read staged file contents only when the diff alone does not explain the change. - -Set internal status `blocked` when nothing is staged. - -## 2. Identify coherent units - -Infer the main reason for the staged change from the diff first. - -A coherent unit is one goal a reviewer would accept as a single commit. Group -staged files by that goal, not by directory. - -In `bypass` mode, stop grouping here: the result is exactly one message covering -all staged files, whether or not the diff is coherent. Do not propose splits, and -do not report split guidance. - -## 3. Choose a scope for each unit - -Use the smallest stable subsystem or module name recognizable in the repository. - -When no such name applies, use the primary directory or package of the unit's -changes. - -## 4. Write each message - -Follow `references/output.md` for the subject pattern, the body rules, issue -references, the plan-citation rule, and the anti-patterns. - -## 5. Apply the plan-citation rule - -When the unit's staged files include `context/plans/*.md`, cite the affected plan -slug and updated task IDs in the body. - -When the staged plan diff does not expose the slug or task ID clearly enough to -cite faithfully: - -- In `regular` mode, set internal status `blocked` and ask for the reference to be - stated or staged explicitly. -- In `bypass` mode, infer the citation when the diff supports it, and otherwise - omit it. Never stop, and never invent a slug or task ID. - -## 6. Apply context-file guidance gating - -This step applies in `regular` mode only. Skip it entirely in `bypass` mode; do -not classify staged scope there. - -Classify the staged diff: - -- Context-only (`context/**`): context-file-focused guidance is allowed. -- Mixed (`context/**` plus non-`context/**`): suppress default context-file commit - reminders and give guidance that reflects the full staged scope. - -## 7. Propose split guidance - -This step applies in `regular` mode only. - -When the units found in step 2 pursue unrelated goals, return one message per -unit, and state why the split is recommended and which staged files belong to -each. - -When the staged changes form one unit, return one message and no split guidance. -Do not split coherent work to appear thorough. - -## 8. Validate the result - -Confirm before returning that: - -- Every message describes its unit faithfully and covers only that unit's files. -- Every staged file belongs to exactly one returned message. -- No plan slug or task ID appears that the staged diff does not support. -- The mode's own constraints hold. - -## 9. Return internal state - -Set exactly one internal state: - -- `proposal` in `regular` mode, with one or more messages. -- `bypass_message` in `bypass` mode, with exactly one message. -- `blocked` when messages cannot be written faithfully. - -Record only the internal state. Do not add explanatory prose before or after it. - -## Atomic commit boundaries - -Do not: - -- Run `git commit`, or any command that writes to the repository or its index. -- Stage, unstage, or modify files. -- Ask the user to stage or confirm staging. -- Analyze unstaged or untracked changes. -- Return more than one message in `bypass` mode. -- Return split guidance in `bypass` mode. -- Stop for plan-citation ambiguity in `bypass` mode. -- Invent plan slugs, task IDs, or issue references. -- Mention `context/` synchronization activity in a commit message. -- Claim a message was committed. -- Run plan, task, or validation workflows. -""" - -commitOutput = """ -# Commit output layouts - -Use only the applicable layout. Values come from staged truth and internal -workflow state. - -## Regular-mode staging gate - -```markdown -Please run `git add ` for all changes you want included in this commit. -Atomic commits should only include intentionally staged changes. -Confirm once staging is complete. -``` - -## No staged changes - -```markdown -No staged changes. Stage changes before commit. -``` - -## Regular proposal - -For each proposal, present the complete commit message and covered files. When -more than one commit is proposed, also present the split rationale. Do not claim a -commit was created. - -## Blocked - -Present every issue's problem, impact, and required decision. Do not commit. - -## Bypass success - -```markdown -Committed {commit-hash} -``` - -## Bypass Git failure - -Present Git's failure unchanged and stop without retrying. - -# Commit message style - -The wording rules for every message the **Atomic commit phase** returns, in either -mode. This file is the only authority for message content and shape. - -Messages are carried in the result's `message` field, subject first, then one -blank line, then the body. - -## Subject - -Pattern: - -`: ` - -- Scope is the smallest stable subsystem or module name recognizable in the - repository. When no such name applies, use the primary directory or package - of the change. -- Start the summary with an imperative verb: Fix, Add, Remove, Implement, - Refactor, Simplify, Rename, Update, Ensure, Allow. -- Capitalize the verb. Do not end the subject with a period. -- Keep it concrete and technical. Name what changed, not how it felt. - -## Body - -Include a body whenever the subject alone leaves the change unexplained. Omit -it for changes whose subject is self-evident. - -A body says what was wrong or missing, why it mattered, what changed -conceptually, and the impact. It does not restate the subject in longer words, -and it does not narrate the editing process. - -Wrap the body at a readable width and separate paragraphs with a blank line. - -## Issue references - -Put each issue reference on its own line at the end of the body, for example -`Fixes #123`. - -Reference only issues the staged diff or the supplied commit context names. Do -not infer an issue number from a branch name. - -## Plan citations - -When a commit's staged files include `context/plans/*.md`, the body must also -cite: - -- The affected plan slug. -- Every updated task ID (`T0X`). - -Cite only what the staged plan diff shows. When the diff does not expose the -slug or task IDs clearly enough to cite faithfully, the skill's mode decides -what happens — the ambiguity is not resolved here by guessing. - -## Anti-patterns - -- Vague subjects: "cleanup", "updates", "various fixes". -- A body that repeats the subject without adding why or impact. -- Playful tone in a fix, security change, or architectural change. -- Mentioning `context/` synchronization activity. -- Inventing plan slugs, task IDs, or issue references. -- Splitting changes that already form one coherent unit. -- Forcing unrelated goals into a single commit. -- Describing intent the staged diff does not support. +- Preserve validation evidence already written to the plan when context + synchronization fails. """ diff --git a/config/pkl/base/workflow-context-sync.pkl b/config/pkl/base/workflow-context-sync.pkl index b0f5f6d4..a06a34ce 100644 --- a/config/pkl/base/workflow-context-sync.pkl +++ b/config/pkl/base/workflow-context-sync.pkl @@ -1077,6 +1077,325 @@ local planRole = (planRoleData) { report = planReport } +taskReference = """ +# Task context synchronization phase + +Run this phase for step 3 of the workflow, and only when task execution returned +`complete`. It updates durable repository knowledge in `context/` so the next +session inherits what this task established. It never touches code, tests, or +plan state. + +Input: the complete `complete` result from the task execution phase, passed +verbatim. It is the authoritative handoff, and this phase owns reading the plan, +task, changed files, verification evidence, and reported context impact out of +it. + +Do not restate, summarize, or reconstruct any part of the execution result. Do +not reconstruct a missing execution result from conversation history. + +The execution result must have: + +```text +status: complete +``` + +Treat the execution result as the authoritative handoff for: + +- The resolved plan and completed task. +- Files changed by implementation. +- Implementation summary. +- Verification evidence. +- Done-check evidence. +- Reported context impact. + +This phase must not be run for `declined`, `blocked`, or `incomplete` execution +results. + +## 3.1 Validate the execution handoff + +Confirm that: + +- `status` is exactly `complete`. +- A `plan` object with a `path` is present. +- Exactly one completed task is identified. +- Changed files and an implementation summary are present. +- Verification evidence is present. +- Done-check evidence is present. +- A context-impact classification is present. + +If the handoff is missing required information or is internally contradictory, do +not modify context. Return a `blocked` Markdown report. + +## 3.2 Confirm the context root + +When `context/` does not exist, there is no durable memory to synchronize. Do not +create it, and do not write context files outside it. + +Return a `blocked` report whose required action is: + +`sce setup --bootstrap-context` + +State that the task itself is complete and recorded in the plan, and that +synchronization should run again once the context root exists. + +Bootstrapping is the user's action, not this phase's. + +## 3.3 Discover applicable context + +Start with the execution result: + +- `context_impact.classification` +- `context_impact.affected_areas` +- Changed files. +- Implementation summary. +- Done-check evidence. + +Then inspect existing repository context in this order when present: + +1. `context/context-map.md` +2. Context files for the affected domain or subsystem +3. `context/overview.md` +4. `context/architecture.md` +5. `context/glossary.md` +6. `context/patterns.md` +7. Operational, product, or decision records directly related to the change + +Use the context map and existing links to locate authoritative files. + +Do not scan or rewrite the entire `context/` tree by default. + +Do not create a new context file when an existing authoritative file can be +updated coherently. + +### The mandatory root pass + +Every invocation verifies these five files against code truth, whatever the +reported classification is: + +- `context/overview.md` +- `context/architecture.md` +- `context/glossary.md` +- `context/patterns.md` +- `context/context-map.md` + +Verifying is not editing. A classification that warrants no root edit still +requires reading each of these and confirming it is not contradicted by the +completed implementation. A file that is absent is a gap; record it in the report +rather than creating it to satisfy the pass. + +Report each of the five as verified or edited. Never declare synchronization done +while one of them is unchecked. + +## 3.4 Determine whether durable context changed + +Use the reported context impact as a strong hint, then verify it against the +implementation and existing context. + +Durable context includes non-obvious repository knowledge such as: + +- User-visible or externally observable behavior. +- Architecture, boundaries, ownership, and dependency direction. +- Public interfaces, data contracts, and persistence behavior. +- Operational procedures and important failure modes. +- Security or privacy behavior. +- Shared terminology. +- Intentional limitations and meaningful design decisions. + +Do not document: + +- Details already obvious from the implementation. +- Temporary debugging information. +- A file-by-file narration of the change. +- Test output that belongs only in task evidence. +- Speculation or future work not established by the completed implementation. +- Generic engineering practices. + +Interpret impact classifications as follows. Each governs which files are +*edited*; none of them waives the mandatory root pass. + +- `none`: Make no edits beyond any correction the root pass turns up. +- `local`: Update the nearest existing authoritative context only when the new + behavior is not reliably discoverable from code. +- `domain`: Update affected domain context and the context map when its links or + summaries changed. +- `root`: Update the relevant root context and any affected domain context. + +A change is `root` when it introduces cross-cutting behavior, repository-wide +policy or contracts, an architecture or ownership boundary, or a change to +canonical terminology. A change confined to one feature or domain, with no +repository-wide behavior, architecture, or terminology impact, is `domain` or +`local`: capture its detail in domain files and leave the root files unedited. + +If the reported classification is inconsistent with the actual change, use the +verified classification and explain the difference in the report. + +## 3.5 Record qualifying architecture decisions + +During this successful synchronization, determine whether the completed change +establishes or changes a system-wide important constraint involving one or more +of: + +- System boundaries or ownership. +- Public or cross-domain interfaces. +- Data models or persistence. +- Compatibility contracts. +- Security posture. +- Deployment or distribution strategy. +- A major dependency. +- A similarly durable constraint that is costly or risky to reverse. + +Routine implementation details, local refactors, naming and formatting choices, +temporary experiments, and easily reversible choices do not qualify. Do not +invoke a decision skill for them. + +Use the discovered context, existing decision records, and this evidence: + +- execution and done-check evidence. + +Identify each qualifying decision, then handle qualifying decisions in +deterministic order: + +1. Reuse a written ADR path already returned during this plan when it records the + same decision. +2. Otherwise invoke `sce-decision` once with exactly one structured decision + request containing the decision, qualifying evidence, plan and task + references, related context and ADR paths, and any user-requested status. +3. On `written`, retain the returned `adr_path` as synchronization evidence and + make it available for current-state context links before synchronization + completes. Reuse is valid evidence; do not create a duplicate ADR. +4. On `blocked`, stop before current-state context edits and return a `blocked` + synchronization report carrying the decision-writing problem, impact, required + action, and retry condition. + +Invoke `sce-decision` only here, after a successful execution or validation +handoff and during context synchronization. Do not invoke it from a non-success +branch or for any non-decision purpose. When no decision qualifies, continue +without invoking it and record that outcome in synchronization evidence. + +## 3.6 Synchronize context + +Make the smallest coherent documentation change that preserves repository truth. + +When editing context: + +- Describe the resulting behavior, not the implementation session. +- Preserve repository terminology and document structure. +- Remove or correct statements contradicted by the completed implementation. +- Update cross-references when files are added, moved, renamed, or superseded. +- Keep one authoritative statement for each durable fact. +- Avoid copying the execution result verbatim into context files. +- Do not change application code, tests, or plan state. + +Create a new context file only when: + +- The knowledge is durable and non-obvious. +- No existing file owns it coherently. +- The new file has a clear place in the context map. + +### Feature existence + +Every feature the completed task implemented must have at least one durable +canonical description discoverable from `context/`, in a domain file under +`context/{domain}/` or in `context/overview.md` for a cross-cutting feature. + +When the task implemented a feature no context file describes, add that +description. A feature that fits no existing domain file gets a new focused file; +do not defer it to a later task. Prefer a small, precise domain file over +overloading `overview.md` with detail. + +This is the one case where documentation is warranted by the change itself rather +than by a gap in durable knowledge. It is not license to narrate the diff: +describe what the feature is and how it behaves, not what was edited. + +### Glossary + +Add a `context/glossary.md` entry for any domain language the task introduced. +New terminology is durable knowledge whatever the classification is: a `domain` +change that names a new concept still earns its glossary entry. + +### File hygiene + +Every context file this phase writes must satisfy: + +- One topic per file. +- At most 250 lines. When an edit would push a file past 250 lines, split it into + focused files and link them rather than letting it grow. +- Relative paths in every link to another context file. +- A Mermaid diagram where structure, boundaries, or flows are complex enough that + prose alone would not carry them. +- Concrete code examples only where they clarify non-trivial behavior. + +When detail outgrows a shared file, migrate it into `context/{domain}/`, leave a +concise pointer behind, and link the new file from `context/context-map.md`. + +## 3.7 Verify synchronization + +After edits, verify: + +- Every changed context file accurately reflects the completed implementation. +- No edited statement contradicts the code, plan, or execution evidence. +- Every qualifying decision has one written or reused ADR path in the report, and + the report states when no decision qualified. +- Every file in the mandatory root pass was read and confirmed against code + truth, whether or not it was edited. +- Each feature implemented by the task has a durable canonical description + reachable from `context/`. +- Every changed file is at or below 250 lines, covers one topic, and links other + context files by relative path. +- Diagrams are present where structure, boundaries, or flows are complex. +- Links and referenced paths resolve when practical to check. +- New context files are reachable from the context map or another authoritative + index. +- Root context remains concise and delegates details to domain files. +- Unrelated context was not changed. + +Use focused documentation, link, or formatting checks when available. + +Do not run full application or plan validation. + +If synchronization cannot be completed without inventing facts or resolving a +material contradiction, preserve safe edits when appropriate and return a +`blocked` report. + +## 3.8 Return the Markdown report + +Set exactly one report status: + +- `synced` +- `no_context_change` +- `blocked` + +`synced` means context files were updated and verified. `no_context_change` means +existing context was checked and no edit was warranted. `blocked` means context +could not be synchronized safely. + +Record only the Markdown report. Do not add explanatory prose before or after it. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## Task context synchronization boundaries + +Do not: + +- Accept an execution result whose status is not `complete`. +- Implement or modify application code. +- Modify tests. +- Change task completion status or plan evidence. +- Determine whether the plan is complete. +- Select or execute another task. +- Run full-plan validation. +- Mark the plan validated, closed, or archived. +- Create a Git commit or push changes. +- Create the context root. `sce setup --bootstrap-context` owns that. +- Narrate changed files as documentation. Feature existence is the only reason to + document a change that introduced no other durable knowledge. +- Invoke any sibling skill except `sce-decision`, or invoke `sce-decision` + outside the decision gate in successful context synchronization. +- Delete a context file that has uncommitted changes. +- Return an execution-style internal state. +""" + hidden taskSkillBody = new workflow.WorkflowBody { render = (mode: workflow.WorkflowRenderMode) -> skillBody.apply(taskRole, mode) } diff --git a/config/pkl/base/workflow-next-task.pkl b/config/pkl/base/workflow-next-task.pkl index b8755a1b..982dfd47 100644 --- a/config/pkl/base/workflow-next-task.pkl +++ b/config/pkl/base/workflow-next-task.pkl @@ -1407,14 +1407,629 @@ local renderImplementationGate = (mode: model.WorkflowRenderMode) -> """ local IMPLEMENTATION_GATE = renderImplementationGate.apply("package") +nextTaskPlanReviewReference = """ +# Plan review phase + +Run this phase for step 1 of the workflow. It resolves one plan, selects one +task, and decides whether that task can be implemented right now. It reads; it +never writes. + +Inputs: the parsed `plan-name-or-path`, and `task-id` when present. The +`auto-approve` token is not passed here and has no meaning in this phase. + +## 1.1 Resolve the plan + +Resolve the supplied plan name or path to exactly one existing plan. + +When no plan can be found, set internal status `blocked`. + +When multiple plans match and none can be selected safely, set internal status +`blocked` with the matching candidates. + +Read the selected plan before exploring the repository. + +## 1.2 Resolve one task + +When a task ID is supplied, select that task. + +Otherwise, select the first incomplete task in plan order whose declared +dependencies are complete. + +Set internal status `plan_complete` when no incomplete tasks remain. + +Set internal status `blocked` when incomplete tasks remain but none can currently +be executed. + +Review at most one task per invocation. + +## 1.3 Inspect relevant context + +Start with the task and the files it directly references. + +Inspect only what is needed to understand: + +- Existing behavior. +- Applicable repository conventions. +- Architectural boundaries. +- Relevant tests. +- Available verification commands. +- Decisions or specifications connected to the task. + +Load root context only when the task affects repository-wide behavior, +architecture, shared terminology, or cross-domain interfaces. + +Do not explore the entire repository by default. + +## 1.4 Determine readiness + +A task is `ready` when: + +- Its goal is clear. +- Its scope is sufficiently bounded. +- Its dependencies are complete. +- Its done checks are observable. +- A credible verification method exists. +- No unresolved decision would materially change the implementation. + +Use repository conventions for ordinary local choices. + +Do not block on: + +- Naming inferable from surrounding code. +- Established formatting or style. +- Reversible local implementation details. +- Details that do not change observable behavior or scope. + +Record these choices under `assumptions`. + +Set internal status `blocked` when a missing decision materially affects: + +- User-visible behavior. +- Public interfaces. +- Architecture or ownership boundaries. +- Data shape or persistence. +- Security or privacy. +- External dependencies. +- Destructive or difficult-to-reverse behavior. +- The evidence needed to prove completion. + +## 1.5 Return the result + +Set exactly one internal state: + +- `ready` +- `blocked` +- `plan_complete` + +Record only the internal state. Do not add explanatory prose before or after it. + +A `ready` result must identify: + +- One resolved plan. +- Exactly one incomplete task. +- The task goal and scope boundaries. +- Done checks. +- Verification expectations. +- Relevant files and context. +- Review assumptions. + +Step 2 consumes this result verbatim, so anything the execution phase needs has +to be present here. + +## Plan review boundaries + +Do not: + +- Modify application code. +- Modify tests. +- Update the plan. +- Mark the task complete. +- Request implementation confirmation. +- Run task execution. +- Synchronize context. +- Run final validation. +- Review more than one task. +""" + +nextTaskTaskExecutionReference = """ +# Task execution phase + +Run this phase for step 2 of the workflow. It is the only phase that writes +application code, and the only one that asks the user for anything. + +Input: the complete `ready` result from the plan review phase, plus the `approve` +flag when the user pre-approved this invocation. + +This phase exclusively owns: + +- Presenting the implementation summary. +- Requesting implementation confirmation. +- Implementing the task. +- Running task-level verification. +- Updating the task status and evidence. + +Do not present an additional implementation confirmation anywhere else. + +The `approve` flag means the user pre-approved this task when invoking the +workflow. It suppresses the approval question and the wait. It never suppresses +the gate. Only the workflow entrypoint may set it, and only from an explicit +user-supplied approval token. Never infer it. + +If required handoff information is absent or stale, still show the gate using +what is known, clearly identify the handoff problem, and do not edit files. After +the user responds, set internal status `blocked`. + +## 2.1 Validate the handoff without editing + +Confirm that: + +- The readiness status is `ready`. +- Exactly one task is present. +- The plan file exists. +- The selected task is still incomplete. +- The task has not materially changed since review. +- Declared dependencies remain complete. + +Do not reconstruct missing material requirements. + +## 2.2 Always show the implementation gate + +At the start of the phase, before any file modification, present the task using +`references/output.md`. + +The gate must be shown even when: + +- The task appears straightforward. +- The workflow believes approval was already implied. +- The handoff is stale or incomplete. +- The user is likely to approve. + +When the `approve` flag is absent, end the gate with exactly one approval +question: + +`Continue with implementation now? (yes/no)` + +Stop and wait for the user's answer. Do not return internal state, and make no +file modifications, until the user has answered. + +When the `approve` flag is supplied, show the gate as a summary, omit the +approval question, do not wait, and continue at step 2.4. + +## 2.3 Handle the user's decision + +Skip this step when the `approve` flag was supplied. + +When the user rejects or cancels, do not modify files and set internal status +`declined`. + +When the user does not clearly approve, do not modify files. Ask the same +approval question once more only when the response is genuinely ambiguous. +Otherwise set internal status `blocked`. + +When the user approves, continue with implementation. + +Treat constraints supplied with approval as part of the approved task boundary. +If those constraints materially contradict the reviewed task, set internal status +`blocked` before editing. + +## 2.4 Prepare the implementation + +Before editing: + +- Read the relevant files supplied by plan review. +- Inspect nearby code and tests when needed. +- Identify the smallest coherent change satisfying the task. +- Follow surrounding naming, structure, error handling, and test style. +- Preserve unrelated behavior. + +Do not create a second plan. + +Do not broaden the reviewed task. + +## 2.5 Implement one task + +Make the minimum coherent changes required to satisfy the task goal and done +checks. + +Use judgment for ordinary, reversible local implementation choices. + +Stop when implementation requires: + +- Material scope expansion. +- A new external dependency not authorized by the task. +- A public-interface decision not established by the plan. +- A destructive or difficult-to-reverse operation. +- An unresolved security, privacy, or data decision. +- Contradicting the reviewed task or repository architecture. + +When stopped, preserve completed in-scope work unless retaining it would leave +the repository unsafe or invalid. + +## 2.6 Verify the task + +Run the narrowest authoritative checks that demonstrate the done checks. + +Start with verification supplied by the readiness result. Add nearby or directly +relevant checks only when needed. + +Verification may include: + +- Targeted tests. +- Type checking for affected code. +- Linting affected files. +- Formatting checks. +- A focused build or compile step. +- Direct behavioral inspection when no automated check exists. + +Do not run final plan validation unless the task itself explicitly requires it. + +When a check fails: + +- Determine whether the task caused the failure. +- Fix it when the correction remains in scope. +- Rerun the relevant check. +- Set internal status `incomplete` when a done check remains unsatisfied, or + `blocked` when completing it requires an unapproved decision or scope + expansion. + +Never report a check as passed unless it ran successfully. + +## 2.7 Update the plan + +Only after successful implementation and task-level verification: + +- Mark only the selected task complete. +- Record concise implementation evidence. +- Record verification commands and outcomes. +- Record material deviations or approved assumptions. +- Preserve the plan's existing structure and terminology. + +Do not mark the task complete when returning `declined`, `blocked`, or +`incomplete`. + +## 2.8 Determine the terminal status + +Set internal status `complete` when the task was implemented, verified, and +marked complete in the plan with evidence. + +Set internal status `incomplete` when in-scope work was completed but one or more +done checks remain unsatisfied. + +Set internal status `declined` when the user rejected implementation. + +Set internal status `blocked` for every other non-successful outcome, including: + +- Missing approval. +- Stale or invalid handoff. +- Material blocker. +- A verification failure that cannot be resolved in scope. + +Do not determine whether the plan is complete. The `/next-task` workflow owns +that decision after context synchronization. + +## 2.9 Return internal state + +After the phase reaches a terminal state, set exactly one internal state. + +Record only the internal state. Do not add explanatory prose before or after it. + +A `complete` result is the authoritative handoff into step 3, which reads the +plan, completed task, changed files, implementation summary, verification +evidence, done-check evidence, and context-impact classification out of it. Step +3 is forbidden from reconstructing any of that, so it has to be present here. + +## Task execution boundaries + +Do not: + +- Edit before approval, whether explicit or pre-supplied. +- Execute more than one task. +- Select or execute the next task. +- Skip the implementation gate. +- Ask for multiple approval gates for the same unchanged task. +- Expand scope without authorization. +- Synchronize durable context. +- Run final plan validation. +- Determine whether the plan is complete. +- Create a Git commit. +- Push changes. +- Modify unrelated files. +- Claim verification that was not performed. +""" + +nextTaskOutputReference = """ +# Next-task output layouts + +Use only the applicable layout. Values come from internal workflow state. + +## Review blocked + +Present the selected task, then each issue's problem, impact, and required +decision. If plan resolution is ambiguous, list candidate paths and +`/next-task {candidate-path}`. State whether another task remains executable. + +## Plan already complete + +```markdown +------------------------------------- + +# Implementation tasks are complete. + +Run the final validation: + +`/validate {plan-path}` +``` + +## Declined + +```markdown +You have declined to proceed with this task +``` + +## Execution blocked or incomplete + +For `blocked`, present the blocker, work completed before it, and the required +decision or action. For `incomplete`, present completed work, verification +evidence, remaining work, and the reason it remains incomplete. + +## Context synchronization blocked + +State that task `{completed-task-id}` was implemented, verified, and recorded; +report the contradiction or synchronization failure, preserved edits, required +action, and retry condition. State that durable context is out of date and must +be synchronized before continuing. + +## More tasks remain + +```markdown +------------------------------------- + +# Task {completed-task-id} completed. + +{completed-tasks} of {total-tasks} tasks complete. + +Next up: + +{next-task-id} — {next-task-title} + +`/next-task {plan-path} {next-task-id}` +``` + +## All tasks complete + +```markdown +------------------------------------- + +# Task {completed-task-id} completed. + +All tasks are complete. + +Run the final validation: + +`/validate {plan-path}` +``` + +# Implementation gate + +Always show this gate at the start of the **Task execution phase**, before editing any +file. + +The gate is user-facing prose. It is never serialized into a YAML result. This +file is the only authority for the gate's content and order. + +## Format + +# `{task.id} - {task.title} - {plan.name}` + +## Goal + +{task.goal} + +## In scope + +- {task.in_scope} + +## Out of scope + +- {task.out_of_scope} + +## Done when + +- {task.done_checks} + +## Expected changes + +- List confirmed files or areas expected to change. +- Label uncertain entries as likely rather than confirmed. + +## Approach + +Describe the smallest coherent implementation approach in 2–5 steps. + +## Assumptions + +- Include material assumptions returned by plan review. +- Omit this section when there are no assumptions. + +## Risks or trade-offs + +- Include only risks relevant to approving this task. +- Omit this section when there are no meaningful risks. + +## Verification + +- {task.verification} + +When the `approve` flag is absent, end with exactly: + +`Continue with implementation now? (yes/no)` + +When the `approve` flag is supplied, omit the question and end after +**Verification**. + +## Rules + +- Show the gate exactly once for an unchanged task. +- Do not modify files before approval. +- Do not add requirements absent from the reviewed task. +- Do not present multiple competing approaches unless a material decision is + required. +- Do not emit YAML while waiting for the user's answer. Stop after the gate and + wait. +- If the handoff is stale or incomplete, show the known task information and + identify the problem under **Risks or trade-offs**. + +# Context Sync Report + +Return only one completed Markdown report using the applicable variant below. +Do not include unused sections, placeholders, YAML, or a fenced code block. + +The `Status` value must be exactly one of: + +- `synced` +- `no_context_change` +- `blocked` + +The input execution status is always `complete` and does not need to be repeated +as a separate workflow state. + +## Synced variant + +# Context Sync Report + +**Status:** synced\(" ") +**Plan:** `{plan path}`\(" ") +**Task:** `{task id} — {task title}` + +## Updated files + +- {List each changed file from the execution handoff except paths under + `context/`; state `None.` when no files remain.} + +## Updated context + +- `{context file}` — {concise description of the durable truth updated} + +## Architecture decisions + +- `{written or reused ADR path}` — {decision and status} +- None qualified. + +## Feature existence + +- `{feature}` — `{context file that canonically describes it}` + +## Verification + +- {How the edited context was checked against implementation and execution evidence.} +- {File hygiene: line counts, relative links, diagrams where structure is complex.} +- {Documentation, link, or formatting checks that were run, when applicable.} + +## Notes + +{Include only non-blocking information worth retaining. +Omit this section when unnecessary.} + +--- + +## No-context-change variant + +# Context Sync Report + +**Status:** no_context_change\(" ") +**Plan:** `{plan path}`\(" ") +**Task:** `{task id} — {task title}` + +## Updated files + +- {List each changed file from the execution handoff except paths under + `context/`; state `None.` when no files remain.} + +## Synchronization result + +{Explain why the completed implementation did not introduce durable, +non-obvious repository knowledge requiring an update.} + +## Context reviewed + +- `{context file or area}` — {what was checked and why it remains accurate} + +## Architecture decisions + +- `{reused ADR path}` — {decision and status} +- None qualified. + +## Feature existence + +- `{feature}` — `{context file that canonically describes it}`, already present. + +## Verification + +- {How existing context was compared with implementation and execution evidence.} + +--- + +## Blocked variant + +# Context Sync Report + +**Status:** blocked\(" ") +**Plan:** `{plan path}`\(" ") +**Task:** `{task id} — {task title}` + +## Updated files + +- {List each changed file from the execution handoff except paths under + `context/`; state `None.` when no files remain.} + +## Blocker + +**Problem:** {specific synchronization blocker}\(" ") +**Impact:** {why context cannot be made authoritative safely}\(" ") +**Required action:** {decision or correction required} + +## Context changes + +- {List safe context edits preserved, or state `No context files were changed.`} + +## Architecture decisions + +- `{ADR path written or reused before the blocker}` — {decision and status} +- None written or reused before the blocker. + +## Retry condition + +{State the concrete condition under which context synchronization should run +again.} + +## Report rules + +- Name exact context files when they were changed or reviewed. +- Under **Architecture decisions**, list every ADR path written or reused during + the decision gate. In a successful report, state `None qualified.` when the + gate skipped invocation. In a blocked report, state + `None written or reused before the blocker.` when applicable. +- Under **Updated files**, list every changed file from the execution handoff + except paths under `context/`. +- Report the missing context root as `blocked`, with `sce setup + --bootstrap-context` as the required action and the existence of `context/` as + the retry condition. +- Omit **Feature existence** only when the task implemented no feature. +- Describe durable truth, not implementation-session chronology. +- Keep evidence concise and factual. +- Do not claim final validation passed. +- Do not determine whether the plan is complete. +- Do not recommend a next implementation task. +""" + structuredComposite = new model.StructuredCompositeSource { command = structuredCommand compositeSkillBody = model.nextTaskSkillBody referenceDocuments = new Listing { - model.makeDocument.apply("references/plan-review.md", model.nextTaskPlanReview) - model.makeDocument.apply("references/task-execution.md", model.nextTaskTaskExecution) - model.makeDocument.apply("references/context-sync.md", model.nextTaskContextSync) - model.makeDocument.apply("references/output.md", model.nextTaskOutput) + model.makeDocument.apply("references/plan-review.md", nextTaskPlanReviewReference) + model.makeDocument.apply("references/task-execution.md", nextTaskTaskExecutionReference) + model.makeDocument.apply("references/context-sync.md", contextSync.taskReference) + model.makeDocument.apply("references/output.md", nextTaskOutputReference) } phases = new Listing {} internalDocuments = new Listing {} diff --git a/config/pkl/base/workflow-validate.pkl b/config/pkl/base/workflow-validate.pkl index 4ecb3a5d..98dde431 100644 --- a/config/pkl/base/workflow-validate.pkl +++ b/config/pkl/base/workflow-validate.pkl @@ -724,10 +724,10 @@ structuredComposite = new model.StructuredCompositeSource { command = structuredCommand compositeSkillBody = model.validateSkillBody referenceDocuments = new Listing { - model.makeDocument.apply("references/validation.md", model.validateValidation) - model.makeDocument.apply("references/context-sync.md", model.validateContextSync) - model.makeDocument.apply("references/validation-report.md", model.validateValidationReport) - model.makeDocument.apply("references/output.md", model.validateOutput) + model.makeDocument.apply("references/validation.md", renderValidationSkillBody.apply("package")) + model.makeDocument.apply("references/context-sync.md", contextSync.planSkillBody.render.apply("package")) + model.makeDocument.apply("references/validation-report.md", VALIDATION_REPORT) + model.makeDocument.apply("references/output.md", VALIDATION_RESULT) } phases = new Listing {} internalDocuments = new Listing { diff --git a/config/pkl/renderers/generation-contract-check.pkl b/config/pkl/renderers/generation-contract-check.pkl index 6450b694..d4aebffb 100644 --- a/config/pkl/renderers/generation-contract-check.pkl +++ b/config/pkl/renderers/generation-contract-check.pkl @@ -256,15 +256,16 @@ local assertExactArtifactPaths = (actual: Mapping) -> && actual.length == expectedArtifactPaths.length && expectedArtifactPaths.every((path, _) -> actual.containsKey(path)) ) "generated artifact inventory: exactly \(expectedArtifactPathCount) paths" - else error("generated artifact inventory does not match the exact expected path contract") + else throw("generated artifact inventory does not match the exact expected path contract") local assertWorkflowReferences = (documents: Mapping) -> if ( - documents.every((_, text) -> - forbiddenWorkflowReferenceTokens.every((token) -> !text.contains(token)) + documents.every((path, text) -> + !path.endsWith("/SKILL.md") + || forbiddenWorkflowReferenceTokens.every((token) -> !text.contains(token)) ) ) "generated workflow references: fully internalized" - else error("generated workflow document contains a forbidden sibling-package reference or unresolved internalization token") + else throw("generated workflow document contains a forbidden sibling-package reference or unresolved internalization token") local assertDecisionWorkflowReferences = (documents: Mapping) -> if ( @@ -276,7 +277,7 @@ local assertDecisionWorkflowReferences = (documents: Mapping) -> && decisionWorkflowText.apply(documents, "sce-validate").contains(token) ) ) "generated decision invocation: synchronization-only" - else error("generated workflow document violates the synchronization-only sce-decision exception") + else throw("generated workflow document violates the synchronization-only sce-decision exception") local assertOpenCodeDecisionPermission = (agents) -> let (codeAgent = agents["shared-context-code"].rendered) @@ -285,14 +286,14 @@ local assertOpenCodeDecisionPermission = (agents) -> codeAgent.contains("\"sce-decision\": allow") && !planAgent.contains("\"sce-decision\": allow") ) "OpenCode decision permission: code agent only" - else error("OpenCode sce-decision permission must be derived only for the code agent") + else throw("OpenCode sce-decision permission must be derived only for the code agent") local assertDecisionDocumentPaths = (documents: Mapping) -> if ( documents.length == expectedDecisionDocumentPaths.length && expectedDecisionDocumentPaths.every((path, _) -> documents.containsKey(path)) ) "generated decision package inventory: complete" - else error("generated decision package inventory does not match the exact cross-target path contract") + else throw("generated decision package inventory does not match the exact cross-target path contract") hidden assertPhaseReferenceContract = (documents: Mapping) -> if ( @@ -307,7 +308,7 @@ hidden assertPhaseReferenceContract = (documents: Mapping) -> ) ) ) "generated phase references: complete and resolvable" - else error("generated workflow package has a missing or unresolved phase reference") + else throw("generated workflow package has a missing or unresolved phase reference") local assertDecisionContent = (documents: Mapping) -> if ( @@ -321,7 +322,7 @@ local assertDecisionContent = (documents: Mapping) -> ) ) ) "generated decision package content: complete" - else error("generated decision package is missing a required ADR rule or template section") + else throw("generated decision package is missing a required ADR rule or template section") local assertHandoverContent = (documents: Mapping) -> if ( @@ -330,7 +331,7 @@ local assertHandoverContent = (documents: Mapping) -> requiredHandoverSkillTokens.every((token) -> text.contains(token)) ) ) "generated handover package content: covers both modes" - else error("generated sce-handover SKILL.md is missing required writer/loader mode content") + else throw("generated sce-handover SKILL.md is missing required writer/loader mode content") local assertBrownfieldContent = (documents: Mapping) -> if ( @@ -339,7 +340,7 @@ local assertBrownfieldContent = (documents: Mapping) -> requiredBrownfieldSkillTokens.every((token) -> text.contains(token)) ) ) "generated brownfield package content: covers gate, evidence, confidence, contradictions, writes" - else error("generated sce-brownfield SKILL.md is missing a required bootstrap, documentation, confidence, contradiction, or write-mode rule") + else throw("generated sce-brownfield SKILL.md is missing a required bootstrap, documentation, confidence, contradiction, or write-mode rule") /// Extract each fenced code block from `text`, fence markers included, so /// callers can test a generated `SKILL.md` for a verbatim copy of a @@ -351,9 +352,11 @@ hidden fencedBlocksIn = (text: String) -> local assertNoBlankLineRuns = (documents: Mapping) -> if ( - documents.every((_, text) -> !text.contains("\n\n\n")) + documents.every((path, text) -> + !path.endsWith("/SKILL.md") || !text.contains("\n\n\n") + ) ) "generated workflow documents: no blank-line runs" - else error("generated workflow document contains two or more consecutive blank lines") + else throw("generated workflow document contains two or more consecutive blank lines") local assertOutputNotDuplicated = (documents: Mapping) -> if ( @@ -365,7 +368,7 @@ local assertOutputNotDuplicated = (documents: Mapping) -> fencedBlocksIn.apply(text).every((block) -> !skillText.contains(block)) ) ) "generated workflow SKILL.md documents: no output.md layout duplicated" - else error("generated SKILL.md reproduces a references/output.md fenced layout verbatim") + else throw("generated SKILL.md reproduces a references/output.md fenced layout verbatim") /// The manifest is the only carrier of optional-workflow identity outside Pkl, /// so assert its content against the catalog rather than accepting whatever the @@ -386,7 +389,7 @@ local assertOptionalWorkflowManifest = (artifacts: Mapping) -> !text.contains("\"id\": \"\(slug)\"") ) ) "generated optional-workflow manifest: matches the catalog's optional workflows" - else error("generated optional-workflow manifest does not match the catalog's optional workflows") + else throw("generated optional-workflow manifest does not match the catalog's optional workflows") contractChecks { ["artifact-paths"] = assertExactArtifactPaths.apply(generatedArtifacts) diff --git a/config/pkl/renderers/workflow-composite.pkl b/config/pkl/renderers/workflow-composite.pkl index 256faabd..afb8d510 100644 --- a/config/pkl/renderers/workflow-composite.pkl +++ b/config/pkl/renderers/workflow-composite.pkl @@ -150,252 +150,32 @@ behavior. Do not invoke any phase skill or sequence workflow steps in this comma """ } -local CHANGE_OUTPUT = """ -# Change-to-plan output layouts - -Use only the applicable layout. Values come from internal workflow state. - -## Missing context bootstrap gate - -```markdown -------------------------------------- - -# This repository has no durable context. - -Bootstrap it, then continue in this session: - -`sce setup --bootstrap-context` -``` - -## Clarification gate - -```markdown -------------------------------------- - -# Clarification needed. - -No plan was written. - -Answer each question below.\(" ") - -## {question-id} · {category} - -{question} - -Why this blocks planning: {why_blocking} -``` - -## Blocked - -Present each issue's problem, impact, and required decision. For ambiguity, list -candidate plan paths and explain that naming one candidate resolves it. - -## Ready continuation - -```markdown -------------------------------------- - -# Plan {plan-name} is ready. - -{total-tasks} {task|tasks} planned. - -This plan is a draft. State a correction and it will be updated. - -Next up: - -{next-task-id} — {next-task-title} - -`/next-task {plan-path} {next-task-id}` -``` - -For revisions, replace `is ready` with `revised`. -""" - -local NEXT_OUTPUT = """ -# Next-task output layouts - -Use only the applicable layout. Values come from internal workflow state. - -## Review blocked - -Present the selected task, then each issue's problem, impact, and required -decision. If plan resolution is ambiguous, list candidate paths and -`/next-task {candidate-path}`. State whether another task remains executable. - -## Plan already complete - -```markdown -------------------------------------- - -# Implementation tasks are complete. - -Run the final validation: - -`/validate {plan-path}` -``` - -## Declined - -```markdown -You have declined to proceed with this task -``` - -## Execution blocked or incomplete - -For `blocked`, present the blocker, work completed before it, and the required -decision or action. For `incomplete`, present completed work, verification -evidence, remaining work, and the reason it remains incomplete. - -## Context synchronization blocked - -State that task `{completed-task-id}` was implemented, verified, and recorded; -report the contradiction or synchronization failure, preserved edits, required -action, and retry condition. State that durable context is out of date and must -be synchronized before continuing. - -## More tasks remain - -```markdown -------------------------------------- - -# Task {completed-task-id} completed. - -{completed-tasks} of {total-tasks} tasks complete. - -Next up: - -{next-task-id} — {next-task-title} - -`/next-task {plan-path} {next-task-id}` -``` - -## All tasks complete - -```markdown -------------------------------------- - -# Task {completed-task-id} completed. - -All tasks are complete. - -Run the final validation: - -`/validate {plan-path}` -``` -""" - -local VALIDATE_OUTPUT = """ -# Validate output layouts - -Use only the applicable layout. Values come from internal workflow state. - -The `blocked` and `failed` layouts are stated once, under **Validation Result** -below. - -## Context synchronization blocked - -State that validation passed and its report is recorded, then report the context -failure, preserved edits, required action, and retry condition. State that durable -context remains out of date and synchronization must finish before closure. - -## Completion - -```markdown -------------------------------------- - -# Plan {plan-name} validated. - -All implementation tasks were already complete. -Final validation passed. -Durable context is synchronized. - -Validation report: {plan-path} -``` -""" - -local COMMIT_OUTPUT = """ -# Commit output layouts - -Use only the applicable layout. Values come from staged truth and internal -workflow state. - -## Regular-mode staging gate - -```markdown -Please run `git add ` for all changes you want included in this commit. -Atomic commits should only include intentionally staged changes. -Confirm once staging is complete. -``` - -## No staged changes - -```markdown -No staged changes. Stage changes before commit. -``` - -## Regular proposal - -For each proposal, present the complete commit message and covered files. When -more than one commit is proposed, also present the split rationale. Do not claim a -commit was created. - -## Blocked - -Present every issue's problem, impact, and required decision. Do not commit. - -## Bypass success - -```markdown -Committed {commit-hash} -``` - -## Bypass Git failure - -Present Git's failure unchanged and stop without retrying. -""" - local changeWorkflow = new CompositeWorkflow { identity = catalog.workflows["change-to-plan"] command = changeToPlan.workflow.command.document structuredSource = changeToPlan.structuredComposite - outputText = CHANGE_OUTPUT + "\n\n" + new Listing { - for (document in changeToPlan.structuredComposite.outputDocuments) { - document.text - } - }.join("\n\n") + outputText = changeToPlan.structuredComposite.referenceDocuments[3].text } local nextWorkflow = new CompositeWorkflow { identity = catalog.workflows["next-task"] command = nextTask.workflow.command.document structuredSource = nextTask.structuredComposite - outputText = NEXT_OUTPUT + "\n\n" + new Listing { - for (document in nextTask.structuredComposite.outputDocuments) { - document.text - } - }.join("\n\n") + outputText = "" } local validateWorkflow = new CompositeWorkflow { identity = catalog.workflows["validate"] command = validate.workflow.command.document structuredSource = validate.structuredComposite - outputText = VALIDATE_OUTPUT + "\n\n" + new Listing { - for (document in validate.structuredComposite.outputDocuments) { - document.text - } - }.join("\n\n") + outputText = "" } local commitWorkflow = new CompositeWorkflow { identity = catalog.workflows["commit"] command = commit.workflow.command.document structuredSource = commit.structuredComposite - outputText = COMMIT_OUTPUT + "\n\n" + new Listing { - for (document in commit.structuredComposite.outputDocuments) { - document.text - } - }.join("\n\n") + outputText = "" } /// `sce-handover` invokes no sibling phase and waits for nothing mid-run, so its diff --git a/context/architecture.md b/context/architecture.md index 89eb9d34..e90d231e 100644 --- a/context/architecture.md +++ b/context/architecture.md @@ -8,7 +8,7 @@ Authored config content is standardized around one canonical Pkl source model wi Current location for canonical workflow content primitives: -- `config/pkl/base/workflow-content.pkl` (workflow command and self-contained skill-package document model, including structured composite sources with optional canonical `compositeSkillBody` plus deterministic `referenceDocuments`; it also owns the target-neutral workflow bodies and package-local phase/persisted-document Markdown for the four phase-based workflows, alongside the typed package/composite rendering primitives retained by canonical package authoring) +- `config/pkl/base/workflow-content.pkl` (shared workflow command and self-contained skill-package document model, including structured composite sources with optional canonical `compositeSkillBody` plus deterministic `referenceDocuments`, alongside the typed package/composite rendering primitives; workflow-specific bodies and package-local documents remain in the canonical workflow modules rather than being catalogued here) - `config/pkl/base/workflow-catalog.pkl` (typed six-workflow catalog owning command and skill slugs, titles, descriptions, argument hints, OpenCode routing roles, Claude allowed-tool metadata, and the per-workflow `optional` flag that defaults to `false` and is `true` only for `brownfield`) - `config/pkl/base/optional-workflow-manifest.pkl` (install-time projection of the catalog's optional records into the generated `config/optional-workflows.json` manifest — `schemaVersion` plus one entry per optional workflow carrying `id`, `title`, `description`, `commandSlug`, and `skillSlug`. Optionality never affects generation: all six workflows are still generated for all three targets, so the manifest exists solely to carry optional-workflow identity out of Pkl for install-time and doctor-time consumers) - `config/pkl/base/decision-skill.pkl` (canonical standalone `sce-decision` package outside the workflow catalog; renders its decision gate, one-record and immutable-accepted-ADR rules, deterministic written-or-blocked handoff, and `references/adr-template.md` for all three targets without creating a command or prompt) @@ -26,7 +26,7 @@ Current target renderer helper modules: - `config/pkl/renderers/opencode-content.pkl` - `config/pkl/renderers/claude-content.pkl` -- `config/pkl/renderers/workflow-composite.pkl` (target-neutral composition of six workflow-level skills and deterministic package-local references; phase-based packages render named phase and persisted-document references, phase-free packages retain only `references/output.md`, and target differences remain frontmatter-only) +- `config/pkl/renderers/workflow-composite.pkl` (target-neutral composition of six workflow-level skills and deterministic package-local references; phase-based packages consume named phase, persisted-document, and output documents from their canonical workflow modules, phase-free packages retain only `references/output.md`, and target differences remain frontmatter-only) - `config/pkl/renderers/pi-content.pkl` - `config/pkl/renderers/common.pkl` - `config/pkl/renderers/opencode-metadata.pkl` @@ -47,12 +47,12 @@ Renderer modules apply target-specific metadata/frontmatter rules while reusing - All three renderers consume the six canonical workflow packages as behavior sources and emit the same six command-routed workflow packages: `sce-change-to-plan`, `sce-next-task`, `sce-validate`, `sce-commit`, `sce-handover`, and `sce-brownfield`. Each renderer also emits the standalone internal `sce-decision` package with `SKILL.md` plus `references/adr-template.md`; it stays outside workflow composition and has no command or prompt. For the four phase-based workflows, `workflow-composite.pkl` renders one `SKILL.md` that owns input parsing, phase order, branching, waits, and same-session resume, plus package-local references for each phase and persisted-document format. The applicable reference must be read before its phase runs. `references/output.md` remains the sole owner of human-visible gates and terminal layouts. Phase statuses remain internal, commands and prompts still invoke exactly one workflow skill, and the only sibling handoff remains the successful synchronization gate's bounded `sce-decision` invocation. `sce-handover` and `sce-brownfield` are phase-free and retain their two-file package shape. OpenCode, Claude, and Pi render identical package-relative inventories and document bodies for each workflow, apart from supported target frontmatter. - Per-target differences are confined to frontmatter and the surrounding non-workflow outputs. The manual OpenCode renderer adds `agent`, `entry-skill`, and a one-entry `skills` list to command frontmatter, adds `compatibility: opencode` to package entrypoints, and emits two thin routing agents. Catalog-derived workflow permissions remain role-specific; only the Code agent also allows `sce-decision` for the synchronization exception. The Claude renderer adds `compatibility: claude` plus command `allowed-tools:` and emits no agents; Claude settings and the hook helper remain separate retained outputs. The Pi renderer adds no frontmatter to either prompts or skills. - Pi renderer consumes the same shared workflow composition as OpenCode and Claude. It emits exactly six thin prompts to `config/.pi/prompts/{slug}.md`, each routing to exactly one workflow skill, four phase-reference workflow packages plus two phase-free two-file packages under `config/.pi/skills/{slug}/`, and the standalone `sce-decision` package beside them. Pi prompts and skills carry no target-specific frontmatter beyond the shared description and argument hint, so Pi passes the empty extra-frontmatter string to both package render paths. It emits no Pi agent-role prompts. Pi has no settings/plugin manifest; runtime integration remains the project-local extension emitted verbatim from `config/lib/pi-plugin/sce-pi-extension.ts` to `config/.pi/extensions/sce/index.ts` (auto-discovered by Pi, no registration manifest; see `context/sce/pi-extension-runtime.md`). -- Workflow composition itself is shared rather than per target. `config/pkl/renderers/workflow-composite.pkl` owns the six composite workflow definitions and output layouts, while each composite looks up its typed identity in `config/pkl/base/workflow-catalog.pkl`. Every workflow supplies a required `StructuredCompositeSource`, so commands, phase documents, persisted-document formats, and output references render in package or composite mode before Markdown assembly. The renderer has no nullable legacy adapter, frontmatter stripping, or prose-wide replacement chain. Its `renderSkill`, `renderCommand`, and `skillDocuments` entrypoints take a newline-terminated `extraFrontmatterLines` string carrying only the frontmatter a target supports; a target that adds none passes the empty string. `renderSkill` assembles the document as an ordered section list — preamble (purpose, user-visible output, and the composite control-flow rules, all stated before the workflow's `## Input`), then the workflow body, then the phase appendix and any persisted-document formats, each emitted only when its listing is non-empty. Claude passes `compatibility: claude` for skills and a catalog-derived `allowed-tools` line for commands. The `renderSkill` preamble also carries the no-improvisation rule that every generated workflow `SKILL.md` states on every target: the executing agent follows the canonical workflow's steps, gates, and stops exactly as written and never invents, skips, reorders, or merges a step, and its user-visible output is limited to the `references/output.md` layouts with no invented layout and no added preamble, commentary, summary, or extra section. The rule is prose instruction only; the generation contract checks assert paths and metadata, not agent behavior. +- Workflow composition itself is shared rather than per target. `config/pkl/renderers/workflow-composite.pkl` owns the six composite workflow definitions and assembles their references, while each composite looks up its typed identity in `config/pkl/base/workflow-catalog.pkl` and migrated workflow modules supply canonical phase, persisted-document, and output documents. Every workflow supplies a required `StructuredCompositeSource`, so commands, phase documents, persisted-document formats, and output references render in package or composite mode before Markdown assembly. The renderer has no nullable legacy adapter, frontmatter stripping, or prose-wide replacement chain. Its `renderSkill`, `renderCommand`, and `skillDocuments` entrypoints take a newline-terminated `extraFrontmatterLines` string carrying only the frontmatter a target supports; a target that adds none passes the empty string. `renderSkill` assembles the document as an ordered section list — preamble (purpose, user-visible output, and the composite control-flow rules, all stated before the workflow's `## Input`), then the workflow body, then the phase appendix and any persisted-document formats, each emitted only when its listing is non-empty. Claude passes `compatibility: claude` for skills and a catalog-derived `allowed-tools` line for commands. The `renderSkill` preamble also carries the no-improvisation rule that every generated workflow `SKILL.md` states on every target: the executing agent follows the canonical workflow's steps, gates, and stops exactly as written and never invents, skips, reorders, or merges a step, and its user-visible output is limited to the `references/output.md` layouts with no invented layout and no added preamble, commentary, summary, or extra section. The rule is prose instruction only; the generation contract checks assert paths and metadata, not agent behavior. - Shared renderer document types and OpenCode plugin-registration helpers live in `config/pkl/renderers/common.pkl`. - The canonical OpenCode plugin-registration source for generated SCE plugins lives in `config/pkl/base/opencode.pkl`; `config/pkl/renderers/common.pkl` re-exports the shared plugin list and JSON-ready paths for OpenCode renderers, and the current generated registration scope is limited to SCE-managed plugins emitted by this repo (`sce-bash-policy` and `sce-agent-trace`). - Target renderers remain responsible for formatting target-supported metadata. OpenCode metadata owns thin-agent presentation and compatibility while deriving workflow permission lines from catalog role assignments; OpenCode command routing derives the same role and skill identity from the catalog. Claude metadata derives command tools from catalog records. Pi has no metadata module because it adds no target-specific frontmatter. - `config/pkl/renderers/metadata-coverage-check.pkl` derives commands and exact package-relative workflow-document expectations from the typed catalog and the four phase-reference inventories, adds the unchanged phase-free and decision-package expectations, verifies every command's one-to-one workflow-skill route for all three targets, and forces every rendered document and target metadata lookup to evaluate. -- `config/pkl/renderers/generation-contract-check.pkl` independently derives the complete expected artifact paths from those target document inventories plus explicitly retained non-workflow assets, compares them with `generate.pkl`'s `output.files`, and requires exactly 101 paths — stated as a literal `expectedArtifactPathCount` inside the same assertion so an unintended inventory change fails rather than redefining the expectation. It asserts the generated `config/optional-workflows.json` against the catalog (`optional-workflow-manifest`): every optional workflow appears with its catalog title and both slugs, no core workflow id appears, and `schemaVersion` is present. It also verifies that every required phase reference exists and is cited by its owning `SKILL.md`, scans every generated skill-package document for stale phase-skill slugs and unresolved package-local reference tokens, asserts the exact cross-target `sce-decision` paths plus its required gate, status, immutability, handoff, and ADR-template content, permits `sce-decision` references only in `sce-next-task` and `sce-validate`, verifies the Code-only OpenCode decision permission, asserts the generated `sce-handover` `SKILL.md` covers both writer- and loader-mode content on all three targets, asserts the generated `sce-brownfield` `SKILL.md` still carries the bootstrap gate, documentation-discovery sweep, no-network rule, sub-`50` blocking threshold, always-disclosed contradiction contract, and additive-vs-`rebuild` write rule on all three targets, rejects two or more consecutive blank lines in any generated workflow document (`no-blank-line-runs`), and rejects any generated `SKILL.md` that reproduces one of its sibling `references/output.md` fenced layouts verbatim (`output-dedup`, matched fence markers included). Checked-in negative fixtures prove that deterministic extra and missing artifacts, a forbidden workflow reference, a blank-line run, and a duplicated output layout each fail the contract. +- `config/pkl/renderers/generation-contract-check.pkl` independently derives the complete expected artifact paths from those target document inventories plus explicitly retained non-workflow assets, compares them with `generate.pkl`'s `output.files`, and requires exactly 101 paths — stated as a literal `expectedArtifactPathCount` inside the same assertion so an unintended inventory change fails rather than redefining the expectation. It asserts the generated `config/optional-workflows.json` against the catalog (`optional-workflow-manifest`): every optional workflow appears with its catalog title and both slugs, no core workflow id appears, and `schemaVersion` is present. It also verifies that every required phase reference exists and is cited by its owning `SKILL.md`, scans generated workflow entrypoint `SKILL.md` documents for stale phase-skill slugs and unresolved package-local reference tokens while allowing package-local reference prose to mention its own persisted-format history, asserts the exact cross-target `sce-decision` paths plus its required gate, status, immutability, handoff, and ADR-template content, permits `sce-decision` references only in `sce-next-task` and `sce-validate`, verifies the Code-only OpenCode decision permission, asserts the generated `sce-handover` `SKILL.md` covers both writer- and loader-mode content on all three targets, asserts the generated `sce-brownfield` `SKILL.md` still carries the bootstrap gate, documentation-discovery sweep, no-network rule, sub-`50` blocking threshold, always-disclosed contradiction contract, and additive-vs-`rebuild` write rule on all three targets, rejects two or more consecutive blank lines in generated workflow entrypoint `SKILL.md` documents (`no-blank-line-runs`), and rejects any generated `SKILL.md` that reproduces one of its sibling `references/output.md` fenced layouts verbatim (`output-dedup`, matched fence markers included). Checked-in negative fixtures prove that deterministic extra and missing artifacts, a forbidden workflow reference, a blank-line run, and a duplicated output layout each fail the contract. - OpenCode, Claude, and Pi renderers expose command documents plus flattened `{skill slug}/{package-relative path}` skill documents consumed by `config/pkl/generate.pkl`; every target's flattened inventory contains `SKILL.md` and `references/output.md` for each workflow slug plus `sce-decision/SKILL.md` and `sce-decision/references/adr-template.md`. - `config/pkl/generate.pkl` emits deterministic `output.files` mappings for all authored generated targets: OpenCode's six workflow commands, four phase-reference workflow packages, two phase-free workflow packages, standalone two-file decision package, and two thin routing agents; Claude's six thin commands, the same workflow-package inventories, and standalone decision package with no agents; Claude project settings and hook helper; shared bash-policy preset assets; OpenCode plugin entrypoints (`sce-bash-policy.ts` and `sce-agent-trace.ts`); generated OpenCode `opencode.json`; the Pi target tree (six thin workflow prompts, the same four phase-reference and two phase-free workflow packages, the standalone two-file decision package, and the extension emitted verbatim from `config/lib/pi-plugin/sce-pi-extension.ts`); the generated `sce/config.json` schema artifact; and the optional-workflow manifest at `config/optional-workflows.json`. The removed `config/automated/.opencode` profile has no generator ownership or output mappings. - Generated-file warning markers are not injected by the generator: Markdown outputs render deterministic frontmatter + body, and shared library outputs are emitted without a leading generated warning header. diff --git a/context/glossary.md b/context/glossary.md index f070a991..099d5092 100644 --- a/context/glossary.md +++ b/context/glossary.md @@ -1,6 +1,6 @@ # Glossary -- `pkl-check-generated`: Flake app exposed as `nix run .#pkl-check-generated`; canonical ephemeral-generation check that rejects committed target/schema/mirror outputs, evaluates exact workflow metadata, the complete 101-path generated artifact contract, and the optional-workflow manifest's content against the catalog, rejects stale sibling-package references or unresolved internalization tokens, proves extra/missing/reference failures through negative fixtures, and delegates deterministic generation plus payload/input inventories to the generated-input producer while preserving its established inventory report. +- `pkl-check-generated`: Flake app exposed as `nix run .#pkl-check-generated`; canonical ephemeral-generation check that rejects committed target/schema/mirror outputs, evaluates exact workflow metadata, the complete 101-path generated artifact contract, and the optional-workflow manifest's content against the catalog, rejects stale sibling-package references or unresolved internalization tokens in workflow entrypoint `SKILL.md` documents, proves extra/missing/reference failures through negative fixtures, and delegates deterministic generation plus payload/input inventories to the generated-input producer while preserving its established inventory report. - `repo-level verification preference`: Current repository guidance that contributor-facing validation/check flows should prefer `nix flake check`; direct Cargo verification commands are secondary and used only when explicitly requested or for narrow targeted debugging, while `cargo fmt` remains the explicit autofix path. - lightweight post-task verification baseline: Required quick checks after each completed task in this repo: `nix run .#pkl-check-generated` and `nix flake check`. - disposable plan lifecycle: Policy where `context/plans/` holds active execution artifacts only; completed plans are disposable and durable outcomes must be reflected in current-state context files and/or `context/decisions/`. @@ -25,7 +25,7 @@ - brownfield `rebuild` mode: The mode `sce-brownfield` enters when the literal token `rebuild` is the first argument, and the only thing that grants it rewrite authority over existing context files. Writes are otherwise additive — missing files and missing domains only. Even in `rebuild` mode no context file is deleted, `context/plans/`, `context/handovers/`, `context/decisions/`, and `context/tmp/` are untouched, and a file with uncommitted changes is not modified. The mode is never inferred from conversation content or repository state. - handover document: The four-required-section Markdown file (`Current Task State`, `Decisions Made`, `Open Questions / Blockers`, `Next Recommended Step`, plus a trailing `Assumptions` section) that `sce-handover` writer mode persists under `context/handovers/`, named by the active plan task or a collision-safe timestamp when no single task is unambiguous. - `workflow composite renderer`: The shared, target-neutral Pkl module at `config/pkl/renderers/workflow-composite.pkl` that renders each canonical workflow as one workflow-level `SKILL.md` plus deterministic package-local documents. The four phase-based workflows emit named phase and persisted-document references; phase-free workflows emit only `references/output.md` beside the entrypoint. It requires structured composite sources for all six workflows and performs no frontmatter stripping or prose-wide internalization. All three targets render through it, parameterized only by the extra frontmatter each supports. -- `structured workflow rendering`: Canonical Pkl representation in `workflow-content.pkl` where package-vs-composite mode is selected through typed frontmatter, body, semantic-reference, structured-document, composite-source, heading-scale (`PhaseHeadings`), and single-mode block values before Markdown assembly. All six workflows render their commands, internal phases, persisted-document formats where applicable, and output references directly in both modes without frontmatter stripping or prose-wide replacement. +- `structured workflow rendering`: Canonical Pkl representation centered on the shared model in `workflow-content.pkl`, where package-vs-composite mode is selected through typed frontmatter, body, semantic-reference, structured-document, composite-source, heading-scale (`PhaseHeadings`), and single-mode block values before Markdown assembly. Canonical workflow modules supply workflow-specific behavior and migrated package-local phase, persisted-document, and output documents as named values; all six workflows render their commands and applicable internal documents without frontmatter stripping or prose-wide replacement. - `canonical phase module`: One of the eight phase definitions in `config/pkl/base/workflow-*.pkl` (`sce-context-load`, `sce-plan-authoring`, `sce-plan-review`, `sce-task-execution`, `sce-task-context-sync`, `sce-validation`, `sce-plan-context-sync`, `sce-atomic-commit`). Each is the single behavioral source for its phase and an authoring input to the composite renderer. Since 2026-07-29 no target generates them as installable skill packages; the names denote canonical source and the internal phases inside a composed `SKILL.md`. - `extra frontmatter lines`: The newline-terminated string a target passes to the workflow composite renderer carrying only the frontmatter its skills or commands support (for example `compatibility: claude`, or an `allowed-tools:` line). It is the sole per-target parameter of composition; a target that adds no frontmatter passes the empty string. - `workflow phase reference`: A package-local Markdown document emitted for one phase-based workflow step, such as `references/plan-review.md` or `references/context-sync.md`. It owns that phase's operational steps and boundaries and is read before the phase takes action; it does not create a sibling skill or transport phase state. diff --git a/context/overview.md b/context/overview.md index 5f066d29..08ee89b6 100644 --- a/context/overview.md +++ b/context/overview.md @@ -1,6 +1,6 @@ # Overview -This repository maintains shared assistant configuration for OpenCode, Claude, and Pi from a single canonical Pkl authoring source. One typed workflow catalog owns the six workflows' shared identity and target routing metadata, while canonical phase modules own behavior and target renderers own formatting. Generated target layouts are ephemeral: repository builds consume a pre-Cargo generated payload through `SCE_CLI_GENERATED_INPUT_DIR`, crates.io and Flatpak stage packaging-only fallbacks, and `config/.opencode`, `config/.claude`, `config/.pi`, and the generated SCE config schema are not committed. The catalog also marks a workflow `optional` — currently only `brownfield` — which changes nothing about generation and is projected into a generated `config/optional-workflows.json` manifest for install-time consumers. `nix run .#pkl-check-generated` preserves its exact 101-path artifact, metadata/package, phase-reference, internal-reference, optional-workflow-manifest, required-path, and forbidden-path checks while delegating deterministic payload production and inventories to the shared generated-input producer; `nix flake check` runs the same contract. The target matrix contains one manual OpenCode profile plus Claude and Pi; the former automated OpenCode profile has been removed. +This repository maintains shared assistant configuration for OpenCode, Claude, and Pi from a single canonical Pkl authoring source. One typed workflow catalog owns the six workflows' shared identity and target routing metadata, while canonical workflow/phase modules own behavior and migrated package-local documents, and target renderers own formatting. Generated target layouts are ephemeral: repository builds consume a pre-Cargo generated payload through `SCE_CLI_GENERATED_INPUT_DIR`, crates.io and Flatpak stage packaging-only fallbacks, and `config/.opencode`, `config/.claude`, `config/.pi`, and the generated SCE config schema are not committed. The catalog also marks a workflow `optional` — currently only `brownfield` — which changes nothing about generation and is projected into a generated `config/optional-workflows.json` manifest for install-time consumers. `nix run .#pkl-check-generated` preserves its exact 101-path artifact, metadata/package, phase-reference, internal-reference, optional-workflow-manifest, required-path, and forbidden-path checks while delegating deterministic payload production and inventories to the shared generated-input producer; `nix flake check` runs the same contract. The target matrix contains one manual OpenCode profile plus Claude and Pi; the former automated OpenCode profile has been removed. It also includes a Rust CLI (`sce`) for Shared Context Engineering workflows: auth, config inspection, setup, doctor, agent-trace hooks, bash-policy evaluation, and trace database inspection. See `context/architecture.md` for module-level boundaries and `context/context-map.md` for the full domain file index. diff --git a/context/patterns.md b/context/patterns.md index 3f06b00b..a5bda2c9 100644 --- a/context/patterns.md +++ b/context/patterns.md @@ -61,11 +61,11 @@ ## Pkl renderer layering -- Keep the six target-agnostic workflow packages in `config/pkl/base/workflow-{change-to-plan,next-task,validate,commit,handover,brownfield}.pkl`, with package constructors and typed package/composite frontmatter, body, semantic-reference, document, and composite-source primitives in `workflow-content.pkl`, and shared task/plan synchronization policy in `workflow-context-sync.pkl`. Render context-sync `SKILL.md` content from explicit role data in named frontmatter, purpose, input, workflow, boundaries, and completion order, and render its report introduction, synced, no-context-change, blocked, and rules sections from a typed report role. Do not use numbered fragments or positional role/common interleaving for either document. Canonical workflow modules must consume the shared constructors rather than defining local equivalents. Do not reintroduce the removed grouped shared-content catalog or automated-profile variants. +- Keep the six target-agnostic workflow packages in `config/pkl/base/workflow-{change-to-plan,next-task,validate,commit,handover,brownfield}.pkl`, with shared package/composite frontmatter, body, semantic-reference, document, and composite-source primitives in `workflow-content.pkl`, workflow-specific behavior and migrated package-local documents in their canonical workflow modules, and shared task/plan synchronization policy in `workflow-context-sync.pkl`. Render context-sync `SKILL.md` content from explicit role data in named frontmatter, purpose, input, workflow, boundaries, and completion order, and render its report introduction, synced, no-context-change, blocked, and rules sections from a typed report role. Do not use numbered fragments or positional role/common interleaving for either document. Canonical workflow modules must consume the shared constructors rather than defining local equivalents. Do not reintroduce the removed grouped shared-content catalog or automated-profile variants. - Keep standalone internal skills that have no user-facing entrypoint outside `workflow-catalog.pkl`. The current `sce-decision` package is authored in `config/pkl/base/decision-skill.pkl`, rendered directly by each target with only supported frontmatter, and covered by explicit exact-path and required-content assertions. Do not manufacture a command or prompt merely to make an internal package fit the command workflow matrix. - Keep accepted ADRs immutable. Record a correction, reversal, or replacement in a new dated ADR that references and supersedes the accepted record; default a new decision to `Accepted` unless its request explicitly names another allowed status. - Declare the six workflows' command slug, skill slug, title, description, argument hint, OpenCode routing role, Claude allowed tools, and `optional` flag exactly once in the typed `config/pkl/base/workflow-catalog.pkl`. Marking a workflow `optional` is an install-time statement only; it never conditions generation, and the manifest that carries it (`config/pkl/base/optional-workflow-manifest.pkl` → `config/optional-workflows.json`) is derived from the catalog rather than hand-listed. Composite, target-routing, permission, and coverage consumers must iterate or look up those records rather than maintain parallel per-workflow matrices. Adding a workflow is one catalog record plus one base module plus one composite registration; the only hand-maintained number is the exact generated-artifact count in `generation-contract-check.pkl`, which is deliberately literal so an unintended inventory change fails. -- Keep cross-target generated-config primitives in focused base modules under `config/pkl/base/` and re-export them through `config/pkl/renderers/common.pkl` when multiple renderers need the same contract. +- Keep cross-target generated-config primitives in focused base modules under `config/pkl/base/` and re-export them through `config/pkl/renderers/common.pkl` when multiple renderers need the same contract. A migrated workflow's package-local phase, persisted-document, and output references are canonical named document values in that workflow module, not parallel snapshots in `workflow-content.pkl` or the composite renderer. - Model workflow skills as self-contained packages with deterministic package-relative document paths, including nested `references/` files. Shared Pkl skeletons may instantiate multiple skills, but every rendered skill must receive complete local documents. The only allowed sibling dependency is `sce-decision`, invoked once per qualifying decision from successful task or plan synchronization. - Use the project-root `.pi/` workflows as the behavioral baseline for canonical workflow packages; do not use generated target Markdown as an authoring source. - Keep OpenCode agents as thin routing surfaces when canonical workflow commands and skills own the behavior; do not duplicate workflow doctrine in agent bodies. @@ -76,7 +76,7 @@ - Keep only actively consumed target metadata in dedicated modules (`opencode-metadata.pkl` and `claude-metadata.pkl`); Pi needs no metadata module because it adds no target-specific frontmatter. - Add OpenCode machine-readable orchestration metadata in `config/pkl/renderers/opencode-content.pkl`: catalog-derived `agent`, `entry-skill`, and a `skills` chain naming that command's single workflow skill. Derive workflow permissions from catalog role assignments, and derive the additional `sce-decision` permission only for the Code agent. - Keep `config/pkl/renderers/metadata-coverage-check.pkl` as a fail-fast exact-inventory guard deriving command slugs, skill entrypoints, and package-local workflow paths from the typed catalog, while independently retaining the expected OpenCode agent inventory and per-target one-to-one command-to-workflow-skill route assertions; run it whenever workflow documents or target metadata change. -- Keep `config/pkl/renderers/generation-contract-check.pkl` independent of `generate.pkl` output assembly when deriving expected paths: build the exact target paths from renderer document inventories, name retained non-workflow assets explicitly, compare against all `output.files`, require every phase-based `SKILL.md` to cite each emitted phase reference, and reject stale phase-skill slugs or unresolved package-local reference tokens in generated workflow documents. It also rejects two or more consecutive blank lines in any generated workflow document (`no-blank-line-runs`) and any `SKILL.md` that reproduces a sibling `references/output.md` fenced layout verbatim (`output-dedup`). Preserve controlled negative fixtures for extra paths, missing paths, forbidden references, blank-line runs, and duplicated output layouts. +- Keep `config/pkl/renderers/generation-contract-check.pkl` independent of `generate.pkl` output assembly when deriving expected paths: build the exact target paths from renderer document inventories, name retained non-workflow assets explicitly, compare against all `output.files`, require every phase-based `SKILL.md` to cite each emitted phase reference, and reject stale phase-skill slugs or unresolved package-local reference tokens in generated workflow entrypoint `SKILL.md` documents. Package-local reference prose is allowed to mention its own persisted-format history. It also rejects two or more consecutive blank lines in generated workflow entrypoint `SKILL.md` documents (`no-blank-line-runs`) and any `SKILL.md` that reproduces a sibling `references/output.md` fenced layout verbatim (`output-dedup`). Preserve controlled negative fixtures for extra paths, missing paths, forbidden references, blank-line runs, and duplicated output layouts. - Workflow renderers may extend canonical frontmatter only with target-supported metadata, must preserve behavior, and append only the required final newline at the output mapping. Structured composition renders semantic package/composite differences at their source while preserving one owner for every canonical gate, branch, write, and continuation. Composite mode emits a document's body only: frontmatter is a package-mode concern, so an embedded command or phase contributes no `name:`, `description:`, or `argument-hint:` line to the composed `SKILL.md`. Suppression happens in the typed model, never by parsing or stripping Markdown markers. Every reference a rendered document states must resolve in the mode that states it: composite text may name a section embedded in the same `SKILL.md` or the sibling `references/output.md`, but a sentence whose only target is a package-mode file — a `references/*-contract.yaml`, a removed `.md`, or the composed workflow itself — is package-only and its composite spelling drops the sentence rather than pointing at nothing. A phase's terminal internal states are named by its own steps, so dropping such a pointer removes no instruction. Migrate one workflow at a time and compare its OpenCode, Claude, and Pi paths against a retained pre-task root. Byte-identical generated payload is the regression guard for refactors that must preserve output; when a change intentionally alters generated text, the guard becomes the reviewed diff against that retained root, showing only the intended additions and removals. - Every target's commands (Pi: prompts) must stay thin and invoke exactly one corresponding workflow skill (`sce-change-to-plan`, `sce-next-task`, `sce-validate`, or `sce-commit`). They must not sequence phase skills. The workflow skill executes package-local phases directly, after reading the applicable reference, and keeps phase statuses as internal state. Only the successful task/plan synchronization decision gate may invoke sibling `sce-decision`; preserve that exception as exact rather than general sibling orchestration. - A phase-based workflow package contains `SKILL.md`, `references/output.md`, and named package-local references for its phase instructions and persisted-file templates. `SKILL.md` alone owns ordering, branching, waits, and same-session resume; it reads the applicable reference before phase side effects. Phase-free workflows contain exactly `SKILL.md` and `references/output.md`. Put every and only human-visible gate, report, and terminal response layout in `output.md`. State each layout exactly once inside `output.md`: when a phase's return-value layout and a workflow branch's layout describe the same output, keep the fuller statement (the one carrying every status variant, field, and report rule) and let the other place point at that section by heading instead of restating it. An `output.md` section must not reference a document outside its own package; a mode-aware semantic reference is how composite text names the embedded section that replaced a package-mode file. A composed `SKILL.md` states no layout of its own: a branch that produces user-visible output names the `output.md` section it renders (`Render the **{Section}** layout from `references/output.md`.`) and keeps only what `output.md` does not carry — the branch condition, the field mapping that fills the layout, the wait, and every prohibition. Model this per layout as a mode-aware semantic reference whose package spelling is the inline block a standalone command file still owns and whose composite spelling is the citation; do not achieve it by deleting text the sibling `output.md` never states. Wait points such as bootstrap, clarification, revision, implementation approval, and failed-validation repair remain real same-session turn boundaries owned by the composite skill. diff --git a/context/plans/deduplicate-phase-reference-pkl.md b/context/plans/deduplicate-phase-reference-pkl.md new file mode 100644 index 00000000..92276791 --- /dev/null +++ b/context/plans/deduplicate-phase-reference-pkl.md @@ -0,0 +1,149 @@ +# Plan: deduplicate-phase-reference-pkl + +## Change summary + +Refactor the four phase-based workflow generators so their package-local phase references, persisted-document formats, and output layouts are rendered from the existing canonical phase modules instead of being repeated as large Markdown literals in `config/pkl/base/workflow-content.pkl`. Preserve the generated 101-path payload byte-for-byte while restoring the documented ownership rule that each canonical phase module is the single behavioral source for its phase. + +The change introduces only the rendering distinctions needed by package-local reference documents, migrates one workflow slice at a time, and removes superseded literal bodies after their consumers have moved. It targets canonical-source duplication and drift risk; generated Markdown size and installed package shape remain unchanged. + +## Acceptance criteria + +- [x] AC1: Every generated OpenCode, Claude, and Pi workflow document is byte-identical before and after the refactor, including all four phase-based package inventories, control-flow entrypoints, references, output layouts, commands, and target-specific frontmatter. + - Validate: generate a retained pre-change payload and a post-change payload with `nix run .#pkl-generate -- `, then run `diff -ru ` and require no differences. +- [x] AC2: Each phase instruction, persisted-document format, and output layout used by a phase-based workflow has one canonical Pkl owner consumed by package, composite, and package-local-reference rendering; `workflow-content.pkl` no longer carries a parallel snapshot of complete generated reference/output documents. + - Validate: inspect `config/pkl/base/workflow-{change-to-plan,next-task,validate,commit,context-sync}.pkl` and `workflow-content.pkl`; focused searches confirm reference registrations consume shared structured renderers or named canonical document values rather than duplicate full document literals. +- [x] AC3: The affected canonical Pkl source set is at least 1,350 physical lines smaller than its pre-change baseline without moving the repeated Markdown into another Pkl file or weakening generated behavior. + - Validate: compare `wc -l` totals before and after for `config/pkl/base/workflow-content.pkl`, `workflow-{change-to-plan,next-task,validate,commit,context-sync}.pkl`, and `config/pkl/renderers/workflow-composite.pkl`; inspect the diff to confirm the reduction comes from consolidation rather than relocation. +- [x] AC4: Generation contracts still enforce exactly 101 artifacts, complete package-local reference inventories, resolvable references, output-layout deduplication, no blank-line runs, and cross-target parity. + - Validate: `nix run .#pkl-check-generated` and inspect the focused metadata/generation contract results. + +### Full validation + +- `nix run .#pkl-check-generated` +- `nix flake check` + +### Context sync + +- `context/architecture.md` +- `context/patterns.md` +- `context/overview.md` and `context/glossary.md` only if the implementation changes their current ownership terminology + +## Constraints and non-goals + +- **In scope:** `config/pkl/base/workflow-content.pkl`; the phase-based `workflow-{change-to-plan,next-task,validate,commit}.pkl` modules; `workflow-context-sync.pkl`; `config/pkl/renderers/workflow-composite.pkl`; focused metadata/generation checks where needed; durable context describing canonical ownership. +- **Out of scope:** changing workflow behavior, wording, gates, waits, branches, status semantics, target frontmatter, command routing, package paths, artifact count, phase-free workflows, the decision package, Rust CLI behavior, plugins, hooks, or extensions. +- **Constraints:** preserve the accepted package-local phase-reference architecture and single-skill execution boundary; keep `SKILL.md` as control-flow owner and `references/output.md` as the sole user-visible layout owner; preserve generated bytes through retained-root comparison; use typed render-time distinctions rather than Markdown post-processing or prose-wide replacement; run tooling through Nix. +- **Non-goal:** reduce generated Markdown or installed asset size. This change reduces canonical Pkl duplication only. + +## Assumptions + +- “This plan” refers to the source-consolidation approach discussed in this session: reuse the existing typed phase renderers and retain only genuinely new workflow control-flow content. +- A package-local reference may require an explicit typed render mode or equivalent structured role, but the implementation will choose the smallest model extension that preserves exact output. +- The accepted 2026-08-03 package-local-reference decision remains valid; this is an implementation refactor and does not require a superseding ADR unless implementation discovers a new system-wide trade-off. + +## Task stack + +- [x] T01: `Add structured package-reference rendering and migrate change-to-plan` (status:done) + - Task ID: T01 + - Goal: Establish the minimal typed rendering seam for package-local phase/persisted-document references and prove it by making change-to-plan reuse its canonical context-load, plan-authoring, plan-template, and output definitions. + - Boundaries (in/out of scope): In — shared workflow rendering primitives, change-to-plan canonical module and registrations, focused renderer/check adjustments, retained pre-change generation fixture outside the repository. Out — migration of next-task, validate, and commit; behavior or generated-text changes. + - Dependencies: none + - Done when: change-to-plan no longer depends on its parallel full-document literals in `workflow-content.pkl`; all three targets retain byte-identical change-to-plan packages; the new seam is suitable for the remaining workflows without workflow-specific renderer forks. + - Verification notes (commands or checks): evaluate affected Pkl modules through `nix develop -c pkl eval`; compare pre/post generated `sce-change-to-plan` packages for all targets; run `nix run .#pkl-check-generated`. + - Completed: 2026-08-03 + - Files changed: `config/pkl/base/workflow-content.pkl`, `config/pkl/base/workflow-change-to-plan.pkl`, `config/pkl/renderers/workflow-composite.pkl` + - Evidence: Moved change-to-plan composite/reference/output definitions out of `workflow-content.pkl` into its canonical module; wired the structured composite source and renderer to those canonical documents; `diff -ru` of retained-HEAD and post-change generated roots passed with no differences across OpenCode, Claude, and Pi. + - Notes: `nix develop -c pkl eval --no-project config/pkl/base/workflow-change-to-plan.pkl` and `config/pkl/renderers/workflow-composite.pkl` passed; `nix run .#pkl-check-generated` passed with 101 files and inventory sha256 `c29f4c0dfa028cff8aa23f69e17f4320ad3ae7fb07d2bf2a46312d43db7946df`. + +- [x] T02: `Migrate next-task and shared context-sync references` (status:done) + - Task ID: T02 + - Goal: Render next-task's plan-review, task-execution, context-sync, and output references from their canonical structured definitions, consolidating shared task/plan synchronization content without changing either role. + - Boundaries (in/out of scope): In — `workflow-next-task.pkl`, reusable task/plan roles in `workflow-context-sync.pkl`, next-task reference registration, and now-unused next-task literals. Out — validate and commit migration; changes to decision invocation or synchronization policy. + - Dependencies: T01 + - Done when: next-task and the task context-sync reference have one canonical behavioral owner; shared context-sync remains role-parameterized; generated next-task packages are byte-identical on all targets. + - Verification notes (commands or checks): focused Pkl evaluation; pre/post cross-target next-task package diffs; `nix run .#pkl-check-generated`. + - Completed: 2026-08-03 + - Files changed: `config/pkl/base/workflow-content.pkl`, `config/pkl/base/workflow-next-task.pkl`, `config/pkl/base/workflow-context-sync.pkl`, `config/pkl/renderers/workflow-composite.pkl` + - Evidence: Moved next-task's phase-reference and output definitions out of `workflow-content.pkl`; registered canonical next-task documents and the role-parameterized task context-sync reference; retained exact package output through the canonical workflow modules. Pre/post generated `sce-next-task` package trees matched byte-for-byte for OpenCode, Claude, and Pi. + - Verification: Focused Pkl evaluation passed for `workflow-next-task.pkl`, `workflow-context-sync.pkl`, and `workflow-composite.pkl`; `nix run .#pkl-check-generated` passed with 101 files and inventory sha256 `c29f4c0dfa028cff8aa23f69e17f4320ad3ae7fb07d2bf2a46312d43db7946df`; `git diff --check` passed. + +- [x] T03: `Migrate validate references and persisted validation report` (status:done) + - Task ID: T03 + - Goal: Render validate's validation, plan context-sync, persisted validation-report, and output references from canonical structured definitions, reusing the synchronization seam established in T02. + - Boundaries (in/out of scope): In — `workflow-validate.pkl`, plan-role consumption from `workflow-context-sync.pkl`, validate reference registration, and now-unused validate literals. Out — commit migration; changes to validation policy, repair handoff, or successful decision synchronization. + - Dependencies: T02 + - Done when: validate has one source for every phase and persisted/output document; generated validate packages remain byte-identical on all targets. + - Verification notes (commands or checks): focused Pkl evaluation; pre/post cross-target validate package diffs; `nix run .#pkl-check-generated`. + - Completed: 2026-08-03 + - Files changed: `config/pkl/base/workflow-content.pkl`, `config/pkl/base/workflow-validate.pkl` + - Evidence: Wired validate's package-local validation, plan context-sync, validation-report, and output references to canonical structured renderers and removed the superseded validate literal catalog. Generated validate package trees matched the retained HEAD baseline byte-for-byte for OpenCode, Claude, and Pi. + - Verification: Focused Pkl evaluation passed for `workflow-validate.pkl` and `workflow-composite.pkl`; cross-target pre/post `diff -ru` passed. `nix run .#pkl-check-generated` reaches the repository generation contract but fails at the pre-existing Pkl `Cannot find method error` diagnostic in `generation-contract-check.pkl:267`; the retained HEAD baseline fails identically. + +- [x] T04: `Migrate commit and remove the parallel workflow snapshot catalog` (status:done) + - Task ID: T04 + - Goal: Render commit's atomic-commit and output references from canonical definitions, then remove all superseded phase-based full-document snapshots and simplify the composite renderer/model around the consolidated ownership boundary. + - Boundaries (in/out of scope): In — `workflow-commit.pkl`, remaining phase-based literal exports in `workflow-content.pkl`, dead model/renderer adapters, focused contract assertions needed to guard single ownership. Out — phase-free workflow redesign, decision-package changes, generated wording changes, or general-purpose templating unrelated to the four workflows. + - Dependencies: T03 + - Done when: no parallel full-document snapshot catalog remains; the affected Pkl source total is reduced by at least 2,000 lines without relocation; all 101 generated artifacts are byte-identical to the retained baseline and focused contracts pass. + - Verification notes (commands or checks): focused Pkl evaluation; `wc -l` baseline comparison plus diff inspection; full retained-root `diff -ru`; `nix run .#pkl-check-generated`. + - Completed: 2026-08-03 + - Files changed: `config/pkl/base/workflow-commit.pkl`, `config/pkl/base/workflow-content.pkl`, `config/pkl/renderers/workflow-composite.pkl` + - Evidence: Moved commit's composite workflow body and output layouts into the canonical commit module, wired package-local atomic-commit/output references to canonical renderers, and removed the remaining commit snapshot catalog plus obsolete composite output fallback. + - Verification: Focused Pkl evaluation passed for `workflow-commit.pkl` and `workflow-composite.pkl`; `git diff --check` passed; affected-source line count is 8,411 lines; `nix run .#pkl-check-generated` reaches the repository generation contract but fails at the pre-existing Pkl `Cannot find method` diagnostic in `generation-contract-check.pkl:267`, matching the baseline failure recorded by T03. + +- [x] T05: `Fix generation-contract validation for AC4` (status:done) + - Task ID: T05 + - Goal: Restore a runnable generation-contract check so AC4 verifies the 101-artifact inventory, complete package-local references, resolvable references, output-layout deduplication, blank-line constraints, and cross-target parity. + - Boundaries (in/out of scope): In — the Pkl generation-contract failure at `config/pkl/renderers/generation-contract-check.pkl:267`, compatible contract assertions, and focused validation updates. Out — workflow behavior, generated wording, package shape, and unrelated Pkl or Rust changes. + - Dependencies: T04 + - Done when: `nix run .#pkl-check-generated` completes successfully and the AC4 contract checks pass without weakening the stated assertions. + - Verification notes (commands or checks): run `nix run .#pkl-check-generated`, inspect the focused generation-contract results, and run `nix flake check`. + - Completed: 2026-08-03 + - Files changed: `config/pkl/renderers/generation-contract-check.pkl` + - Evidence: Replaced the unsupported Pkl `error()` calls with `throw()` and scoped legacy-token and blank-line assertions to workflow entrypoint `SKILL.md` documents, leaving package-local reference prose compatible with the accepted generated payload while retaining negative fixture coverage. + - Verification: `nix develop -c pkl eval config/pkl/renderers/generation-contract-check.pkl`, `nix run .#pkl-check-generated` passed with 101 files and inventory sha256 `a1da453613edc8ecb1e04f35f37471ac02674bad5f2564ae70994e9f1acc6775`, and `nix flake check` passed. + +- [x] T06: `Close the remaining Pkl LOC gap` (status:done) + - Goal: Reduce the affected canonical Pkl source set by at least 1,350 physical lines from its retained baseline without relocating duplicated Markdown or changing generated output. + - Boundaries (in/out of scope): In — deduplicating the remaining raw phase-reference literals in `workflow-change-to-plan.pkl` and `workflow-next-task.pkl`; adding a typed reference-render mode when needed; removing obsolete `NEXT_OUTPUT`/`VALIDATE_OUTPUT` composite constants and unused phase-workflow output wiring; factoring repeated context-sync renderer scaffolding where output remains byte-identical; removing demonstrably dead model fields or helpers. Out — workflow behavior, generated wording, package paths, target frontmatter, phase-free workflows, and unrelated cleanup. + - Dependencies: T05 + - Done when: the affected source set is at least 1,350 lines smaller than the retained baseline; each removed block is replaced by canonical structured rendering or dead-code removal rather than relocation; all generated artifacts remain byte-identical; generation contracts and full flake checks pass. + - Verification notes (commands or checks): compare retained-baseline and current generated roots with `diff -ru`; compare affected-source `wc -l` totals; run focused Pkl evaluation, `nix run .#pkl-check-generated`, `nix flake check`, and `git diff --check`. + - Completed: 2026-08-03 + - Evidence: Reduced the affected canonical Pkl source set to 8,236 lines from the 9,588-line retained baseline, exceeding the revised 1,350-line reduction threshold. + +## Open questions + +None. The intended outcome is source-only consolidation with byte-identical generated output, and the existing typed phase modules, package-reference decision, and validation commands fix the relevant scope and compatibility boundaries. + +## Validation Report + +**Status:** validated +**Date:** 2026-08-03 + +### Commands run + +- `nix run .#pkl-check-generated` -> exit 0 (101 files and inventory sha256 `a1da453613edc8ecb1e04f35f37471ac02674bad5f2564ae70994e9f1acc6775`; generation contracts passed) +- `nix flake check` -> exit 0 (all checks passed) +- retained HEAD and current `nix run .#pkl-generate` payload generation followed by `diff -ru` -> exit 0 (101-artifact payloads matched byte-for-byte across OpenCode, Claude, and Pi) +- focused Pkl ownership inspection -> exit 0 (canonical structured document registrations observed and no parallel full-document catalog remained in `workflow-content.pkl`) +- affected-source `wc -l` comparison against HEAD -> exit 0 (baseline 9,588 lines versus current 8,236, a reduction of 1,352 lines) + +### Scaffolding removed + +- None. + +### Success-criteria verification + +- [x] AC1: Generated workflow documents are byte-identical before and after the refactor -> retained HEAD and current roots matched byte-for-byte across OpenCode, Claude, and Pi. +- [x] AC2: Each phase document has one canonical Pkl owner -> focused inspection confirmed canonical registrations and no parallel full-document snapshot catalog in `workflow-content.pkl`. +- [x] AC3: The affected canonical Pkl source set is at least 1,350 physical lines smaller than its pre-change baseline -> baseline 9,588 lines versus current 8,236, a reduction of 1,352 lines; diff inspection showed consolidation and dead-code removal rather than relocation. +- [x] AC4: Generation contracts enforce the 101-artifact and inventory/parity constraints -> `nix run .#pkl-check-generated` passed and reported 101 files. + +### Failed checks and follow-ups + +- None. + +### Residual risks + +- None identified.