@juzser/blacksmith 0.1.0 → 0.1.1

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 (61) 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 +1 -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 +103 -0
  13. package/.claude/skills/bs/audit.md +250 -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 +33 -0
  18. package/.claude/skills/bs/plan.md +155 -0
  19. package/.claude/skills/bs/report.md +129 -0
  20. package/.claude/skills/bs/run.md +325 -0
  21. package/.claude/skills/bs/status.md +54 -0
  22. package/.claude/skills/bs/ui.md +12 -0
  23. package/.claude/skills/bs/waivers.md +13 -0
  24. package/.claude/skills/bs/wave.md +261 -0
  25. package/README.md +119 -65
  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/cli.js +107 -7
  31. package/factory/orchestrator/dist/crosscheck.js +11 -0
  32. package/factory/orchestrator/dist/daemon.js +14 -0
  33. package/factory/orchestrator/dist/db/projector.js +272 -90
  34. package/factory/orchestrator/dist/db/queries.js +83 -14
  35. package/factory/orchestrator/dist/db/schema.js +7 -0
  36. package/factory/orchestrator/dist/events.js +38 -4
  37. package/factory/orchestrator/dist/harness.js +367 -0
  38. package/factory/orchestrator/dist/judges.js +49 -8
  39. package/factory/orchestrator/dist/lessons.js +4 -4
  40. package/factory/orchestrator/dist/mcp.js +4 -3
  41. package/factory/orchestrator/dist/paths.js +167 -15
  42. package/factory/orchestrator/dist/plan.js +1 -1
  43. package/factory/orchestrator/dist/planQuorum.js +36 -8
  44. package/factory/orchestrator/dist/providers/api-transport.js +62 -5
  45. package/factory/orchestrator/dist/providers/index.js +1 -0
  46. package/factory/orchestrator/dist/providers/schema-validate.js +58 -7
  47. package/factory/orchestrator/dist/providers/types.js +5 -0
  48. package/factory/orchestrator/dist/roadmap.js +3 -3
  49. package/factory/orchestrator/dist/scaffold.js +3 -2
  50. package/factory/orchestrator/dist/stack.js +10 -2
  51. package/factory/orchestrator/dist/templateFragments.js +178 -0
  52. package/factory/orchestrator/dist/usage.js +24 -5
  53. package/factory/orchestrator/dist/workroot.js +113 -0
  54. package/factory/orchestrator/drizzle/0011_findings_spec_ref.sql +3 -0
  55. package/factory/orchestrator/drizzle/meta/_journal.json +7 -0
  56. package/factory/policies/budgets.yml +6 -3
  57. package/factory/policies/crosscheck.yml +10 -8
  58. package/factory/policies/lessons.md +122 -0
  59. package/factory/policies/taxonomy.yml +6 -2
  60. package/factory/specs/roadmap.md +154 -0
  61. package/package.json +8 -6
