@jaybeeuu/agent-cortex 1.38.1 → 1.40.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 (88) hide show
  1. package/.agents/skills/style-versioning/SKILL.md +1 -1
  2. package/.github/workflows/ci.yml +47 -14
  3. package/AGENTS.md +19 -3
  4. package/CHANGELOG.md +42 -0
  5. package/README.md +118 -63
  6. package/agents/README.md +13 -10
  7. package/agents/ralph-plan/agent.md +1 -1
  8. package/agents/ralph-plan.agent.md +1 -1
  9. package/bin/agent-cortex.mjs +29 -8
  10. package/bin/installers/claude.mjs +569 -105
  11. package/bin/installers/copilot.mjs +22 -12
  12. package/bin/installers/pi.mjs +37 -34
  13. package/docs/claude-hooks.md +3 -3
  14. package/docs/ideas/extension-manifests.md +75 -0
  15. package/docs/ideas/record-ideas-as-beads.md +115 -0
  16. package/docs/ideas/subagent-visibility.md +72 -0
  17. package/docs/ideas/task-session-context.md +89 -0
  18. package/docs/research/skill-design-research.md +4 -4
  19. package/docs/research/skill-improvements-analysis.md +1 -1
  20. package/docs/skills/skill-anatomy.md +38 -2
  21. package/docs/technical-direction/migration-execution-labels.md +132 -0
  22. package/extensions/agent-modes/README.md +3 -2
  23. package/extensions/agent-modes/discover.test.ts +30 -7
  24. package/extensions/agent-modes/discover.ts +1 -1
  25. package/extensions/skill-stats/index.test.ts +3 -2
  26. package/lib/cli.mjs +24 -6
  27. package/package.json +4 -4
  28. package/plugin.json +1 -1
  29. package/pnpm-workspace.yaml +1 -1
  30. package/scripts/build-copilot-agents.mjs +1 -1
  31. package/scripts/check-no-sync.mjs +49 -0
  32. package/scripts/lib/compose-agent.mjs +32 -14
  33. package/skills/engineering/design-an-interface/SKILL.md +78 -58
  34. package/skills/engineering/grill-with-docs/REFERENCE.md +78 -0
  35. package/skills/engineering/grill-with-docs/SKILL.md +66 -63
  36. package/skills/engineering/improve-codebase-architecture/SKILL.md +66 -48
  37. package/skills/engineering/technical-direction/FORMAT.md +38 -0
  38. package/skills/engineering/technical-direction/SKILL.md +70 -77
  39. package/skills/planning/classify-bead/SKILL.md +59 -35
  40. package/skills/planning/create-task/REFERENCE.md +40 -0
  41. package/skills/planning/create-task/SKILL.md +70 -66
  42. package/skills/planning/create-task/scripts/create-chores.ts +6 -1
  43. package/skills/planning/create-task/scripts/node_modules/.bin/tsc +21 -0
  44. package/skills/planning/create-task/scripts/node_modules/.bin/tsserver +21 -0
  45. package/skills/planning/create-task/scripts/node_modules/.bin/tsx +21 -0
  46. package/skills/planning/prd-to-tasks/REFERENCE.md +66 -0
  47. package/skills/planning/prd-to-tasks/SKILL.md +86 -170
  48. package/skills/planning/record-idea/FORMAT.md +44 -0
  49. package/skills/planning/record-idea/SKILL.md +70 -53
  50. package/skills/planning/request-refactor-plan/FORMAT.md +45 -0
  51. package/skills/planning/request-refactor-plan/SKILL.md +57 -46
  52. package/skills/planning/write-a-prd/FORMAT.md +54 -0
  53. package/skills/planning/write-a-prd/SKILL.md +49 -48
  54. package/skills/planning/write-a-ticket/SKILL.md +68 -53
  55. package/skills/productivity/handoff/SKILL.md +12 -0
  56. package/skills/productivity/init-beads/SKILL.md +48 -40
  57. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsc +21 -0
  58. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsserver +21 -0
  59. package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsx +21 -0
  60. package/skills/productivity/write-a-skill/SKILL.md +2 -1
  61. package/skills/review/maintain-agent-docs/SKILL.md +71 -51
  62. package/skills/workflow/hitl-collab/SKILL.md +86 -17
  63. package/skills/workflow/ralph/REFERENCE.md +22 -17
  64. package/skills/workflow/ralph/SKILL.md +88 -74
  65. package/skills/workflow/run-pipeline-stage/REFERENCE.md +22 -0
  66. package/skills/workflow/run-pipeline-stage/SKILL.md +91 -93
  67. package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +6 -107
  68. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsc +21 -0
  69. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsserver +21 -0
  70. package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsx +21 -0
  71. package/test/claude-installer.test.mjs +308 -0
  72. package/test/cli.test.mjs +40 -30
  73. package/test/copilot-installer.test.mjs +92 -82
  74. package/test/helpers/fake-claude.mjs +152 -0
  75. package/test/installer.test.mjs +309 -57
  76. package/test/pi-installer.test.mjs +115 -99
  77. package/token-map.README.md +21 -10
  78. package/token-map.json +7 -6
  79. package/.claude-plugin/marketplace.json +0 -16
  80. package/claude/.claude-plugin/plugin.json +0 -11
  81. package/claude/agents/plan.md +0 -58
  82. package/claude/agents/ralph-plan.md +0 -121
  83. package/claude/agents/ralph.md +0 -193
  84. package/claude/agents/strategy.md +0 -111
  85. package/claude/hooks/scripts/notify.mjs +0 -54
  86. package/claude/hooks.json +0 -38
  87. /package/{claude → claude-extras}/.mcp.json +0 -0
  88. /package/{claude → claude-extras}/scripts/statusline-command.sh +0 -0
@@ -1,41 +1,41 @@
1
1
  ---
2
2
  name: ralph
3
- description: "Run all pending beads end-to-end using parallel subagents with review gates: initialise, dispatch up to 5 concurrent pipeline-stage chores, open and report PRs immediately, then wait for merges before continuing. Use when running the full task backlog with human approval points."
3
+ description: "Run all pending beads end-to-end with up to 5 concurrent pipeline-stage chores in dedicated worktrees, opening review-gated PRs immediately and pausing for human merges. Use when you want to \"run the backlog\", \"run all beads\", or \"run ralph\" with human approval gates."
4
4
  ---
