@juzser/blacksmith 0.4.0 → 0.5.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.
- package/.claude/agents/{auditor.md → bs-auditor.md} +5 -5
- package/.claude/agents/{coder.md → bs-coder.md} +8 -7
- package/.claude/agents/{grader.md → bs-grader.md} +4 -4
- package/.claude/agents/{merger.md → bs-merger.md} +4 -4
- package/.claude/agents/{planner.md → bs-planner.md} +20 -6
- package/.claude/agents/{researcher.md → bs-researcher.md} +6 -5
- package/.claude/agents/{reviewer.md → bs-reviewer.md} +13 -5
- package/.claude/agents/{scribe.md → bs-scribe.md} +11 -2
- package/.claude/agents/{security-reviewer.md → bs-security-reviewer.md} +6 -6
- package/.claude/agents/{spec-reviewer.md → bs-spec-reviewer.md} +15 -10
- package/.claude/agents/{tester.md → bs-tester.md} +40 -12
- package/.claude/agents/bs-uiux.md +257 -0
- package/.claude/agents/{verifier.md → bs-verifier.md} +4 -4
- package/.claude/agents/{wave-runner.md → bs-wave-runner.md} +14 -5
- package/.claude/skills/bs/SKILL.md +99 -21
- package/.claude/skills/bs/audit.md +34 -27
- package/.claude/skills/bs/dispatch.md +100 -50
- package/.claude/skills/bs/lessons.md +28 -14
- package/.claude/skills/bs/mcp.md +4 -4
- package/.claude/skills/bs/new.md +3 -3
- package/.claude/skills/bs/plan.md +27 -18
- package/.claude/skills/bs/report.md +11 -11
- package/.claude/skills/bs/run.md +181 -49
- package/.claude/skills/bs/status.md +14 -7
- package/.claude/skills/bs/ui.md +21 -5
- package/.claude/skills/bs/waivers.md +78 -2
- package/.claude/skills/bs/wave.md +109 -53
- package/README.md +53 -32
- package/factory/orchestrator/dist/agentNames.js +43 -0
- package/factory/orchestrator/dist/agents-registry.js +11 -4
- package/factory/orchestrator/dist/agentsSync.js +48 -14
- package/factory/orchestrator/dist/artifacts.js +31 -0
- package/factory/orchestrator/dist/attribution.js +4 -0
- package/factory/orchestrator/dist/audit.js +125 -17
- package/factory/orchestrator/dist/budgetAlarm.js +132 -37
- package/factory/orchestrator/dist/budgets.js +302 -84
- package/factory/orchestrator/dist/claims.js +9 -19
- package/factory/orchestrator/dist/cli.js +790 -100
- package/factory/orchestrator/dist/cliName.js +27 -0
- package/factory/orchestrator/dist/crosscheck.js +136 -8
- package/factory/orchestrator/dist/daemon.js +154 -36
- package/factory/orchestrator/dist/db/projector.js +278 -29
- package/factory/orchestrator/dist/db/queries.js +1831 -94
- package/factory/orchestrator/dist/db/schema.js +57 -4
- package/factory/orchestrator/dist/declaredArtifactLine.js +18 -0
- package/factory/orchestrator/dist/delegation.js +86 -19
- package/factory/orchestrator/dist/diffstat.js +15 -8
- package/factory/orchestrator/dist/dispatchLint.js +13 -37
- package/factory/orchestrator/dist/effort.js +14 -2
- package/factory/orchestrator/dist/effortTiers.js +13 -0
- package/factory/orchestrator/dist/env.js +26 -0
- package/factory/orchestrator/dist/epic.js +323 -38
- package/factory/orchestrator/dist/epicBudget.js +93 -0
- package/factory/orchestrator/dist/epicWidth.js +22 -5
- package/factory/orchestrator/dist/errorIssues.js +10 -4
- package/factory/orchestrator/dist/escalation.js +2 -2
- package/factory/orchestrator/dist/events.js +105 -3
- package/factory/orchestrator/dist/feedback.js +169 -0
- package/factory/orchestrator/dist/findingContext.js +26 -0
- package/factory/orchestrator/dist/findings.js +83 -12
- package/factory/orchestrator/dist/gate.js +120 -10
- package/factory/orchestrator/dist/goalCheck.js +2 -2
- package/factory/orchestrator/dist/harness.js +25 -17
- package/factory/orchestrator/dist/hookDecision.js +92 -3
- package/factory/orchestrator/dist/integration.js +9 -7
- package/factory/orchestrator/dist/judgePreflight.js +25 -4
- package/factory/orchestrator/dist/judgeRoles.js +47 -0
- package/factory/orchestrator/dist/judgeStopHook.js +90 -32
- package/factory/orchestrator/dist/judges.js +419 -21
- package/factory/orchestrator/dist/lessons.js +190 -11
- package/factory/orchestrator/dist/mcp.js +6 -6
- package/factory/orchestrator/dist/paths.js +10 -7
- package/factory/orchestrator/dist/plan.js +269 -33
- package/factory/orchestrator/dist/planQuorum.js +5 -2
- package/factory/orchestrator/dist/policy.js +1275 -30
- package/factory/orchestrator/dist/projectName.js +25 -0
- package/factory/orchestrator/dist/promptCapture.js +306 -0
- package/factory/orchestrator/dist/promptHook.js +33 -0
- package/factory/orchestrator/dist/promptImport.js +281 -0
- package/factory/orchestrator/dist/prompts.js +13 -0
- package/factory/orchestrator/dist/providers/schema-validate.js +2 -2
- package/factory/orchestrator/dist/providers/types.js +1 -1
- package/factory/orchestrator/dist/queue.js +4 -4
- package/factory/orchestrator/dist/quorum.js +18 -5
- package/factory/orchestrator/dist/results.js +25 -7
- package/factory/orchestrator/dist/roadmap.js +10 -5
- package/factory/orchestrator/dist/run-cli.js +15 -10
- package/factory/orchestrator/dist/runner.js +2 -2
- package/factory/orchestrator/dist/schemas.js +56 -8
- package/factory/orchestrator/dist/severity.js +8 -4
- package/factory/orchestrator/dist/spec.js +177 -13
- package/factory/orchestrator/dist/specChange.js +13 -9
- package/factory/orchestrator/dist/stack.js +6 -6
- package/factory/orchestrator/dist/storeRoot.js +90 -0
- package/factory/orchestrator/dist/symbols.js +261 -6
- package/factory/orchestrator/dist/taskEvents.js +179 -27
- package/factory/orchestrator/dist/taskStatus.js +14 -0
- package/factory/orchestrator/dist/testerAudit.js +31 -12
- package/factory/orchestrator/dist/testgate.js +16 -13
- package/factory/orchestrator/dist/uiuxGate.js +83 -0
- package/factory/orchestrator/dist/usage.js +97 -40
- package/factory/orchestrator/dist/waivers.js +39 -5
- package/factory/orchestrator/dist/waveBudget.js +2 -0
- package/factory/orchestrator/dist/waveConcurrency.js +143 -7
- package/factory/orchestrator/dist/workroot.js +1 -1
- package/factory/orchestrator/dist/worktree.js +61 -19
- package/factory/orchestrator/drizzle/0013_operator_feedback.sql +19 -0
- package/factory/orchestrator/drizzle/0014_misty_madripoor.sql +2 -0
- package/factory/orchestrator/drizzle/0015_gifted_omega_flight.sql +1 -0
- package/factory/orchestrator/drizzle/0016_milestones_project_default.sql +30 -0
- package/factory/orchestrator/drizzle/0017_events_raw_cli_session_id.sql +2 -0
- package/factory/orchestrator/drizzle/meta/_journal.json +35 -0
- package/factory/policies/budgets.yml +123 -33
- package/factory/policies/crosscheck.yml +51 -13
- package/factory/policies/delegation.yml +3 -3
- package/factory/policies/effort.yml +18 -10
- package/factory/policies/guardrails.yml +8 -6
- package/factory/policies/harness.yml +5 -5
- package/factory/policies/lessons.md +53 -2
- package/factory/policies/scheduler.yml +4 -4
- package/factory/policies/sensitive-paths.yml +1 -1
- package/factory/policies/severity.yml +13 -1
- package/factory/policies/stack.yml +6 -6
- package/factory/policies/taxonomy.yml +9 -3
- package/factory/policies/worktree.yml +15 -9
- package/factory/specs/roadmap.md +7 -7
- package/factory/specs/schema/event.schema.json +8 -1
- package/factory/specs/schema/result.schema.json +21 -8
- package/factory/specs/schema/task-spec.schema.json +12 -0
- package/package.json +16 -12
- package/.claude/agents/uiux.md +0 -133
package/.claude/skills/bs/new.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# `/bs new <project> [--ui]` — scaffold a target project
|
|
2
2
|
|
|
3
|
-
1. Ask where the project should live, then run `
|
|
3
|
+
1. Ask where the project should live, then run `bs new <project> [--ui]
|
|
4
4
|
[--target-dir <dir>]`. Without `--target-dir` it lands beside the clone, in
|
|
5
|
-
`<repo-parent>/<project>` — or, when `
|
|
5
|
+
`<repo-parent>/<project>` — or, when `bs` is an installed package rather
|
|
6
6
|
than a clone, in the directory you run it from, never inside the package.
|
|
7
7
|
Either way that is a default rather than a requirement —
|
|
8
8
|
the answer becomes the `<project-dir>` every later command takes, so take
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
bootstrap milestone in `factory/specs/roadmap.md` — all in one call.
|
|
16
16
|
An answer the templates cannot build (`frontend: react`) makes it **refuse
|
|
17
17
|
before creating anything**, rather than quietly handing over the frontend
|
|
18
|
-
they do ship. `
|
|
18
|
+
they do ship. `bs stack check` says in advance which answers are
|
|
19
19
|
honoured, merely recorded, or refused.
|
|
20
20
|
2. The gate run is `pnpm install` then `lint`, `typecheck`, `test:coverage`,
|
|
21
21
|
`build` — `ci.yml`'s order, so the lockfile lands in the first commit and no
|
|
@@ -11,8 +11,8 @@ one — and it scales steps 3–4 below plus most of `/bs run`. Ask, do not
|
|
|
11
11
|
recall:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
bs effort show --effort <small|medium|huge> # no plan file exists yet
|
|
15
|
+
bs effort show --plan factory/specs/active/<epic>/plan-vN.json
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
`profile` is what this epic buys, and every step below that a tier touches
|
|
@@ -34,13 +34,13 @@ there means "not looked at", not "looked at and clean".
|
|
|
34
34
|
|
|
35
35
|
1. **Static analysis for claims first.** Before any decomposition, get the
|
|
36
36
|
target repo's import/dependency graph so claims are computed, not
|
|
37
|
-
guessed (architecture §5) — dispatch `researcher`
|
|
38
|
-
(`.claude/agents/researcher.md`) for an unfamiliar repo, or do it
|
|
37
|
+
guessed (architecture §5) — dispatch `bs-researcher`
|
|
38
|
+
(`.claude/agents/bs-researcher.md`) for an unfamiliar repo, or do it
|
|
39
39
|
directly with Grep/Read for a small one.
|
|
40
|
-
2. Dispatch a **`planner`** session (`.claude/agents/planner.md`, frontier
|
|
40
|
+
2. Dispatch a **`bs-planner`** session (`.claude/agents/bs-planner.md`, frontier
|
|
41
41
|
tier) with the goal + the claims analysis. It drafts the epic spec and
|
|
42
42
|
task specs (`factory/specs/schema/task-spec.schema.json` shape).
|
|
43
|
-
3. Dispatch a **`spec-reviewer`** session (`.claude/agents/spec-reviewer.md`)
|
|
43
|
+
3. Dispatch a **`bs-spec-reviewer`** session (`.claude/agents/bs-spec-reviewer.md`)
|
|
44
44
|
— a *different model* than the planner's, per its own frontmatter — to
|
|
45
45
|
hunt spec gaps/ambiguities/missing-nonfunctional clauses
|
|
46
46
|
(`docs/standards/agent-constraints.md` "planner"; `severity.yml`: most
|
|
@@ -49,7 +49,7 @@ there means "not looked at", not "looked at and clean".
|
|
|
49
49
|
back tagged to one of them:
|
|
50
50
|
|
|
51
51
|
1. Claims and dependency edges, cross-checked against
|
|
52
|
-
`
|
|
52
|
+
`bs claims impact`.
|
|
53
53
|
2. TDD-ability -- a named failing test per task, before its code.
|
|
54
54
|
3. Nonfunctional and security clauses.
|
|
55
55
|
4. Budget and diff-cap fit.
|
|
@@ -57,8 +57,13 @@ there means "not looked at", not "looked at and clean".
|
|
|
57
57
|
6. From round 2 on, only the previous round's findings plus any task
|
|
58
58
|
that changed since then.
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
`
|
|
60
|
+
The prompt also carries, inline on its own line,
|
|
61
|
+
`Declared artifact: /abs/path/to/state/results/<epic-id>.spec-review.json`
|
|
62
|
+
— the absolute form of the path `bs-spec-reviewer.md` names. The PreToolUse
|
|
63
|
+
guard refuses a judge dispatch without it.
|
|
64
|
+
|
|
65
|
+
When `size.small` reads true on the draft (`bs wave schedule` or
|
|
66
|
+
`bs plan ingest`'s `parallelism.size`, run against the draft plan
|
|
62
67
|
file), recommend effort tier `small` -- single-pass spec review -- to
|
|
63
68
|
the operator unless a security trigger floors it first, and say why in
|
|
64
69
|
the same message: a plan that cannot spread past a few tasks and a
|
|
@@ -74,9 +79,10 @@ there means "not looked at", not "looked at and clean".
|
|
|
74
79
|
confidence) for you:
|
|
75
80
|
|
|
76
81
|
```bash
|
|
77
|
-
|
|
82
|
+
bs plan quorum --plan <the draft's plan.json> --plan-version <n> \
|
|
78
83
|
--session <session-id> --causal-parent <event-id> \
|
|
79
84
|
--confidence <your own 0–1 confidence in this plan> \
|
|
85
|
+
--project <project-dir> \
|
|
80
86
|
--out <scratch>/quorum-v<n>.json
|
|
81
87
|
```
|
|
82
88
|
|
|
@@ -86,7 +92,10 @@ there means "not looked at", not "looked at and clean".
|
|
|
86
92
|
exist. (`--epic <epic>` instead of `--plan` critiques a version already
|
|
87
93
|
filed.) The draft's own `epic_id`/`version` must be the ones the command
|
|
88
94
|
names, or it refuses (`plan.identity-mismatch`) rather than record one
|
|
89
|
-
plan's identity with another plan's triggers. `--
|
|
95
|
+
plan's identity with another plan's triggers. `--project <project-dir>`
|
|
96
|
+
has no worktree to derive from at this step — no task has one yet — so
|
|
97
|
+
name it directly, or a `<project-dir>/.blacksmith/crosscheck.yml` overlay
|
|
98
|
+
never reaches the providers this quorum weighs. `--out` keeps the outcome
|
|
90
99
|
— three rationales of several kB each — where step 5 can hand it to the
|
|
91
100
|
operator whole instead of quoting a terminal.
|
|
92
101
|
|
|
@@ -109,10 +118,10 @@ there means "not looked at", not "looked at and clean".
|
|
|
109
118
|
"planner: autonomy — spec sign-off per epic").
|
|
110
119
|
6. On approval, write task specs to
|
|
111
120
|
`factory/specs/active/<epic>/plan-v1.json` and validate:
|
|
112
|
-
`
|
|
121
|
+
`bs plan validate factory/specs/active/<epic>/plan-v1.json` must
|
|
113
122
|
report `{"valid":true}` before anything else touches this plan. Write the
|
|
114
123
|
tier onto the plan file as a top-level `"effort": "<tier>"` — that is
|
|
115
|
-
where `/bs run` reads it, and `
|
|
124
|
+
where `/bs run` reads it, and `bs plan amend` carries it into
|
|
116
125
|
v(n+1) so a re-plan is not a fresh choice. Omit the field to take the
|
|
117
126
|
policy default; a value that is not `small`/`medium`/`huge` fails
|
|
118
127
|
validation rather than degrading to it.
|
|
@@ -121,7 +130,7 @@ there means "not looked at", not "looked at and clean".
|
|
|
121
130
|
against it:
|
|
122
131
|
|
|
123
132
|
```bash
|
|
124
|
-
|
|
133
|
+
bs wave schedule factory/specs/active/<epic>/plan-v1.json \
|
|
125
134
|
--session <session-id> --repo <project-dir>
|
|
126
135
|
```
|
|
127
136
|
|
|
@@ -154,7 +163,7 @@ there means "not looked at", not "looked at and clean".
|
|
|
154
163
|
Beside the schedule, the read that names what it only counts:
|
|
155
164
|
|
|
156
165
|
```bash
|
|
157
|
-
|
|
166
|
+
bs claims impact --plan factory/specs/active/<epic>/plan-v1.json \
|
|
158
167
|
<task-id>... --repo <project-dir>
|
|
159
168
|
```
|
|
160
169
|
|
|
@@ -162,8 +171,8 @@ there means "not looked at", not "looked at and clean".
|
|
|
162
171
|
at; `promised` holds the ones a producer's `keeps_exports` already
|
|
163
172
|
answers, which the schedule admits and the diff is later checked against.
|
|
164
173
|
7. Log the sign-off itself as a decision checkpoint (this is exactly what
|
|
165
|
-
`
|
|
166
|
-
`
|
|
174
|
+
`bs dream`'s "plan sign-off" extraction looks for, `lessons.ts`):
|
|
175
|
+
`bs event append '{"session_id":"...","actor":"operator",
|
|
167
176
|
"event_type":"plan-version-created","plan_version":1,
|
|
168
177
|
"causal_parent":"...","payload":{"epic_id":"<epic>","version":1,
|
|
169
178
|
"note":"<operator's own words>"}}'`.
|
|
@@ -172,7 +181,7 @@ there means "not looked at", not "looked at and clean".
|
|
|
172
181
|
the sign-off event:
|
|
173
182
|
|
|
174
183
|
```bash
|
|
175
|
-
|
|
184
|
+
bs plan ingest factory/specs/active/<epic>/plan-v1.json --project <project-dir> \
|
|
176
185
|
--session <session-id> --plan-version 1 --causal-parent <sign-off event id>
|
|
177
186
|
```
|
|
178
187
|
|
|
@@ -8,8 +8,8 @@ duties, v3.2)"), plus running the scheduler first — a report that omits
|
|
|
8
8
|
pending proposals lets them sit invisible instead of surfacing them.
|
|
9
9
|
|
|
10
10
|
1. **Ask what the factory is answerable for, then run the scheduler.**
|
|
11
|
-
`
|
|
12
|
-
register `
|
|
11
|
+
`bs projects list` reads the roadmap's `- project:` bullets — the
|
|
12
|
+
register `bs new` writes to — and prints the factory itself plus every
|
|
13
13
|
project it built that has a checkout, ending in the `--project` line to
|
|
14
14
|
pass on. Do not assemble that list from memory: the maintenance pass
|
|
15
15
|
reads one lockfile per flag and reports one proposal per repo, so a repo
|
|
@@ -17,9 +17,9 @@ pending proposals lets them sit invisible instead of surfacing them.
|
|
|
17
17
|
mentioned. (The daemon raises `unwatched-project` for a child project with
|
|
18
18
|
a checkout that is left off the line — not for the factory itself, which is in
|
|
19
19
|
the pass by default, and not for a declared project with no checkout at
|
|
20
|
-
all, which `
|
|
20
|
+
all, which `bs projects list` marks with `?` instead of leaving it
|
|
21
21
|
off the printed list. The two surfaces no longer answer the same
|
|
22
|
-
question.) Then run `
|
|
22
|
+
question.) Then run `bs scheduler run
|
|
23
23
|
[--dry] --session <id> [--project <dir>...]` with those flags — a
|
|
24
24
|
deterministic pass over the event log, it never dispatches an agent
|
|
25
25
|
itself (`factory/policies/scheduler.yml`, architecture §12). Read its
|
|
@@ -42,7 +42,7 @@ pending proposals lets them sit invisible instead of surfacing them.
|
|
|
42
42
|
where the planner reads the living spec/analytics/recheck outcomes
|
|
43
43
|
and proposes new epics — the operator's tick is required regardless
|
|
44
44
|
of confidence, same as any other plan sign-off.
|
|
45
|
-
2. **Ask who may say yes.** `
|
|
45
|
+
2. **Ask who may say yes.** `bs scheduler admit --session <id>
|
|
46
46
|
[--project <dir>...]`, with the same flag line step 1 printed, re-reads
|
|
47
47
|
the same proposals and classifies
|
|
48
48
|
each one `auto` or `operator` against `scheduler.yml`'s `autonomy:`
|
|
@@ -66,9 +66,9 @@ pending proposals lets them sit invisible instead of surfacing them.
|
|
|
66
66
|
`confidence_floor` is an operator decision about standing policy, not
|
|
67
67
|
a way past one proposal — and a `security-surface` denial is the one
|
|
68
68
|
nothing in the file can lift.
|
|
69
|
-
3. Gather `
|
|
69
|
+
3. Gather `bs stats overview [--session <id>]` and `bs stats roadmap
|
|
70
70
|
[--session <id>]` (milestone progress + budget burn per milestone).
|
|
71
|
-
4. **Read back the disagreements.** `
|
|
71
|
+
4. **Read back the disagreements.** `bs judge escalations --session
|
|
72
72
|
<id>` folds the lineage for `quorum-decision` events whose latest word
|
|
73
73
|
was `escalate` — a gate finding, an epic verdict or a plan critique the
|
|
74
74
|
cross-provider quorum could not settle. It exits `1` on an open
|
|
@@ -83,7 +83,7 @@ pending proposals lets them sit invisible instead of surfacing them.
|
|
|
83
83
|
`mode: shadow` disagreement, which the gate outcome never reported to
|
|
84
84
|
anyone). Resolving one is an operator reading, never this session
|
|
85
85
|
deciding on its own which provider was right.
|
|
86
|
-
5. **Read back the parallelism.** `
|
|
86
|
+
5. **Read back the parallelism.** `bs wave audit --session <id>
|
|
87
87
|
[--epic <id>]` folds every `wave-admitted` against the
|
|
88
88
|
`dispatch_decision` intervals underneath it and says whether a wave
|
|
89
89
|
admitted N wide actually *ran* N wide. `wave check` only ever certified
|
|
@@ -97,11 +97,11 @@ pending proposals lets them sit invisible instead of surfacing them.
|
|
|
97
97
|
check before reporting it as a stall. A `partial` verdict is **not** a
|
|
98
98
|
finding; put `widest` in the digest as the one number that says how wide
|
|
99
99
|
this factory has ever actually run.
|
|
100
|
-
6. Dispatch **`scribe`** (`.claude/agents/scribe.md`, small tier) with that
|
|
100
|
+
6. Dispatch **`bs-scribe`** (`.claude/agents/bs-scribe.md`, small tier) with that
|
|
101
101
|
JSON plus step 2's admissions as input: shipped / in-flight / blocked /
|
|
102
102
|
budget burn / next milestone / **N rechecks pending, M maintenance
|
|
103
103
|
bumps auto-schedulable** (never silently dropped), ≤300 words, linking
|
|
104
|
-
into the dashboard (`
|
|
104
|
+
into the dashboard (`bs ui serve`'s URL) — never paraphrase numbers
|
|
105
105
|
the query didn't return.
|
|
106
106
|
7. This fires automatically on a weekly cadence and immediately on any
|
|
107
107
|
milestone completion (architecture §12) — for an ad hoc `/bs report`,
|
|
@@ -114,7 +114,7 @@ pending proposals lets them sit invisible instead of surfacing them.
|
|
|
114
114
|
|
|
115
115
|
**Provider calibration note (Phase 8).** While any provider in
|
|
116
116
|
`factory/policies/crosscheck.yml` is still `mode: shadow`, run
|
|
117
|
-
`
|
|
117
|
+
`bs stats providers [--session <id>] [--since <iso-date>]` alongside the
|
|
118
118
|
scheduler pass and fold a one-line mention into the digest when a provider
|
|
119
119
|
has accumulated enough runs to review (`runs`, `verdicts`, `agreementRate`,
|
|
120
120
|
`schemaFailureRate`, `transportFailureRate`, `failuresByCode` per provider —
|
package/.claude/skills/bs/run.md
CHANGED
|
@@ -15,19 +15,33 @@ epic. "Hand the wave over" below says how, and says the one thing that makes
|
|
|
15
15
|
it safe.
|
|
16
16
|
|
|
17
17
|
Ask the epic's effort tier once, at the top of the run, and keep the answer
|
|
18
|
-
for the whole epic — `
|
|
18
|
+
for the whole epic — `bs effort show --plan
|
|
19
19
|
factory/specs/active/<epic>/plan-vN.json`. Step 13 here, and steps 3, 6 and 7
|
|
20
20
|
of the wave playbook, each name the `profile` field that scales them; nothing
|
|
21
21
|
else in either file moves. Read `effective`, not `requested`: a plan whose
|
|
22
22
|
live tasks fire a security trigger is floored, and running it at the tier the
|
|
23
23
|
file asked for would be running it below the floor.
|
|
24
24
|
|
|
25
|
+
Ask the cross-provider gate once too, at the top of the run and before any
|
|
26
|
+
wave is admitted — `bs judge preflight --project <project-dir>`, the same
|
|
27
|
+
call INSTALL.md makes at setup. When it reports the gating pool cannot
|
|
28
|
+
decide (fewer active external providers than `quorum_rule.min_providers`
|
|
29
|
+
after OpenRouter substitution, or a provider the project's own
|
|
30
|
+
`.blacksmith/crosscheck.yml` names but this box cannot reach), STOP and ask
|
|
31
|
+
the operator before admitting a wave — per `.claude/skills/bs/SKILL.md`'s
|
|
32
|
+
"Talking to the operator" rules (options carry a confidence %; not restated
|
|
33
|
+
here): add an OpenRouter key, add a model, pick which providers to run with,
|
|
34
|
+
or continue without cross-check. Skipping this is not a shortcut — steps 15
|
|
35
|
+
and 16 spend a real judge call to find the same gap mid-run, after the epic's
|
|
36
|
+
work is already done. Full substitution and precedence mechanism:
|
|
37
|
+
docs/runbooks/providers.md §9d.
|
|
38
|
+
|
|
25
39
|
1. Ask the graph how wide this wave can be, then ask the gate whether it may
|
|
26
40
|
be that wide. Two commands, two different questions — do not skip to the
|
|
27
41
|
second with a set you picked by eye.
|
|
28
42
|
|
|
29
43
|
```bash
|
|
30
|
-
|
|
44
|
+
bs wave next factory/specs/active/<epic>/plan-vN.json \
|
|
31
45
|
--session <session-id> --repo <project-dir>
|
|
32
46
|
```
|
|
33
47
|
|
|
@@ -46,7 +60,7 @@ file asked for would be running it below the floor.
|
|
|
46
60
|
|
|
47
61
|
Then put that proposal through the gate that actually admits it:
|
|
48
62
|
|
|
49
|
-
`
|
|
63
|
+
`bs wave check factory/specs/active/<epic>/plan-vN.json <task-id>...`
|
|
50
64
|
— claims must be pairwise disjoint and share no `worktree.yml`
|
|
51
65
|
`serialize_always_globs` hotspot. A violation means cut a dependency
|
|
52
66
|
edge and run the pair serially instead of forcing the wave.
|
|
@@ -66,6 +80,16 @@ file asked for would be running it below the floor.
|
|
|
66
80
|
operator's call. So a proposed wave can still be refused here. That is
|
|
67
81
|
the gate working, not the proposal being wrong — drop tasks from the
|
|
68
82
|
tail of `wave` and re-check.
|
|
83
|
+
- With `--session`, `wave check` admits only live tasks of an ingested
|
|
84
|
+
plan. A plan version whose tasks the log never saw is refused
|
|
85
|
+
`cli.plan-not-ingested`: run `bs plan ingest` on it, then re-check.
|
|
86
|
+
An id with no task row is refused `plan.unknown-task`, and a task
|
|
87
|
+
that is `completed`, `superseded` or `waived` is refused
|
|
88
|
+
`cli.task-not-live`, naming each task and its status. Drop those ids.
|
|
89
|
+
A `failed` or `escalated` task stays admissible: an operator still
|
|
90
|
+
holds it, and the escalation ladder re-admits it. A follow-up
|
|
91
|
+
`findings raise` minted stays admissible while it is live, and a wave
|
|
92
|
+
of follow-ups alone still needs the plan it names ingested first.
|
|
69
93
|
- Never narrow a wave because a narrow one feels safer. A wave of one
|
|
70
94
|
passes every check in this file — one task is disjoint with nothing,
|
|
71
95
|
shares a hotspot with nothing, crosses no import edge — so `valid: true`
|
|
@@ -84,9 +108,9 @@ would cost:
|
|
|
84
108
|
- **Inline**, in this session, when the wave is small enough for this
|
|
85
109
|
window. Read `wave.md` and work it here.
|
|
86
110
|
- **In a session of its own**, when it is not, but you still want to drive
|
|
87
|
-
it yourself: `
|
|
111
|
+
it yourself: `bs session start <wave-id> --continues <session-id>#<n>`,
|
|
88
112
|
where `<n>` is the index of the event that admitted this wave.
|
|
89
|
-
- **Dispatched**, as the **`wave-runner`** agent, when the wave would eat
|
|
113
|
+
- **Dispatched**, as the **`bs-wave-runner`** agent, when the wave would eat
|
|
90
114
|
the window this epic needs to reach its own end. It is the only role
|
|
91
115
|
`factory/policies/delegation.yml` grants `Agent`, and it earns that by
|
|
92
116
|
opening its own log first — so hand it the event id of *your dispatch*,
|
|
@@ -106,12 +130,12 @@ to make (D13, D-266). What it does not buy is a shortcut. A wave session
|
|
|
106
130
|
opened without `--continues` writes into a log nothing here reads, and the
|
|
107
131
|
verbs below then report a wave that appears never to have run rather than
|
|
108
132
|
failing — which is the same silence, arriving as a green. When you dispatched
|
|
109
|
-
the wave rather than ran it, `
|
|
133
|
+
the wave rather than ran it, `bs delegation check <session-id>` is what
|
|
110
134
|
turns that silence into a red: a `wave-runner` that dispatched before opening
|
|
111
135
|
its log, or against the wrong event, is `unverifiable` and exits 1.
|
|
112
136
|
|
|
113
137
|
**Then check that it did.** Once the wave's tasks reach a terminal state,
|
|
114
|
-
`
|
|
138
|
+
`bs wave audit --session <id> --epic <epic>` reads the log back and
|
|
115
139
|
reports the width the wave actually ran at, not the width it was admitted
|
|
116
140
|
at. Ask it with *this* session: it folds the lineage, so it sees the
|
|
117
141
|
dispatches a wave session made under the admission this one wrote. Exit `1`
|
|
@@ -125,7 +149,7 @@ playbooks are written to prevent.
|
|
|
125
149
|
|
|
126
150
|
11. Repeat until every task in the live plan version is `completed`/`waived`,
|
|
127
151
|
or `superseded` by a successor that is itself terminal-OK (recursively —
|
|
128
|
-
a successor chain counts too). Dispatch the **`planner`** again for
|
|
152
|
+
a successor chain counts too). Dispatch the **`bs-planner`** again for
|
|
129
153
|
the epic verdict against acceptance criteria — gaps found → a NEW
|
|
130
154
|
`plan-v(n+1)` with inferred tasks (never a live-graph mutation,
|
|
131
155
|
architecture §12), auto-scheduled at confidence ≥0.8 else parked for an
|
|
@@ -133,7 +157,7 @@ playbooks are written to prevent.
|
|
|
133
157
|
on it**, whichever step cut it:
|
|
134
158
|
|
|
135
159
|
```bash
|
|
136
|
-
|
|
160
|
+
bs plan ingest factory/specs/active/<epic>/plan-v<n+1>.json --project <project-dir> \
|
|
137
161
|
--session <session-id> --plan-version <n+1> --causal-parent <event-id>
|
|
138
162
|
```
|
|
139
163
|
|
|
@@ -148,11 +172,11 @@ playbooks are written to prevent.
|
|
|
148
172
|
branch**. Every gate up to here ran inside a task worktree, so every
|
|
149
173
|
green you have so far is a green about a worktree — the envkit epic
|
|
150
174
|
shipped six green lint gates on a branch whose `pnpm lint` exited 1
|
|
151
|
-
(D-42). Check out `
|
|
175
|
+
(D-42). Check out `bs/<epic>/integration` in the project first (this
|
|
152
176
|
command refuses to move your working tree, and refuses a dirty one):
|
|
153
177
|
|
|
154
178
|
```bash
|
|
155
|
-
|
|
179
|
+
bs integration check --epic <epic> --project <project-dir> \
|
|
156
180
|
--checks <checks.json> \
|
|
157
181
|
--session <session-id> --plan-version <n> --causal-parent <event-id>
|
|
158
182
|
```
|
|
@@ -168,25 +192,35 @@ playbooks are written to prevent.
|
|
|
168
192
|
check, the review and the close all claim to have verified a plan that
|
|
169
193
|
no longer exists. One dogfooded product epic closed at v3 with its
|
|
170
194
|
integration check and its closing spec review both stamped v1; the goal
|
|
171
|
-
check, passed the flag, said v3. Read the version off `
|
|
195
|
+
check, passed the flag, said v3. Read the version off `bs plan ingest`'s receipt and
|
|
172
196
|
pass it every time.
|
|
173
|
-
13. Dispatch the **`spec-reviewer`** again — this time against the code.
|
|
197
|
+
13. Dispatch the **`bs-spec-reviewer`** again — this time against the code.
|
|
174
198
|
The pre-code review at `/bs plan` step 3 read the spec against nothing;
|
|
175
199
|
this one reads it against the assembled branch, which is the only reading
|
|
176
200
|
that can see a criterion the finished code proves wrong. The envkit epic
|
|
177
201
|
deadlocked on exactly that: a correct S2 whose fix criterion 3 mandated
|
|
178
202
|
and criterion 1 forbade (D-33). It writes to a close-specific path so it
|
|
179
|
-
cannot clobber the pre-code artifact
|
|
203
|
+
cannot clobber the pre-code artifact. Put
|
|
204
|
+
`Declared artifact: /abs/path/to/state/results/<epic>.spec-review-close-vN.json`
|
|
205
|
+
inline on its own line in the dispatch prompt (the PreToolUse guard refuses
|
|
206
|
+
a judge dispatch without it); hand that file — each item naming the
|
|
180
207
|
`criterion_ref` it is against — to:
|
|
181
208
|
|
|
182
209
|
```bash
|
|
183
|
-
|
|
210
|
+
bs epic spec-review --epic <epic> --project <project-dir> \
|
|
184
211
|
--plan factory/specs/active/<epic>/plan-vN.json \
|
|
185
212
|
--reviewed-by spec-reviewer \
|
|
186
|
-
|
|
213
|
+
--evidence state/results/<epic>.spec-review-close-vN.json \
|
|
187
214
|
--session <session-id> --plan-version <n> --causal-parent <event-id>
|
|
188
215
|
```
|
|
189
216
|
|
|
217
|
+
`--evidence` is required unless you pass `--no-findings` instead, and
|
|
218
|
+
the two are exclusive: a reviewer that found nothing writes `[]` to that
|
|
219
|
+
path, and `--no-findings` is the operator attesting a review that ran
|
|
220
|
+
outside the factory — recorded as `attested_by: operator`, never read as
|
|
221
|
+
a file. A missing flag is refused (`cli.missing-flag`), because an empty
|
|
222
|
+
review read from an absent file is how a capped reviewer closed clean.
|
|
223
|
+
|
|
190
224
|
Its `dispatch_decision` — and step 14's, and the planner's when it
|
|
191
225
|
renders a verdict — goes against the reserved `<epic>/integration` ref,
|
|
192
226
|
never a `<epic>/spec-review-rN` you coin for the occasion
|
|
@@ -205,12 +239,12 @@ playbooks are written to prevent.
|
|
|
205
239
|
distinguishes them. It
|
|
206
240
|
exits 0 even when it raises findings: what it found blocks the plan, not
|
|
207
241
|
this command. A spec finding is unwaivable at S1/S2 and no task's diff can
|
|
208
|
-
contain the fix, so the answer is `
|
|
242
|
+
contain the fix, so the answer is `bs plan amend --plan … --findings …
|
|
209
243
|
--rationale … --sites …` (§6a of the operator guide). `--sites` is every
|
|
210
244
|
place that shape occurs, not only the file the finding was reported
|
|
211
245
|
against — answer it before writing the changes, because it is the question
|
|
212
246
|
that decides how much the amendment fixes (D-123). It cuts plan v(n+1):
|
|
213
|
-
ingest it (step 11's `
|
|
247
|
+
ingest it (step 11's `bs plan ingest`), go back to step 11 with the new
|
|
214
248
|
version, and re-run this review against the branch that results. Never
|
|
215
249
|
record a spec defect as a coder failure; that is
|
|
216
250
|
the deadlock this step exists to end.
|
|
@@ -221,20 +255,22 @@ playbooks are written to prevent.
|
|
|
221
255
|
did not write. Get the clause list first (read-only, no event):
|
|
222
256
|
|
|
223
257
|
```bash
|
|
224
|
-
|
|
258
|
+
bs epic goal --epic <epic>
|
|
225
259
|
```
|
|
226
260
|
|
|
227
|
-
Hand those clauses and the live plan to a **`spec-reviewer`** session —
|
|
261
|
+
Hand those clauses and the live plan to a **`bs-spec-reviewer`** session —
|
|
228
262
|
a fresh one, never the planner's, and never the same dispatch as step 13:
|
|
229
|
-
`
|
|
263
|
+
`bs dispatch check` refuses to let one dispatch answer for both.
|
|
230
264
|
Dispatch it *after* step 13's record is written, not alongside it — a
|
|
231
265
|
dispatch that predates the previous record has already answered for that
|
|
232
266
|
one, so two sessions fired up front leave this record unaccounted for and
|
|
233
|
-
`
|
|
234
|
-
verdict per clause, in the goal's order, and record it
|
|
267
|
+
`bs dispatch check` reports that record `unverifiable`. Take back one
|
|
268
|
+
verdict per clause, in the goal's order, and record it. Its prompt carries
|
|
269
|
+
`Declared artifact: /abs/path/to/state/results/<epic>.goal-coverage-vN.json`
|
|
270
|
+
inline on its own line, for the same reason:
|
|
235
271
|
|
|
236
272
|
```bash
|
|
237
|
-
|
|
273
|
+
bs epic goal-check --epic <epic> \
|
|
238
274
|
--plan factory/specs/active/<epic>/plan-vN.json \
|
|
239
275
|
--coverage state/results/<epic>.goal-coverage-vN.json \
|
|
240
276
|
--checked-by spec-reviewer \
|
|
@@ -244,8 +280,8 @@ playbooks are written to prevent.
|
|
|
244
280
|
`covered` must name live plan task ids; `out-of-scope` must give a reason,
|
|
245
281
|
and that reason is quoted back to the epic judge. `uncovered` mints an
|
|
246
282
|
S2-major spec finding against the plan file — no task diff can contain
|
|
247
|
-
that fix, so the answer is `
|
|
248
|
-
you back to step 11 — through `
|
|
283
|
+
that fix, so the answer is `bs plan amend`, which cuts v(n+1) and sends
|
|
284
|
+
you back to step 11 — through `bs plan ingest`, as in step 13. The
|
|
249
285
|
command exits 0 even when it raises findings.
|
|
250
286
|
|
|
251
287
|
**It refuses (`cli.no-epic-goal`) when the owning milestone states no
|
|
@@ -260,40 +296,48 @@ playbooks are written to prevent.
|
|
|
260
296
|
integrable at all:
|
|
261
297
|
|
|
262
298
|
```bash
|
|
263
|
-
|
|
299
|
+
bs epic verdict --epic <epic> --project <project-dir> \
|
|
264
300
|
--session <session-id> --plan-version <n> --causal-parent <event-id>
|
|
265
301
|
```
|
|
266
302
|
|
|
267
303
|
Mechanical oracles first: non-terminal tasks, open blocking findings, a
|
|
268
|
-
missing/failed/stale integration-root check, a
|
|
269
|
-
|
|
270
|
-
without spending a judge call.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
304
|
+
missing/failed/stale integration-root check, a closing spec review that's
|
|
305
|
+
stale or missing when the tier required one, or a missing/stale
|
|
306
|
+
spec-vs-goal check return `hold` (exit 1) without spending a judge call.
|
|
307
|
+
A tier that waived the review (step 13: `when-plan-amended` on a plan
|
|
308
|
+
still at v1) is not a hold on that ground — the verdict records the skip
|
|
309
|
+
as a fact instead of staying silent about it, same as step 13 asks. A
|
|
310
|
+
review that IS on record is still walked through every staleness check
|
|
311
|
+
regardless of tier. `--project` is required — the verdict reads the
|
|
312
|
+
integration branch head to decide whether the records from steps 12, 13
|
|
313
|
+
and 14 still cover it. On `hold`, do not open the PR — report the
|
|
314
|
+
`blockers` to the operator and go back to step 11.
|
|
274
315
|
|
|
275
316
|
Once the oracles pass, the judge call is real money when an external
|
|
276
317
|
provider is `active` in `crosscheck.yml`: codex spends the operator's
|
|
277
|
-
ChatGPT quota, DeepSeek spends prepaid credit
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
318
|
+
ChatGPT quota, DeepSeek spends prepaid credit. Say which purse it is to
|
|
319
|
+
the operator before this call, not after.
|
|
320
|
+
|
|
321
|
+
Step 16 no longer pays twice for the same integration head: the
|
|
322
|
+
`quorum-decision` this call writes now carries `integration_head`, and a
|
|
323
|
+
clean `go` against an unchanged head is reused rather than re-asked
|
|
324
|
+
(issue #270). Anything that invalidates it — a new commit, a `hold`, or a
|
|
325
|
+
decision from before `integration_head` existed — still re-runs.
|
|
283
326
|
16. Record the close. The verdict above is a read-only probe and writes
|
|
284
327
|
nothing; `epic close` is what makes it a fact in the log (D-43):
|
|
285
328
|
|
|
286
329
|
```bash
|
|
287
|
-
|
|
330
|
+
bs epic close --epic <epic> --project <project-dir> \
|
|
288
331
|
--session <session-id> --plan-version <n> --causal-parent <event-id>
|
|
289
332
|
```
|
|
290
333
|
|
|
291
|
-
It
|
|
292
|
-
(
|
|
334
|
+
It reuses step 15's `go` decision when the integration head hasn't moved
|
|
335
|
+
(see step 15), otherwise re-runs the verdict, then emits `epic-closed` on
|
|
336
|
+
`go` and refuses (exit 1, no event) on `hold`. **Never pass `--override-rationale`
|
|
293
337
|
yourself** — closing over a hold is the operator's call; ask for it and
|
|
294
338
|
quote the blockers. If the epic was cut by `/bs audit`
|
|
295
339
|
([`audit.md`](audit.md) step 10), follow the close with
|
|
296
|
-
`
|
|
340
|
+
`bs audit resolve <project-dir> --epic <epic> --session <session-id> --causal-parent <event-id> [--specs-dir <dir>]`
|
|
297
341
|
so every finding this plan still claims is marked `fixed` in the
|
|
298
342
|
project's audit store — the rest come back `deferred`, left exactly as
|
|
299
343
|
they were, because the plan scoped them out on purpose. The store, not
|
|
@@ -301,18 +345,106 @@ playbooks are written to prevent.
|
|
|
301
345
|
newest plan from the work root's specs dir by default; when this
|
|
302
346
|
project's plans live elsewhere, pass `--specs-dir` naming the same specs
|
|
303
347
|
dir the epic was run from, or it refuses rather than guess.
|
|
304
|
-
17. Open **one integration PR per epic** with
|
|
305
|
-
|
|
306
|
-
results, reviewer verdict, waivers granted, timeline link. The head is
|
|
307
|
-
`smith/<epic>/integration`. The base is the target repo's `main` unless
|
|
348
|
+
17. Open **one integration PR per epic** with a scribe-written body. The head is
|
|
349
|
+
`bs/<epic>/integration`. The base is the target repo's `main` unless
|
|
308
350
|
the epic was cut from another epic's integration branch, in which case
|
|
309
351
|
the PR stacks on that branch and the operator merges the parent's PR
|
|
310
|
-
first — a child epic cut from `
|
|
352
|
+
first — a child epic cut from `bs/<parent>/integration` opens its PR
|
|
311
353
|
against that branch, behind the parent's PR; once the parent has merged
|
|
312
354
|
and its branch is deleted, GitHub retargets the child to `main`. The
|
|
313
355
|
operator reviews on GitHub; this session never merges to `main`
|
|
314
356
|
(`docs/standards/guardrails.md`).
|
|
315
357
|
|
|
358
|
+
**Build the fact pack first.** The scribe has no `Bash` and a small turn
|
|
359
|
+
cap, so it cannot run `git` or `bs`, and a scribe left to grep raw logs
|
|
360
|
+
caps and fills the gaps by invention — a wrong event id, a merged task
|
|
361
|
+
called dead, "no waivers" over two grants. Compute every fact in your own
|
|
362
|
+
session, from the epic session with `--lineage` so the waves' records
|
|
363
|
+
count. Every fact comes from the log or from git, never from the SQLite
|
|
364
|
+
projection: `stats kanban` and `stats timeline` read a projection that
|
|
365
|
+
can lag the log, and `db rebuild` clears it before it re-reads, so do
|
|
366
|
+
not refresh it for this.
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
# one pass over the log (pass an --n that covers the whole lineage)
|
|
370
|
+
bs event tail <session-id> --lineage --n 100000
|
|
371
|
+
# the fingerprint map: finding_id, task_id and fingerprint of the epic's findings
|
|
372
|
+
bs findings list --session <session-id> --epic <epic>
|
|
373
|
+
# the goal the summary states
|
|
374
|
+
bs epic goal --epic <epic> [--roadmap-path <file>]
|
|
375
|
+
# the branch itself
|
|
376
|
+
git log --oneline <base>..bs/<epic>/integration
|
|
377
|
+
git diff --shortstat <base>...bs/<epic>/integration
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
From the `event tail` pass keep, each with its `event_id`:
|
|
381
|
+
- `waiver-granted` and `waiver-denied` records whose
|
|
382
|
+
`payload.fingerprint` matches one of the epic's findings, mapped to
|
|
383
|
+
that finding's id and task. Match on the stored `fingerprint` that
|
|
384
|
+
`findings list` prints, and drop a decision that matches none: an
|
|
385
|
+
ancestor session can carry an earlier epic's decisions. Grants come
|
|
386
|
+
from here, not from
|
|
387
|
+
`findings list --status`, because a grant only moves a raised or
|
|
388
|
+
confirmed finding to `waived`; an amended or fix-verified one keeps
|
|
389
|
+
its status.
|
|
390
|
+
- `wave-merged` records: `payload.task_ids` and the event id.
|
|
391
|
+
- `epic-closed` from step 16: its event id, `machine_verdict`, and
|
|
392
|
+
`payload.summary.tasks` — each task's `task_status`, read from the log
|
|
393
|
+
at close. A follow-up cleared by closing all its findings (fixed, refuted
|
|
394
|
+
or waived) still reads `todo` there; cross-check it against the findings and never publish it
|
|
395
|
+
as an open task.
|
|
396
|
+
- `audit-resolved`, for an epic cut by `/bs audit`: every record whose
|
|
397
|
+
`payload.epic` is this epic — one epic can resolve more than once, and
|
|
398
|
+
the lineage carries a parent epic's resolve too. List each event id.
|
|
399
|
+
`fixed` and `deferred` are fingerprint arrays: fixed is the union of
|
|
400
|
+
every kept record's `fixed`; deferred is the last record's `deferred`
|
|
401
|
+
minus that union. Write the two counts into the pack yourself.
|
|
402
|
+
- `integration-check` records whose `payload.epic_id` is this epic and
|
|
403
|
+
whose `head_sha` equals the `epic-closed` record's
|
|
404
|
+
`summary.integration.check.head_sha`: each check's `name` and `pass`.
|
|
405
|
+
|
|
406
|
+
`epic goal` reads this repo's roadmap by default; when the epic's
|
|
407
|
+
roadmap lives elsewhere, pass `--roadmap-path` naming it, or the goal
|
|
408
|
+
you hand over is the wrong one. For a UI epic, take the screenshots
|
|
409
|
+
from each task's tester result, `state/results/<task-id>.tester*.json`,
|
|
410
|
+
field `artifacts` (the files sit under `state/artifacts/<task-id>/`);
|
|
411
|
+
[`docs/standards/stack.md`](../../../docs/standards/stack.md) wants
|
|
412
|
+
them on this PR. The pack carries a screenshot only as an image you
|
|
413
|
+
have uploaded or attached — never a local path, which no reviewer can
|
|
414
|
+
open; one you cannot attach stays out.
|
|
415
|
+
|
|
416
|
+
Write only these filtered facts into one pack file — never raw command
|
|
417
|
+
output, which puts the scribe back to grepping logs. Dispatch the scribe with that file as its **only source**, and the
|
|
418
|
+
PR-body scratch file as its write root, under one rule: **omit, never
|
|
419
|
+
infer**. A fact the pack does not hold stays out of the body; a count,
|
|
420
|
+
a status, or an event id is copied from the pack, never worked out. If
|
|
421
|
+
the pack is wrong, rebuild it and dispatch again; do not let the scribe
|
|
422
|
+
reach past it into `state/events/`.
|
|
423
|
+
|
|
424
|
+
The PR body opens with a short plain-language summary, written under
|
|
425
|
+
`.claude/skills/bs/SKILL.md`'s "Talking to the operator" section — cite
|
|
426
|
+
that section for how to write it, do not restate its rule here. In the
|
|
427
|
+
project's own terms, not Blacksmith's: what this epic changed, what is
|
|
428
|
+
still open, and what decision the operator must make, if any. The
|
|
429
|
+
existing fact sections below follow it as the technical part the rule
|
|
430
|
+
asks for.
|
|
431
|
+
|
|
432
|
+
The PR body has this shape and nothing else: the plain-language opening
|
|
433
|
+
above; **Summary** (the epic id
|
|
434
|
+
and its goal, one paragraph); **Tasks** (one line per task: id,
|
|
435
|
+
`task_status`, and its `wave-merged` event id when it has one);
|
|
436
|
+
**Waivers** (granted and denied, each with its finding id and event id,
|
|
437
|
+
or the word "none" only when both lists in the pack are empty);
|
|
438
|
+
**Verification** (the verdict outcome, the `epic-closed` event id, the
|
|
439
|
+
`integration-check` results, the `audit-resolved` event ids and the
|
|
440
|
+
fixed and deferred counts when there are any, the shortstat, and the
|
|
441
|
+
commit count from the log);
|
|
442
|
+
**Screenshots** (only when the pack carries them); **Timeline** (the
|
|
443
|
+
dashboard link, when you put one in the pack). The scribe's 300-word
|
|
444
|
+
cap binds the prose — Summary and the sentences around the lists; the
|
|
445
|
+
Tasks, Waivers and check lists are artifacts and are never cut to fit
|
|
446
|
+
it, since a dropped line reads as a task or waiver that was not there.
|
|
447
|
+
|
|
316
448
|
Before the first push, read the authorship the branch is about to make
|
|
317
449
|
public — `git log --format=%ae <base>..HEAD | sort -u` — and stop on any
|
|
318
450
|
address that is not a noreply one; a coder's worktree commit carries
|
|
@@ -324,7 +456,7 @@ playbooks are written to prevent.
|
|
|
324
456
|
Append it by hand, under the reserved ref and the live plan version:
|
|
325
457
|
|
|
326
458
|
```bash
|
|
327
|
-
|
|
459
|
+
bs event append '{"session_id":"<session-id>","actor":"orchestrator","event_type":"integration-pr-opened","task_id":"<epic>/integration","plan_version":<n>,"causal_parent":"<event-id>","payload":{"step":17,"pr_url":"<url>","pr_number":<n>,"repo":"<owner>/<repo>","base_ref":"<base>","head_ref":"bs/<epic>/integration","head_sha":"<sha>","base_sha":"<sha>","commits":<n>,"changed_files":<n>,"additions":<n>,"deletions":<n>}}'
|
|
328
460
|
```
|
|
329
461
|
|
|
330
462
|
The receipt says whether the timeline reads the type; it does, and it
|