@esneiderbravo/speclaw 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +66 -55
  2. package/dist/cli/commands/cortex.js +49 -0
  3. package/dist/cli/commands/init.js +21 -15
  4. package/dist/cli/commands/lawbook.js +34 -1
  5. package/dist/cli/commands/update.js +14 -2
  6. package/dist/cli/index.js +10 -1
  7. package/dist/modules/cortex/brief.js +75 -0
  8. package/dist/modules/cortex/harness.js +270 -0
  9. package/dist/modules/cortex/register.js +49 -0
  10. package/dist/modules/foundation/assets/AGENTS.template.md +13 -6
  11. package/dist/modules/foundation/assets/CLAUDE.template.md +15 -11
  12. package/dist/modules/foundation/assets/docs/standards/lawbook.template.md +24 -37
  13. package/dist/modules/foundation/assets/workflows/speclaw.yml +1 -1
  14. package/dist/modules/foundation/context-budget.js +2 -0
  15. package/dist/modules/foundation/setup-tool.js +3 -2
  16. package/dist/modules/lawbook/assets/agents/archiver.md +19 -0
  17. package/dist/modules/lawbook/assets/agents/explorer.md +24 -0
  18. package/dist/modules/lawbook/assets/agents/implementer.md +20 -0
  19. package/dist/modules/lawbook/assets/agents/planner.md +27 -0
  20. package/dist/modules/lawbook/assets/agents/reviewer.md +25 -0
  21. package/dist/modules/lawbook/assets/agents/tester.md +21 -0
  22. package/dist/modules/lawbook/assets/commands/cortex.md +11 -0
  23. package/dist/modules/lawbook/assets/rules/spec-tasks-mandatory-steps.md +11 -10
  24. package/dist/modules/lawbook/assets/skills/build/steps/03-implement.md +1 -1
  25. package/dist/modules/lawbook/assets/skills/build/steps/04-hand-off.md +17 -0
  26. package/dist/modules/lawbook/assets/skills/cortex/SKILL.md +13 -0
  27. package/dist/modules/lawbook/assets/skills/cortex/steps/01-load-or-start.md +25 -0
  28. package/dist/modules/lawbook/assets/skills/cortex/steps/02-dispatch-loop.md +19 -0
  29. package/dist/modules/lawbook/assets/skills/cortex/steps/03-complete.md +10 -0
  30. package/dist/modules/lawbook/assets/skills/test/SKILL.md +11 -0
  31. package/dist/modules/lawbook/assets/skills/{build/steps/04-quality-gates.md → test/steps/01-quality-gates.md} +1 -1
  32. package/dist/modules/lawbook/assets/skills/{build/steps/05-manual-verification.md → test/steps/02-manual-verification.md} +1 -1
  33. package/dist/modules/lawbook/assets/skills/{build/steps/06-discipline-reports.md → test/steps/03-discipline-reports.md} +5 -2
  34. package/dist/modules/lawbook/change-tool.js +22 -0
  35. package/dist/modules/lawbook/engine.js +4 -0
  36. package/dist/modules/lawbook/levels.js +9 -3
  37. package/dist/modules/lawbook/register.js +7 -0
  38. package/dist/modules/tools/assets/packs.json +1 -6
  39. package/dist/server.js +4 -1
  40. package/dist/shared/agents.js +3 -3
  41. package/dist/shared/exposure.js +2 -2
  42. package/dist/shared/tool-catalog.js +3 -2
  43. package/package.json +2 -2
  44. package/dist/modules/lawbook/assets/skills/build/steps/07-hand-off.md +0 -9
  45. package/dist/modules/tools/assets/packs/agents/backend-developer.md +0 -61
  46. package/dist/modules/tools/assets/packs/agents/frontend-developer.md +0 -62
  47. package/dist/modules/tools/assets/packs/agents/product-strategy-analyst.md +0 -56
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Deterministic multi-agent harness state for a lawbook change.
3
+ *
4
+ * Speclaw does not spawn LLMs. This module only persists stage transitions;
5
+ * the host agent (Cursor/Claude/…) follows the Cortex skill and calls these
6
+ * ops via `speclaw cortex` or the `cortex` MCP tool.
7
+ *
8
+ * Cortex must not import from the lawbook module (no cycles). Ceremony level
9
+ * is read locally from `change.json` `confirmedLevel` (default 3).
10
+ */
11
+ import fs from "node:fs";
12
+ import path from "node:path";
13
+ export const HARNESS_STAGES = [
14
+ "exploring",
15
+ "planning",
16
+ "questions",
17
+ "implementing",
18
+ "reviewing",
19
+ "testing",
20
+ "archiving",
21
+ "done",
22
+ ];
23
+ export const harnessOps = ["status", "start", "advance", "rework"];
24
+ const DEFAULT_MAX_REWORK = 3;
25
+ function specRoot(projectPath) {
26
+ return path.join(projectPath, "lawbook");
27
+ }
28
+ function changeDir(projectPath, change) {
29
+ return path.join(specRoot(projectPath), "changes", change);
30
+ }
31
+ function harnessPath(projectPath, change) {
32
+ return path.join(changeDir(projectPath, change), "harness.json");
33
+ }
34
+ function nowIso() {
35
+ return new Date().toISOString();
36
+ }
37
+ function requireChangeDir(projectPath, change) {
38
+ const dir = changeDir(projectPath, change);
39
+ if (!fs.existsSync(dir)) {
40
+ throw new Error(`change "${change}" not found under lawbook/changes/`);
41
+ }
42
+ return dir;
43
+ }
44
+ /**
45
+ * Read confirmed ceremony level from change.json without importing lawbook.
46
+ * Missing file or field → 3.
47
+ */
48
+ function readConfirmedLevel(projectPath, change) {
49
+ const p = path.join(changeDir(projectPath, change), "change.json");
50
+ if (!fs.existsSync(p))
51
+ return 3;
52
+ try {
53
+ const raw = JSON.parse(fs.readFileSync(p, "utf8"));
54
+ const n = raw.confirmedLevel;
55
+ if (n === 0 || n === 1 || n === 2 || n === 3)
56
+ return n;
57
+ }
58
+ catch {
59
+ /* default */
60
+ }
61
+ return 3;
62
+ }
63
+ /** Read harness.json or return null when absent. */
64
+ export function readHarness(projectPath, change) {
65
+ requireChangeDir(projectPath, change);
66
+ const p = harnessPath(projectPath, change);
67
+ if (!fs.existsSync(p))
68
+ return null;
69
+ return JSON.parse(fs.readFileSync(p, "utf8"));
70
+ }
71
+ function writeHarness(projectPath, change, state) {
72
+ const p = harnessPath(projectPath, change);
73
+ fs.writeFileSync(p, JSON.stringify(state, null, 2) + "\n");
74
+ }
75
+ function nextAfterExplore(level) {
76
+ return level === 0 ? "implementing" : "planning";
77
+ }
78
+ function nextAfterImplement(level) {
79
+ return level === 0 ? "testing" : "reviewing";
80
+ }
81
+ /**
82
+ * Legal one-step advances (not rework). Rework is handled separately.
83
+ */
84
+ function allowedAdvance(from, level, verdict) {
85
+ switch (from) {
86
+ case "exploring":
87
+ return nextAfterExplore(level);
88
+ case "planning":
89
+ return "implementing";
90
+ case "questions":
91
+ return "planning";
92
+ case "implementing":
93
+ return nextAfterImplement(level);
94
+ case "reviewing":
95
+ if (verdict === "FAIL") {
96
+ throw new Error(`harness advance from reviewing with FAIL requires op "rework" (not advance)`);
97
+ }
98
+ if (verdict !== "PASS") {
99
+ throw new Error(`harness advance from reviewing requires verdict PASS or FAIL`);
100
+ }
101
+ return "testing";
102
+ case "testing":
103
+ if (verdict === "FAIL") {
104
+ throw new Error(`harness advance from testing with FAIL requires op "rework"`);
105
+ }
106
+ if (verdict !== "PASS") {
107
+ throw new Error(`harness advance from testing requires verdict PASS or FAIL`);
108
+ }
109
+ return "archiving";
110
+ case "archiving":
111
+ return "done";
112
+ case "done":
113
+ throw new Error(`harness already done — no further advance`);
114
+ default: {
115
+ const _exhaustive = from;
116
+ throw new Error(`unknown stage ${String(_exhaustive)}`);
117
+ }
118
+ }
119
+ }
120
+ /**
121
+ * Dispatch a harness op for a change.
122
+ *
123
+ * // Covers: req~harness-state~1
124
+ */
125
+ export function handleHarness(args) {
126
+ const { projectPath, change, harnessOp } = args;
127
+ requireChangeDir(projectPath, change);
128
+ if (harnessOp === "status") {
129
+ return { state: readHarness(projectPath, change) };
130
+ }
131
+ if (harnessOp === "start") {
132
+ const existing = readHarness(projectPath, change);
133
+ if (existing && existing.stage !== "done") {
134
+ throw new Error(`harness already started for "${change}" (stage=${existing.stage}); use status/advance/rework`);
135
+ }
136
+ const level = readConfirmedLevel(projectPath, change);
137
+ const state = {
138
+ version: 1,
139
+ change,
140
+ stage: "exploring",
141
+ level,
142
+ iteration: 0,
143
+ maxRework: DEFAULT_MAX_REWORK,
144
+ verdicts: { review: null, test: null },
145
+ openQuestions: [],
146
+ history: [
147
+ {
148
+ at: nowIso(),
149
+ from: "exploring",
150
+ to: "exploring",
151
+ op: "start",
152
+ note: args.note,
153
+ },
154
+ ],
155
+ };
156
+ writeHarness(projectPath, change, state);
157
+ return state;
158
+ }
159
+ const current = readHarness(projectPath, change);
160
+ if (!current) {
161
+ throw new Error(`no harness.json for "${change}" — run cortex start first`);
162
+ }
163
+ if (harnessOp === "advance") {
164
+ // Planner may pause for questions instead of advancing to implement.
165
+ if (current.stage === "planning" && args.pauseForQuestions) {
166
+ const questions = args.openQuestions ?? [];
167
+ if (questions.length === 0) {
168
+ throw new Error(`pauseForQuestions requires at least one openQuestions entry`);
169
+ }
170
+ const next = {
171
+ ...current,
172
+ stage: "questions",
173
+ openQuestions: questions,
174
+ history: [
175
+ ...current.history,
176
+ {
177
+ at: nowIso(),
178
+ from: "planning",
179
+ to: "questions",
180
+ op: "advance",
181
+ note: args.note,
182
+ },
183
+ ],
184
+ };
185
+ writeHarness(projectPath, change, next);
186
+ return next;
187
+ }
188
+ const to = allowedAdvance(current.stage, current.level, args.verdict ?? undefined);
189
+ const verdicts = { ...current.verdicts };
190
+ if (current.stage === "reviewing" && args.verdict)
191
+ verdicts.review = args.verdict;
192
+ if (current.stage === "testing" && args.verdict)
193
+ verdicts.test = args.verdict;
194
+ const next = {
195
+ ...current,
196
+ stage: to,
197
+ verdicts,
198
+ openQuestions: current.stage === "questions" ? [] : current.openQuestions,
199
+ history: [
200
+ ...current.history,
201
+ {
202
+ at: nowIso(),
203
+ from: current.stage,
204
+ to,
205
+ op: "advance",
206
+ note: args.note,
207
+ },
208
+ ],
209
+ };
210
+ writeHarness(projectPath, change, next);
211
+ return next;
212
+ }
213
+ if (harnessOp === "rework") {
214
+ if (current.stage !== "reviewing" && current.stage !== "testing") {
215
+ throw new Error(`rework only allowed from reviewing or testing (now ${current.stage})`);
216
+ }
217
+ if (args.verdict !== "FAIL") {
218
+ throw new Error(`rework requires verdict FAIL`);
219
+ }
220
+ if (current.iteration >= current.maxRework) {
221
+ throw new Error(`max rework (${current.maxRework}) reached — coordinator must ask the human before continuing`);
222
+ }
223
+ const verdicts = { ...current.verdicts };
224
+ if (current.stage === "reviewing")
225
+ verdicts.review = "FAIL";
226
+ if (current.stage === "testing")
227
+ verdicts.test = "FAIL";
228
+ const next = {
229
+ ...current,
230
+ stage: "implementing",
231
+ iteration: current.iteration + 1,
232
+ verdicts,
233
+ history: [
234
+ ...current.history,
235
+ {
236
+ at: nowIso(),
237
+ from: current.stage,
238
+ to: "implementing",
239
+ op: "rework",
240
+ note: args.note,
241
+ },
242
+ ],
243
+ };
244
+ writeHarness(projectPath, change, next);
245
+ return next;
246
+ }
247
+ throw new Error(`unknown harnessOp '${String(harnessOp)}'`);
248
+ }
249
+ /**
250
+ * Archive blockers derived from harness verdicts.
251
+ *
252
+ * // Covers: req~harness-archive-gate~1
253
+ */
254
+ export function harnessArchiveBlockers(projectPath, change) {
255
+ const state = readHarness(projectPath, change);
256
+ if (!state) {
257
+ return [`missing harness.json — run \`speclaw cortex start --change ${change}\``];
258
+ }
259
+ const blockers = [];
260
+ if (state.verdicts.test !== "PASS") {
261
+ blockers.push(`harness test verdict is not PASS (got ${String(state.verdicts.test)})`);
262
+ }
263
+ if (state.level >= 1 && state.verdicts.review !== "PASS") {
264
+ blockers.push(`harness review verdict is not PASS (got ${String(state.verdicts.review)})`);
265
+ }
266
+ if (state.stage !== "archiving" && state.stage !== "done") {
267
+ blockers.push(`harness stage is ${state.stage} — advance to archiving before archive`);
268
+ }
269
+ return blockers;
270
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Cortex MCP registration — One brain. Many agents.
3
+ *
4
+ * // Covers: req~cortex-module~1
5
+ */
6
+ import { z } from "zod";
7
+ import { defineTool, text } from "../../shared/mcp.js";
8
+ import { shouldExpose } from "../../shared/exposure.js";
9
+ import { handleHarness, harnessOps, readHarness, } from "./harness.js";
10
+ import { briefForStage } from "./brief.js";
11
+ export const cortexActions = [...harnessOps, "brief"];
12
+ /**
13
+ * Register the canonical `cortex` MCP tool.
14
+ *
15
+ * @param server - MCP server instance.
16
+ * @param opts - Exposure profile.
17
+ */
18
+ export function registerCortex(server, opts = {}) {
19
+ const minimal = Boolean(opts.minimal);
20
+ const add = (name, description, inputSchema, handler) => {
21
+ if (!shouldExpose(name, minimal))
22
+ return;
23
+ defineTool(server, { name, description, inputSchema, handler });
24
+ };
25
+ add("cortex", "Cortex multi-agent loop: status, start, advance, rework, brief for a change.", {
26
+ projectPath: z.string(),
27
+ change: z.string(),
28
+ action: z.enum(cortexActions),
29
+ note: z.string().optional(),
30
+ verdict: z.enum(["PASS", "FAIL"]).optional(),
31
+ openQuestions: z.array(z.string()).optional(),
32
+ pauseForQuestions: z.boolean().optional(),
33
+ }, async ({ projectPath, change, action, note, verdict, openQuestions, pauseForQuestions }) => {
34
+ if (action === "brief") {
35
+ const state = readHarness(projectPath, change);
36
+ const brief = briefForStage(state?.stage ?? null);
37
+ return text(JSON.stringify({ state, ...brief }, null, 2));
38
+ }
39
+ return text(handleHarness({
40
+ projectPath,
41
+ change,
42
+ harnessOp: action,
43
+ note,
44
+ verdict: verdict ?? null,
45
+ openQuestions,
46
+ pauseForQuestions,
47
+ }));
48
+ });
49
+ }
@@ -22,23 +22,30 @@ Claude-specific notes: [`CLAUDE.md`](CLAUDE.md). The law: [`LAWS.md`](LAWS.md).
22
22
  after Compass returns nothing useful, the graph is missing (`compass_index`
23
23
  first), or the target isn't indexed code (stylesheets, config, logs). Cheat
24
24
  sheet: [`docs/compass.md`](docs/compass.md).
25
- 3. **Follow the lawbook workflow** for every non-trivial change; archive
26
- within the same PR. Rules:
25
+ 3. **Follow Cortex** (*One brain. Many agents.*) for every non-trivial change;
26
+ archive within the same PR. The primary agent is the **coordinator**
27
+ (`cortex` skill / `/lawbook/cortex`) — it MUST NOT implement
28
+ product code itself. It dispatches explorer → planner → implementer →
29
+ reviewer → tester → archiver (or adopts each role while obeying that
30
+ role's permission profile). Drive state with the `cortex` MCP tool or
31
+ `speclaw cortex`. Rules:
27
32
  [`docs/standards/lawbook.md`](docs/standards/lawbook.md).
28
33
  4. **Run the quality gates yourself** before declaring anything done — see
29
- [`docs/standards/testing-standards.md`](docs/standards/testing-standards.md):
34
+ [`docs/standards/testing-standards.md`](docs/standards/testing-standards.md)
35
+ (owned by the **tester** role under Cortex):
30
36
  - Tests: `{{test_commands}}`
31
37
  - Lint / type-check: `{{lint_commands}}`
32
38
  5. **Respect the conventions** — branches `{{branch_pattern}}`, commits
33
39
  {{commit_style}}, code that reads like its neighbors. See
34
40
  [`docs/standards/base-standards.md`](docs/standards/base-standards.md) and
35
41
  [`docs/standards/conventions.md`](docs/standards/conventions.md).
36
- 6. **Use the skills.** `ai-specs/` is the canonical home for skills, commands,
37
- and subagents, mirrored to each IDE directory via symlinks.
42
+ 6. **Use the skills and role agents.** `ai-specs/` is the canonical home for
43
+ skills, commands, rules, and agents, mirrored to each IDE directory via
44
+ symlinks.
38
45
  7. **Ask before irreversible or outward-facing actions** — destructive commands;
39
46
  writing to a real data store (DB rows or files with real user data, including
40
47
  for tests — verify against an isolated/throwaway store); publishing
41
- reviews/tickets/comments.
48
+ reviews/tickets/comments. Planner questions always go to the human.
42
49
 
43
50
  ## The standards (the law, in detail)
44
51
 
@@ -48,21 +48,24 @@ target is not indexed code — stylesheets, JSON/config, markdown, logs,
48
48
  generated files, lockfiles. Never skip Compass because grep "feels faster."
49
49
  See [`docs/compass.md`](docs/compass.md).
50
50
 
51
- ## Rule 2 — Spec-driven, always
51
+ ## Rule 2 — Spec-driven Cortex loop, always
52
52
 
53
- No non-trivial change lands without a spec change (propose → implement →
54
- verify → archive). The rules are in
53
+ No non-trivial change lands without a lawbook change (propose → implement →
54
+ verify → archive) run through **Cortex** (*One brain. Many agents.*). You are the
55
+ **coordinator** unless you were spawned as a role agent: use the `cortex`
56
+ skill / `/lawbook/cortex` and the `cortex` MCP tool; do **not** implement product code yourself.
57
+ Role agents live in `ai-specs/agents/`. The rules are in
55
58
  [`docs/standards/lawbook.md`](docs/standards/lawbook.md);
56
- the workflow skills live in `ai-specs/skills/` and the `/lawbook` commands wrap
57
- them. A change is not done until it is archived — archiving belongs in the PR.
59
+ workflow skills live in `ai-specs/skills/` and `/lawbook` commands wrap them.
60
+ A change is not done until it is archived — archiving belongs in the PR.
58
61
 
59
62
  ## Rule 3 — Quality gates are non-negotiable
60
63
 
61
64
  - Tests: `{{test_commands}}`
62
65
  - Lint / type-check: `{{lint_commands}}`
63
66
 
64
- Run them yourself and report real output. Never claim success you did not
65
- observe. Full rules:
67
+ The **tester** role runs them and reports real output. Never claim success you
68
+ did not observe. Full rules:
66
69
  [`docs/standards/testing-standards.md`](docs/standards/testing-standards.md).
67
70
 
68
71
  ## Rule 4 — Conventions
@@ -72,11 +75,11 @@ its neighbors, comments that carry constraints (never ticket IDs). Full rules:
72
75
  [`docs/standards/base-standards.md`](docs/standards/base-standards.md) and
73
76
  [`docs/standards/conventions.md`](docs/standards/conventions.md).
74
77
 
75
- ## Rule 5 — Skills are law-adjacent
78
+ ## Rule 5 — Skills and role agents are law-adjacent
76
79
 
77
- Skills, commands, and subagents live in `ai-specs/` (symlinked into
78
- `.claude/`, `.cursor/`, `.codex/`, `.agents/`). When a skill matches the
79
- task, use it — do not improvise a parallel process.
80
+ Skills, commands, rules, and agents live in `ai-specs/` (symlinked into
81
+ `.claude/`, `.cursor/`, `.codex/`, `.agents/`). When a skill or role matches
82
+ the task, use it — do not improvise a parallel process.
80
83
 
81
84
  ## Rule 6 — Stop conditions
82
85
 
@@ -85,3 +88,4 @@ schema drops), writing to a real data store (DB rows or files holding real user
85
88
  data — including to set up or tear down test data; verification runs against an
86
89
  isolated/throwaway store instead), publishing anything outward-facing (PR
87
90
  reviews, tickets, comments), or any action that contradicts a standard.
91
+ Planner clarifying questions always go to the human via the coordinator.
@@ -6,38 +6,35 @@ mechanical steps are speclaw MCP tools).
6
6
 