5
5
 
6
- # Fleet
6
+ # Ralph
7
7
 
8
- Parallel task orchestration: find ready beads, dispatch them as background subagents, process each outcome through the pipeline (code → verify → review → document, with fix loops on failure), then open review-gated PRs before considering feature work complete.
8
+ Ralph is a parallel orchestration loop. It advances AFK task beads through pipeline-stage chores (`code` → `verify` → `review` → `document`), dispatching each stage as a background subagent in the feature's worktree, then opens review-gated feature and epic PRs and pauses for human merges. Ralph never writes code itself — it dispatches, tracks, and reports.
9
9
 
10
- Orchestration state is derived entirely from beads — there is no separate state file. In-flight work is tracked as chore beads with status `in_progress`. Ready work is discovered via `bd ready`. Pipeline configuration lives in `skills/planning/create-task/pipeline.json`. Stage runner prompt templates live in `skills/workflow/run-pipeline-stage/prompts/` and playbooks in `skills/workflow/run-pipeline-stage/playbooks/`.
10
+ State model: task state lives in beads (ready/in_progress via `bd`); the only local file is `.agent-cortex/ralph/state.json`, holding the poll-timer shellId and the agent-ID→bead mapping. Pipeline configuration comes from `skills/planning/create-task/pipeline.json`, and stage execution belongs to the `run-pipeline-stage` skill.
11
11
 
12
- ## Branching and Review Model
12
+ ## When to use
13
13
 
14
- 1. **Epic integration branch**: each epic runs on `epic/<epic-id>` (base: `origin/main`, never local `main`).
15
- 2. **Feature branch per parent bead**: each AFK parent task runs on `feature/<parent-task-id>`, based from its epic branch. This branch is treated as the **agent branch** for HITL PRs.
16
- 3. **Dedicated worktree per parent bead**: each feature branch uses `.agent-cortex/worktrees/<parent-task-id>`.
17
- 4. **Feature PR gate**: each feature has a child HITL task bead (`lifecycle:feature-pr`) created by `create-task`. When `document` completes, open/update PR `feature/<parent-task-id> -> epic/<epic-id>` (agent-branch → feature branch), report the PR URL immediately, then wait for the HITL PR gate bead to be closed by a human.
18
- 5. **Epic PR gate**: when an epic's feature beads are complete, open/update a PR `epic/<epic-id> -> main` and pause until merged.
14
+ - "Run the backlog", "run all beads", "run ralph", "run everything pending".
15
+ - A planning session has produced classified, unblocked AFK task beads and you want autonomous execution with human review gates.
16
+ - You want the full pipeline (implement → verify → review → document) orchestrated concurrently, with fix loops on failure.
19
17
 
20
- See [REFERENCE.md](./REFERENCE.md) for detailed procedures: dispatching, fix loop, log polling, and shutdown.
18
+ ## When NOT to use
21
19
 
22
- ---
20
+ - Working a single bead or stage inline — use the `run-pipeline-stage` skill instead.
21
+ - Interactive planning, PRDs, or scoping — use the `plan` skill instead.
22
+ - Running as a background or delegated subagent — ralph must be the interactive foreground agent, or it cannot receive completion notifications.
23
23
 
24
- ## Initialization
24
+ ## Workflow
25
25
 
26
- Run once at startup:
26
+ ### 1. Initialize (run once at startup)
27
27
 
28
- 1. Run `bd prime`. Hold the full output verbatim in memory — forward it unchanged to every subagent.
28
+ 1. Run `bd prime` and hold the output verbatim in memory.
29
29
  2. Ensure `.agent-cortex/` and `.agent-cortex/worktrees/` are in the project's `.gitignore` (append any that are missing).
30
- 3. Ensure Ralph's workspace directory exists: `mkdir -p .agent-cortex/ralph`.
31
- 4. Read `skills/planning/create-task/pipeline.json` and hold it in memory — you need `maxFixRounds` for the fix loop.
32
- 5. Run `bd ready` to get the initial list of available beads.
33
- 6. For each available bead:
30
+ 3. Create the workspace: `mkdir -p .agent-cortex/ralph`.
31
+ 4. Initialize state: write `.agent-cortex/ralph/state.json` with `{ "timerShellId": null, "inflight": [] }`.
32
+ 5. Read `skills/planning/create-task/pipeline.json` and hold it in memory — you need its `maxFixRounds` for the fix loop.
33
+ 6. Run `bd ready` and classify each available bead:
34
34
  - **Chore with a `stage:*` label**: pipeline stage bead — eligible for dispatch.
35
- - **Task or other type without an `implementation-type:*` label**: unexpected here — classification is a planning-stage concern already applied by `create-task`. Do not invoke `classify-bead`; treat as needs-refinement and note for the shutdown summary.
36
- - **Task labelled `implementation-type:hitl`**: skip — record the bead ID for the **Pending Human Action** summary at shutdown.
37
- 7. For each ready chore bead (up to 5), **dispatch** it (see _Dispatching a chore bead_ in REFERENCE.md). Chores for a parent bead must run from that parent's worktree.
38
- 8. **If** any chore beads were dispatched in step 7, start the **poll timer** (Copilot only): run `sleep 120` as a background bash process and hold its shellId in memory. PI has no timer — keep a `wait_for_agents` call outstanding over every in-flight agent ID instead (see the Event Loop note). **Otherwise**, if HITL gate beads are pending (check `bd list -l lifecycle:feature-pr -l implementation-type:hitl` and `bd list -l awaiting-epic-pr-merge`), proceed to **HITL Pause** (see REFERENCE.md) immediately.
35
+ - **Task or other type without an `implementation-type:*` label**: unexpected here — classification happens at planning time via `create-task`. Do not invoke `classify-bead`; treat as needs-refinement and note it for the shutdown summary.
36
+ - **Task labelled `implementation-type:hitl`**: skip — record the ID for the Pending Human Action summary at shutdown.
37
+ 7. For each ready chore bead (up to 5), dispatch it from its parent's feature worktree (see _Dispatching a chore bead_ in REFERENCE.md — create branches/worktrees first).
38
+ 8. Hand over to your harness's completion-detection mechanism: Copilot keeps a `sleep 120` poll timer running in the background; PI keeps a {{TOOL:wait_for_agents}} call outstanding over every in-flight agent ID. If no chore was dispatched and HITL gate beads are pending (`bd list -l lifecycle:feature-pr -l implementation-type:hitl` or `bd list -l awaiting-epic-pr-merge`), go straight to HITL Pause (REFERENCE.md).
39
39
  9. Regenerate `.agent-cortex/ralph/progress.md`:
