5-phase-workflow 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +31 -104
  2. package/bin/install.js +163 -178
  3. package/bin/sync-agents.js +59 -54
  4. package/docs/workflow-guide.md +35 -79
  5. package/package.json +1 -1
  6. package/src/agents/step-executor-agent.md +3 -3
  7. package/src/agents/step-orchestrator-agent.md +12 -12
  8. package/src/agents/verification-agent.md +5 -8
  9. package/src/codex-commands/plan.md +65 -0
  10. package/src/commands/5/address-review-findings.md +43 -52
  11. package/src/commands/5/analyze-feature.md +1 -1
  12. package/src/commands/5/configure.md +75 -179
  13. package/src/commands/5/eject.md +0 -1
  14. package/src/commands/5/implement.md +68 -74
  15. package/src/commands/5/lean-check.md +7 -5
  16. package/src/commands/5/reconfigure.md +48 -129
  17. package/src/commands/5/review.md +42 -14
  18. package/src/commands/5/synchronize-agents.md +1 -1
  19. package/src/commands/5/update.md +2 -2
  20. package/src/hooks/statusline.js +5 -3
  21. package/src/references/configure-tables.md +0 -33
  22. package/src/settings.json +0 -12
  23. package/src/skills/baseline-conventions/SKILL.md +37 -0
  24. package/src/skills/cognitive-load/SKILL.md +52 -0
  25. package/src/skills/configure-agents-md/SKILL.md +72 -0
  26. package/src/skills/configure-rules/SKILL.md +146 -0
  27. package/src/skills/documentation-style/SKILL.md +32 -0
  28. package/src/skills/fowler-code-smells/SKILL.md +25 -0
  29. package/src/skills/review-style/SKILL.md +142 -0
  30. package/src/templates/AGENTS.md +19 -27
  31. package/src/templates/workflow/REVIEW-FINDINGS.md +2 -9
  32. package/src/workflows/5-implement.js +53 -91
  33. package/docs/findings.md +0 -361
  34. package/docs/progress.md +0 -102
  35. package/src/commands/5/apply-review-findings.md +0 -66
  36. package/src/commands/5/commit.md +0 -43
  37. package/src/commands/5/plan.md +0 -190
  38. package/src/commands/5/reply-pr-comments.md +0 -48
  39. package/src/commands/5/split.md +0 -86
  40. package/src/commands/5/triage-pr-comments.md +0 -70
  41. package/src/hooks/config-guard.js +0 -30
  42. package/src/skills/configure-docs-index/SKILL.md +0 -243
  43. package/src/skills/configure-skills/SKILL.md +0 -311
  44. package/src/skills/generate-readme/EXAMPLES.md +0 -168
  45. package/src/skills/generate-readme/SKILL.md +0 -122
  46. package/src/skills/generate-readme/TEMPLATE.md +0 -141
  47. package/src/skills/use-index/SKILL.md +0 -49
  48. package/src/templates/ARCHITECTURE.md +0 -33
  49. package/src/templates/CONCERNS.md +0 -33
  50. package/src/templates/CONVENTIONS.md +0 -74
  51. package/src/templates/TESTING.md +0 -24
  52. package/src/templates/workflow/FIX-PLAN.md +0 -55
  53. package/src/templates/workflow/PLAN-COMPACT.md +0 -42
  54. package/src/templates/workflow/PLAN.md +0 -76
  55. package/src/templates/workflow/REVIEW-SUMMARY.md +0 -53
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: review-style
3
+ description: Review changes against coding and documentation standards (repo standards plus a list of style skills), then optionally fix the findings. Use when the user wants a style, standards or conventions review of a branch, a commit range or uncommitted work.
4
+ ---
5
+
6
+ # Review style
7
+
8
+ Review a change against two kinds of standards:
9
+
10
+ - **Repo standards**: whatever the repository documents about how code is written.
11
+ - **Styles**: the style skills listed below. They apply in every repository.
12
+
13
+ Repo standards always win. Where a repo standard endorses something a style would flag, the style finding is
14
+ **suppressed**.
15
+
16
+ ## Styles
17
+
18
+ Each path is relative to this skill's base directory. Add a style by adding one line.
19
+
20
+ - `../fowler-code-smells/SKILL.md`
21
+ - `../cognitive-load/SKILL.md`
22
+ - `../documentation-style/SKILL.md`. It applies only to code comments, doc comments and Markdown files.
23
+ - `../baseline-conventions/SKILL.md`
24
+
25
+ ## Process
26
+
27
+ ### 1. Pin the scope
28
+
29
+ The caller's words pick one of these modes:
30
+
31
+ | Mode | Example | Diff |
32
+ |------|---------|------|
33
+ | Since fixed point plus uncommitted (default) | `/review-style master` | `git diff $(git merge-base <fixed-point> HEAD)`, plus untracked files |
34
+ | Committed only | `/review-style master committed only` | `git diff <fixed-point>...HEAD` |
35
+ | Uncommitted only | `/review-style uncommitted` | `git diff HEAD`, plus untracked files |
36
+ | Staged only | `/review-style staged` | `git diff --cached` |
37
+ | Unstaged only | `/review-style unstaged` | `git diff`, plus untracked files |
38
+
39
+ When the words don't clearly name a mode, ask. When a mode needs a fixed point and none is given, ask for it.
40
+ Offer the merge-base with the default branch (`master` or `main`) as the suggested answer.
41
+
42
+ When the caller names files, limit the diff to them, for example `git diff <fixed-point> -- <files>`. Other
43
+ changed files stay out of the review and out of the fixes.
44
+
45
+ Untracked files are those from `git ls-files --others --exclude-standard`. In the modes whose diff says "plus
46
+ untracked files", add each one to the diff as a new file whose every line is added. The other modes leave them out.
47
+
48
+ Confirm the fixed point resolves with `git rev-parse`. Stop when the diff is empty. Write the diff to one temp
49
+ file, in the scratchpad when there is one. Also note `git log <fixed-point>..HEAD --oneline` when the mode
50
+ includes commits.
51
+
52
+ The step is done when one diff file exists and every reviewer will read that same file.
53
+
54
+ ### 2. Collect the repo standards
55
+
56
+ Search the repository for every file that documents how code is written:
57
+
58
+ - `CODING_STANDARDS.md`, `CONTRIBUTING.md`, `CODESTYLE.md`, `STYLEGUIDE.md`, and docs about style or conventions.
59
+ Look at the repository root, `.github/` and `docs/`.
60
+ - `CLAUDE.md` and `AGENTS.md` at every level, plus every file they link to about code, tests or docs.
61
+ The block between `<!-- foifi:start` and `<!-- foifi:end -->` holds workflow rules, not repository
62
+ standards; count only the files it links under "Standards". In a legacy file that says a workflow generated it
63
+ from a template, count only the parts it names as repository standards.
64
+
65
+ Skip linter and formatter configs. Tooling enforces them already.
66
+
67
+ ### 3. Resolve the styles
68
+
69
+ Turn each path in [Styles](#styles) into an absolute path from this skill's base directory. Reviewers don't
70
+ know that directory, so they only get absolute paths.
71
+
72
+ ### 4. Review in parallel
73
+
74
+ Start both reviewers in one message, as foreground sub-agents:
75
+
76
+ - One **repo reviewer** for all repo standards together, when step 2 found any.
77
+ - One **style reviewer** for all styles together. Two reviewers keep the token cost flat as styles are added.
78
+
79
+ Each prompt carries:
80
+
81
+ - The diff file path and the commit list.
82
+ - Its standards: the repo standard files, or the absolute paths of every style's `SKILL.md`. The style
83
+ reviewer reads each `SKILL.md` and every file it links to, and applies each style only where it says it
84
+ applies.
85
+ - For the style reviewer, the repo standard files too, so they can suppress overridden findings.
86
+ - The **context rule**: before judging a hunk, read its whole enclosing method and type. Follow the calls,
87
+ types and parents it touches whenever a rule needs them. Search the repository when a rule asks about
88
+ duplication.
89
+ - The **scope rule**: anchor every finding on a changed line. Flag a problem in surrounding code only when the
90
+ change creates or worsens it, such as adding a fourth level of nesting. Leave problems that already existed
91
+ alone. Lift this rule only when the caller asked for it.
92
+ - The brief:
93
+
94
+ > Apply every rule of your standard to every changed hunk. Report each finding as:
95
+ > `path:line`, a title of a few words, the quoted code, the rule (standard file plus rule name), hard or judgement, and a suggested
96
+ > fix in a few words. Every finding gets a suggested fix. Use one sentence when a few words can't carry it. A breach of a repo standard may be hard. A style finding is always a judgement call. Skip anything
97
+ > tooling enforces.
98
+ >
99
+ > Style reviewer only: when a repo standard endorses what your style would flag, report it under
100
+ > **Suppressed**, citing the repo rule that overrides it.
101
+
102
+ ### 5. Merge and report
103
+
104
+ - Merge findings that flag the same line for the same reason. Cite every rule involved.
105
+ - Number the findings `F1`, `F2`, … and group them by file.
106
+ - Write each finding in this shape. ⛔️ marks a hard breach of a repo standard. ⚠️ marks a judgement call.
107
+ The title names the problem in a few words.
108
+ ```
109
+ - <icon> **<ID> <title>** _(<lines>)_
110
+ <what is wrong and why>
111
+ → <fix> _(<standards>)_
112
+ ```
113
+ For example:
114
+ ```
115
+ - ⛔️ **F1 Javadoc repeats the accessor** _(:71)_
116
+ `@return the entity links.` adds nothing the method name doesn't say.
117
+ → Drop the line. _(Repo comment rules, Doc)_
118
+ - ⚠️ **F7 Plural name on an invariant checker** _(:12)_
119
+ The plural name suggests a collection, but the class checks an invariant.
120
+ → Rename to `DocumentEntityLinkInvariantHelper`. _(Cog)_
121
+ ```
122
+ - Every finding shows its fix. When a reviewer sent none, write one.
123
+ - List suppressed findings in a separate **Suppressed** section, each with its overriding repo rule.
124
+ - End with one line: findings per standard, hard violations count, and the worst issue.
125
+
126
+ ### 6. Fix
127
+
128
+ When the caller asked for a report only, stop after step 5. When the caller asked for fixes up front, fix every
129
+ finding. Otherwise, and only when there are findings, ask: fix all, fix hard violations only, fix the IDs I list,
130
+ or fix nothing.
131
+
132
+ Start one **fixer** sub-agent with:
133
+
134
+ - The selected findings, verbatim, with their rule references.
135
+ - The absolute paths of all standards, so it can look a rule up.
136
+ - The brief:
137
+
138
+ > Fix each finding in the working tree. Then run the repository's documented cheap check, such as compile
139
+ > and format, the way its `CLAUDE.md` or `CONTRIBUTING.md` says. Leave the changes uncommitted. Report
140
+ > each ID as fixed or skipped, with the reason for every skip.
141
+
142
+ Suppressed findings are never fixed. Relay the fixer's report.
@@ -1,37 +1,35 @@
1
- # Repository Guide
1
+ <!-- foifi:start — Managed by foifi. /5:reconfigure rewrites everything up to foifi:end. Everything outside this block belongs to the repository and ranks above it: it is part of the repository's own standards. -->
2
2
 
3
- {PROJECT_OVERVIEW}
3
+ # Workflow Rules (foifi)
4
4
 
5
5
  ## Build & Run Commands
6
6
 
7
7
  {BUILD_RUN_COMMANDS}
8
8
 
9
- ## Skill Usage
9
+ ## Commit Messages
10
10
 
11
- Before implementing changes, always check the available skills for relevant implementation guidance.
11
+ {COMMIT_MESSAGE_RULE}
12
12
 
13
- Use skills to understand project-specific workflows, commands, testing expectations, and implementation conventions before editing code.
13
+ ## Standards
14
14
 
15
- ## Commit Messages
15
+ These rules decide how code is written here, in this order:
16
+
17
+ 1. **This repository's own standards always win.** They are everything in `AGENTS.md` and `CLAUDE.md` outside this block, plus these files:
18
+
19
+ {REPO_STANDARDS_LINKS}
16
20
 
17
- Use the `/5:commit` command or `$5-commit` skill when creating commits. It reads `.5/config.json` and applies the configured `git.commitMessage.pattern`, including ticket IDs from branch names when configured.
21
+ 2. **The workflow's style skills set the baseline** wherever the repository's standards say nothing: `fowler-code-smells`, `cognitive-load`, `documentation-style`, and `baseline-conventions`. Follow them when you write or review code. Where a repository standard endorses something a style would flag, the repository standard wins.
22
+ 3. **The workflow rules below** (Simplicity First, Testing, Surgical Changes, Goal-Driven Execution) apply as well. When a repository standard asks for more, such as a changelog entry or a test, do what it asks.
18
23
 
19
- ## Workflow Rules
24
+ Run the `review-style` skill to check a change against all of them.
20
25
 
21
- When running `/5:` workflow commands, follow the command instructions exactly as written.
22
- Do not skip steps, combine phases, or proceed to actions not specified in the current command.
23
- Each phase produces a specific artifact - do not create artifacts belonging to other phases.
26
+ ## Planning
24
27
 
25
- ## Coding Guidelines
28
+ Plan non-trivial changes in plan mode (Codex: run `$5-plan`). Shape each plan as the change needs; add a mermaid diagram when a flow, state machine, or component relationships explain the change better than text, and plan what the repository standards require, such as tests or a changelog entry.
26
29
 
27
- {CONVENTIONS_REFERENCE}
30
+ When the request names a ticket, fetch it (Jira MCP or `gh issue view`) and confirm its content with the user before planning.
28
31
 
29
- 1. Prefer explicit types or contracts for public APIs, data transfer shapes, service methods, hooks, and async return values where the language supports them.
30
- 2. Keep comments and docs concise; document constraints and non-obvious behavior, not the obvious.
31
- 3. Keep files focused and bounded; split broad controllers, services, hooks, and components early.
32
- 4. Extract helpers or classes when logic starts mixing orchestration, parsing, IO, and mapping in one place.
33
- 5. Favor SRP and DRY, but follow surrounding module conventions before introducing new abstractions.
34
- 6. Keep features modular: wire backend providers in feature modules, keep UI state in hooks, and avoid cross-layer shortcuts.
32
+ After the user approves a plan, run `/5:implement {plan-path}` (Codex: `$5-implement {plan-path}`). Do not implement the plan any other way.
35
33
 
36
34
  ## Simplicity First
37
35
 
@@ -86,7 +84,7 @@ When your changes create orphans:
86
84
 
87
85
  The test: Every changed line should trace directly to the user's request.
88
86
 
89
- Before you report a task as done, check your own diff (`git status --short` and `git diff --stat`): revert files and changes that do not trace to the request, and remove new dependencies nobody asked for. For a deeper pass, run `/5:lean-check` (Codex: `$5-lean-check`).
87
+ Before you report a task as done, check your own diff (`git status --short` and `git diff --stat`): revert files and changes that do not trace to the request. For every dependency the diff adds: keep it and name it in your reply if the user asked for it; otherwise remove it with the package manager and use existing code, the standard library, or an installed dependency instead. For a deeper pass, run `/5:lean-check` (Codex: `$5-lean-check`).
90
88
 
91
89
  ## Goal-Driven Execution
92
90
 
@@ -110,10 +108,4 @@ Strong success criteria let you loop independently. Weak criteria ("make it work
110
108
 
111
109
  {PROJECT_DOCUMENTATION_LINKS}
112
110
 
113
- ## Codebase Index
114
-
115
- {CODEBASE_INDEX_LINKS}
116
-
117
- Use the `use-index` skill before running broad Glob/Grep scans. It handles freshness checks, file selection by task type, and fallback strategies. If index files are more than one day old, regenerate them by running `.5/index/rebuild-index.sh` before relying on them.
118
-
119
- {CUSTOM_DOCUMENTATION}
111
+ <!-- foifi:end -->
@@ -8,12 +8,7 @@
8
8
 
9
9
  ## How to Use This File
10
10
 
11
- 1. Review this file if you want context before applying fixes
12
- 2. Run: `/5:address-review-findings`
13
- 3. The command will present each finding one by one with a recommendation
14
- 4. Choose `fix`, `wont_fix`, `wait`, or provide textual instructions
15
-
16
- The command records your decisions separately and applies only findings marked `fix`.
11
+ `/5:review` hands this file to `/5:address-review-findings`, which fixes the clear findings on its own and asks you, one question at a time, about the rest. Run `/5:address-review-findings --interactive` to decide on every finding yourself.
17
12
 
18
13
  ---
19
14
 
@@ -44,6 +39,4 @@ The command records your decisions separately and applies only findings marked `
44
39
  - Questions: {N}
45
40
  - Manual Review: {N}
46
41
 
47
- **Next Steps:**
48
- 1. Run: `/5:address-review-findings`
49
- 2. Decide on each finding interactively
42
+ **Next Step:** `/5:address-review-findings` (runs automatically after `/5:review`)
@@ -1,9 +1,9 @@
1
1
  export const meta = {
2
2
  name: '5-implement',
3
- description: 'Execute a unified plan: derive steps, run executors in parallel waves, verify. Claude Code only; Codex uses the prose loop.',
4
- whenToUse: 'Invoked by the /5:implement command when the Workflow tool is available. Reads args from the command, returns the run result for the command to persist to the slim state.json.',
3
+ description: 'Execute a full plan: derive steps, run executors in parallel waves, verify. Claude Code only; Codex uses the prose loop.',
4
+ whenToUse: 'Invoked by the /5:implement command for full plans when the Workflow tool is available. Compact plans never reach it; the command implements them inline.',
5
5
  phases: [
6
- { title: 'Orchestrate', detail: 'derive steps + components (agent for non-trivial plans, inline for compact)' },
6
+ { title: 'Orchestrate', detail: 'one orchestrator agent derives steps + components' },
7
7
  { title: 'Execute', detail: 'one executor agent per component; parallel components fire together per step' },
8
8
  { title: 'Verify', detail: 'inline when all passed + mechanical, else one verification agent' }
9
9
  ]
@@ -15,12 +15,11 @@ export const meta = {
15
15
  // the canonical human-readable contract; keep these prompts in sync with them.
16
16
  //
17
17
  // This script has NO filesystem access. It orchestrates agents and RETURNS the
18
- // final result. The /5:implement command (which has Write) persists the slim
19
- // state.json and runs auto-commit after this returns.
18
+ // final result. The /5:implement command runs the fast-path build/test check and
19
+ // auto-commit after this returns. Nothing is persisted: a rerun starts over.
20
20
  //
21
- // The execution graph (steps/components) is derived fresh on every run and is
22
- // NOT persisted. Resume works because component names are copied verbatim from
23
- // the plan's Component Checklist, so re-derivation is stable by name.
21
+ // Models: haiku for mechanical work, sonnet for ordinary logic, opus at effort
22
+ // medium for complex work and for every retry.
24
23
  // ─────────────────────────────────────────────────────────────────────────────
25
24
 
26
25
  const RESULT_SCHEMA = {
@@ -41,13 +40,12 @@ const RESULT_SCHEMA = {
41
40
  const VERIFICATION_SCHEMA = {
42
41
  type: 'object',
43
42
  additionalProperties: false,
44
- required: ['status', 'completeness', 'infrastructure', 'quality', 'scope'],
43
+ required: ['status', 'completeness', 'infrastructure', 'scope'],
45
44
  properties: {
46
45
  status: { enum: ['passed', 'partial', 'failed'] },
47
46
  completeness: { enum: ['passed', 'partial', 'failed'] },
48
47
  infrastructure: { enum: ['passed', 'failed'] },
49
48
  acceptanceCriteria: { type: 'string', description: 'satisfied/total, e.g. "3/3"' },
50
- quality: { enum: ['passed', 'partial', 'failed'] },
51
49
  scope: { enum: ['passed', 'drift'] },
52
50
  commands: {
53
51
  type: 'array',
@@ -81,7 +79,7 @@ const STATE_SCHEMA = {
81
79
  number: { type: 'integer' },
82
80
  name: { type: 'string' },
83
81
  mode: { enum: ['parallel', 'sequential'] },
84
- model: { enum: ['haiku', 'sonnet'] },
82
+ model: { enum: ['haiku', 'sonnet', 'opus'] },
85
83
  components: { type: 'array', items: { type: 'string' } }
86
84
  }
87
85
  }
@@ -97,7 +95,7 @@ const STATE_SCHEMA = {
97
95
  action: { enum: ['create', 'modify', 'delete', 'rename'] },
98
96
  step: { type: 'integer' },
99
97
  mode: { enum: ['parallel', 'sequential'] },
100
- model: { enum: ['haiku', 'sonnet'] },
98
+ model: { enum: ['haiku', 'sonnet', 'opus'] },
101
99
  file: { type: 'string' },
102
100
  sourceFile: { type: ['string', 'null'] },
103
101
  description: { type: 'string' },
@@ -130,17 +128,15 @@ function orchestratorPrompt(a) {
130
128
 
131
129
  Feature: ${a.feature}
132
130
  Plan: ${a.paths.plan}
133
- Codebase scan: ${a.paths.scan} (read only if present)
134
131
  Config: ${a.paths.config} (read only if present)
135
132
 
136
- Turn the lean component checklist in the plan into steps + components:
137
- - COPY EVERY COMPONENT NAME VERBATIM from the plan's Component Checklist. Resume matches components by name across runs, so a renamed or reformatted name makes completed work run twice.
133
+ The plan has no fixed shape. Derive the components from whatever it describes: one component per target file (or tightly coupled file group), named in short kebab-case, then turn them into steps + components:
138
134
  - Group independent components into one step with mode "parallel"; use "sequential" only when components touch the same file, one imports another, or there is an explicit dependency.
139
135
  - Prefer fewer steps. Tests run after the components they validate.
140
- - model "haiku" by default (mechanical, UI, tests, docs, config, single-file). model "sonnet" only for complex logic, cross-module, security/auth, migrations, or public API.
141
- - 1-2 high-signal patternRefs per component with line ranges or symbols so executors avoid whole-file reads.
136
+ - model "haiku" for mechanical work (UI tweaks, tests, docs, config, simple single-file edits); "sonnet" for ordinary logic; "opus" only for complex logic, cross-module behavior, security/auth, data migrations, or public API contracts.
137
+ - 1-2 high-signal patternRefs per component with line ranges or symbols so executors avoid whole-file reads. Take them from the plan where it names patterns, else find them with Glob/Grep.
142
138
  - verifyCommands: narrowest relevant check first, then project build/test.
143
- - Exclude [DEFERRED] work. Represent every other component once. dependsOn must reference existing component names.
139
+ - Exclude work the plan defers or rules out. Represent every other component once. dependsOn must reference existing component names.
144
140
 
145
141
  Return an object matching the schema (steps[] and pendingComponents[]).`
146
142
  }
@@ -148,6 +144,9 @@ Return an object matching the schema (steps[] and pendingComponents[]).`
148
144
  function executorPrompt(c, a, opts) {
149
145
  const refs = (c.patternRefs || []).map(r => ` - ${r.file}${r.read ? ` (${r.read})` : ''}${r.reason ? ` — ${r.reason}` : ''}`).join('\n') || ' - none'
150
146
  const verify = (c.verifyCommands || []).join(' && ') || 'infer the narrowest relevant test/build command'
147
+ const standards = a.standards || {}
148
+ const repoStandards = (standards.repo || []).map(f => ` - ${f}`).join('\n') || ' - none found'
149
+ const styles = (standards.styles || []).map(f => ` - ${f}`).join('\n') || ' - none found'
151
150
  const retry = opts && opts.retry
152
151
  ? '\nThis is a RETRY of a failed attempt — read the error context carefully and correct the root cause.'
153
152
  : ''
@@ -158,23 +157,27 @@ Action: ${c.action}
158
157
  Target file: ${c.file}${c.sourceFile ? `\nSource file (rename from): ${c.sourceFile}` : ''}
159
158
  Intent: ${c.description || ''}
160
159
 
161
- Read only these pattern references (ranges/symbols), plus the target file for modify/rename:
160
+ Read only these pattern references (ranges/symbols), plus the target file for modify/rename — and for create when it already exists:
162
161
  ${refs}
163
162
 
164
- Rules: smallest coherent change; reuse what already exists in this codebase before writing new code, then prefer stdlib, native platform features, and installed dependencies; touch only the target file and what it strictly needs (its test, an import site); mirror existing naming/exports/layout/tests; follow any local skill or rule; add no new dependency; no abstraction or error handling beyond what the intent requires. Fix mechanical issues you cause (imports, types, lint). STOP and report failed for missing dependencies, unplanned auth/schema/API/contract changes, or unclear product decisions. If verify fails only from pre-existing unrelated issues, report that as a deviation with the exact evidence — do not mark the component failed. Do not make more than three attempts on the same failing issue.
163
+ Standards — read the parts that apply to your target and follow them. Repository standards win over the style skills.
164
+ Repository standards:
165
+ ${repoStandards}
166
+ Style skills:
167
+ ${styles}
168
+
169
+ Rules: Nothing is persisted between runs, so your work may already be done: for \`create\`, read the target first when it exists — if it already fulfils the intent, report success with no change; otherwise complete it, never overwrite it blindly. Smallest coherent change; reuse what already exists in this codebase before writing new code, then prefer stdlib, native platform features, and installed dependencies; touch only the target file and what it strictly needs (its test, an import site); mirror existing naming/exports/layout/tests; follow any local skill or rule; add no new dependency; no abstraction or error handling beyond what the intent requires. Fix mechanical issues you cause (imports, types, lint). STOP and report failed for missing dependencies, unplanned auth/schema/API/contract changes, or unclear product decisions. If verify fails only from pre-existing unrelated issues, report that as a deviation with the exact evidence — do not mark the component failed. Do not make more than three attempts on the same failing issue.
165
170
 
166
171
  Then run: ${verify}
167
172
 
168
173
  Return structured output: status, filesCreated, filesModified, verify, deviations (none or brief), skipped (none, or what you deliberately did not build — add when ...), error (none or description). Keep it concise — no logs or diffs unless failed.`
169
174
  }
