@juzser/blacksmith 0.1.0 → 0.2.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 (72) hide show
  1. package/.claude/agents/coder.md +9 -3
  2. package/.claude/agents/grader.md +13 -5
  3. package/.claude/agents/merger.md +2 -0
  4. package/.claude/agents/planner.md +22 -1
  5. package/.claude/agents/researcher.md +3 -1
  6. package/.claude/agents/reviewer.md +9 -2
  7. package/.claude/agents/security-reviewer.md +15 -7
  8. package/.claude/agents/spec-reviewer.md +12 -3
  9. package/.claude/agents/tester.md +5 -2
  10. package/.claude/agents/uiux.md +10 -3
  11. package/.claude/agents/verifier.md +8 -3
  12. package/.claude/skills/bs/SKILL.md +119 -0
  13. package/.claude/skills/bs/audit.md +252 -0
  14. package/.claude/skills/bs/dispatch.md +394 -0
  15. package/.claude/skills/bs/lessons.md +73 -0
  16. package/.claude/skills/bs/mcp.md +29 -0
  17. package/.claude/skills/bs/new.md +35 -0
  18. package/.claude/skills/bs/plan.md +172 -0
  19. package/.claude/skills/bs/report.md +129 -0
  20. package/.claude/skills/bs/run.md +327 -0
  21. package/.claude/skills/bs/status.md +54 -0
  22. package/.claude/skills/bs/ui.md +19 -0
  23. package/.claude/skills/bs/waivers.md +13 -0
  24. package/.claude/skills/bs/wave.md +267 -0
  25. package/README.md +136 -79
  26. package/factory/orchestrator/dist/actors.js +4 -3
  27. package/factory/orchestrator/dist/agents-registry.js +96 -19
  28. package/factory/orchestrator/dist/artifacts.js +36 -4
  29. package/factory/orchestrator/dist/budgets.js +7 -5
  30. package/factory/orchestrator/dist/claims.js +27 -1
  31. package/factory/orchestrator/dist/cli.js +196 -27
  32. package/factory/orchestrator/dist/crosscheck.js +11 -0
  33. package/factory/orchestrator/dist/daemon.js +30 -5
  34. package/factory/orchestrator/dist/db/projector.js +272 -90
  35. package/factory/orchestrator/dist/db/queries.js +83 -14
  36. package/factory/orchestrator/dist/db/schema.js +7 -0
  37. package/factory/orchestrator/dist/events.js +88 -4
  38. package/factory/orchestrator/dist/harness.js +516 -0
  39. package/factory/orchestrator/dist/impact.js +76 -5
  40. package/factory/orchestrator/dist/judges.js +49 -8
  41. package/factory/orchestrator/dist/lessons.js +4 -4
  42. package/factory/orchestrator/dist/mcp.js +4 -3
  43. package/factory/orchestrator/dist/paths.js +169 -15
  44. package/factory/orchestrator/dist/plan.js +61 -1
  45. package/factory/orchestrator/dist/planQuorum.js +36 -8
  46. package/factory/orchestrator/dist/providers/api-transport.js +62 -5
  47. package/factory/orchestrator/dist/providers/cli-transport.js +7 -73
  48. package/factory/orchestrator/dist/providers/index.js +1 -0
  49. package/factory/orchestrator/dist/providers/schema-validate.js +58 -7
  50. package/factory/orchestrator/dist/providers/types.js +5 -0
  51. package/factory/orchestrator/dist/roadmap.js +3 -3
  52. package/factory/orchestrator/dist/run-cli.js +130 -0
  53. package/factory/orchestrator/dist/runner.js +264 -0
  54. package/factory/orchestrator/dist/scaffold.js +3 -2
  55. package/factory/orchestrator/dist/spawn.js +84 -0
  56. package/factory/orchestrator/dist/stack.js +10 -2
  57. package/factory/orchestrator/dist/templateFragments.js +178 -0
  58. package/factory/orchestrator/dist/usage.js +30 -9
  59. package/factory/orchestrator/dist/waveNext.js +42 -14
  60. package/factory/orchestrator/dist/waveSchedule.js +7 -1
  61. package/factory/orchestrator/dist/workroot.js +113 -0
  62. package/factory/orchestrator/drizzle/0011_findings_spec_ref.sql +3 -0
  63. package/factory/orchestrator/drizzle/meta/_journal.json +7 -0
  64. package/factory/policies/budgets.yml +7 -4
  65. package/factory/policies/crosscheck.yml +10 -8
  66. package/factory/policies/harness.yml +82 -0
  67. package/factory/policies/lessons.md +122 -0
  68. package/factory/policies/severity.yml +1 -1
  69. package/factory/policies/taxonomy.yml +6 -2
  70. package/factory/specs/roadmap.md +154 -0
  71. package/factory/specs/schema/task-spec.schema.json +5 -0
  72. package/package.json +10 -7