40
40
  ```bash
41
41
  # workspace must be the absolute path you cd'd into — never . or $(pwd)
@@ -43,63 +43,77 @@ Run once at startup:
43
43
  pnpm --prefix skills/workflow/run-pipeline-stage/scripts exec tsx generate-progress.ts --workspace "$workspace" > "$workspace/.agent-cortex/ralph/progress.md"
44
44
  ```
45
45
 
46
- ---
46
+ ### 2. Event loop
47
47
 
48
- ## Event Loop
48
+ On each completion notification (background agent finished, or the poll timer fired):
49
49
 
50
- After initialization, wait for background agents or the poll timer to complete. Completion detection is harness-specific: the `sleep 120` poll timer described below is the **Copilot** mechanism. **PI** replaces it with the blocking `wait_for_agents` tool — it returns as soon as any in-flight agent finishes, so each return plays the role of a poll-timer tick with its completed-agent result attached; there is no timer to start or kill on PI. On each completion notification:
50
+ 1. Poll that parent's log for new lines — `tail -n +<nextLine> .agent-cortex/ralph/ralph-<parent-id>.log` (logs are keyed by parent bead ID, so every stage of a feature shares one file) — and post only new key events (stage transitions, test/lint results), never empty updates.
51
+ 2. Read the completed agent's output with {{TOOL:read_agent}} and parse its `---REPORT---` block for `BEAD_ID`, `STAGE_COMPLETED`, and the outcome.
52
+ 3. Close the chore bead: `bd close <bead-id>`.
53
+ 4. Advance the parent per the dispatch table:
51
54
 
52
- ### Poll timer completed
55
+ | Stage completed | Condition | Next action |
56
+ |-----------------|-----------|-------------|
57
+ | `code` | — | Closing the code chore unblocks the verify chore |
58
+ | `fix` | — | Closing the fix chore unblocks the verify chore |
59
+ | `verify` | `VERIFY_OUTCOME: PASS` | Closing the verify chore unblocks the review chore |
60
+ | `verify` | `VERIFY_OUTCOME: FAIL` | Run the fix loop (REFERENCE.md) |
61
+ | `review` | `REVIEW_OUTCOME: APPROVED` | Closing the review chore unblocks the document chore |
62
+ | `review` | `REVIEW_OUTCOME: CHANGES_REQUESTED` | Run the fix loop (REFERENCE.md) |
63
+ | `document` | — | Open/update the feature PR now (`feature/<parent-id>` → its base branch), report the URL, and update the child HITL gate bead (`lifecycle:feature-pr`). Wait for a human to close that bead after merge, then `bd close <parent-id>` |
53
64
 
54
- 1. **Poll all in-flight bead logs** (see _Log polling_ in REFERENCE.md).
55
- 2. Regenerate `.agent-cortex/ralph/progress.md`.
56
- 3. **HITL pause check**: if `bd list --status=in_progress --type=chore` returns empty AND `bd ready` has no `stage:*` chore beads AND HITL gate beads are pending (`bd list -l lifecycle:feature-pr -l implementation-type:hitl` or `bd list -l awaiting-epic-pr-merge` returns results), proceed to **HITL Pause** (see REFERENCE.md) — do **not** restart the timer.
57
- 4. **Otherwise**: restart the timer: run `sleep 120` as a new background bash process, hold its shellId in memory.
65
+ 5. Run `bd ready` and dispatch new ready `stage:*` chore beads while the in-flight count (`bd list --status=in_progress --type=chore`) is under 5. Do not schedule new parent features while any `lifecycle:feature-pr` HITL gate bead is open.
66
+ 6. If no chores are in-flight and `bd ready` returns no `stage:*` chores, proceed to HITL Pause (REFERENCE.md) when HITL gate beads are pending, otherwise to Shutdown (REFERENCE.md).
67
+ 7. Regenerate `.agent-cortex/ralph/progress.md`.
58
68
 
59
- ### Background agent completed
69
+ ### 3. Branching and review model
60
70
 
61
- 1. **Poll that bead's log** to flush any final lines.
62
- 2. **Read** the completed agent's full output with {{TOOL:read_agent}} (on PI the completed result arrives in the `wait_for_agents` response; read_agent remains a fallback for a specific result).
63
- 3. **Identify the bead**: parse the `---REPORT---` block for `BEAD_ID` and `STAGE_COMPLETED`.
64
- 4. **Close** the chore bead: `bd close <bead-id>`.
65
- 5. **Handle stage outcome**:
71
+ - **Single-feature epics** (exactly one feature task child — count with `bd children <epic-id>`, excluding chores): no epic branch. `feature/<parent-id>` is based directly on `origin/main`, its feature PR targets `main`, and no epic PR is opened.
72
+ - **Multi-feature epics** (two or more feature task children): the epic runs on `epic/<epic-id>`, based on `origin/main` — never local `main`. Each AFK parent task runs on `feature/<parent-id>`, based from its epic branch, in the dedicated worktree `.agent-cortex/worktrees/<parent-id>`.
73
+ - Feature PR gate: `feature/<parent-id>` → `epic/<epic-id>` (or → `main` for single-feature epics). Epic PR gate: `epic/<epic-id>` → `main`.
74
+ - Branch/worktree setup and the PR commands live in REFERENCE.md (_Feature branches and worktrees_, _Feature PR gate_).
66
75
 