170
175
 
171
- function verifyPrompt(a, results, resumeDone) {
176
+ function verifyPrompt(a, results) {
172
177
  const ran = results.flatMap(s => s.items.map(i =>
173
- ` step ${s.step} ${i.component.name}: ${i.result ? i.result.status : 'no result'} (verify ${i.result ? i.result.verify : '?'})${i.escalated ? ' [escalated to sonnet]' : ''}`))
174
- const prior = [...(resumeDone || [])]
175
- .filter(n => !results.some(s => s.items.some(i => i.component.name === n)))
176
- .map(n => ` ${n}: completed in a prior session`)
177
- const summary = [...ran, ...prior].join('\n') || ' (no components ran this invocation)'
178
+ ` step ${s.step} ${i.component.name}: ${i.result ? i.result.status : 'no result'} (verify ${i.result ? i.result.verify : '?'})${i.escalated ? ' [escalated to opus]' : ''}`))
179
+ const summary = ran.join('\n') || ' (no components ran)'
180
+ const repoStandards = ((a.standards && a.standards.repo) || []).join(', ') || 'none found'
178
181
  const baseline = (a.baseline && a.baseline.length)
179
182
  ? a.baseline.map(b => ` ${b.command || b.details && b.details.command || '?'}: ${b.status}${b.summary ? ` — ${b.summary}` : ''}`).join('\n')