7
7
  ## The loop
8
8
 
9
- No non-trivial change lands without a spec change:
10
-
11
- 1. **explore** — think an idea through before committing (writes nothing).
12
- 2. **draft** — create `lawbook/changes/<name>/`: `proposal.md`, delta specs under
13
- `specs/<capability>/spec.md`, `design.md`, `tasks.md`, and a `reports/`
14
- folder.
15
- 3. **build** — implement the tasks in order, keeping code and spec in
16
- agreement, and write the discipline reports under `reports/`.
17
- 4. **sync** — reconcile the delta specs against what was actually built, then
18
- promote them into the canonical `lawbook/specs/` (`lawbook_sync`). The tool
19
- is a deterministic copy; the agent does the code↔spec reconciliation first.
20
- 5. **archive** — finalize: reconcile, sync, then move the change to
21
- `lawbook/changes/archive/` (`lawbook_archive`), **within the same PR** —
22
- never a post-merge chore. The archive is gated (see below).
9
+ No non-trivial change lands without a lawbook change. The default execution
10
+ model is **Cortex** (*One brain. Many agents.*): the host primary agent is the
11
+ **coordinator** (`cortex` skill / MCP `cortex`) and dispatches explorer → planner →
12
+ implementer → reviewer → tester → archiver. State:
13
+ `lawbook/changes/<name>/harness.json` (`speclaw cortex`). Lawbook owns specs
14
+ and ceremony; Cortex owns the multi-agent loop.
15
+
16
+ 1. **explore** (explorer) — think an idea through before committing (writes nothing).
17
+ 2. **draft** / **quick** (planner) — create `lawbook/changes/<name>/` artifacts
18
+ for the confirmed ceremony level; questions go to the human via the
19
+ coordinator.
20
+ 3. **build** (implementer) — implement tasks; hand off before final gates.
21
+ 4. **review** (reviewer) — `reports/review.md` PASS/FAIL (skipped at level 0).
22
+ 5. **test** (tester) — quality gates, manual verification, discipline reports.
23
+ 6. **sync** / **archive** (archiver) — reconcile, sync when needed, archive
24
+ within the same PR. Gated on Cortex verdicts plus tasks/reports/sync.
23
25
 