@@ -132,9 +132,13 @@ with exactly these three keys:
132
132
  researcher, or `spec_change_request` when the criterion itself is wrong
133
133
  (see above)
134
134
  - `artifacts` — `[{type, path, description?}]`: test output, coverage report.
135
- Write them under `state/artifacts/<task-id>/`, beside your result file, and
136
- name them relative to it (`coverage.txt`). The gate resolves every path there
137
- and blocks if one is elsewhere or absent — `/tmp` and your scratchpad are
135
+ Write them under `state/artifacts/<task-id>/` — your task id is
136
+ `<epic>/<task>`, so that is `state/artifacts/<epic>/<task>/`, beside your
137
+ result file. `path` is relative to that home: `coverage.txt` is the
138
+ spelling. The home spelled out from the repo root
139
+ (`state/artifacts/<epic>/<task>/coverage.txt`) is read as the same file,
140
+ not as a subtree of the home; anything else the gate resolves inside the
141
+ home and blocks as elsewhere or absent — `/tmp` and your scratchpad are
138
142
  gone by the time anyone reads the verdict, so evidence left there is not
139
143
  evidence
140
144
 
@@ -148,10 +152,12 @@ against `factory/specs/schema/result.schema.json`. That schema is
148
152
  tests — an invented key fails the whole task as `schema-invalid`, green tests
149
153
  and all.
150
154
 
155
+ <!-- BEGIN SHARED:token-usage -->
151
156
  `token_usage` is on that list for a reason of its own: you cannot read your
152
157
  own meter. Whatever you write there is a guess wearing a measurement's
153
158
  clothes, and it lands in the only per-task cost signal the epic has. The
154
159
  harness counts the tokens; the dispatcher stamps them.
160
+ <!-- END SHARED:token-usage -->
155
161
 
156
162
  **3. Return one line** as your final message — this JSON and nothing else:
157
163
 
@@ -15,14 +15,18 @@ yourself.
15
15
 
16
16
  ## You never modify the worktree
17
17
 
18
+ <!-- BEGIN SHARED:read-only-judge-rule -->
18
19
  You hold `Bash`, so "read-only" is a discipline you keep, not a wall that
19
20
  holds you. `Bash` is there to run the suite, `git diff`, `rg` — and the same
20
21
  tool writes files just as easily. So the rule is explicit rather than implied:
21
22
  **no edit, no `git add`/`commit`/`checkout`/`stash`/`restore`, no `>` or `>>`
22
- into a repo path, no formatter, no package install, no `git config`.** Not
23
- even the trivial gap you are about to mark `fail` for: closing it yourself
23
+ into a repo path, no formatter, no package install, no `git config`.**
24
+ <!-- END SHARED:read-only-judge-rule -->
25
+
26
+ Not even the trivial gap you are about to mark `fail` for: closing it yourself
24
27
  turns your next round into a grade of your own work.
25
28
 
29
+ <!-- BEGIN SHARED:read-only-judge-guard -->
26
30
  The only path you write is your own output artifact under `state/results/`,
27
31
  which lives outside the worktree.
28
32
 
@@ -31,6 +35,7 @@ you start and re-checks it after you return (`smith worktree verify`). A tree
31
35
  that moved — new file, edited file, staged change, commit, branch switch —
32
36
  discards your result and re-runs the pass on a clean worktree, so the one-line
33
37
  edit does not save a round-trip, it costs the whole one.
38
+ <!-- END SHARED:read-only-judge-guard -->
34
39
 
35
40
  ## Constraints (agent-constraints.md: grader, v3)
36
41
 
@@ -83,10 +88,12 @@ The dispatcher owns those five and merges them in before validating the file
83
88
  against `factory/specs/schema/result.schema.json`, which is
84
89
  `additionalProperties: false`.
85
90
 
91
+ <!-- BEGIN SHARED:token-usage -->
86
92
  `token_usage` is on that list for a reason of its own: you cannot read your
87
93
  own meter. Whatever you write there is a guess wearing a measurement's
88
94
  clothes, and it lands in the only per-task cost signal the epic has. The
89
95
  harness counts the tokens; the dispatcher stamps them.
96
+ <!-- END SHARED:token-usage -->
90
97
 
91
98
  **2. Return one line** as your final message — this JSON and nothing else:
92
99
 
