From 863c7fac120b3483f8f748432ae1687329a36373 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Thu, 3 Sep 2026 13:32:02 -0400 Subject: [PATCH 01/17] refactor(bugfix): demand-load phase routing Split explicit phase dispatch and completion guidance from the bugfix controller so commands avoid loading unrelated workflow context. Assisted-by: Codex --- .coderabbit.yaml | 52 +++++++++++----- AGENTS.md | 12 ++-- CONTRIBUTING.md | 35 +++++++---- _shared/recipes/phase-override-resolution.md | 9 ++- bugfix/README.md | 19 +++++- bugfix/SKILL.md | 2 +- bugfix/commands/assess.md | 4 +- bugfix/commands/diagnose.md | 4 +- bugfix/commands/document.md | 4 +- bugfix/commands/feedback.md | 2 +- bugfix/commands/fix.md | 4 +- bugfix/commands/pr.md | 4 +- bugfix/commands/reproduce.md | 4 +- bugfix/commands/review.md | 4 +- bugfix/commands/start.md | 4 +- bugfix/commands/test.md | 4 +- bugfix/skills/assess.md | 4 +- bugfix/skills/completion.md | 36 +++++++++++ bugfix/skills/controller.md | 63 +++----------------- bugfix/skills/diagnose.md | 3 +- bugfix/skills/dispatch.md | 15 +++++ bugfix/skills/document.md | 2 +- bugfix/skills/feedback.md | 2 +- bugfix/skills/fix.md | 2 +- bugfix/skills/pr.md | 2 +- bugfix/skills/reproduce.md | 2 +- bugfix/skills/review.md | 2 +- bugfix/skills/start.md | 4 +- bugfix/skills/test.md | 2 +- bugfix/skills/unattended.md | 5 +- code-review/SKILL.md | 2 +- cve-fix/SKILL.md | 2 +- design/SKILL.md | 2 +- docs-writer/SKILL.md | 2 +- e2e/SKILL.md | 2 +- implement/SKILL.md | 2 +- kcs/SKILL.md | 2 +- prd/SKILL.md | 2 +- sizing/SKILL.md | 2 +- 39 files changed, 194 insertions(+), 135 deletions(-) create mode 100644 bugfix/skills/completion.md create mode 100644 bugfix/skills/dispatch.md diff --git a/.coderabbit.yaml b/.coderabbit.yaml index b5ec2673..5a3b2bb4 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -61,8 +61,9 @@ reviews: - label: "workflow-structure" instructions: >- Apply when the PR changes SKILL.md, guidelines.md, controller.md, - or adds/removes/renames files in skills/ or commands/ directories. - Structural changes affect how AI agents discover and execute workflows. + dispatch.md, completion.md, or adds/removes/renames files in skills/ + or commands/ directories. Structural changes affect how AI agents + discover and execute workflows. - label: "new-workflow" instructions: >- @@ -153,15 +154,21 @@ reviews: step-by-step instructions or decision logic - Must include $ARGUMENTS placeholder to pass user context - Path references must be relative to the command file's location: - use ../skills/controller.md or ../SKILL.md, not absolute paths - and not skills/controller.md (missing ../ prefix) - - Every command must have a corresponding skill file it routes to + use ../skills/controller.md, ../skills/dispatch.md, ../SKILL.md, + or a direct phase-skill path; do not use absolute paths or omit + the required ../ prefix + - Every command must route to its corresponding phase, either through + a direct file reference or an explicit phase parameter passed to a + dispatcher (for example, PHASE=assess) - No IDE-specific syntax - # ── Phase skill files ─────────────────────────────────────── + # ── Workflow skill files ──────────────────────────────────── - path: "*/skills/*.md" instructions: | - Phase skill review (ai-workflows conventions): + Workflow skill review (ai-workflows conventions): + - First classify the file as a phase implementation, controller, + dispatcher, completion guide, or other support file. Apply + phase-specific rules only to phase implementations. - Maximum 10 steps per skill invocation — flag if exceeded (cognitive load / context window risk for AI agents) - Main steps must be numbered sequentially: no gaps, no @@ -174,8 +181,17 @@ reviews: - Synthesis tasks (summarization, assessment, verdict) must NOT be buried after heavy per-item processing — they degrade in long contexts - - controller.md must reference sibling skills as phase-name.md - (not skills/phase-name.md) — relative to its own directory + - controller.md, dispatch.md, and completion.md must reference sibling + skill files as file-name.md (not skills/file-name.md) — relative to + their own directory + - A controller may centrally dispatch phases and own transitions, or + limit itself to discovery and ambiguous-input routing when explicit + commands use a lightweight dispatcher + - A dispatcher must remain a thin router: resolve the requested phase, + preserve override behavior and context, and delegate transition + decisions rather than implementing phase logic + - A completion guide may centralize next-step recommendations so phase + files do not duplicate the workflow transition model - Skills referencing _shared/ resources must use the correct relative path depth (e.g., ../../_shared/recipes/self-review-gate.md from skills/) @@ -699,20 +715,28 @@ reviews: that exist. Flag references to files that don't exist (dangling references). Also flag skill or command files that exist but are never referenced from SKILL.md, controller.md, or any - command file (orphaned files). For skills/* simple skills, require + command file (orphaned files). Treat an explicit dispatcher parameter + such as PHASE=assess as a reference to skills/assess.md when the + dispatcher documents that mapping. Treat files referenced by a + reachable dispatcher or completion guide as reachable. For skills/* + simple skills, require only that supporting resources are reachable from SKILL.md or another reachable reference; do not require workflow-specific files. mode: "warning" - name: "no-content-duplication" instructions: | - When any of SKILL.md, guidelines.md, or controller.md in a - workflow is changed, compare it against whichever of the other - two files are present and check for verbatim duplication of + When any of SKILL.md, guidelines.md, controller.md, dispatch.md, or + completion.md in a workflow is changed, compare it against the other + architectural files that are present and check for duplication of multi-line instruction blocks or paragraphs. Each has a distinct role: SKILL.md is the thin entry point, guidelines.md holds principles/limits/ - safety/quality/escalation, controller.md manages phase dispatch. + safety/quality/escalation. A controller may own centralized phase + routing and transitions; in a demand-loaded design it handles + discovery and ambiguous routing, dispatch.md handles explicit phase + routing, and completion.md may hold the authoritative transition + model. Phase names and brief one-line descriptions appearing in multiple files is EXPECTED (cross-referencing, not duplication) — only flag substantial blocks of identical prose or diff --git a/AGENTS.md b/AGENTS.md index 23970470..2a035646 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,10 +37,12 @@ workflow-name/ guidelines.md # Behavioral rules: principles, hard limits, safety, quality README.md # Human-readable documentation (prerequisites, artifacts, usage) skills/ - controller.md # Optional phase dispatcher + controller.md # Optional discovery and ambiguous-input router + dispatch.md # Optional lightweight explicit-phase dispatcher + completion.md # Optional centralized next-step guidance phase-name.md # Implementation for each phase commands/ - phase-name.md # Thin wrappers that invoke controller or SKILL.md + phase-name.md # Thin wrappers that invoke a controller, dispatcher, SKILL.md, or phase scripts/ # Optional — deterministic operations invoked by skills prompts/ # Optional — prompt templates for sub-agent delegation ``` @@ -69,7 +71,7 @@ guidelines, README, or artifact lifecycle by default. 3. **Relative paths**: All file references must be relative to the file's location (for symlink compatibility) 4. **Phase-based execution**: Most workflows operate through discrete phases with explicit transitions 5. **Shared resources**: Cross-cutting concerns live in `_shared/` and are referenced by relative path from workflows or simple skills -6. **Phase overrides**: Projects can override individual phases by placing a replacement skill file at `.workflows/{workflow}/skills/{phase}.md` in their repo root. The controller checks for this override before falling back to the built-in default. See CONTRIBUTING.md for details. +6. **Phase overrides**: Projects can override individual phases by placing a replacement skill file at `.workflows/{workflow}/skills/{phase}.md` in their repo root. The controller or lightweight dispatcher checks for this override before falling back to the built-in default. See CONTRIBUTING.md for details. ### Shared Resources (`_shared/`) @@ -95,8 +97,8 @@ Recipes are self-contained, parameterized procedures that packages reference via ### File Reference Conventions Critical for symlink resolution: -- `commands/*.md` reference `../skills/controller.md` (if workflow has a controller) or `../SKILL.md` (for workflows without a controller) or `../skills/phase-name.md` (direct phase reference) -- `skills/controller.md` (when present) references sibling skills as `phase-name.md` (not `skills/phase-name.md`) +- `commands/*.md` reference `../skills/controller.md`, `../skills/dispatch.md`, `../SKILL.md`, or `../skills/phase-name.md`; dispatchers identify the target with an explicit phase parameter +- `skills/controller.md`, `skills/dispatch.md`, and `skills/completion.md` reference sibling skills as `phase-name.md` (not `skills/phase-name.md`) - `SKILL.md` references `guidelines.md` and optionally `skills/controller.md` (same directory) - `skills/{skill-name}/SKILL.md` references its resources relative to the simple skill directory (for example, `references/rendering.md`) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a41d13ff..9481c6c2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,10 +37,12 @@ workflow-name/ guidelines.md # Behavioral rules: principles, hard limits, safety, quality, escalation README.md # Human-readable documentation skills/ - controller.md # Optional -- phase dispatch, transitions, next-step recommendations + controller.md # Optional -- workflow routing and orchestration + dispatch.md # Optional -- lightweight explicit-phase dispatch + completion.md # Optional -- centralized next-step recommendations phase-name.md # One file per phase commands/ - phase-name.md # Thin wrappers that invoke the controller or SKILL.md for a specific phase + phase-name.md # Thin wrappers that invoke a router, SKILL.md, or phase Project-level phase overrides (in the consuming repo): @@ -78,12 +80,16 @@ Some workflows use a controller to manage phase execution and transitions. This - List all phases with references to sibling skill files (e.g. `assess.md`, not `skills/assess.md`). - Define how to execute a phase (announce, read, execute, report, wait). -- Provide next-step recommendations after each phase. +- Provide next-step recommendations after each phase, directly or through a + dedicated completion guide. - Never auto-advance -- always wait for the user. ### skills/phase-name.md -Each phase skill contains the detailed steps for that phase. At the end, it should instruct the agent to report findings and re-read the controller for next-step guidance. +Each phase skill contains the detailed steps for that phase. At the end, it +should report findings and follow the workflow's completion contract: either +return to the invoking router, read a completion guide, or re-read the +controller, as defined by that workflow. ### commands/phase-name.md @@ -99,13 +105,18 @@ Dispatch the **phase-name** phase. Context: $ARGUMENTS ``` -The path `../skills/controller.md` is relative to the command file's location inside `commands/`. If the workflow has no controller, commands can reference `../SKILL.md` or the phase skill directly. +The path `../skills/controller.md` is relative to the command file's location +inside `commands/`. The bugfix workflow is the first to use a lightweight +`skills/dispatch.md` that resolves overrides and loads only the requested phase +and a dedicated completion guide. Migrate other workflows separately so each +change can account for its routing and override contracts. If the workflow has +no controller, commands can reference `../SKILL.md` or the phase skill directly. ## Path Conventions All internal file references must be **relative to the file's own location**: -- `commands/*.md` reference the controller as `../skills/controller.md` (or `../SKILL.md` if no controller) +- `commands/*.md` reference `../skills/controller.md`, `../skills/dispatch.md`, `../SKILL.md`, or a phase skill directly - `skills/controller.md` (when present) references sibling skills as `assess.md`, `fix.md`, etc. - `SKILL.md` references `guidelines.md` and optionally `skills/controller.md` (both in the same directory) @@ -115,7 +126,7 @@ This ensures symlinks resolve paths correctly regardless of where the workflow i ## Phase Overrides -Projects can override individual phase skills without forking the workflow. When a controller dispatches a phase, it checks for a project-level override before falling back to the built-in default: +Projects can override individual phase skills without forking the workflow. When a controller or dispatcher routes a phase, it checks for a project-level override before falling back to the built-in default: 1. **`.workflows/{workflow}/skills/{phase}.md`** — project-level override at the repo root 2. **`{phase}.md`** — workflow's built-in default (sibling file in `skills/`) @@ -126,10 +137,12 @@ For example, a team that needs a custom `/sync` phase for the design workflow dr ### Rules for Override Files -- **Start from a copy.** Copy the built-in phase file and modify it rather than writing from scratch. This avoids accidentally omitting contract scaffolding such as artifact paths, exit behavior, or the controller re-read instruction. +- **Start from a copy.** Copy the built-in phase file and modify it rather than writing from scratch. This avoids accidentally omitting contract scaffolding such as artifact paths and exit behavior. - **Full replacement.** An override replaces the entire phase — it is not merged with the built-in. The override file must be self-contained. -- **Same contract.** The override must read the same input artifacts and write the same output artifacts as the built-in phase. Downstream phases and the controller depend on this contract (see the Artifacts table in each controller). -- **Same exit behavior.** End the override file with the same "report findings and re-read the controller" instruction so the controller can recommend next steps. +- **Same contract.** The override must read the same input artifacts and write the same output artifacts as the built-in phase. Downstream phases and the workflow router depend on this contract (see the workflow's Artifacts table). +- **Same exit behavior.** Preserve the built-in phase's completion contract. + Depending on the workflow, that may return to the invoking router, read a + completion guide, or re-read the controller. - **No cross-references to built-in internals.** The override should not reference sibling files in the workflow's `skills/` directory — it lives in the project repo and should be self-contained. ### Version Control @@ -254,7 +267,7 @@ for example `$bugfix assess`. 1. Install locally: `./install.sh cursor` (or `all`). 2. Open a Cursor project and reference the package to verify discovery. -3. For a workflow, run at least one phase and verify controller dispatch. For a +3. For a workflow, run at least one phase and verify its configured routing. For a simple skill, exercise its primary behavior and permission gates. 4. Run every changed script's tests and the same checks configured in CI. 5. Uninstall and reinstall to verify clean teardown: `./uninstall.sh && ./install.sh cursor`. diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index 9e171306..1003086c 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -1,6 +1,6 @@ --- name: phase-override-resolution -version: 0.1.0 +version: 0.1.1 --- # Recipe: Phase Override Resolution @@ -24,8 +24,11 @@ default. Use the first match found: 2. **`{PHASE_FILE}`** — workflow's built-in default (sibling file in `skills/`) If the override file exists but is empty, appears malformed, or does not -contain exit instructions to re-read the controller, warn the user and fall -back to the built-in default. +contain completion or exit guidance, warn the user and fall back to the +built-in default. Valid exit guidance may return control to the invoking +router, read a completion guide, or re-read a controller; require the same +behavioral contract as the workflow's built-in phase rather than one specific +routing architecture. If using a project override, announce it: *"Using project override for /{phase}."* diff --git a/bugfix/README.md b/bugfix/README.md index 2c772a11..e1cd0917 100644 --- a/bugfix/README.md +++ b/bugfix/README.md @@ -37,6 +37,7 @@ bugfix/ │ ├── start.md │ ├── assess.md │ ├── diagnose.md +│ ├── dispatch.md │ ├── document.md │ ├── fix.md │ ├── pr.md @@ -48,6 +49,7 @@ bugfix/ ├── skills/ # Detailed process definitions │ ├── start.md │ ├── assess.md +│ ├── completion.md │ ├── controller.md │ ├── diagnose.md │ ├── document.md @@ -65,11 +67,24 @@ bugfix/ ### How Commands and Skills Work Together -Each **command** is a thin wrapper that invokes a corresponding **skill**. When you run `/diagnose`, the command file tells the agent to read `skills/diagnose.md` and execute it — passing along any arguments you provided plus existing session context. +Each **command** is a thin wrapper that invokes `skills/dispatch.md` with the +requested phase. The dispatcher resolves a project override, loads only that +phase, and passes along the command arguments and session context. It does not +load the full controller for an explicit command. `SKILL.md` routes to commands first: if the user invoked a specific command (e.g. `/unattended`, `/diagnose`), it reads the matching `commands/{command}.md`. Otherwise it falls through to the interactive controller flow. -This separation keeps commands simple and consistent while the skills contain the full process details. +The controller remains available for unqualified requests and legacy project +overrides whose exit guidance explicitly re-reads it. Explicit commands use +`skills/completion.md` as the authoritative next-step model without reloading +the controller after a built-in phase. + +Routing `/feedback` through the dispatcher also gives it the same project-level +phase override support as the other attended commands. + +Bugfix is the first workflow to use this demand-loaded dispatch pattern. Other +workflows continue to use controller-based command routing and can be migrated +in follow-up changes that account for their individual routing contracts. ## Workflow Phases diff --git a/bugfix/SKILL.md b/bugfix/SKILL.md index a1e3c054..20ea747d 100644 --- a/bugfix/SKILL.md +++ b/bugfix/SKILL.md @@ -1,6 +1,6 @@ --- name: bugfix -version: 0.7.0 +version: 0.8.0 description: >- Diagnostic and repair workflow that analyzes error logs, traces root causes, implements fixes, and verifies with regression tests. diff --git a/bugfix/commands/assess.md b/bugfix/commands/assess.md index 88a5637d..be92f3c6 100644 --- a/bugfix/commands/assess.md +++ b/bugfix/commands/assess.md @@ -4,8 +4,8 @@ description: "Analytical bug assessment: error signature, recommendation, source --- # /assess -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=assess`. -Dispatch the **assess** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/diagnose.md b/bugfix/commands/diagnose.md index 813078c4..03eda0d6 100644 --- a/bugfix/commands/diagnose.md +++ b/bugfix/commands/diagnose.md @@ -4,8 +4,8 @@ description: "Identify root cause and impact of a bug" --- # /diagnose -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=diagnose`. -Dispatch the **diagnose** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/document.md b/bugfix/commands/document.md index f17e03f0..60fb2c20 100644 --- a/bugfix/commands/document.md +++ b/bugfix/commands/document.md @@ -4,8 +4,8 @@ description: "Write release notes and documentation for the fix" --- # /document -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=document`. -Dispatch the **document** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/feedback.md b/bugfix/commands/feedback.md index f12e8bfa..374400ff 100644 --- a/bugfix/commands/feedback.md +++ b/bugfix/commands/feedback.md @@ -4,7 +4,7 @@ description: "Address PR review comments on a bug fix" --- # /feedback -Read `../skills/feedback.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=feedback`. Address PR review feedback. Context: diff --git a/bugfix/commands/fix.md b/bugfix/commands/fix.md index 817424f9..f23a0a0f 100644 --- a/bugfix/commands/fix.md +++ b/bugfix/commands/fix.md @@ -4,8 +4,8 @@ description: "Implement the bug fix with minimal diff" --- # /fix -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=fix`. -Dispatch the **fix** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/pr.md b/bugfix/commands/pr.md index 86309ec4..dd68bf61 100644 --- a/bugfix/commands/pr.md +++ b/bugfix/commands/pr.md @@ -4,8 +4,8 @@ description: "Submit a pull request for the bug fix" --- # /pr -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=pr`. -Dispatch the **pr** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/reproduce.md b/bugfix/commands/reproduce.md index d81f3a8a..28590a22 100644 --- a/bugfix/commands/reproduce.md +++ b/bugfix/commands/reproduce.md @@ -4,8 +4,8 @@ description: "Confirm and document bug reproduction steps" --- # /reproduce -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=reproduce`. -Dispatch the **reproduce** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/review.md b/bugfix/commands/review.md index a2a1a5c0..c7a485a8 100644 --- a/bugfix/commands/review.md +++ b/bugfix/commands/review.md @@ -4,8 +4,8 @@ description: "Critically evaluate fix and tests for quality" --- # /review -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=review`. -Dispatch the **review** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/start.md b/bugfix/commands/start.md index 9c6ca632..f12233e9 100644 --- a/bugfix/commands/start.md +++ b/bugfix/commands/start.md @@ -4,8 +4,8 @@ description: "Present available bugfix phases and help choose where to begin" --- # /start -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=start`. -Dispatch the **start** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/commands/test.md b/bugfix/commands/test.md index a91e07ba..d9428bdc 100644 --- a/bugfix/commands/test.md +++ b/bugfix/commands/test.md @@ -4,8 +4,8 @@ description: "Verify the fix and create regression tests" --- # /test -Read `../skills/controller.md` and follow it. +Read `../skills/dispatch.md` and follow it with `PHASE=test`. -Dispatch the **test** phase. Context: +Context: $ARGUMENTS diff --git a/bugfix/skills/assess.md b/bugfix/skills/assess.md index 57726d2e..cfc881c1 100644 --- a/bugfix/skills/assess.md +++ b/bugfix/skills/assess.md @@ -379,5 +379,5 @@ assessment, not pad every section. ## When This Phase Is Done -Report your assessment and state where the artifact was written. Then -**re-read the controller** (`skills/controller.md`) for next-step guidance. +Report your assessment and state where the artifact was written. Then return +to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/completion.md b/bugfix/skills/completion.md new file mode 100644 index 00000000..09f69cb2 --- /dev/null +++ b/bugfix/skills/completion.md @@ -0,0 +1,36 @@ +--- +name: completion +description: Recommend next steps after one attended bugfix phase. +--- + +# Bugfix Phase Completion + +After the completed `PHASE` reports its results, recommend the best next step +for the actual outcome, mention relevant alternatives briefly, and stop for the +user unless the `/start` guidance below applies. + +- **start:** After the user selects a phase, read `dispatch.md` and follow it + with the selected `PHASE`. Their selection is authorization to proceed; do not + require them to enter a slash command. +- **assess:** Usually recommend `/reproduce`. Offer `/fix` when the root cause is + already clear or `/diagnose` when existing evidence makes reproduction + unnecessary. +- **reproduce:** Recommend `/diagnose` when reproduction succeeded or produced + useful evidence. Recommend `/assess` if the problem definition must change. +- **diagnose:** Recommend `/fix` when the root cause is established. Otherwise + offer another `/diagnose` when new evidence supports a revised hypothesis, + `/reproduce` for missing evidence, or `/assess` for an incorrect premise. +- **fix:** Recommend `/test`. Offer `/diagnose` if implementation invalidated the + root-cause analysis. +- **test:** Recommend `/review` after successful validation. Offer `/document` + or `/pr` if review is intentionally skipped; recommend `/fix` for code failures. +- **review:** Recommend `/fix` and then `/test` when blockers remain. Otherwise + recommend `/document`, or `/pr` if separate documentation is unnecessary. +- **document:** Recommend `/pr`; offer `/review` if review has not occurred. +- **pr:** Recommend `/feedback` when review comments arrive; otherwise the + workflow is complete for now. +- **feedback:** Repeat `/feedback` while comments remain; otherwise the workflow + is complete. + +Never auto-advance between attended phases. The only exception is dispatching +the phase the user explicitly selected after `/start`. diff --git a/bugfix/skills/controller.md b/bugfix/skills/controller.md index 1690443e..2b1a20af 100644 --- a/bugfix/skills/controller.md +++ b/bugfix/skills/controller.md @@ -53,61 +53,11 @@ Phases can be skipped or reordered at the user's discretion. WORKFLOW=`bugfix`, PHASE_FILE=`{phase}.md`. 3. **Read** the resolved skill file 4. **Execute** the skill's steps directly — the user should see your progress -5. When the skill is done, it will tell you to report your findings and - re-read this controller. Do that — then use "Recommending Next Steps" - below to offer options. -6. Present the skill's results and your recommendations to the user -7. **Stop and wait** for the user to tell you what to do next. - -## Recommending Next Steps - -After each phase completes, present the user with **options** — not just one -next step. Use the typical flow as a baseline, but adapt to what actually -happened. - -### Typical Flow - -```text -assess → reproduce → diagnose → fix → test → review → document → pr -``` - -### What to Recommend - -After presenting results, consider what just happened, then offer options that make sense: - -**Continuing to the next step** — often the next phase in the flow is the best option - -**Skipping forward** — sometimes phases aren't needed: - -- Assess found an obvious root cause → offer `/fix` alongside `/reproduce` -- The bug is a test coverage gap, not a runtime issue → skip `/reproduce` - and `/diagnose` -- Review says everything is solid → offer `/pr` directly -- PR has been submitted and reviewers have commented → offer `/feedback` -- Feedback round completed and new comments arrived → offer `/feedback` again (repeatable) - -**Going back** — sometimes earlier work needs revision: - -- Test failures → offer `/fix` to rework the implementation -- Review finds the fix is inadequate → offer `/fix` -- Diagnosis was wrong → offer `/diagnose` again with new information - -**Ending early** — not every bug needs the full pipeline: - -- A trivial fix might go straight from `/fix` → `/test` → `/review` → `/pr` -- If the user already has their own PR process, they may stop after `/review` - -### How to Present Options - -Lead with your top recommendation, then list alternatives briefly: - -```text -Recommended next step: /test — verify the fix with regression tests. - -Other options: -- /review — critically evaluate the fix before testing -- /pr — if you've already tested manually and want to submit -``` +5. When the skill returns control for completion guidance, read `completion.md` + and follow the guidance for the completed phase. If a legacy project + override instead tells you to re-read this controller, treat that as the + same return and read `completion.md`. +6. **Stop and wait** for the user to tell you what to do next. ## Starting the Workflow @@ -127,4 +77,5 @@ directly — don't force them through earlier phases. ## Rules - **Never auto-advance.** Always wait for the user between phases. -- **Recommendations come from this file, not from skills.** Skills report findings; this controller decides what to recommend next. +- **Recommendations come from `completion.md`.** Phase skills report findings; + the completion guide provides the authoritative next-step model. diff --git a/bugfix/skills/diagnose.md b/bugfix/skills/diagnose.md index 7a6da977..97a7ac60 100644 --- a/bugfix/skills/diagnose.md +++ b/bugfix/skills/diagnose.md @@ -163,5 +163,4 @@ Report your findings: - Where the root cause analysis was written - Your proposed plan -Then **re-read the controller** (`skills/controller.md`) for next-step guidance. - +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md new file mode 100644 index 00000000..79b285e6 --- /dev/null +++ b/bugfix/skills/dispatch.md @@ -0,0 +1,15 @@ +--- +name: dispatch +description: Resolve and execute one explicitly requested bugfix phase. +--- + +# Bugfix Phase Dispatch + +Given `PHASE`, announce `Starting /{PHASE}.` Then read and follow +`../../_shared/recipes/phase-override-resolution.md` with `WORKFLOW=bugfix` and +`PHASE_FILE={PHASE}.md`. Read and execute the resolved phase file, passing +through the command context unchanged. + +The built-in fallback is the phase file beside this dispatcher. Follow the +phase through its reporting step. When it returns control for completion +guidance, read `completion.md` and follow the guidance for `PHASE`. diff --git a/bugfix/skills/document.md b/bugfix/skills/document.md index 88213bbe..544d17a3 100644 --- a/bugfix/skills/document.md +++ b/bugfix/skills/document.md @@ -177,4 +177,4 @@ Report your results: - Any gaps flagged for later - Your proposed plan -Then **re-read the controller** (`skills/controller.md`) for next-step guidance. +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/feedback.md b/bugfix/skills/feedback.md index bd85f4c2..31fe985f 100644 --- a/bugfix/skills/feedback.md +++ b/bugfix/skills/feedback.md @@ -368,4 +368,4 @@ Report your results as described in Step 7. This phase is repeatable — if new comments arrive or existing responses need another round, run `/feedback` again. -Then **re-read the controller** (`controller.md`) for next-step guidance. +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/fix.md b/bugfix/skills/fix.md index b838d47c..d2d0c0ee 100644 --- a/bugfix/skills/fix.md +++ b/bugfix/skills/fix.md @@ -144,4 +144,4 @@ Report your results: - Where the implementation notes were written - Your proposed plan -Then **re-read the controller** (`skills/controller.md`) for next-step guidance. +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/pr.md b/bugfix/skills/pr.md index 6c5263b9..88981529 100644 --- a/bugfix/skills/pr.md +++ b/bugfix/skills/pr.md @@ -660,4 +660,4 @@ Report your results: - What was included - Any follow-up actions needed (mark ready for review, add reviewers, etc.) -Then **re-read the controller** (`controller.md`) for next-step guidance. +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/reproduce.md b/bugfix/skills/reproduce.md index 7eecb559..bf9cd5be 100644 --- a/bugfix/skills/reproduce.md +++ b/bugfix/skills/reproduce.md @@ -90,4 +90,4 @@ Report your findings: - Where the reproduction report was written - Your proposed plan -Then **re-read the controller** (`skills/controller.md`) for next-step guidance. +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/review.md b/bugfix/skills/review.md index ccdd6160..cf61e183 100644 --- a/bugfix/skills/review.md +++ b/bugfix/skills/review.md @@ -243,4 +243,4 @@ are insufficient, say what's missing. Your verdict and recommendation (from Step 6) serve as the phase summary. Tell the user where the review was written (`.artifacts/bugfix/{issue}/review.md`). -Then **re-read the controller** (`skills/controller.md`) for next-step guidance. +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/start.md b/bugfix/skills/start.md index 57b7f4d5..86dda726 100644 --- a/bugfix/skills/start.md +++ b/bugfix/skills/start.md @@ -88,5 +88,5 @@ and optionally provide additional context (issue URL, description, etc.). ## When This Phase Is Done -After the user selects a phase, **re-read the controller** (`controller.md`) -and dispatch the chosen phase. +After the user selects a phase, return to the invoking workflow router for +completion guidance. diff --git a/bugfix/skills/test.md b/bugfix/skills/test.md index c1512209..b44190ba 100644 --- a/bugfix/skills/test.md +++ b/bugfix/skills/test.md @@ -137,4 +137,4 @@ Report your results: - Where the verification report was written - Your proposed plan -Then **re-read the controller** (`skills/controller.md`) for next-step guidance. +Then return to the invoking workflow router for completion guidance. diff --git a/bugfix/skills/unattended.md b/bugfix/skills/unattended.md index 5d75d053..e157bc81 100644 --- a/bugfix/skills/unattended.md +++ b/bugfix/skills/unattended.md @@ -82,8 +82,9 @@ Run these phases in order. Read each skill from the same `skills/` directory: 1. Announce the phase: *"Starting /fix (unattended mode)."* 2. Read the skill file from the table above. While executing it, apply these overrides: - - "Never auto-advance" / "Stop and wait" / "re-read the controller" / - "Checkpoint: Confirm" sections — ignore; proceed without pausing + - "Never auto-advance" / "Stop and wait" / "return to the invoking workflow + router" / "re-read the controller" / "Checkpoint: Confirm" sections — + ignore; proceed without pausing - "Stop and request human guidance" (escalation) — write an escalation report (see Escalation below) and terminate - "Create Feature Branch" (fix.md Step 2) — skip if `branch` is set or diff --git a/code-review/SKILL.md b/code-review/SKILL.md index 683328ff..80a22955 100644 --- a/code-review/SKILL.md +++ b/code-review/SKILL.md @@ -1,6 +1,6 @@ --- name: code-review -version: 0.4.0 +version: 0.4.1 description: >- AI-driven code review workflow that reviews uncommitted changes using a discoverable reviewer profile, presents findings for human decision, and diff --git a/cve-fix/SKILL.md b/cve-fix/SKILL.md index a3183a01..9d850e56 100644 --- a/cve-fix/SKILL.md +++ b/cve-fix/SKILL.md @@ -1,6 +1,6 @@ --- name: cve-fix -version: 0.4.0 +version: 0.4.1 description: >- Automated CVE remediation that reads vulnerability details from Jira vulnerability tickets, applies multi-strategy dependency fixes, validates diff --git a/design/SKILL.md b/design/SKILL.md index d75938a3..fdc4968f 100644 --- a/design/SKILL.md +++ b/design/SKILL.md @@ -1,6 +1,6 @@ --- name: design -version: 0.9.0 +version: 0.9.1 description: >- Design-and-decompose workflow that takes a PRD, researches the problem space, drafts a technical design document with a requirement-anchored testplan, diff --git a/docs-writer/SKILL.md b/docs-writer/SKILL.md index 69e919be..b4ca9873 100644 --- a/docs-writer/SKILL.md +++ b/docs-writer/SKILL.md @@ -1,6 +1,6 @@ --- name: docs-writer -version: 0.3.0 +version: 0.3.1 description: Documentation workflow that converts requirements into structured AsciiDoc sections, runs Vale for style compliance, and produces merge-ready content. Use when creating or updating AsciiDoc documentation from Jira tickets, GitHub issues, or feature descriptions. --- # Docs Writer Workflow Orchestrator diff --git a/e2e/SKILL.md b/e2e/SKILL.md index 8ee655a1..f097b15c 100644 --- a/e2e/SKILL.md +++ b/e2e/SKILL.md @@ -1,6 +1,6 @@ --- name: e2e -version: 0.6.0 +version: 0.6.1 description: >- Story-to-e2e-test workflow that takes a Jira [QE] Story, discovers the project's e2e testing infrastructure, plans test scenarios, writes e2e diff --git a/implement/SKILL.md b/implement/SKILL.md index d122d10b..3f678a68 100644 --- a/implement/SKILL.md +++ b/implement/SKILL.md @@ -1,6 +1,6 @@ --- name: implement -version: 0.8.0 +version: 0.8.1 description: >- Story-to-code workflow that takes a Jira Story, plans the implementation, writes contract-based tests and production code via TDD, validates against diff --git a/kcs/SKILL.md b/kcs/SKILL.md index fa94f1fd..df81331b 100644 --- a/kcs/SKILL.md +++ b/kcs/SKILL.md @@ -1,6 +1,6 @@ --- name: kcs -version: 0.3.0 +version: 0.3.1 description: >- KCS article workflow that gathers bug context from Jira and user input, drafts a KCS Solution article in markdown, validates it against the KCS diff --git a/prd/SKILL.md b/prd/SKILL.md index b8f1a057..4e23ff38 100644 --- a/prd/SKILL.md +++ b/prd/SKILL.md @@ -1,6 +1,6 @@ --- name: prd -version: 0.9.0 +version: 0.9.1 description: >- Requirements-to-PRD workflow that ingests requirements from Jira, clarifies ambiguities through iterative Q&A, drafts a Product Requirements Document, diff --git a/sizing/SKILL.md b/sizing/SKILL.md index 0fe486e8..804b3193 100644 --- a/sizing/SKILL.md +++ b/sizing/SKILL.md @@ -1,6 +1,6 @@ --- name: sizing -version: 0.3.0 +version: 0.3.1 description: >- Pre-cycle Feature sizing workflow that assesses Features from Jira using T-shirt sizes (XS–XXL), produces per-team effort breakdowns (DEV, QE, UX, UI, DOCS), From f7b11647d655694eb518073b0492f1276f10ed7f Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Thu, 3 Sep 2026 13:51:29 -0400 Subject: [PATCH 02/17] fix(bugfix): centralize dispatch handoffs Delegate controller-selected phases through the dispatcher, normalize every valid override exit through completion guidance, and correct the documented dispatcher location. Assisted-by: Codex --- bugfix/README.md | 2 +- bugfix/skills/controller.md | 15 +++------------ bugfix/skills/dispatch.md | 6 ++++-- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/bugfix/README.md b/bugfix/README.md index e1cd0917..978bfd99 100644 --- a/bugfix/README.md +++ b/bugfix/README.md @@ -37,7 +37,6 @@ bugfix/ │ ├── start.md │ ├── assess.md │ ├── diagnose.md -│ ├── dispatch.md │ ├── document.md │ ├── fix.md │ ├── pr.md @@ -52,6 +51,7 @@ bugfix/ │ ├── completion.md │ ├── controller.md │ ├── diagnose.md +│ ├── dispatch.md │ ├── document.md │ ├── feedback.md │ ├── fix.md diff --git a/bugfix/skills/controller.md b/bugfix/skills/controller.md index 2b1a20af..bf1f9c0f 100644 --- a/bugfix/skills/controller.md +++ b/bugfix/skills/controller.md @@ -46,18 +46,9 @@ Phases can be skipped or reordered at the user's discretion. ## How to Execute a Phase -1. **Announce** the phase to the user before doing anything else, e.g., "Starting the /fix phase." - This is very important so the user knows that the workflow is working and learns about the commands. -2. **Locate** the skill file — read and follow - `../../_shared/recipes/phase-override-resolution.md` with - WORKFLOW=`bugfix`, PHASE_FILE=`{phase}.md`. -3. **Read** the resolved skill file -4. **Execute** the skill's steps directly — the user should see your progress -5. When the skill returns control for completion guidance, read `completion.md` - and follow the guidance for the completed phase. If a legacy project - override instead tells you to re-read this controller, treat that as the - same return and read `completion.md`. -6. **Stop and wait** for the user to tell you what to do next. +Set `PHASE` to the selected phase, then read `dispatch.md` and follow it. The +dispatcher owns phase announcement, override resolution, execution, and +completion routing for both built-in phases and project overrides. ## Starting the Workflow diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md index 79b285e6..e972e420 100644 --- a/bugfix/skills/dispatch.md +++ b/bugfix/skills/dispatch.md @@ -11,5 +11,7 @@ Given `PHASE`, announce `Starting /{PHASE}.` Then read and follow through the command context unchanged. The built-in fallback is the phase file beside this dispatcher. Follow the -phase through its reporting step. When it returns control for completion -guidance, read `completion.md` and follow the guidance for `PHASE`. +phase through its reporting step. Treat any valid phase exit—returning to the +invoking router, requesting completion guidance, or re-reading the +controller—as a return to this dispatcher. Then read `completion.md` and follow +its guidance for `PHASE`. From 0186d55498c8ded71688b74efea5823048552aa7 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Thu, 3 Sep 2026 13:58:50 -0400 Subject: [PATCH 03/17] fix(bugfix): stop dispatch after phase failures Prevent completion routing after override or phase failures and clarify that unattended execution retains its dedicated entry path. Assisted-by: Codex --- bugfix/README.md | 9 +++++---- bugfix/skills/dispatch.md | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/bugfix/README.md b/bugfix/README.md index 978bfd99..14064bdb 100644 --- a/bugfix/README.md +++ b/bugfix/README.md @@ -67,10 +67,11 @@ bugfix/ ### How Commands and Skills Work Together -Each **command** is a thin wrapper that invokes `skills/dispatch.md` with the -requested phase. The dispatcher resolves a project override, loads only that -phase, and passes along the command arguments and session context. It does not -load the full controller for an explicit command. +Each attended phase **command** is a thin wrapper that invokes +`skills/dispatch.md` with the requested phase. The dispatcher resolves a +project override, loads only that phase, and passes along the command arguments +and session context. It does not load the full controller for an explicit +command. `/unattended` continues to use its dedicated unattended flow. `SKILL.md` routes to commands first: if the user invoked a specific command (e.g. `/unattended`, `/diagnose`), it reads the matching `commands/{command}.md`. Otherwise it falls through to the interactive controller flow. diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md index e972e420..28c51405 100644 --- a/bugfix/skills/dispatch.md +++ b/bugfix/skills/dispatch.md @@ -15,3 +15,6 @@ phase through its reporting step. Treat any valid phase exit—returning to the invoking router, requesting completion guidance, or re-reading the controller—as a return to this dispatcher. Then read `completion.md` and follow its guidance for `PHASE`. + +If override resolution or phase execution fails, report the failure and stop +without reading `completion.md`. From a426b0a2def850342abdecaaa9a039309f3f4014 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Thu, 3 Sep 2026 14:39:00 -0400 Subject: [PATCH 04/17] style(sizing): keep entry point under line limit Reflow existing failure guidance without changing behavior so the version-bumped SKILL.md remains strictly under 30 lines. Assisted-by: Codex --- sizing/SKILL.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sizing/SKILL.md b/sizing/SKILL.md index 804b3193..748e4312 100644 --- a/sizing/SKILL.md +++ b/sizing/SKILL.md @@ -23,8 +23,7 @@ description: >- execute the `/ingest` phase in batch mode - Otherwise, ask the user for a Feature key or release identifier -If a step fails or produces unexpected output (e.g., Jira MCP errors, network -failures, invalid issue keys), stop and report the error to the user. Do not -advance to the next phase. Offer to retry the failed step or escalate. +If a step fails or produces unexpected output (e.g., Jira MCP errors, network failures, +invalid issue keys), stop and report the error to the user. Do not advance to the next phase. Offer to retry the failed step or escalate. For principles, hard limits, safety, quality, and escalation rules, see `guidelines.md`. From 03ec2659fcd161808bdf21e3c700131aba1a8598 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Fri, 4 Sep 2026 14:44:10 -0400 Subject: [PATCH 05/17] docs(workflows): generalize dispatcher guidance Describe lightweight dispatch and override announcements without tying the convention to a single workflow. Assisted-by: Codex --- CONTRIBUTING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9481c6c2..21f83dab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -106,11 +106,11 @@ $ARGUMENTS ``` The path `../skills/controller.md` is relative to the command file's location -inside `commands/`. The bugfix workflow is the first to use a lightweight +inside `commands/`. A workflow may instead use a lightweight `skills/dispatch.md` that resolves overrides and loads only the requested phase -and a dedicated completion guide. Migrate other workflows separately so each -change can account for its routing and override contracts. If the workflow has -no controller, commands can reference `../SKILL.md` or the phase skill directly. +and a dedicated completion guide. Migrate workflows separately so each change +can account for its routing and override contracts. If the workflow has no +controller, commands can reference `../SKILL.md` or the phase skill directly. ## Path Conventions @@ -131,7 +131,7 @@ Projects can override individual phase skills without forking the workflow. When 1. **`.workflows/{workflow}/skills/{phase}.md`** — project-level override at the repo root 2. **`{phase}.md`** — workflow's built-in default (sibling file in `skills/`) -For example, a team that needs a custom `/sync` phase for the design workflow drops a file at `.workflows/design/skills/sync.md` in their repo. The controller picks it up automatically and announces the override to the user. +For example, a team that needs a custom `/sync` phase for the design workflow drops a file at `.workflows/design/skills/sync.md` in their repo. The controller or dispatcher picks it up automatically and announces the override to the user. **Filename mapping.** Most workflows map `/phase` to `{phase}.md`, but some use different filenames. For example, docs-writer maps `/gather` to `gather-context.md` and `/plan` to `plan-structure.md`. Check the Phases list in the workflow's controller to find the correct filename for the override. @@ -151,7 +151,7 @@ Commit `.workflows/` to the consuming repo. Overrides are team-level decisions ### Discoverability -When a project uses overrides, document them in the project's `CLAUDE.md` or `AGENTS.md` so newcomers know which phases behave differently from the built-in defaults. The controller announces overrides at runtime, but a static list prevents surprises when reading workflow documentation. +When a project uses overrides, document them in the project's `CLAUDE.md` or `AGENTS.md` so newcomers know which phases behave differently from the built-in defaults. The controller or dispatcher announces overrides at runtime, but a static list prevents surprises when reading workflow documentation. ### Example Project Layout From 8bfe1cae7e7608af5459a8b3375993ce265f7bca Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Fri, 4 Sep 2026 14:56:09 -0400 Subject: [PATCH 06/17] docs(workflows): clarify command-relative routing paths Document dispatcher and direct-phase references relative to command wrappers, and make non-default filename discovery independent of controller presence. Assisted-by: Codex --- CONTRIBUTING.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 21f83dab..e970aaad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -107,10 +107,11 @@ $ARGUMENTS The path `../skills/controller.md` is relative to the command file's location inside `commands/`. A workflow may instead use a lightweight -`skills/dispatch.md` that resolves overrides and loads only the requested phase -and a dedicated completion guide. Migrate workflows separately so each change -can account for its routing and override contracts. If the workflow has no -controller, commands can reference `../SKILL.md` or the phase skill directly. +`../skills/dispatch.md` from its command wrappers to resolve overrides and load +only the requested phase and a dedicated completion guide. Migrate workflows +separately so each change can account for its routing and override contracts. +If the workflow has no controller, commands can reference `../SKILL.md` or +`../skills/{phase}.md` directly. ## Path Conventions @@ -133,7 +134,7 @@ Projects can override individual phase skills without forking the workflow. When For example, a team that needs a custom `/sync` phase for the design workflow drops a file at `.workflows/design/skills/sync.md` in their repo. The controller or dispatcher picks it up automatically and announces the override to the user. -**Filename mapping.** Most workflows map `/phase` to `{phase}.md`, but some use different filenames. For example, docs-writer maps `/gather` to `gather-context.md` and `/plan` to `plan-structure.md`. Check the Phases list in the workflow's controller to find the correct filename for the override. +**Filename mapping.** Most workflows map `/phase` to `{phase}.md`, but some use different filenames. For example, docs-writer maps `/gather` to `gather-context.md` and `/plan` to `plan-structure.md`. Check the workflow's routing documentation—its controller, dispatcher, or documented phase map—to find the correct filename for the override. ### Rules for Override Files From df4e818b177cb73428f44d042ca3ec5e3b94f469 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Fri, 4 Sep 2026 15:13:40 -0400 Subject: [PATCH 07/17] docs(workflows): preserve override routing contract Require every phase route to resolve the documented phase filename through the shared override contract before loading a phase. Assisted-by: Codex --- CONTRIBUTING.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e970aaad..df594f3a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,8 +110,10 @@ inside `commands/`. A workflow may instead use a lightweight `../skills/dispatch.md` from its command wrappers to resolve overrides and load only the requested phase and a dedicated completion guide. Migrate workflows separately so each change can account for its routing and override contracts. -If the workflow has no controller, commands can reference `../SKILL.md` or -`../skills/{phase}.md` directly. +If the workflow has no controller or dispatcher, its command wrapper or +`../SKILL.md` entry point must perform the same override resolution before +reading the resolved phase file. Never bypass override resolution by reading a +phase skill directly. ## Path Conventions @@ -127,14 +129,14 @@ This ensures symlinks resolve paths correctly regardless of where the workflow i ## Phase Overrides -Projects can override individual phase skills without forking the workflow. When a controller or dispatcher routes a phase, it checks for a project-level override before falling back to the built-in default: +Projects can override individual phase skills without forking the workflow. Every phase route—whether invoked through a controller, dispatcher, workflow entry point, or command wrapper—must resolve the phase filename and check for a project-level override before falling back to the built-in default: -1. **`.workflows/{workflow}/skills/{phase}.md`** — project-level override at the repo root -2. **`{phase}.md`** — workflow's built-in default (sibling file in `skills/`) +1. **`.workflows/{workflow}/skills/{phase-file}`** — project-level override at the repo root +2. **`{phase-file}`** — workflow's built-in default (sibling file in `skills/`) -For example, a team that needs a custom `/sync` phase for the design workflow drops a file at `.workflows/design/skills/sync.md` in their repo. The controller or dispatcher picks it up automatically and announces the override to the user. +For example, a team that needs a custom `/sync` phase for the design workflow drops a file at `.workflows/design/skills/sync.md` in their repo. The route resolves that file and announces the override to the user. -**Filename mapping.** Most workflows map `/phase` to `{phase}.md`, but some use different filenames. For example, docs-writer maps `/gather` to `gather-context.md` and `/plan` to `plan-structure.md`. Check the workflow's routing documentation—its controller, dispatcher, or documented phase map—to find the correct filename for the override. +**Filename mapping.** Determine `{phase-file}` once from the workflow's routing documentation—its controller, dispatcher, or documented phase map—and use that same filename for both the project override and built-in fallback. Most workflows map `/phase` to `{phase}.md`, but some use different filenames. For example, docs-writer maps `/gather` to `gather-context.md` and `/plan` to `plan-structure.md`. ### Rules for Override Files @@ -152,7 +154,7 @@ Commit `.workflows/` to the consuming repo. Overrides are team-level decisions ### Discoverability -When a project uses overrides, document them in the project's `CLAUDE.md` or `AGENTS.md` so newcomers know which phases behave differently from the built-in defaults. The controller or dispatcher announces overrides at runtime, but a static list prevents surprises when reading workflow documentation. +When a project uses overrides, document them in the project's `CLAUDE.md` or `AGENTS.md` so newcomers know which phases behave differently from the built-in defaults. The route announces project overrides at runtime, but a static list prevents surprises when reading workflow documentation. ### Example Project Layout From f750c62664b3a31fe75ee1f22d3a811c908d8a63 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Fri, 4 Sep 2026 16:10:40 -0400 Subject: [PATCH 08/17] fix(bugfix): clarify phase terminal outcomes Require detectable terminal exits without imposing one routing architecture across workflows, and distinguish valid failing phase reports from operational failures. Assisted-by: Codex --- _shared/recipes/phase-override-resolution.md | 13 +++++++------ bugfix/skills/dispatch.md | 7 +++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index 1003086c..c50197b1 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -23,12 +23,13 @@ default. Use the first match found: at the repo root 2. **`{PHASE_FILE}`** — workflow's built-in default (sibling file in `skills/`) -If the override file exists but is empty, appears malformed, or does not -contain completion or exit guidance, warn the user and fall back to the -built-in default. Valid exit guidance may return control to the invoking -router, read a completion guide, or re-read a controller; require the same -behavioral contract as the workflow's built-in phase rather than one specific -routing architecture. +If the override file exists but is empty, appears malformed, or does not end +with a detectable terminal instruction, warn the user and fall back to the +built-in default. The terminal instruction must explicitly direct one supported +exit: return control to the invoking router, read a completion guide, or re-read +a controller. The invoking workflow's router determines which supported exits +it accepts or normalizes; preserve the built-in phase's behavioral contract +without requiring one routing architecture for every workflow. If using a project override, announce it: *"Using project override for /{phase}."* diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md index 28c51405..7318e76e 100644 --- a/bugfix/skills/dispatch.md +++ b/bugfix/skills/dispatch.md @@ -16,5 +16,8 @@ invoking router, requesting completion guidance, or re-reading the controller—as a return to this dispatcher. Then read `completion.md` and follow its guidance for `PHASE`. -If override resolution or phase execution fails, report the failure and stop -without reading `completion.md`. +If override resolution fails, an operational error prevents the phase from +completing, or the phase lacks a supported terminal exit, report the failure +and stop without reading `completion.md`. A completed phase report with a +failing verdict is a valid outcome: read `completion.md` so it can provide +recovery guidance. From 23c3d88177b0eef188748594318b36f6834218f7 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Tue, 8 Sep 2026 10:26:52 -0400 Subject: [PATCH 09/17] docs(bugfix): clarify dispatcher fallback contract Assisted-by: Codex --- bugfix/SKILL.md | 2 +- bugfix/skills/dispatch.md | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/bugfix/SKILL.md b/bugfix/SKILL.md index 20ea747d..5a86db93 100644 --- a/bugfix/SKILL.md +++ b/bugfix/SKILL.md @@ -1,6 +1,6 @@ --- name: bugfix -version: 0.8.0 +version: 0.8.1 description: >- Diagnostic and repair workflow that analyzes error logs, traces root causes, implements fixes, and verifies with regression tests. diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md index 7318e76e..c79f68da 100644 --- a/bugfix/skills/dispatch.md +++ b/bugfix/skills/dispatch.md @@ -1,6 +1,6 @@ --- name: dispatch -description: Resolve and execute one explicitly requested bugfix phase. +description: Resolve and execute one requested bugfix phase. --- # Bugfix Phase Dispatch @@ -14,10 +14,11 @@ The built-in fallback is the phase file beside this dispatcher. Follow the phase through its reporting step. Treat any valid phase exit—returning to the invoking router, requesting completion guidance, or re-reading the controller—as a return to this dispatcher. Then read `completion.md` and follow -its guidance for `PHASE`. +its guidance for `PHASE`. Supporting all three exit forms preserves +compatibility with project overrides written for earlier routing contracts. -If override resolution fails, an operational error prevents the phase from -completing, or the phase lacks a supported terminal exit, report the failure -and stop without reading `completion.md`. A completed phase report with a -failing verdict is a valid outcome: read `completion.md` so it can provide -recovery guidance. +After the recipe applies its invalid-override fallback, if no usable phase file +can be resolved, an operational error prevents the phase from completing, or +the phase lacks a supported terminal exit, report the failure and stop without +reading `completion.md`. A completed phase report with a failing verdict is a +valid outcome: read `completion.md` so it can provide recovery guidance. From 2782bddda8412148debe9f39c3b1185d75c1b075 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Tue, 8 Sep 2026 15:12:24 -0400 Subject: [PATCH 10/17] docs(overrides): define phase validation contract Assisted-by: Codex --- CONTRIBUTING.md | 6 +- _shared/recipes/phase-override-resolution.md | 69 +++++++++++++++----- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index df594f3a..af242294 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -145,7 +145,11 @@ For example, a team that needs a custom `/sync` phase for the design workflow dr - **Same contract.** The override must read the same input artifacts and write the same output artifacts as the built-in phase. Downstream phases and the workflow router depend on this contract (see the workflow's Artifacts table). - **Same exit behavior.** Preserve the built-in phase's completion contract. Depending on the workflow, that may return to the invoking router, read a - completion guide, or re-read the controller. + completion guide, or re-read the controller. A dispatcher may normalize these + exits to the same completion destination. Legacy controller returns remain + supported for existing overrides; newly authored phases in dispatcher-based + workflows should return to the invoking router. Controller-based workflows + may continue to use controller returns directly. - **No cross-references to built-in internals.** The override should not reference sibling files in the workflow's `skills/` directory — it lives in the project repo and should be self-contained. ### Version Control diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index c50197b1..c15d5998 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -1,6 +1,6 @@ --- name: phase-override-resolution -version: 0.1.1 +version: 0.2.0 --- # Recipe: Phase Override Resolution @@ -12,24 +12,61 @@ before falling back to the workflow's built-in default. | Parameter | Required | Description | |-----------|----------|-------------| | WORKFLOW | Yes | Workflow name (e.g., `bugfix`, `design`, `docs-writer`) | -| PHASE_FILE | Yes | The filename to resolve — typically `{phase}.md`, but some workflows use different filenames (e.g., docs-writer maps `/gather` to `gather-context.md`). The calling controller supplies the correct value. | +| PHASE_FILE | Yes | The filename to resolve — typically `{phase}.md`, but some workflows use different filenames (e.g., docs-writer maps `/gather` to `gather-context.md`). The caller supplies the mapped filename. | ## Procedure -Check for a project-level override before falling back to the workflow -default. Use the first match found: +1. Locate `.workflows/{WORKFLOW}/skills/{PHASE_FILE}` at the consuming repo + root. The built-in fallback is the same `PHASE_FILE` in the installed + workflow's `skills/` directory, independent of the caller's location. +2. If no override exists, use the built-in phase. Otherwise, read the override + and validate it using the contract below before executing any of its steps. +3. If validation rejects the override, warn with the specific reason and use + the built-in phase. Rejection is recoverable; it is not a resolution failure. +4. If using a project override, announce it: *"Using project override for + /{phase}."* Read and execute the selected file only after resolution. -1. **`.workflows/{WORKFLOW}/skills/{PHASE_FILE}`** — project-level override - at the repo root -2. **`{PHASE_FILE}`** — workflow's built-in default (sibling file in `skills/`) +Resolution fails only when the selected built-in fallback cannot be located, +read, or contains no executable phase instructions. Report that failure and +stop. Do not switch implementations after phase execution has started; report +operational errors through the invoking workflow's error handling. -If the override file exists but is empty, appears malformed, or does not end -with a detectable terminal instruction, warn the user and fall back to the -built-in default. The terminal instruction must explicitly direct one supported -exit: return control to the invoking router, read a completion guide, or re-read -a controller. The invoking workflow's router determines which supported exits -it accepts or normalizes; preserve the built-in phase's behavioral contract -without requiring one routing architecture for every workflow. +## Override Validation -If using a project override, announce it: *"Using project override for -/{phase}."* +Reject an unreadable override or one with no executable instructions. Also +reject unclosed YAML frontmatter or fenced code blocks, unresolved merge +conflict markers, or a missing or unsupported terminal instruction. These are +the malformed-file conditions; do not reject an override for different heading +names, formatting, or additional phase steps alone. + +The terminal instruction is the last executable instruction in the phase's +completion section, or at the end of the file if there is no completion section. +Ignore blank lines, headings, comments, and quoted or fenced examples. Join +wrapped lines and ignore Markdown emphasis, inline-code delimiters, an optional +leading "Then", capitalization, and trailing punctuation when identifying the +following imperative forms: + +| Exit | Accepted instruction forms | +|------|----------------------------| +| Router return | `Return to the invoking router`, `Return to the invoking workflow router`, or `Return control to the invoking router` | +| Completion guide | `Read` or `Re-read` followed by a named completion guide (a filename or Markdown link), or `Read the completion guide` when the router names that guide | +| Controller return | `Re-read the controller`, `Re-read this controller`, or `Re-read` followed by the workflow's controller filename or Markdown link | + +A form may include a target in parentheses and a suffix such as "for next-step +guidance" or "and follow it". It must direct that exit after reporting; a +mention, negated instruction, or conditional exit with a path that never +returns is insufficient. Reject conflicting exit destinations or additional +phase work after the terminal instruction. + +Read the built-in phase's completion instructions for comparison, without +executing them. Compare the override's destination with the built-in's after +applying only the invoking router's documented normalization. Accept equivalent +destinations even when the wording or exit form differs. Without documented +normalization, the exit and destination must match. If the built-in has no +explicit terminal instruction, use the router's documented completion contract; +if neither defines a comparable destination, warn and use the built-in phase. + +Legacy controller-return exits remain supported for existing overrides. A +dispatcher may normalize them to its completion guide to preserve the original +next-step behavior; this compatibility has no planned removal. Controller-based +workflows may continue to use controller returns directly. From 3155e159db3b1fb5343dc32ad99f70f3f0a6b762 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Tue, 8 Sep 2026 15:40:03 -0400 Subject: [PATCH 11/17] fix(overrides): preserve legacy completion behavior Assisted-by: Codex --- _shared/recipes/phase-override-resolution.md | 68 +++++++++++--------- bugfix/skills/dispatch.md | 7 +- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index c15d5998..cfafef15 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -23,8 +23,10 @@ before falling back to the workflow's built-in default. and validate it using the contract below before executing any of its steps. 3. If validation rejects the override, warn with the specific reason and use the built-in phase. Rejection is recoverable; it is not a resolution failure. -4. If using a project override, announce it: *"Using project override for - /{phase}."* Read and execute the selected file only after resolution. +4. If using a project override, announce it: *"Using project override: + {WORKFLOW}/{PHASE_FILE}."* Identify the file using these supplied values; + do not infer a command name from the filename. Read and execute the selected + file only after resolution. Resolution fails only when the selected built-in fallback cannot be located, read, or contains no executable phase instructions. Report that failure and @@ -33,38 +35,46 @@ operational errors through the invoking workflow's error handling. ## Override Validation +A routing refactor must continue to accept previously valid overrides without +requiring edits. Preserve their input and output artifacts, reporting, and +completion behavior. Falling back to a built-in phase does not preserve a +valid override's customization. + Reject an unreadable override or one with no executable instructions. Also -reject unclosed YAML frontmatter or fenced code blocks, unresolved merge -conflict markers, or a missing or unsupported terminal instruction. These are -the malformed-file conditions; do not reject an override for different heading -names, formatting, or additional phase steps alone. +reject unclosed YAML frontmatter or fenced code blocks, or unresolved merge +conflict markers outside quoted or fenced examples. Do not reject an override +for different headings, formatting, or additional phase steps alone. + +Validate the completion instructions by their behavior, not by an exact phrase +or the position of a sentence. Read the override's executable instructions and +the invoking router's completion contract before running the phase. Examples +of supported completion behavior include: -The terminal instruction is the last executable instruction in the phase's -completion section, or at the end of the file if there is no completion section. -Ignore blank lines, headings, comments, and quoted or fenced examples. Join -wrapped lines and ignore Markdown emphasis, inline-code delimiters, an optional -leading "Then", capitalization, and trailing punctuation when identifying the -following imperative forms: +- Reporting results and re-reading the workflow's controller for next steps. +- Returning to the invoking workflow router for completion guidance. +- Reading the workflow's completion guide. -| Exit | Accepted instruction forms | -|------|----------------------------| -| Router return | `Return to the invoking router`, `Return to the invoking workflow router`, or `Return control to the invoking router` | -| Completion guide | `Read` or `Re-read` followed by a named completion guide (a filename or Markdown link), or `Read the completion guide` when the router names that guide | -| Controller return | `Re-read the controller`, `Re-read this controller`, or `Re-read` followed by the workflow's controller filename or Markdown link | +These are examples, not an exhaustive grammar. Equivalent wording and existing +phase-specific handoffs remain valid. A dispatcher that normalizes controller +returns must accept legacy overrides that request those returns, even when the +current built-in phase uses a different exit. Apply the documented normalization +to the whole handoff, including the user's selection and any continuation. +Do not reject a legacy handoff solely because it differs from the current +built-in phase's completion instructions. -A form may include a target in parentheses and a suffix such as "for next-step -guidance" or "and follow it". It must direct that exit after reporting; a -mention, negated instruction, or conditional exit with a path that never -returns is insufficient. Reject conflicting exit destinations or additional -phase work after the terminal instruction. +For example, the legacy bugfix `/start` phase waits for the user to select a +phase, then says to re-read the controller and dispatch the chosen phase. Accept +that unchanged instruction. The router must preserve the wait and dispatch the +selected phase once after selection; the continuation is part of the supported +handoff, not forbidden work after a return. -Read the built-in phase's completion instructions for comparison, without -executing them. Compare the override's destination with the built-in's after -applying only the invoking router's documented normalization. Accept equivalent -destinations even when the wording or exit form differs. Without documented -normalization, the exit and destination must match. If the built-in has no -explicit terminal instruction, use the router's documented completion contract; -if neither defines a comparable destination, warn and use the built-in phase. +Reject completion behavior only when it is absent or incompatible with the +workflow's contract: for example, a controller mentioned only in an example, +conflicting destinations, or advancing without user selection where the +contract requires it. An explicit terminal sentence is unnecessary when the +workflow's router already defines how a phase returns after its steps finish. +A documented stop for missing input, an operational error, or a user decision +is a valid pause or failure outcome, not a missing completion instruction. Legacy controller-return exits remain supported for existing overrides. A dispatcher may normalize them to its completion guide to preserve the original diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md index c79f68da..780f19f7 100644 --- a/bugfix/skills/dispatch.md +++ b/bugfix/skills/dispatch.md @@ -19,6 +19,7 @@ compatibility with project overrides written for earlier routing contracts. After the recipe applies its invalid-override fallback, if no usable phase file can be resolved, an operational error prevents the phase from completing, or -the phase lacks a supported terminal exit, report the failure and stop without -reading `completion.md`. A completed phase report with a failing verdict is a -valid outcome: read `completion.md` so it can provide recovery guidance. +the phase has no completion behavior compatible with this workflow, report the +failure and stop without reading `completion.md`. A completed phase report with +a failing verdict is a valid outcome: read `completion.md` so it can provide +recovery guidance. From dbebe6dfe2de993ff507aad0bd7261fbd90e15af Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Tue, 8 Sep 2026 15:56:05 -0400 Subject: [PATCH 12/17] fix(bugfix): normalize PR version bump Assisted-by: Codex --- bugfix/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bugfix/SKILL.md b/bugfix/SKILL.md index 5a86db93..20ea747d 100644 --- a/bugfix/SKILL.md +++ b/bugfix/SKILL.md @@ -1,6 +1,6 @@ --- name: bugfix -version: 0.8.1 +version: 0.8.0 description: >- Diagnostic and repair workflow that analyzes error logs, traces root causes, implements fixes, and verifies with regression tests. From 7ebbb6fb6903b38046a040d5f2ef3da461b76389 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Tue, 8 Sep 2026 16:00:25 -0400 Subject: [PATCH 13/17] docs(overrides): keep continuation guidance neutral Assisted-by: Codex --- _shared/recipes/phase-override-resolution.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index cfafef15..67221f47 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -62,11 +62,9 @@ to the whole handoff, including the user's selection and any continuation. Do not reject a legacy handoff solely because it differs from the current built-in phase's completion instructions. -For example, the legacy bugfix `/start` phase waits for the user to select a -phase, then says to re-read the controller and dispatch the chosen phase. Accept -that unchanged instruction. The router must preserve the wait and dispatch the -selected phase once after selection; the continuation is part of the supported -handoff, not forbidden work after a return. +Preserve waits for user input and authorized continuations defined by the +invoking workflow. Normalize the complete handoff and execute each authorized +continuation once. Reject completion behavior only when it is absent or incompatible with the workflow's contract: for example, a controller mentioned only in an example, From 7966d8203760648508fa890881defe681e86d7b1 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Tue, 8 Sep 2026 17:09:27 -0400 Subject: [PATCH 14/17] fix(overrides): leave execution to workflow routers Assisted-by: Codex --- _shared/recipes/phase-override-resolution.md | 38 +++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index 67221f47..5f41811d 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -19,19 +19,26 @@ before falling back to the workflow's built-in default. 1. Locate `.workflows/{WORKFLOW}/skills/{PHASE_FILE}` at the consuming repo root. The built-in fallback is the same `PHASE_FILE` in the installed workflow's `skills/` directory, independent of the caller's location. -2. If no override exists, use the built-in phase. Otherwise, read the override - and validate it using the contract below before executing any of its steps. -3. If validation rejects the override, warn with the specific reason and use +2. If no override exists, select the built-in phase. Otherwise, read the + override for validation only, using the contract below. +3. If validation rejects the override, warn with the specific reason and select the built-in phase. Rejection is recoverable; it is not a resolution failure. 4. If using a project override, announce it: *"Using project override: {WORKFLOW}/{PHASE_FILE}."* Identify the file using these supplied values; - do not infer a command name from the filename. Read and execute the selected - file only after resolution. + do not infer a command name from the filename. +5. Return the selected file's location to the invoking router with its + instructions unchanged, whether it is an override or the built-in fallback. + +The invoking router executes the selected phase and handles its complete +handoff. It preserves required waits and user selections, applies its documented +normalization, and executes each authorized continuation once. This recipe does +not execute phase steps, completion guides, waits, or continuations. Resolution fails only when the selected built-in fallback cannot be located, read, or contains no executable phase instructions. Report that failure and -stop. Do not switch implementations after phase execution has started; report -operational errors through the invoking workflow's error handling. +stop. Once the invoking router starts phase execution, it must not switch +implementations; it reports operational errors through the workflow's error +handling. ## Override Validation @@ -47,8 +54,8 @@ for different headings, formatting, or additional phase steps alone. Validate the completion instructions by their behavior, not by an exact phrase or the position of a sentence. Read the override's executable instructions and -the invoking router's completion contract before running the phase. Examples -of supported completion behavior include: +the invoking router's completion contract without executing either. Examples of +supported completion behavior include: - Reporting results and re-reading the workflow's controller for next steps. - Returning to the invoking workflow router for completion guidance. @@ -57,14 +64,11 @@ of supported completion behavior include: These are examples, not an exhaustive grammar. Equivalent wording and existing phase-specific handoffs remain valid. A dispatcher that normalizes controller returns must accept legacy overrides that request those returns, even when the -current built-in phase uses a different exit. Apply the documented normalization -to the whole handoff, including the user's selection and any continuation. -Do not reject a legacy handoff solely because it differs from the current -built-in phase's completion instructions. - -Preserve waits for user input and authorized continuations defined by the -invoking workflow. Normalize the complete handoff and execute each authorized -continuation once. +current built-in phase uses a different exit. During validation, interpret the +whole handoff under the router's documented normalization solely to assess +compatibility, including user selections and continuations. Leave the handoff +unchanged for the router to execute. Do not reject a legacy handoff solely +because it differs from the current built-in phase's completion instructions. Reject completion behavior only when it is absent or incompatible with the workflow's contract: for example, a controller mentioned only in an example, From 4fb6e1ff8dd1b432c9dcfd26030d8917ed365ad9 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Tue, 8 Sep 2026 17:23:33 -0400 Subject: [PATCH 15/17] refactor(overrides): load validation on demand Assisted-by: Codex --- _shared/recipes/phase-override-resolution.md | 49 ++---------------- _shared/recipes/phase-override-validation.md | 53 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 45 deletions(-) create mode 100644 _shared/recipes/phase-override-validation.md diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index 5f41811d..75e7fee6 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -19,8 +19,10 @@ before falling back to the workflow's built-in default. 1. Locate `.workflows/{WORKFLOW}/skills/{PHASE_FILE}` at the consuming repo root. The built-in fallback is the same `PHASE_FILE` in the installed workflow's `skills/` directory, independent of the caller's location. -2. If no override exists, select the built-in phase. Otherwise, read the - override for validation only, using the contract below. +2. If no override exists, select the built-in phase without loading validation + instructions. Only when an override exists, read and follow + [phase-override-validation.md](phase-override-validation.md) with the supplied + parameters and the invoking router's completion contract. 3. If validation rejects the override, warn with the specific reason and select the built-in phase. Rejection is recoverable; it is not a resolution failure. 4. If using a project override, announce it: *"Using project override: @@ -39,46 +41,3 @@ read, or contains no executable phase instructions. Report that failure and stop. Once the invoking router starts phase execution, it must not switch implementations; it reports operational errors through the workflow's error handling. - -## Override Validation - -A routing refactor must continue to accept previously valid overrides without -requiring edits. Preserve their input and output artifacts, reporting, and -completion behavior. Falling back to a built-in phase does not preserve a -valid override's customization. - -Reject an unreadable override or one with no executable instructions. Also -reject unclosed YAML frontmatter or fenced code blocks, or unresolved merge -conflict markers outside quoted or fenced examples. Do not reject an override -for different headings, formatting, or additional phase steps alone. - -Validate the completion instructions by their behavior, not by an exact phrase -or the position of a sentence. Read the override's executable instructions and -the invoking router's completion contract without executing either. Examples of -supported completion behavior include: - -- Reporting results and re-reading the workflow's controller for next steps. -- Returning to the invoking workflow router for completion guidance. -- Reading the workflow's completion guide. - -These are examples, not an exhaustive grammar. Equivalent wording and existing -phase-specific handoffs remain valid. A dispatcher that normalizes controller -returns must accept legacy overrides that request those returns, even when the -current built-in phase uses a different exit. During validation, interpret the -whole handoff under the router's documented normalization solely to assess -compatibility, including user selections and continuations. Leave the handoff -unchanged for the router to execute. Do not reject a legacy handoff solely -because it differs from the current built-in phase's completion instructions. - -Reject completion behavior only when it is absent or incompatible with the -workflow's contract: for example, a controller mentioned only in an example, -conflicting destinations, or advancing without user selection where the -contract requires it. An explicit terminal sentence is unnecessary when the -workflow's router already defines how a phase returns after its steps finish. -A documented stop for missing input, an operational error, or a user decision -is a valid pause or failure outcome, not a missing completion instruction. - -Legacy controller-return exits remain supported for existing overrides. A -dispatcher may normalize them to its completion guide to preserve the original -next-step behavior; this compatibility has no planned removal. Controller-based -workflows may continue to use controller returns directly. diff --git a/_shared/recipes/phase-override-validation.md b/_shared/recipes/phase-override-validation.md new file mode 100644 index 00000000..06883da0 --- /dev/null +++ b/_shared/recipes/phase-override-validation.md @@ -0,0 +1,53 @@ +--- +name: phase-override-validation +version: 0.1.0 +--- +# Recipe: Phase Override Validation + +Read only when the resolver finds a project override. Use its `WORKFLOW` and +`PHASE_FILE` parameters and the invoking router's completion contract. Read the +override for validation only; return acceptance or a specific rejection reason +to the resolver. Do not execute the phase or its handoff. + +## Compatibility Contract + +A routing refactor must continue to accept previously valid overrides without +requiring edits. Preserve their input and output artifacts, reporting, and +completion behavior. Falling back to a built-in phase does not preserve a +valid override's customization. + +Reject an unreadable override or one with no executable instructions. Also +reject unclosed YAML frontmatter or fenced code blocks, or unresolved merge +conflict markers outside quoted or fenced examples. Do not reject an override +for different headings, formatting, or additional phase steps alone. + +Validate the completion instructions by their behavior, not by an exact phrase +or the position of a sentence. Read the override's executable instructions and +the invoking router's completion contract without executing either. Examples of +supported completion behavior include: + +- Reporting results and re-reading the workflow's controller for next steps. +- Returning to the invoking workflow router for completion guidance. +- Reading the workflow's completion guide. + +These are examples, not an exhaustive grammar. Equivalent wording and existing +phase-specific handoffs remain valid. A dispatcher that normalizes controller +returns must accept legacy overrides that request those returns, even when the +current built-in phase uses a different exit. During validation, interpret the +whole handoff under the router's documented normalization solely to assess +compatibility, including user selections and continuations. Leave the handoff +unchanged for the router to execute. Do not reject a legacy handoff solely +because it differs from the current built-in phase's completion instructions. + +Reject completion behavior only when it is absent or incompatible with the +workflow's contract: for example, a controller mentioned only in an example, +conflicting destinations, or advancing without user selection where the +contract requires it. An explicit terminal sentence is unnecessary when the +workflow's router already defines how a phase returns after its steps finish. +A documented stop for missing input, an operational error, or a user decision +is a valid pause or failure outcome, not a missing completion instruction. + +Legacy controller-return exits remain supported for existing overrides. A +dispatcher may normalize them to its completion guide to preserve the original +next-step behavior; this compatibility has no planned removal. Controller-based +workflows may continue to use controller returns directly. From 02c06b226178247521ff54eea642ad9cb2bb7c36 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Wed, 9 Sep 2026 09:47:33 -0400 Subject: [PATCH 16/17] fix(overrides): enforce phase compatibility contracts Part of flightctl/ai-workflows#113 Assisted-by: Codex --- _shared/recipes/phase-override-resolution.md | 16 ++++++++++++---- _shared/recipes/phase-override-validation.md | 14 ++++++++++++++ bugfix/skills/dispatch.md | 9 ++++++--- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/_shared/recipes/phase-override-resolution.md b/_shared/recipes/phase-override-resolution.md index 75e7fee6..8ff49fea 100644 --- a/_shared/recipes/phase-override-resolution.md +++ b/_shared/recipes/phase-override-resolution.md @@ -17,8 +17,9 @@ before falling back to the workflow's built-in default. ## Procedure 1. Locate `.workflows/{WORKFLOW}/skills/{PHASE_FILE}` at the consuming repo - root. The built-in fallback is the same `PHASE_FILE` in the installed - workflow's `skills/` directory, independent of the caller's location. + root. Resolve the built-in fallback as + `../../{WORKFLOW}/skills/{PHASE_FILE}` relative to this recipe, independent + of the caller's location. 2. If no override exists, select the built-in phase without loading validation instructions. Only when an override exists, read and follow [phase-override-validation.md](phase-override-validation.md) with the supplied @@ -28,14 +29,21 @@ before falling back to the workflow's built-in default. 4. If using a project override, announce it: *"Using project override: {WORKFLOW}/{PHASE_FILE}."* Identify the file using these supplied values; do not infer a command name from the filename. -5. Return the selected file's location to the invoking router with its - instructions unchanged, whether it is an override or the built-in fallback. +5. Return the selected file's location and any `COMPLETION_HANDOFF` + classification to the invoking router with the file's instructions + unchanged, whether it is an override or the built-in fallback. The invoking router executes the selected phase and handles its complete handoff. It preserves required waits and user selections, applies its documented normalization, and executes each authorized continuation once. This recipe does not execute phase steps, completion guides, waits, or continuations. +Completion handling must occur exactly once. Initialize +`COMPLETION_CONSUMED=false`. A router that executes a phase's completion-guide +handoff sets `COMPLETION_CONSUMED=true` and skips its default follow-up +completion read. A router that normalizes the handoff without executing its +destination leaves it false and performs its normal completion read once. + Resolution fails only when the selected built-in fallback cannot be located, read, or contains no executable phase instructions. Report that failure and stop. Once the invoking router starts phase execution, it must not switch diff --git a/_shared/recipes/phase-override-validation.md b/_shared/recipes/phase-override-validation.md index 06883da0..ad5973a9 100644 --- a/_shared/recipes/phase-override-validation.md +++ b/_shared/recipes/phase-override-validation.md @@ -21,6 +21,13 @@ reject unclosed YAML frontmatter or fenced code blocks, or unresolved merge conflict markers outside quoted or fenced examples. Do not reject an override for different headings, formatting, or additional phase steps alone. +Before accepting the override, read the built-in phase at +`../../{WORKFLOW}/skills/{PHASE_FILE}` and the workflow's documented artifact +contract. Compare the required input, output, and reporting artifacts. Reject +an override that omits a required artifact, renames it, or changes its required +location. Additional artifacts remain valid unless the workflow contract +prohibits them. + Validate the completion instructions by their behavior, not by an exact phrase or the position of a sentence. Read the override's executable instructions and the invoking router's completion contract without executing either. Examples of @@ -30,6 +37,13 @@ supported completion behavior include: - Returning to the invoking workflow router for completion guidance. - Reading the workflow's completion guide. +Return `COMPLETION_HANDOFF` as `router-return`, `controller-return`, +`completion-guide`, or `router-defined` for the accepted handoff. If the handoff +reads a completion guide, the invoking router must set +`COMPLETION_CONSUMED=true` and skip any default follow-up read. If the router +normalizes the handoff without executing its destination, completion remains +unconsumed and the router performs its normal read once. + These are examples, not an exhaustive grammar. Equivalent wording and existing phase-specific handoffs remain valid. A dispatcher that normalizes controller returns must accept legacy overrides that request those returns, even when the diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md index 780f19f7..73023ecd 100644 --- a/bugfix/skills/dispatch.md +++ b/bugfix/skills/dispatch.md @@ -13,9 +13,12 @@ through the command context unchanged. The built-in fallback is the phase file beside this dispatcher. Follow the phase through its reporting step. Treat any valid phase exit—returning to the invoking router, requesting completion guidance, or re-reading the -controller—as a return to this dispatcher. Then read `completion.md` and follow -its guidance for `PHASE`. Supporting all three exit forms preserves -compatibility with project overrides written for earlier routing contracts. +controller—as a return to this dispatcher. Initialize +`COMPLETION_CONSUMED=false`; set it to true if the phase handoff reads +`completion.md`. When the phase returns, read the guide once and follow its +guidance for `PHASE` only when `COMPLETION_CONSUMED=false`. Supporting all three +exit forms preserves compatibility with project overrides written for earlier +routing contracts. After the recipe applies its invalid-override fallback, if no usable phase file can be resolved, an operational error prevents the phase from completing, or From 927eec3dd3acc6177e18d196033e502f7fd43ad8 Mon Sep 17 00:00:00 2001 From: Andy Dalton Date: Wed, 9 Sep 2026 09:55:21 -0400 Subject: [PATCH 17/17] fix(overrides): make validation inputs deterministic Part of flightctl/ai-workflows#113 Assisted-by: Codex --- _shared/recipes/phase-override-validation.md | 10 +++++----- bugfix/skills/dispatch.md | 15 ++++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/_shared/recipes/phase-override-validation.md b/_shared/recipes/phase-override-validation.md index ad5973a9..9388d96f 100644 --- a/_shared/recipes/phase-override-validation.md +++ b/_shared/recipes/phase-override-validation.md @@ -22,11 +22,11 @@ conflict markers outside quoted or fenced examples. Do not reject an override for different headings, formatting, or additional phase steps alone. Before accepting the override, read the built-in phase at -`../../{WORKFLOW}/skills/{PHASE_FILE}` and the workflow's documented artifact -contract. Compare the required input, output, and reporting artifacts. Reject -an override that omits a required artifact, renames it, or changes its required -location. Additional artifacts remain valid unless the workflow contract -prohibits them. +`../../{WORKFLOW}/skills/{PHASE_FILE}` and the workflow's artifact contract at +`../../{WORKFLOW}/skills/controller.md`, both relative to this recipe. Compare +the required input, output, and reporting artifacts. Reject an override that +omits a required artifact, renames it, or changes its required location. +Additional artifacts remain valid unless the workflow contract prohibits them. Validate the completion instructions by their behavior, not by an exact phrase or the position of a sentence. Read the override's executable instructions and diff --git a/bugfix/skills/dispatch.md b/bugfix/skills/dispatch.md index 73023ecd..cd73bfe5 100644 --- a/bugfix/skills/dispatch.md +++ b/bugfix/skills/dispatch.md @@ -5,7 +5,8 @@ description: Resolve and execute one requested bugfix phase. # Bugfix Phase Dispatch -Given `PHASE`, announce `Starting /{PHASE}.` Then read and follow +Given `PHASE`, initialize `COMPLETION_CONSUMED=false`, then announce +`Starting /{PHASE}.` Read and follow `../../_shared/recipes/phase-override-resolution.md` with `WORKFLOW=bugfix` and `PHASE_FILE={PHASE}.md`. Read and execute the resolved phase file, passing through the command context unchanged. @@ -13,12 +14,12 @@ through the command context unchanged. The built-in fallback is the phase file beside this dispatcher. Follow the phase through its reporting step. Treat any valid phase exit—returning to the invoking router, requesting completion guidance, or re-reading the -controller—as a return to this dispatcher. Initialize -`COMPLETION_CONSUMED=false`; set it to true if the phase handoff reads -`completion.md`. When the phase returns, read the guide once and follow its -guidance for `PHASE` only when `COMPLETION_CONSUMED=false`. Supporting all three -exit forms preserves compatibility with project overrides written for earlier -routing contracts. +controller—as a return to this dispatcher. If the returned +`COMPLETION_HANDOFF` executes `completion.md`, set `COMPLETION_CONSUMED=true` +before executing that handoff. When the phase returns, read the guide once and +follow its guidance for `PHASE` only when `COMPLETION_CONSUMED=false`. +Supporting all three exit forms preserves compatibility with project overrides +written for earlier routing contracts. After the recipe applies its invalid-override fallback, if no usable phase file can be resolved, an operational error prevents the phase from completing, or