180
183
  : ' (none recorded)'
@@ -183,6 +186,7 @@ function verifyPrompt(a, results, resumeDone) {
183
186
  Feature: ${a.feature}
184
187
  Plan: ${a.paths.plan}
185
188
  Config: ${a.paths.config} (read only if present)
189
+ Repository standards: ${repoStandards}
186
190
 
187
191
  Baseline (pre-change) command results — treat any failure listed here as PRE-EXISTING, not caused by this change:
188
192
  ${baseline}
@@ -190,40 +194,16 @@ ${baseline}
190
194
  Component results:
191
195
  ${summary}
192
196
 
193
- Checks: completeness (every planned component done, acceptance criteria addressed); files exist for create/modify, rename moved correctly, delete removed; build + test pass (reuse the baseline and component results above when they already prove status — rerun only the commands whose inputs changed, not identical passing ones); correctness (inspect changed files, not just existence); quality (logic-bearing changes have tests when a test framework exists); scope (run \`git status --short\` and \`git diff HEAD --stat\`, and read untracked files directly since \`git diff HEAD\` omits them: every changed file traces to a planned component — its target, its test, or an import site; flag files outside the plan, work the plan's Scope marks Out or [DEFERRED], new dependencies no component requires, and unrequested abstractions — report drift only in scope; it does not change status). Prefer changed files over broad scanning.
197
+ Checks — only whether the plan was built and works; code quality and correctness belong to /5:review, which runs next: completeness (every planned component done, and any acceptance criteria the plan states addressed); files exist for create/modify, rename moved correctly, delete removed; build + test pass (reuse the baseline and component results above when they already prove status — rerun only the commands whose inputs changed, not identical passing ones); scope (run \`git status --short\` and \`git diff HEAD --stat\`, and read untracked files directly since \`git diff HEAD\` omits them: every changed file traces to a planned component — its target, its test, an import site, or a file a repository standard requires (such as a changelog entry); flag files outside the plan, work the plan rules out or defers, new dependencies no component requires, and unrequested abstractions — report drift only in scope; it does not change status). Prefer changed files over broad scanning.
194
198
 
195
- Return structured output: status, completeness, infrastructure, acceptanceCriteria ("satisfied/total"), quality, scope, commands[], failures[] (one "drift: {path} — {why}" entry per drift finding).`
199
+ Return structured output: status, completeness, infrastructure, acceptanceCriteria ("satisfied/total"), scope, commands[], failures[] (one "drift: {path} — {why}" entry per drift finding).`
196
200
  }
197
201
 
198
202
  // ── Helpers ──────────────────────────────────────────────────────────────────
199
203
 
200
- // Build a single trivial step in JS for compact plans (no orchestrator agent).
201
- function compactSteps(components) {
202
- const norm = components.map((c, i) => ({
203
- name: c.name,
204
- action: c.action || 'modify',
205
- step: 1,
206
- mode: 'parallel',
207
- model: c.model || 'haiku',
208
- file: c.file,
209
- sourceFile: c.sourceFile || null,
210
- description: c.description || '',
211
- dependsOn: c.dependsOn || [],
212
- patternRefs: c.patternRefs || [],
213
- verifyCommands: c.verifyCommands || [],
214
- notes: []
215
- }))
216
- // If two components write the same file or one depends on another, fall back to sequential.
217
- const files = norm.map(c => c.file)
218
- const fileConflict = new Set(files).size !== files.length
219
- const hasDep = norm.some(c => c.dependsOn && c.dependsOn.length)
220
- const mode = (fileConflict || hasDep) ? 'sequential' : 'parallel'
221
- norm.forEach(c => { c.mode = mode })
222
- const stepModel = norm.some(c => c.model === 'sonnet') ? 'sonnet' : 'haiku'
223
- return {
224
- steps: [{ number: 1, name: 'implement', mode, model: stepModel, components: norm.map(c => c.name) }],
225
- pendingComponents: norm
226
- }
204
+ // Model options per tier. Opus runs at medium effort: deep enough for complex work, cheaper than high.
205
+ function modelOpts(model) {
206
+ return model === 'opus' ? { model: 'opus', effort: 'medium' } : { model: model || 'haiku' }
227
207
  }
228
208
 
229
209
  async function runStep(step, components, a) {
@@ -234,28 +214,28 @@ async function runStep(step, components, a) {
234
214
  if (step.mode === 'parallel' && stepComps.length > 1) {
235
215
  // Fire every parallel component together — true concurrency, one wave.
236
216
  waveResults = await parallel(stepComps.map(c => () =>
237
- agent(executorPrompt(c, a), { label: `exec:${c.name}`, phase: 'Execute', model: c.model || 'haiku', schema: RESULT_SCHEMA })
217
+ agent(executorPrompt(c, a), { label: `exec:${c.name}`, phase: 'Execute', ...modelOpts(c.model), schema: RESULT_SCHEMA })
238
218
  .then(result => ({ component: c, result }))
239
219
  .catch(() => ({ component: c, result: null }))))
240
220
  } else {
241
221
  waveResults = []
242
222
  for (const c of stepComps) {
243
- const result = await agent(executorPrompt(c, a), { label: `exec:${c.name}`, phase: 'Execute', model: c.model || 'haiku', schema: RESULT_SCHEMA })
223
+ const result = await agent(executorPrompt(c, a), { label: `exec:${c.name}`, phase: 'Execute', ...modelOpts(c.model), schema: RESULT_SCHEMA })
244
224
  .catch(() => null)
245
225
  waveResults.push({ component: c, result })
246
226
  }
247
227
  }
248
228
 
249
- // Retry failed OR crashed (null) components up to twice, escalating to sonnet.
229
+ // Retry failed OR crashed (null) components up to twice, escalating to opus.
250
230
  // A crashed agent (null result) is retried too — an infra error should not be
251
231
  // treated more harshly than a clean structured failure.
252
232
  for (const wr of waveResults) {
253
233
  let attempt = 1
254
234
  while ((wr.result == null || wr.result.status === 'failed') && attempt <= 2) {
255
- log(`retry ${wr.component.name} (attempt ${attempt + 1}) on sonnet`)
235
+ log(`retry ${wr.component.name} (attempt ${attempt + 1}) on opus`)
256
236
  wr.escalated = true
257
237
  const retried = await agent(executorPrompt(wr.component, a, { retry: true }),
258
- { label: `retry:${wr.component.name}`, phase: 'Execute', model: 'sonnet', schema: RESULT_SCHEMA }).catch(() => null)
238
+ { label: `retry:${wr.component.name}`, phase: 'Execute', ...modelOpts('opus'), schema: RESULT_SCHEMA }).catch(() => null)
259
239
  if (retried) wr.result = retried
260
240
  attempt++
261
241
  }
@@ -267,35 +247,25 @@ async function runStep(step, components, a) {
267
247
  // ── Main ─────────────────────────────────────────────────────────────────────
268
248
 
269
249
  const a = args || {}
270
- const resumeDone = new Set(a.completedComponents || [])
271
250
 
272
251
  phase('Orchestrate')
273
- if (resumeDone.size) log(`resume: ${resumeDone.size} component(s) already complete, matched by name`)
274
- let plan
275
- if (a.isCompact && Array.isArray(a.components) && a.components.length) {
276
- log(`compact plan: ${a.components.length} component(s), no orchestrator agent`)
277
- plan = compactSteps(a.components)
278
- } else {
279
- plan = await agent(orchestratorPrompt(a), { label: 'orchestrate', phase: 'Orchestrate', schema: STATE_SCHEMA })
280
- }
252
+ const plan = await agent(orchestratorPrompt(a), { label: 'orchestrate', phase: 'Orchestrate', schema: STATE_SCHEMA })
281
253
  const steps = plan.steps
282
254
  const components = plan.pendingComponents
283
255
 
284
256
  phase('Execute')
285
257
  const results = []
286
258
  for (const step of steps) {
287
- const remaining = components.filter(c => step.components.includes(c.name) && !resumeDone.has(c.name))
288
- if (!remaining.length) { log(`step ${step.number} already complete (resume), skipping`); continue }
289
- const stepResult = await runStep({ ...step, components: remaining.map(c => c.name) }, components, a)
290
- results.push(stepResult)
259
+ results.push(await runStep(step, components, a))
291
260
  }
292
261
 
293
262
  phase('Verify')
294
263
  const allItems = results.flatMap(s => s.items)
295
264
  const allPassed = allItems.length > 0 && allItems.every(i => i.result && i.result.status === 'success' && i.result.verify !== 'failed')
296
- // Non-mechanical when a component was planned as sonnet OR needed a sonnet retry to pass —
297
- // either signals reasoning-level work that warrants the full verification agent.
298
- const usedSonnet = components.some(c => (c.model || 'haiku') === 'sonnet') || allItems.some(i => i.escalated)
265
+ // Mechanical when every component was planned as haiku and none needed a retry; anything
266
+ // else signals reasoning-level work that warrants the full verification agent.
267
+ const usedOpus = components.some(c => c.model === 'opus') || allItems.some(i => i.escalated)
268
+ const mechanical = !usedOpus && components.every(c => (c.model || 'haiku') === 'haiku')
299
269
  // Deterministic scope signal: files an executor touched beyond its planned target(s).
300
270
  // Tests and import sites are legitimate, so this is reported for the user, never a failure.
301
271
  const extraFiles = allItems.flatMap(i => {
@@ -306,29 +276,21 @@ const extraFiles = allItems.flatMap(i => {
306
276
  })
307
277
  if (extraFiles.length) log(`scope: ${extraFiles.length} file(s) touched outside planned targets`)
308
278
  let verification
309
- if (allPassed && !usedSonnet) {
310
- log('all components passed + mechanical (no sonnet, no escalation) — inline verify, no verification agent')
311
- // No git access here: /5:implement runs the fast-path scope check itself when it sees inline: true.
312
- verification = { status: 'passed', completeness: 'passed', infrastructure: 'passed', acceptanceCriteria: 'n/a', quality: 'passed', commands: [], failures: [], inline: true }
279
+ if (allPassed && mechanical) {
280
+ log('all components passed + mechanical — no verification agent; /5:implement runs build/test and the scope check')
281
+ // No shell access here: /5:implement runs build/test and the scope check itself when it sees inline: true.
282
+ verification = { status: 'passed', completeness: 'passed', infrastructure: 'passed', acceptanceCriteria: 'n/a', commands: [], failures: [], inline: true }
313
283
  } else {
314
- if (!allItems.length) log('no components ran this invocation (resume) — verifying the already-completed feature against the plan')
315
- verification = await agent(verifyPrompt(a, results, resumeDone), {
316
- label: 'verify', phase: 'Verify', model: usedSonnet ? 'sonnet' : 'haiku', schema: VERIFICATION_SCHEMA
284
+ verification = await agent(verifyPrompt(a, results), {
285
+ label: 'verify', phase: 'Verify', ...modelOpts(usedOpus ? 'opus' : 'sonnet'), schema: VERIFICATION_SCHEMA
317
286
  })
318
287
  }
319
288
 
320
- // Union prior + newly-succeeded so the command can MERGE (not replace) completed history on resume.
321
- const newlyCompleted = allItems.filter(i => i.result && i.result.status === 'success').map(i => i.component.name)
322
- const completedComponents = [...new Set([...resumeDone, ...newlyCompleted])]
323
-
324
- // Returned to the /5:implement command, which persists the slim state.json and auto-commits.
325
- // steps + components are returned for reporting and per-step staging only — they are NOT persisted;
326
- // the next run re-derives them, and resume matches on completedComponents by name.
289
+ // Returned to the /5:implement command for the fast-path check, per-step staging, and the report.
327
290
  return {
328
291
  feature: a.feature,
329
292
  steps,
330
293
  components,
331
- completedComponents,
332
294
  results: results.map(s => ({
333
295
  step: s.step,
334
296
  name: s.name,