67
- | Stage completed | Condition | Next action |
68
- |-----------------|-----------|-------------|
69
- | `code` | — | Closing the code chore unblocks the verify chore. |
70
- | `fix` | — | Closing the fix chore unblocks the verify chore. |
71
- | `verify` | `VERIFY_OUTCOME: PASS` | Closing the verify chore unblocks the review chore. |
72
- | `verify` | `VERIFY_OUTCOME: FAIL` | Run the **fix loop** (see REFERENCE.md). |
73
- | `review` | `REVIEW_OUTCOME: APPROVED` | Closing the review chore unblocks the document chore. |
74
- | `review` | `REVIEW_OUTCOME: CHANGES_REQUESTED` | Run the **fix loop** (see REFERENCE.md). |
75
- | `document` | — | Open/update feature PR immediately (`feature/<parent-id> -> epic/<epic-id>`), report the PR URL, then update the child HITL PR gate bead (`lifecycle:feature-pr`) with the PR URL/status. Wait for human to close that HITL bead after merge, then close the parent task bead. |
76
-
77
- 6. **Check for newly ready beads**: run `bd ready` and inspect results:
78
- - **Chore beads with `stage:*` label**: dispatch if in-flight count (from `bd list --status=in_progress --type=chore`) is < 5.
79
- - **Task beads without `implementation-type:*` label**: unexpected here — classification happens at planning time via `create-task`. Do not invoke `classify-bead`; treat as needs-refinement and note for shutdown.
80
- - If any feature PR gate bead (`lifecycle:feature-pr`, `implementation-type:hitl`) is open, do **not** schedule new parent features. Keep working only already in-flight chores.
81
- 7. **Check shutdown or pause**: if `bd list --status=in_progress --type=chore` returns no results AND `bd ready` returns no chore beads with `stage:*` labels:
82
- - If HITL gate beads are pending (`bd list -l lifecycle:feature-pr -l implementation-type:hitl` or `bd list -l awaiting-epic-pr-merge` returns results), proceed to **HITL Pause** (see REFERENCE.md).
83
- - Otherwise, proceed to **Shutdown** (see REFERENCE.md).
84
- 8. Regenerate `.agent-cortex/ralph/progress.md`.
76
+ ### 4. HITL pause and shutdown
85
77
 
86
- ---
78
+ - **HITL Pause** — when no chores are in-flight, none ready, and HITL gate beads are pending: regenerate `progress.md`, open/update epic PRs to `main` for multi-feature epics and tag each epic `awaiting-epic-pr-merge` (single-feature epics need none — their feature PRs already target `main`), run `bd dolt push`, output the Pending Human Action table, then stop completely until re-prompted.
79
+ - **Shutdown** — when all work is complete: regenerate `progress.md`, open/update epic PRs to `main` for multi-feature epics and tag them (single-feature epics need none), run `bd dolt push`, then output the Pending Human Action / Needs Refinement / cap-blocked / Pending Epic Review summaries that apply, or "All beads complete."
80
+
81
+ ## Red Flags
82
+
83
+ - Running as a background or delegated subagent instead of the interactive foreground agent.
84
+ - Spawning a stage runner via {{TOOL:bash}} or running a stage inline instead of {{TOOL:task}}.
85
+ - Editing bead files directly instead of using `bd` commands.
86
+ - Auto-merging a PR, or continuing past a feature/epic gate before a human merge.
87
+
88
+ ## Common Rationalizations
89
+
90
+ | Rationalization | Rebuttal |
91
+ |---|---|
92
+ | "I'll just run this one stage inline" | An orchestrator that executes stages stops being an orchestrator — the review gates exist to catch exactly that shortcut. |
93
+ | "One more task in flight won't hurt" | The 5-task cap bounds log polling, state bookkeeping, and PR sequencing; exceeding it loses track of in-flight work. |
94
+ | "The review passed, so I can merge" | Feature and epic PR merges are human-controlled; the gate exists so a person sees every change. |
95
+
96
+ ## Philosophy / rationale
97
+
98
+ - Orchestration state derives from beads so a crash loses nothing but an in-memory ID mapping: `state.json` holds only the poll-timer shellId and the agent-ID→bead mapping, never task state.
99
+ - Classification happens up-front at planning time (`create-task`), so the loop can trust `bd ready` instead of re-interpreting each bead's intent.
100
+ - Human review gates are non-negotiable because agent-authored changes still need a person to merge them.
101
+
102
+ ## Phase-gate checklists
103
+
104
+ - [ ] Init complete: `bd prime` held, gitignore entries present, workspace and state.json created, pipeline.json read, first `bd ready` classified, first chores dispatched.
105
+ - [ ] Event loop handed off: completion-detection mechanism running (or HITL Pause/Shutdown started) and `progress.md` regenerated.
106
+
107
+ ## Cross-skill references
108
+
109
+ - The `run-pipeline-stage` skill owns the stage-runner prompt, per-stage playbooks, the `---REPORT---` format, and fix-loop feedback beads — read it before dispatching any stage.
110
+ - The `create-task` skill owns `pipeline.json` and creates the `lifecycle:feature-pr` HITL gate beads.
111
+ - Do not invoke `classify-bead` from this loop — classification was already applied at planning time.
112
+
113
+ ## Verification checklist
87
114
 