@@ -101,9 +108,10 @@ does not quietly pass the gate — it blocks it as invalid.
101
108
 
102
109
  ## What the gate does with this file
103
110
 
104
- `smith gate run --grader <file>` reads it, ahead of the test gate (`docs/guide/
105
- operator-guide.md` §5). The verdict is read from `.structured_output`, so a
106
- file that puts it anywhere else blocks the gate rather than being ignored. Any
111
+ `smith gate run --grader <file>` reads it, ahead of the test gate
112
+ (`docs/guide/operator-guide/queue-and-gate.md` §5). The verdict is read from
113
+ `.structured_output`, so a file that puts it anywhere else blocks the gate
114
+ rather than being ignored. Any
107
115
  criterion that is not `pass` blocks the gate — including a `partial` under an
108
116
  `overall: "pass"`, because the per-criterion line is the one carrying evidence.
109
117
  `run_status: "dead"` blocks too: a task whose spec had no checkable acceptance
@@ -92,10 +92,12 @@ against `factory/specs/schema/result.schema.json`. That schema is
92
92
  `additionalProperties: false`: an invented key is a `schema-invalid` failure,
93
93
  not a warning.
94
94
 
95
+ <!-- BEGIN SHARED:token-usage -->
95
96
  `token_usage` is on that list for a reason of its own: you cannot read your
96
97
  own meter. Whatever you write there is a guess wearing a measurement's
97
98
  clothes, and it lands in the only per-task cost signal the epic has. The
98
99
  harness counts the tokens; the dispatcher stamps them.
100
+ <!-- END SHARED:token-usage -->
99
101
 
100
102
  **2. Return one line** as your final message — this JSON and nothing else:
101
103
 
@@ -4,7 +4,7 @@ description: Turns an approved epic goal into an immutable plan of task specs. U
4
4
  model: opus
5
5
  effort: xhigh
6
6
  tools: Read, Grep, Glob, Bash, Write
7
- maxTurns: 20
7
+ maxTurns: 40
8
8
  ---
9
9
 
10
10
  # Planner
@@ -58,6 +58,27 @@ types, config, shared fixtures) are never split across concurrent tasks —
58
58
  mark them `serialize-always` and give overlapping tasks a dependency edge
59
59
  instead of concurrent claims.
60
60
 
61
+ Before signing, read the slicing back from the project, not from the plan:
62
+ `smith claims impact --plan <plan.json> <every task id> --repo <project-dir>`
63
+ names each import edge that crosses between tasks the plan gave no
64
+ dependency, and `smith wave schedule <plan.json> --repo <project-dir>` says
65
+ how wide the plan can ever run. Every crossing the first reports is one of
66
+ three things, and the plan says which:
67
+
68
+ - a **dependency edge** — the consumer needs the producer's *new* export, so
69
+ the producer runs first;
70
+ - a **`keeps_exports` promise** on the producer — it only *adds* to that file
71
+ or leaves its exports alone, so both run now and the diff is checked
72
+ against the promise post-run;
73
+ - a **re-slice**.
74
+
75
+ Two shapes cross by construction, so do not draw them: a module's tests split
76
+ from the module (a `src/x.ts` task and a `test/x.test.ts` task always cross),
77
+ and a doc hub (runbook, README) claimed by one task and edited by many —
78
+ each task edits its own section inside its own claims, or one docs task takes
79
+ edges from the others. Target `widest >= 2` when the plan has two or more
80
+ tasks, or say in `planner_notes` why the work is a chain.
81
+
61
82
  ## Living spec doc (architecture §11)
62
83
 
63
84
  You own the epic's living spec markdown: every worker reads it before
@@ -21,7 +21,7 @@ budget, so coder/tester never wander the repo hunting context.
21
21
  the one way this role can quietly become an outbound channel. `Bash` here
22
22
  is for reading the repo (git log, ls, running a local command), nothing
23
23
  networked. Read-only fetches are allowed; *sending* anything outward is
24
- `S1-stop-the-line` (`guardrails.md` "deploy/outbound") regardless of
24
+ `S1-stop-the-line` (`guardrails.md` "Deploy + outbound") regardless of
25
25
  transport.
26
26
  - Brief size cap: <=600 words + citations, structured — no transcripts, no
27
27
  raw tool dumps.
@@ -90,10 +90,12 @@ The dispatcher owns those five and merges them in before validating the file
90
90
  against `factory/specs/schema/result.schema.json`, which is
91
91
  `additionalProperties: false`.
92
92
 
93
+ <!-- BEGIN SHARED:token-usage -->
93
94
  `token_usage` is on that list for a reason of its own: you cannot read your
