@kungfu-tech/buildchain 3.0.6-alpha.0 → 3.0.6-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +4 -4
  2. package/actions/promote-buildchain-ref/README.md +13 -1
  3. package/bin/buildchain.mjs +13 -1
  4. package/contracts/auditable-demo-scenario-v1.schema.json +52 -0
  5. package/contracts/release-candidate-recovery-v1.schema.json +104 -0
  6. package/dist/site/buildchain-contract.json +134 -34
  7. package/dist/site/buildchain-site.json +178 -47
  8. package/dist/site/capability-registry.json +5 -5
  9. package/dist/site/cli-registry.json +40 -4
  10. package/dist/site/controller-registry.json +60 -4
  11. package/dist/site/kfd-claims.json +190 -20
  12. package/dist/site/kfd-upstream-aggregate.json +9 -9
  13. package/dist/site/manual-registry.json +10 -10
  14. package/dist/site/node-api-registry.json +1295 -80
  15. package/dist/site/page-registry.json +164 -33
  16. package/dist/site/public-surface-audit.json +428 -21
  17. package/dist/site/publication-authority-registry.json +66 -1
  18. package/dist/site/publication-registry.json +4 -4
  19. package/dist/site/release-provenance.json +2 -0
  20. package/dist/site/site-manifest.json +14 -14
  21. package/dist/site/workflow-registry.json +203 -15
  22. package/docs/MAP.md +2 -0
  23. package/docs/auditable-demo.md +58 -11
  24. package/docs/aws-us-elastic-runner-burst-plane.md +114 -80
  25. package/docs/cli-reference.md +154 -0
  26. package/docs/dev-alpha-candidate-patrol.md +13 -5
  27. package/docs/dev-delivery-warrant.md +158 -0
  28. package/docs/node-api-reference.md +105 -44
  29. package/docs/publication-authority.md +11 -0
  30. package/docs/publish-transaction.md +10 -1
  31. package/docs/release-candidate.md +140 -12
  32. package/docs/release-governance.md +66 -1
  33. package/docs/reusable-build-surface.md +11 -1
  34. package/docs/shifu-gate-profiles.md +12 -1
  35. package/docs/versioning.md +2 -0
  36. package/package.json +5 -2
  37. package/packages/core/buildchain-contract.js +30 -2
  38. package/packages/core/buildchain-publication-authority.js +3 -1
  39. package/packages/core/channel-candidate.js +2 -21
  40. package/packages/core/channel-promotion-baseline.js +199 -0
  41. package/packages/core/dev-delivery-candidate-identity.js +94 -0
  42. package/packages/core/dev-delivery-common.js +73 -0
  43. package/packages/core/dev-delivery-proof.js +252 -0
  44. package/packages/core/dev-delivery-warrant-cancellation.js +94 -0
  45. package/packages/core/dev-delivery-warrant-settlement.js +73 -0
  46. package/packages/core/dev-delivery-warrant.js +591 -0
  47. package/packages/core/index.js +7 -0
  48. package/packages/core/publication-sealed-bundle.js +10 -1
  49. package/packages/core/release-candidate-recovery.js +539 -0
  50. package/scripts/audit-publication-control-plane.mjs +12 -4
  51. package/scripts/auditable-demo-bundle-verification.mjs +148 -0
  52. package/scripts/auditable-demo-platform.mjs +86 -50
  53. package/scripts/auditable-demo-presentation.mjs +83 -0
  54. package/scripts/auditable-demo-renditions.mjs +264 -0
  55. package/scripts/auditable-demo.mjs +24 -30
  56. package/scripts/aws-windows-jit-campaign-core.mjs +7 -8
  57. package/scripts/aws-windows-jit-controller.mjs +1 -0
  58. package/scripts/aws-windows-jit-core.mjs +1 -1
  59. package/scripts/build-contract-core.mjs +58 -3
  60. package/scripts/buildchain-cli-help.mjs +8 -0
  61. package/scripts/buildchain-patrol.mjs +9 -0
  62. package/scripts/check-inventory.mjs +25 -3
  63. package/scripts/dev-alpha-candidate-patrol.mjs +45 -48
  64. package/scripts/dev-delivery-proof.mjs +193 -0
  65. package/scripts/dev-delivery-warrant.mjs +426 -0
  66. package/scripts/dev-pr-auto-merge.mjs +497 -55
  67. package/scripts/dev-pr-delivery-warrant.mjs +209 -0
  68. package/scripts/dispatch-artifact-signing-authority.mjs +2 -4
  69. package/scripts/gate-profile-core.mjs +24 -0
  70. package/scripts/generate-channel-promotion-workflow.mjs +30 -14
  71. package/scripts/generate-site-bundle.mjs +2 -2
  72. package/scripts/git-fetch-process-tree.mjs +142 -0
  73. package/scripts/lifecycle-substage-evidence.mjs +274 -0
  74. package/scripts/locked-source-checkout.mjs +6 -3
  75. package/scripts/publication-candidate-sealer.mjs +104 -0
  76. package/scripts/release-candidate-resolver.mjs +91 -5
  77. package/scripts/resolve-artifact-transfer-mode.mjs +9 -0
  78. package/scripts/resolve-build-contract.mjs +7 -0
  79. package/scripts/resume-from-candidate-run.mjs +598 -0
  80. package/scripts/route-offline-runners.mjs +1 -0
  81. package/scripts/run-lifecycle-core.mjs +9 -9
  82. package/scripts/shifu-gate-profile.mjs +10 -16
  83. package/scripts/site-capability-metadata.mjs +15 -0