24
26
  ## Mandatory task steps
25
27
 
26
28
  `tasks.md` MUST include the steps defined in `lawbook/config.yaml` and the
27
- `spec-tasks-mandatory-steps` rule: feature branch first, tests reviewed and
28
- run, manual verification executed by the agent, discipline reports produced,
29
- docs updated, archive within the PR. The agent performs the manual testing
30
- itself — never delegates it.
29
+ `spec-tasks-mandatory-steps` rule. The **tester** role performs manual
30
+ verification — never the user; the coordinator must not archive without a
31
+ test PASS.
31
32
 
32
33
  ## Reports
33
34
 
34
- Every change carries a `reports/` folder. `build` writes one report per
35
- discipline it touched, named for that discipline — an open set (`backend.md`,
36
- `frontend.md`, `api.md`, `database.md`, `infra.md`, … — `api.md` required
37
- whenever the change touches an API surface) recording what was tested
38
- and the real results — unit, integration, and end-to-end as applicable — with
39
- the commands run and their output. It is evidence of testing that travels with
40
- the change; the archive is blocked until at least one discipline report exists.
35
+ Every change carries a `reports/` folder. The tester writes discipline reports;
36
+ the reviewer writes `review.md`. Archive is blocked until evidence and harness
37
+ verdicts are complete.
41
38
 