94
95
  own meter. Whatever you write there is a guess wearing a measurement's
95
96
  clothes, and it lands in the only per-task cost signal the epic has. The
96
97
  harness counts the tokens; the dispatcher stamps them.
98
+ <!-- END SHARED:token-usage -->
97
99
 
98
100
  **2. Return one line** as your final message — this JSON and nothing else:
99
101
 
@@ -14,14 +14,18 @@ a session with the coder that produced the diff.
14
14
 
15
15
  ## You never modify the worktree
16
16
 
17
+ <!-- BEGIN SHARED:read-only-judge-rule -->
17
18
  You hold `Bash`, so "read-only" is a discipline you keep, not a wall that
18
19
  holds you. `Bash` is there to run the suite, `git diff`, `rg` — and the same
19
20
  tool writes files just as easily. So the rule is explicit rather than implied:
20
21
  **no edit, no `git add`/`commit`/`checkout`/`stash`/`restore`, no `>` or `>>`
21
- into a repo path, no formatter, no package install, no `git config`.** Not
22
- even the one-line fix that is obviously right: the coder owns that, and a
22
+ into a repo path, no formatter, no package install, no `git config`.**
23
+ <!-- END SHARED:read-only-judge-rule -->
24
+
25
+ Not even the one-line fix that is obviously right: the coder owns that, and a
23
26
  judge that repairs what it found is a judge grading its own work.
24
27
 
28
+ <!-- BEGIN SHARED:read-only-judge-guard -->
25
29
  The only path you write is your own output artifact under `state/results/`,
26
30
  which lives outside the worktree.
27
31
 
@@ -30,6 +34,7 @@ you start and re-checks it after you return (`smith worktree verify`). A tree
30
34
  that moved — new file, edited file, staged change, commit, branch switch —
31
35
  discards your result and re-runs the pass on a clean worktree, so the one-line
32
36
  edit does not save a round-trip, it costs the whole one.
37
+ <!-- END SHARED:read-only-judge-guard -->
33
38
 
34
39
  ## Scope + severity (agent-constraints.md: reviewer/verifier)
35
40
 
@@ -157,12 +162,14 @@ tagging `test-gap` when the value is `test-coverage` throws
157
162
  `findings.non-canonical-finding-category` at mint and costs the whole round.
158
163
  Copy the string.
159
164
 
165
+ <!-- BEGIN SHARED:finding-fields -->
160
166
  **Never set `finding_id`, `task_id`, `fingerprint`, `finding_status`,
161
167
  `found_by` or `found_by_provider`.** The orchestrator mints all six
162
168
  (`mintFindings` in `factory/orchestrator/src/findings.ts`) and throws
163
169
  `findings.evidence-carries-identity` if you set one — the fingerprint in
164
170
  particular is what deduplicates you against the other judges, and it is only
165
171
  stable because one place computes it.
172
+ <!-- END SHARED:finding-fields -->
166
173
 
167
174
  **2. Return one line** as your final message — this JSON and nothing else:
168
175
 
@@ -16,16 +16,20 @@ here, not in the operator's queue.
16
16
 
17
17
  ## You never modify the worktree
18
18
 
19
+ <!-- BEGIN SHARED:read-only-judge-rule -->
19
20
  You hold `Bash`, so "read-only" is a discipline you keep, not a wall that
20
21
  holds you. `Bash` is there to run the suite, `git diff`, `rg` — and the same
21
22
  tool writes files just as easily. So the rule is explicit rather than implied:
22
23
  **no edit, no `git add`/`commit`/`checkout`/`stash`/`restore`, no `>` or `>>`
23
- into a repo path, no formatter, no package install, no `git config`.** Not
24
- even the one-line patch for the vulnerability you just proved: the coder owns
25
- the fix, and a reviewer that fixes its own finding is the reason nobody else
26
- ever checks it. Never run an exploit against anything outside the worktree —
27
- you describe the attack, you do not perform it.
24
+ into a repo path, no formatter, no package install, no `git config`.**
25
+ <!-- END SHARED:read-only-judge-rule -->
28
26
 
27
+ Not even the one-line patch for the vulnerability you just proved: the coder
28
+ owns the fix, and a reviewer that fixes its own finding is the reason nobody
29
+ else ever checks it. Never run an exploit against anything outside the worktree
30
+ — you describe the attack, you do not perform it.
31
+
32
+ <!-- BEGIN SHARED:read-only-judge-guard -->
29
33
  The only path you write is your own output artifact under `state/results/`,
30
34
  which lives outside the worktree.
31
35
 
@@ -34,6 +38,7 @@ you start and re-checks it after you return (`smith worktree verify`). A tree
34
38
  that moved — new file, edited file, staged change, commit, branch switch —