@@ -8,7 +8,7 @@ confidence: high
8
8
  sensitivity: public
9
9
  evidence_grade: A
10
10
  review_state: self-reviewed
11
- last_reviewed: 2026-08-02
11
+ last_reviewed: 2026-08-05
12
12
  ai_provenance:
13
13
  model_family: GPT-5
14
14
  product: Codex
@@ -52,6 +52,39 @@ the default. Both classes retain 4 MiB per step, a clean Home/XDG environment,
52
52
  no inherited credentials, and a network-disabled read-only container with
53
53
  bounded tmpfs.
54
54
 
55
+ Consumers may optionally add a
56
+ `buildchain.declarative-demo-presentation/v1` presentation. This contract
57
+ binds one consumer-owned proof label, question, summary, and optional
58
+ transition to every demo in declared order. Buildchain verifies that each
59
+ question is the same title used by capture and media; it does not invent or
60
+ reinterpret the product argument.
61
+
62
+ The presentation also chooses one of two README materialization modes. The
63
+ default, when no presentation is declared, remains the original full generated
64
+ block with commands, renditions, evidence, and claim boundary. `media-only`
65
+ updates only the image inside each existing README marker so consumer-authored
66
+ narrative and transitions survive regeneration. The generated technical
67
+ details move to a separately declared Markdown specification, where stable
68
+ per-demo markers preserve proof order and idempotent updates. The publication
69
+ pull request stages that specification together with the README and
70
+ content-addressed evidence. No presentation field grants publication or Work
71
+ authority.
72
+
73
+ The optional top-level `compositionMode` is an explicit visual contract.
74
+ Omitting it preserves `presentation-framed`; declaring `terminal-fill` makes
75
+ the bounded PTY replay the complete pixel surface without renderer-owned
76
+ window chrome. Buildchain carries that choice into both native scenes. It does
77
+ not infer full-frame intent from output resolution.
78
+
79
+ The optional `buildchain.declarative-demo-playback/v1` contract separates
80
+ observed command latency from presentation timing. Its
81
+ `deterministic-readable` mode preserves the captured terminal event payloads
82
+ and their order, records the observed final-event time as non-authoritative
83
+ evidence, and maps event ordinals onto the declared `activeDurationMs` before a
84
+ bounded `finalHoldMs`. Both native renditions therefore replay at the same
85
+ readable pace even when an identical command runs faster or slower. Omitting
86
+ the contract preserves the original PTY timestamp behavior.
87
+
55
88
  The uploaded metadata must bind the executable SHA-256, declare an empty
56
89
  runtime dependency set, and provide a bounded `executableFiles` array of exact
57
90
  artifact-relative paths and SHA-256 digests. GitHub Artifact transport does not
@@ -97,6 +130,7 @@ jobs:
97
130
  scenario-path: .buildchain/auditable-demo.json
98
131
  renderer-image: ghcr.io/kungfu-systems/build-images/demo-renderer@sha256:RENDERER_DIGEST
99
132
  render-media: true
133
+ render-failure-advisory: false
100
134
  media-profile: responsive-web-delivery-v1
101
135
  materialize: true
102
136
  materialize-base-ref: dev/v1/v1.0
@@ -193,6 +227,10 @@ The Gate:
193
227
  bounded tmpfs;
194
228
  - verifies the renderer manifest, media probe, exact input roots, exact output
195
229
  member set, and complete checksums;
230
+ - independently verifies the requested composition mode, browser-observed
231
+ content viewport, PTY rows and columns, and deterministic cell geometry for
232
+ every frame set; `terminal-fill` is rejected unless the viewport and cell
233
+ grid resolve to the complete declared frame;
196
234
  - uploads a content-addressed qualified bundle plus an independent GitHub
197
235
  Artifact id, URL, archive digest, and expiry-bearing source coordinate.
198
236
 
@@ -202,9 +240,9 @@ passed gate receipt, and checksums covering every member exactly once.
202
240
 
203
241
  ## Selective Render
204
242
 
