@yemi33/minions 0.1.2390 → 0.1.2392

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.
@@ -1,448 +1,507 @@
1
1
  # Minions Concept Dictionary
2
2
 
3
3
  > Plain-English definitions for every first-class noun in the Minions system. This is the team's
4
- > shared language before we redesign the UI; it is intentionally factual design opinions live in
4
+ > shared language before we redesign the UI; it is intentionally factual -- design opinions live in
5
5
  > [`architecture-suggestions.md`](./architecture-suggestions.md).
6
6
  >
7
- > Every backing claim is anchored to a file path and line number. If you change the code, please
8
- > update the line numbers here too.
7
+ > Backing claims use stable `path#symbol` references instead of exact source-line anchors. Search
8
+ > for the named symbol when the implementation moves.
9
9
 
10
10
  ---
11
11
 
12
12
  ## How the system fits together (one paragraph)
13
13
 
14
- A **human** types something into the **Command Center** chat. CC turns that into a **Work Item**
15
- (or a **Plan**, **Note**, **Schedule**, **Watch**, etc.) by emitting an `===ACTIONS===` JSON block.
16
- The **Engine** wakes up on its 60-second tick, looks at the pending **Dispatch Queue**, picks an
17
- **Agent** (a Minion / Team Member) by consulting **Routing**, spawns a CLI process for that agent
18
- (Claude or Copilot), and waits. The agent reads its **Charter**, the **Playbook** for the work
19
- type, the project's **CLAUDE.md**, the **Pinned Context**, the team's **Notes** and
20
- **Knowledge Base**, then does the work usually opening a **Pull Request**. When the agent exits,
21
- it writes a **Completion** report; the engine syncs the PR back, marks the Work Item done, and
22
- runs the **Inbox** through the **KB Sweep** so the team's memory grows. **Watches**, **Schedules**,
23
- and **Pipelines** are the three ways things happen without a human typing.
14
+ A **human** asks the **Command Center** to inspect or change the system. CC uses the dashboard's
15
+ existing `/api/*` routes, most often to create a **Work Item**, **Plan**, **Note**, **Schedule**, or
16
+ **Watch**. On its default 10-second tick, the **Engine** considers the pending **Dispatch Queue**,
17
+ consults **Routing**, selects an **Agent**, and invokes the configured runtime adapter (Claude,
18
+ Copilot, or Codex). The agent receives its **Charter**, the work-type **Playbook**, project
19
+ instructions, and bounded team memory, then does the work -- often opening a **Pull Request**.
20
+ Before exit it writes a trusted **Completion** JSON report; lifecycle code uses that report to
21
+ finish the Work Item and attach durable artifacts. **Watches**, **Schedules**, and **Pipelines**
22
+ provide persistent automation without a new human chat turn.
24
23
 
25
24
  ---
26
25
 
27
26
  ## 1. Command Center (CC)
28
27
 
29
- **What it is.** The chat box on the dashboard's home page. It's a Claude (or Copilot) instance
30
- running with a beefy system prompt that knows about your projects, agents, work items, and the
31
- JSON action grammar. You talk to CC; CC dispatches Work Items, creates Plans, files Notes, opens
32
- Watches, etc. It is the primary human-to-fleet interface.
28
+ **What it is.** The conversational control surface on the dashboard home page. CC runs through the
29
+ runtime adapter selected by `resolveCcCli`, with a system prompt that describes the live API. It can
30
+ answer questions and use direct localhost `/api/*` calls to change Minions state.
31
+
32
+ CC actions are direct API writes correlated to the current turn through `X-CC-Turn-Id`; the
33
+ dashboard then builds synthetic action results for the UI.
33
34
 
34
35
  **Where it lives.**
36
+
35
37
  - System prompt: `prompts/cc-system.md`
36
- - Per-tab and global session state: `engine/state.db` (`cc_sessions`).
37
- - Direct CLI invocation: `engine/llm.js` `callLLM({ direct: true })` — bypasses
38
- `spawn-agent.js` and runs the runtime CLI itself.
39
-
40
- **Backing classes / functions.**
41
- - Streaming endpoint handler: `dashboard.js` line 7194 (`/api/command-center/stream` → `handleCommandCenterStream`).
42
- - Non-streaming handler: `dashboard.js` line 7193 (`/api/command-center` → `handleCommandCenter`).
43
- - Action parser: `parseCCActions` / `executeCCActions` (search `dashboard.js` for `parseCCActions`).
44
- - Tab session bookkeeping: dashboard.js around line 1185 (`/api/cc-sessions/:id`).
45
-
46
- **How the existing dashboard surfaces it.** `dashboard/pages/home.html` the Command Center is
47
- the top-of-page input box. There is also a "past commands" / history modal.
48
-
49
- **Endpoints (`dashboard.js` line refs from the `ROUTES` table starting at line 6807).**
50
-
51
- | Method | Path | Line | Purpose |
52
- |--------|------|------|---------|
53
- | POST | `/api/command-center` | 7193 | Single-shot CC turn |
54
- | POST | `/api/command-center/stream` | 7194 | SSE-streaming CC turn |
55
- | POST | `/api/command-center/new-session` | 7191 | Clear active CC session |
56
- | POST | `/api/command-center/abort` | 7192 | Cancel an in-flight stream |
57
- | GET | `/api/cc-sessions` | 7195 | List per-tab sessions |
58
- | DELETE | `/api/cc-sessions/:id` | (see line 1185) | Close a tab |
59
-
60
- **Relationships.** CC is the *creator* of almost every other concept on this page (Work Item,
61
- Plan, Note, Schedule, Watch, Knowledge entry, Pinned note). Per-call cap is
62
- `ENGINE_DEFAULTS.ccMaxTurns` (50, `engine/shared.js` line 860+); sessions themselves never expire.
38
+ - Session records: `engine/state.db` table `cc_sessions`
39
+ - Shared invocation path: `dashboard.js#ccCall` and `engine/llm.js#callLLM`
40
+ - Runtime selection: `engine/shared.js#resolveCcCli` and `engine/runtimes/index.js#resolveRuntime`
41
+
42
+ **Backing symbols.**
43
+
44
+ - Request handlers: `dashboard.js#handleCommandCenter` and
45
+ `dashboard.js#handleCommandCenterStream`
46
+ - Turn/action correlation: `dashboard.js#_ccTurnCreations` and
47
+ `dashboard.js#_buildSyntheticActionResultsForTurn`
48
+ - Session persistence: `engine/small-state-store.js` CC-session helpers
49
+ - Per-response tool-turn cap: `engine/shared.js#ENGINE_DEFAULTS.ccMaxTurns` (default 50)
50
+
51
+ **Existing dashboard.** `dashboard/pages/home.html` contains the classic CC surface; the Slim home
52
+ surface uses the same server handlers and sessions.
53
+
54
+ **Endpoints.**
55
+
56
+ | Method | Path | Purpose |
57
+ |---|---|---|
58
+ | POST | `/api/command-center` | Non-streaming CC turn |
59
+ | POST | `/api/command-center/stream` | SSE-streaming CC turn |
60
+ | POST | `/api/command-center/triage` | Isolated, watch-driven headless turn |
61
+ | POST | `/api/command-center/new-session` | Clear the active CC session |
62
+ | POST | `/api/command-center/abort` | Abort an in-flight turn |
63
+ | GET | `/api/cc-sessions` | List per-tab session metadata |
64
+ | POST | `/api/cc-sessions/warm` | Pre-warm a compatible worker pool |
65
+ | DELETE | `/api/cc-sessions/:id` | Delete a tab's persisted session |
66
+
67
+ **Relationships.** CC is a human-facing client of the same APIs used by the rest of the dashboard.
68
+ It creates and updates other concepts; it is not a second state store or a privileged orchestration
69
+ path.
63
70
 
64
71
  ---
65
72
 
66
73
  ## 2. Work Item
67
74
 
68
- **What it is.** A unit of work the engine can dispatch to an agent. Has a title, type
69
- (`implement`, `fix`, `review`, ), priority, optional project, and lifecycle state. Most things on
70
- the home page eventually reduce to a Work Item.
75
+ **What it is.** A unit of work the engine can dispatch to an agent. It has a title, canonical work
76
+ type (`implement`, `fix`, `review`, and so on), priority, optional project and agent hints,
77
+ dependencies, and lifecycle state.
71
78
 
72
79
  **Where it lives.**
73
- - Durable records: `engine/state.db` `work_items`, keyed by central/project scope.
74
- - In-flight dispatch rows: `engine/state.db` `dispatches`.
75
-
76
- **Backing classes / functions.**
77
- - Status constants: `engine/shared.js` line 1348 (`WI_STATUS`).
78
- - Type constants: `engine/shared.js` line 1359 (`WORK_TYPE`).
79
- - `addToDispatch`: `engine/dispatch.js` line 128.
80
- - `updateWorkItemStatus`: `engine/lifecycle.js` line 484 (validates against `WI_STATUS`).
81
- - `isItemCompleted`: `engine/lifecycle.js` line 477.
82
- - Lifecycle: pending → dispatched → done | failed; failed auto-retries up to
83
- `ENGINE_DEFAULTS.maxRetries`.
84
-
85
- **Existing dashboard.** `dashboard/pages/work.html` — the side-panel "Work Items" tab with
86
- pending / active / completed columns.
87
-
88
- **Endpoints (all under `/api/work-items*`, `dashboard.js` lines 6852–6888).**
89
- - `POST /api/work-items` (6852) — create
90
- - `POST /api/work-items/update` (6853) edit
91
- - `POST /api/work-items/retry` (6854) back to pending
92
- - `POST /api/work-items/delete` (6855) — kill + remove
93
- - `POST /api/work-items/cancel` (6856) — cancel with reason
94
- - `POST /api/work-items/archive` (6857) — move to archive
95
- - `GET /api/work-items/archive` (6858) list archive
96
- - `POST /api/work-items/reopen` (6859) done/failed pending
97
- - `POST /api/work-items/feedback` (6860) — 👍 / 👎 → inbox note
98
-
99
- **Relationships.** A Work Item is the *body* the **Dispatch Queue** carries. It points to a
100
- **Project**, an **Agent** (post-dispatch), and a **Pull Request** (post-completion). Materialized
101
- from a **PRD Item** via the plan-to-prd flow. **Pipelines** can declare Work Items as stages.
80
+
81
+ - Durable records: `engine/state.db` table `work_items`
82
+ - In-flight execution records: `engine/state.db` table `dispatches`
83
+ - Read/write facade: `engine/work-items-store.js`
84
+
85
+ **Backing symbols.**
86
+
87
+ - Statuses: `engine/shared.js#WI_STATUS`
88
+ - Work types: `engine/shared.js#WORK_TYPE`
89
+ - Queue admission: `engine/dispatch.js#addToDispatch`
90
+ - Lifecycle updates: `engine/lifecycle.js#updateWorkItemStatus`
91
+ - Completion predicate: `engine/lifecycle.js#isItemCompleted`
92
+
93
+ The common path is `pending` (or `queued`) -> `dispatched` -> `done` or `failed`. `paused`,
94
+ `decomposed`, and `cancelled` are also canonical states. Failures can retry up to
95
+ `ENGINE_DEFAULTS.maxRetries`, with per-agent reassignment governed separately.
96
+
97
+ **Existing dashboard.** `dashboard/pages/work.html` is the classic Work Items screen. Slim embeds
98
+ that same screen for queued-work details rather than maintaining a second renderer.
99
+
100
+ **Endpoints.**
101
+
102
+ - `GET /api/work-items` -- list enriched, size-bounded records
103
+ - `GET /api/work-items/<id>` -- fetch one full record for detail/edit
104
+ - `POST /api/work-items` -- create
105
+ - `POST /api/work-items/update` -- edit
106
+ - `POST /api/work-items/retry` -- return a failed/dispatched item to pending
107
+ - `POST /api/work-items/cancel` and `/delete` -- stop and remove/cancel
108
+ - `POST /api/work-items/archive` and `GET /api/work-items/archive`
109
+ - `POST /api/work-items/reopen`
110
+ - `POST /api/work-items/feedback`
111
+
112
+ **Relationships.** A Work Item is the durable intent carried by a **Dispatch**. It may point to a
113
+ **Project**, depend on other Work Items, be materialized from a **PRD Item**, and acquire one or more
114
+ associated **Pull Request** records over its lifecycle.
102
115
 