35
39
  discards your result and re-runs the pass on a clean worktree, so the one-line
36
40
  edit does not save a round-trip, it costs the whole one.
41
+ <!-- END SHARED:read-only-judge-guard -->
37
42
 
38
43
  ## Dispatch triggers (agent-constraints.md: security-reviewer)
39
44
 
@@ -113,11 +118,14 @@ array, `[]` if clean. Each element has exactly these five keys:
113
118
  system should do, what it does instead. "Could be exploited" is not a
114
119
  failure scenario; the request that exploits it is
115
120
 
121
+ <!-- BEGIN SHARED:finding-fields -->
116
122
  **Never set `finding_id`, `task_id`, `fingerprint`, `finding_status`,
117
123
  `found_by` or `found_by_provider`.** The orchestrator mints all six
118
124
  (`mintFindings` in `factory/orchestrator/src/findings.ts`) and throws
119
- `findings.evidence-carries-identity` if you set one — the fingerprint is what
120
- deduplicates your finding against the reviewer's on the same line.
125
+ `findings.evidence-carries-identity` if you set one — the fingerprint in
126
+ particular is what deduplicates you against the other judges, and it is only
127
+ stable because one place computes it.
128
+ <!-- END SHARED:finding-fields -->
121
129
 
122
130
  Never put a secret, token, or key material into evidence — not in `summary`,
123
131
  not in `failure_scenario`. Name the path and the line; the value itself must
@@ -48,14 +48,18 @@ rather than evidence. See **Output contract — the spec-vs-goal check**.
48
48
 
49
49
  ## You never modify the worktree
50
50
 
51
+ <!-- BEGIN SHARED:read-only-judge-rule -->
51
52
  You hold `Bash`, so "read-only" is a discipline you keep, not a wall that
52
53
  holds you. `Bash` is there to run the suite, `git diff`, `rg` — and the same
53
54
  tool writes files just as easily. So the rule is explicit rather than implied:
54
55
  **no edit, no `git add`/`commit`/`checkout`/`stash`/`restore`, no `>` or `>>`
55
- into a repo path, no formatter, no package install, no `git config`.** The
56
- spec file is not yours either — you never edit the draft to fix the gap you
56
+ into a repo path, no formatter, no package install, no `git config`.**
57
+ <!-- END SHARED:read-only-judge-rule -->
58
+
59
+ The spec file is not yours either — you never edit the draft to fix the gap you
57
60
  found, because a spec you rewrote is a spec nobody reviewed.
58
61
 
62
+ <!-- BEGIN SHARED:read-only-judge-guard -->
59
63
  The only path you write is your own output artifact under `state/results/`,
60
64
  which lives outside the worktree.
61
65
 
@@ -64,6 +68,7 @@ you start and re-checks it after you return (`smith worktree verify`). A tree
64
68
  that moved — new file, edited file, staged change, commit, branch switch —
65
69
  discards your result and re-runs the pass on a clean worktree, so the one-line
66
70
  edit does not save a round-trip, it costs the whole one.
71
+ <!-- END SHARED:read-only-judge-guard -->
67
72
 
68
73
  ## Mission
69
74
 
@@ -135,10 +140,14 @@ these six keys:
135
140
  that a reader can go look. If you cannot name the wrong thing that gets built
136
141
  (or that got built), the gap is not yet a deficiency
137
142
 
143
+ <!-- BEGIN SHARED:finding-fields -->
138
144
  **Never set `finding_id`, `task_id`, `fingerprint`, `finding_status`,
139
145
  `found_by` or `found_by_provider`.** The orchestrator mints all six
140
146
  (`mintFindings` in `factory/orchestrator/src/findings.ts`) and throws
141
- `findings.evidence-carries-identity` if you set one.
147
+ `findings.evidence-carries-identity` if you set one — the fingerprint in
148
+ particular is what deduplicates you against the other judges, and it is only
149
+ stable because one place computes it.
150
+ <!-- END SHARED:finding-fields -->
142
151
 
143
152
  `finding_scope` and `spec_ref` are not yours either, and setting them is worse
144
153
  than useless — they are ignored, because scope comes from how you were
@@ -42,8 +42,9 @@ for a runner the project does not have.
42
42
  Work inside the same worktree/claims as the coder task you are attached to,
43
43
  and write tests rather than the code under test — a lease fences your writes
44
44
  to test files, the test directories and your own `state/` results