88
- ## Constraints
89
-
90
- - **Always** run in **foreground** (interactive) mode. If you find yourself executing as a background task, immediately surface a warning to the user and ask them to re-run you in foreground mode.
91
- - **Never** write, edit, or create source code or documentation yourself.
92
- - **Never** edit bead task files directly — only use `bd` commands.
93
- - **ALWAYS call the {{TOOL:task}} tool to spawn subagents** — never use {{TOOL:bash}}, never run stages inline, never use any other tool. This is your only spawning mechanism.
94
- - **Always** derive orchestration state from beads — do not maintain a separate state file.
95
- - **Always** include the full `bd prime` output verbatim in every {{TOOL:task}} tool prompt.
96
- - **Always** keep the poll timer running (Copilot) — restart it immediately after it fires — **unless** the HITL pause condition is met (no chores in-flight, no `stage:*` chores ready, HITL gate beads pending), in which case proceed to **HITL Pause** (see REFERENCE.md) and stop instead. On PI there is no timer to keep alive — always keep one `wait_for_agents` call outstanding while agents are in-flight.
97
- - **Never** post empty poll updates to chat — only surface new log content.
98
- - **Max 5** tasks in-flight at once.
99
- - **Max fix rounds** per task as defined by `maxFixRounds` in `skills/planning/create-task/pipeline.json`.
100
- - **Always** execute chore subagents from the parent feature worktree (`.agent-cortex/worktrees/<parent-id>`), never from repo root.
101
- - **Never** auto-merge PRs. Merges are human-controlled.
102
- - **Only continue past a feature review gate after the feature PR HITL task bead is closed by a human (after merge into the epic branch).**
103
- - **Only continue past an epic review gate after the epic PR is merged into `main`.**
104
- - **When a feature hits the HITL PR gate, push and open the PR immediately and report the URL — do not wait for explicit approval to push or create the PR.**
105
- - **Always** bump the patch version in `plugin.json` as part of any commit that changes agent or skill files.
115
+ - [ ] Init ran once with observable results: `state.json` exists, `bd ready` was parsed, and the first chore beads are claimed.
116
+ - [ ] Every stage runner was spawned with {{TOOL:task}} from the parent's feature worktree, with the `---REPORT---` instruction in its prompt.
117
+ - [ ] In-flight count never exceeded 5, and fix loops respect `maxFixRounds` from `pipeline.json`.
118
+ - [ ] Feature and epic PRs were pushed and reported immediately at their gates, and nothing was auto-merged.
119
+ - [ ] `bd dolt push` and a final `progress.md` regeneration ran before HITL Pause/Shutdown, and the chat received no empty poll updates.
@@ -0,0 +1,22 @@
1
+ # Reference — run-pipeline-stage
2
+
3
+ Rarely-needed detail for the `run-pipeline-stage` skill. The main workflow lives in
4
+ `SKILL.md`; this file covers maintenance of its scripts package only.
5
+
6
+ ## Scripts package maintenance
7
+
8
+ The scripts package (`skills/workflow/run-pipeline-stage/scripts`, a private workspace
9
+ package `@agent-cortex/run-pipeline-stage-scripts`) backs the progress-doc generator used
10
+ in `SKILL.md` step 6.
11
+
12
+ Typecheck and test it with:
13
+
14
+ ```bash
15
+ pnpm --prefix skills/workflow/run-pipeline-stage/scripts typecheck
16
+ pnpm --prefix skills/workflow/run-pipeline-stage/scripts test
17
+ ```
18
+
19
+ ### Data-fetch / renderer split
20
+
21
+ The data-fetch layer (`parseBdList` / `parseBdShow`) is kept separate from the renderer
22
+ so the `bd` output format can be swapped without re-fetching.
@@ -1,120 +1,63 @@
1
1
  ---
2
2
  name: run-pipeline-stage
3
- description: Execute a single pipeline stage for a task. Use when you want to work through beads inline, pick up a specific stage bead, or work without the full ralph parallel orchestrator.
3
+ description: Execute a single pipeline stage for a bead (code, verify, review, document) via its playbook and dispatch rules, reporting the outcome in a fixed REPORT shape. Use when you want to "work through beads inline", "pick up a specific stage bead", or run one stage "without the full ralph orchestrator".
4
4
  ---
5
5
 
6
6
  # Run Pipeline Stage
7
7
 
8
- Execute a single pipeline stage. Stage beads (`code`, `verify`, `review`, `document`) are created by the `create-task` skill from the pipeline definition in `skills/planning/create-task/pipeline.json`; this skill handles executing one at a time.
8
+ Stage beads (`stage:code`, `stage:verify`, `stage:review`, `stage:document`, `stage:fix`) are created by the `create-task` skill from the pipeline definition in `skills/planning/create-task/pipeline.json`. This skill executes one stage at a time and reports the outcome.
9
9
 
10
- ## Quick Start
10
+ ## When to use
11
11
 