205
- `render-media: true` enables the second job. It downloads the just-uploaded Gate
206
- bundle by its content-addressed name, recomputes the Gate member root, verifies
207
- the exact source SHA and renderer digest, and only then renders the complete
243
+ `render-media: true` enables the full-media step only after every declared demo
244
+ has passed the required Gate. It recomputes each Gate member root, verifies the
245
+ exact source SHA and renderer digest, and only then renders the complete
208
246
  qualified scene.
209
247
 
210
248
  The media bundle contains MP4, WebM, GIF, poster, probe, renderer manifest,
@@ -213,10 +251,19 @@ distribution checksums. A web-delivery profile also retains
213
251
  `media-inspection.json`, whose content root is bound into the receipt.
214
252
  `render-media: false` does not weaken or skip the Gate.
215
253
 
254
+ `render-failure-advisory: true` makes only the full-media step advisory. A
255
+ render failure remains visible as a failed step and workflow warning, while the
256
+ required Gate keeps its normal failure semantics. Failed or partial media can
257
+ never open a materialization PR. Use this for an Alpha lane whose binary
258
+ publication must not depend on animation capacity; keep the default `false`
259
+ for explicit media refreshes and other workflows that require complete media.
260
+
216
261
  When the Gate bundle contains a qualified terminal capture, the render job
217
262
  passes it read-only to the immutable renderer. The renderer manifest binds the
218
263
  capture root and terminal-state-machine version, but raw capture bytes remain
219
264
  in the Gate bundle rather than being copied into the public media bundle.
265
+ Missing, malformed, out-of-bounds, non-full-frame, rendition-mismatched, or
266
+ internally drifted composition evidence fails before media finalization.
220
267
 
221
268
  ## Media Qualification Profiles
222
269
 
@@ -225,13 +272,13 @@ The single machine-readable source is
225
272
  profile through `media-profile`; they cannot pass ffmpeg commands, codec flags,
226
273
  shell fragments, arbitrary profile paths, or transcoding instructions.
227
274
 
228
- | Profile | Meaning |
229
- | --- | --- |
230
- | `archive-v1` | Default compatibility contract. Retains the exact renderer outputs and classifies GIF as README compatibility evidence without making a browser-delivery claim. |
231
- | `web-delivery-v1` | Independently qualifies H.264 MP4 and VP9 WebM playback sources, forbids audio, requires exact scene dimensions and bounded duration/frame-rate drift, checks per-rendition byte ceilings, and proves MP4 `moov` precedes `mdat`. PNG remains the lossless evidence poster. |
232
- | `responsive-web-delivery-v1` | Extends `web-delivery-v1` with exact 1280x720 H.264 MP4 and VP9 WebM responsive sources plus a 1280x720 README GIF while keeping the primary MP4/WebM and evidence poster at the source scene dimensions. Every declared downscale must preserve the scene aspect ratio and may never upscale. |
233
- | `responsive-long-form-web-delivery-v1` | Extends the responsive profile for explicitly admitted long-form scenes. Its measured-baseline multipliers raise only the GIF ceiling to 8 MiB and the four video ceilings to 4 MiB; all codec, native-resolution, no-audio, duration, and authority checks remain unchanged. |
234
- | `site-hero-v1` | Extends `web-delivery-v1` and additionally requires a qualified WebP browser poster. The current Build Images v1 renderer does not emit that member, so selecting this profile fails closed until the producer adds it. |
275
+ | Profile | Meaning |
276
+ | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
277
+ | `archive-v1` | Default compatibility contract. Retains the exact renderer outputs and classifies GIF as README compatibility evidence without making a browser-delivery claim. |
278
+ | `web-delivery-v1` | Independently qualifies H.264 MP4 and VP9 WebM playback sources, forbids audio, requires exact scene dimensions and bounded duration/frame-rate drift, checks per-rendition byte ceilings, and proves MP4 `moov` precedes `mdat`. PNG remains the lossless evidence poster. |
279
+ | `responsive-web-delivery-v1` | Extends `web-delivery-v1` with exact 1280x720 H.264 MP4 and VP9 WebM responsive sources plus a 1280x720 README GIF while keeping the primary MP4/WebM and evidence poster at the source scene dimensions. Every declared downscale must preserve the scene aspect ratio and may never upscale. |
280
+ | `responsive-long-form-web-delivery-v1` | Extends the responsive profile for explicitly admitted long-form scenes. Its measured-baseline multipliers raise only the GIF ceiling to 8 MiB and the four video ceilings to 4 MiB; all codec, native-resolution, no-audio, duration, and authority checks remain unchanged. |
281
+ | `site-hero-v1` | Extends `web-delivery-v1` and additionally requires a qualified WebP browser poster. The current Build Images v1 renderer does not emit that member, so selecting this profile fails closed until the producer adds it. |
235
282
 