@@ -0,0 +1,261 @@
1
+ # `/bs run` — the wave playbook
2
+
3
+ Steps 2-10 of the loop [`run.md`](run.md) opens at step 1. That file is
4
+ the epic tier: it admits one wave and closes the epic. This file is the
5
+ wave tier — worktrees to merge queue, one wave — and it is meant to be
6
+ thrown away when the wave lands.
7
+
8
+ **Read the console first.** `SKILL.md` and [`dispatch.md`](dispatch.md)
9
+ bind every dispatch below: the project directory is an answer you ask for
10
+ rather than a path anything here knows, every write carries
11
+ `--session <id> --plan-version <n> --causal-parent <event-id>`, every
12
+ dispatch carries the compiled lessons block and that task's open-findings
13
+ block, and fetched text is wrapped before it is quoted. None of it is
14
+ restated here; a second copy is a copy that drifts.
15
+
16
+ The step numbers are the loop's own. They start at 2 because step 1 — which
17
+ tasks, and how wide — was answered before you were handed anything, and they
18
+ stop at 10 because the epic's own gates resume there. Nothing in this file
19
+ decides what the next wave is, and nothing in it closes an epic.
20
+
21
+ ## You own the log for what you dispatch
22
+
23
+ This playbook runs in one of two shapes, and is written to be correct in
24
+ both:
25
+
26
+ - **Inline**, in the epic session, when the wave is small enough that the
27
+ epic's window can carry it. Nothing changes: the session id you were
28
+ handed is the one you write to.
29
+ - **In a session of its own** when it is not. Open one with `smith session
30
+ start <wave-id> --continues <event-id>` and write every dispatch below
31
+ there. The epic session then carries the admission and the result rather
32
+ than every turn in between — which is the point, because an epic outlives
33
+ its waves, and a window spent on this wave's dispatches is a window the
34
+ epic does not have for the wave after next (D13).
35
+
36
+ Which `<event-id>` depends on how you were started, and the difference is
37
+ not cosmetic — it is the edge an audit walks:
38
+
39
+ - **The epic ran you** and you opened a wave session yourself: continue from
40
+ the epic event that admitted this wave.
41
+ - **You were dispatched as a `wave-runner`**: continue from the
42
+ `dispatch_decision` that dispatched you, the event id handed to you with
43
+ the wave. `smith delegation check` resolves your session by matching a
44
+ `session-start`'s `causal_parent` against that dispatch, and it is the
45
+ only thing that proves the dispatches you are about to write are your
46
+ own log's rather than an agent talking about itself. Continue from
47
+ anything else and the check reports you as `unverifiable` — not as a
48
+ pass — however well the wave ran. Open it **before** your first dispatch,
49
+ for the same reason: a grant is earned by owning the log first.
50
+
51
+ Either way, one rule holds: **the log you write is the log the epic reads**,
52
+ and `--continues` is the whole of what makes that true. Every deciding read
53
+ at the epic tier folds the lineage rather than one session — `wave audit`,
54
+ `budget alarm`, `tester check`, `judge outstanding`, `escalation check`,
55
+ `dispatch check`, `delegation check` — so a dispatch recorded in a wave
56
+ session is visible from the epic session that admitted it, and is *not*
57
+ visible from a sibling wave's. Open a wave session without `--continues` and
58
+ none of those verbs can see your work: they will not error, they will answer
59
+ about a wave that appears never to have run.
60
+
61
+ **What you are handed**, and carry through every command below: the project
62
+ directory, the epic id, the live plan path, the admitted task ids, the
63
+ effort `profile` the epic resolved once at the top of its run, the session
64
+ id you write to, and the event id to hang the first dispatch off as
65
+ `--causal-parent`.
66
+
67
+ **What you hand back** when the wave lands: each task's terminal state, the
68
+ merge-queue outcome, every finding raised with its severity, any escalation
69
+ that reached the operator, and — if you opened one — the wave session id and
70
+ its last event id, so the epic session goes on chaining from where you
71
+ stopped.
72
+
73
+ ## Run the whole wave at once
74
+
75
+ The wave is the unit of work, not the task. Three rules follow, and they are
76
+ the difference between a factory and a queue with extra steps:
77
+
78
+ - **One message, many dispatches.** When steps 3–7 reach a phase, issue
79
+ that phase for *every* task in the wave as parallel tool calls in a
80
+ single message. Five coders in one message is five agents working; five
81
+ messages of one coder is five agents waiting. The worktrees are
82
+ disjoint by construction — that is what step 1's `wave check` certified
83
+ before you were handed the wave — so there is nothing for them to
84
+ collide over.
85
+ - **No lockstep barrier.** Each task walks 3 → 7 at its own pace. Do not
86
+ hold a finished coder until its neighbours finish theirs; dispatch its
87
+ tester the moment it returns. Waiting for the slowest task at every
88
+ phase boundary costs the wave the difference between its longest task
89
+ and the sum of its phases, which is most of what parallelism buys.
90
+ - **A blocked task blocks itself.** Gate outcome `blocked` bounces to
91
+ *that* task's coder (step 9) while its neighbours carry on. One task
92
+ escalating to the operator does not stop the other four; report it and
93
+ keep the wave moving.
94
+
95
+ The single place the wave rejoins is step 10's merge queue, which is
96
+ serial on purpose — `smith queue run` rebases one task at a time onto
97
+ `smith/<epic>/integration` and runs the cumulative tests between. Merging
98
+ is the one thing that cannot be done in parallel, and it is already the
99
+ one thing this playbook never asks you to.
100
+
101
+ ## The steps
102
+
103
+ 2. Per admitted task, and for all of them together: `smith worktree create
104
+ <project-dir> <epic> <task-id>`.
105
+ 3. Pre-code, if the task needs it: dispatch `researcher` for an unknown, or
106
+ `uiux` (`.claude/agents/uiux.md`) for any UI-affecting acceptance
107
+ criterion — before the coder starts, not after.
108
+ - `profile.preCodeResearch` gates the researcher: `when-needed` is the
109
+ line above, `never` (`small`) means the coder reading the repo *is* the
110
+ brief. An epic that genuinely cannot start without a research brief is
111
+ not a `small` epic — raise the tier rather than dispatching anyway.
112
+ - `profile.preCodeUiux` gates the uiux spec, and is `when-ui-criterion` at
113
+ every tier: no tier ships a UI change without a spec to review it
114
+ against. It is listed as a knob so the answer is asked for rather than
115
+ assumed, not because a tier can turn it off.
116
+ - A returned brief goes through `smith research check --brief <path>`
117
+ before it is attached to a task spec ("Fetched and quoted text goes into
118
+ a prompt fenced" above). Exit 1 sends it back; on exit 0, carry
119
+ `recommendation.provenance` into the coder's prompt so the task knows
120
+ whether its research rests on this repo or on a fetched page. Any raw
121
+ fetched text you quote alongside it is wrapped with `smith prompt wrap`.
122
+ 4. Dispatch **`coder`** (`.claude/agents/coder.md`) in that worktree.
123
+ Token/diff caps (`budgets.yml`: 150k tokens, 400 diff lines) and YAGNI
124
+ are the coder's own constraints — don't restate them here, the template
125
+ does.
126
+ 5. Dispatch **`tester`** (`.claude/agents/tester.md`) for missing unit
127
+ coverage and epic-level e2e/screenshots.
128
+ - Then the **uiux visual pass**, but only when all three hold: the task
129
+ is UI-affecting, the tester actually returned screenshot artifacts, and
130
+ step 3 wrote a uiux spec for this task (agent-interviews.md N-6). Miss
131
+ any one and skip it — say so; a "visual pass" over screenshots that do
132
+ not exist is worse than no pass. Dispatch it with the spec path and the
133
+ image paths and **nothing else**: no diff, no components, no test code.
134
+ The pass is a judgment about the rendered screen, and a uiux session
135
+ that reads the diff ends up reviewing intent, which the reviewer
136
+ already covers.
137
+ 6. Dispatch **`grader`** (`.claude/agents/grader.md`) — bounded rubric
138
+ loop, `profile.graderRounds` rounds (2 at `huge`, 1 below; never more
139
+ than 2, agent-constraints.md "grader (v3)"), before any gate
140
+ runs; it never decides pass/fail itself. At one round the grader scores
141
+ once and a failed criterion is the coder's bounce, not a re-grade. Its result file is an **input to
142
+ step 7**, not a note to the operator: pass it as `--grader` or the rubric
143
+ gates nothing (D-34).
144
+ 7. Run the gate pipeline:
145
+ `smith gate run <task-id> --worktree <dir> --checks checks.json --result
146
+ result.json --grader state/results/<task-id>.grader-r<round>.json
147
+ --findings findings.json --session ... --plan-version N
148
+ --causal-parent ...` (schema check → grader verdict → tests → coverage
149
+ evidence → findings intake → severity decision,
150
+ `docs/guide/operator-guide/queue-and-gate.md` §5).
151
+ - `--grader` takes step 6's file, latest round. A criterion that came back
152
+ `fail` or `partial` blocks before any check command runs — the outcome is
153
+ `blocked` with `reason: "grader-fail"`, and the payload's
154
+ `failed_criteria` is what you hand back to the coder.
155
+ - Name a check `coverage` and the gate reads
156
+ `coverage/coverage-summary.json` instead of scraping the text table,
157
+ which hides every file at 100% — including the file the task exists to
158
+ add (D-40). `blocked` with `reason: "coverage-evidence"` means the run
159
+ produced no per-file number for a file this task's claims name; fix the
160
+ reporter or the include glob, not the code. Ask the same question
161
+ outside a gate run with `smith coverage check <worktree-dir> --plan
162
+ <plan.json> --task <task-id>` (§5c).
163
+ - Findings come from dispatching **`reviewer`**
164
+ (`.claude/agents/reviewer.md`, fresh context, read-only) then
165
+ **`verifier`** (`.claude/agents/verifier.md`, adversarial refute
166
+ mandate) — never skip the adversarial stage on an S1/S2 finding
167
+ (`crosscheck.yml` `asymmetric_roles`). Which findings that covers is
168
+ `profile.verifierSeverities`, plus a
169
+ `profile.verifierS3SpotCheckRatio` sample of S3-minor: `[S1, S2]` + 0.2
170
+ at `huge`, `[S1, S2]` + 0 at `medium`, `[S1]` + 0 at `small`. The S3
171
+ sample is a calibration measurement on the reviewer, so it is the first
172
+ thing a cheaper tier drops; `S1-stop-the-line` is in every tier's list
173
+ and no tier may remove it. A finding outside the tier's list still goes
174
+ to the coder — it is verified by the coder's fix, not waived.
175
+ - Dispatch **`security-reviewer`** only when its conditional triggers
176
+ fire — never per-task by default. Ask, do not recall:
177
+ `smith security triggers --task <spec.json>` and dispatch iff
178
+ `dispatchSecurityReviewer` is true ("Dispatching the security-reviewer"
179
+ above).
180
+ - Every judge dispatched in steps 5–7 — uiux visual pass, grader,
181
+ reviewer, verifier, security-reviewer — is bracketed by
182
+ `smith worktree fingerprint` / `smith worktree verify`
183
+ ("Fingerprint the worktree around every judge" above). Exit 1 discards
184
+ that judge's result; it does not become a finding against the coder.
185
+ - Each of those is also bracketed by `smith judge dispatch` /
186
+ `smith judge report` ("Declare each judge's artifact before you dispatch
187
+ it" above). `smith judge outstanding --task <task-id>` exits 1 while any
188
+ judge still owes its file — re-poke it and report before running the
189
+ gate, because the gate now refuses to score with a non-empty outstanding
190
+ set (`reason: judges-outstanding`) rather than reading a silent judge as
191
+ zero findings.
192
+ - The gate scores tests it did not write, so once it has run, make the log
193
+ say who did: `smith tester check <session-id> --task <task-id>`
194
+ (`crosscheck.yml` `role_isolation`, operator-guide/dispatch-audits.md §2d). Exit 1
195
+ means no `tester` dispatch precedes this task's `testgate-result`, the
196
+ coder and tester dispatches share one `agent_id`, or the answer is
197
+ unknowable. A
198
+ coder that writes and runs its own tests grades itself and every gate
199
+ downstream still goes green — step 5 is what prevents that, and this is
200
+ the log checking that step 5 happened.
201
+ 8. Every dispatch in steps 3–7 carries the compiled lessons block for that
202
+ role (`smith lessons for-dispatch <role> --plan … --task …`), every
203
+ worktree dispatch also carries the open-findings block for that task
204
+ (`smith findings for-dispatch --plan … --task …`) — both under "Dispatch
205
+ contract" above — and each is a `dispatch_decision` event with a `causal_parent`
206
+ chaining back to the prompt/decision that caused it (architecture §7) —
207
+ this is the timeline, not optional bookkeeping.
208
+ 9. Gate outcome `blocked` → bounce to the coder on the **same branch**.
209
+ After 2 failed rounds on the same task, escalate model tier
210
+ automatically (sonnet → opus, logged — `budgets.yml`
211
+ `escalation_ladder`); after 3, escalate to the operator. Never skip a
212
+ rung, never loop past one. Count the rounds from this task's
213
+ `dispatch_decision` events, not from the agent's own account of itself
214
+ — see "Round counting and escalation" above. Then have the log check
215
+ you: `smith escalation check <session-id> --task <task-id>`, which
216
+ exits 1 if the rung you just climbed is not evidenced.
217
+ 10. Gate outcome `pass`/`pass-with-waivers-pending` → before admitting,
218
+ ask what the diff did to everyone outside the claims:
219
+ `smith claims impact <worktree-dir> <spec.json>`. Exit 1 means a
220
+ `proven` break — this task removed an export a file outside its claims
221
+ still imports — and that is a bounce to the coder, not a merge. A
222
+ `possible` / `signature-changed` entry exits 0 and is a note: the
223
+ scanner reads text, not types (operator-guide/wave.md §2). Then admit
224
+ into the
225
+ merge queue: `smith queue run <epic> --project <project-dir>
226
+ --test-cmd "<cumulative test command>" --tasks tasks.json`. On a
227
+ `rebase-conflict` outcome, dispatch **`merger`**
228
+ (`.claude/agents/merger.md`) with both diffs + specs, and note three
229
+ things the queue's own behaviour forces (agent-interviews.md N-12):
230
+ - **Into the failing task's existing worktree** — a fresh one would not
231
+ reproduce the conflict. The result gives you only `taskId` and
232
+ `conflictingFiles`, so the path is the `worktreeDir` you wrote for
233
+ that task in `tasks.json`; carry it into the prompt yourself.
234
+ - **Claims = the queue's `conflictingFiles`**, verbatim. Anything else
235
+ the merger touches is a claim violation like any other.
236
+ - The queue already ran `git rebase --abort` (`queue.ts`), so the
237
+ merger arrives at a clean tree and **replays** the rebase rather than
238
+ resuming it — and it **never lands the merge**. When it returns
239
+ `resolution: "mechanical"`, re-run `smith queue run`; the queue stays
240
+ the single place a merge can happen.
241
+
242
+ `resolution: "escalated"` — low confidence, or both sides changed the
243
+ same logic — goes to the operator with the side-by-side. Never
244
+ auto-resolve a semantic conflict silently (`worktree.yml`
245
+ `conflict_resolution_ladder`).
246
+
247
+ Once the wave is merged, check the epic's spend — `smith budget alarm
248
+ <session-id> [--epic <epic>]`. Exit 1 means either the epic crossed
249
+ `alarm_ratio` (re-plan the remaining work to fit, or ask the operator —
250
+ extension is always an operator question) **or** the log is too holey to
251
+ rule a crossing out. Read the two numbers as what they are:
252
+ `measuredTokens` is a floor, never the bill (judges return findings, not
253
+ Results, so their tokens are in no event), and `projectedTokens` prices
254
+ every unmeasured dispatch at its `budgets.yml` cap. `unverifiable` with
255
+ `rolesWithoutCap` non-empty is a policy gap, not a spend problem: that
256
+ role has no cap to price it with. `unverifiable` with `tasksOverPrice`
257
+ non-empty means this epic has already been measured spending more on one
258
+ task than the projection charges an unmeasured dispatch, so its caps are
259
+ bounding nothing here (D-188) — the fix is to record the missing spend,
260
+ never to raise the cap until the number fits. Do not report an epic as
261
+ under budget on the strength of `measuredTokens` alone.
package/README.md CHANGED
@@ -15,12 +15,15 @@ and hands you exactly one pull request.
15
15
  ![TypeScript](https://img.shields.io/badge/TypeScript-1f1f1f)
16
16
 
17
17
  **[Features](#features) · [Install](#install) · [Using it](#using-it) ·
18
- [How it works](#how-it-works) · [Safety](#safety) · [Status](#status) ·
19
- [Docs](#docs)**
18
+ [How it works](#how-it-works) · [Safety](#safety) ·
19
+ [Dashboard](#the-dashboard) · [Status](#status) · [Docs](#docs)**
20
20
 
21
- <img src="ui/e2e/__screenshots__/phase-6b/overview-desktop-dark.png" width="900" alt="Blacksmith Overview page: a 'Needs you' banner reading '1 waiver pending, 1 task escalated', counters for active agents, budget used, epics in flight and alerts, and a 'Now running' list of two live sessions" />
21
+ <pre>
22
+ goal → contracts you sign → one worktree per contract, run in parallel
23
+ → schema · tests · reviewer · verifier → one pull request you merge
24
+ </pre>
22
25
 
23
- <sub>The one screen that asks something of you. The rest is the factory reporting in.</sub>
26
+ <sub>Two touchpoints. Everything between them runs unattended.</sub>
24
27
 
25
28
  </div>
26
29
 
@@ -55,12 +58,7 @@ the moment you sign it and versioned in the event log, so a worker cannot
55
58
  quietly reinterpret the job. No contract, no dispatch.
56
59
 
57
60
  </td>
58
- <td width="50%"><img src="ui/e2e/__screenshots__/phase-6b/task-detail-desktop-dark.png" width="100%" alt="Task detail page for epic-9/task-3 showing a Spec contract card with case, origin, epic, plan version and claims, and an Attempts list naming each agent, provider and outcome" /></td>
59
- </tr>
60
-
61
- <tr valign="top">
62
- <td><img src="ui/e2e/__screenshots__/phase-6b/flow-desktop-dark.png" width="100%" alt="Flow page: task cards arranged in three columns labelled Wave 0 (6 tasks), Wave 1 (2 tasks) and Wave 2 (1 task), joined by dashed dependency edges" /></td>
63
- <td>
61
+ <td width="50%">
64
62
 
65
63
  **Workers that cannot collide**
66
64
 
@@ -75,21 +73,6 @@ instead. An edit outside a claim fails the gate rather than reaching the queue.
75
73
  <tr valign="top">
76
74
  <td>
77
75
 
78
- **A frontier planner, cheap workers**
79
-
80
- Planning and judgment go to a frontier model; the bulk of the work goes to
81
- small, fast tiers, many at once. Every session and every live agent is visible
82
- with the tier that drew it, and analytics breaks cost down per task, per tier
83
- and per provider.
84
-
85
- </td>
86
- <td><img src="ui/e2e/__screenshots__/phase-6b/sessions-desktop-dark.png" width="100%" alt="Sessions page: two session cards, sess-fixture and sess-multiproject-fixture, joined by dashed edges to six live agent cards labelled coder - small, coder - mid and planner - frontier, each marked working" /></td>
87
- </tr>
88
-
89
- <tr valign="top">
90
- <td><img src="ui/e2e/__screenshots__/phase-6b/kanban-desktop-dark.png" width="100%" alt="Kanban board with Todo, In progress, Reviewing and Blocked columns; cards carry severity chips such as S2-major and agent chips such as coder - mid" /></td>
91
- <td>
92
-
93
76
  **Gates decide what merges, not confidence**
94
77
 
95
78
  Schema check → tests → coverage evidence → a fresh-context reviewer that never
@@ -98,41 +81,46 @@ the reviewer. S1 stops the line, S2 bounces back to the same branch, S3 batches
98
81
  into one waiver question per epic. Only S3 and S4 are ever waivable.
99
82
 
100
83
  </td>
101
- </tr>
102
-
103
- <tr valign="top">
104
84
  <td>
105
85
 
106
86
  **A second opinion from another vendor**
107
87
 
108
88
  The factory grades its own judgment calls against models from a different
109
89
  vendor — Codex over its CLI, DeepSeek over its API, beside the native Claude
110
- judge. They ship switched off — which of them a machine can actually
111
- call is a fact about that machine, not about this repo — and the one you
112
- switch on arrives in **shadow mode**: every verdict recorded, none of them
113
- gating anything, until you have read the numbers and promoted it
114
- deliberately.
90
+ judge. Both external judges ship `enabled: auto`: they join the quorum on a
91
+ machine that holds the credentials and are skipped on one that does not, so
92
+ which of them you get is a fact about your machine, not about this repo. A
93
+ judge earns its vote in **shadow mode** first — every verdict recorded, none
94
+ of them gating anything — and is promoted only once you have read the numbers.
115
95
 
116
96
  </td>
117
- <td><img src="ui/e2e/__screenshots__/phase-6b/analytics-desktop-dark.png" width="100%" alt="Analytics page with throughput, cost-per-task, same-mistake-rate and recheck-pass-rate cards, bar charts of cost by model tier and by provider, and a cross-check quorum panel" /></td>
118
97
  </tr>
119
98
 
120
99
  <tr valign="top">
121
- <td><img src="ui/e2e/__screenshots__/phase-6b/lessons-desktop-dark.png" width="100%" alt="Lessons page listing lesson candidates with scope and status chips, each with approve and reject actions" /></td>
122
100
  <td>
123
101
 
124
102
  **It learns from its own errors**
125
103
 
126
104
  Errors are classified against a taxonomy, and a scribe distills them into
127
105
  lesson candidates you approve or reject. Approved lessons splice into later
128
- prompts — and the same-mistake rate on the analytics page tells you whether
129
- that is actually working. A loop you can audit, not a memory you have to trust.
106
+ prompts — and the same-mistake rate tells you whether that is actually
107
+ working. A loop you can audit, not a memory you have to trust.
108
+
109
+ </td>
110
+ <td>
111
+
112
+ **A frontier planner, cheap workers**
113
+
114
+ Planning and judgment go to a frontier model; the bulk of the work goes to
115
+ small, fast tiers, many at once. Every session and every live agent is visible
116
+ with the tier that drew it, and cost breaks down per task, per tier and per
117
+ provider.
130
118
 
131
119
  </td>
132
120
  </tr>
133
121
 
134
122
  <tr valign="top">
135
- <td>
123
+ <td colspan="2">
136
124
 
137
125
  **The log is the source of truth**
138
126
 
@@ -142,27 +130,32 @@ the entire database from the log alone. Nothing the factory did exists only in
142
130
  a chat transcript.
143
131
 
144
132
  </td>
145
- <td><img src="ui/e2e/__screenshots__/phase-6b/timeline-desktop-dark.png" width="100%" alt="Timeline page: an event list filtered by Prompts, Dispatches, Gate events, Scheduler and Errors chips, showing task-added, user_prompt and session-start entries with timestamps and task ids" /></td>
146
133
  </tr>
147
134
  </table>
148
135
 
149
136
  **Also in the box**
150
137
 
151
- - **Eleven dashboard pages**, dark and light, desktop and mobile: errors by
152
- taxonomy category, roadmap progress joined to real task and token counts, and
153
- per-project scoping. It binds to `127.0.0.1` and is read-only — clicking
154
- nothing there dispatches an agent.
155
138
  - **Project scaffolding.** `/bs new <project>` generates a target project from
156
139
  the stack you answered for at install time; `/bs mcp` layers an MCP surface
157
140
  onto it.
141
+ - **An audit that ends in an epic.** `/bs audit <project-dir>` reads a project
142
+ that already exists on four axes, ranks what it finds, and cuts one epic from
143
+ what you accept.
158
144
  - **A factory that extends itself.** New agent roles, policies and taxonomy
159
145
  values are data files, not code — see
160
146
  [extending](docs/guide/extending.md).
161
147
  - **One integration branch per epic**, one pull request at the end, merged by
162
148
  you.
149
+ - **A local dashboard**, eleven read-only pages over the same event log —
150
+ optional, and [further down](#the-dashboard).
163
151
 
164
152
  ## Install
165
153
 
154
+ Two ways in, and they are **not** equivalent. A clone is what drives an epic.
155
+ The package is the `smith` CLI on a machine that has no clone.
156
+
157
+ ### A clone — the whole factory
158
+
166
159
  ```bash
167
160
  git clone https://github.com/juzser/blacksmith.git && cd blacksmith
168
161
  pnpm install --frozen-lockfile
@@ -177,7 +170,9 @@ bash scripts/check.sh # ends in `== PASS ==` on a good install
177
170
  ```
178
171
 
179
172
  Driving a real epic additionally needs the **Claude Code CLI** — the planner and
180
- every worker run as Claude Code sessions.
173
+ every worker run as Claude Code sessions. Open one **in the clone** and you have
174
+ `/bs`; that is the operator surface everything under [Using it](#using-it)
175
+ assumes.
181
176
 
182
177
  **Rather not do this by hand?** Open a Claude Code session in the clone and say
183
178
  *"install Blacksmith"*. [`INSTALL.md`](INSTALL.md) is an executable runbook: it
@@ -185,24 +180,42 @@ asks before touching anything outside the clone, and it doubles as the human
185
180
  version — per-platform setup (macOS, Debian/Ubuntu, Fedora, Alpine, WSL2),
186
181
  troubleshooting, and the known platform gaps stated rather than papered over.
187
182
 
188
- ### From npm
183
+ ### The package — `smith` inside a project you already have
189
184
 
190
- The CLI alone is also on the registry as
185
+ The CLI is published as
191
186
  [`@juzser/blacksmith`](https://www.npmjs.com/package/@juzser/blacksmith):
192
187
 
193
188
  ```bash
194
- npx @juzser/blacksmith --help # one-off
195
- npm i -g @juzser/blacksmith && smith --help
189
+ cd /path/to/your-project
190
+ npx @juzser/blacksmith init # creates .blacksmith/ beside your code
191
+ npx @juzser/blacksmith --help # or: npm i -g @juzser/blacksmith && smith --help
196
192
  ```
197
193
 
198
- That package is the `smith` binary plus everything it reads at runtime — the
199
- policies, the JSON Schemas, the scaffold templates, the agent role files, the
200
- database migrations. It is **not** the whole factory: the `/bs` console, the
201
- dashboard, the docs and the roadmap stay in the clone, and a registry install
202
- keeps its state (`state/`, `factory/specs/active/`) under its own install
203
- directory rather than beside the project it is working on. Driving an epic
204
- still means a Claude Code session opened in a clone. Take the package when you
205
- want `smith` on a machine without a clone; take the clone for everything else.
194
+ The tarball is the `smith` binary plus everything it reads at runtime — the
195
+ policies, the JSON Schemas, the scaffold templates, the roadmap default, the
196
+ agent role files, the database migrations. Installed, `smith` writes beside
197
+ **you**, not beside itself: state, epic plans and your `.env` go under
198
+ `.blacksmith/` in the directory you run it from, and `smith new` scaffolds
199
+ there too. `SMITH_HOME` overrides that root if you want one home for several
200
+ projects. (In a clone it still writes into the clone, as it always has — the
201
+ layout under the root is identical either way, which is what makes the two
202
+ installs one codebase.)
203
+
204
+ **What a package install does not give you is `/bs`.** `/bs` is not a CLI
205
+ command; it is a Claude Code **skill** — `.claude/skills/bs/`, a router and ten
206
+ playbooks that a session reads and follows. The playbooks ship in the tarball,
207
+ but they land under `node_modules/@juzser/blacksmith/`, which is not a place
208
+ Claude Code looks for skills or agent definitions. So a package gives you the
209
+ `smith` verbs and not the loop that drives them: validate plans, run the gates,
210
+ append events, read stats — yes; `/bs plan` and `/bs run` — from a clone.
211
+ Closing that gap is its own milestone, scoped and not yet cut:
212
+ [`docs/specs/plugin-port-scope.md`](docs/specs/plugin-port-scope.md).
213
+
214
+ > **Take `latest`.** `0.1.1` is the first release that knows it is a package:
215
+ > `smith init`, a work root beside your project, a shipped roadmap for
216
+ > `smith new` to read. `0.1.0`, the release before it, has none of that — it
217
+ > derives every path from a repo root and keeps state inside its own install
218
+ > directory, which the next `npm i` replaces. Nothing above describes `0.1.0`.
206
219
 
207
220
  ## Using it
208
221
 
@@ -286,15 +299,16 @@ Day to day, from a Claude Code session opened in this repo:
286
299
  | `/bs lessons` | Review pending lesson candidates |
287
300
  | `/bs report` | Render the scribe's progress digest |
288
301
 
289
- Underneath, every one of those is a `smith` command you can run yourself —
290
- `smith --help` lists them all.
302
+ Each of those is a playbook, not a script: the deterministic half is a `smith`
303
+ command you can run yourself — `smith --help` lists all of them — and the
304
+ judgment half is a Claude Code session the playbook dispatches. That is also
305
+ the line between the two installs: the `smith` half travels in the package, the
306
+ playbooks are read from a clone.
291
307
 
292
308
  → **[The operator loop](docs/guide/operator-loop.md)** — the six steps, in the
293
309
  order you meet them.<br />
294
310
  → **[Operator guide](docs/guide/operator-guide.md)** — the same ground with real
295
- commands and real output.<br />
296
- → **[The dashboard](docs/guide/dashboard.md)** — what each of the eleven pages
297
- shows you.
311
+ commands and real output.
298
312
 
299
313
  ## How it works
300
314
 
@@ -334,6 +348,39 @@ runs, plus branch protection — not by trust. Full rules:
334
348
  Found a vulnerability? [`SECURITY.md`](SECURITY.md) — report privately, not in
335
349
  a public issue.
336
350
 
351
+ ## The dashboard
352
+
353
+ Optional, and deliberately small: `/bs ui` (or `smith ui serve`) binds eleven
354
+ read-only pages to `127.0.0.1`. They are a projection of the event log and
355
+ nothing else — `smith db rebuild` reconstructs them from it, `smith stats`
356
+ prints the same facts in a terminal, and nothing you click there dispatches an
357
+ agent. The factory runs without ever opening it.
358
+
359
+ <table>
360
+ <tr valign="top">
361
+ <td width="50%"><img src="ui/e2e/__screenshots__/phase-6b/overview-desktop-dark.png" width="100%" alt="Blacksmith Overview page: a 'Needs you' banner reading '1 waiver pending, 1 task escalated', counters for active agents, budget used, epics in flight and alerts, and a 'Now running' list of two live sessions" /><br /><sub><b>Overview</b> — the one screen that asks something of you.</sub></td>
362
+ <td width="50%"><img src="ui/e2e/__screenshots__/phase-6b/task-detail-desktop-dark.png" width="100%" alt="Task detail page for epic-9/task-3 showing a Spec contract card with case, origin, epic, plan version and claims, and an Attempts list naming each agent, provider and outcome" /><br /><sub><b>Task detail</b> — the contract, and every attempt against it.</sub></td>
363
+ </tr>
364
+ <tr valign="top">
365
+ <td><img src="ui/e2e/__screenshots__/phase-6b/flow-desktop-dark.png" width="100%" alt="Flow page: task cards arranged in three columns labelled Wave 0 (6 tasks), Wave 1 (2 tasks) and Wave 2 (1 task), joined by dashed dependency edges" /><br /><sub><b>Flow</b> — waves and the dependency edges that shaped them.</sub></td>
366
+ <td><img src="ui/e2e/__screenshots__/phase-6b/kanban-desktop-dark.png" width="100%" alt="Kanban board with Todo, In progress, Reviewing and Blocked columns; cards carry severity chips such as S2-major and agent chips such as coder - mid" /><br /><sub><b>Kanban</b> — what is moving, and what is stuck and why.</sub></td>
367
+ </tr>
368
+ <tr valign="top">
369
+ <td><img src="ui/e2e/__screenshots__/phase-6b/sessions-desktop-dark.png" width="100%" alt="Sessions page: two session cards, sess-fixture and sess-multiproject-fixture, joined by dashed edges to six live agent cards labelled coder - small, coder - mid and planner - frontier, each marked working" /><br /><sub><b>Sessions</b> — every live agent and the tier that drew it.</sub></td>
370
+ <td><img src="ui/e2e/__screenshots__/phase-6b/analytics-desktop-dark.png" width="100%" alt="Analytics page with throughput, cost-per-task, same-mistake-rate and recheck-pass-rate cards, bar charts of cost by model tier and by provider, and a cross-check quorum panel" /><br /><sub><b>Analytics</b> — cost per task, per tier, per provider, and the same-mistake rate.</sub></td>
371
+ </tr>
372
+ <tr valign="top">
373
+ <td><img src="ui/e2e/__screenshots__/phase-6b/lessons-desktop-dark.png" width="100%" alt="Lessons page listing lesson candidates with scope and status chips, each with approve and reject actions" /><br /><sub><b>Lessons</b> — candidates waiting on your approve or reject.</sub></td>
374
+ <td><img src="ui/e2e/__screenshots__/phase-6b/timeline-desktop-dark.png" width="100%" alt="Timeline page: an event list filtered by Prompts, Dispatches, Gate events, Scheduler and Errors chips, showing task-added, user_prompt and session-start entries with timestamps and task ids" /><br /><sub><b>Timeline</b> — the append-only log itself, filtered.</sub></td>
375
+ </tr>
376
+ </table>
377
+
378
+ Dark and light, desktop and mobile; errors by taxonomy category, roadmap
379
+ progress joined to real task and token counts, and per-project scoping.
380
+
381
+ → **[The dashboard](docs/guide/dashboard.md)** — what each of the eleven pages
382
+ shows you. It is part of the clone, not of the package.
383
+
337
384
  ## Status
338
385
 
339
386
  Phases 1–9 are built and merged: loop runner, worktree engine, gates, state and
@@ -341,8 +388,14 @@ analytics, dashboard, self-extension, cross-provider judges, hardening. Phase 10
341
388
  is half in: `smith daemon` watches the factory in the background and its ops
342
389
  runbook is written; the hosted UI stays deferred. Beside the phases, `/bs audit`
343
390
  is built: an existing project can be read on four axes and one epic cut from
344
- what you accept. And the CLI is on npm as `@juzser/blacksmith` — the binary and
345
- what it reads, not the console or the dashboard, which still run from a clone.
391
+ what you accept.
392
+
393
+ The CLI is on npm as `@juzser/blacksmith`, at `0.1.1` — the first version
394
+ that runs beside you and knows it is a package, rather than out of the
395
+ clone-shaped install `0.1.0` was. The package is the binary and what it
396
+ reads. The dashboard, the docs, the test suite and `/bs` itself come from a
397
+ clone; a plugin is what would move `/bs`, and it is
398
+ [scoped, not cut](docs/specs/plugin-port-scope.md).
346
399
 
347
400
  The one thing to know up front: **the daemon watches, it does not drive.** It
348
401
  tells you what the factory needs — budget alarms, agents that never came back,
@@ -352,7 +405,7 @@ and nothing advances.
352
405
 
353
406
  → **[What is built, what is not](docs/guide/status.md)**, and the unflinching
354
407
  version in
355
- [Limitations today](docs/guide/operator-guide.md#limitations-today).
408
+ [Limitations today](docs/guide/operator-guide/limitations.md#limitations-today).
356
409
 
357
410
  ## Docs
358
411
 
@@ -361,11 +414,12 @@ version in
361
414
  | [`INSTALL.md`](INSTALL.md) | Getting it running, per platform |
362
415
  | [`docs/guide/operator-loop.md`](docs/guide/operator-loop.md) | The six steps you actually do |
363
416
  | [`docs/guide/operator-guide.md`](docs/guide/operator-guide.md) | Every command, end to end, with output |
364
- | [`docs/guide/dashboard.md`](docs/guide/dashboard.md) | The dashboard tour |
365
417
  | [`docs/guide/status.md`](docs/guide/status.md) | What is real today |
366
418
  | [`docs/guide/extending.md`](docs/guide/extending.md) | Adding agents, policies, taxonomy values |
367
419
  | [`docs/specs/black-smith-architecture.md`](docs/specs/black-smith-architecture.md) | Why it is shaped this way |
368
420
  | [`docs/specs/audit-command-scope.md`](docs/specs/audit-command-scope.md) | What `/bs audit` promises an audited project, and why |
421
+ | [`docs/specs/plugin-port-scope.md`](docs/specs/plugin-port-scope.md) | What it would take to run `/bs` without a clone |
422
+ | [`docs/guide/dashboard.md`](docs/guide/dashboard.md) | The dashboard tour |
369
423
  | [`docs/runbooks/providers.md`](docs/runbooks/providers.md) | Setting up the cross-provider judges |
370
424
  | [`docs/runbooks/ops.md`](docs/runbooks/ops.md) | Running `smith daemon` unattended |
371
425
  | [`docs/README.md`](docs/README.md) | Everything else, one line each |
@@ -17,9 +17,10 @@
17
17
  // - 'user' — what waivers.ts, lessons.ts and prompts.ts default to when no
18
18
  // actor is supplied, which is how every decision made through the UI is
19
19
  // attributed (ui/server never passes one).
20
- // - 'operator' — what docs/guide/operator-guide.md and .claude/skills/bs/
21
- // SKILL.md hand the operator, in all six of their `--actor` examples,
22
- // including the `smith waivers apply` line that writes waiver-granted.
20
+ // - 'operator' — what docs/guide/operator-guide/*.md and .claude/skills/bs/
21
+ // SKILL.md hand the operator, in every `--actor` example they carry (three
22
+ // today), including the `smith waivers apply` line in
23
+ // severity-and-budget.md that writes waiver-granted.
23
24
  // - 'operator-skill' — what the operator's own console passes; 467 of the 668
24
25
  // recorded events carry it. It is a skill rather than a person, and it is
25
26
  // here anyway: it acts only on a turn the operator took, and the decision