@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.
- package/.claude/agents/coder.md +9 -3
- package/.claude/agents/grader.md +13 -5
- package/.claude/agents/merger.md +2 -0
- package/.claude/agents/planner.md +1 -1
- package/.claude/agents/researcher.md +3 -1
- package/.claude/agents/reviewer.md +9 -2
- package/.claude/agents/security-reviewer.md +15 -7
- package/.claude/agents/spec-reviewer.md +12 -3
- package/.claude/agents/tester.md +5 -2
- package/.claude/agents/uiux.md +10 -3
- package/.claude/agents/verifier.md +8 -3
- package/.claude/skills/bs/SKILL.md +103 -0
- package/.claude/skills/bs/audit.md +250 -0
- package/.claude/skills/bs/dispatch.md +394 -0
- package/.claude/skills/bs/lessons.md +73 -0
- package/.claude/skills/bs/mcp.md +29 -0
- package/.claude/skills/bs/new.md +33 -0
- package/.claude/skills/bs/plan.md +155 -0
- package/.claude/skills/bs/report.md +129 -0
- package/.claude/skills/bs/run.md +325 -0
- package/.claude/skills/bs/status.md +54 -0
- package/.claude/skills/bs/ui.md +12 -0
- package/.claude/skills/bs/waivers.md +13 -0
- package/.claude/skills/bs/wave.md +261 -0
- package/README.md +119 -65
- package/factory/orchestrator/dist/actors.js +4 -3
- package/factory/orchestrator/dist/agents-registry.js +96 -19
- package/factory/orchestrator/dist/artifacts.js +36 -4
- package/factory/orchestrator/dist/budgets.js +7 -5
- package/factory/orchestrator/dist/cli.js +107 -7
- package/factory/orchestrator/dist/crosscheck.js +11 -0
- package/factory/orchestrator/dist/daemon.js +14 -0
- package/factory/orchestrator/dist/db/projector.js +272 -90
- package/factory/orchestrator/dist/db/queries.js +83 -14
- package/factory/orchestrator/dist/db/schema.js +7 -0
- package/factory/orchestrator/dist/events.js +38 -4
- package/factory/orchestrator/dist/harness.js +367 -0
- package/factory/orchestrator/dist/judges.js +49 -8
- package/factory/orchestrator/dist/lessons.js +4 -4
- package/factory/orchestrator/dist/mcp.js +4 -3
- package/factory/orchestrator/dist/paths.js +167 -15
- package/factory/orchestrator/dist/plan.js +1 -1
- package/factory/orchestrator/dist/planQuorum.js +36 -8
- package/factory/orchestrator/dist/providers/api-transport.js +62 -5
- package/factory/orchestrator/dist/providers/index.js +1 -0
- package/factory/orchestrator/dist/providers/schema-validate.js +58 -7
- package/factory/orchestrator/dist/providers/types.js +5 -0
- package/factory/orchestrator/dist/roadmap.js +3 -3
- package/factory/orchestrator/dist/scaffold.js +3 -2
- package/factory/orchestrator/dist/stack.js +10 -2
- package/factory/orchestrator/dist/templateFragments.js +178 -0
- package/factory/orchestrator/dist/usage.js +24 -5
- package/factory/orchestrator/dist/workroot.js +113 -0
- package/factory/orchestrator/drizzle/0011_findings_spec_ref.sql +3 -0
- package/factory/orchestrator/drizzle/meta/_journal.json +7 -0
- package/factory/policies/budgets.yml +6 -3
- package/factory/policies/crosscheck.yml +10 -8
- package/factory/policies/lessons.md +122 -0
- package/factory/policies/taxonomy.yml +6 -2
- package/factory/specs/roadmap.md +154 -0
- 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
|

|
|
16
16
|
|
|
17
17
|
**[Features](#features) · [Install](#install) · [Using it](#using-it) ·
|
|
18
|
-
[How it works](#how-it-works) · [Safety](#safety) ·
|
|
19
|
-
[Docs](#docs)**
|
|
18
|
+
[How it works](#how-it-works) · [Safety](#safety) ·
|
|
19
|
+
[Dashboard](#the-dashboard) · [Status](#status) · [Docs](#docs)**
|
|
20
20
|
|
|
21
|
-
<
|
|
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>
|
|
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%"
|
|
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.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
|
129
|
-
|
|
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
|
-
###
|
|
183
|
+
### The package — `smith` inside a project you already have
|
|
189
184
|
|
|
190
|
-
The CLI
|
|
185
|
+
The CLI is published as
|
|
191
186
|
[`@juzser/blacksmith`](https://www.npmjs.com/package/@juzser/blacksmith):
|
|
192
187
|
|
|
193
188
|
```bash
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
199
|
-
policies, the JSON Schemas, the scaffold templates, the
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
290
|
-
`smith --help` lists them
|
|
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
|
|
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.
|
|
345
|
-
|
|
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
|
|
21
|
-
// SKILL.md hand the operator, in
|
|
22
|
-
// including the `smith waivers apply` line
|
|
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
|