236
283
  For web-delivery profiles, Buildchain runs its own fixed `ffprobe` invocation
237
284
  inside the same immutable, network-disabled renderer image. That command is
@@ -8,11 +8,11 @@ confidence: high
8
8
  sensitivity: public
9
9
  evidence_grade: A
10
10
  review_state: unreviewed
11
- last_reviewed: 2026-08-02
11
+ last_reviewed: 2026-08-03
12
12
  ai_provenance:
13
13
  model_family: GPT-5
14
14
  product: Codex
15
- generated_at: 2026-08-01
15
+ generated_at: 2026-08-03
16
16
  invisible_information: No hidden model checkpoint, parameters, or private training data were available.
17
17
  ---
18
18
 
@@ -189,7 +189,7 @@ and atomically refuses a sixth accepted instance. Five accepted instances
189
189
  therefore reserve at most USD 21.75. The campaign also persists the
190
190
  operator-observed spend from earlier Windows work, and refuses to arm unless
191
191
  that baseline, all five reservations, and one USD 4.35 fail-closed race
192
- allowance remain below the USD 80 phase cap.
192
+ allowance remain below the USD 110 phase cap.
193
193
 
194
194
  The campaign starts unarmed and expires within 24 hours. Its `CONTROL` record
195
195
  can be created only once: a killed or expired campaign cannot be re-armed by
@@ -199,16 +199,38 @@ paid launch. Reservations are never refunded: a controller crash, ambiguous
199
199
  launch, or successful launch all remain charged to the campaign, favoring a
200
200
  false stop over an accidental budget overrun.
201
201
 
202
+ The 2026-08-03 timeout-only campaign decision narrows the campaign to two
203
+ accepted instances with one active instance at a time. The second reservation
204
+ is an operator-gated repair retry: it may be used only after the first attempt
205
+ is classified as non-counting and runner, EC2, EBS, SSM, and workflow residue
206
+ have returned to zero. The two-slot ledger is a maximum spend boundary, not an
207
+ authorization to consume both reservations.
208
+
202
209
  Each stack owns a stack-scoped reaper log group, so an independent retained
203
210
  one-shot campaign stack can be created without colliding with another
204
211
  campaign's audit log resource.
205
212
 
206
- The tag-filtered AWS Budget is defense in depth, not the authoritative launch
207
- gate. It is disabled by default because a linked account cannot activate a
208
- cost-allocation tag. Set `EnableTagFilteredBudget=true` only after the AWS
209
- Organizations management account has activated `kungfu:provider` and a Cost
210
- Explorer readback proves that `windows-ec2-jit` spend is visible. The DynamoDB
211
- reservation cap remains mandatory in either mode.
213
+ The account-native AWS Budget is defense in depth, not the authoritative launch
214
+ gate. It is owned by the singleton
215
+ `kungfu-buildchain-windows-jit-budget-guard` stack rather than any retained
216
+ campaign stack. This prevents Budget-name collisions and prevents a stale
217
+ campaign reaper from becoming the provider-wide cost authority. The Budget
218
+ filters exactly `USAGE_TYPE=BoxUsage:c7i.4xlarge`,
219
+ `OPERATION=RunInstances:0002` (Windows), and `REGION=us-east-1`; its 80% and
220
+ 95% actual notifications persist the provider kill sentinel, terminate every
221
+ tagged Windows JIT instance, and delete scoped JIT parameters. Every launch
222
+ controller refuses to proceed when the sentinel exists or when the Budget
223
+ identity or dimension filter does not match.
224
+
225
+ Budget installation is intentionally deployable by the workload account without
226
+ AWS Organizations management-account access. It fails closed unless Cost
227
+ Explorer exposes all three AWS-owned billing dimensions in the requested phase
228
+ window. The `kungfu:provider=windows-ec2-jit` resource tag remains mandatory for
229
+ ownership, cleanup, and IAM scoping, but it is not a billing filter. Do not
230
+ create an unfiltered fallback Budget or treat an incomplete dimension readback
231
+ as evidence.
232
+ The DynamoDB campaign reservation remains the atomic launch authority because
233
+ Cost Explorer and AWS Budgets can lag provider activity.
212
234
 
213
235
  Qualification requires one runner-profile smoke and three trusted exact-source
214
236
  full Windows jobs all bound to the same campaign, independent cancellation and
@@ -216,82 +238,94 @@ timeout cleanup exercises, and zero repository runner, EC2 instance,
216
238
  disposable volume, min capacity, and desired capacity within 15 minutes of the
217
239
  final job.
218
240
 