12
- 1. Run `bd prime` and hold the output for your own context. Subagents you spawn can run `bd prime` themselves if they need project context.
13
- 2. If no bead is specified, run `bd ready` and ask the user which to work on.
14
- 3. Claim the bead with `bd update <id> --claim`.
15
- 4. Read the bead's `stage:*` label to determine which stage to execute.
16
- 5. Load the universal stage runner prompt from `skills/workflow/run-pipeline-stage/prompts/stage-runner.md`.
17
- 6. Populate `<stage>` (from the bead's `stage:*` label), and follow `skills/workflow/run-pipeline-stage/playbooks/<stage>.md` for stage-specific behavior before spawning a subagent.
12
+ - "Work through beads inline" instead of running a full ralph fleet.
13
+ - "Pick up a specific stage bead" and execute it to a REPORT.
14
+ - Re-run a stage after a `stage:fix` chore completes.
15
+ - Follow a stage's playbook discipline with the right stage skills — tests, style, security, documentation.
18
16
 
19
- ## Progress Report
17
+ ## When NOT to use
20
18
 
21
- To generate a Markdown snapshot of all bead status (Mermaid dependency graph, active work table, completed list), run:
19
+ - Running many beads concurrently — that is the `ralph` skill.
20
+ - Creating or planning beads — use `create-task` or `plan`.
21
+ - Exploratory bead bookkeeping without a stage — that is `bd-tool`.
22
22
 
23
- ```bash
24
- # workspace must be the absolute path of the project — never . or $(pwd)
25
- workspace="/absolute/path/to/project"
26
- pnpm --prefix skills/workflow/run-pipeline-stage/scripts exec tsx generate-progress.ts --workspace "$workspace"
27
- ```
28
-
29
- To typecheck or test the scripts package:
30
-
31
- ```bash
32
- pnpm --prefix skills/workflow/run-pipeline-stage/scripts typecheck
33
- pnpm --prefix skills/workflow/run-pipeline-stage/scripts test
34
- ```
35
-
36
- The data-fetch layer (`parseBdList` / `parseBdShow`) is kept separate from the renderer so the output format can be swapped without re-fetching.
23
+ ## Workflow
37
24
 
38
- ## Progress Logging
39
-
40
- When running inside the ralph orchestrator, subagents must write structured progress lines to `.agent-cortex/ralph/ralph-{bead-id}.log` (appending) so ralph can surface live updates. The bead ID and log file path are provided in each prompt.
41
-
42
- **Format** — one entry per line:
43
- ```
44
- [ISO-timestamp] [bead-id] [stage] message
45
- ```
46
-
47
- **When to log:**
48
- - Stage start: `[...] [abc-123] [code] Stage started`
49
- - Stage transitions: `[...] [abc-123] [code→verify] Stage complete`, `[...] [abc-123] [verify→review] PASS`, `[...] [abc-123] [verify→fix] FAIL`
50
- - Key events only:
51
- - Test results: `Tests: 12 passed, 0 failed`
52
- - Lint result: `Lint: PASS` or `Lint: FAIL — <brief reason>`
53
- - Build errors: `Build failed: <brief reason>`
54
- - Security scan result: `Security scan: PASS` or `Security scan: FAIL — <finding>`
55
- - Any significant blocker or decision
56
-
57
- **How to write a log line:**
58
- ```bash
59
- mkdir -p .agent-cortex/ralph && echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] [bead-id] [stage] message" >> .agent-cortex/ralph/ralph-bead-id.log
60
- ```
61
-
62
- Do not log every file read or minor action — only transitions and key events.
63
-
64
- ## Pipeline
65
-
66
- The canonical pipeline is defined in `skills/planning/create-task/pipeline.json`. Current stages:
67
-
68
- | Stage | Notes |
69
- |-------|-------|
70
- | **code** | Implement the task using a test-driven approach |
71
- | **verify** | Run the project's test and lint commands and report the outcome |
72
- | **review** | Review the implementation for security, correctness, and alignment with task requirements |
73
- | **document** | Review changes and update documentation if key decisions, behaviour changes, or constraints were introduced |
74
-
75
- The fix loop (on verify or review failure) is controlled by `maxFixRounds` in `pipeline.json`.
76
-
77
- ### Stage Transitions
78
-
79
- Before dispatching a subagent for any stage, run these two commands (replacing `<id>` and `<stage>` with the bead ID and the stage about to start):
25
+ 1. Run `bd prime` and hold the output; subagents can run it themselves if they need context.
26
+ 2. If no bead was specified, run `bd ready` and ask the user which to work on.
27
+ 3. Claim the bead with `bd update <id> --claim` — the bead, not the prompt, is the source of truth.
28
+ 4. Read the bead's `stage:*` label — it names the stage to execute.
29
+ 5. Load the universal stage-runner prompt (`skills/workflow/run-pipeline-stage/prompts/stage-runner.md`), populate `<stage>`, and read the matching playbook (`skills/workflow/run-pipeline-stage/playbooks/<stage>.md`) for stage-specific rules.
30
+ 6. Tag the stage and regenerate the progress doc so pairing sessions stay current:
80
31
 
81
32
  ```bash
82
33
  bd tag <id> stage:<stage>
83
34
  # workspace must be the absolute path of the worktree — never . or $(pwd)
84
35
  workspace="/absolute/path/to/worktree"
85
- mkdir -p "$workspace/.agent-cortex/ralph"
86
36
  pnpm --prefix skills/workflow/run-pipeline-stage/scripts exec tsx generate-progress.ts --workspace "$workspace" > "$workspace/.agent-cortex/ralph/progress.md"
87
37
  ```
88
38
 
89
- This tags the bead with its current stage (beads are the source of truth for stage progress) and regenerates the progress doc so any inline pairing session stays current.
39
+ 7. Dispatch one subagent per stage with the composed prompt — spawn it with {{TOOL:task}} and end the prompt with the REPORT contract below.
40
+ 8. Route the REPORT through the Dispatch Rules: advance to the next stage, create a feedback bead, or close the parent.
41
+
42
+ Each step leaves observable state — a claimed bead, a `stage:` tag, a regenerated progress doc, and a REPORT that drives the next action.
90
43
 
91
44
  ## Dispatch Rules
92
45
 
93
- | Stage completed | Condition | Next action |
94
- |-----------------|-----------|-------------|
95
- | `code` | — | Run **verify** stage |
96
- | `verify` | `OUTCOME: SUCCESS` | Run **review** stage |
46
+ | Stage complete | Condition | Next action |
47
+ |---|---|---|
48
+ | `code` | — | Run **verify** |
49
+ | `verify` | `OUTCOME: SUCCESS` | Run **review** |
97
50
  | `verify` | `OUTCOME: BLOCKED` | Create a `stage:fix` chore (see _Feedback Beads_) |
98
- | `review` | `OUTCOME: SUCCESS` | Run **document** stage |
99
- | `review` | `OUTCOME: BLOCKED` and fixRounds < maxFixRounds | Create a `stage:fix` chore (see _Feedback Beads_); increment fixRounds |
100
- | `review` | `OUTCOME: BLOCKED` and fixRounds ≥ maxFixRounds | `bd update <parent-id> --status blocked --notes "max fix rounds reached"` — record for shutdown |
51
+ | `review` | `OUTCOME: SUCCESS` | Run **document** |
52
+ | `review` | `OUTCOME: BLOCKED` and fixRounds < maxFixRounds | Create a `stage:fix` chore; increment fixRounds |
53
+ | `review` | `OUTCOME: BLOCKED` and fixRounds ≥ maxFixRounds | `bd update <parent-id> --status blocked --notes "max fix rounds reached"`; record for shutdown |
101
54
  | `document` | — | `bd close <id>` — done |
102
55
 
103
- `maxFixRounds` is read from `skills/planning/create-task/pipeline.json` (`maxFixRounds` field, currently `4`).
104
-
105
- ### Fix loop flow
106
-
107
- When a `stage:fix` chore completes, the next stage depends on which stage triggered the fix:
108
- - **Fix after verify failure** → re-run **verify**
109
- - **Fix after review failure** → re-run **review**
110
-
111
- The orchestrator (ralph or inline agent) tracks fix rounds and re-dispatches the original stage after the fix chore completes.
56
+ `maxFixRounds` is read from `skills/planning/create-task/pipeline.json` (currently `4`). A fix chore re-runs the stage that failed — fix after verify → verify; fix after review → review.
112
57
 
113
58
  ## Feedback Beads
114
59
 
115
- When a stage reports a failure or rejection, the orchestrator creates a new chore bead whose description contains the feedback. This keeps feedback durable and visible, and makes the orchestrator's dispatch path uniform — it just picks up whatever `bd ready` returns.
116
-
117
- **Create the bead:**
60
+ On stage failure, create a chore bead whose description carries the feedback so the orchestrator's dispatch path stays uniform — it just picks up whatever `bd ready` returns:
118
61
 
119
62
  ```bash
120
63
  new_id=$(bd create "[<parent-id>] <title>" --type chore \
@@ -124,23 +67,37 @@ bd tag $new_id workflow:ralph
124
67
  bd dep add $new_id <parent-id> --type parent-child
125
68
  ```
126
69
 
127
- | Triggering outcome | Suggested title | Next stage tag | Feedback content to put in description |
70
+ | Triggering outcome | Suggested title | Next stage tag | Description content |
128
71
  |---|---|---|---|
129
72
  | `OUTCOME: BLOCKED` from verify | `Fix: verify failures` | `stage:code` | Full BLOCKING_ISSUES list |
130
73
  | `OUTCOME: BLOCKED` from review | `Fix: reviewer feedback` | `stage:fix` | Full BLOCKING_ISSUES list |
131
74
 
132
- After creating the feedback bead, do **not** dispatch a new agent immediately — the bead will appear in `bd ready` on the next cycle and be dispatched through the normal scheduling path. The stage that consumed the feedback from the REPORT is now finished; its agent result has been processed.
75
+ Do not dispatch a new agent right after creating the feedback bead — it appears in `bd ready` on the next cycle and flows through the normal scheduling path.
76
+
77
+ ## Progress Logging
78
+
79
+ Inside the ralph orchestrator, write one structured line per transition or key event to `.agent-cortex/ralph/ralph-{bead-id}.log`:
80
+
81
+ ```
82
+ [ISO-timestamp] [bead-id] [stage] message
83
+ ```
84
+
85
+ Log stage starts and completes, test/lint/build/security results, blockers, and decisions — not file reads or minor actions.
86
+
87
+ ```bash
88
+ mkdir -p .agent-cortex/ralph && echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] [bead-id] [stage] message" >> .agent-cortex/ralph/ralph-bead-id.log
89
+ ```
133
90
 
134
91
  ## Report Format
135
92
 
136
- Every subagent prompt **must** end with this instruction:
93
+ Every subagent prompt must end with the REPORT instruction:
137
94
 
138
95
  > End your response with a `---REPORT---` block in exactly this format:
139
96
  > ```
140
97
  > ---REPORT---
141
98
  > BEAD_ID: <id>
142
99
  > STAGE_COMPLETED: <code|verify|review|document>
143
- > SUMMARY: <2–3 sentence summary of what was done>
100
+ > SUMMARY: <2-3 sentence summary of what was done>
144
101
  > FILES_CHANGED: <comma-separated list, or "none">
145
102
  > OUTCOME: <SUCCESS|BLOCKED>
146
103
  > BLOCKING_ISSUES: ← only if OUTCOME is BLOCKED
@@ -148,4 +105,45 @@ Every subagent prompt **must** end with this instruction:
148
105
  > ---
149
106
  > ```
150
107
 
151
- Subagents report facts. **Do not ask subagents to suggest or predict the next step.**
108
+ Subagents report facts — do not ask them to suggest or predict the next step.
109
+
110
+ ## Red Flags
111
+
112
+ - Dispatching a subagent before tagging the stage — beads are the only source of truth for stage progress.
113
+ - Composing a subagent prompt without the REPORT contract — the output cannot be routed.
114
+ - Creating a feedback bead and then dispatching anyway — bypasses the fix-round accounting and parent-child dependency graph.
115
+ - Skipping the playbook "because the stage is simple" — playbooks carry the per-stage discipline the pipeline relies on.
116
+
117
+ ## Common Rationalizations
118
+
119
+ | "The stage is small — I'll just run it directly" | The stage skills and playbook keep output conformant; skipping them produces work that loops back as a fix chore. |
120
+ | "I'll dispatch the fix right away — faster than a chore bead" | Feedback beads keep dispatch uniform and durable; direct re-dispatch breaks fix-round accounting and the dependency graph. |
121
+ | "The stage is obvious from the prompt — no tag needed" | Beads are the source of truth; prompt drift desynchronises the progress doc, the log, and downstream dispatch. |
122
+
123
+ ## Cross-skill references
124
+
125
+ - `create-task` owns `pipeline.json` — stages, `maxFixRounds`, and the stage templates.
126
+ - `bd-tool` covers bead mechanics beyond the commands in this skill.
127
+ - `ralph` runs many stage beads concurrently and consumes this skill's log and REPORT contracts.
128
+ - Playbooks delegate to stage skills: `tdd`/`style-code`/`style-tests` (code), `review-security` (review), `style-documentation` (document).
129
+
130
+ ## Examples
131
+
132
+ - Input: a `stage:verify` bead reporting `OUTCOME: BLOCKED` with two failing tests → Output: a `Fix: verify failures` chore tagged `stage:code` whose description lists both failures; verify closes and the chore is picked up on the next `bd ready` cycle.
133
+ - Input: a `stage:document` bead reporting `OUTCOME: SUCCESS` → Output: the parent bead is closed with `bd close <id>` and that task's pipeline ends.
134
+
135
+ ## Philosophy / rationale
136
+
137
+ - Beads hold all orchestration state — there is no separate state file to drift out of sync.
138
+ - Subagents return facts in one fixed REPORT shape so routing stays mechanical across stages and harnesses.
139
+ - Feedback as beads, not direct re-dispatches, puts every agent on a single scheduling path and keeps every decision visible in the dependency graph.
140
+
141
+ ## Verification checklist
142
+
143
+ - [ ] Bead claimed (`bd update <id> --claim`) before any executor works it.
144
+ - [ ] `bd tag <id> stage:<stage>` run and progress doc regenerated before dispatch.
145
+ - [ ] Correct playbook read and followed for the stage; stage skills invoked where the playbook says.
146
+ - [ ] Composed prompt ends with the complete REPORT contract block.
147
+ - [ ] Progress log lines written for every stage transition and key result.
148
+ - [ ] REPORT routed per the Dispatch Rules — next stage, feedback bead, or `bd close <id>`.
149
+ - [ ] Feedback beads carry the full BLOCKING_ISSUES content and the parent-child dependency.
@@ -1,7 +1,5 @@
1
1
  import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
4
- import { join } from 'node:path';
5
3
  import {
6
4
  parseListLine,
7
5
  parseBdList,
@@ -144,6 +142,12 @@ describe('parseListLine', () => {
144
142
  assert.deepEqual(result, { id: 'proj-eee', status: 'deferred', title: 'Deferred task' });
145
143
  });
146
144
 
145
+ it('parses current bd list format without the priority marker column', () => {
146
+ // Current bd emits `{STATUS} {ID} P{N} {TITLE}`; the `●` before P{N} is legacy.
147
+ const result = parseListLine('◐ proj-bbb P2 Second task');
148
+ assert.deepEqual(result, { id: 'proj-bbb', status: 'in_progress', title: 'Second task' });
149
+ });
150
+
147
151
  it('returns null for separator/summary lines', () => {
148
152
  assert.equal(parseListLine('---'), null);
149
153
  assert.equal(parseListLine('Total: 5 issues'), null);
@@ -676,108 +680,3 @@ describe('fetchBeads', () => {
676
680
  assert.equal(beads.filter((b) => b.id === 'proj-child1').length, 1);
677
681
  });
678
682
  });
679
-
680
- // ─── Behavior 11: plugin session-start hook wiring ────────────────────────────
681
-
682
- describe('plugin session-start hook wiring', () => {
683
- const repoRoot = join(import.meta.dirname, '..', '..', '..');
684
-
685
- it('declares a hooks config path in plugin.json', () => {
686
- const pluginJsonRaw = readFileSync(join(repoRoot, 'plugin.json'), 'utf8');
687
- const pluginJson = JSON.parse(pluginJsonRaw) as { hooks?: unknown };
688
- assert.equal(pluginJson.hooks, 'hooks.json');
689
- });
690
-
691
- it('defines a sessionStart prompt hook that injects baseline context', () => {
692
- const hooksJsonRaw = readFileSync(join(repoRoot, 'hooks.json'), 'utf8');
693
- const hooksJson = JSON.parse(hooksJsonRaw) as {
694
- hooks?: { sessionStart?: Array<{ type?: unknown; prompt?: unknown }> };
695
- };
696
- assert.ok(Array.isArray(hooksJson.hooks?.sessionStart));
697
- const sessionStartHooks = hooksJson.hooks?.sessionStart ?? [];
698
- assert.ok(
699
- sessionStartHooks.some(
700
- (entry) => entry.type === 'prompt' && typeof entry.prompt === 'string' && entry.prompt.length > 0,
701
- ),
702
- );
703
- });
704
- });
705
-
706
- // ─── Behavior 12: skill anatomy documentation contracts ───────────────────────
707
-
708
- describe('skill anatomy documentation contracts', () => {
709
- const repoRoot = join(import.meta.dirname, '..', '..', '..');
710
-
711
- it('includes the canonical skill anatomy doc', () => {
712
- const anatomyDoc = readFileSync(join(repoRoot, 'docs', 'skills', 'skill-anatomy.md'), 'utf8');
713
- assert.ok(anatomyDoc.length > 0);
714
- });
715
-
716
- it('documents canonical anatomy and an annotated template acceptance checklist', () => {
717
- const anatomyDoc = readFileSync(join(repoRoot, 'docs', 'skills', 'skill-anatomy.md'), 'utf8');
718
- assert.match(anatomyDoc, /canonical skill anatomy/i);
719
- assert.match(anatomyDoc, /annotated template/i);
720
- assert.match(anatomyDoc, /acceptance criteria|checklist/i);
721
- });
722
- });
723
-
724
- // ─── Behavior 13: skill anatomy expanded documentation requirements ────────────
725
-
726
- describe('skill anatomy expanded documentation requirements', () => {
727
- const repoRoot = join(import.meta.dirname, '..', '..', '..');
728
-
729
- it('documents required facets for each optional section', () => {
730
- const anatomyDoc = readFileSync(join(repoRoot, 'docs', 'skills', 'skill-anatomy.md'), 'utf8');
731
- assert.match(anatomyDoc, /optional sections/i);
732
- assert.match(anatomyDoc, /what it is/i);
733
- assert.match(anatomyDoc, /example snippet/i);
734
- assert.match(anatomyDoc, /when to include/i);
735
- assert.match(anatomyDoc, /when to omit/i);
736
- });
737
-
738
- it('requires placement of "When NOT to use" adjacent to "When to use"', () => {
739
- const anatomyDoc = readFileSync(join(repoRoot, 'docs', 'skills', 'skill-anatomy.md'), 'utf8');
740
- assert.match(anatomyDoc, /##\s+When to use[\s\S]{0,400}##\s+When NOT to use/i);
741
- });
742
-
743
- it('keeps the full annotated SKILL.md template at the end of the document', () => {
744
- const anatomyDoc = readFileSync(join(repoRoot, 'docs', 'skills', 'skill-anatomy.md'), 'utf8').trimEnd();
745
- assert.match(anatomyDoc, /##\s+Annotated template[\s\S]*```md[\s\S]*```$/i);
746
- });
747
- });
748
-
749
- // ─── Behavior 15: research doc promotion/linking contracts ─────────────────────
750
-
751
- describe('research doc promotion/linking contracts', () => {
752
- const repoRoot = join(import.meta.dirname, '..', '..', '..');
753
-
754
- it('links each research doc from docs/inspirations.md and marks each as promoted', () => {
755
- const inspirationsDoc = readFileSync(join(repoRoot, 'docs', 'inspirations.md'), 'utf8');
756
- const researchDir = join(repoRoot, 'docs', 'research');
757
- const researchFiles = readdirSync(researchDir).filter((fileName) => fileName.endsWith('.md'));
758
-
759
- for (const researchFile of researchFiles) {
760
- assert.match(inspirationsDoc, new RegExp(`\\(research\\/${researchFile.replace('.', '\\.')}\\)`));
761
- const researchDoc = readFileSync(join(researchDir, researchFile), 'utf8');
762
- assert.match(researchDoc, /promoted research note/i);
763
- assert.match(researchDoc, /\[Inspirations\]\(\.\.\/inspirations\.md\)/i);
764
- }
765
- });
766
-
767
- it('does not keep promoted research docs in .agent-cortex/working-docs (true move, not copy)', () => {
768
- const researchDir = join(repoRoot, 'docs', 'research');
769
- const researchFiles = readdirSync(researchDir).filter((fileName) => fileName.endsWith('.md'));
770
- const repoWorkingDocsDir = join(repoRoot, '.agent-cortex', 'working-docs');
771
- const workingDocSearchRoots = [repoWorkingDocsDir, join(repoWorkingDocsDir, 'research')];
772
-
773
- for (const workingDocsDir of workingDocSearchRoots) {
774
- if (!existsSync(workingDocsDir)) {
775
- continue;
776
- }
777
-
778
- for (const researchFile of researchFiles) {
779
- assert.equal(existsSync(join(workingDocsDir, researchFile)), false);
780
- }
781
- }
782
- });
783
- });