@jaybeeuu/agent-cortex 1.38.1 → 1.39.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.
- package/AGENTS.md +3 -1
- package/CHANGELOG.md +30 -0
- package/README.md +34 -16
- package/agents/README.md +7 -5
- package/agents/ralph-plan/agent.md +1 -1
- package/agents/ralph-plan.agent.md +1 -1
- package/bin/agent-cortex.mjs +13 -5
- package/bin/installers/claude.mjs +129 -15
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/agents/ralph-plan.md +1 -1
- package/docs/ideas/extension-manifests.md +75 -0
- package/docs/ideas/record-ideas-as-beads.md +115 -0
- package/docs/ideas/subagent-visibility.md +72 -0
- package/docs/ideas/task-session-context.md +89 -0
- package/docs/research/skill-design-research.md +4 -4
- package/docs/research/skill-improvements-analysis.md +1 -1
- package/docs/skills/skill-anatomy.md +38 -2
- package/docs/technical-direction/migration-execution-labels.md +132 -0
- package/lib/cli.mjs +9 -3
- package/package.json +2 -2
- package/plugin.json +1 -1
- package/pnpm-workspace.yaml +1 -1
- package/skills/engineering/design-an-interface/SKILL.md +78 -58
- package/skills/engineering/grill-with-docs/REFERENCE.md +78 -0
- package/skills/engineering/grill-with-docs/SKILL.md +66 -63
- package/skills/engineering/improve-codebase-architecture/SKILL.md +66 -48
- package/skills/engineering/technical-direction/FORMAT.md +38 -0
- package/skills/engineering/technical-direction/SKILL.md +70 -77
- package/skills/planning/classify-bead/SKILL.md +59 -35
- package/skills/planning/create-task/REFERENCE.md +40 -0
- package/skills/planning/create-task/SKILL.md +70 -66
- package/skills/planning/create-task/scripts/create-chores.ts +6 -1
- package/skills/planning/create-task/scripts/node_modules/.bin/tsc +21 -0
- package/skills/planning/create-task/scripts/node_modules/.bin/tsserver +21 -0
- package/skills/planning/create-task/scripts/node_modules/.bin/tsx +21 -0
- package/skills/planning/prd-to-tasks/REFERENCE.md +66 -0
- package/skills/planning/prd-to-tasks/SKILL.md +86 -170
- package/skills/planning/record-idea/FORMAT.md +44 -0
- package/skills/planning/record-idea/SKILL.md +70 -53
- package/skills/planning/request-refactor-plan/FORMAT.md +45 -0
- package/skills/planning/request-refactor-plan/SKILL.md +57 -46
- package/skills/planning/write-a-prd/FORMAT.md +54 -0
- package/skills/planning/write-a-prd/SKILL.md +49 -48
- package/skills/planning/write-a-ticket/SKILL.md +68 -53
- package/skills/productivity/handoff/SKILL.md +12 -0
- package/skills/productivity/init-beads/SKILL.md +48 -40
- package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsc +21 -0
- package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsserver +21 -0
- package/skills/productivity/validate-agent-dir/scripts/node_modules/.bin/tsx +21 -0
- package/skills/productivity/write-a-skill/SKILL.md +2 -1
- package/skills/review/maintain-agent-docs/SKILL.md +71 -51
- package/skills/workflow/hitl-collab/SKILL.md +86 -17
- package/skills/workflow/ralph/REFERENCE.md +22 -17
- package/skills/workflow/ralph/SKILL.md +88 -74
- package/skills/workflow/run-pipeline-stage/REFERENCE.md +22 -0
- package/skills/workflow/run-pipeline-stage/SKILL.md +91 -93
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +6 -107
- package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsc +21 -0
- package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsserver +21 -0
- package/skills/workflow/run-pipeline-stage/scripts/node_modules/.bin/tsx +21 -0
- package/test/claude-installer.test.mjs +248 -0
- package/token-map.README.md +5 -3
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ralph
|
|
3
|
-
description: "Run all pending beads end-to-end
|
|
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
|
-
#
|
|
6
|
+
# Ralph
|
|
7
7
|
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
12
|
+
## When to use
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
24
|
+
## Workflow
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
### 1. Initialize (run once at startup)
|
|
27
27
|
|
|
28
|
-
1. Run `bd prime
|
|
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.
|
|
31
|
-
4.
|
|
32
|
-
5.
|
|
33
|
-
6.
|
|
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
|
|
36
|
-
- **Task labelled `implementation-type:hitl`**: skip — record the
|
|
37
|
-
7. For each ready chore bead (up to 5),
|
|
38
|
-
8.
|
|
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
|
-
|
|
48
|
+
On each completion notification (background agent finished, or the poll timer fired):
|
|
49
49
|
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
###
|
|
69
|
+
### 3. Branching and review model
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
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
|
|
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
|
-
|
|
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
|
-
##
|
|
10
|
+
## When to use
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
##
|
|
17
|
+
## When NOT to use
|
|
20
18
|
|
|
21
|
-
|
|
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
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
|
94
|
-
|
|
95
|
-
| `code` | — | Run **verify**
|
|
96
|
-
| `verify` | `OUTCOME: SUCCESS` | Run **review**
|
|
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**
|
|
99
|
-
| `review` | `OUTCOME: BLOCKED` and fixRounds < maxFixRounds | Create a `stage:fix` chore
|
|
100
|
-
| `review` | `OUTCOME: BLOCKED` and fixRounds ≥ maxFixRounds | `bd update <parent-id> --status blocked --notes "max fix rounds reached"
|
|
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` (
|
|
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
|
-
|
|
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 |
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
});
|