219
- ### Phase 2 campaign controller
220
-
221
- `scripts/aws-windows-jit-campaign.mjs` is the one-shot operator boundary.
222
- Without a mutation mode it emits the arm plan. `arm-campaign` requires the
223
- campaign id, exact source SHA, state table, observed prior phase spend, and a
224
- bounded one-to-five accepted-instance ceiling to be repeated as confirmations,
225
- then creates `CONTROL` and `CAMPAIGN#<id>` with
226
- `attribute_not_exists`
227
- conditions. DynamoDB therefore refuses a second campaign in the same retained
228
- state table. The operator can always use `kill-campaign`; there is deliberately
229
- no clear or re-arm operation.
230
-
231
- Every `scripts/aws-windows-jit-controller.mjs --execute` call must provide the
232
- same `--campaign-id`, `--confirm-campaign-id`, `--state-table`, and
233
- `--confirm-state-table`. After the GitHub, AMI, active-instance, SSM, and EC2
234
- DryRun checks pass, the controller
235
- atomically reserves one run. Duplicate run-attempt-qualification identities,
236
- source mismatch, expiry, `KILLED`, the sixth accepted instance, or a
237
- reservation that would exceed the baseline-adjusted USD 80 phase ceiling all
238
- fail closed before `RunInstances`.
239
-
240
- Example dry-run and arm boundary (do not execute without a new campaign budget
241
- decision):
241
+ ### Phase 2 operator workflow
242
+
243
+ `pnpm operator:windows-jit` is the reusable lifecycle entrypoint. Its default
244
+ mode is `plan`, which performs no AWS or GitHub call. A plan binds the account,
245
+ region, unique campaign and stack names, source SHA/ref, Cost Explorer window,
246
+ workflow id, network, OIDC provider, expiry, slot ceiling, singleton Budget
247
+ identity, and exact confirmation digest.
248
+
249
+ The modes are deliberately separated:
250
+
251
+ - `plan` emits the deterministic mutation boundary and digest.
252
+ - `audit` reads AWS and GitHub only. It verifies the account, disabled workflow,
253
+ singleton guard stack, exact Budget filter, SNS thresholds/subscribers,
254
+ provider kill sentinel, campaign stack, and zero EC2/EBS/SSM/JIT/runner
255
+ residue.
256
+ - `install-budget --execute` deploys or updates only the singleton Budget guard.
257
+ It refuses to mutate unless all exact Windows billing dimensions are visible,
258
+ the Windows workflow is disabled, and the account, campaign, source, Budget,
259
+ and plan digest confirmations match.
260
+ - `prepare --execute` requires the installed Budget guard, absent kill
261
+ sentinel, fresh Cost Explorer readback filtered by `BoxUsage:c7i.4xlarge`,
262
+ `RunInstances:0002`, and `us-east-1`, zero residue, a
263
+ never-used campaign stack name, and the disabled workflow. The receipt binds
264
+ the query timestamp and exact filter identity. Preparation deploys the
265
+ campaign stack and atomically arms the ledger with that provider-spend
266
+ baseline. It never enables or dispatches the workflow and never creates EC2
267
+ capacity.
268
+ - `close --execute` disables the workflow first, persists `KILLED`, publishes
269
+ the campaign kill switch, and reports terminal success only after EC2, EBS,
270
+ SSM, JIT parameter, and GitHub runner residue is zero. It is safe to rerun
271
+ while the reaper settles.
272
+
273
+ All mutating modes require `--execute`, `--confirm-plan-digest`,
274
+ `--confirm-account-id`, `--confirm-campaign-id`, and
275
+ `--confirm-source-sha`. Budget installation and preparation additionally
276
+ require `--confirm-budget-name`. A future paid workload still requires a
277
+ separate exact workflow/run authorization and uses
278
+ `scripts/aws-windows-jit-controller.mjs`; preparation is not paid-launch
279
+ authority.
280
+
281
+ Start by recording one reproducible plan:
242
282
 