42
39
  ## Delta specs
43
40
 
@@ -51,18 +48,8 @@ the change; the archive is blocked until at least one discipline report exists.
51
48
  ## Archiving discipline
52
49
 
53
50
  Always archive with the `archive` command / `lawbook_archive` tool, never a manual
54
- `mv` — the tool performs the spec promotion and validation a manual move skips.
55
-
56
- Before archiving, the agent runs a reconciliation review: it compares what was
57
- built against the delta specs and, when the code has drifted past the original
58
- contracts, shows short insights and reconciles the delta specs.
59
-
60
- `lawbook_archive` is then **gated in the engine** — it refuses to archive (and
61
- reports the reason) while any task is unchecked, while `reports/` holds no
62
- discipline report, or while the delta specs are not yet synced into the
63
- canonical specs. Because the gate covers both the tool and the CLI, a change
64
- reaches the archive only when it is genuinely complete: reconcile, `sync`, then
65
- archive.
51
+ `mv`. The engine refuses archive while tasks are unchecked, reports are missing,
52
+ specs are out of sync when required, or harness review/test verdicts are not PASS.
66
53
 
67
54
  ## Amendments to the law
68
55
 
@@ -18,7 +18,7 @@ jobs:
18
18
  with:
19
19
  fetch-depth: 0