103
116
  ---
104
117
 
105
118
  ## 3. Plan
106
119
 
107
- **What it is.** A markdown document in `plans/` describing what should be built and why. The plan
108
- flow is: human (or agent) writes plan → human approves → `plan-to-prd` agent converts it to a
109
- **PRD** JSON → materializer creates **Work Items** with `depends_on` edges → engine executes them
110
- → verify task auto-runs → human archives.
120
+ **What it is.** A human-readable Markdown proposal that is approved before execution. The normal
121
+ flow is:
122
+
123
+ ```
124
+ Plan Markdown -> plan-to-prd Work Item -> PRD rows -> Work Items -> verify Work Item(s)
125
+ ```
126
+
127
+ The `plan-to-prd` agent writes `agents/<id>/prd-result.json`. On successful completion,
128
+ `engine/lifecycle.js` validates that sidecar against the expected plan and imports it into the SQL
129
+ PRD store before the plan-to-PRD Work Item can finish.
111
130
 
112
131
  **Where it lives.**
113
- - Drafts: `plans/*.md`.
114
- - Archived: `plans/archive/*.md`.
115
- - Status field is on the PRD JSON twin (see PRD).
116
-
117
- **Backing classes / functions.**
118
- - Status constants: `engine/shared.js` line 1365 (`PLAN_STATUS = { ACTIVE, AWAITING_APPROVAL,
119
- APPROVED, PAUSED, REJECTED, COMPLETED, REVISION_REQUESTED }`).
120
- - Atomic dispatch: `queuePlanToPrd` (used by every plan-to-prd path).
121
- - Plan completion / archival: `engine/lifecycle.js`
122
- - `checkPlanCompletion` line 22
123
- - `archivePlan` line 355
124
- - `cleanupPlanWorktrees` line 415.
125
- - Plan dirs: `engine/pipeline.js` line 23 (`PLANS_DIR`).
126
-
127
- **Existing dashboard.** `dashboard/pages/plans.html` — plan browser, approve / reject / archive
128
- buttons.
129
-
130
- **Slim dashboard.** A **Plans** cockpit tile (`data-tile="plans"` in `dashboard/slim/body.html`)
131
- opens `#slim-plans-modal` — a two-tab control panel (**Plans** / **PRD**) rendered lazily by
132
- `dashboard/slim/js/plans.js` into `#slim-plans-body`. The **Plans** tab lists the `.md` drafts with
133
- their status and wires the lifecycle actions (approve / execute / archive at minimum, plus reject /
134
- pause / regenerate / delete / unarchive) to the **existing** `GET /api/plans`, `GET /api/plans/:file`,
135
- and the `POST /api/plans/*` endpoints — **no new server routes** are added. The tile's count is
136
- fetched lazily via `GET /api/plans` (`loadPlansCounts`), *not* from `/api/status` (the status
137
- snapshot carries no plans/PRD count). The whole surface lives under `dashboard/slim/` and is gated
138
- solely by the **`slim-ux`** feature flag — there is **no new `engine.*` flag or Settings-parity
139
- toggle**; Slim itself is the gate. The renderer exposes `openPlansModal` / `renderPlansTab` /
140
- `renderPlansTile` / `loadPlansCounts` in the shared Slim IIFE scope; tile→modal/tab binding is wired
141
- by `modals-tiles.js` + `status.js`.
142
-
143
- **Endpoints (`dashboard.js` lines 6952–6963).**
144
- - `GET /api/plans` (6952) — list .md drafts + .json PRDs
145
- - `POST /api/plans/trigger-verify` (6953)
146
- - `POST /api/plans/approve` (6954) — kicks off plan-to-prd
147
- - `POST /api/plans/pause` (6955)
148
- - `POST /api/plans/execute` (6956)
149
- - `POST /api/plans/reject` (6957)
150
- - `POST /api/plans/regenerate` (6958)
151
- - `POST /api/plans/delete` (6959)
152
- - `POST /api/plans/archive` (6960) — manual archive
153
- - `POST /api/plans/unarchive` (6961)
154
- - `POST /api/plans/revise` (6962)
155
- - `POST /api/plans/discuss` (6963)
156
- - `POST /api/plans/create` (7055)
157
-
158
- **Relationships.** Plan ↔ **PRD** ↔ **Work Items** is a one-to-one-to-many chain. **Pipelines**
159
- can include `plan` stages. **Verification** is owned by the plan: when all work items finish, a
160
- verify Work Item auto-spawns.
132
+
133
+ - Live source documents: `plans/*.md`
134
+ - Archived source documents: `plans/archive/*.md`
135
+ - Executable lifecycle/status: the corresponding SQL-backed **PRD**
136
+
137
+ Executable lifecycle state is SQL-backed. Manual archive moves the Markdown source to
138
+ `plans/archive/` and marks the authoritative PRD archived in place.
139
+
140
+ **Backing symbols.**
141
+
142
+ - Plan statuses: `engine/shared.js#PLAN_STATUS`
143
+ - Atomic conversion enqueue: `engine/shared.js#queuePlanToPrd`
144
+ - Completion gate: `engine/lifecycle.js#checkPlanCompletion`
145
+ - Manual archive: `engine/lifecycle.js#archivePlan`
146
+ - Plan worktree cleanup: `engine/lifecycle.js#cleanupPlanWorktrees`
147
+ - PRD sidecar import: `engine/lifecycle.js#runPostCompletionHooks`
148
+
149
+ **Existing dashboard.** `dashboard/pages/plans.html` owns the classic Plans and PRD tabs and all
150
+ lifecycle actions.
151
+
152
+ **Slim dashboard.** The Plans cockpit tile lazily gets its active count from `GET /api/plans`
153
+ through `dashboard/slim/js/plans.js#loadPlansCounts`. Opening the tile embeds the literal classic
154
+ `/plans?embed=1` screen via `dashboard/slim/js/modals-tiles.js#renderPlansBody`; Slim does not carry
155
+ a parallel Plans/PRD renderer.
156
+
157
+ **Endpoints.**
158
+
159
+ - `GET /api/plans` -- list Markdown plans plus SQL-backed PRD summaries
160
+ - `POST /api/plans/create`
161
+ - `POST /api/plans/approve`, `/execute`, `/pause`, `/reject`, `/revise`
162
+ - `POST /api/plans/regenerate`
163
+ - `POST /api/plans/trigger-verify`
164
+ - `POST /api/plans/archive`, `/unarchive`, `/delete`
165
+ - `POST /api/plans/discuss`
166
+
167
+ **Relationships.** A Plan has one executable PRD and many materialized Work Items. A cross-repo
168
+ plan can fan items into multiple projects and create one verify Work Item per touched project.
169
+ Archiving remains an explicit human action after verification.
161
170
 
162
171
  ---
163
172
 
164
173
  ## 4. PRD (Product Requirements Document)
165
174
 
166
- **What it is.** The structured JSON twin of a Plan. Where the Plan markdown is for humans, the
167
- PRD JSON is what the engine reads to materialize work items. Each PRD has an `items` array; each
168
- item has acceptance criteria, complexity, dependencies, and a status (`missing | updated | done`).
175
+ **What it is.** The structured, machine-executable representation of a Plan. Its full document
176
+ shape remains JSON-compatible, but the authoritative records are SQL rows: a parent in `prds` and
177
+ children in `prd_items`. The compatibility filename still ends in `.json`; it is an identifier,
178
+ not a live file under `prd/`.
169
179
 
170
- **Where it lives.** `prd/*.json`, archived to `prd/archive/*.json`. The materializer treats
171
- `missing` and `updated` items as work to do (`PRD_MATERIALIZABLE`, `engine/shared.js` line 1370).
180
+ The current document shape uses `missing_features[]`. Each feature can carry acceptance criteria,
181
+ complexity, dependencies, project, type, and a status of `missing`, `updated`, or `done`.
172
182
 
173
- **Backing classes / functions.**
174
- - Status constants: `engine/shared.js` line 1370 (`PRD_ITEM_STATUS`, `PRD_MATERIALIZABLE`).
175
- - Sync from Work Items: `syncPrdItemStatus`, `reconcilePrdStatuses` (`engine/lifecycle.js`
176
- lines 564, 597).
177
- - Plan-to-PRD agent: `playbooks/plan-to-prd.md`, dispatched via `queuePlanToPrd`.
178
- - PRD dir: `engine/pipeline.js` line 24 (`PRD_DIR`).
183
+ **Where it lives.**
179
184
 
180
- **Existing dashboard.** `dashboard/pages/plans.html` same page as Plan, with a graph view of
181
- PRD items and their states. Recent feature: PRD graph view at parity with list view (commit
182
- `b4767d2d`).
185
+ - Parent records: `engine/state.db` table `prds`
186
+ - Item records: `engine/state.db` table `prd_items`
187
+ - Verify-PR links: `engine/state.db` table `prd_verify_prs`
188
+ - Read/write facade: `engine/prd-store.js`
183
189
 
184
- **Slim dashboard.** The same `#slim-plans-modal` (opened from the Plans cockpit tile) carries a
185
- **PRD** tab rendered by `dashboard/slim/js/plans.js`, mirroring the classic PRD view: it lists
186
- materialized PRDs with their work items, the verify task, and linked PRs. Reads use the **existing**
187
- `GET /api/prd`, `GET /api/plans` (the `.json` entries, for per-PRD lifecycle status), and
188
- `GET /api/work-items` (the verify row) — no new routes. See **§3 Plan → Slim dashboard** for the
189
- shared tile/modal, lazy-count source, and `slim-ux`-only gating (no new `engine.*` flag).
190
+ Archived PRDs remain in SQL. Current manual archive sets the PRD's archive metadata in place.
190
191
 
191
- **Endpoints (`dashboard.js`).**
192
- - `POST /api/prd-items` (6968) — create PRD item
193
- - `POST /api/prd-items/update` (6969)
194
- - `POST /api/prd-items/remove` (6970) — also cancels matching Work Item
192
+ **Backing symbols.**
193
+
194
+ - Item statuses: `engine/shared.js#PRD_ITEM_STATUS`
195
+ - Materializable statuses: `engine/shared.js#PRD_MATERIALIZABLE`
196
+ - SQL writes and item upserts: `engine/prd-store.js#writePrd` and `#_upsertPrd`
197
+ - Reads: `engine/prd-store.js#readPrd` and `#listPrdRows`
198
+ - Work Item -> PRD status sync: `engine/lifecycle.js#syncPrdItemStatus`
199
+ - Reconciliation sweep: `engine/lifecycle.js#reconcilePrdStatuses`
200
+ - Stable Work Item join: `work_items.prd_item_id -> prd_items.id`
201
+
202
+ **Existing dashboard.** `dashboard/pages/plans.html` renders the PRD graph/list. The Slim Plans tile
203
+ embeds the same screen.
204
+
205
+ **Endpoints.**
195
206
 