243
283
  ```bash
244
- windows_campaign=win-REPLACE_WITH_CAMPAIGN_ID
245
- windows_source=REPLACE_WITH_EXACT_40_CHARACTER_SHA
246
- windows_state_table=REPLACE_WITH_CAMPAIGN_STATE_TABLE
247
- windows_expires_at=REPLACE_WITH_ISO_TIMESTAMP_WITHIN_24_HOURS
248
- windows_phase_spend_baseline_usd=REPLACE_WITH_OBSERVED_PRIOR_WINDOWS_SPEND
249
- windows_max_accepted_instances=REPLACE_WITH_INTEGER_FROM_1_THROUGH_5
250
-
251
- node scripts/aws-windows-jit-campaign.mjs plan-arm \
252
- --campaign-id "$windows_campaign" \
253
- --source-sha "$windows_source" \
254
- --state-table "$windows_state_table" \
255
- --expires-at "$windows_expires_at" \
256
- --phase-spend-baseline-usd "$windows_phase_spend_baseline_usd" \
257
- --max-accepted-instances "$windows_max_accepted_instances"
258
-
259
- node scripts/aws-windows-jit-campaign.mjs arm-campaign \
260
- --campaign-id "$windows_campaign" \
261
- --confirm-campaign-id "$windows_campaign" \
262
- --source-sha "$windows_source" \
263
- --confirm-source-sha "$windows_source" \
264
- --state-table "$windows_state_table" \
265
- --confirm-state-table "$windows_state_table" \
266
- --expires-at "$windows_expires_at" \
267
- --phase-spend-baseline-usd "$windows_phase_spend_baseline_usd" \
268
- --confirm-phase-spend-baseline-usd "$windows_phase_spend_baseline_usd" \
269
- --max-accepted-instances "$windows_max_accepted_instances" \
270
- --confirm-max-accepted-instances "$windows_max_accepted_instances"
284
+ pnpm operator:windows-jit plan \
285
+ --aws-profile us \
286
+ --account-id 727884401362 \
287
+ --campaign-id win-REPLACE \
288
+ --source-sha REPLACE_WITH_EXACT_40_CHARACTER_SHA \
289
+ --source-ref refs/heads/dev/v4/v4.0 \
290
+ --observed-at REPLACE_WITH_ISO_TIMESTAMP \
291
+ --expires-at REPLACE_WITH_ISO_TIMESTAMP_WITHIN_24_HOURS \
292
+ --cost-start REPLACE_WITH_PHASE_START_DATE \
293
+ --cost-end REPLACE_WITH_EXCLUSIVE_END_DATE \
294
+ --max-accepted-instances 1 \
295
+ --workflow-id 322620360 \
296
+ --vpc-id REPLACE_WITH_VPC_ID \
297
+ --subnet-id REPLACE_WITH_SUBNET_ID \
298
+ --oidc-provider-arn REPLACE_WITH_GITHUB_OIDC_PROVIDER_ARN
271
299
  ```
272
300
 
273
- Arming creates a permanent one-shot control record and admits only the
274
- explicitly confirmed number of paid instances, never more than five. Its
275
- rollback is fail-closed, not deletion: `kill-campaign` first
276
- persists `KILLED`, then publishes to the dedicated SNS topic so the reaper
277
- terminates active card-owned instances and removes their JIT parameters. The
278
- command is idempotent, but the operator must read back DynamoDB, EC2, SSM, and
279
- GitHub runners before treating cleanup as complete:
301
+ Reuse those exact arguments for `audit`, `install-budget`, `prepare`, or
302
+ `close`; never regenerate `--observed-at` between the plan and its confirmed
303
+ mutation. Capture stdout as the operator receipt. Do not put credentials,
304
+ tokens, JIT configuration, or signed URLs in arguments or receipts.
280
305
 
281
- ```bash
282
- windows_kill_topic=REPLACE_WITH_DEDICATED_KILL_SWITCH_TOPIC_ARN
283
-
284
- node scripts/aws-windows-jit-campaign.mjs kill-campaign \
285
- --campaign-id "$windows_campaign" \
286
- --confirm-campaign-id "$windows_campaign" \
287
- --source-sha "$windows_source" \
288
- --confirm-source-sha "$windows_source" \
289
- --state-table "$windows_state_table" \
290
- --confirm-state-table "$windows_state_table" \
291
- --kill-switch-topic "$windows_kill_topic" \
292
- --confirm-kill-switch-topic "$windows_kill_topic" \
293
- --reason operator-kill
294
- ```
306
+ ### Lower-level campaign and launch controllers
307
+
308
+ `scripts/aws-windows-jit-campaign-core.mjs` owns the pure one-shot ledger
309
+ contract used by the operator and launch controller. Arming creates `CONTROL`
310
+ and `CAMPAIGN#<id>` with `attribute_not_exists` conditions, so DynamoDB refuses
311
+ a second campaign in the same retained state table. There is deliberately no
312
+ clear or re-arm operation.
313
+
314
+ Every `scripts/aws-windows-jit-controller.mjs --execute` call must provide the
315
+ same `--account-id`, `--campaign-id`, `--confirm-campaign-id`, `--state-table`,
316
+ and `--confirm-state-table`. Before GitHub JIT material is created, the
317
+ controller verifies the exact provider Budget/dimension filter and proves the
318
+ global Budget kill sentinel absent. After the GitHub, AMI, active-instance,
319
+ SSM, and EC2 DryRun checks pass, the controller
320
+ atomically reserves one run. Duplicate run-attempt-qualification identities,
321
+ source mismatch, expiry, `KILLED`, the sixth accepted instance, or a
322
+ reservation that would exceed the USD 110 ceiling after combining the persisted
323
+ fresh Cost Explorer baseline with all in-flight campaign reservations all fail
324
+ closed in one DynamoDB transaction before `RunInstances`. AWS Budget alarms are
325
+ defense in depth for delayed billing telemetry; the atomic ledger is the
326
+ authoritative launch-time guard. The operator is the only supported mutation
327
+ surface for campaign preparation and closeout; direct imports of the core are
328
+ not operator authority.
295
329
 