20
20
  - name: ⚖️ Verify
21
- uses: esneiderbravo/speclaw@v1
21
+ uses: esneiderbravo/speclaw@v2
22
22
  - name: 🛡️ Upload SARIF
23
23
  uses: github/codeql-action/upload-sarif@v4
24
24
  if: always()
@@ -1,4 +1,5 @@
1
1
  import { registerCompass } from "../compass/register.js";
2
+ import { registerCortex } from "../cortex/register.js";
2
3
  import { registerSpec } from "../lawbook/register.js";
3
4
  import { registerTools } from "../tools/register.js";
4
5
  import { registerFoundationCore } from "./register-core.js";
@@ -25,6 +26,7 @@ export function collectRegisteredTools(minimal) {
25
26
  registerFoundationCore(stub, opts);
26
27
  registerSpec(stub, opts);
27
28
  registerCompass(stub, opts);
29
+ registerCortex(stub, opts);
28
30
  registerTools(stub, opts);
29
31
  return tools;
30
32
  }
@@ -64,12 +64,13 @@ export function handleSpeclawSetup(args) {
64
64
  return {
65
65
  instructions: [
66
66
  "1. Analyze the repository at projectPath and fill profile fields from the real codebase.",
67
- "2. Call speclaw_setup with action configure-agent / add-pack as needed.",
67
+ "2. Call speclaw_setup with action configure-agent as needed (packs catalog may be empty).",
68
68
  "3. Run lawbook_change action init and compass_index when scaffold completes via CLI if needed.",
69
+ "4. Non-trivial work uses Cortex: cortex skill / speclaw cortex (MCP tool cortex).",
69
70
  ],
70
71
  profileFields: profileFieldHelp,
71
72
  packs: loadPacks(),
72
- note: "Full scaffold runs via CLI: speclaw init — not MCP.",
73
+ note: "Full scaffold runs via CLI: speclaw init — not MCP. Role agents install with the lawbook workflow.",
73
74
  };
74
75
  case "configure-agent": {
75
76
  if (!args.agent)
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: archiver
3
+ description: Reconcile specs, sync, and archive a change when Cortex stage is archiving. No new feature implementation.
4
+ tools: Read, Grep, Glob, Write, Edit, Bash, CallMcpTool, mcp__speclaw__compass_explore, mcp__speclaw__lawbook_change, mcp__speclaw__lawbook_validate, mcp__speclaw__lawbook_sync, mcp__speclaw__lawbook_archive, mcp__speclaw__cortex
5
+ ---
6
+
7
+ You are the **archiver** role in speclaw's **Cortex** (One brain. Many agents.).
8
+
9
+ ## Goal
10
+
11
+ Follow the `sync` then `archive` skills: reconcile delta specs to built code,
12
+ `lawbook_change` action sync when needed, then archive. Advance Cortex to
13
+ `done` after a successful archive.
14
+
15
+ ## Hard constraints
16
+
17
+ - Do **not** start new feature work outside reconciliation.
18
+ - If archive is gated, report blockers to the coordinator — do not bypass the
19
+ engine.
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: explorer
3
+ description: Read-only codebase investigation for a lawbook change. Use when the Cortex stage is exploring (or investigate for bugs). Compass-first; writes nothing under lawbook/ or src/.
4
+ tools: Read, Grep, Glob, CallMcpTool, mcp__speclaw__compass_explore, mcp__speclaw__compass_find, mcp__speclaw__compass_impact, mcp__speclaw__compass_trace, mcp__speclaw__compass_index, mcp__speclaw__lawbook_investigate
5
+ disallowedTools: Write, Edit, MultiEdit, Bash, NotebookEdit
6
+ ---
7
+
8
+ You are the **explorer** role in speclaw's **Cortex** (One brain. Many agents.).
9
+
10
+ ## Goal
11
+
12
+ Investigate the idea or bug with Compass **before** any grep/read. Produce a
13
+ short brief for the planner: relevant symbols, blast radius, risks, and open
14
+ questions. Do **not** draft change artifacts or edit source.
15
+
16
+ ## Skill
17
+
18
+ Follow the `explore` skill (or `investigate` when `changeType` is bug).
19
+
20
+ ## Hard constraints
21
+
22
+ - No Write / StrReplace / git writes / draft / archive / Cortex advance to
23
+ implementing.
24
+ - When finished, return the brief to the coordinator and stop.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: implementer
3
+ description: Implement drafted lawbook tasks in source and tests. Use when Cortex stage is implementing. Does not run final quality gates, review, sync, or archive.
4
+ tools: Read, Grep, Glob, Write, Edit, Bash, CallMcpTool, mcp__speclaw__compass_explore, mcp__speclaw__compass_find, mcp__speclaw__compass_impact, mcp__speclaw__compass_index, mcp__speclaw__lawbook_change, mcp__speclaw__cortex
5
+ disallowedTools: NotebookEdit
6
+ ---
7
+
8
+ You are the **implementer** role in speclaw's **Cortex** (One brain. Many agents.).
9
+
10
+ ## Goal
11
+
12
+ Work `tasks.md` in order using the `build` skill through implementation only.
13
+ Keep code and delta specs in agreement. Check off completed tasks.
14
+
15
+ ## Hard constraints
16
+
17
+ - Do **not** archive, push, or `laws accept`.
18
+ - Do **not** skip the reviewer by "quietly fixing" after a FAIL — wait for
19
+ Cortex `rework` from the coordinator.
20
+ - Stop after implementation hand-off; tester owns gates and discipline reports.
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: planner
3
+ description: Draft lawbook change artifacts and ceremony level. Use when Cortex stage is planning. Asks clarifying questions via the coordinator; never edits src/.
4
+ tools: Read, Grep, Glob, Write, Edit, CallMcpTool, mcp__speclaw__compass_explore, mcp__speclaw__compass_find, mcp__speclaw__lawbook_change, mcp__speclaw__lawbook_level
5
+ disallowedTools: Bash, NotebookEdit
6
+ ---
7
+
8
+ You are the **planner** role in speclaw's **Cortex** (One brain. Many agents.).
9
+
10
+ ## Goal
11
+
12
+ Turn the explorer brief + user intent into a reviewable change under
13
+ `lawbook/changes/<name>/` at the confirmed ceremony level. Prefer `draft` /
14
+ `quick` skills.
15
+
16
+ ## Questions
17
+
18
+ If anything material is ambiguous, **stop**. Return numbered questions to the
19
+ coordinator (do not invent answers). The coordinator advances Cortex with
20
+ `pauseForQuestions`. After human answers, continue drafting.
21
+
22
+ ## Hard constraints
23
+
24
+ - May write only under `lawbook/changes/<name>/` (and related lawbook paths).
25
+ - Do **not** edit `src/`, run archive, or implement code.
26
+ - When the draft is complete, tell the coordinator to `cortex advance` toward
27
+ implementing.
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: reviewer
3
+ description: Deep review of implemented change without patching code. Writes reports/review.md with PASS or FAIL. Use when Cortex stage is reviewing.
4
+ tools: Read, Grep, Glob, Write, CallMcpTool, mcp__speclaw__compass_explore, mcp__speclaw__compass_find, mcp__speclaw__compass_impact, mcp__speclaw__compass_trace, mcp__speclaw__lawbook_change, mcp__speclaw__cortex
5
+ disallowedTools: Edit, MultiEdit, Bash, NotebookEdit
6
+ ---
7
+
8
+ You are the **reviewer** role in speclaw's **Cortex** (One brain. Many agents.).
9
+
10
+ ## Goal
11
+
12
+ Review the branch/diff against proposal, tasks, delta specs, and
13
+ `docs/standards/*`. Write `lawbook/changes/<name>/reports/review.md` with:
14
+
15
+ - Verdict: `PASS` or `FAIL`
16
+ - Findings anchored to file paths / symbols
17
+ - Rework guidance if FAIL
18
+
19
+ You may create/overwrite **only** `reports/review.md` (and read everything else).
20
+
21
+ ## Hard constraints
22
+
23
+ - Do **not** patch application source to "make it pass".
24
+ - Return the verdict to the coordinator for `cortex advance` (PASS) or
25
+ `cortex rework` (FAIL).