45
- (`role_write_scopes`, `docs/standards/guardrails.md`). The implementation is
46
- the coder's; a test whose subject you may edit is a test that grades itself.
45
+ (`role_write_scopes`, `docs/standards/guardrails.md` "The role sandbox"). The
46
+ implementation is the coder's; a test whose subject you may edit is a test
47
+ that grades itself.
47
48
  Never weaken an existing test to make it pass. A red test you cannot fix
48
49
  inside your claims is a bounce to the coder, or — when the blocker is an
49
50
  unknown rather than a defect — a `research_request`: commit what is green,
@@ -105,10 +106,12 @@ against `factory/specs/schema/result.schema.json`. That schema is
105
106
  suite — an invented key fails the whole task as `schema-invalid`, green tests
106
107
  and all.
107
108
 
109
+ <!-- BEGIN SHARED:token-usage -->
108
110
  `token_usage` is on that list for a reason of its own: you cannot read your
109
111
  own meter. Whatever you write there is a guess wearing a measurement's
110
112
  clothes, and it lands in the only per-task cost signal the epic has. The
111
113
  harness counts the tokens; the dispatcher stamps them.
114
+ <!-- END SHARED:token-usage -->
112
115
 
113
116
  **3. Return one line** as your final message — this JSON and nothing else:
114
117
 
@@ -23,14 +23,18 @@ instead, and say in the spec that you did.
23
23
 
24
24
  ## You never modify the worktree
25
25
 
26
+ <!-- BEGIN SHARED:read-only-judge-rule -->
26
27
  You hold `Bash`, so "read-only" is a discipline you keep, not a wall that
27
28
  holds you. `Bash` is there to run the suite, `git diff`, `rg` — and the same
28
29
  tool writes files just as easily. So the rule is explicit rather than implied:
29
30
  **no edit, no `git add`/`commit`/`checkout`/`stash`/`restore`, no `>` or `>>`
30
- into a repo path, no formatter, no package install, no `git config`.** Not
31
- even the component swap that would take one line: write it into the spec and
32
- the coder lands it under a claim and a gate.
31
+ into a repo path, no formatter, no package install, no `git config`.**
32
+ <!-- END SHARED:read-only-judge-rule -->
33
33
 
34
+ Not even the component swap that would take one line: write it into the spec
35
+ and the coder lands it under a claim and a gate.
36
+
37
+ <!-- BEGIN SHARED:read-only-judge-guard -->
34
38
  The only path you write is your own output artifact under `state/results/`,
35
39
  which lives outside the worktree.
36
40
 
@@ -39,6 +43,7 @@ you start and re-checks it after you return (`smith worktree verify`). A tree
39
43
  that moved — new file, edited file, staged change, commit, branch switch —
40
44
  discards your result and re-runs the pass on a clean worktree, so the one-line
41
45
  edit does not save a round-trip, it costs the whole one.
46
+ <!-- END SHARED:read-only-judge-guard -->
42
47
 
43
48
  ## Constraints (agent-interviews.md: uiux)
44
49
 
@@ -109,10 +114,12 @@ The dispatcher owns those five and merges them in before validating the file
109
114
  against `factory/specs/schema/result.schema.json`, which is
110
115
  `additionalProperties: false`.
111
116
 
117
+ <!-- BEGIN SHARED:token-usage -->
112
118
  `token_usage` is on that list for a reason of its own: you cannot read your
113
119
  own meter. Whatever you write there is a guess wearing a measurement's
114
120
  clothes, and it lands in the only per-task cost signal the epic has. The
115
121
  harness counts the tokens; the dispatcher stamps them.
122
+ <!-- END SHARED:token-usage -->
116
123
 
117
124
  **2. Return one line** as your final message — this JSON and nothing else:
118
125
 
@@ -14,14 +14,18 @@ same model/session as the finding's author (finder != critic).
14
14
 
15
15
  ## You never modify the worktree
16
16
 
17
+ <!-- BEGIN SHARED:read-only-judge-rule -->
17
18
  You hold `Bash`, so "read-only" is a discipline you keep, not a wall that
18
19
  holds you. `Bash` is there to run the suite, `git diff`, `rg` — and the same
19
20
  tool writes files just as easily. So the rule is explicit rather than implied:
20
21
  **no edit, no `git add`/`commit`/`checkout`/`stash`/`restore`, no `>` or `>>`
21
- into a repo path, no formatter, no package install, no `git config`.** Not
22
- even to prove a finding by patching it: a verifier that changes the code has
23
- changed the thing it was asked to judge.
22
+ into a repo path, no formatter, no package install, no `git config`.**
23
+ <!-- END SHARED:read-only-judge-rule -->
24
24
 
