compound-workflow 1.4.3 → 1.4.5

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.
package/README.md CHANGED
@@ -1,193 +1,84 @@
1
- # Compound Workflow (.agents)
1
+ # Compound Workflow
2
2
 
3
- A portable, command-first workflow: **clarify plan execute verify → capture**. Commands are the public API; skills and agents are composable internals.
3
+ Compound Workflow is a portable, command-first system for shipping software with less ambiguity and stronger verification.
4
+ It follows a simple cycle: **clarify -> plan -> execute -> verify -> capture**.
5
+ Use it when you want repeatable delivery without ad-hoc process drift.
4
6
 
5
- It reduces delivery failures from **unclear intent**, **weak verification**, and **lost context**. Use it when you want structured cycles without ad-hoc tooling.
7
+ Inspired by [Compound Engineering](https://every.to/guides/compound-engineering) (Every).
6
8
 
7
- *This template and README are continually refined during development.*
9
+ Best fit when you need:
8
10
 
9
- Inspired by [Compound Engineering](https://every.to/guides/compound-engineering) (Every) the AI-native philosophy that each unit of work should compound into the next.
11
+ - Clear intent and acceptance criteria before coding
12
+ - Structured execution with explicit review gates
13
+ - A repeatable process that captures reusable learnings
10
14
 
11
- Runtime assets live in `src/.agents/` and `src/AGENTS.md`. Supports **Cursor**, **Claude**, and **OpenCode** via one Install action per project.
15
+ ## Workflow
12
16
 
13
- ---
14
-
15
- ## Get started
16
-
17
- **1. Add the package and run Install** (in the project where you want the workflow):
18
-
19
- ```bash
20
- npm install compound-workflow
21
- npx compound-workflow install
22
- npx compound-workflow install all
23
- ```
24
-
25
- **2. Choose how you use it:**
26
-
27
- - **Cursor:** If your project already has a `.cursor` directory, Install will create the correct structure: one symlink per skill under `.cursor/skills/`, plus `.cursor/agents`, `.cursor/commands`, and `.cursor/references` (each symlinked to the package). No plugin needed. Use the plugin from this repo if you need a different loading method.
28
- - **OpenCode:** Install writes `opencode.json` and a symlink at `.agents/compound-workflow-skills`; OpenCode loads from the package. Run `/install` or `npx compound-workflow install` in the project.
29
- - **Claude:** Add the compound-workflow plugin from this repo. In any repo, run `/install` or the CLI above.
30
-
31
- **What Install does:** Merges `AGENTS.md` (preserves your Repo Config Block), creates standard dirs (`docs/`, `todos/`), writes `opencode.json` (for OpenCode), and—if the project has a `.cursor` directory—creates `.cursor/skills/<skill>`, `.cursor/agents`, `.cursor/commands`, and `.cursor/references` (symlinks into the package). All paths reference `node_modules/compound-workflow`; no file copying.
32
-
33
- **CLI options:** `all` / `--all` (full install shortcut; same as `--cursor`), `--dry-run` (preview), `--root /path/to/project`, `--no-config` (skip Repo Config Block reminder), `--cursor` (create `.cursor` and wire Cursor symlinks even if `.cursor` does not already exist).
34
-
35
- **Legacy (clone inside repo):** If you cloned this repo inside a host repo and need to copy files without npm, use `./scripts/sync-into-repo.sh` (copy only; does not update opencode.json). Prefer the npm + Install flow above.
36
-
37
- To update to a new release, see [Updating compound-workflow](#updating-compound-workflow).
38
-
39
- ---
40
-
41
- ## Updating compound-workflow
42
-
43
- - **Cursor (plugin):** If you load the plugin from this repo, pull latest and reload the plugin in Cursor.
44
- - **Cursor (npm + .cursor):** Run `npm update compound-workflow`, then run **Install** again (`npx compound-workflow install`) to refresh the `.cursor/skills`, `.cursor/agents`, `.cursor/commands`, and `.cursor/references` symlinks and AGENTS.md.
45
- - **OpenCode / npm:** Run `npm update compound-workflow` (or bump the version in `package.json` and `npm install`), then run **Install** again. This refreshes `opencode.json`, merges the latest `AGENTS.md` template, and ensures dirs exist; Repo Config Block is preserved.
46
- - **Claude (plugin):** Update via the editor’s plugin; if from repo, pull latest and reload.
47
-
48
- ---
49
-
50
- ## Workflow at a glance
51
-
52
- Clarify what to build -> plan how (fidelity + confidence) -> triage todos -> execute -> review -> capture learnings -> log and assess.
17
+ The workflow turns a request into validated output and reusable team knowledge.
53
18
 
54
19
  ```mermaid
55
20
  flowchart LR
56
- A["brainstorm"] --> B["plan"] --> C["triage"] --> D["work"] --> E["review"] --> F["capture"] --> G["metrics"]
21
+ A["brainstorm"] --> B["plan"] --> C["work (includes triage)"] --> D["review"] --> E["capture"] --> F["metrics"]
57
22
  ```
58
23
 
59
- ---
60
-
61
- If docs conflict: follow [docs/principles/workflow-baseline-principles.md](docs/principles/workflow-baseline-principles.md), then [src/AGENTS.md](src/AGENTS.md), then command docs under [src/.agents/commands/](src/.agents/commands/).
62
-
63
- ---
64
-
65
- ## Step-by-step: intent and commands
66
-
67
- | Step | Intent | Command | Output / note |
68
- |------|--------|---------|---------------|
69
- | Clarify what to build | Dialogue only; no code | `/workflow:brainstorm [topic]` | `docs/brainstorms/` |
70
- | Define how (fidelity + confidence) | Plan only; no code; include agentic access + validation contract | `/workflow:plan [description or brainstorm path]` | `docs/plans/` |
71
- | Ready the queue | Priority/dependencies + executable agentic contract checks for pending todos | `/workflow:triage` | — |
72
- | Execute | File-based todos; risk-tier testing; evidence-backed implementation; no auto-ship | `/workflow:work <plan-path>` | `todos/` |
73
- | Validate quality | Independent, evidence-based review for code/config changes (docs-only exempt); no fixes by default | `/workflow:review [PR, branch, or current]` | pass / pass-with-notes / fail |
74
- | Capture learnings | One solution doc for future use | `/workflow:compound [context]` | `docs/solutions/` |
75
- | Log and improve | Session log + optional aggregate review | `/metrics` + `/assess weekly 7` (or monthly) | `docs/metrics/daily/`, weekly/monthly |
76
-
77
- #### 1. Clarify (brainstorm)
78
-
79
- **Intent:** Dialogue only; no code. **Command:** `/workflow:brainstorm [topic]`. **Output:** `docs/brainstorms/`.
80
-
81
- #### 2. Define how (plan)
82
-
83
- **Intent:** Plan only; no code; fidelity + confidence; include an agentic access + validation contract. **Command:** `/workflow:plan [description or brainstorm path]`. **Output:** `docs/plans/`.
84
-
85
- #### 3. Ready the queue (triage)
86
-
87
- **Intent:** Priority/dependencies for pending todos and readiness checks for agentic executability. **Command:** `/workflow:triage`. **Output:** —.
88
-
89
- #### 4. Execute (work)
90
-
91
- **Intent:** File-based todos; risk-tier testing; success-criteria evidence + quality gates before completion; no auto-ship. **Command:** `/workflow:work <plan-path>`. **Output:** `todos/`.
92
-
93
- `/workflow:work` must not run until `/workflow:triage` has approved executable ready todos.
24
+ ## Get Started
94
25
 
95
- For code/config changes, `/workflow:work` ends at implementation-complete and requires `/workflow:review` before workflow completion. Docs-only work can close without `/workflow:review`.
96
-
97
- #### 5. Validate quality (review)
98
-
99
- **Intent:** Independent, evidence-based review with explicit independence mode (`independent|degraded`) and evidence disclosure; no fixes by default. **Command:** `/workflow:review [PR|branch|current]`. **Output:** pass / pass-with-notes / fail.
100
-
101
- #### 6. Capture learnings (compound)
102
-
103
- **Intent:** One solution doc for future use. **Command:** `/workflow:compound [context]`. **Output:** `docs/solutions/`.
104
-
105
- #### 7. Log and improve
106
-
107
- **Intent:** Session log + optional aggregate review. **Command:** `/metrics` + `/assess weekly 7` (or monthly). **Output:** `docs/metrics/daily/`, weekly/monthly.
108
-
109
- **Optional QA:** **`/test-browser [PR|branch|current]`** — Browser validation on affected pages via **agent-browser CLI only** (not MCP). Install: `npm install -g agent-browser` then `agent-browser install`. See [src/.agents/commands/test-browser.md](src/.agents/commands/test-browser.md).
110
-
111
- ---
112
-
113
- ## Command reference
114
-
115
- **Onboarding:** `/install` — one action: merges AGENTS.md, creates dirs, preserves Repo Config Block; writes opencode.json (OpenCode) and, if present, symlinks into `.cursor/skills/` (Cursor). Run `npx compound-workflow install` in the project (requires `npm install compound-workflow`). Re-run after `npm update compound-workflow` to refresh config; see [Updating compound-workflow](#updating-compound-workflow).
116
-
117
- **Core workflow:** See [Step-by-step](#step-by-step-intent-and-commands) above.
118
-
119
- **QA:** `/test-browser [PR|branch|current]` — browser checks on affected routes (agent-browser CLI only).
120
-
121
- **Improvement:** `/metrics [plan|todo|pr|solution|label]` — log session to `docs/metrics/daily/` and assess. `/assess [daily|weekly|monthly] [count]` — aggregate metrics and optional summary files.
122
-
123
- **Experimental:** `/workflow:review-v2 [PR|branch|current]` — interactive snippet review; output-only (no GitHub publish).
124
-
125
- Full detail: [src/AGENTS.md](src/AGENTS.md), [src/.agents/commands/](src/.agents/commands/).
126
-
127
- ---
128
-
129
- ## Artifacts
130
-
131
- - **Brainstorms:** `docs/brainstorms/YYYY-MM-DD-<topic>-brainstorm.md`
132
- - **Plans:** `docs/plans/YYYY-MM-DD-<type>-<slug>-plan.md`
133
- - **Todos:** `todos/{id}-{status}-{priority}-{slug}.md`
134
- - **Solutions:** `docs/solutions/<category>/YYYY-MM-DD-<module-slug>-<symptom-slug>.md`
135
- - **Metrics:** `docs/metrics/daily/YYYY-MM-DD.md`, `docs/metrics/weekly/YYYY-WW.md`, `docs/metrics/monthly/YYYY-MM.md`
136
-
137
- ---
138
-
139
- ## How it works (internals)
140
-
141
- Commands are the public API. Skills and agents are invoked by commands; you don’t call them directly.
142
-
143
- - **Workflow skills:** `brainstorming`, `file-todos`, `compound-docs`, `document-review`, `technical-review`, `git-worktree`, `agent-browser`, `process-metrics`, `react-ddd-mvc-frontend`, `xstate-actor-orchestration`, `standards`.
144
- - **State orchestration:** Use a state-orchestration skill when complexity exceeds simple local state (e.g. `xstate-actor-orchestration` per Skill Index)—UI container-as-orchestrator flows, backend/internal actor orchestration, receptionist/child-actor patterns, retries/timeouts/cancellation, or boolean-flag sprawl.
145
- - **Skill-local metadata:** Some skills may include tool-specific metadata under `src/.agents/skills/<skill>/agents/` (for example `openai.yaml`) when required by skill validation/runtime.
146
- - **Guardrail standards:** `data-foundations`, `pii-protection-prisma`, `financial-workflow-integrity`, `audit-traceability` — applied when work touches multi-tenant data, PII, money, or audit.
147
- - **Agents:** Used by plan, review, and work for research, lint, and validation (e.g. `repo-research-analyst`, `learnings-researcher`, `git-history-analyzer`, `agent-native-reviewer`, `planning-technical-reviewer`).
148
-
149
- Full “when to use what” and reference standards: [src/AGENTS.md](src/AGENTS.md).
150
-
151
- ---
152
-
153
- ## Guardrails
154
-
155
- - **No auto-ship:** `/workflow:work` and `/workflow:review` do not commit, push, or create PRs by default.
156
-
157
- - **Brainstorm and plan do not write code.** Output is documents only.
26
+ ```bash
27
+ npm install compound-workflow
28
+ ```
158
29
 
159
- - **Todo completion requires evidence:** acceptance/success criteria plus quality gates must be recorded before `complete`.
30
+ `npm install` adds the package and automatically configures your repo (`AGENTS.md`, required directories, and runtime wiring).
31
+ If your package manager skips lifecycle scripts, run `npx compound-workflow install` manually.
160
32
 
161
- - **Independent review policy:** code/config changes require `/workflow:review` before workflow completion; docs-only changes are exempt.
33
+ Install configures:
162
34
 
163
- - **Standards baseline policy:** code/config changes must pass `skill: standards` as a hard gate (declarative flow, immutable transforms, maintainability boundaries) in both `/workflow:work` and `/workflow:review`; docs-only changes are exempt.
35
+ - Workflow template content in `AGENTS.md`
36
+ - Standard workspace directories for plans/todos/docs
37
+ - Runtime configuration used by supported tools
164
38
 
165
- - **Quality gate fallback:** if `lint_command` or `typecheck_command` is missing from repo config, workflow asks once for run-provided commands and continues only if they pass.
39
+ ## Critical Path
166
40
 
167
- - **Artifact policy:** do not create ad-hoc artifacts outside canonical outputs (`docs/plans`, `todos`, `docs/solutions`, `docs/metrics`) unless explicitly requested.
41
+ After install, use this default sequence:
168
42
 
169
- - Add a separate shipping command if you want automated commit/PR and quality gates.
43
+ 1. `/workflow:brainstorm` for requirements clarity
44
+ 2. `/workflow:plan` for implementation design
45
+ 3. `/workflow:work` to execute against the approved plan (includes automatic triage)
46
+ 4. `/workflow:review` to validate quality before completion
47
+ 5. `/workflow:compound` to capture reusable learnings
170
48
 
171
- ---
49
+ Optional:
172
50
 
173
- ## Troubleshooting
51
+ - `/workflow:triage` for manual backlog curation before or during execution
52
+ - `/metrics` and `/assess` for process improvement
174
53
 
175
- **Skills not showing in Cursor?** Cursor discovers skills from (1) the plugin’s `skills/` directory when you load the plugin from this repo, or (2) the project’s `.cursor/skills/` when you use npm: ensure the project has a `.cursor` directory and run `npx compound-workflow install`—Install creates the full structure (`.cursor/skills/<skill>`, `.cursor/agents`, `.cursor/commands`, `.cursor/references`). If skills still don’t appear, check Cursor Settings → Rules and any `permission.skill` settings.
54
+ ## Commands (Quick Map)
176
55
 
177
- If your project does not already have `.cursor/`, run `npx compound-workflow install --cursor` to create it and wire links. Install now fails fast when existing non-symlink files/directories block `.cursor` link creation, to prevent partial installs and command drift.
56
+ Core flow: `/workflow:brainstorm` -> `/workflow:plan` -> `/workflow:work` -> `/workflow:review` -> `/workflow:compound` -> `/metrics` (optional `/assess` for rollups).
178
57
 
179
- **Skills not showing in OpenCode?** OpenCode uses the `.agents/compound-workflow-skills` symlink and `opencode.json` `skills.paths`. Run Install from the project root (`npx compound-workflow install`). The learnings-capture skill is named **compound-docs** (hyphen, plural); **compound_doc** (underscore) is an alias that resolves to the same skill.
58
+ | Command | Purpose | Related skills | Related agents |
59
+ |---|---|---|---|
60
+ | `/install` | Configure workflow files and runtime wiring in the repo | install CLI (no workflow skill routing) | none |
61
+ | `/workflow:brainstorm` | Clarify what to build through structured discussion | `brainstorming` (primary), `document-review` (optional refinement) | `repo-research-analyst` |
62
+ | `/workflow:plan` | Convert intent into an executable plan with fidelity/confidence | state-orchestration skill when needed (for example `xstate-actor-orchestration`) | `repo-research-analyst`, `learnings-researcher`, `best-practices-researcher`, `framework-docs-researcher`, `git-history-analyzer`, `spec-flow-analyzer`, `planning-technical-reviewer` |
63
+ | `/workflow:triage` | Manual queue curation for complex/multi-item backlogs (optional; `/workflow:work` runs triage automatically) | `file-todos` | none |
64
+ | `/workflow:work` | Execute plan/todos with quality gates and validation evidence | `git-worktree`, `file-todos`, `standards`, state-orchestration skill when needed | `repo-research-analyst`, `learnings-researcher`, `best-practices-researcher`, `framework-docs-researcher`, `git-history-analyzer` |
65
+ | `/workflow:review` | Perform independent quality review before completion | `git-worktree` (for non-current targets), `standards` | `learnings-researcher`, `lint`, `bug-reproduction-validator`, `git-history-analyzer`, `framework-docs-researcher`, `agent-native-reviewer` |
66
+ | `/workflow:compound` | Capture reusable implementation learnings in `docs/solutions/` | `compound-docs` (primary), `document-review` (optional) | `learnings-researcher`, `best-practices-researcher`, `framework-docs-researcher` |
67
+ | `/metrics` | Log session outcomes and improvement actions | `process-metrics`, `file-todos` (optional for follow-ups) | none |
68
+ | `/assess` | Aggregate metrics trends and propose process improvements | `file-todos` (for approved follow-up actions) | none |
69
+ | `/test-browser` | Validate affected routes with browser-level checks | `agent-browser`, `git-worktree` (optional branch isolation) | none |
180
70
 
181
- ---
71
+ Canonical command docs: [src/.agents/commands/](src/.agents/commands/)
182
72
 
183
- ## Configuration and optional bits
73
+ ## Learn More
184
74
 
185
- **Repo configuration:** Commands read a **Repo Config Block** (YAML) in `AGENTS.md` for `default_branch`, `dev_server_url`, `test_command`, `lint_command`, `typecheck_command`, etc. Run **`/install`** once; then edit `AGENTS.md` to set the Repo Config Block.
75
+ - Workflow principles: [docs/principles/workflow-baseline-principles.md](docs/principles/workflow-baseline-principles.md)
76
+ - Project command and policy index: [src/AGENTS.md](src/AGENTS.md)
77
+ - Command definitions: [src/.agents/commands/](src/.agents/commands/)
186
78
 
187
- **agent-browser:** `/test-browser` uses the agent-browser CLI only. Install: `npm install -g agent-browser` then `agent-browser install`. See [src/.agents/commands/test-browser.md](src/.agents/commands/test-browser.md).
79
+ If docs conflict: follow `docs/principles/workflow-baseline-principles.md`, then `src/AGENTS.md`, then command docs.
188
80
 
189
- **Source of truth**
81
+ Guardrails:
190
82
 
191
- - Workflows and commands: [src/.agents/](src/.agents/)
192
- - Baseline principles (tie-breaker): [docs/principles/workflow-baseline-principles.md](docs/principles/workflow-baseline-principles.md)
193
- - Principles and skill index: [src/AGENTS.md](src/AGENTS.md)
83
+ - Independent review policy: code/config changes require `/workflow:review` before workflow completion (docs-only changes are exempt).
84
+ - Standards baseline policy: code/config changes must pass the standards baseline gate in `/workflow:work` and `/workflow:review`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compound-workflow",
3
- "version": "1.4.3",
3
+ "version": "1.4.5",
4
4
  "description": "Clarify → plan → execute → verify → capture. One Install action for Cursor, Claude, and OpenCode.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -18,7 +18,9 @@
18
18
  "skills"
19
19
  ],
20
20
  "scripts": {
21
- "check:pack-readme": "node scripts/check-pack-readme.mjs"
21
+ "postinstall": "node scripts/postinstall.mjs",
22
+ "check:pack-readme": "node scripts/check-pack-readme.mjs",
23
+ "test:install": "node --test tests/install-cli.test.mjs"
22
24
  },
23
25
  "engines": {
24
26
  "node": ">=18"
@@ -11,6 +11,16 @@ const requiredChecks = [
11
11
  pattern: "tie-breaker",
12
12
  description: "baseline principles tie-breaker rule",
13
13
  },
14
+ {
15
+ file: "docs/principles/workflow-baseline-principles.md",
16
+ pattern: "/workflow:work` - implement in isolation with evidence (includes required triage gate)",
17
+ description: "canonical flow routes triage through work by default",
18
+ },
19
+ {
20
+ file: "docs/principles/workflow-baseline-principles.md",
21
+ pattern: "Optional manual command:",
22
+ description: "principles preserve standalone manual triage command",
23
+ },
14
24
  {
15
25
  file: "src/AGENTS.md",
16
26
  pattern: "## Contract Precedence",
@@ -33,12 +43,18 @@ const requiredChecks = [
33
43
  },
34
44
  {
35
45
  file: "README.md",
36
- pattern: "code/config changes require `/workflow:review`",
46
+ anyOf: [
47
+ "code/config changes require `/workflow:review`",
48
+ "Independent review policy:",
49
+ ],
37
50
  description: "README review gate policy",
38
51
  },
39
52
  {
40
53
  file: "README.md",
41
- pattern: "Standards baseline policy:",
54
+ anyOf: [
55
+ "Standards baseline policy:",
56
+ "standards baseline gate",
57
+ ],
42
58
  description: "README standards baseline guardrail",
43
59
  },
44
60
  {
@@ -51,16 +67,36 @@ const requiredChecks = [
51
67
  pattern: "Contract precedence:",
52
68
  description: "triage command precedence note",
53
69
  },
70
+ {
71
+ file: "src/.agents/commands/workflow/triage.md",
72
+ pattern: "independently runnable",
73
+ description: "triage command explicitly standalone while work auto-runs triage",
74
+ },
54
75
  {
55
76
  file: "src/.agents/commands/workflow/work.md",
56
77
  pattern: "Contract precedence:",
57
78
  description: "work command precedence note",
58
79
  },
80
+ {
81
+ file: "src/.agents/commands/workflow/plan.md",
82
+ pattern: "Start `/workflow:work`",
83
+ description: "plan command default next-step routes to work",
84
+ },
59
85
  {
60
86
  file: "src/.agents/commands/workflow/work.md",
61
87
  pattern: "HARD GATE - WORKTREE FIRST",
62
88
  description: "worktree hard-gate wording in work command",
63
89
  },
90
+ {
91
+ file: "src/.agents/commands/workflow/work.md",
92
+ pattern: "required prompt/create gate",
93
+ description: "mandatory worktree decision prompt/create gate in work command",
94
+ },
95
+ {
96
+ file: "src/.agents/commands/workflow/work.md",
97
+ pattern: "Do not infer or assume an answer when the user has not answered.",
98
+ description: "worktree decision cannot be silently assumed",
99
+ },
64
100
  {
65
101
  file: "src/.agents/commands/workflow/work.md",
66
102
  pattern:
@@ -160,7 +196,11 @@ const readFile = (relativePath) => {
160
196
 
161
197
  for (const check of requiredChecks) {
162
198
  const contents = readFile(check.file);
163
- if (!contents.includes(check.pattern)) {
199
+ const hasPattern = check.pattern ? contents.includes(check.pattern) : false;
200
+ const hasAnyOf = Array.isArray(check.anyOf)
201
+ ? check.anyOf.some((pattern) => contents.includes(pattern))
202
+ : false;
203
+ if (!hasPattern && !hasAnyOf) {
164
204
  failures.push(`Missing required contract text (${check.description}) in ${check.file}`);
165
205
  }
166
206
  }
@@ -14,29 +14,32 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
14
  function usage(exitCode = 0) {
15
15
  const msg = `
16
16
  Usage:
17
- npx compound-workflow install [all|--all] [--root <projectDir>] [--dry-run] [--no-config] [--cursor]
17
+ npx compound-workflow install [all|--all] [--root <projectDir>] [--dry-run] [--no-config]
18
18
 
19
19
  One action: writes opencode.json (loads from package), merges AGENTS.md, creates dirs,
20
20
  and prompts for Repo Config Block (unless --no-config).
21
21
 
22
- all, --all Full install shortcut (enables Cursor integration; creates .cursor if needed)
22
+ all, --all Kept for compatibility
23
23
  --root <dir> Project directory (default: cwd)
24
24
  --dry-run Print planned changes only
25
25
  --no-config Skip Repo Config Block prompt (only write opencode.json + AGENTS.md + dirs)
26
- --cursor Force Cursor integration (create .cursor if missing, then wire links)
27
26
  `;
28
27
  (exitCode === 0 ? console.log : console.error)(msg.trimStart());
29
28
  process.exit(exitCode);
30
29
  }
31
30
 
32
31
  function parseArgs(argv) {
33
- const out = { root: process.cwd(), dryRun: false, noConfig: false, cursor: false };
32
+ const out = { root: process.cwd(), dryRun: false, noConfig: false };
34
33
  for (let i = 2; i < argv.length; i++) {
35
34
  const a = argv[i];
36
35
  if (a === "--dry-run") out.dryRun = true;
37
36
  else if (a === "--no-config") out.noConfig = true;
38
- else if (a === "--cursor") out.cursor = true;
39
- else if (a === "--all" || a === "all") out.cursor = true;
37
+ else if (a === "--cursor") {
38
+ // Deprecated compatibility alias; install now auto-detects .cursor.
39
+ }
40
+ else if (a === "--all" || a === "all") {
41
+ // Deprecated compatibility alias; install now auto-detects .cursor.
42
+ }
40
43
  else if (a === "--root") {
41
44
  const v = argv[i + 1];
42
45
  if (!v) usage(1);
@@ -58,7 +61,10 @@ function realpathSafe(p) {
58
61
 
59
62
  const packageRoot = realpathSafe(path.join(__dirname, ".."));
60
63
  const packageAgents = path.join(packageRoot, "src", ".agents");
61
- const PKG_PREFIX = "node_modules/compound-workflow";
64
+ const LOCAL_RUNTIME_ROOT = ".agents/compound-workflow";
65
+ const LOCAL_COMMANDS_ROOT = `${LOCAL_RUNTIME_ROOT}/commands`;
66
+ const LOCAL_AGENTS_ROOT = `${LOCAL_RUNTIME_ROOT}/agents`;
67
+ const LOCAL_REFERENCES_ROOT = `${LOCAL_RUNTIME_ROOT}/references`;
62
68
 
63
69
  function walkFiles(dirAbs, predicate) {
64
70
  const out = [];
@@ -101,14 +107,14 @@ function discoverCommands(agentsRoot) {
101
107
  const files = walkFiles(commandsDir, (p) => p.endsWith(".md"));
102
108
  const map = new Map();
103
109
  for (const fileAbs of files) {
104
- const rel = path.relative(packageRoot, fileAbs).replaceAll(path.sep, "/");
110
+ const relWithinCommands = path.relative(commandsDir, fileAbs).replaceAll(path.sep, "/");
105
111
  const md = fs.readFileSync(fileAbs, "utf8");
106
112
  const fm = parseFrontmatter(md);
107
113
  const id = (fm.invocation || fm.name || path.basename(fileAbs, ".md")).trim();
108
114
  const description = (fm.description || id).trim();
109
115
  if (!id) continue;
110
- const pkgRel = `${PKG_PREFIX}/${rel}`;
111
- map.set(id, { id, rel: pkgRel, description });
116
+ const localRel = `${LOCAL_COMMANDS_ROOT}/${relWithinCommands}`;
117
+ map.set(id, { id, rel: localRel, description });
112
118
  }
113
119
  return map;
114
120
  }
@@ -118,18 +124,65 @@ function discoverAgents(agentsRoot) {
118
124
  const files = walkFiles(agentsDir, (p) => p.endsWith(".md"));
119
125
  const map = new Map();
120
126
  for (const fileAbs of files) {
121
- const rel = path.relative(packageRoot, fileAbs).replaceAll(path.sep, "/");
127
+ const relWithinAgents = path.relative(agentsDir, fileAbs).replaceAll(path.sep, "/");
122
128
  const md = fs.readFileSync(fileAbs, "utf8");
123
129
  const fm = parseFrontmatter(md);
124
130
  const id = (fm.name || path.basename(fileAbs, ".md")).trim();
125
131
  const description = (fm.description || id).trim();
126
132
  if (!id) continue;
127
- const pkgRel = `${PKG_PREFIX}/${rel}`;
128
- map.set(id, { id, rel: pkgRel, description });
133
+ const localRel = `${LOCAL_AGENTS_ROOT}/${relWithinAgents}`;
134
+ map.set(id, { id, rel: localRel, description });
129
135
  }
130
136
  return map;
131
137
  }
132
138
 
139
+ function copyDirContents(sourceDir, targetDir) {
140
+ if (!fs.existsSync(sourceDir)) return;
141
+ fs.mkdirSync(targetDir, { recursive: true });
142
+ const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
143
+ for (const entry of entries) {
144
+ const src = path.join(sourceDir, entry.name);
145
+ const dst = path.join(targetDir, entry.name);
146
+ if (entry.isDirectory()) {
147
+ copyDirContents(src, dst);
148
+ continue;
149
+ }
150
+ if (entry.isFile()) {
151
+ fs.mkdirSync(path.dirname(dst), { recursive: true });
152
+ fs.copyFileSync(src, dst);
153
+ }
154
+ if (entry.isSymbolicLink()) {
155
+ const real = realpathSafe(src);
156
+ const realStat = fs.statSync(real);
157
+ if (realStat.isDirectory()) {
158
+ copyDirContents(real, dst);
159
+ } else if (realStat.isFile()) {
160
+ fs.mkdirSync(path.dirname(dst), { recursive: true });
161
+ fs.copyFileSync(real, dst);
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ function syncRuntimeAssets(targetRoot, dryRun) {
168
+ const mappings = [
169
+ { label: "commands", src: path.join(packageAgents, "commands"), dst: path.join(targetRoot, LOCAL_COMMANDS_ROOT) },
170
+ { label: "agents", src: path.join(packageAgents, "agents"), dst: path.join(targetRoot, LOCAL_AGENTS_ROOT) },
171
+ { label: "references", src: path.join(packageAgents, "references"), dst: path.join(targetRoot, LOCAL_REFERENCES_ROOT) },
172
+ ];
173
+
174
+ for (const mapping of mappings) {
175
+ if (!fs.existsSync(mapping.src)) continue;
176
+ if (dryRun) {
177
+ console.log("[dry-run] Would sync", mapping.label, "to", path.relative(targetRoot, mapping.dst));
178
+ continue;
179
+ }
180
+ fs.rmSync(mapping.dst, { recursive: true, force: true });
181
+ copyDirContents(mapping.src, mapping.dst);
182
+ console.log("Synced", mapping.label + ":", path.relative(targetRoot, mapping.dst));
183
+ }
184
+ }
185
+
133
186
  function ensureObject(v) {
134
187
  return v && typeof v === "object" && !Array.isArray(v) ? v : {};
135
188
  }
@@ -237,39 +290,29 @@ function ensureSkillsSymlink(targetRoot, dryRun) {
237
290
  }
238
291
  }
239
292
 
240
- function ensureCursorDirSymlink(targetRoot, cursorSubdir, pkgSubdir, dryRun, label, cursorReady) {
293
+ function ensureCursorDirSync(targetRoot, cursorSubdir, pkgSubdir, dryRun, label, cursorReady) {
241
294
  const cursorDir = path.join(targetRoot, ".cursor");
242
295
  if (!cursorReady) return { status: "skipped-missing-cursor" };
243
296
  const pkgPath = path.join(packageRoot, "src", ".agents", pkgSubdir);
244
297
  if (!fs.existsSync(pkgPath)) return { status: "skipped-missing-package-path" };
245
298
 
246
- const linkPath = path.join(cursorDir, cursorSubdir);
247
- const targetRel = path.join("..", "node_modules", "compound-workflow", "src", ".agents", pkgSubdir);
248
- const targetAbs = path.resolve(path.dirname(linkPath), targetRel);
249
-
299
+ const targetPath = path.join(cursorDir, cursorSubdir);
250
300
  if (dryRun) {
251
- console.log("[dry-run] Would create .cursor/" + cursorSubdir, "symlink (Cursor)");
301
+ console.log("[dry-run] Would sync .cursor/" + cursorSubdir, "from", label || pkgSubdir, "(Cursor)");
252
302
  return { status: "dry-run" };
253
303
  }
254
304
 
255
- let needCreate = true;
256
- try {
257
- const stat = fs.lstatSync(linkPath);
258
- if (stat.isSymbolicLink() && symlinkPointsTo(linkPath, targetAbs)) needCreate = false;
259
- else if (!stat.isSymbolicLink()) {
260
- console.warn("Skipped", ".cursor/" + cursorSubdir, "because it exists and is not a symlink");
261
- return { status: "blocked-nonsymlink", path: linkPath };
305
+ if (fs.existsSync(targetPath)) {
306
+ const stat = fs.lstatSync(targetPath);
307
+ if (!stat.isDirectory()) {
308
+ return { status: "blocked-nondirectory", path: targetPath };
262
309
  }
263
- } catch (_) {}
264
-
265
- if (needCreate) {
266
- removePathIfExists(linkPath);
267
- const type = process.platform === "win32" ? "dir" : "dir";
268
- fs.symlinkSync(targetRel, linkPath, type);
269
- console.log("Created", ".cursor/" + cursorSubdir, "->", label || pkgSubdir, "(Cursor)");
270
- return { status: "created" };
271
310
  }
272
- return { status: "ok" };
311
+
312
+ fs.rmSync(targetPath, { recursive: true, force: true });
313
+ copyDirContents(pkgPath, targetPath);
314
+ console.log("Synced", ".cursor/" + cursorSubdir, "from", label || pkgSubdir, "(Cursor)");
315
+ return { status: "synced" };
273
316
  }
274
317
 
275
318
  function ensureCursorSkills(targetRoot, dryRun, cursorReady) {
@@ -278,29 +321,13 @@ function ensureCursorSkills(targetRoot, dryRun, cursorReady) {
278
321
 
279
322
  const packageSkillsDir = path.join(packageRoot, "src", ".agents", "skills");
280
323
  if (!fs.existsSync(packageSkillsDir)) return { blocked: [] };
281
-
282
- const skillNames = [];
283
- try {
284
- for (const name of fs.readdirSync(packageSkillsDir)) {
285
- const skillPath = path.join(packageSkillsDir, name);
286
- if (fs.statSync(skillPath).isDirectory() && fs.existsSync(path.join(skillPath, "SKILL.md"))) {
287
- skillNames.push(name);
288
- }
289
- }
290
- } catch (_) {
291
- return;
292
- }
293
-
294
324
  const skillsDir = path.join(cursorDir, "skills");
295
- const type = process.platform === "win32" ? "dir" : "dir";
296
-
297
325
  if (dryRun) {
298
- console.log("[dry-run] Would create .cursor/skills/<skill> symlinks for:", skillNames.join(", "));
326
+ console.log("[dry-run] Would sync .cursor/skills from package skills (Cursor)");
299
327
  return { blocked: [] };
300
328
  }
301
329
 
302
- if (!fs.existsSync(skillsDir)) fs.mkdirSync(skillsDir, { recursive: true });
303
- else {
330
+ if (fs.existsSync(skillsDir)) {
304
331
  const stat = fs.lstatSync(skillsDir);
305
332
  if (!stat.isDirectory()) {
306
333
  console.warn("Skipped .cursor/skills because it exists and is not a directory");
@@ -308,29 +335,10 @@ function ensureCursorSkills(targetRoot, dryRun, cursorReady) {
308
335
  }
309
336
  }
310
337
 
311
- const blocked = [];
312
- for (const name of skillNames) {
313
- const linkPath = path.join(skillsDir, name);
314
- const targetRel = path.join("..", "..", "node_modules", "compound-workflow", "src", ".agents", "skills", name);
315
- const targetAbs = path.resolve(path.dirname(linkPath), targetRel);
316
- let needCreate = true;
317
- try {
318
- const stat = fs.lstatSync(linkPath);
319
- if (stat.isSymbolicLink() && symlinkPointsTo(linkPath, targetAbs)) needCreate = false;
320
- else if (!stat.isSymbolicLink()) {
321
- console.warn("Skipped", ".cursor/skills/" + name, "because it exists and is not a symlink");
322
- blocked.push(linkPath);
323
- continue;
324
- }
325
- } catch (_) {}
326
-
327
- if (needCreate) {
328
- removePathIfExists(linkPath);
329
- fs.symlinkSync(targetRel, linkPath, type);
330
- console.log("Created", ".cursor/skills/" + name, "-> package skill (Cursor)");
331
- }
332
- }
333
- return { blocked };
338
+ fs.rmSync(skillsDir, { recursive: true, force: true });
339
+ copyDirContents(packageSkillsDir, skillsDir);
340
+ console.log("Synced .cursor/skills from package skills (Cursor)");
341
+ return { blocked: [] };
334
342
  }
335
343
 
336
344
  function verifyCursorIntegration(targetRoot) {
@@ -345,13 +353,12 @@ function verifyCursorIntegration(targetRoot) {
345
353
  const issues = [];
346
354
 
347
355
  for (const check of checks) {
348
- const linkPath = path.join(cursorDir, check.rel);
349
- const expectedAbs = path.join(targetRoot, "node_modules", "compound-workflow", "src", ".agents", check.rel);
350
- if (!fs.existsSync(linkPath)) issues.push(`${check.name} is missing`);
356
+ const dirPath = path.join(cursorDir, check.rel);
357
+ if (!fs.existsSync(dirPath)) issues.push(`${check.name} is missing`);
351
358
  else {
352
- const stat = fs.lstatSync(linkPath);
353
- if (stat.isSymbolicLink() && !symlinkPointsTo(linkPath, expectedAbs)) {
354
- issues.push(`${check.name} symlink points to unexpected target`);
359
+ const stat = fs.lstatSync(dirPath);
360
+ if (!stat.isDirectory()) {
361
+ issues.push(`${check.name} exists but is not a directory`);
355
362
  }
356
363
  }
357
364
  }
@@ -413,9 +420,9 @@ function ensureCursorIntegration(targetRoot, dryRun, forceCursor) {
413
420
 
414
421
  const skillReport = ensureCursorSkills(targetRoot, dryRun, cursorReady);
415
422
  const dirReports = [
416
- ensureCursorDirSymlink(targetRoot, "agents", "agents", dryRun, "package agents", cursorReady),
417
- ensureCursorDirSymlink(targetRoot, "commands", "commands", dryRun, "package commands", cursorReady),
418
- ensureCursorDirSymlink(targetRoot, "references", "references", dryRun, "package references", cursorReady),
423
+ ensureCursorDirSync(targetRoot, "agents", "agents", dryRun, "package agents", cursorReady),
424
+ ensureCursorDirSync(targetRoot, "commands", "commands", dryRun, "package commands", cursorReady),
425
+ ensureCursorDirSync(targetRoot, "references", "references", dryRun, "package references", cursorReady),
419
426
  ];
420
427
 
421
428
  const issues = [];
@@ -423,8 +430,8 @@ function ensureCursorIntegration(targetRoot, dryRun, forceCursor) {
423
430
  for (const p of skillReport.blocked) issues.push(`${path.relative(targetRoot, p)} blocks symlink creation (not a symlink)`);
424
431
  }
425
432
  for (const report of dirReports) {
426
- if (report?.status === "blocked-nonsymlink") {
427
- issues.push(`${path.relative(targetRoot, report.path)} blocks symlink creation (not a symlink)`);
433
+ if (report?.status === "blocked-nondirectory") {
434
+ issues.push(`${path.relative(targetRoot, report.path)} blocks sync (not a directory)`);
428
435
  }
429
436
  }
430
437
 
@@ -579,12 +586,14 @@ function main() {
579
586
  console.log("Package root:", packageRoot);
580
587
  console.log("OpenCode CLI detected:", hasCommand("opencode") ? "yes" : "no");
581
588
 
589
+ syncRuntimeAssets(targetRoot, args.dryRun);
582
590
  writeOpenCodeJson(targetRoot, args.dryRun);
583
591
  ensureSkillsSymlink(targetRoot, args.dryRun);
584
592
  reportOpenCodeIntegration(targetRoot, args.dryRun);
585
- const cursorReport = ensureCursorIntegration(targetRoot, args.dryRun, args.cursor);
593
+ const cursorExists = fs.existsSync(path.join(targetRoot, ".cursor"));
594
+ const cursorReport = ensureCursorIntegration(targetRoot, args.dryRun, cursorExists);
586
595
  if (cursorReport.status === "skipped-no-cursor") {
587
- console.log("Cursor integration: skipped (.cursor missing). Run install with `all` or `--cursor` to create it.");
596
+ console.log("Cursor integration: skipped (.cursor not found).");
588
597
  } else {
589
598
  console.log("Cursor integration: verified skills, agents, commands, and references.");
590
599
  }
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { spawnSync } from "node:child_process";
6
+
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+ const packageRoot = path.resolve(__dirname, "..");
9
+
10
+ function realpathSafe(p) {
11
+ try {
12
+ return fs.realpathSync(p);
13
+ } catch {
14
+ return path.resolve(p);
15
+ }
16
+ }
17
+
18
+ function isTruthy(v) {
19
+ const s = String(v || "").toLowerCase();
20
+ return s === "1" || s === "true" || s === "yes";
21
+ }
22
+
23
+ function hasFile(dir, name) {
24
+ try {
25
+ return fs.existsSync(path.join(dir, name));
26
+ } catch {
27
+ return false;
28
+ }
29
+ }
30
+
31
+ function shouldSkip(targetRoot) {
32
+ if (!targetRoot) return "INIT_CWD not set";
33
+ if (isTruthy(process.env.npm_config_global)) return "global install";
34
+ if (isTruthy(process.env.COMPOUND_WORKFLOW_SKIP_POSTINSTALL)) return "disabled by env";
35
+ if (!hasFile(targetRoot, "package.json")) return "no package.json in target root";
36
+ if (realpathSafe(targetRoot) === realpathSafe(packageRoot)) return "package development install";
37
+ return null;
38
+ }
39
+
40
+ function run() {
41
+ const targetRoot = process.env.INIT_CWD ? path.resolve(process.env.INIT_CWD) : "";
42
+ const skipReason = shouldSkip(targetRoot);
43
+ if (skipReason) {
44
+ console.log(`[compound-workflow] postinstall skipped (${skipReason})`);
45
+ return;
46
+ }
47
+
48
+ const cliPath = path.join(packageRoot, "scripts", "install-cli.mjs");
49
+ const result = spawnSync(
50
+ process.execPath,
51
+ [cliPath, "install", "--root", targetRoot, "--no-config"],
52
+ { stdio: "inherit", env: process.env }
53
+ );
54
+
55
+ if (result.status !== 0) {
56
+ console.warn(
57
+ "[compound-workflow] automatic setup failed; run `npx compound-workflow install` in your project."
58
+ );
59
+ }
60
+ }
61
+
62
+ run();
@@ -863,17 +863,16 @@ Examples:
863
863
 
864
864
  After writing the plan file, use **AskQuestion** to present these options:
865
865
 
866
- Do not route directly from plan generation to `/workflow:work`.
867
-
868
866
  **Question:** "Plan ready at `docs/plans/YYYY-MM-DD-<type>-<slug>-plan.md`. What would you like to do next?"
869
867
 
870
868
  **Options:**
871
869
 
872
870
  1. **Open plan in editor** - Open the plan file for review
873
871
  2. **Review and refine** - Improve the document through structured self-review
874
- 3. **Start `/workflow:triage`** - Triage todos derived from this plan before execution
875
- 4. **Create Issue** - Create issue in project tracker (GitHub/Linear)
876
- 5. **Other** - Adjust the plan
872
+ 3. **Start `/workflow:work`** - Execute this plan (includes default triage gate)
873
+ 4. **Start `/workflow:triage`** - Manually curate/prioritize queue before execution
874
+ 5. **Create Issue** - Create issue in project tracker (GitHub/Linear)
875
+ 6. **Other** - Adjust the plan
877
876
 
878
877
  Optional (only if those workflows exist in this repo):
879
878
 
@@ -884,6 +883,7 @@ Based on selection:
884
883
 
885
884
  - **Open plan in editor** → Open the plan file in the editor (navigate to `docs/plans/<plan_filename>.md`)
886
885
  - **Review and refine** → Load `document-review` skill.
886
+ - **Start `/workflow:work`** → Run `/workflow:work <plan_path>`; `/workflow:work` must run triage before implementation.
887
887
  - **Start `/workflow:triage`** → Ensure plan todos exist (create via `file-todos` if needed), then run `/workflow:triage` to approve priority/dependencies and the executable ready queue.
888
888
  - **Technical review** → Load `technical-review` skill; then if user agrees to changes, load `document-review` to update the plan.
889
889
  - **Create Issue** → See "Issue Creation" section below
@@ -891,7 +891,7 @@ Based on selection:
891
891
 
892
892
  **Note:** Only if `/deepen-plan` exists in this repo and the user has enabled it (e.g., ultrathink), you may run `/deepen-plan` after plan creation for extra depth; it is optional, not required.
893
893
 
894
- Loop back to options after changes until user selects `/workflow:triage` or ends the session.
894
+ Loop back to options after changes until user selects `/workflow:work`, `/workflow:triage`, or ends the session.
895
895
 
896
896
  ## Issue Creation
897
897
 
@@ -933,6 +933,6 @@ When user selects "Create Issue", detect their project tracker from repo guidanc
933
933
 
934
934
  5. **After creation:**
935
935
  - Display the issue URL
936
- - Ask if they want to proceed to `/workflow:triage`
936
+ - Ask if they want to proceed to `/workflow:work` (default path) or `/workflow:triage` (manual queue curation)
937
937
 
938
938
  NEVER CODE! Just research and write the plan.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: triage
3
3
  invocation: workflow:triage
4
- description: Triage and prioritize todo files into an executable ready queue (priority, dependencies, recommended action)
4
+ description: Manual triage command to prioritize todo files into an executable ready queue (priority, dependencies, recommended action)
5
5
  argument-hint: "[optional: todo path, issue id, status filter ('pending'|'ready'|'active')]"
6
6
  ---
7
7
 
@@ -9,6 +9,8 @@ argument-hint: "[optional: todo path, issue id, status filter ('pending'|'ready'
9
9
 
10
10
  Turn todo items into a prioritized executable queue.
11
11
 
12
+ This command is independently runnable. `/workflow:work` runs the same triage gate automatically before execution.
13
+ Use `/workflow:triage` when you want explicit manual queue curation before or during execution.
12
14
  This command does not implement fixes. It approves and organizes work so `/workflow:work` can execute without ambiguity.
13
15
  Output of this command is the only executable queue for `/workflow:work`.
14
16
 
@@ -100,7 +100,7 @@ The input must be a plan file path.
100
100
  - Continue only when provided commands run successfully.
101
101
  - If commands are not provided or fail, do not mark related todos complete.
102
102
 
103
- Note: full execution preflight (triage + contract checks + isolation checks) runs after todo creation/triage in Step 3.5.
103
+ Note: full execution preflight (auto-triage + contract checks + isolation checks) runs after todo creation in Step 3.5.
104
104
 
105
105
  1.75. **Resolve Plan Scope Contract (REQUIRED)**
106
106
 
@@ -138,16 +138,23 @@ The input must be a plan file path.
138
138
  - If you are already on a branch that clearly matches this plan, continue.
139
139
  - Otherwise, continue anyway — the current active branch remains the reference/base for a new worktree unless the user explicitly requests a different base.
140
140
 
141
- 2) Ask the user (required decision prompt):
141
+ 2) Resolve the user decision (required prompt/create gate):
142
142
 
143
- - "Use a worktree for this work? (default: Yes; required unless you explicitly opt out)"
143
+ - If the user already gave an explicit instruction in this run:
144
+ - "create a worktree" / "yes use a worktree" => use worktree path
145
+ - "do not use a worktree" / "no worktree" => opt-out path
146
+ - Otherwise, you MUST ask this exact decision before proceeding:
147
+ - "Use a worktree for this work? (Yes/No; default recommendation: Yes)"
144
148
  - Options:
145
149
  - Yes (worktree)
146
150
  - No (stay in current checkout; create/switch to a feature branch)
147
151
 
148
- If Yes: ask for the new branch name (e.g., `feat/<slug>`, `fix/<slug>`).
152
+ Mandatory behavior:
149
153
 
150
- If the user does not explicitly choose "No", proceed with "Yes" by default.
154
+ - Do not infer or assume an answer when the user has not answered.
155
+ - Do not run `skill: git-worktree` until the user has answered Yes (or already explicitly requested worktree creation).
156
+ - If Yes: ask for the new branch name when missing (e.g., `feat/<slug>`, `fix/<slug>`), then continue.
157
+ - If No: require explicit opt-out confirmation, then continue with the non-worktree path.
151
158
 
152
159
  3) If worktree is chosen, run:
153
160
 
@@ -217,20 +224,21 @@ The input must be a plan file path.
217
224
  - Each todo MUST include a link back to the plan file in `Resources` and reference the specific section(s) it implements.
218
225
  - Default todo `status`:
219
226
  - `ready` when the plan is approved and confidence is not low
220
- - `pending` when plan confidence is low or requires explicit triage
227
+ - `pending` when plan confidence is low or requires additional triage decisions
221
228
  - Default todo `priority`: `p2` unless the plan indicates urgency/risk.
222
229
 
223
- After creating todos:
230
+ After creating todos, run an in-command triage pass (same readiness/dependency rules as `/workflow:triage`) before any implementation work:
224
231
 
225
- - Run `/workflow:triage` before any implementation work to approve/prioritize the queue for this plan.
226
- - Do not proceed to Phase 2 until triage completes and execution order is explicit.
227
- - If triage leaves no unblocked `ready` todos, stop and report pending/deferred/blocked items.
232
+ - approve/prioritize queue items for this plan
233
+ - make execution order explicit
234
+ - if no unblocked `ready` todos remain, stop and report pending/deferred/blocked items
235
+ - use standalone `/workflow:triage` only when the user explicitly requests manual queue curation
228
236
 
229
237
  3.5. **Execution Preflight (HARD GATE before Phase 2)**
230
238
 
231
239
  Contract checksum (MUST all be true before implementation):
232
240
 
233
- - triage completed for this plan
241
+ - auto-triage completed for this plan (or standalone `/workflow:triage` completed)
234
242
  - isolation gate recorded (`worktree_decision`, execution context, `gate_status: passed`)
235
243
  - blocking spikes execute before dependent build todos
236
244
 
@@ -241,7 +249,7 @@ The input must be a plan file path.
241
249
  - validation path is explicit (commands/routes/checks)
242
250
  - evidence expectations are explicit
243
251
  - quality gate commands are explicit or marked for ask-once fallback
244
- - If a todo lacks this contract, move it to `pending` for triage before coding.
252
+ - If a todo lacks this contract, move it to `pending` and require triage resolution before coding.
245
253
 
246
254
  ### Phase 2: Execute
247
255
 
@@ -268,7 +276,7 @@ The input must be a plan file path.
268
276
 
269
277
  - If no unblocked `ready` todos remain:
270
278
  - summarize remaining `pending`, `deferred` (parked for reference), and blocked items
271
- - require re-running `/workflow:triage` for pending/blocked prioritization
279
+ - require re-running triage (auto-triage within `/workflow:work` or standalone `/workflow:triage`) for pending/blocked prioritization
272
280
  - stop (do not invent work)
273
281
 
274
282
  For each task in priority order:
@@ -319,7 +327,7 @@ The input must be a plan file path.
319
327
  - If new, non-critical work is discovered, do NOT silently expand scope.
320
328
  - Ask the user to choose one:
321
329
  1) Do now (scope increase): only if small + tightly coupled
322
- 2) Create a triage item: create a new `pending` todo (default `p3` unless urgent) to be approved or deferred via `/workflow:triage`
330
+ 2) Create a triage item: create a new `pending` todo (default `p3` unless urgent) to be approved or deferred via triage
323
331
  3) Park for reference: create a todo with Problem Statement + Findings + rationale, then mark it **deferred** (`*-deferred-*.md`, `status: deferred`) so it is kept for future reference but not in the executable queue
324
332
  4) Compound candidate only: capture as a `/workflow:compound` documentation candidate (no todo by default)
325
333
  - Always record the decision in the todo Work Log.
@@ -368,7 +376,7 @@ The input must be a plan file path.
368
376
  - Convert the decision into explicit todos (implementation/investigation/deferral).
369
377
  - If the chosen option is to run a timeboxed investigation or prototype, follow the **Spike Protocol** below.
370
378
  - Record the decision + rationale in the todo Work Log.
371
- - Re-approve the todo through `/workflow:triage` before returning it to `ready`.
379
+ - Re-approve the todo through triage before returning it to `ready`.
372
380
 
373
381
  **Spike Protocol (allocate a spike)**
374
382
 
@@ -376,7 +384,7 @@ The input must be a plan file path.
376
384
 
377
385
  Steps:
378
386
 
379
- 1. **Spike todo:** Create a new `todos/*-pending-*.md` todo tagged `tags: [spike]` (or convert the current blocked todo to a spike todo). Fill Problem Statement, Proposed Solutions (options), and Acceptance Criteria (deliverable). Carry forward any plan metadata (initial priority, depends_on, unblocks, parallelizable). If triage has not been run, recommend `/workflow:triage` to approve the spike and set timebox + deliverable; then treat the spike as `ready` once approved.
387
+ 1. **Spike todo:** Create a new `todos/*-pending-*.md` todo tagged `tags: [spike]` (or convert the current blocked todo to a spike todo). Fill Problem Statement, Proposed Solutions (options), and Acceptance Criteria (deliverable). Carry forward any plan metadata (initial priority, depends_on, unblocks, parallelizable). Ensure triage approves the spike and sets timebox + deliverable before treating it as `ready`.
380
388
  2. **Isolated execution:** Recommend a dedicated spike worktree. Use `skill: git-worktree` with branch name `spike/<todo_id>-<slug>` (e.g. `spike/003-auth-approach`). Run worktree bootstrap per the git-worktree skill. Execute the spike in that worktree so build work is not mixed with exploration.
381
389
  3. **Research subagents (per spike):** Run mandatory baseline research in parallel:
382
390
  - Always (when agents exist): Task repo-research-analyst(context), Task learnings-researcher(context)
package/src/AGENTS.md CHANGED
@@ -26,10 +26,13 @@ This `.agents` workspace is portable and command-first.
26
26
 
27
27
  1. `/workflow:brainstorm` -> clarify what to build
28
28
  2. `/workflow:plan` -> define how to build it
29
- 3. `/workflow:triage` -> approve and prioritize the todo queue before execution
30
- 4. `/workflow:work` -> implement
31
- 5. `/workflow:review` -> validate quality
32
- 6. `/workflow:compound` -> capture durable learnings
29
+ 3. `/workflow:work` -> implement (includes triage gate for todo readiness/prioritization)
30
+ 4. `/workflow:review` -> validate quality
31
+ 5. `/workflow:compound` -> capture durable learnings
32
+
33
+ Optional manual step:
34
+
35
+ - `/workflow:triage` -> explicitly curate/prioritize backlog items before execution when needed
33
36
 
34
37
  Continuous improvement:
35
38
 
@@ -62,7 +65,7 @@ If workflow documents conflict, resolve them in this order:
62
65
  - **Solution scope contract is mandatory in every plan.** Plans must declare `solution_scope` (`partial_fix|full_remediation|migration`) plus explicit completion expectation and non-goals so `/workflow:work` can enforce intent.
63
66
  - **SpecFlow is a validation gate, not a rewrite engine.** High fidelity required; Medium recommended; Low optional. Output must translate into acceptance criteria/edge cases, not new scope.
64
67
  - **Isolation preflight is a hard gate.** `/workflow:work` must complete and record worktree/isolation preflight before any implementation commands. `/workflow:review` must do the same for non-current PR/branch targets before analysis.
65
- - **Triage before execution is mandatory.** `/workflow:work` must not execute todos until a `/workflow:triage` pass has prioritized the queue and validated dependencies/ready state for the current plan.
68
+ - **Triage before execution is mandatory.** `/workflow:work` must run a triage pass before executing todos to prioritize the queue and validate dependencies/ready state for the current plan. `/workflow:triage` remains available as an explicit manual command.
66
69
  - **Spike governance is explicit and ordered.** Risky plans must evaluate spike need, spike candidates must declare initial priority/dependencies/unblocks/timebox/deliverable, triage confirms those assumptions, and `/workflow:work` executes blocking spikes before dependent build todos.
67
70
  - **Agentic access/testability is mandatory in planning.** Every plan must include an executable access + validation contract so work/review can run deterministically.
68
71
  - **Independent review is required for code/config changes.** `/workflow:review` must emit `review_independence_mode: independent|degraded`, plus independence evidence and skipped-pass disclosure.