196
- **Relationships.** PRD is the bridge between **Plan** (human-readable) and the **Work Item**
197
- queue (machine-executable). When a plan's PRD items are all `done`, the plan completes; archive
198
- is still manual.
207
+ - `GET /api/prd` -- SQL-derived progress, Work Item, and PR state
208
+ - `POST /api/prd-items` -- add an item
209
+ - `POST /api/prd-items/update` -- edit an item
210
+ - `POST /api/prd-items/remove` -- remove an item and cancel its materialized Work Item
211
+
212
+ **Relationships.** PRD is the bridge between a human Plan and executable Work Items. Its parent row,
213
+ item rows, Work Item foreign keys, and verify PR associations form one SQL-backed lifecycle.
199
214
 
200
215
  ---
201
216
 
202
217
  ## 5. Note
203
218
 
204
- **What it is.** A small markdown file written by an agent (after a task) or a human (via "+
205
- Note") capturing what was learned. Notes are *raw*; the consolidation engine reads them and
206
- either merges them into `notes.md` or promotes them into a **Knowledge Base** category.
219
+ **What it is.** A small Markdown artifact written by a human, agent, or engine process to capture
220
+ an outcome, warning, or reusable finding. A Note is raw input; consolidation decides whether its
221
+ information belongs in team `notes.md`, the Knowledge Base, or both.
222
+
223
+ **Where it lives.**
207
224
 
208
- **Where it lives.** `notes/inbox/*.md` while raw, `notes/archive/<category>/*.md` after KB sweep,
209
- and merged content lives in `notes.md`.
225
+ - New notes: `notes/inbox/*.md`
226
+ - Processed source artifacts: `notes/archive/*.md`
227
+ - Consolidated team digest: `notes.md`
228
+ - Classified durable knowledge: `knowledge/<category>/*.md`
210
229
 
211
- **Backing classes / functions.**
212
- - Inbox writer: `writeToInbox` — `engine/shared.js` line 648 (re-exported line 2959).
213
- - ID parser: `parseNoteId` (same module).
214
- - Consolidation orchestration: `engine/consolidation.js`
215
- - `consolidateInbox` line 24
216
- - `consolidateWithLLM` line 116
217
- - `classifyToKnowledgeBase` line 389
218
- - `archiveInboxFiles` line 444.
230
+ **Backing symbols.**
219
231
 
220
- **Existing dashboard.** `dashboard/pages/inbox.html` the inbox tab. A "+ Note" quick-action
221
- exists in the top bar of `home.html`.
232
+ - Writer and ID parser: `engine/shared.js#writeToInbox` and `#parseNoteId`
233
+ - Consolidation entry point: `engine/consolidation.js#consolidateInbox`
234
+ - LLM merge: `engine/consolidation.js#consolidateWithLLM`
235
+ - Classification: `engine/consolidation.js#classifyToKnowledgeBase`
236
+ - Source archival: `engine/consolidation.js#archiveInboxFiles`
222
237
 
223
- **Endpoints (`dashboard.js`).**
224
- - `POST /api/notes` (6946) — write to inbox
225
- - `GET /api/notes-full` (6947) — read consolidated `notes.md`
226
- - `POST /api/notes-save` (6948) — save edited `notes.md`
238
+ **Existing dashboard.** `dashboard/pages/inbox.html` surfaces Notes, the inbox, and KB controls.
239
+
240
+ **Endpoints.**
227
241
 
228
- **Relationships.** Notes feed **Inbox** → **Consolidation** → **Knowledge Base** (or
229
- `notes.md`). Agents are *required* to drop a note in the inbox at the end of every successful
230
- task; failure cases must NOT write a note.
242
+ - `POST /api/notes`
243
+ - `GET /api/notes-full`
244
+ - `POST /api/notes-save`
245
+
246
+ **Relationships.** Notes enter the **Notes Inbox**, are consolidated into team memory, and can
247
+ produce **Knowledge Base** entries. Successful agent tasks write the requested findings note;
248
+ failed or partial tasks do not create a success artifact.
231
249
 
232
250
  ---
233
251
 
234
252
  ## 6. Knowledge Base (KB)
235
253
 
236
- **What it is.** The team's long-term memory. After consolidation, notes get classified into one of
237
- five categories and archived. Agents read the KB before researching outside.
254
+ **What it is.** The team's categorized long-term memory. The five canonical categories in
255
+ `KB_CATEGORIES` are `architecture`, `conventions`, `project-notes`, `build-reports`, and `reviews`.
256
+ The consolidation pipeline can also use supporting categories such as `general`, while personal
257
+ agent memory is kept separately under `knowledge/agents/`.
238
258
 
239
259
  **Where it lives.**
240
- - `notes/archive/architecture/*.md`
241
- - `notes/archive/conventions/*.md`
242
- - `notes/archive/project-notes/*.md`
243
- - `notes/archive/build-reports/*.md`
244
- - `notes/archive/reviews/*.md`
245
260
 
246
- **Backing classes / functions.**
247
- - Categories: `engine/shared.js` line 840 (`KB_CATEGORIES`).
248
- - Pin store: `engine/shared.js` line 15 (`PINNED_ITEMS_PATH = engine/kb-pins.json`).
249
- - Sweep / classification: `engine/kb-sweep.js`, `engine/consolidation.js`
250
- `classifyToKnowledgeBase` line 389.
261
+ - Shared entries: `knowledge/<category>/*.md`
262
+ - Per-agent memory: `knowledge/agents/<agent-id>.md`
263
+ - Sweep recovery archive: `knowledge/_swept/`
264
+
265
+ **Backing symbols.**
266
+
267
+ - Canonical categories: `engine/shared.js#KB_CATEGORIES`
268
+ - Query/read layer: `engine/queries.js#KNOWLEDGE_DIR` and KB readers
269
+ - Classification: `engine/consolidation.js#classifyToKnowledgeBase`
270
+ - Compaction and TTL sweep: `engine/kb-sweep.js`
271
+
272
+ **Existing dashboard.** `dashboard/pages/inbox.html` contains the KB browser and sweep controls.
251
273
 
252
- **Existing dashboard.** `dashboard/pages/inbox.html` — same tab as Notes. KB browser by category.
274
+ **Endpoints.**
253
275
 
254
- **Endpoints (`dashboard.js`).**
255
- - `GET /api/knowledge` (7146) — list KB grouped by category
256
- - `POST /api/knowledge` (7147) — create entry directly
257
- - `POST /api/knowledge/sweep` (7163) — async sweep
258
- - `GET /api/knowledge/sweep/status` (7164) — poll sweep
276
+ - `GET /api/knowledge`
277
+ - `POST /api/knowledge`
278
+ - `POST /api/knowledge/sweep`
279
+ - `GET /api/knowledge/sweep/status`
259
280
 
260
- **Relationships.** Inbox KB agent prompt context. Pinned notes (next entry) are a *subset* of
261
- the KB.
281
+ **Relationships.** KB entries feed bounded memory retrieval for agent prompts. An entry may be
282
+ pinned, but **Pinned Context** is a separate prompt layer and storage surface rather than a subset
283
+ of the KB.
262
284
 
263
285
  ---
264
286
 
265
287
  ## 7. Pinned Context (`pinned.md`)
266
288
 
267
- **What it is.** Critical context the human flagged as "READ FIRST." Prepended to every agent
268
- prompt regardless of work type. Use sparingly — pinned notes pollute every dispatch.
289
+ **What it is.** Critical human-curated context that is always included in agent prompt context.
290
+ Pinned content is intentionally small and high priority.
291
+
292
+ **Where it lives.**
269
293
 
270
- **Where it lives.** `pinned.md` (root). Index file: `engine/kb-pins.json` (`PINNED_ITEMS_PATH`,
271
- `engine/shared.js` line 15).
294
+ - Content: `<MINIONS_DIR>/pinned.md`
295
+ - KB pin index: `<MINIONS_DIR>/engine/kb-pins.json`
272
296
 
273
- **Backing classes / functions.**
274
- - Add / remove handlers: `dashboard.js` lines 6891, 6895, 6908.
275
- - Parser: `parsePinnedEntries` (referenced at line 6893).
276
- - Slow-state cache invalidation explicitly on edits (`includeSlow: true`, line 6905).
297
+ The Markdown content and KB pin index serve different purposes: `pinned.md` is the global prompt
298
+ layer, while `kb-pins.json` protects selected KB entries from sweep removal.
277
299
 
278
- **Existing dashboard.** `dashboard/pages/home.html` — "Pinned Context" widget. Pin / unpin
279
- buttons appear in the KB browser.
300
+ **Backing symbols.**
280
301
 
281
- **Endpoints (`dashboard.js`).**
282
- - `GET /api/pinned` (6891)
283
- - `POST /api/pinned` (6895) — add
284
- - `POST /api/pinned/remove` (6908)
302
+ - Pin-index path: `engine/shared.js#PINNED_ITEMS_PATH`
303
+ - Pin-index reader: `engine/shared.js#getPinnedItems`
304
+ - Markdown parser: `dashboard.js#parsePinnedEntries`
305
+ - Prompt injection and untrusted-input fencing: `engine/playbook.js`
285
306
 
286
- **Relationships.** Pinned KB. Pinned content shows up in *every* agent prompt (even short
287
- ones), so it's also coupled to **Charter** and **Routing** in terms of "what gets read first."
307
+ **Existing dashboard.** The home and Knowledge surfaces expose pinned context and pin/unpin
308
+ controls.
309
+
310
+ **Endpoints.**
311
+
312
+ - `GET /api/pinned`
313
+ - `POST /api/pinned`
314
+ - `POST /api/pinned/update`
315
+ - `POST /api/pinned/remove`
316
+
317
+ **Relationships.** Pinned Context is independent of **Routing** and **Charters** but appears in the
318
+ same final prompt context. Because every dispatch sees it, stale or oversized content has
319
+ fleet-wide impact.
288
320
 
289
321
  ---
290
322
 
291
323
  ## 8. Notes Inbox
292
324
 
293
- **What it is.** The waiting room for raw notes before consolidation. Files dropped into
294
- `notes/inbox/` are the engine's signal that an agent succeeded; they get consolidated into
295
- `notes.md` or promoted into the **KB** on a schedule.
325
+ **What it is.** The staging area for raw notes before consolidation. Files can come from humans,
326
+ agents, and engine alerts.
296
327
 
297
- **Where it lives.** `notes/inbox/*.md` (filename convention:
298
- `<agent>-<work-item-id>-<date>-<time>.md`, with YAML frontmatter `id:`, `agent:`, `date:`).
328
+ **Where it lives.** `<MINIONS_DIR>/notes/inbox/*.md`. Agent findings conventionally use
329
+ `<agent>-<work-item-id>-<date>-<time>.md` plus YAML frontmatter containing `id`, `agent`, and
330
+ `date`.
299
331
 
300
- **Backing classes / functions.**
301
- - Inbox dir constant: `INBOX_DIR` in `engine/queries.js` (used at line 526).
302
- - Consolidation tick path: `engine/consolidation.js` `consolidateInbox` line 24.
303
- - Promote / delete API handlers: `handleInboxPersist`, `handleInboxPromoteKb`,
304
- `handleInboxOpen`, `handleInboxDelete`.
332
+ **Backing symbols.**
305
333
 
306
- **Existing dashboard.** `dashboard/pages/inbox.html` — note list, promote-to-KB buttons,
307
- consolidate-now button.
334
+ - Directory: `engine/queries.js#INBOX_DIR`
335
+ - Writer: `engine/shared.js#writeToInbox`
336
+ - Consolidation: `engine/consolidation.js#consolidateInbox`
337
+ - Manual handlers: `dashboard.js#handleInboxPersist`, `#handleInboxPromoteKb`,
338
+ `#handleInboxOpen`, and `#handleInboxDelete`
308
339
 
309
- **Endpoints (`dashboard.js`).**
310
- - `POST /api/inbox/persist` (7172) — promote to `notes.md`
311
- - `POST /api/inbox/promote-kb` (7173) — promote to KB category
312
- - `POST /api/inbox/open` (7174) — reveal in OS file manager
313
- - `POST /api/inbox/delete` (7175)
340
+ **Existing dashboard.** `dashboard/pages/inbox.html` lists pending notes and manual disposition
341
+ actions.
342
+
343
+ **Endpoints.**
314
344
 
315
- **Relationships.** Inbox is the staging area between **Notes** (the act of writing) and the
316
- **KB** / `notes.md` (the durable store). Failure inboxes are explicitly forbidden by team rules.
345
+ - `POST /api/inbox/persist`
346
+ - `POST /api/inbox/promote-kb`
347
+ - `POST /api/inbox/open`
348
+ - `POST /api/inbox/delete`
349
+
350
+ **Relationships.** Inbox is the boundary between raw **Notes** and durable `notes.md` / **KB**
351
+ memory. Consolidation archives processed source files so the original evidence remains
352
+ recoverable.
317
353
 
318
354
  ---
319
355
 
320
356
  ## 9. Schedule (cron)
321
357
 
322
- **What it is.** A recurring trigger that creates a Work Item on a cron pattern. The engine ticks
323
- every 10 s; if a schedule's last-run was its interval ago and the cron pattern matches, the
324
- engine drops a Work Item into the queue.
358
+ **What it is.** A recurring trigger that creates a Work Item when a three-field cron expression
359
+ (`minute hour day-of-week`) matches. Schedule-time template variables are resolved before the Work
360
+ Item enters the queue, including nested string fields.
325
361
 
326
362
  **Where it lives.**
327
- - Definitions: `config.json` `schedules: []` (3-field cron `min hour dow`).
328
- - Last-run history: `engine/state.db` `schedule_runs`.
329
-
330
- **Backing classes / functions.**
331
- - Cron parser: `engine/scheduler.js`
332
- - `parseCronField` line 63
333
- - `parseCronExpr` line 106
334
- - `shouldRunNow` line 145.
335
- - Variable substitution: `resolveScheduleTemplateVars` line 46 (handles `{{date}}`, etc., before
336
- the work item lands in the queue).
337
- - Work-item factory: `createScheduledWorkItem` line 168.
338
- - Tick path: `discoverScheduledWork` line 209.
339
-
340
- **Existing dashboard.** `dashboard/pages/schedule.html` schedule list, natural-language → cron
341
- helper.
342
-
343
- **Endpoints (`dashboard.js`).**
344
- - `GET /api/schedules` (7200)
345
- - `POST /api/schedules` (7201) — create
346
- - `POST /api/schedules/update` (7202)
347
- - `POST /api/schedules/delete` (7203)
348
- - `POST /api/schedules/run-now` (7204)
349
- - `POST /api/schedules/parse-natural` (7199) — natural-language → cron
350
-
351
- **Relationships.** Schedule → emits Work Items into the **Dispatch Queue** on a cron. Closely
352
- analogous to **Watch** (event-driven instead of time-driven).
363
+
364
+ - Definitions: `config.json` under `schedules[]`
365
+ - Run history: `engine/state.db` table `schedule_runs`
366
+
367
+ **Backing symbols.**
368
+
369
+ - Cron parsing: `engine/scheduler.js#parseCronField` and `#parseCronExpr`
370
+ - Match decision: `engine/scheduler.js#shouldRunNow`
371
+ - Variable map: `engine/scheduler.js#buildScheduleTemplateVars`
372
+ - Recursive substitution: `engine/scheduler.js#applyScheduleTemplateVarsRecursive`
373
+ - Work Item factory: `engine/scheduler.js#createScheduledWorkItem`
374
+ - Discovery: `engine/scheduler.js#discoverScheduledWork`
375
+
376
+ **Existing dashboard.** `dashboard/pages/schedule.html` provides definition CRUD, run-now, and
377
+ natural-language-to-cron assistance.
378
+
379
+ **Endpoints.**
380
+
381
+ - `GET /api/schedules`
382
+ - `POST /api/schedules`
383
+ - `POST /api/schedules/update`
384
+ - `POST /api/schedules/delete`
385
+ - `POST /api/schedules/run-now`
386
+ - `POST /api/schedules/parse-natural`
387
+
388
+ **Relationships.** A Schedule is time-driven and emits **Work Items**. A **Watch** is state-driven
389
+ and can run a broader action registry.
353
390
 
354
391
  ---
355
392
 
356
393
  ## 10. Watch
357
394
 
358
- **What it is.** A persistent monitor on a PR or Work Item that fires when a condition is met
359
- (merged, build passes, build fails, status changes, new comments, vote changes). Watches are
360
- event-driven, schedules are time-driven.
395
+ **What it is.** A persistent monitor that evaluates a registered target type and condition, then
396
+ notifies or runs a configured follow-up action. The eight built-in target types are:
361
397
 
362
- **Where it lives.** `engine/state.db` `watches`.
398
+ `pr`, `work-item`, `meeting`, `plan`, `schedule`, `pipeline`, `dispatch`, and `agent`.
363
399
 
364
- **Backing classes / functions.**
365
- - Status constants: `engine/shared.js` line 1380 (`WATCH_STATUS`).
366
- - Condition constants: `WATCH_CONDITION` (same file, near 1380); fire-once set
367
- `WATCH_ABSOLUTE_CONDITIONS`.
368
- - CRUD: `engine/watches.js` `createWatch` line 44, `updateWatch` line 88, `deleteWatch`
369
- line 116.
370
- - Tick path: `evaluateWatch` line 138, `checkWatches` line 214 (runs every 3 ticks).
371
- - State diff store: `_captureState` line 297 (`_lastState` per watch).
400
+ Additional target types can be loaded from `<MINIONS_DIR>/watches.d/*.js`.
372
401
 
373
- **Existing dashboard.** `dashboard/pages/watches.html` watch list, condition picker.
402
+ **Where it lives.** `engine/state.db` table `watches`.
374
403
 
375
- **Endpoints (`dashboard.js`).**
376
- - `GET /api/watches` (7207)
377
- - `POST /api/watches` (7208) — create
378
- - `POST /api/watches/update` (7209) — pause / resume / modify
379
- - `POST /api/watches/delete` (7210)
404
+ **Backing symbols.**
380
405
 
381
- **Relationships.** Watch optionally re-fires (notify, dispatch, etc.) when its condition flips.
382
- A merged-PR watch is the canonical "tell me when X ships" primitive.
406
+ - Statuses and built-in target names: `engine/shared.js#WATCH_STATUS` and
407
+ `#WATCH_TARGET_TYPE`
408
+ - Conditions: `engine/shared.js#WATCH_CONDITION`
409
+ - Fire-once fallback set: `engine/shared.js#WATCH_ABSOLUTE_CONDITIONS`
410
+ - Target registry: `engine/watches.js#TARGET_TYPES` and `#registerTargetType`
411
+ - CRUD: `engine/watches.js#createWatch`, `#updateWatch`, and `#deleteWatch`
412
+ - Evaluation: `engine/watches.js#evaluateWatch` and `#checkWatches`
413
+ - Plugin loader: `engine/watches.js#_loadPluginTargetTypes`
414
+ - Follow-up action registry: `engine/watch-actions.js`
415
+
416
+ The engine schedules `checkWatches` every `ENGINE_DEFAULTS.watchPollEvery` ticks. The default is 18
417
+ ticks, approximately three minutes at the default 10-second engine tick. Each watch can impose a
418
+ longer minimum `interval`.
419
+
420
+ **Existing dashboard.** `dashboard/pages/watches.html` lists watches and gets live target/action
421
+ registries from the server.
422
+
423
+ **Endpoints.**
424
+
425
+ - `GET /api/watches`
426
+ - `GET /api/watches/target-types`
427
+ - `GET /api/watches/action-types`
428
+ - `POST /api/watches`
429
+ - `POST /api/watches/update`
430
+ - `POST /api/watches/delete`
431
+
432
+ **Relationships.** A Watch can write an inbox notification or run actions such as
433
+ `dispatch-work-item`, `run-skill`, `webhook`, `minions-api`, `cc-triage`,
434
+ `cancel-work-item`, `trigger-pipeline`, `archive-plan`, and `resume-plan`.
383
435
 
384
436
  ---
385
437
 
386
438
  ## 11. Pipeline
387
439
 
388
- **What it is.** A multi-stage workflow. Stages can be a Work Item (`task`), a `meeting`, or a
389
- `plan`. Stages can declare dependencies on previous stages. Pipelines run via triggers (manual,
390
- schedule, watch) and persist run state in SQLite.
440
+ **What it is.** A reusable multi-stage workflow with dependency tracking. Shipped stage types are
441
+ `task`, `meeting`, `plan`, `api`, `merge-prs`, `schedule`, `wait`, `parallel`, and `condition`.
442
+ Pipelines can be triggered manually or through automation such as a schedule or watch action.
391
443
 
392
444
  **Where it lives.**
393
- - Definitions: `pipelines/*.json` (one file per pipeline).
394
- - Run state: `engine/state.db` `pipeline_runs`.
395
-
396
- **Backing classes / functions.**
397
- - Dirs: `engine/pipeline.js` lines 19–24 (`PIPELINES_DIR`, `PIPELINE_RUNS_PATH`, `PLANS_DIR`,
398
- `PRD_DIR`).
399
- - CRUD: `getPipelines` line 35, `getPipeline` line 53, `savePipeline` line 58, `deletePipeline`
400
- line 63.
401
- - Run lifecycle: `getActiveRun` line 80, `startRun` line 86, `updateRunStage` line 116,
402
- `completeRun` line 127.
403
-
404
- **Existing dashboard.** `dashboard/pages/pipelines.html` — pipeline editor, run history, stage
405
- state.
406
-
407
- **Endpoints (`dashboard.js`).**
408
- - `GET /api/pipelines` (7213)
409
- - `POST /api/pipelines` (7220) — create
410
- - `POST /api/pipelines/update` (7232)
411
- - `POST /api/pipelines/delete` (7248)
412
- - `POST /api/pipelines/trigger` (7256)
413
- - `POST /api/pipelines/continue` (7268) — past wait stage
414
- - `POST /api/pipelines/abort` (7280)
415
- - `POST /api/pipelines/retrigger` (7307)
416
-
417
- **Relationships.** Pipeline = composer of Work Items / Meetings / Plans. Confusion vector:
418
- unrelated to ADO/GitHub Actions pipelines, even though the word collides.
445
+
446
+ - Definitions: `pipelines/*.json`
447
+ - Run state: `engine/state.db` table `pipeline_runs`
448
+
449
+ Definitions intentionally remain file-backed; run history is SQL-backed.
450
+
451
+ **Backing symbols.**
452
+
453
+ - Definition directory and CRUD: `engine/pipeline.js#PIPELINES_DIR`, `#getPipelines`,
454
+ `#getPipeline`, `#savePipeline`, and `#deletePipeline`
455
+ - Stage/status enums: `engine/shared.js#STAGE_TYPE` and `#PIPELINE_STATUS`
456
+ - Run reads: `engine/pipeline.js#getPipelineRuns` ->
457
+ `engine/small-state-store.js#readPipelineRuns`
458
+ - Run mutations: `engine/shared.js#mutatePipelineRuns`
459
+ - Lifecycle: `engine/pipeline.js#startRun`, `#updateRunStage`, `#upsertRunStage`, and
460
+ `#completeRun`
461
+
462
+ **Existing dashboard.** `dashboard/pages/pipelines.html` provides definition editing, triggering,
463
+ run history, and wait-stage continuation.
464
+
465
+ **Endpoints.**
466
+
467
+ - `GET /api/pipelines`
468
+ - `POST /api/pipelines`
469
+ - `POST /api/pipelines/update`
470
+ - `POST /api/pipelines/delete`
471
+ - `POST /api/pipelines/trigger`
472
+ - `POST /api/pipelines/continue`
473
+ - `POST /api/pipelines/abort`
474
+ - `POST /api/pipelines/retrigger`
475
+
476
+ **Relationships.** A Pipeline composes Work Items, Meetings, Plans, API calls, and control-flow
477
+ stages. It is unrelated to a GitHub Actions or Azure DevOps build pipeline despite the shared word.
419
478
 
420
479
  ---
421
480
 
422
481
  ## 12. Dispatch
423
482
 
424
- **What it is.** The act of taking a pending Work Item and spawning an agent process for it. A
425
- dispatch holds the agent's PID, prompt sidecar path, worktree path, and current status until the
426
- process exits.
483
+ **What it is.** One execution attempt for a Work Item. A dispatch records the selected agent,
484
+ runtime, prompt sidecar, process/session metadata, worktree, branch/PR locks, and result.
427
485
 
428
- **Where it lives.** Active rows in `engine/state.db` `dispatches`.
486
+ **Where it lives.** `engine/state.db` table `dispatches`.
429
487
 
430
- **Backing classes / functions.**
431
- - `mutateDispatch`: `engine/dispatch.js` line 60 (the only safe RMW path).
432
- - `addToDispatch`: line 128.
433
- - `findActivePrOrBranchLock`: line 112 (dedupe).
434
- - `completeDispatch`: line 327.
435
- - `cancelPendingDispatchesForPr`: line 550.
436
- - Result codes: `engine/shared.js` line 1433 (`DISPATCH_RESULT`).
488
+ **Backing symbols.**
437
489
 
438
- **Existing dashboard.** `dashboard/pages/engine.html` — dispatch log; `home.html` — "Dispatch
439
- Queue" widget.
490
+ - Transactional mutation: `engine/dispatch.js#mutateDispatch`
491
+ - Queue insertion and dedupe: `engine/dispatch.js#addToDispatch`
492
+ - PR/branch lock detection: `engine/dispatch.js#findActivePrOrBranchLock`
493
+ - Completion: `engine/dispatch.js#completeDispatch`
494
+ - Result enum: `engine/shared.js#DISPATCH_RESULT`
495
+ - Store implementation: `engine/dispatch-store.js`
440
496
 
441
- **Endpoints.** No public CRUD — dispatch is a side effect of `/api/work-items` and the engine
442
- tick. Read shape via `/api/status` (line 6838).
497
+ **Existing dashboard.** `dashboard/pages/engine.html` shows dispatch history and logs; home/work
498
+ surfaces show active execution context.
443
499
 
444
- **Relationships.** Dispatch wraps a **Work Item** + an **Agent** + a **Project** worktree. A
445
- **Completion** is dispatch's exit signal.
500
+ **Endpoints.** Dispatch is mostly a side effect of Work Item creation and engine discovery. Its
501
+ read shape appears through `/api/status`, `/api/agents`, and Work Item APIs.
502
+
503
+ **Relationships.** A Dispatch combines one Work Item, one Agent, one selected runtime, and one
504
+ execution workspace. A **Completion** report is its trusted exit contract.
446
505
 
447
506
  ---
448
507
 
@@ -450,393 +509,487 @@ tick. Read shape via `/api/status` (line 6838).
450
509
 
451
510
  **What it is.** The sectioned view reconstructed from SQL dispatch rows:
452
511
 
453
- - `pending[]` admitted Work Items waiting on agent / dependency / cooldown / budget.
454
- - `active[]` currently spawned.
455
- - `completed[]` finished (success or failure), kept for audit until cleaned.
512
+ - `pending[]` -- admitted work waiting on capacity, dependencies, cooldowns, or an agent
513
+ - `active[]` -- currently executing dispatches
514
+ - `completed[]` -- terminal attempts retained for audit/cleanup
515
+ - `review[]` -- candidates rejected by the optional pre-dispatch acceptance gate
456
516
 
457
- The queue's invariants are: max concurrent (default 5), per-PR / per-branch lock to avoid two
458
- agents fighting on the same branch, dependency-aware spawning (`depends_on` IDs must be done
459
- first), retry on failure up to `ENGINE_DEFAULTS.maxRetries`.
517
+ **Where it lives.** `engine/state.db` table `dispatches`, reconstructed by
518
+ `engine/dispatch-store.js#readDispatchSectioned`.
460
519
 
461
- **Where it lives.** `engine/state.db` `dispatches`.
520
+ **Backing symbols.**
462
521
 
463
- **Backing classes / functions.** All in `engine/dispatch.js`. Mutation only via `mutateDispatch`
464
- line 60. Queue dedupe keys: `getDispatchProjectKey` line 80, `getPrDispatchTargetKey` line 85,
465
- `getPrDispatchDedupeKey` line 95, `getBranchDispatchLockKey` line 103.
522
+ - Dashboard/query view: `engine/queries.js#getDispatchQueue`
523
+ - Queue mutation: `engine/dispatch.js#mutateDispatch`
524
+ - Acceptance-review routing: `engine/dispatch.js#_routeToReviewQueue`
525
+ - Concurrency default: `engine/shared.js#ENGINE_DEFAULTS.maxConcurrent` (default 5)
466
526
 
467
- **Existing dashboard.** `dashboard/pages/home.html` ("Dispatch Queue" section) and
468
- `engine.html` (full log).
527
+ The queue enforces Work Item and dispatch-key dedupe, fix-target and branch locks, dependency
528
+ readiness, concurrency, retry policy, and budget/cooldown gates.
469
529
 
470
- **Endpoints.** Read-only via `/api/status` (line 6838).
530
+ **Existing dashboard.** Home, Work Items, and Engine screens expose different projections of the
531
+ same SQL-backed queue.
471
532
 
472
- **Relationships.** Queue Dispatches Work Items. The queue is the engine's state of mind.
533
+ **Relationships.** Queue contains **Dispatches**; each Dispatch attempts a **Work Item**. Pending
534
+ reasons explain why intent has not yet become an active process.
473
535
 
474
536
  ---
475
537
 
476
538
  ## 14. Completion
477
539
 
478
- **What it is.** The structured report an agent writes before exit. JSON shape lives at the path
479
- the engine puts in `MINIONS_COMPLETION_REPORT`. Fields: `status`, `summary`, `verdict`, `pr`,
480
- `failure_class`, `retryable`, `needs_rerun`, `artifacts[]`. Fenced ` ```completion ` blocks in
481
- stdout are also accepted as a fallback.
540
+ **What it is.** The JSON report an agent writes to the exact path supplied in
541
+ `MINIONS_COMPLETION_REPORT`. It is the sole structured completion source. A zero process exit code
542
+ is only a transport signal; mutating work without a valid required report fails with
543
+ `completion-report-missing`.
544
+
545
+ Each spawn also receives `MINIONS_COMPLETION_NONCE`. The agent copies it verbatim into the report;
546
+ a mismatch invalidates every reported signal and fails the dispatch as
547
+ `completion-nonce-mismatch`.
482
548
 
483
549
  **Where it lives.**
484
- - File path: `engine/completions/<dispatchId>.json` (built by `dispatchCompletionReportPath`,
485
- `engine/shared.js` line 351).
486
- - Field constants: `COMPLETION_FIELDS` (`engine/shared.js` line 1474–1475).
487
550
 
488
- **Backing classes / functions.** Parsing happens during `completeDispatch` (`engine/dispatch.js`
489
- line 327) and `engine/lifecycle.js`'s post-completion path (`syncPrsFromOutput` line 644).
551
+ - `<MINIONS_DIR>/engine/completions/<dispatch-id>.json`
552
+ - Canonical schema: [`docs/completion-reports.md`](../completion-reports.md)
490
553
 
491
- **Existing dashboard.** `dashboard/pages/work.html` — completion details when an item is
492
- expanded; `home.html` "Recent Completions" widget.
554
+ **Backing symbols.**
493
555
 
494
- **Endpoints.** Read-only via `/api/status` and `/api/work-items/archive`.
556
+ - Path builder: `engine/shared.js#dispatchCompletionReportPath`
557
+ - Recognized core fields: `engine/shared.js#COMPLETION_FIELDS`
558
+ - File parsing: `engine/lifecycle.js#parseCompletionReportFile`
559
+ - Required-report gate: `engine/lifecycle.js#requiredCompletionReportFailure`
560
+ - Dispatch terminalization: `engine/dispatch.js#completeDispatch`
495
561
 
496
- **Relationships.** Completion sits between **Dispatch** (the run) and **Work Item** (the long-term
497
- record). It also feeds **Pull Request** sync (`pr` field).
562
+ Core fields include `status`, `summary`, `files_changed`, `tests`, `pr`, `not_changed`,
563
+ `failure_class`, `retryable`, `needs_rerun`, `verdict`, `artifacts`, `nonce`, and
564
+ `securityFlags`. The canonical schema documents additional optional fields and exact semantics.
565
+
566
+ **Existing dashboard.** Work Item detail and recent-completion surfaces display the persisted
567
+ summary, artifacts, tests, PR, and failure metadata.
568
+
569
+ **Relationships.** Completion turns a process exit into a trustworthy lifecycle decision. It can
570
+ attach a PR, publish artifacts, request a retry/rerun, carry a review verdict, flag prompt
571
+ injection, and invalidate superseded Work Items.
498
572
 
499
573
  ---
500
574
 
501
- ## 15. Pull Request (as tracked in minions)
575
+ ## 15. Pull Request (as tracked in Minions)
502
576
 
503
- **What it is.** A project-scoped row in the SQL PR store. Tracks status, vote tally, build
504
- state, review verdict, and the work item that created it. *Not* the GitHub/ADO PR itself —
505
- minions polls the host and writes a sanitized snapshot here.
577
+ **What it is.** A project-scoped SQL record that mirrors the useful state of an external GitHub or
578
+ Azure DevOps PR: host identity, source branch, lifecycle status, build state, human feedback,
579
+ review verdict, and Minions linkage. It is not the host PR itself.
506
580
 
507
- **Where it lives.** `engine/state.db` `pull_requests`; cross-project links use `pr_links`.
581
+ **Where it lives.**
508
582
 
509
- **Backing classes / functions.**
510
- - Status / pollable constants: `engine/shared.js` line 1372 (`PR_STATUS`,
511
- `PR_POLLABLE_STATUSES`).
512
- - GitHub poller: `engine/github.js`.
513
- - ADO poller: `engine/ado.js`.
514
- - Parallel comment poller for human comments only (filters bots).
515
- - Sync from agent output: `syncPrsFromOutput` (`engine/lifecycle.js` line 644).
516
- - PR-attachment requirement check: `isPrAttachmentRequired` (line 875).
583
+ - PR records: `engine/state.db` table `pull_requests`
584
+ - Cross-record links: `engine/state.db` table `pr_links`
585
+ - Store facade: `engine/pull-requests-store.js`
517
586
 
518
- **Existing dashboard.** `dashboard/pages/prs.html` — the "Pull Requests" tab.
587
+ **Backing symbols.**
519
588
 
520
- **Endpoints (`dashboard.js`).**
521
- - `POST /api/pull-requests/link` (6974) — manually link external PR
522
- - `POST /api/pull-requests/delete` (7030)
589
+ - Statuses and polling eligibility: `engine/shared.js#PR_STATUS` and
590
+ `#PR_POLLABLE_STATUSES`
591
+ - GitHub integration: `engine/github.js`
592
+ - Azure DevOps integration: `engine/ado.js`
593
+ - Agent-output/report sync: `engine/lifecycle.js#syncPrsFromOutput`
594
+ - Required-attachment gate: `engine/lifecycle.js#isPrAttachmentRequired`
523
595
 
524
- **Relationships.** PR ↔ Work Item is one-to-one in normal flow (review / fix work items can
525
- re-attach to the same PR). PR ↔ Watch is one-to-many (you can watch the same PR with multiple
526
- conditions).
596
+ **Existing dashboard.** `dashboard/pages/prs.html` is the classic PR screen; Slim embeds that same
597
+ screen for PR details.
598
+
599
+ **Endpoints.**
600
+
601
+ - `GET /api/pull-requests`
602
+ - `POST /api/pull-requests/link`
603
+ - `POST /api/pull-requests/observe`
604
+ - `POST /api/pull-requests/delete`
605
+ - Targeted resume/clear endpoints under `/api/pull-requests/clear-*`
606
+
607
+ **Relationships.** An implementation Work Item commonly creates the first PR association. Review,
608
+ fix, test, and follow-up Work Items can all attach to the same PR, and multiple Watches can observe
609
+ it independently.
527
610
 
528
611
  ---
529
612
 
530
613
  ## 16. Agent / Minion / Team Member
531
614
 
532
- **What it is.** A named role with a charter, a skill list, a default CLI runtime, and metrics.
533
- Examples: Ripley (architect / explorer), Dallas (engineer), Lambert (analyst), Rebecca
534
- (architect), Ralph (engineer). Sometimes called "Minions" (the project's name), "Team Members"
535
- (in the dashboard), or just "Agents" (in the code).
615
+ **What it is.** A named role with a charter, descriptive `expertise` tags, runtime/model
616
+ configuration, and execution metrics. "Minion", "Team Member", and "Agent" refer to the same
617
+ concept in different UI/code contexts.
618
+
619
+ `expertise` is not the executable **Skill** system. It appears in the identity prompt and provides
620
+ a soft preference to `pickReReviewAgentHints` for reviewer selection; it is not a hard routing
621
+ constraint. The legacy config key `skills` is accepted only as a compatibility fallback.
536
622
 
537
623
  **Where it lives.**
538
- - Default roster: `engine/shared.js` line 1486 (`DEFAULT_AGENTS`).
539
- - Charter: `agents/<id>/charter.md` — read by `getAgentCharter` (`engine/queries.js` line 505).
540
- - Per-agent config (cli, model, budget, skills): `config.json` `agents.<id>`.
541
- - Metrics: `engine/state.db` `metrics` (per-agent token / cost / quality / runtime).
542
624
 
543
- **Backing classes / functions.**
544
- - Charter loader: `engine/queries.js` line 505.
545
- - Roster builder: `getAgents` line 509.
546
- - Spawn entry: `engine/spawn-agent.js`.
547
- - Charter injection into prompt: `engine/playbook.js` line 517.
625
+ - Default roster: `engine/shared.js#DEFAULT_AGENTS`
626
+ - Per-agent config: `config.json` under `agents.<id>`
627
+ - Charter: `agents/<id>/charter.md`
628
+ - Metrics and dispatch history: SQL-backed runtime state
629
+
630
+ **Backing symbols.**
548
631
 
549
- **Existing dashboard.** `dashboard/pages/home.html` — "Minions Members" / agent cards.
632
+ - Roster/status projection: `engine/queries.js#getAgents`
633
+ - Detail projection: `engine/queries.js#getAgentDetail`
634
+ - Identity/charter prompt: `engine/playbook.js#buildSystemPrompt`
635
+ - Soft re-review preference: `engine/lifecycle.js#pickReReviewAgentHints`
636
+ - Runtime selection: `engine/shared.js#resolveAgentCli`
637
+ - Bundled adapters: `engine/runtimes/index.js` (`claude`, `copilot`, `codex`)
638
+
639
+ **Existing dashboard.** Agent cards and detail views show status, runtime/model, charter, output,
640
+ inbox, and recent dispatches.
550
641
 
551
642
  **Endpoints.**
552
- - `POST /api/agent-kill/:id` (line 3847)
553
- - `GET /api/agent/:id/live-stream` (SSE — search for `/live-stream`)
554
- - `GET /api/agent-detail/:id` (line 6686)
555
643
 
556
- **Relationships.** Agent ↔ Charter (1:1), Agent ↔ Skill (1:N), Agent ↔ runtime (Claude or
557
- Copilot via `resolveAgentCli`), Agent ↔ Work Item (N:N over history). Routing decides which agent
558
- gets which work type.
644
+ - `GET /api/agents`
645
+ - `GET /api/agent/:id`
646
+ - `POST /api/agent/:id/kill`
647
+ - `GET /api/agent/:id/live-stream`
648
+ - `GET /api/agent/:id/live` and `/live-output`
649
+ - `GET /api/agent/:id/output`
650
+ - `POST /api/agents/steer`
651
+ - `POST /api/agents/cancel`
652
+ - `POST /api/agents/charter`
653
+
654
+ **Relationships.** Routing and optional hints choose an Agent for a Work Item. The selected runtime
655
+ adapter determines CLI behavior; the Charter and expertise tags shape identity; executable Skills
656
+ remain runtime/harness assets.
559
657
 
560
658
  ---
561
659
 
562
660
  ## 17. Project
563
661
 
564
- **What it is.** A repository the engine knows about. Has a name, local path, repo host
565
- (`github` or `ado`), repository ID, main branch, and per-source toggles (`workSources`).
662
+ **What it is.** A repository Minions knows how to operate on. A project definition carries its
663
+ name, local operator checkout, repository identity/host, main branch, checkout mode, and enabled
664
+ work sources.
566
665
 
567
666
  **Where it lives.**
568
- - Definitions: `config.json` `projects: []`.
569
- - Runtime records: project-scoped rows in `engine/state.db`.
570
- - Removal artifact: `projects/.archived/<name>-YYYYMMDD/`.
571
-
572
- **Backing classes / functions.**
573
- - Helpers: `engine/shared.js`
574
- - `getProjects`
575
- - `stateScope`, `readWorkItems`, `readPullRequests`
576
- - `projectStateDir` for file-backed project definitions/artifacts.
577
- - Removal: `engine/projects.js` `removeProject` (canonical teardown — never edit `config.json`
578
- directly).
579
-
580
- **Existing dashboard.** `dashboard/pages/settings.html` — Projects section.
581
-
582
- **Endpoints (`dashboard.js`).**
583
- - `POST /api/projects/browse` (7181)
584
- - `POST /api/projects/scan` (7182)
585
- - `POST /api/projects/confirm-token` (7183) SEC-05 single-use token
586
- - `POST /api/projects/add` (7184)
587
- - `POST /api/projects/remove` (7185)
588
-
589
- **Relationships.** Project ⊃ Work Items, Pull Requests, Schedules (via `project` field), and
590
- Pipelines that target it. The minions repo is special: it's the home of the engine itself.
667
+
668
+ - Definitions: `config.json` under `projects[]`
669
+ - Runtime records: project-scoped rows in `engine/state.db`
670
+ - Project definitions/artifacts: `projects/<name>/`
671
+ - Removal archive: `projects/.archived/<name>-YYYYMMDD/`
672
+
673
+ **Backing symbols.**
674
+
675
+ - Config projection: `engine/shared.js#getProjects`
676
+ - Scope helpers: `engine/shared.js#stateScope`, `#readWorkItems`, and
677
+ `#readPullRequests`
678
+ - Checkout mode: `engine/shared.js#resolveCheckoutMode`
679
+ - Canonical removal: `engine/projects.js#removeProject`
680
+
681
+ `checkoutMode: "worktree"` is the default isolated execution model.
682
+ `checkoutMode: "live"` opts a project into guarded in-place execution.
683
+
684
+ **Existing dashboard.** `dashboard/pages/settings.html` owns project onboarding and removal.
685
+
686
+ **Endpoints.**
687
+
688
+ - `POST /api/projects/browse`
689
+ - `POST /api/projects/scan`
690
+ - `POST /api/projects/confirm-token`
691
+ - `POST /api/projects/add`
692
+ - `POST /api/projects/remove`
693
+
694
+ **Relationships.** Projects scope Work Items, PRs, worktrees, and project-targeted automation.
695
+ Project removal is a coordinated lifecycle operation, never a direct `config.json` edit.
591
696
 
592
697
  ---
593
698
 
594
699
  ## 18. Skill
595
700
 
596
- **What it is.** A reusable prompt / workflow snippet under `.claude/skills/<name>/SKILL.md`.
597
- Skills can be `scope: minions` (installed personally to the runtime's user dir) or
598
- `scope: project` (PR'd into the project repo). Agents auto-extract skills from their output via
599
- ` ```skill ` fenced blocks.
701
+ **What it is.** An executable prompt/workflow asset stored as `SKILL.md`. Agents can emit a
702
+ fenced `skill` artifact with `scope: minions` (personal runtime-native installation) or
703
+ `scope: project` (queued for a PR into the project-native skill root).
600
704
 
601
- **Where it lives.**
602
- - User skills: `~/.claude/skills/`, `~/.copilot/skills/`, etc. (runtime-specific).
603
- - Project skills: `<project>/.claude/skills/`, `<project>/.github/skills/`.
604
- - Frontmatter parser: `parseSkillFrontmatter` (`engine/shared.js`, exported line 14 of
605
- `engine/queries.js`).
705
+ This concept is distinct from `agents.<id>.expertise`, which is descriptive agent metadata.
606
706
 
607
- **Backing classes / functions.**
608
- - Discovery: `engine/queries.js` `collectSkillFiles` line 789, `getSkills` line 891,
609
- `getSkillIndex` line 916.
610
- - Per-runtime roots: adapter `getSkillRoots()` / `getSkillWriteTargets()` (engine/runtimes/).
707
+ **Where it lives.** Runtime adapters own discovery and write targets:
611
708
 
612
- **Existing dashboard.** `dashboard/pages/tools.html` — skill browser.
709
+ - Claude: personal `.claude/skills`, project `.claude/skills`
710
+ - Copilot: personal `.copilot/skills`, project `.github/skills`
711
+ - Codex: personal and project `.agents/skills`
712
+ - Portable discovery: `.agents/skills` is visible across bundled adapters
613
713
 
614
- **Endpoints.**
615
- - `GET /api/skill` (line 7178) — read a single skill file.
714
+ Adapters may discover additional compatible roots without changing orchestration code.
715
+
716
+ **Backing symbols.**
616
717
 
617
- **Relationships.** Skill Runtime adapter (storage paths differ). Skills ↔ Agent prompts
618
- (skills can be invoked mid-task).
718
+ - Frontmatter parser: `engine/shared.js#parseSkillFrontmatter`
719
+ - Discovery: `engine/queries.js#collectSkillFiles`
720
+ - Dashboard projections: `engine/queries.js#getSkills` and `#getSkillIndex`
721
+ - Extraction: `engine/lifecycle.js#extractSkillsFromOutput`
722
+ - Adapter contract: `getSkillRoots()` and `getSkillWriteTargets()` in
723
+ `engine/runtimes/{claude,copilot,codex}.js`
724
+
725
+ **Existing dashboard.** `dashboard/pages/tools.html` contains the skill browser.
726
+
727
+ **Endpoints.** `GET /api/skill` reads a selected skill; the broader index is included in dashboard
728
+ status data.
729
+
730
+ **Relationships.** Skills are runtime/harness assets that an Agent can invoke. The runtime adapter
731
+ owns their paths, while Minions lifecycle code owns extraction and project-scope PR dispatch.
619
732
 
620
733
  ---
621
734
 
622
735
  ## 19. MCP Server
623
736
 
624
- **What it is.** A Model Context Protocol server the runtime CLI can call. Examples: GitHub MCP,
625
- Azure DevOps MCP, custom tool servers. Configured per-fleet and per-runtime; agents see them as
626
- extra tools.
737
+ **What it is.** A Model Context Protocol tool server discovered by the selected CLI runtime. MCP
738
+ configuration is runtime-native; repository/user harness files are not merged into Minions
739
+ `config.json`.
627
740
 
628
741
  **Where it lives.**
629
- - Configuration: `config.json` `mcpServers: { … }`.
630
- - Aggregator: `getMcpServers` in `dashboard.js` line 759 (also re-reads runtime-specific
631
- configs at lines 750–787, e.g. `~/.copilot/mcp-config.json`, `~/.claude/mcp-config.json`).
632
742
 
633
- **Backing classes / functions.**
634
- - Loader: `dashboard.js` line 759 (`getMcpServers`).
635
- - Engine status integration: `getStatusJson` includes `mcpServers` (line 905).
636
- - Per-runtime adapter knobs: `engine.copilotDisableBuiltinMcps` (default true) strips the
637
- built-in `github-mcp-server` because it would mutate state behind the engine's back.
743
+ - Claude user registrations: `~/.claude.json` (`mcpServers`)
744
+ - Copilot user registrations: `~/.copilot/mcp-config.json`
745
+ - Workspace registrations surfaced by the dashboard: `<project>/.mcp.json`
746
+ - Other runtime-native locations: owned by the corresponding CLI/adapter contract
747
+
748
+ **Backing symbols.**
638
749
 
639
- **Existing dashboard.** `dashboard/pages/tools.html` — MCP server list with status.
750
+ - Dashboard inventory: `dashboard.js#getMcpServers`
751
+ - Watched config paths: `engine/queries.js` slow-state dependency collector
752
+ - Runtime preparation/discovery: `engine/runtimes/*`
753
+ - Copilot built-in suppression: `engine.copilotDisableBuiltinMcps`
640
754
 
641
- **Endpoints.** Read-only via `/api/status`. There is no dedicated MCP CRUD endpoint
642
- configuration is via `/api/settings` (config.json edits).
755
+ The dashboard reads configuration files to inventory registrations; it does not claim live
756
+ connection health. Agent spawning relies on native runtime discovery from the assigned working
757
+ directory rather than copying repository harness configuration into Minions settings.
643
758
 
644
- **Relationships.** MCP Runtime (Copilot has built-in MCPs that we explicitly disable). MCP ↔
645
- Skill is unrelated; skills are prompt-level, MCPs are tool-level.
759
+ **Existing dashboard.** `dashboard/pages/tools.html` lists discovered MCP registrations.
760
+
761
+ **Endpoints.** MCP inventory appears in `/api/status`; there is no dedicated MCP CRUD API.
762
+
763
+ **Relationships.** MCP servers provide tools. **Skills** provide reusable prompt workflows. Both
764
+ are runtime-visible assets, but they have separate discovery and execution contracts.
646
765
 
647
766
  ---
648
767
 
649
768
  ## 20. Engine
650
769
 
651
- **What it is.** The orchestrator daemon. One Node process; runs a 10 s tick that drains the
652
- **Dispatch Queue**, polls **PRs**, evaluates **Watches** every 3 ticks, runs **Schedules**,
653
- consolidates the **Inbox**, and so on. It's also the gatekeeper for control state
654
- (`paused | running | stopping`).
770
+ **What it is.** The orchestration daemon. Its default tick is 10 seconds. Tick phases handle
771
+ timeouts/steering, inbox consolidation, cleanup, watch evaluation, PR polling/reconciliation,
772
+ dispatch, work discovery, snapshots, and diagnostics.
655
773
 
656
774
  **Where it lives.**
657
- - Process: `engine.js` (root).
658
- - State: `engine/state.db` (logs, metrics, queues, watches, schedules, PRDs) plus
659
- `engine/control.json` for process coordination.
660
775
 
661
- **Backing classes / functions.**
662
- - Tick: `engine.js` (top-level `tick()`).
663
- - Defaults: `engine/shared.js` line 860 (`ENGINE_DEFAULTS`).
664
- - Concurrency: SQLite transactions for runtime records; file locks only for intentionally
665
- file-backed definitions and coordination sidecars.
666
- - Restart re-attach: PID files in `engine/tmp/pid-<id>.pid` + `live-output.log` mtimes,
667
- 20-min grace.
776
+ - Process entry: `engine.js`
777
+ - Authoritative runtime state: `engine/state.db`
778
+ - Process coordination: `engine/control.json`, PID/stop-intent files, and bounded sidecars
779
+
780
+ **Backing symbols.**
781
+
782
+ - Tick: `engine.js#tick` / `#tickInner`
783
+ - Defaults: `engine/shared.js#ENGINE_DEFAULTS`
784
+ - Watch cadence: `ENGINE_DEFAULTS.watchPollEvery` (18 ticks by default)
785
+ - Cold-process reattachment: `engine/cli.js` startup reattachment path
786
+ - Stale-orphan grace: `engine/timeout.js` with `ENGINE_DEFAULTS.heartbeatTimeout`
787
+
788
+ Tracked live agents are not killed merely for output silence. Cold agents can be reattached after
789
+ an engine restart through persisted PID/session data and `agents/<id>/live-output.log`; pooled ACP
790
+ leases intentionally follow a different lifecycle.
668
791
 
669
- **Existing dashboard.** `dashboard/pages/engine.html` engine timeline, log, controls.
792
+ **Existing dashboard.** `dashboard/pages/engine.html` exposes engine state, dispatch history, logs,
793
+ and controls.
670
794
 
671
795
  **Endpoints.**
672
- - `POST /api/engine/wakeup` (7406) — set `_wakeupAt` so the tick fires now.
673
- - `POST /api/engine/restart` (7410) — graceful restart.
674
- - `GET /api/status` (6838), `/api/health` (6844), `/api/status-stream` (6839, SSE).
675
796
 
676
- **Relationships.** Engine = the verb. Every other concept on this page is the engine's data.
797
+ - `GET /api/status`
798
+ - `GET /api/status-stream`
799
+ - `GET /api/health`
800
+ - `POST /api/engine/wakeup`
801
+ - `POST /api/engine/restart`
802
+ - PR polling/auto-fix controls under `/api/engine/*`
803
+
804
+ **Relationships.** Engine is the coordinator over every other concept. SQLite stores durable
805
+ runtime records; files remain for definitions, human documents, caches, artifacts, and process
806
+ coordination.
677
807
 
678
808
  ---
679
809
 
680
810
  ## 21. Settings
681
811
 
682
- **What it is.** `config.json`. Holds projects, agents, engine defaults, schedules, features, and
683
- runtime knobs. Merged with `.claude/settings.local.json` for user-only overrides.
812
+ **What it is.** Minions configuration stored in `config.json`: projects, agents, engine defaults,
813
+ schedules, features, and runtime selection/options.
814
+
815
+ Repository and user harness settings are not merged into this object. Files such as runtime-native
816
+ MCP/skill configuration remain owned and discovered by the selected CLI.
817
+
818
+ **Where it lives.**
819
+
820
+ - Minions settings: `<MINIONS_DIR>/config.json`
821
+ - Routing table: `<MINIONS_DIR>/routing.md` (separate, intentionally file-backed)
822
+ - Runtime-native harness configuration: runtime-owned user/repository paths
823
+
824
+ **Backing symbols.**
684
825
 
685
- **Where it lives.** `config.json` (root); `.claude/settings.local.json` (gitignored).
826
+ - Loader: `engine/queries.js#getConfig`
827
+ - Defaults: `engine/shared.js#ENGINE_DEFAULTS`
828
+ - Settings handlers: `dashboard.js#handleSettingsRead`, `#handleSettingsUpdate`,
829
+ `#handleSettingsReset`, and `#handleSettingsRouting`
686
830
 
687
- **Backing classes / functions.**
688
- - Loader: `engine/queries.js` `getConfig` (around line 86–166, includes migrations like
689
- `applyLegacyCcModelMigration`).
690
- - Defaults: `engine/shared.js` line 860 (`ENGINE_DEFAULTS`).
691
- - Routing knob: `routing.md` (separate file).
831
+ **Existing dashboard.** `dashboard/pages/settings.html` is the canonical settings surface.
692
832
 
693
- **Existing dashboard.** `dashboard/pages/settings.html` — multi-tab editor for engine, projects,
694
- agents, runtimes.
833
+ **Endpoints.**
695
834
 
696
- **Endpoints (`dashboard.js`).**
697
- - Settings reads / writes are via the `/api/settings*` family (search for them in the ROUTES
698
- table around 6249–6599 in earlier dashboard.js layouts; the agent-driven version uses the
699
- ROUTES registry).
700
- - `POST /api/settings/reset` — restore defaults.
701
- - `POST /api/settings/routing` — read `routing.md`.
835
+ - `GET /api/settings`
836
+ - `POST /api/settings`
837
+ - `POST /api/settings/reset`
838
+ - `POST /api/settings/routing`
702
839
 
703
- **Relationships.** Settings is the *write target* for almost every config-changing action in CC
704
- and the dashboard. Two locations to know about: per-fleet (`engine.*`) and per-agent
705
- (`agents.<id>.*`). They don't fall through to each other for runtime selection.
840
+ **Relationships.** Fleet defaults live under `engine.*`; agent overrides live under
841
+ `agents.<id>.*`; project behavior lives under `projects[]`. Agent and Command Center runtime/model
842
+ resolution are intentionally independent.
706
843
 
707
844
  ---
708
845
 
709
846
  ## 22. Feature Flag
710
847
 
711
- **What it is.** A temporary gate registered in `engine/features.js`. Resolved per request:
712
- env var (`MINIONS_FEATURE_<UPPER_SNAKE>`) `config.features[id]` registry default. Throws if
713
- asked for an unknown id. The slim UX itself is gated behind `slim-ux`.
848
+ **What it is.** A temporary product/UX gate registered in `engine/features.js`. Resolution order
849
+ is environment override (`MINIONS_FEATURE_<ID>`) -> `config.features[id]` -> registry default.
850
+ Unknown flag IDs fail loudly.
714
851
 
715
- **Where it lives.** `engine/features.js` lines 1–62 (registry + `isFeatureOn`).
852
+ Feature flags are not a substitute for permanent `engine.*` configuration. The `slim-ux` flag gates
853
+ the redesigned dashboard.
716
854
 
717
- **Backing classes / functions.**
718
- - Registry: `FEATURES` (top of `engine/features.js`).
719
- - Resolver: `isFeatureOn(id, config)`.
720
- - Env override: any `MINIONS_FEATURE_*` translates id `slim-ux` ↔ `MINIONS_FEATURE_SLIM_UX`.
855
+ **Where it lives.** `engine/features.js#FEATURES`.
721
856
 
722
- **Existing dashboard.** `dashboard/pages/settings.html` — "Show experimental flags" disclosure.
723
- Slim UX also has its own minimal flags-only settings dialog (`dashboard/slim.html` line ~445).
857
+ **Backing symbols.**
724
858
 
725
- **Endpoints (`dashboard.js`).**
726
- - `GET /api/features` (7457)
727
- - `POST /api/features/toggle` (7458)
859
+ - Resolver: `engine/features.js#isFeatureOn`
860
+ - Listing: `engine/features.js#listFeatures`
861
+ - Registry check: `engine/features.js#hasFeature`
728
862
 
729
- **Relationships.** Feature flag everything that gets ramped behind one. When the feature
730
- ships, *delete the registry entry and the gate* — stale entries past `expires` surface in
731
- preflight.
863
+ **Existing dashboard.** Settings exposes registered experimental flags and their current values.
864
+
865
+ **Endpoints.**
866
+
867
+ - `GET /api/features`
868
+ - `POST /api/features/toggle`
869
+
870
+ **Relationships.** A flag gates code/UI behavior until rollout is complete. Registry metadata
871
+ includes defaults and expiry dates so stale experiments are visible to operators.
732
872
 
733
873
  ---
734
874
 
735
875
  ## 23. Routing (`routing.md`)
736
876
 
737
- **What it is.** A markdown table mapping work types to agents (e.g. `implement dallas`,
738
- `review ripley`, `fix _author_`). The engine parses it on every tick.
877
+ **What it is.** A global Markdown table mapping work types to preferred and fallback agents. The
878
+ engine reads it through an mtime-based cache during agent resolution.
739
879
 
740
- **Where it lives.** `routing.md` (root).
880
+ **Where it lives.** `<MINIONS_DIR>/routing.md`.
741
881
 
742
- **Backing classes / functions.**
743
- - Parser: `engine/routing.js` `parseRoutingTable` line 31.
744
- - Path constant: line 15.
745
- - Cache: line 59 (`_routingCache`).
746
- - Re-export: line 301.
882
+ There is no project-local routing override. Project-local **playbook** overrides exist, but routing
883
+ uses the single global `ROUTING_PATH`.
747
884
 
748
- **Existing dashboard.** `dashboard/pages/settings.html` — Routing panel (read-only with an edit
749
- modal).
885
+ **Backing symbols.**
750
886
 
751
- **Endpoints.**
752
- - `POST /api/settings/routing` — read `routing.md`.
887
+ - Path and reader: `engine/routing.js#ROUTING_PATH` and `#getRouting`
888
+ - Parser: `engine/routing.js#parseRoutingTable`
889
+ - Cache: `engine/routing.js#getRoutingTableCached`
890
+ - Work-type lookup: `engine/routing.js#routeForWorkType`
891
+ - Final resolution: `engine/routing.js#resolveAgent`
892
+
893
+ **Existing dashboard.** Settings exposes the routing table editor.
753
894
 
754
- **Relationships.** Routing decides which **Agent** receives which **Work Type**. The CC action
755
- parser pre-flights routing to surface "no agent available" warnings before enqueue. Per-project
756
- overrides are possible via `projects/<name>/routing.md`.
895
+ **Endpoints.** `POST /api/settings/routing` updates `routing.md`; `GET /api/settings` includes the
896
+ current routing content.
897
+
898
+ **Relationships.** Routing supplies preferred/fallback candidates for a Work Item type. Explicit
899
+ hard pins, author routing, availability, budget, retry reassignment, and temporary-agent policy
900
+ still participate in final selection.
757
901
 
758
902
  ---
759
903
 
760
904
  ## 24. Charter (Agent Charter)
761
905
 
762
- **What it is.** A short markdown file describing an agent's role, voice, and rules of engagement.
763
- Loaded into the agent's system prompt at every dispatch.
906
+ **What it is.** A Markdown file describing one Agent's role, voice, expertise boundary, and rules
907
+ of engagement. It is loaded into that Agent's system prompt for each dispatch.
908
+
909
+ **Where it lives.** `agents/<id>/charter.md`.
910
+
911
+ **Backing symbols.**
764
912
 
765
- **Where it lives.** `agents/<id>/charter.md`. Examples: `agents/dallas/charter.md`,
766
- `agents/ripley/charter.md`, …
913
+ - Prompt loading/injection: `engine/playbook.js#buildSystemPrompt`
914
+ - Dashboard detail read: `engine/queries.js#getAgentDetail`
915
+ - Dashboard write handler: the `/api/agents/charter` route in `dashboard.js`
767
916
 
768
- **Backing classes / functions.**
769
- - Loader: `engine/queries.js` `getAgentCharter` line 505.
770
- - Injection into prompt: `engine/playbook.js` line 517 (`prompt += '## Your Charter\n\n' +
771
- charter`).
917
+ The prompt and detail surfaces each read the charter at their respective system-prompt/detail
918
+ boundaries.
772
919
 
773
- **Existing dashboard.** Agent detail modal on `home.html` shows the charter.
920
+ **Existing dashboard.** Agent detail shows the charter; Settings can edit agent identity metadata.
921
+
922
+ **Endpoints.**
774
923
 
775
- **Endpoints.** Read-only via `/api/agent-detail/:id` (line 6686).
924
+ - `GET /api/agent/:id` -- detail including charter
925
+ - `POST /api/agents/charter` -- save charter content
776
926
 
777
- **Relationships.** Charter Agent (1:1). Distinct from Skills (skills are reusable work
778
- recipes; charter is identity).
927
+ **Relationships.** A Charter is one-to-one with an Agent. It is identity/context, whereas a Skill
928
+ is a reusable executable workflow.
779
929
 
780
930
  ---
781
931
 
782
932
  ## 25. Meeting
783
933
 
784
- **What it is.** A multi-agent debate workflow. Three rounds: investigate debate conclude.
785
- Participants are explicitly listed; each round writes a structured findings file before the
786
- engine advances. The engine times out / advances rounds automatically.
787
-
788
- **Where it lives.** `meetings/*.json` (definitions + transcripts). Per-agent artifact notes
789
- land in `notes/inbox/`.
790
-
791
- **Backing classes / functions.**
792
- - Dirs / status: `engine/meeting.js`
793
- - lines 21–24 (`MEETINGS_DIR`, `MEETING_NOTE_ARTIFACT_ROOT`, `TERMINAL_MEETING_STATUSES`,
794
- `ROUND_STATUS_BY_NAME`).
795
- - line 29 (`ROUND_NUMBER_BY_NAME`).
796
- - Round bookkeeping: `roundKeyFor` line 40, `getRoundFailures` line 46, `hasRoundFailure`
797
- line 59, `hasRoundSuccess` line 63, `hasRoundTerminalOutcome` line 69,
798
- `allParticipantsFinishedRound` line 73.
799
- - Advance / fail handling: `advanceMeetingIfRoundComplete` line 93,
800
- `buildFailedMeetingConclusion` line 87.
801
- - Empty-output detection: `EMPTY_OUTPUT_PATTERNS` line 15, `isEmptyMeetingContent` line 124.
802
-
803
- **Existing dashboard.** `dashboard/pages/meetings.html` — meeting browser, round status, notes.
804
-
805
- **Endpoints (`dashboard.js`).**
806
- - `POST /api/meetings` (7322) — create
807
- - `GET /api/meetings` (7337)
808
- - `POST /api/meetings/note` (7349)
809
- - `POST /api/meetings/advance` (7359)
810
- - `POST /api/meetings/end` (7369)
811
- - `POST /api/meetings/archive` (7378)
812
- - `POST /api/meetings/unarchive` (7387)
813
- - `POST /api/meetings/delete` (7396)
814
-
815
- **Relationships.** Meeting → emits Notes into the inbox. Each meeting round dispatches one Work
816
- Item per participant. Pipelines may include `meeting` stages.
934
+ **What it is.** A multi-agent debate workflow with three rounds: investigate, debate, and conclude.
935
+ Participants produce round artifacts; the meeting advances when the current round reaches terminal
936
+ outcomes or the operator explicitly intervenes.
817
937
 
818
- ---
938
+ **Where it lives.**
819
939
 
820
- ## Cross-cutting relationship cheatsheet
940
+ - Meeting definitions/state/transcript: `meetings/<id>.json`
941
+ - Participant note artifacts: `notes/inbox/`
821
942
 
822
- ```
823
- Human ──► Command Center ──► [Work Item | Plan | Note | Schedule | Watch | Pinned | Knowledge]
824
-
825
- └─► Dispatch Queue ──► Dispatch ──► Agent (CLI)
826
-
827
- ├─► Pull Request (synced from output)
828
- ├─► Completion (JSON report)
829
- └─► Notes Inbox ──► Consolidation ──► KB / notes.md
830
-
831
- └─► Pinned (manual subset)
943
+ **Backing symbols.**
832
944
 
833
- Plan ──► PRD ──► Work Items (depends_on edges) ──► … ──► Verify Work Item ──► Manual Archive
945
+ - Paths/status maps: `engine/meeting.js#MEETINGS_DIR`,
946
+ `#MEETING_NOTE_ARTIFACT_ROOT`, `#ROUND_STATUS_BY_NAME`, and
947
+ `#ROUND_NUMBER_BY_NAME`
948
+ - Round outcome helpers: `#getRoundFailures` and `#allParticipantsFinishedRound`
949
+ - Advancement: `#advanceMeetingIfRoundComplete`
950
+ - Empty-output guard: `#EMPTY_OUTPUT_PATTERNS` and `#isEmptyMeetingContent`
834
951
 
835
- Pipeline (stages: task / meeting / plan) ──► spawns Work Items / Meetings / Plans
952
+ **Existing dashboard.** `dashboard/pages/meetings.html` shows meetings, rounds, participant
953
+ artifacts, and controls.
836
954
 
837
- Schedule (cron) ──► spawns Work Items
838
- Watch (event) ──► spawns notifications / Work Items / pipeline-continuations
955
+ **Endpoints.**
956
+
957
+ - `POST /api/meetings`
958
+ - `GET /api/meetings`
959
+ - `POST /api/meetings/note`
960
+ - `POST /api/meetings/advance`
961
+ - `POST /api/meetings/end`
962
+ - `POST /api/meetings/archive`
963
+ - `POST /api/meetings/unarchive`
964
+ - `POST /api/meetings/delete`
965
+
966
+ **Relationships.** A Meeting dispatches one participant Work Item per round, writes durable Notes,
967
+ and can itself be a Pipeline stage.
968
+
969
+ ---
970
+
971
+ ## Cross-cutting relationship cheatsheet
839
972
 
840
- Engine reads: routing.md, config.json, definitions, engine/state.db
841
- Engine writes: control.json, artifacts, engine/state.db
973
+ ```
974
+ Human ---> Command Center ---> dashboard /api/* ---> [Work Item | Plan | Note | Schedule | Watch]
975
+ |
976
+ +--> Dispatch Queue ---> Dispatch ---> Agent
977
+ |
978
+ +--> Pull Request
979
+ +--> Completion JSON
980
+ +--> Notes Inbox
981
+ |
982
+ +--> notes.md
983
+ +--> Knowledge Base
984
+
985
+ Plan Markdown ---> plan-to-prd sidecar ---> SQL PRD + PRD Items ---> Work Items ---> Verify
986
+
987
+ Pipeline definition ---> SQL pipeline run ---> stages (task / meeting / plan / API / control flow)
988
+
989
+ Schedule (time) ---> Work Item
990
+ Watch (state) ---> notification or registered follow-up action
991
+
992
+ Engine reads: config.json, routing.md, definitions, human docs, engine/state.db
993
+ Runtime reads: runtime-native harness assets from the assigned working directory
994
+ Engine writes: engine/state.db, control/process sidecars, artifacts, and requested human docs
842
995
  ```