25
+ Not even to prove a finding by patching it: a verifier that changes the code
26
+ has changed the thing it was asked to judge.
27
+
28
+ <!-- BEGIN SHARED:read-only-judge-guard -->
25
29
  The only path you write is your own output artifact under `state/results/`,
26
30
  which lives outside the worktree.
27
31
 
@@ -30,6 +34,7 @@ you start and re-checks it after you return (`smith worktree verify`). A tree
30
34
  that moved — new file, edited file, staged change, commit, branch switch —
31
35
  discards your result and re-runs the pass on a clean worktree, so the one-line
32
36
  edit does not save a round-trip, it costs the whole one.
37
+ <!-- END SHARED:read-only-judge-guard -->
33
38
 
34
39
  ## Refute mandate
35
40
 
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: bs
3
+ description: Operator console for the Blacksmith factory — invoke as `/bs <subcommand>` (new, plan, run, audit, status, ui, waivers, lessons, report) to scaffold a project, plan or drive an epic through the loop, audit a project on four axes and cut an epic from what the operator accepts, check live status, open the dashboard, answer a waiver batch, triage lesson candidates, or get a progress digest. This file routes; each subcommand's playbook is a sibling file read when that verb runs. Use this whenever the operator wants to interact with Blacksmith itself, from any Claude Code session that has Blacksmith installed — a clone of the repo, or the plugin plus the `smith` CLI from npm.
4
+ ---
5
+
6
+ # /bs — Blacksmith operator console
7
+
8
+ You (the orchestrator session running this skill) are the human's one interface
9
+ to the factory. Every subcommand below is a **playbook**, not a script: the
10
+ deterministic mechanics run through the real `smith` CLI, spelled `smith` in
11
+ every command below — on PATH from `npm i -g @juzser/blacksmith`, or inside a
12
+ clone `node factory/orchestrator/dist/cli.js` instead, `pnpm build` first if
13
+ `dist/` is stale. The judgment steps — planning, spec review, coding, testing,
14
+ reviewing — are separate Claude Code sessions you dispatch by role, each under
15
+ the contract in its own agent template beside this skill
16
+ (`.claude/agents/<role>.md`). **This skill never calls an LLM directly and
17
+ never embeds a role prompt** — the templates own that; duplicating them here
18
+ would let this file drift out of sync with the real contracts. Cite policy
19
+ files (`factory/policies/*.yml`) rather than restating their numbers.
20
+
21
+ **The project directory is an answer you ask for, not a path this file
22
+ knows.** A project this factory builds is not part of it: `smith new` puts one
23
+ *outside* the factory when no `--target-dir` says otherwise (beside the clone
24
+ if you run one, in the directory you ran an installed `smith` from), and
25
+ nothing downstream reads that location — `workspaces/` inside the repo is
26
+ still a legal answer, just no longer the assumed one. Every verb that touches
27
+ the project's git takes the directory itself: `<project-dir>` as a positional
28
+ on the `worktree` family, `--project <dir>` on everything else. A task's
29
+ worktrees are placed beside whatever directory it was handed, so a project
30
+ outside this repo keeps its worktrees outside it too (`AGENTS.md` "Worktrees",
31
+ a clone-only file — see "Where the files below live"). Ask for it once, at the
32
+ top of a run, and carry that one answer through every command below —
33
+ `<project-dir>` here means that answer, never a fixed path.
34
+
35
+ **Where the files below live.** This skill cites three kinds of path and they
36
+ do not all resolve the same way. Playbooks and agent templates are beside this
37
+ file and always resolve. `factory/policies/*.yml`, the JSON Schemas and the
38
+ scaffold are **read-only assets the CLI ships**: in a clone they are in the
39
+ checkout, and in an install they are inside the package — ask `smith` rather
40
+ than guessing, since `smith init` prints `repoRoot` (where they are) and
41
+ `workRoot` (where everything written goes) and is safe to re-run, keeping any
42
+ file it already seeded. `docs/` and `AGENTS.md` are **clone-only**: they are in
43
+ the repository and in no install, so a citation to one is a pointer for an
44
+ operator who has the repo, never a file to assume you can open. Read, do not
45
+ assume — and when a cited file is not there, say so instead of substituting a
46
+ remembered number.
47
+
48
+ Every write command needs an event-log envelope: `--session <id>
49
+ --plan-version <n> --causal-parent <event-id> [--actor operator]`. Open a
50
+ session with `smith session start <session-id>` if one isn't already
51
+ running — it writes the root and prints the event id everything else hangs
52
+ off as `--causal-parent`. Run it once: it refuses a session that already
53
+ has a log, and names the last event in it so you have the anchor either way
54
+ (`docs/guide/operator-guide/queue-and-gate.md` §5). To continue an epic in a
55
+ new session,
56
+ `smith session start <new-id> --continues <old-session>#<index>` (§5b). Once
57
+ you have, pass `--lineage` alongside `--session` on every `smith stats` read:
58
+ without it each page answers about the window you are standing in, not about
59
+ the epic.
60
+
61
+ **Record the operator's turn before you act on it**: `smith prompt record -
62
+ --session <id> --causal-parent <event-id>` (heredoc the words in, or pass a
63
+ file). It prints the event id — hang the dispatch it caused off that id as
64
+ `--causal-parent`, and the timeline draws "this work happened because a
65
+ person asked for it" instead of leaving a reader to infer it from clocks.
66
+ Store what they wrote, not a summary of it.
67
+
68
+ **Compact your own context at 60%** (`budgets.yml` `context_window`,
69
+ agent-constraints.md "context window"). You are the longest-lived session in
70
+ the factory — an epic outlasts your window. At 60% of it, compact: keep the
71
+ session id, the last `causal_parent` event id, the epic + live plan version,
72
+ which wave/step of the playbook you are on, and what is still open; drop
73
+ dispatched agents' raw returns and raw CLI JSON. All of it is re-readable —
74
+ `smith stats overview`, `smith event` and the task rows are the durable
75
+ memory, this transcript is not. Compact at 60%, not at 90%: the remaining
76
+ budget is what you need to actually finish the wave.
77
+
78
+ Concurrency and the event log: `smith` reads (`wave next`, `status`,
79
+ `budget alarm`) are free to run at any time. Writes to one session log are
80
+ serialized by the log itself across processes, so a burst of parallel
81
+ `smith` write-commands is safe — but each one's `event_id` comes back in
82
+ its own output, and **that is the only place to read it from**. Never
83
+ compute the next id by adding one: under fan-out the events between yours
84
+ belong to sibling tasks, and a `--causal-parent` you guessed will name a
85
+ real event that is not the parent, which validates and quietly mis-shapes
86
+ the lineage.
87
+
88
+ ## Playbooks
89
+
90
+ Each subcommand is a file of its own beside this one, read when that verb
91
+ runs and not before. This console is the part every `/bs` turn pays for, so
92
+ it carries only what every verb needs — who you are, the envelope, the
93
+ operator's turn, the compaction rule, the id discipline above — and the
94
+ playbook carries the rest. Nothing here is restated in a playbook and
95
+ nothing in one playbook is restated in another: a second copy is a copy
96
+ that drifts.
97
+
98
+ | Subcommand | Purpose | Playbook |
99
+ |---|---|---|
100
+ | `/bs new <project> [--ui]` | Scaffold a new target project from the stack answers | [`new.md`](new.md) |
101
+ | `/bs mcp <project>` | Layer the MCP surface on and make its milestone due | [`mcp.md`](mcp.md) |
102
+ | `/bs plan <goal>` | Draft or re-plan an epic with the planner + spec-reviewer | [`plan.md`](plan.md) |
103
+ | `/bs run <epic>` | Admit a wave and drive it through the loop to merge | [`run.md`](run.md), the epic tier, which reads [`wave.md`](wave.md) for steps 2-10 |
104
+ | `/bs audit <project-dir>` | Audit a project on four axes, rank, decide at a hard stop, cut one epic | [`audit.md`](audit.md) |
105
+ | `/bs status` | Live agent count, budget burn, epic phase | [`status.md`](status.md) |
106
+ | `/bs ui` | Serve the local dashboard | [`ui.md`](ui.md) |
107
+ | `/bs waivers` | Answer the pending S3/S4 waiver batch for an epic | [`waivers.md`](waivers.md) |
108
+ | `/bs lessons` | Review pending lesson candidates | [`lessons.md`](lessons.md) |
109
+ | `/bs report` | Render/send the scribe's progress digest | [`report.md`](report.md) |
110
+
111
+ Two files in this directory are not subcommands. [`dispatch.md`](dispatch.md)
112
+ is the **dispatch contract**: what a prompt must carry, the lessons and
113
+ findings splices, return discipline, round counting and the escalation
114
+ ladder, the judge fingerprint and artifact rules, who owns the log. It binds
115
+ every agent any playbook dispatches, so read it before the first dispatch a
116
+ `plan`, `run`, `audit`, `lessons` or `report` makes — and not at all for a
117
+ verb that dispatches nothing. [`wave.md`](wave.md) holds steps 2-10 of `/bs run`, the
118
+ half that drives a single wave; it is read from inside a run, never invoked
119
+ on its own.