@juzser/blacksmith 0.3.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} +8 -5
- package/.claude/agents/{coder.md → bs-coder.md} +8 -7
- package/.claude/agents/{grader.md → bs-grader.md} +16 -9
- 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} +16 -5
- package/.claude/agents/{scribe.md → bs-scribe.md} +11 -2
- package/.claude/agents/{security-reviewer.md → bs-security-reviewer.md} +9 -6
- package/.claude/agents/{spec-reviewer.md → bs-spec-reviewer.md} +18 -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} +7 -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 +45 -31
- package/.claude/skills/bs/dispatch.md +133 -47
- 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 +57 -16
- package/.claude/skills/bs/report.md +11 -11
- package/.claude/skills/bs/run.md +190 -52
- 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 +143 -50
- 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 +70 -13
- package/factory/orchestrator/dist/artifacts.js +31 -0
- package/factory/orchestrator/dist/attribution.js +4 -0
- package/factory/orchestrator/dist/audit.js +245 -20
- package/factory/orchestrator/dist/autonomy.js +6 -2
- 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 +1087 -116
- package/factory/orchestrator/dist/cliName.js +27 -0
- package/factory/orchestrator/dist/crossFinding.js +20 -0
- package/factory/orchestrator/dist/crosscheck.js +136 -8
- package/factory/orchestrator/dist/daemon.js +352 -67
- package/factory/orchestrator/dist/db/projector.js +327 -54
- 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 +108 -0
- 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 +494 -42
- package/factory/orchestrator/dist/epicBudget.js +93 -0
- package/factory/orchestrator/dist/epicWidth.js +22 -5
- package/factory/orchestrator/dist/errorIssues.js +182 -11
- package/factory/orchestrator/dist/escalation.js +2 -2
- package/factory/orchestrator/dist/events.js +164 -14
- package/factory/orchestrator/dist/feedback.js +169 -0
- package/factory/orchestrator/dist/findingContext.js +26 -0
- package/factory/orchestrator/dist/findings.js +108 -14
- package/factory/orchestrator/dist/gate.js +120 -10
- package/factory/orchestrator/dist/gh.js +19 -2
- package/factory/orchestrator/dist/git.js +20 -2
- package/factory/orchestrator/dist/goalCheck.js +2 -2
- package/factory/orchestrator/dist/harness.js +25 -17
- package/factory/orchestrator/dist/hookDecision.js +411 -39
- package/factory/orchestrator/dist/integration.js +20 -8
- package/factory/orchestrator/dist/issueReporter.js +81 -16
- package/factory/orchestrator/dist/judgePreflight.js +25 -4
- package/factory/orchestrator/dist/judgeRoles.js +47 -0
- package/factory/orchestrator/dist/judgeStopHook.js +239 -0
- package/factory/orchestrator/dist/judges.js +419 -21
- package/factory/orchestrator/dist/lessons.js +190 -11
- package/factory/orchestrator/dist/logCache.js +291 -0
- package/factory/orchestrator/dist/mcp.js +6 -6
- package/factory/orchestrator/dist/paths.js +20 -7
- package/factory/orchestrator/dist/plan.js +399 -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/projects.js +12 -1
- 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 +471 -30
- 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/scheduler.js +3 -3
- package/factory/orchestrator/dist/schemas.js +56 -8
- package/factory/orchestrator/dist/severity.js +8 -4
- package/factory/orchestrator/dist/spec.js +246 -12
- 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 +192 -31
- package/factory/orchestrator/dist/taskStatus.js +14 -0
- package/factory/orchestrator/dist/taxonomy.js +11 -0
- package/factory/orchestrator/dist/testerAudit.js +31 -12
- package/factory/orchestrator/dist/testgate.js +20 -16
- package/factory/orchestrator/dist/uiuxGate.js +83 -0
- package/factory/orchestrator/dist/usage.js +113 -48
- package/factory/orchestrator/dist/waivers.js +99 -12
- package/factory/orchestrator/dist/waveBudget.js +2 -0
- package/factory/orchestrator/dist/waveConcurrency.js +143 -7
- package/factory/orchestrator/dist/waveSchedule.js +84 -0
- package/factory/orchestrator/dist/workroot.js +1 -1
- package/factory/orchestrator/dist/worktree.js +76 -21
- 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 +27 -3
- 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
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
# provider does not fail loudly; it spends a doomed call on every quorum
|
|
15
15
|
# trigger, has it caught, and leaves a failure row that reads like an outage.
|
|
16
16
|
# So turn on the one you actually have — a one-line edit, runbook §2, and
|
|
17
|
-
# `
|
|
17
|
+
# `bs judge preflight` says beforehand whether it will work.
|
|
18
18
|
# Full setup/calibration/promotion procedure: docs/runbooks/providers.md.
|
|
19
19
|
#
|
|
20
20
|
# Shadow mode (Phase 8 design decision): `mode: shadow` means a provider's
|
|
21
|
-
# verdicts are RECORDED (judge-verdict events, `
|
|
21
|
+
# verdicts are RECORDED (judge-verdict events, `bs stats providers`) but
|
|
22
22
|
# have ZERO gating power — quorum.ts falls back to the native verdict alone
|
|
23
23
|
# whenever no provider in a case is `mode: active`. Flipping a provider to
|
|
24
24
|
# `mode: active` in this file (an operator edit, never a runtime write) is
|
|
@@ -48,13 +48,21 @@ providers:
|
|
|
48
48
|
# extractor generations diverge exactly as D-118 claimed: first-parseable
|
|
49
49
|
# returns `[]`, first-validating returns the verdict. If you change these
|
|
50
50
|
# args, re-run that comparison rather than reasoning about it.
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
#
|
|
52
|
+
# Model and effort are pinned here, not inherited. Without `-m` the judge
|
|
53
|
+
# runs whatever `~/.codex/config.toml` defaults to — an interactive-use
|
|
54
|
+
# choice, often the frontier model at high effort — so a confirm/refute
|
|
55
|
+
# call billed at `model_tier: mid` spent frontier quota. `model` below must
|
|
56
|
+
# name the same id as `-m`: it is what the event log records (without it a
|
|
57
|
+
# cli judge is logged as `codex:default`), and nothing checks the two agree.
|
|
58
|
+
args: ["exec", "--color", "never", "-m", "gpt-6-sol", "-c", "model_reasoning_effort=\"medium\""]
|
|
59
|
+
model: gpt-6-sol
|
|
60
|
+
model_tier: mid # taxonomy.yml model_tier — judge tier, architecture §4
|
|
53
61
|
# PRECONDITION: `codex` on PATH, and `codex login` run on every machine
|
|
54
62
|
# that dispatches a quorum trigger. Without either the CLI transport still
|
|
55
63
|
# spawns, fails, and quorum.ts records a provider error per trigger —
|
|
56
64
|
# caught, so nothing gates on it, but it is latency and noise.
|
|
57
|
-
# `
|
|
65
|
+
# `bs judge preflight` checks the first half locally; only a real call
|
|
58
66
|
# can check the second.
|
|
59
67
|
# `auto`, not `true`. This is the one field in the file that describes a
|
|
60
68
|
# MACHINE, and the file is checked in, so `true` here would be a claim
|
|
@@ -69,7 +77,7 @@ providers:
|
|
|
69
77
|
# session still spends a call per trigger and records the failure.
|
|
70
78
|
#
|
|
71
79
|
# Turned on for THIS box, 2026-09-02, by the operator who owns it: `codex`
|
|
72
|
-
# resolves on PATH and `codex login` is done, both checked by `
|
|
80
|
+
# resolves on PATH and `codex login` is done, both checked by `bs judge
|
|
73
81
|
# preflight` and by a real `codex exec` call. Rollback for one box is
|
|
74
82
|
# `enabled: false` here, which `auto` never overrides.
|
|
75
83
|
enabled: auto
|
|
@@ -89,11 +97,30 @@ providers:
|
|
|
89
97
|
# is make this box gate the moment one is enabled, with no second edit
|
|
90
98
|
# and no second decision to remember. Rollback is `mode: shadow` here.
|
|
91
99
|
mode: active
|
|
100
|
+
# OpenRouter substitution (operator decision 1a, docs/runbooks/providers.md
|
|
101
|
+
# §9): when `codex` is missing from PATH or not logged in, and
|
|
102
|
+
# OPENROUTER_API_KEY is set, this provider runs through OpenRouter
|
|
103
|
+
# instead — same name, same mode, same gating power, only the transport
|
|
104
|
+
# and model underneath change. `openai/gpt-6-sol` is an EXACT catalog
|
|
105
|
+
# match (`curl -s https://openrouter.ai/api/v1/models`, checked
|
|
106
|
+
# 2026-09-30) for the id `-m gpt-6-sol` pins above: codex substitutes as
|
|
107
|
+
# literally the same model, not an approximation. No
|
|
108
|
+
# response_format_json_object override: the catalog entry lists
|
|
109
|
+
# `response_format` among its supported parameters, so the default
|
|
110
|
+
# (true) applies.
|
|
111
|
+
openrouter_fallback:
|
|
112
|
+
model: openai/gpt-6-sol
|
|
92
113
|
deepseek:
|
|
93
114
|
kind: api
|
|
94
115
|
transport: api
|
|
95
116
|
base_url: https://api.deepseek.com
|
|
96
|
-
|
|
117
|
+
# `deepseek-reasoner` retired from DeepSeek's own `/models` listing
|
|
118
|
+
# (live check of `/models`, 2026-09-30): a call naming it is now silently
|
|
119
|
+
# answered by `deepseek-flash` instead of erroring, so the pin below
|
|
120
|
+
# matters -- a stale model id here fails open, not closed.
|
|
121
|
+
# `deepseek-v4-pro` is DeepSeek's current reasoning-tier model, the
|
|
122
|
+
# direct-API successor to the retired `deepseek-reasoner`.
|
|
123
|
+
model: deepseek-v4-pro
|
|
97
124
|
response_format_json_object: true
|
|
98
125
|
api_key_env: DEEPSEEK_API_KEY
|
|
99
126
|
model_tier: mid
|
|
@@ -103,7 +130,7 @@ providers:
|
|
|
103
130
|
# Without it api-transport.ts throws `Environment variable "DEEPSEEK_API_KEY"
|
|
104
131
|
# is not set` on every quorum trigger; quorum.ts catches it, so the gate
|
|
105
132
|
# holds on the native verdict alone, but each trigger records a provider
|
|
106
|
-
# error. `
|
|
133
|
+
# error. `bs judge preflight` reports the name it looked for and never
|
|
107
134
|
# the value it found, so it is safe to run anywhere.
|
|
108
135
|
#
|
|
109
136
|
# `auto`, not `true`, for the same reason codex is: this file is checked in
|
|
@@ -123,6 +150,17 @@ providers:
|
|
|
123
150
|
# two dogfooded product epics (docs/runbooks/providers.md §3).
|
|
124
151
|
# Rollback is `mode: shadow` here; nothing else remembers the promotion.
|
|
125
152
|
mode: active
|
|
153
|
+
# OpenRouter substitution (operator decision 1a): when DEEPSEEK_API_KEY
|
|
154
|
+
# is missing and OPENROUTER_API_KEY is set, this provider runs through
|
|
155
|
+
# OpenRouter instead. `deepseek/deepseek-v4-pro` is an EXACT catalog
|
|
156
|
+
# match (`curl -s https://openrouter.ai/api/v1/models`, checked
|
|
157
|
+
# 2026-09-30) for the id pinned above: the fallback substitutes as
|
|
158
|
+
# literally the same model, not an approximation, same as the codex
|
|
159
|
+
# substitution above. No response_format_json_object override: the
|
|
160
|
+
# catalog entry lists `response_format` among its supported parameters,
|
|
161
|
+
# same as the direct-API entry above, so the default (true) applies.
|
|
162
|
+
openrouter_fallback:
|
|
163
|
+
model: deepseek/deepseek-v4-pro
|
|
126
164
|
|
|
127
165
|
quorum_triggers:
|
|
128
166
|
# architecture §6, agent-constraints.md "cross-check (phase 8)" — all four,
|
|
@@ -195,7 +233,7 @@ quorum_rule:
|
|
|
195
233
|
# deciding with two opinions in front of them rather than one — which is the
|
|
196
234
|
# whole point of the file — not an automatic override.
|
|
197
235
|
#
|
|
198
|
-
# It silences one advisory in `
|
|
236
|
+
# It silences one advisory in `bs judge preflight` and nothing else. A
|
|
199
237
|
# provider enabled where it cannot be called is still a problem, and
|
|
200
238
|
# `gating.canDecide` still reports false, because it is false.
|
|
201
239
|
accept_non_gating_actives: true
|
|
@@ -204,7 +242,7 @@ asymmetric_roles:
|
|
|
204
242
|
finder_ne_critic: true
|
|
205
243
|
critic_mandate: refute, not confirm
|
|
206
244
|
# The machine-readable form of finder_ne_critic (P9-23). Each pair says
|
|
207
|
-
# "this critic must not run on that finder's own model"; `
|
|
245
|
+
# "this critic must not run on that finder's own model"; `bs dispatch
|
|
208
246
|
# check <session>` asserts it against the event log after the fact, using
|
|
209
247
|
# the `model` field every dispatch_decision now carries. Without this list
|
|
210
248
|
# the rule was unenforceable prose: it named no roles.
|
|
@@ -229,13 +267,13 @@ role_isolation:
|
|
|
229
267
|
#
|
|
230
268
|
# The only evidence of a separate turn the event log can hold is a separate
|
|
231
269
|
# `dispatch_decision`, written by the node that dispatched, never by an agent
|
|
232
|
-
# about itself. `
|
|
270
|
+
# about itself. `bs tester check <session>` asserts that against the log
|
|
233
271
|
# after the fact, per `testgate-result`.
|
|
234
272
|
#
|
|
235
273
|
# That reading survives delegation.yml granting `Agent` because of what the
|
|
236
274
|
# grant costs: a grantee must open its own session first, so its dispatches
|
|
237
275
|
# are its own log's, and no grant may hand a role its own auditor from the
|
|
238
|
-
# `pairs` below. `
|
|
276
|
+
# `pairs` below. `bs delegation check` enforces both, which is what keeps
|
|
239
277
|
# a widened grant from quietly disarming this file.
|
|
240
278
|
#
|
|
241
279
|
# One entry, and it is meant to stay one until a second role starts grading
|
|
@@ -289,7 +327,7 @@ independent_finder:
|
|
|
289
327
|
# summary and the failure scenario and never the source. A finder cannot: it
|
|
290
328
|
# has nothing to read but the diff. Shipping worktree source to a third-party
|
|
291
329
|
# API is a decision no code in this repo has standing to make quietly, so it
|
|
292
|
-
# is a switch, it ships false, and `
|
|
330
|
+
# is a switch, it ships false, and `bs crossfind run` REFUSES rather than
|
|
293
331
|
# falling back to a diffless "find bugs" prompt that would invent findings.
|
|
294
332
|
send_diff: false
|
|
295
333
|
max_diff_bytes: 120000 # refuse rather than truncate: half a diff produces confident findings about code that is not there
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
# event log for what it dispatches" (docs/standards/agent-constraints.md).
|
|
10
10
|
# Until D13 step 3 that was enforced by granting `Agent` to nobody, which also
|
|
11
11
|
# capped an epic at one operator session. A grantee that opens its own session
|
|
12
|
-
# with `
|
|
12
|
+
# with `bs session start <id> --continues <dispatch-event-id>` is a real
|
|
13
13
|
# dispatching node with a real log, so the cap can lift without the rule
|
|
14
14
|
# bending.
|
|
15
15
|
#
|
|
16
|
-
# What a grant may not do — asserted by `
|
|
16
|
+
# What a grant may not do — asserted by `bs delegation check` and by
|
|
17
17
|
# delegation.test.ts against the shipped files, so a widened grant fails CI:
|
|
18
18
|
#
|
|
19
19
|
# - dispatch itself (a role that dispatches itself writes dispatches about
|
|
20
|
-
# itself, and `
|
|
20
|
+
# itself, and `bs tester check` reads a second dispatch as proof of a
|
|
21
21
|
# second turn),
|
|
22
22
|
# - dispatch its own auditor from crosscheck.yml `role_isolation.pairs`
|
|
23
23
|
# (a coder that picks and prompts its own tester grades itself), or
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# written for: a decision made fresh every time is a decision made differently
|
|
8
8
|
# every time. So the tiers are declared here and asked for, never recalled.
|
|
9
9
|
#
|
|
10
|
-
# HOST: `
|
|
10
|
+
# HOST: `bs effort show --plan <plan.json>` reads this file plus the plan's
|
|
11
11
|
# own `effort` field and returns the profile for that epic
|
|
12
12
|
# (factory/orchestrator/src/effort.ts). `.claude/skills/bs/plan.md` and
|
|
13
13
|
# `run.md` run that verb at the top of `/bs plan` and `/bs run` and obey the
|
|
@@ -19,6 +19,14 @@
|
|
|
19
19
|
# `effort_scaling:` block is the prose sibling of this file — it says fan-out
|
|
20
20
|
# is a wall-clock optimisation; this says how much judgment each epic buys.
|
|
21
21
|
#
|
|
22
|
+
# Budgets follow the same tier (2026-09-29): `budgets.yml` sizes the epic cap
|
|
23
|
+
# and every per-task cap for small / medium / huge, and each budget reader
|
|
24
|
+
# takes the tier the epic runs at — the plan's `effort`, else `default_tier`
|
|
25
|
+
# below, raised to `security_floor` when the floor applies. That is
|
|
26
|
+
# a size, not a skipped step — the budgets still report and alarm at every
|
|
27
|
+
# tier. Agent `maxTurns` is not tiered: one ceiling per template, sized for
|
|
28
|
+
# `huge`.
|
|
29
|
+
#
|
|
22
30
|
# THE INVARIANT THAT MAKES THIS SAFE: a tier scales judgment steps only. It
|
|
23
31
|
# never touches a mechanical oracle or a guardrail — see `invariants:` at the
|
|
24
32
|
# bottom, which the host returns alongside every profile so the list cannot be
|
|
@@ -61,7 +69,7 @@ tiers:
|
|
|
61
69
|
pre_code_uiux: when-ui-criterion
|
|
62
70
|
# /bs plan steps 3-4 — planner <-> spec-reviewer until nothing S1/S2 is left.
|
|
63
71
|
spec_review_rounds: until-clean
|
|
64
|
-
# /bs plan step 4 — `
|
|
72
|
+
# /bs plan step 4 — `bs plan quorum` before operator sign-off.
|
|
65
73
|
plan_quorum: always
|
|
66
74
|
# /bs run step 6 — the grader's bounded rubric loop (agent-constraints.md
|
|
67
75
|
# caps it at 2; a tier may lower that number, never raise it).
|
|
@@ -120,22 +128,22 @@ tiers:
|
|
|
120
128
|
|
|
121
129
|
# ── What no tier may touch ──────────────────────────────────────────
|
|
122
130
|
#
|
|
123
|
-
# Returned verbatim by `
|
|
131
|
+
# Returned verbatim by `bs effort show` next to every profile. These are
|
|
124
132
|
# mechanical oracles and guardrails, not judgments: their cost is a command
|
|
125
133
|
# exiting, not an agent thinking, so scaling them saves nothing and buys
|
|
126
134
|
# nothing but a weaker claim about the result.
|
|
127
135
|
invariants:
|
|
128
136
|
- the gate pipeline — schema check, grader verdict, tests, coverage
|
|
129
|
-
evidence, findings intake, severity decision (`
|
|
137
|
+
evidence, findings intake, severity decision (`bs gate run`)
|
|
130
138
|
- the root-level integration check on the assembled branch
|
|
131
|
-
(`
|
|
132
|
-
- claim disjointness and worktree isolation (`
|
|
133
|
-
`
|
|
139
|
+
(`bs integration check`)
|
|
140
|
+
- claim disjointness and worktree isolation (`bs wave check`,
|
|
141
|
+
`bs worktree create/fingerprint/verify`)
|
|
134
142
|
- the security-reviewer's conditional dispatch
|
|
135
|
-
(`
|
|
143
|
+
(`bs security triggers`) — sensitive-paths.yml decides it, not a tier
|
|
136
144
|
- the operator's plan sign-off, which no tier may skip or infer
|
|
137
|
-
- the epic-final verdict and its mechanical holds (`
|
|
138
|
-
`
|
|
145
|
+
- the epic-final verdict and its mechanical holds (`bs epic verdict`,
|
|
146
|
+
`bs epic close`)
|
|
139
147
|
- the event log — every dispatch is still a `dispatch_decision` with a
|
|
140
148
|
causal parent, at every tier
|
|
141
149
|
- the escalation ladder after a blocked round (budgets.yml
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Blacksmith — guardrail enforcement policy
|
|
2
2
|
#
|
|
3
3
|
# docs/standards/guardrails.md is the contract; this file is the data half of
|
|
4
|
-
# what enforces it. HOST: `
|
|
4
|
+
# what enforces it. HOST: `bs policy check`/`bs policy hook`
|
|
5
5
|
# (factory/orchestrator/src/policy.ts), and — via `dist/policyHook.js` —
|
|
6
6
|
# `.claude/hooks/guard.sh`, the PreToolUse gate on every guarded tool call
|
|
7
7
|
# an agent session makes.
|
|
@@ -36,9 +36,11 @@ protected_branches:
|
|
|
36
36
|
# history-rewrite rule only (rule 5) — worktree.yml's
|
|
37
37
|
# `integration_branch.pattern`: a leaf ref "smith/<epic>" cannot coexist
|
|
38
38
|
# with "smith/<epic>/<task-id>" refs in real git (D/F ref conflict), so the
|
|
39
|
-
# shape is "smith/<epic>/integration", never a bare "smith/<epic>".
|
|
39
|
+
# shape is "smith/<epic>/integration", never a bare "smith/<epic>". Both
|
|
40
|
+
# prefixes are listed (bs-rename, operator decision 2/3): new epics
|
|
41
|
+
# integrate on bs/, but one already under way on smith/ stays there.
|
|
40
42
|
names: [main, master]
|
|
41
|
-
patterns: ["smith/*/integration"]
|
|
43
|
+
patterns: ["bs/*/integration", "smith/*/integration"]
|
|
42
44
|
|
|
43
45
|
catch_up_remotes:
|
|
44
46
|
# rule 3's one exception: the remotes a protected branch is allowed to
|
|
@@ -123,7 +125,7 @@ rules:
|
|
|
123
125
|
# ---------------------------------------------------------------------------
|
|
124
126
|
#
|
|
125
127
|
# Everything above applies to every agent session. This block applies to one
|
|
126
|
-
# additional condition: a `
|
|
128
|
+
# additional condition: a `bs sandbox open` lease is active over the
|
|
127
129
|
# directory the command will run in (factory/orchestrator/src/sandbox.ts).
|
|
128
130
|
# The orchestrator opens a lease before handing a worktree to one of the six
|
|
129
131
|
# read-only judge roles and closes it after.
|
|
@@ -141,7 +143,7 @@ rules:
|
|
|
141
143
|
#
|
|
142
144
|
# What it is not: a container, a seccomp profile, or a read-only mount. A
|
|
143
145
|
# command that writes through an interpreter (`python3 -c "open(...,'w')"`)
|
|
144
|
-
# is invisible to a matcher, and always will be. `
|
|
146
|
+
# is invisible to a matcher, and always will be. `bs worktree verify`
|
|
145
147
|
# stays in the pipeline behind this for exactly that reason. Both halves are
|
|
146
148
|
# stated in docs/standards/guardrails.md; neither is sold as the other.
|
|
147
149
|
#
|
|
@@ -157,7 +159,7 @@ judge_sandbox:
|
|
|
157
159
|
# `Edit`/`Write` (.claude/agents/*.md). `researcher` is deliberately absent
|
|
158
160
|
# — fetching is its job, and it is never leased. A lease is matched to a
|
|
159
161
|
# rule set by role, and a role named in neither list falls back to *this*
|
|
160
|
-
# one, so the list is the vocabulary `
|
|
162
|
+
# one, so the list is the vocabulary `bs sandbox open --role` validates
|
|
161
163
|
# against rather than a gate of its own.
|
|
162
164
|
roles: [reviewer, verifier, spec-reviewer, security-reviewer, grader, uiux]
|
|
163
165
|
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
# architecture §19 "Worker harness port". A *provider* is the model vendor a
|
|
4
4
|
# judge's verdict comes from (crosscheck.yml); a *harness* is the program
|
|
5
5
|
# that holds a worker turn — gives the agent its tools, its working directory,
|
|
6
|
-
# its turn limit. HOST: `
|
|
6
|
+
# its turn limit. HOST: `bs harness list` / `bs harness plan`
|
|
7
7
|
# (factory/orchestrator/src/harness.ts), which read this file when `--policy`
|
|
8
|
-
# names no other. `
|
|
9
|
-
# (§18 rule 3); `
|
|
8
|
+
# names no other. `bs` renders an invocation from it and never starts one
|
|
9
|
+
# (§18 rule 3); `bs-run` (src/run-cli.ts) is the separate binary that does.
|
|
10
10
|
#
|
|
11
11
|
# Shape, per harness:
|
|
12
12
|
# kind `in-process` — the Claude Code Agent tool, no program started
|
|
13
|
-
# (`command`/`args` unused); `cli` — a program `
|
|
13
|
+
# (`command`/`args` unused); `cli` — a program `bs-run` spawns
|
|
14
14
|
# with the rendered prompt on stdin.
|
|
15
15
|
# roles taxonomy roles this harness serves; empty = every role that
|
|
16
16
|
# ships a `.claude/agents/<role>.md`.
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
# when this is empty). Rule 6's fingerprint runs regardless.
|
|
26
26
|
# schema_args appended only when the turn names a schema (`--schema`), so a
|
|
27
27
|
# turn that validates nothing renders without one.
|
|
28
|
-
# output how
|
|
28
|
+
# output how bs-run reads the program's output: `text` (default),
|
|
29
29
|
# `codex-json` (the `codex exec --json` JSONL stream),
|
|
30
30
|
# `claude-json` (the `claude -p --output-format json` object).
|
|
31
31
|
# models tier → model id for `{model}`; tiers are taxonomy.yml
|
|
@@ -81,8 +81,8 @@ select on. Each names its own bullet, validated against `taxonomy.yml`:
|
|
|
81
81
|
At dispatch, an `agent-role` entry reaches only the role its `agent_role`
|
|
82
82
|
names, and a `case-type` entry only a task whose `case` its `case_type`
|
|
83
83
|
names. An entry in one of those scopes with **no** selector reaches NOBODY —
|
|
84
|
-
it is inert, not universal, and `
|
|
85
|
-
such. `
|
|
84
|
+
it is inert, not universal, and `bs lessons for-dispatch` reports it as
|
|
85
|
+
such. `bs lessons raise` refuses to mint one; the entries that predate
|
|
86
86
|
the selector (D-129) are the only ones that can still be in that state.
|
|
87
87
|
|
|
88
88
|
Two kinds of entry are therefore injected at dispatch and still never
|
|
@@ -124,6 +124,26 @@ nothing.
|
|
|
124
124
|
- agent_role: planner
|
|
125
125
|
- statement: An acceptance criterion that probes a script running under 'set -e' must name the outer exit status it expects, never an echo the script prints afterwards: errexit ends the script at the first failing command, so a line printed after it is unreachable and the grader can only mark the wording, not the property.
|
|
126
126
|
|
|
127
|
+
### lesson-raised-3aaf982e84ac: A file-length delta criterion must state whether the doc comments att...
|
|
128
|
+
|
|
129
|
+
- lesson_id: lesson-raised-3aaf982e84ac
|
|
130
|
+
- finding_category: correctness
|
|
131
|
+
- agent_role: planner
|
|
132
|
+
- statement: A file-length delta criterion must state whether the doc comments attached to the moved symbols move with them, and its window must be calibrated on that same choice; a window measured with comments included and silent about it fails a coder who leaves the comments behind.
|
|
133
|
+
|
|
134
|
+
### lesson-raised-d478f9d6ea0b: Name an extraction task's scope as a symbol list, not a line range, a...
|
|
135
|
+
|
|
136
|
+
- lesson_id: lesson-raised-d478f9d6ea0b
|
|
137
|
+
- finding_category: correctness
|
|
138
|
+
- agent_role: planner
|
|
139
|
+
- statement: Name an extraction task's scope as a symbol list, not a line range, and derive its length window from the symbols that move; a window calibrated on a span that is wider than the enumerated symbols rewards the over-broad move and rejects the correct one, and a text-preserving destructure hides the difference from every other criterion.
|
|
140
|
+
|
|
141
|
+
### bs-audit-3-scribe-cites-event-ids: A PR body or timeline summary cites events by event id (<session>#<n>...
|
|
142
|
+
|
|
143
|
+
- lesson_id: bs-audit-3-scribe-cites-event-ids
|
|
144
|
+
- agent_role: scribe
|
|
145
|
+
- statement: A PR body or timeline summary cites events by event id (<session>#<n>, where n is the zero-based line index of the log), never by a line number of the log file, and states no number the event log does not carry: coverage percentages, turn caps, round reasons and provider counts included. The orchestrator checks every cited id against the log before the body is published.
|
|
146
|
+
|
|
127
147
|
## claim-path
|
|
128
148
|
|
|
129
149
|
### lesson-raised-3b5746704cfc: A function that computes a filesystem path and hands it to a child pr...
|
|
@@ -654,6 +674,37 @@ _(none yet)_
|
|
|
654
674
|
- lesson_id: lesson-raised-3a400ca69b5e
|
|
655
675
|
- statement: When two verbs are compared for cost, check when each one runs before concluding: the cheaper one may run after the very gate it was meant to save.
|
|
656
676
|
|
|
677
|
+
### lesson-raised-44a58c2a7c7a: When checking a length-delta criterion, classify every line in the mo...
|
|
678
|
+
|
|
679
|
+
- lesson_id: lesson-raised-44a58c2a7c7a
|
|
680
|
+
- finding_category: correctness
|
|
681
|
+
- statement: When checking a length-delta criterion, classify every line in the moved region as code, comment or blank and count them; never derive a line count by subtracting line numbers, because the span between two anchors includes whatever else lives there.
|
|
682
|
+
|
|
683
|
+
### lesson-raised-394329488a2d: SMITH_EPIC_CAP_TOKENS in the gitignored .env overrides the epic cap i...
|
|
684
|
+
|
|
685
|
+
- lesson_id: lesson-raised-394329488a2d
|
|
686
|
+
- statement: SMITH_EPIC_CAP_TOKENS in the gitignored .env overrides the epic cap in budgets.yml, so the committed cap is not the enforced one; read budget alarm's capTokens and budgetEnvOverrides for the live cap, never budgets.yml.
|
|
687
|
+
|
|
688
|
+
### lesson-raised-add2171a83a1: On a plan whose tasks are all origin user, the plan-quorum triggers a...
|
|
689
|
+
|
|
690
|
+
- lesson_id: lesson-raised-add2171a83a1
|
|
691
|
+
- statement: On a plan whose tasks are all origin user, the plan-quorum triggers are mechanically silent - trigger 1 sums declared budgets, not measured spend, and trigger 3's per-task arm only reads non-user origins - so the only live trigger is the orchestrator's own --confidence self-report; report it honestly below 0.8 when the draft needed repair rounds.
|
|
692
|
+
|
|
693
|
+
### lesson-raised-be27b49f1d19: budget alarm reports unverifiable when dispatches for roles without a...
|
|
694
|
+
|
|
695
|
+
- lesson_id: lesson-raised-be27b49f1d19
|
|
696
|
+
- statement: budget alarm reports unverifiable when dispatches for roles without an attribution path (auditor, security-reviewer) are in the log, and the planner role has no per-role cap, so a planner overrun is only visible against the epic cap.
|
|
697
|
+
|
|
698
|
+
### bs-audit-3-gate-timeout-under-load: Size a test-gate check's timeout for a loaded machine, not a quiet on...
|
|
699
|
+
|
|
700
|
+
- lesson_id: bs-audit-3-gate-timeout-under-load
|
|
701
|
+
- statement: Size a test-gate check's timeout for a loaded machine, not a quiet one: a suite that runs in about 200 s bare can be killed at a 300 s default with no output while another build shares the CPUs. When a check dies at its timeout with no test output, read machine load before blaming the code, log it as an env failure, and raise that check's timeout_ms through the per-check override; never drop or narrow the check to get it under the limit.
|
|
702
|
+
|
|
703
|
+
### lesson-dream-vam-audit-7-2026-09-28-135: Every judge or worker dispatch brief names the JSON Schema its result...
|
|
704
|
+
|
|
705
|
+
- lesson_id: lesson-dream-vam-audit-7-2026-09-28-135
|
|
706
|
+
- statement: Every judge or worker dispatch brief names the JSON Schema its result file must satisfy: the full result envelope (task_id, agent, provider, model_tier, token_usage), the verdict at .structured_output, and the schema's own keys; the orchestrator schema-checks the file as soon as the agent returns, before gate run.
|
|
707
|
+
|
|
657
708
|
## security
|
|
658
709
|
|
|
659
710
|
_(none yet)_
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Blacksmith — scheduler policy
|
|
2
2
|
#
|
|
3
3
|
# Knobs for `factory/orchestrator/src/scheduler.ts` (architecture §12
|
|
4
|
-
# "Recheck scheduling" + "Scheduled growth passes"; `
|
|
4
|
+
# "Recheck scheduling" + "Scheduled growth passes"; `bs scheduler run`).
|
|
5
5
|
# A deterministic pass over the event log that only ever emits PROPOSAL
|
|
6
6
|
# events — it never dispatches an agent or widens scope on its own.
|
|
7
7
|
|
|
@@ -50,7 +50,7 @@ lessons:
|
|
|
50
50
|
autonomy:
|
|
51
51
|
# Who says yes to what this pass proposes. The scheduler decides WHAT is
|
|
52
52
|
# due; this block decides what may proceed without an operator tick, and
|
|
53
|
-
# `
|
|
53
|
+
# `bs scheduler admit` (src/autonomy.ts) applies it. That command still
|
|
54
54
|
# enacts nothing — it prints the classification so it can be read and
|
|
55
55
|
# argued with before anything moves.
|
|
56
56
|
#
|
|
@@ -71,7 +71,7 @@ autonomy:
|
|
|
71
71
|
# or the enable marker classifies operator and never reaches the merge at
|
|
72
72
|
# all. The loop may merge what it builds; it may not merge what bounds it.
|
|
73
73
|
#
|
|
74
|
-
# None of those six is enforced by code yet, because `
|
|
74
|
+
# None of those six is enforced by code yet, because `bs loop` does not
|
|
75
75
|
# exist yet. Until it does, this block's `enabled: true` still only governs
|
|
76
76
|
# dispatch, and the merge is performed by whoever is driving the session.
|
|
77
77
|
enabled: true
|
|
@@ -82,7 +82,7 @@ autonomy:
|
|
|
82
82
|
# says. The list is a ceiling, never a floor.
|
|
83
83
|
#
|
|
84
84
|
# `error-report` — the daemon proposing that an error the log holds with
|
|
85
|
-
# no `issue-reported` event be filed (`
|
|
85
|
+
# no `issue-reported` event be filed (`bs issues report`) — is left out
|
|
86
86
|
# on purpose, and listing it would not change that either. Filing writes
|
|
87
87
|
# to an external issue tracker under an authenticated `gh` token whose
|
|
88
88
|
# scope includes `repo`, and this block's standing decision is that
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# a task can claim `src/auth/**` without writing the word "auth" anywhere in
|
|
14
14
|
# its clauses, and that is exactly the task worth catching.
|
|
15
15
|
#
|
|
16
|
-
# HOST: `
|
|
16
|
+
# HOST: `bs security triggers --task <spec.json>` reads this file and
|
|
17
17
|
# returns the triggers that fired, with the claim and the glob that fired each
|
|
18
18
|
# one (factory/orchestrator/src/security.ts, punch list P9-4). The dispatcher
|
|
19
19
|
# in `.claude/skills/bs/dispatch.md` runs that verb rather than eyeballing the
|
|
@@ -31,6 +31,14 @@ levels:
|
|
|
31
31
|
- a11y WCAG AA failure
|
|
32
32
|
- new flaky test introduced by the task
|
|
33
33
|
- behavioral-drift touching a core flow
|
|
34
|
+
- >
|
|
35
|
+
serious visual defect against the uiux spec or the project's design
|
|
36
|
+
system: a spec'd layout broken, or content clipped/overflowing, at
|
|
37
|
+
a required viewport; an interactive target below the project's
|
|
38
|
+
declared touch-target minimum (fall back to the WCAG 2.2 target
|
|
39
|
+
size minimum only when the project declares none); a required
|
|
40
|
+
state (empty, error, loading) missing (contrast: see a11y WCAG AA
|
|
41
|
+
above)
|
|
34
42
|
on_trigger: >
|
|
35
43
|
bounce to coder on the same branch; after 2 failed rounds, escalate
|
|
36
44
|
model tier (mid -> frontier, budgets.yml); after 3, escalate to
|
|
@@ -40,7 +48,11 @@ levels:
|
|
|
40
48
|
blocks_merge: false
|
|
41
49
|
semantics: waivable — batched to operator at epic end
|
|
42
50
|
classes:
|
|
43
|
-
-
|
|
51
|
+
- >
|
|
52
|
+
minor visual deviation from the uiux spec: spacing, color or type a
|
|
53
|
+
few px or a shade off a design-system token — not a broken layout,
|
|
54
|
+
clipped content, a missing required state, or a touch-target/
|
|
55
|
+
contrast failure below WCAG AA (those are S2-major, above)
|
|
44
56
|
- performance regression > 20%
|
|
45
57
|
- over-engineering (default severity — see rule below)
|
|
46
58
|
- behavioral-drift not touching a core flow
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# What the operator answered when they installed this clone (INSTALL.md
|
|
4
4
|
# Step 6, "The stack interview"). Read by `factory/orchestrator/src/stack.ts`
|
|
5
|
-
# via `
|
|
5
|
+
# via `bs stack show`, and through it by the scaffolder and by every agent
|
|
6
6
|
# that needs to know what this operator builds with.
|
|
7
7
|
#
|
|
8
8
|
# This file used to be a document. `docs/standards/stack.md` shipped one
|
|
@@ -13,20 +13,20 @@
|
|
|
13
13
|
# question would otherwise put words in the operator's mouth.
|
|
14
14
|
#
|
|
15
15
|
# Not every answer is executable. The shipped templates implement a subset —
|
|
16
|
-
# `
|
|
17
|
-
# recorded for the agents to read but not built into `
|
|
18
|
-
# silently pretends: an answer the templates cannot honour makes `
|
|
16
|
+
# `bs stack check` prints which of your answers they honour and which are
|
|
17
|
+
# recorded for the agents to read but not built into `bs new`. Nothing here
|
|
18
|
+
# silently pretends: an answer the templates cannot honour makes `bs new`
|
|
19
19
|
# refuse rather than scaffold something else.
|
|
20
20
|
|
|
21
21
|
# ── Language ────────────────────────────────────────────────────────
|
|
22
22
|
# What the coder writes. `typescript` is the only value the shipped templates
|
|
23
|
-
# scaffold; any other value is recorded, and `
|
|
23
|
+
# scaffold; any other value is recorded, and `bs new` refuses rather than
|
|
24
24
|
# handing you a TypeScript project you did not ask for.
|
|
25
25
|
language: typescript # typescript | javascript | python | go | rust | other
|
|
26
26
|
|
|
27
27
|
# ── Frontend ────────────────────────────────────────────────────────
|
|
28
28
|
# `none` is the default because most projects are not UI projects, and the
|
|
29
|
-
# base template is a plain library. `
|
|
29
|
+
# base template is a plain library. `bs new --ui` needs a value the
|
|
30
30
|
# templates implement — today that is `vue` and nothing else.
|
|
31
31
|
frontend: none # none | vue | react | svelte | solid | vite-vanilla | other
|
|
32
32
|
|
|
@@ -77,6 +77,7 @@ gate_event: [schema-check-result, artifact-check-result,
|
|
|
77
77
|
finding-raised, finding-reverified, finding-suppressed,
|
|
78
78
|
finding-transitioned, finding-reattributed,
|
|
79
79
|
severity-decisions, waiver-granted, waiver-denied,
|
|
80
|
+
task-waiver-approved,
|
|
80
81
|
gate-outcome, issue-reported]
|
|
81
82
|
# schema-check-result — task Result vs result.schema.json
|
|
82
83
|
# artifact-check-result — every artifacts[].path in that
|
|
@@ -95,7 +96,7 @@ gate_event: [schema-check-result, artifact-check-result,
|
|
|
95
96
|
# always logged, including when the
|
|
96
97
|
# project declares nothing to install
|
|
97
98
|
# judges-outstanding — a judge this task dispatched through
|
|
98
|
-
# `
|
|
99
|
+
# `bs judge dispatch` never reported
|
|
99
100
|
# back, so the gate refuses to score an
|
|
100
101
|
# unknown: a missing `--evidence` reads
|
|
101
102
|
# identically whether the judge found
|
|
@@ -194,6 +195,11 @@ gate_event: [schema-check-result, artifact-check-result,
|
|
|
194
195
|
# waiver-batch / log-only)
|
|
195
196
|
# waiver-granted/-denied — operator waiver-batch answer,
|
|
196
197
|
# keyed by finding fingerprint
|
|
198
|
+
# task-waiver-approved — operator approval of one waived
|
|
199
|
+
# task, keyed by task id and valid from
|
|
200
|
+
# its plan_version on; what the
|
|
201
|
+
# epic gate accepts in place of a
|
|
202
|
+
# gate run
|
|
197
203
|
# gate-outcome — the composed gate pipeline's
|
|
198
204
|
# final structured result
|
|
199
205
|
# issue-reported — issueReporter.ts's record of one
|
|
@@ -219,10 +225,10 @@ error:
|
|
|
219
225
|
# (planner, scribe) wrote outside its declared write root
|
|
220
226
|
# (P9-3); shipped as a code before it was a class
|
|
221
227
|
# judge-mutation — a read-only judge moved the worktree it
|
|
222
|
-
# was judging (P9-5, `
|
|
228
|
+
# was judging (P9-5, `bs worktree verify`)
|
|
223
229
|
# uncited-claim — a researcher finding with no citation, or a
|
|
224
230
|
# citation that is neither a repo path with a line number nor
|
|
225
|
-
# a URL actually fetched (P9-6, `
|
|
231
|
+
# a URL actually fetched (P9-6, `bs research check`)
|
|
226
232
|
# unsourced-recommendation — a brief's recommendation names no
|
|
227
233
|
# finding, or names one the brief does not carry, so what came
|
|
228
234
|
# from fetched text is invisible (P9-6)
|
|
@@ -17,19 +17,24 @@ worktree:
|
|
|
17
17
|
# Relative to whatever directory the project was handed as, never to this
|
|
18
18
|
# clone: a project beside the repo keeps its worktrees beside the repo too.
|
|
19
19
|
path_pattern: "<project-parent>/.wt/<project>/<task-id>"
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
# bs-rename, operator decision 2/3: bs/ is the current prefix for every new
|
|
21
|
+
# epic; one that already integrates on the legacy smith/ prefix keeps it
|
|
22
|
+
# for its whole life rather than switching mid-epic (integration_branch
|
|
23
|
+
# below).
|
|
24
|
+
branch_pattern: "bs/<epic>/<task-id>"
|
|
25
|
+
created_from: integration branch head (bs/<epic>/integration), fresh each time
|
|
22
26
|
lifecycle: deleted after merge — a stale worktree is a bug
|
|
23
27
|
one_worktree_per_task: true
|
|
24
28
|
|
|
25
29
|
integration_branch:
|
|
26
|
-
# Phase-3 correction: a bare "
|
|
27
|
-
# "
|
|
30
|
+
# Phase-3 correction: a bare "bs/<epic>" ref cannot coexist with
|
|
31
|
+
# "bs/<epic>/<task-id>" refs — git's ref namespace is hierarchical, so a
|
|
28
32
|
# leaf ref and a directory prefix of the same name conflict (D/F conflict,
|
|
29
33
|
# confirmed against a real git repo while implementing worktree.ts). The
|
|
30
34
|
# integration branch is therefore a sibling of task branches under the
|
|
31
|
-
# epic's ref prefix, not a leaf at "
|
|
32
|
-
|
|
35
|
+
# epic's ref prefix, not a leaf at "bs/<epic>" itself. An epic that already
|
|
36
|
+
# integrates on smith/<epic>/integration (legacy) keeps that prefix instead.
|
|
37
|
+
pattern: "bs/<epic>/integration"
|
|
33
38
|
rule: workers never touch main/master; only the operator merges the
|
|
34
39
|
integration PR into the target repo's main.
|
|
35
40
|
|
|
@@ -75,7 +80,8 @@ merge_queue:
|
|
|
75
80
|
mode: serial
|
|
76
81
|
order: dependency order (topological, per recorded edges)
|
|
77
82
|
admission_steps:
|
|
78
|
-
- rebase task branch onto current
|
|
83
|
+
- rebase task branch onto current integration branch head (bs/<epic>/integration,
|
|
84
|
+
or smith/<epic>/integration for a legacy epic)
|
|
79
85
|
- run the cumulative regression gate (every previously merged task's
|
|
80
86
|
tests in this epic, not just the incoming task)
|
|
81
87
|
- admit on green; reject and bounce on red
|
|
@@ -90,6 +96,6 @@ merge_queue:
|
|
|
90
96
|
enabled: true
|
|
91
97
|
max_lines_per_layer: 200
|
|
92
98
|
note: >
|
|
93
|
-
workers emit small stacked layers (within the
|
|
94
|
-
rather than monolithic diffs; the queue lands stacks in dependency
|
|
99
|
+
workers emit small stacked layers (within the task diff cap,
|
|
100
|
+
budgets.yml `task.coder.cap_diff_lines`) rather than monolithic diffs; the queue lands stacks in dependency
|
|
95
101
|
order (GitHub native stacked PRs).
|