296
330
  ## Phase 3 contract
297
331
 
@@ -223,6 +223,160 @@ buildchain dev
223
223
  buildchain dev merge-queue --repository <owner/repo> --branch <dev/vN/vN.M> [--from-config | --workflow <required-workflow.yml>...] [--cwd <dir>] [--check-response-timeout-minutes <n>] [--max-entries-to-build <n>] [--apply]
224
224
  ```
225
225
 
226
+ ### `buildchain dev pr-admit`
227
+
228
+ - Help: `buildchain dev pr-admit --help`
229
+ - Canonical id: `dev`
230
+ - Options: `--branch`, `--execute`, `--expected-head`, `--json`, `--output`, `--pull-request`, `--repository`
231
+ - Syntax:
232
+
233
+ ```text
234
+ buildchain dev pr-admit --repository <owner/repo> --branch <dev/vN/vN.M> --pull-request <n> --expected-head <sha> [--execute] [--output <file>] [--json]
235
+ ```
236
+
237
+ ### `buildchain dev proof classify`
238
+
239
+ - Help: `buildchain dev proof classify --help`
240
+ - Canonical id: `dev`
241
+ - Options: `--json`, `--output`
242
+ - Syntax:
243
+
244
+ ```text
245
+ buildchain dev proof <source|verify-source|classify|replay|integration|verify-integration> [--output <file>] [--json]
246
+ ```
247
+
248
+ ### `buildchain dev proof integration`
249
+
250
+ - Help: `buildchain dev proof integration --help`
251
+ - Canonical id: `dev`
252
+ - Options: `--json`, `--output`
253
+ - Syntax:
254
+
255
+ ```text
256
+ buildchain dev proof <source|verify-source|classify|replay|integration|verify-integration> [--output <file>] [--json]
257
+ ```
258
+
259
+ ### `buildchain dev proof replay`
260
+
261
+ - Help: `buildchain dev proof replay --help`
262
+ - Canonical id: `dev`
263
+ - Options: `--json`, `--output`
264
+ - Syntax:
265
+
266
+ ```text
267
+ buildchain dev proof <source|verify-source|classify|replay|integration|verify-integration> [--output <file>] [--json]
268
+ ```
269
+
270
+ ### `buildchain dev proof source`
271
+
272
+ - Help: `buildchain dev proof source --help`
273
+ - Canonical id: `dev`
274
+ - Options: `--json`, `--output`
275
+ - Syntax:
276
+
277
+ ```text
278
+ buildchain dev proof <source|verify-source|classify|replay|integration|verify-integration> [--output <file>] [--json]
279
+ ```
280
+
281
+ ### `buildchain dev proof verify-integration`
282
+
283
+ - Help: `buildchain dev proof verify-integration --help`
284
+ - Canonical id: `dev`
285
+ - Options: `--json`, `--output`
286
+ - Syntax:
287
+
288
+ ```text
289
+ buildchain dev proof <source|verify-source|classify|replay|integration|verify-integration> [--output <file>] [--json]
290
+ ```
291
+
292
+ ### `buildchain dev proof verify-source`
293
+
294
+ - Help: `buildchain dev proof verify-source --help`
295
+ - Canonical id: `dev`
296
+ - Options: `--json`, `--output`
297
+ - Syntax:
298
+
299
+ ```text
300
+ buildchain dev proof <source|verify-source|classify|replay|integration|verify-integration> [--output <file>] [--json]
301
+ ```
302
+
303
+ ### `buildchain dev warrant cancel-queued`
304
+
305
+ - Help: `buildchain dev warrant cancel-queued --help`
306
+ - Canonical id: `dev`
307
+ - Options: `--branch`, `--execute`, `--json`, `--output`, `--repository`
308
+ - Syntax:
309
+
310
+ ```text
311
+ buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe> --repository <owner/repo> --branch <dev/vN/vN.M> [--execute] [--output <file>] [--json]
312
+ ```
313
+
314
+ ### `buildchain dev warrant close`
315
+
316
+ - Help: `buildchain dev warrant close --help`
317
+ - Canonical id: `dev`
318
+ - Options: `--branch`, `--execute`, `--json`, `--output`, `--repository`
319
+ - Syntax:
320
+
321
+ ```text
322
+ buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe> --repository <owner/repo> --branch <dev/vN/vN.M> [--execute] [--output <file>] [--json]
323
+ ```
324
+
325
+ ### `buildchain dev warrant heartbeat`
326
+
327
+ - Help: `buildchain dev warrant heartbeat --help`
328
+ - Canonical id: `dev`
329
+ - Options: `--branch`, `--execute`, `--json`, `--output`, `--repository`
330
+ - Syntax:
331
+
332
+ ```text
333
+ buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe> --repository <owner/repo> --branch <dev/vN/vN.M> [--execute] [--output <file>] [--json]
334
+ ```
335
+
336
+ ### `buildchain dev warrant observe`
337
+
338
+ - Help: `buildchain dev warrant observe --help`
339
+ - Canonical id: `dev`
340
+ - Options: `--branch`, `--execute`, `--json`, `--output`, `--repository`
341
+ - Syntax:
342
+
343
+ ```text
344
+ buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe> --repository <owner/repo> --branch <dev/vN/vN.M> [--execute] [--output <file>] [--json]
345
+ ```
346
+
347
+ ### `buildchain dev warrant recover`
348
+
349
+ - Help: `buildchain dev warrant recover --help`
350
+ - Canonical id: `dev`
351
+ - Options: `--branch`, `--execute`, `--json`, `--output`, `--repository`
352
+ - Syntax:
353
+
354
+ ```text
355
+ buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe> --repository <owner/repo> --branch <dev/vN/vN.M> [--execute] [--output <file>] [--json]
356
+ ```
357
+
358
+ ### `buildchain dev warrant select`
359
+
360
+ - Help: `buildchain dev warrant select --help`
361
+ - Canonical id: `dev`
362
+ - Options: `--branch`, `--execute`, `--json`, `--output`, `--repository`
363
+ - Syntax:
364
+
365
+ ```text
366
+ buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe> --repository <owner/repo> --branch <dev/vN/vN.M> [--execute] [--output <file>] [--json]
367
+ ```
368
+
369
+ ### `buildchain dev warrant submit`
370
+
371
+ - Help: `buildchain dev warrant submit --help`
372
+ - Canonical id: `dev`
373
+ - Options: `--branch`, `--execute`, `--json`, `--output`, `--repository`
374
+ - Syntax:
375
+
376
+ ```text
377
+ buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe> --repository <owner/repo> --branch <dev/vN/vN.M> [--execute] [--output <file>] [--json]
378
+ ```
379
+
226
380
  ## `diagnostics`
227
381
 
228
382
  ### `buildchain diagnostics`
@@ -8,12 +8,12 @@ confidence: high
8
8
  sensitivity: public
9
9
  evidence_grade: A
10
10
  review_state: self-reviewed
11
- last_reviewed: 2026-08-03
11
+ last_reviewed: 2026-08-04
12
12
  ai_provenance:
13
13
  model_family: GPT-5
14
14
  product: Codex
15
- generated_at: 2026-07-29
16
- visible_context: Existing Buildchain source locks, Kungfu exact-source Alpha preflight, Dev Patrol, protected auto-merge policy, repository release governance, and the consumer-owned settlement renderer threat model.
15
+ generated_at: 2026-08-04
16
+ visible_context: Existing Buildchain source locks, Kungfu exact-source Alpha preflight, Dev Patrol, cancelled duplicate runs, protected auto-merge policy, repository release governance, and the consumer-owned settlement renderer threat model.
17
17
  invisible_context_boundary: No credentials, private logs, or private configuration were used.
18
18
  ---
19
19
 
@@ -27,8 +27,10 @@ bounded development history from newest to oldest (stopping early at the Alpha
27
27
  head), and selects the newest commit that satisfies all of these conditions:
28
28
 
29
29
  - the source is strictly ahead of the recorded target head;
30
- - the latest completed Dev Patrol for that exact commit SHA succeeded;
31
- - the latest completed Alpha preflight for the same commit SHA succeeded; and
30
+ - the latest completed, non-cancelled Dev Patrol for that exact commit SHA
31
+ succeeded;
32
+ - the latest completed, non-cancelled Alpha preflight for the same commit SHA
33
+ succeeded; and
32
34
  - both runs are within the caller's evidence age limit.
33
35
 
34
36
  The selected commit can be behind the observed development head when newer
@@ -37,6 +39,12 @@ head, selected SHA, and count of skipped newer commits. This makes a slow native
37
39
  verification lane live under continuous development without silently treating
38
40
  an unqualified head as releasable.
39
41
 
42
+ A cancelled workflow run carries no qualification verdict, so a newer
43
+ cancelled duplicate does not erase the prior completed verdict for the same
44
+ workflow and source SHA. Other non-success conclusions remain authoritative:
45
+ a newer failed, timed-out, skipped, or otherwise non-successful completed run
46
+ still excludes that SHA and forces the controller to fall back or fail closed.
47
+
40
48
  History discovery is bounded to the newest 1000 development commits. The
41
49
  controller then compares the selected SHA to the exact Alpha head before it can
42
50
  be eligible, so a bounded scan cannot turn a commit outside the promotion