@kungfu-tech/buildchain 4.0.2-alpha.4 → 4.0.2-alpha.41

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 (153) hide show
  1. package/AGENTS.md +10 -1
  2. package/CONTRIBUTING.md +24 -0
  3. package/README.md +2 -2
  4. package/actions/promote-buildchain-ref/README.md +1 -1
  5. package/actions/v4-release-candidate-promote/README.md +28 -0
  6. package/architecture/agent-change-map.md +66 -7
  7. package/architecture/ci-lane-change-budget.json +366 -0
  8. package/architecture/internal-capabilities.json +52 -8
  9. package/architecture/maintainability-debt.json +148 -92
  10. package/architecture/maintainability-policy.json +34 -30
  11. package/architecture/release-tail-contract-inventory.json +6 -6
  12. package/architecture/v4-architecture-constitution.md +23 -20
  13. package/architecture/v4-cross-platform-adopter-qualification.json +1 -1
  14. package/architecture/v4-delivery-authority-parity.json +2 -2
  15. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.json +1 -1
  16. package/architecture/v4-floating-consumer-policy.json +2 -2
  17. package/architecture/v4-next-development-parity.json +5 -5
  18. package/architecture/v4-partial-mutation-recovery-qualification.json +4 -1
  19. package/architecture/v4-platform-stage-checkpoints.json +1 -1
  20. package/architecture/v4-provider-operation-journal-contract.json +5 -2
  21. package/architecture/v4-publication-facade-patches.json +64 -0
  22. package/architecture/v4-release-activation-shadow-domain.json +5 -2
  23. package/architecture/v4-release-topology.json +143 -35
  24. package/architecture/v4-rust-wasm-production-authority.json +58 -0
  25. package/architecture/v4-stable-publication-fence.json +5 -2
  26. package/architecture/v4-stage-capsule-qualification.json +2 -2
  27. package/architecture/v4-tail-reseal-parity.json +8 -6
  28. package/architecture/v4-universal-workflow-bootstrap.json +171 -0
  29. package/architecture/v4-universal-workflow-fault-campaign.json +72 -0
  30. package/architecture/v4-universal-workflow-train-admission.json +40 -0
  31. package/architecture/workflow-taxonomy.json +1451 -0
  32. package/bin/buildchain.mjs +7 -7
  33. package/contracts/buildchain-v2-residuals-v1.json +57 -48
  34. package/contracts/dev-delivery-authority-v2.schema.json +16 -2
  35. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  36. package/contracts/v4-canonical-contracts-v1.schema.json +1 -0
  37. package/dist/site/buildchain-contract.json +93 -48
  38. package/dist/site/buildchain-site.json +222 -69
  39. package/dist/site/capability-registry.json +4 -4
  40. package/dist/site/controller-registry.json +50 -13
  41. package/dist/site/kfd-claims.json +2569 -982
  42. package/dist/site/kfd-upstream-aggregate.json +1 -1
  43. package/dist/site/manual-registry.json +13 -13
  44. package/dist/site/node-api-registry.json +88 -83
  45. package/dist/site/page-registry.json +204 -51
  46. package/dist/site/public-surface-audit.json +3207 -1219
  47. package/dist/site/publication-authority-registry.json +1124 -362
  48. package/dist/site/publication-registry.json +4 -4
  49. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
  50. package/dist/site/site-manifest.json +17 -17
  51. package/dist/site/workflow-registry.json +5063 -1659
  52. package/docs/MAP.md +1 -0
  53. package/docs/auditable-demo.md +1 -1
  54. package/docs/cli.md +3 -3
  55. package/docs/dev-delivery-warrant.md +1 -1
  56. package/docs/engineering-housekeeper.md +3 -3
  57. package/docs/kfd-support.md +26 -2
  58. package/docs/next-development-transition.md +2 -2
  59. package/docs/node-api-reference.md +129 -129
  60. package/docs/publication-authority.md +2 -2
  61. package/docs/release-candidate.md +3 -3
  62. package/docs/release-flow.md +67 -19
  63. package/docs/release-governance.md +8 -8
  64. package/docs/release-passport.md +27 -2
  65. package/docs/reusable-build-surface.md +16 -0
  66. package/docs/v4-adopter-delivery.md +2 -2
  67. package/docs/v4-production-release.md +71 -8
  68. package/docs/v4-rust-wasm-production-authority.md +58 -0
  69. package/docs/v4-stage-capsule.md +2 -2
  70. package/docs/v4-tail-reseal.md +1 -1
  71. package/docs/workflow-catalog.md +154 -0
  72. package/docs/workflow-path-migration.md +109 -0
  73. package/package.json +10 -6
  74. package/packages/core/artifact-verification-envelope.js +5 -5
  75. package/packages/core/buildchain-contract.js +1 -1
  76. package/packages/core/buildchain-kfd-claims.js +2 -2
  77. package/packages/core/buildchain-publication-authority.js +42 -26
  78. package/packages/core/buildchain-v4-domain.wasm +0 -0
  79. package/packages/core/ci-lane-change-budget.js +14 -1
  80. package/packages/core/controller-evidence.js +4 -1
  81. package/packages/core/dev-delivery-candidate-identity.js +40 -6
  82. package/packages/core/dev-delivery-warrant-state.js +3 -4
  83. package/packages/core/dev-delivery-warrant.js +12 -2
  84. package/packages/core/github-governance-authority.js +4 -4
  85. package/packages/core/kfd-adopter-manifest.js +46 -47
  86. package/packages/core/next-development-projection.js +2 -2
  87. package/packages/core/release-line-dry-run.js +1 -1
  88. package/packages/core/release-passport-contract.js +5 -5
  89. package/packages/core/release-passport.js +5 -4
  90. package/packages/core/release-tail-product-capabilities.js +29 -0
  91. package/packages/core/release-tail-provider-plane.js +68 -1048
  92. package/packages/core/v4-canonical-contracts.js +14 -75
  93. package/packages/core/v4-domain-wasm-artifact.js +7 -0
  94. package/packages/core/v4-domain-wasm.js +216 -0
  95. package/packages/core/v4-floating-consumer-evidence.js +1 -1
  96. package/packages/core/v4-floating-consumer-policy.js +1 -1
  97. package/packages/core/v4-partial-mutation-recovery-qualification.js +9 -386
  98. package/packages/core/v4-product-publication.js +57 -0
  99. package/packages/core/v4-protected-publication-source.js +19 -21
  100. package/packages/core/v4-provider-operation-journal.js +18 -487
  101. package/packages/core/v4-provider-readback-idempotency.js +12 -97
  102. package/packages/core/v4-release-activation-shadow.js +13 -500
  103. package/packages/core/v4-release-invocation.js +28 -389
  104. package/packages/core/v4-stable-publication-fence.js +13 -342
  105. package/packages/core/v4-universal-workflow-bootstrap.js +586 -0
  106. package/scripts/binary-publication-evidence.mjs +135 -0
  107. package/scripts/build-contract-core.mjs +1 -14
  108. package/scripts/build-v4-domain-wasm.mjs +189 -0
  109. package/scripts/check-action-bundles.mjs +12 -2
  110. package/scripts/check-ci-lane-change-budget.mjs +4 -1
  111. package/scripts/check-core-mechanism-inventory.mjs +4 -3
  112. package/scripts/check-inventory.mjs +35 -44
  113. package/scripts/check-maintainability.mjs +16 -113
  114. package/scripts/check-v4-floating-consumer-policy-contract.mjs +2 -2
  115. package/scripts/check-v4-public-dogfood-contract.mjs +22 -9
  116. package/scripts/check-v4-release-topology.mjs +214 -50
  117. package/scripts/check-v4-runtime-semantic-closure.mjs +4 -1
  118. package/scripts/check-v4-universal-workflow-bootstrap.mjs +266 -0
  119. package/scripts/check-workflow-taxonomy.mjs +6 -0
  120. package/scripts/copy-v4-domain-wasm.mjs +14 -0
  121. package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
  122. package/scripts/dev-delivery-authority.mjs +8 -8
  123. package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
  124. package/scripts/dev-delivery-warrant-options.mjs +14 -9
  125. package/scripts/dev-delivery-warrant-store.mjs +73 -7
  126. package/scripts/dev-delivery-warrant-transition.mjs +109 -0
  127. package/scripts/dev-delivery-warrant.mjs +76 -99
  128. package/scripts/dev-pr-auto-merge.mjs +15 -15
  129. package/scripts/generate-channel-build-workflow.mjs +7 -2
  130. package/scripts/generate-channel-promotion-workflow.mjs +7 -5
  131. package/scripts/generate-site-bundle.mjs +11 -11
  132. package/scripts/generate-v4-universal-workflow-facades.mjs +458 -0
  133. package/scripts/generate-workflow-taxonomy.mjs +25 -0
  134. package/scripts/github-output.mjs +31 -0
  135. package/scripts/maintainability-metrics.mjs +16 -5
  136. package/scripts/maintainability-public-surface.mjs +115 -0
  137. package/scripts/next-development-review.mjs +307 -0
  138. package/scripts/release-asset-client.mjs +91 -0
  139. package/scripts/release-candidate-resolver.mjs +17 -18
  140. package/scripts/resume-from-candidate-run.mjs +1 -1
  141. package/scripts/source-verification-evidence.mjs +344 -0
  142. package/scripts/stable-candidate-qualification.mjs +1 -1
  143. package/scripts/universal-facade-maintainability.mjs +82 -0
  144. package/scripts/v4-product-publication-intent.mjs +121 -0
  145. package/scripts/v4-publication-settlement.mjs +211 -0
  146. package/scripts/v4-universal-workflow-backflow.mjs +212 -0
  147. package/scripts/v4-universal-workflow-engine.mjs +618 -0
  148. package/scripts/v4-universal-workflow-self-dogfood.mjs +205 -0
  149. package/scripts/verify-version-state-delta.mjs +173 -0
  150. package/scripts/workflow-taxonomy.mjs +507 -0
  151. package/templates/native-dev-delivery.yml +4 -7
  152. package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
  153. package/templates/universal-buildchain-bootstrap.yml +28 -0
@@ -1,22 +1,5 @@
1
- import {
2
- V4ContractFault,
3
- v4ContentRoot,
4
- validateV4Clock,
5
- validateV4Root,
6
- } from "./v4-canonical-contracts.js";
7
- import {
8
- V4_PROVIDER_OPERATION_ATTEMPT_CONTRACT,
9
- V4_PROVIDER_OPERATION_CONFIRMATION_CONTRACT,
10
- V4_PROVIDER_OPERATION_INTENT_CONTRACT,
11
- V4_PROVIDER_OPERATION_OBSERVATION_CONTRACT,
12
- V4_PROVIDER_OPERATION_RECONCILIATION_CONTRACT,
13
- foldV4ProviderOperationJournal,
14
- v4ProviderOperationEntryRoot,
15
- v4ProviderOperationJournalRoot,
16
- v4ProviderOperationJournalStateRoot,
17
- v4ProviderOperationRoot,
18
- validateV4ProviderOperationIdentity,
19
- } from "./v4-provider-operation-journal.js";
1
+ import { V4ContractFault } from "./v4-canonical-contracts.js";
2
+ import { V4DomainWasmFault, invokeV4DomainWasm } from "./v4-domain-wasm.js";
20
3
 
21
4
  export const V4_RELEASE_ACTIVATION_REQUEST_CONTRACT =
22
5
  "buildchain-v4-release-activation-request/v1";
@@ -25,495 +8,25 @@ export const V4_RELEASE_ACTIVATION_PLAN_CONTRACT =
25
8
  export const V4_RELEASE_ACTIVATION_STATE_CONTRACT =
26
9
  "buildchain-v4-release-activation-state/v1";
27
10
 
28
- const TOKEN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
29
-
30
- function fault(code, path, message) {
31
- throw new V4ContractFault(code, path, message);
32
- }
33
-
34
- function exactKeys(value, expected, path) {
35
- if (!value || typeof value !== "object" || Array.isArray(value))
36
- fault(
37
- "invalid-release-activation-shape",
38
- path,
39
- `${path} must be an object`,
40
- );
41
- const actual = Object.keys(value).sort();
42
- const canonical = [...expected].sort();
43
- if (
44
- actual.length !== canonical.length ||
45
- actual.some((key, index) => key !== canonical[index])
46
- )
47
- fault(
48
- "invalid-release-activation-shape",
49
- path,
50
- `${path} keys do not match the closed activation contract`,
51
- );
52
- }
53
-
54
- function token(value, path) {
55
- if (typeof value !== "string" || !TOKEN.test(value))
56
- fault(
57
- "invalid-release-activation-token",
58
- path,
59
- `${path} must be an ASCII token`,
60
- );
61
- }
62
-
63
- function normalizeTokens(values, path) {
64
- if (!Array.isArray(values))
65
- fault("invalid-release-activation-shape", path, `${path} must be an array`);
66
- for (const [index, value] of values.entries())
67
- token(value, `${path}/${index}`);
68
- const sorted = [...values].sort();
69
- if (new Set(sorted).size !== sorted.length)
70
- fault(
71
- "duplicate-release-activation-dependency",
72
- path,
73
- `${path} must not contain duplicate values`,
74
- );
75
- return sorted;
76
- }
77
-
78
- function normalizeRoots(values, path) {
79
- if (!Array.isArray(values) || values.length === 0)
80
- fault(
81
- "unrooted-release-activation-observation",
82
- path,
83
- `${path} must contain rooted provider-neutral evidence`,
84
- );
85
- for (const [index, value] of values.entries())
86
- validateV4Root(value, `${path}/${index}`);
87
- const sorted = [...values].sort();
88
- if (new Set(sorted).size !== sorted.length)
89
- fault(
90
- "duplicate-release-activation-observation-root",
91
- path,
92
- `${path} must not contain duplicate roots`,
93
- );
94
- return sorted;
95
- }
96
-
97
- function validateCoordinates(request) {
98
- validateV4Root(request.transactionRoot, "$/transactionRoot");
99
- if (request.qualificationRoot === null)
100
- fault(
101
- "missing-release-activation-qualification",
102
- "$/qualificationRoot",
103
- "release activation requires an explicit qualification root",
104
- );
105
- validateV4Root(request.qualificationRoot, "$/qualificationRoot");
106
- validateV4Root(request.authorityRoot, "$/authorityRoot");
107
- validateV4Root(request.policyRoot, "$/policyRoot");
108
- validateV4Clock(request.declaredAt, "$/declaredAt");
109
- }
110
-
111
- function normalizeSteps(request) {
112
- if (!Array.isArray(request.steps) || request.steps.length === 0)
113
- fault(
114
- "invalid-release-activation-plan",
115
- "$/steps",
116
- "release activation requires at least one step",
117
- );
118
- const normalized = request.steps.map((step, index) => {
119
- const path = `$/steps/${index}`;
120
- exactKeys(
121
- step,
122
- ["id", "dependencies", "operation", "compensationBoundaryRoot"],
123
- path,
124
- );
125
- token(step.id, `${path}/id`);
126
- validateV4ProviderOperationIdentity(step.operation);
127
- validateV4Root(
128
- step.compensationBoundaryRoot,
129
- `${path}/compensationBoundaryRoot`,
130
- );
131
- if (
132
- step.operation.transactionRoot !== request.transactionRoot ||
133
- step.operation.authorityRoot !== request.authorityRoot ||
134
- step.operation.policyRoot !== request.policyRoot
135
- )
136
- fault(
137
- "release-activation-authority-mismatch",
138
- `${path}/operation`,
139
- "step operation coordinates must match the qualified activation request",
140
- );
141
- const operationRoot = v4ProviderOperationRoot(step.operation);
142
- const payload = {
143
- id: step.id,
144
- dependencies: normalizeTokens(step.dependencies, `${path}/dependencies`),
145
- operation: structuredClone(step.operation),
146
- operationRoot,
147
- compensationBoundaryRoot: step.compensationBoundaryRoot,
148
- };
149
- return {
150
- ...payload,
151
- stepRoot: v4ContentRoot("release-activation-step", payload),
152
- };
153
- });
154
- normalized.sort((left, right) =>
155
- left.id < right.id ? -1 : left.id > right.id ? 1 : 0,
156
- );
157
- if (new Set(normalized.map(({ id }) => id)).size !== normalized.length)
158
- fault(
159
- "duplicate-release-activation-step",
160
- "$/steps",
161
- "release activation step ids must be unique",
162
- );
163
- if (
164
- new Set(normalized.map(({ operationRoot }) => operationRoot)).size !==
165
- normalized.length
166
- )
167
- fault(
168
- "conflicting-release-activation-operation",
169
- "$/steps",
170
- "one logical provider operation cannot be owned by multiple activation steps",
171
- );
172
- const byId = new Map(normalized.map((step) => [step.id, step]));
173
- for (const step of normalized)
174
- for (const dependency of step.dependencies)
175
- if (!byId.has(dependency) || dependency === step.id)
176
- fault(
177
- "invalid-release-activation-dependency",
178
- `$/steps/${step.id}/dependencies`,
179
- "dependencies must name another declared activation step",
180
- );
181
- const visiting = new Set();
182
- const visited = new Set();
183
- const visit = (step) => {
184
- if (visiting.has(step.id))
185
- fault(
186
- "release-activation-dependency-cycle",
187
- `$/steps/${step.id}/dependencies`,
188
- "release activation dependencies must be acyclic",
189
- );
190
- if (visited.has(step.id)) return;
191
- visiting.add(step.id);
192
- for (const dependency of step.dependencies) visit(byId.get(dependency));
193
- visiting.delete(step.id);
194
- visited.add(step.id);
195
- };
196
- for (const step of normalized) visit(step);
197
- return normalized;
198
- }
199
-
200
- function normalizeEvent(event, index, steps) {
201
- const path = `$/events/${index}`;
202
- const common = ["kind", "stepId", "ordinal"];
203
- const specific = {
204
- attempt: ["attemptedAt", "effectRoot"],
205
- observation: ["observedAt", "status", "evidenceRoots"],
206
- reconciliation: ["reconciledAt", "disposition", "authorityRoot"],
207
- confirmation: ["confirmedAt", "outcome", "authorityRoot"],
208
- };
209
- if (!specific[event?.kind])
210
- fault(
211
- "invalid-release-activation-event",
212
- `${path}/kind`,
213
- "release activation event kind is unsupported",
214
- );
215
- exactKeys(event, [...common, ...specific[event.kind]], path);
216
- token(event.stepId, `${path}/stepId`);
217
- if (!steps.has(event.stepId))
218
- fault(
219
- "invalid-release-activation-event",
220
- `${path}/stepId`,
221
- "event must name a declared activation step",
222
- );
223
- if (!Number.isSafeInteger(event.ordinal) || event.ordinal < 1)
224
- fault(
225
- "invalid-release-activation-ordinal",
226
- `${path}/ordinal`,
227
- "event ordinal must be a positive safe integer",
228
- );
229
- const normalized = structuredClone(event);
230
- if (event.kind === "attempt") {
231
- validateV4Clock(event.attemptedAt, `${path}/attemptedAt`);
232
- validateV4Root(event.effectRoot, `${path}/effectRoot`);
233
- } else if (event.kind === "observation") {
234
- validateV4Clock(event.observedAt, `${path}/observedAt`);
235
- if (!["succeeded", "failed", "unknown"].includes(event.status))
236
- fault(
237
- "invalid-release-activation-observation",
238
- `${path}/status`,
239
- "observation status is unsupported",
240
- );
241
- normalized.evidenceRoots = normalizeRoots(
242
- event.evidenceRoots,
243
- `${path}/evidenceRoots`,
244
- );
245
- } else if (event.kind === "reconciliation") {
246
- validateV4Clock(event.reconciledAt, `${path}/reconciledAt`);
247
- validateV4Root(event.authorityRoot, `${path}/authorityRoot`);
248
- if (!["retry", "confirm", "terminal"].includes(event.disposition))
249
- fault(
250
- "invalid-release-activation-reconciliation",
251
- `${path}/disposition`,
252
- "reconciliation disposition is unsupported",
253
- );
254
- } else {
255
- validateV4Clock(event.confirmedAt, `${path}/confirmedAt`);
256
- validateV4Root(event.authorityRoot, `${path}/authorityRoot`);
257
- if (!["confirmed", "rejected"].includes(event.outcome))
258
- fault(
259
- "invalid-release-activation-confirmation",
260
- `${path}/outcome`,
261
- "confirmation outcome is unsupported",
262
- );
263
- }
264
- if (
265
- "authorityRoot" in normalized &&
266
- normalized.authorityRoot !== steps.get(event.stepId).operation.authorityRoot
267
- )
268
- fault(
269
- "release-activation-authority-mismatch",
270
- `${path}/authorityRoot`,
271
- "journal authority cannot differ from the planned operation authority",
272
- );
273
- return normalized;
274
- }
275
-
276
- function normalizeEvents(request, steps) {
277
- if (!Array.isArray(request.events))
278
- fault(
279
- "invalid-release-activation-shape",
280
- "$/events",
281
- "events must be an array",
282
- );
283
- const unique = new Map();
284
- for (const [index, event] of request.events.entries()) {
285
- const normalized = normalizeEvent(event, index, steps);
286
- const key = `${normalized.stepId}:${normalized.ordinal}`;
287
- const retained = unique.get(key);
288
- if (retained && JSON.stringify(retained) !== JSON.stringify(normalized))
289
- fault(
290
- "conflicting-release-activation-event",
291
- `$/events/${index}`,
292
- "one step ordinal cannot carry conflicting journal facts",
293
- );
294
- unique.set(key, retained ?? normalized);
295
- }
296
- const events = [...unique.values()].sort((left, right) => {
297
- if (left.stepId !== right.stepId)
298
- return left.stepId < right.stepId ? -1 : 1;
299
- return left.ordinal - right.ordinal;
300
- });
301
- const expected = new Map();
302
- for (const event of events) {
303
- const ordinal = (expected.get(event.stepId) ?? 0) + 1;
304
- if (event.ordinal !== ordinal)
305
- fault(
306
- "release-activation-event-gap",
307
- `$/events/${event.stepId}/${event.ordinal}`,
308
- "deduplicated event ordinals must be contiguous per step",
309
- );
310
- expected.set(event.stepId, ordinal);
11
+ function project(request) {
12
+ try {
13
+ return invokeV4DomainWasm("release-activation", request);
14
+ } catch (error) {
15
+ if (error instanceof V4DomainWasmFault) {
16
+ throw new V4ContractFault(error.code, error.path, error.message);
17
+ }
18
+ throw error;
311
19
  }
312
- return events;
313
- }
314
-
315
- function normalizeRequest(request) {
316
- exactKeys(
317
- request,
318
- [
319
- "schema",
320
- "declaredAt",
321
- "transactionRoot",
322
- "qualificationRoot",
323
- "authorityRoot",
324
- "policyRoot",
325
- "steps",
326
- "events",
327
- ],
328
- "$",
329
- );
330
- if (request.schema !== V4_RELEASE_ACTIVATION_REQUEST_CONTRACT)
331
- fault(
332
- "unsupported-release-activation-version",
333
- "$/schema",
334
- "unsupported release activation request schema",
335
- );
336
- validateCoordinates(request);
337
- const steps = normalizeSteps(request);
338
- const byId = new Map(steps.map((step) => [step.id, step]));
339
- return { steps, events: normalizeEvents(request, byId) };
340
20
  }
341
21
 
342
22
  export function planV4ReleaseActivation(request) {
343
- const { steps } = normalizeRequest(request);
344
- const payload = {
345
- schema: V4_RELEASE_ACTIVATION_PLAN_CONTRACT,
346
- mode: "production",
347
- productionAuthority: "v4",
348
- declaredAt: request.declaredAt,
349
- transactionRoot: request.transactionRoot,
350
- qualificationRoot: request.qualificationRoot,
351
- authorityRoot: request.authorityRoot,
352
- policyRoot: request.policyRoot,
353
- steps,
354
- };
355
- return {
356
- ...payload,
357
- planRoot: v4ContentRoot("release-activation-plan", payload),
358
- };
359
- }
360
-
361
- function rootedEntry(entry) {
362
- return { ...entry, entryRoot: v4ProviderOperationEntryRoot(entry) };
363
- }
364
-
365
- function materializeJournal(request, step, events) {
366
- const entries = [];
367
- const append = (entry) => {
368
- entries.push(rootedEntry(entry));
369
- return entries.at(-1);
370
- };
371
- append({
372
- kind: "intent",
373
- schema: V4_PROVIDER_OPERATION_INTENT_CONTRACT,
374
- sequence: 0,
375
- priorEntryRoot: null,
376
- operation: structuredClone(step.operation),
377
- operationRoot: step.operationRoot,
378
- declaredAt: request.declaredAt,
379
- inputRoot: request.qualificationRoot,
380
- });
381
- let attemptOrdinal = 0;
382
- let attemptRoot = null;
383
- let observationRoot = null;
384
- for (const event of events) {
385
- const common = {
386
- sequence: entries.length,
387
- priorEntryRoot: entries.at(-1).entryRoot,
388
- operationRoot: step.operationRoot,
389
- };
390
- if (event.kind === "attempt") {
391
- attemptOrdinal += 1;
392
- const entry = append({
393
- kind: "attempt",
394
- schema: V4_PROVIDER_OPERATION_ATTEMPT_CONTRACT,
395
- ...common,
396
- attemptOrdinal,
397
- attemptedAt: event.attemptedAt,
398
- effectRoot: event.effectRoot,
399
- });
400
- attemptRoot = entry.entryRoot;
401
- observationRoot = null;
402
- } else if (event.kind === "observation") {
403
- const entry = append({
404
- kind: "observation",
405
- schema: V4_PROVIDER_OPERATION_OBSERVATION_CONTRACT,
406
- ...common,
407
- attemptRoot: attemptRoot ?? request.qualificationRoot,
408
- observedAt: event.observedAt,
409
- status: event.status,
410
- evidenceRoots: event.evidenceRoots,
411
- });
412
- observationRoot = entry.entryRoot;
413
- } else if (event.kind === "reconciliation") {
414
- append({
415
- kind: "reconciliation",
416
- schema: V4_PROVIDER_OPERATION_RECONCILIATION_CONTRACT,
417
- ...common,
418
- observationRoot: observationRoot ?? request.qualificationRoot,
419
- authorityRoot: event.authorityRoot,
420
- reconciledAt: event.reconciledAt,
421
- disposition: event.disposition,
422
- });
423
- } else {
424
- append({
425
- kind: "confirmation",
426
- schema: V4_PROVIDER_OPERATION_CONFIRMATION_CONTRACT,
427
- ...common,
428
- observationRoot: observationRoot ?? request.qualificationRoot,
429
- authorityRoot: event.authorityRoot,
430
- confirmedAt: event.confirmedAt,
431
- outcome: event.outcome,
432
- });
433
- }
434
- }
435
- return entries;
23
+ return project(request).plan;
436
24
  }
437
25
 
438
26
  export function foldV4ReleaseActivation(request) {
439
- const normalized = normalizeRequest(request);
440
- const plan = planV4ReleaseActivation(request);
441
- const events = new Map(normalized.steps.map(({ id }) => [id, []]));
442
- for (const event of normalized.events) events.get(event.stepId).push(event);
443
- const confirmed = new Set();
444
- const failedSteps = [];
445
- const readbackSteps = [];
446
- const stepStates = normalized.steps.map((step) => {
447
- const retained = events.get(step.id);
448
- if (retained.length === 0)
449
- return {
450
- stepId: step.id,
451
- operationRoot: step.operationRoot,
452
- phase: "planned",
453
- journalRoot: null,
454
- journalStateRoot: null,
455
- entryCount: 0,
456
- attemptCount: 0,
457
- confirmationRoot: null,
458
- };
459
- const entries = materializeJournal(request, step, retained);
460
- const state = foldV4ProviderOperationJournal(entries);
461
- if (state.phase === "confirmed") confirmed.add(step.id);
462
- if (["rejected", "terminal"].includes(state.phase))
463
- failedSteps.push(step.id);
464
- if (["attempting", "observed", "confirmable"].includes(state.phase))
465
- readbackSteps.push(step.id);
466
- return {
467
- stepId: step.id,
468
- operationRoot: step.operationRoot,
469
- phase: state.phase,
470
- journalRoot: v4ProviderOperationJournalRoot(entries),
471
- journalStateRoot: v4ProviderOperationJournalStateRoot(entries),
472
- entryCount: state.entryCount,
473
- attemptCount: state.attemptCount,
474
- confirmationRoot: state.confirmationRoot,
475
- };
476
- });
477
- const eligibleSteps =
478
- failedSteps.length === 0
479
- ? normalized.steps
480
- .filter((step, index) => {
481
- const phase = stepStates[index].phase;
482
- return (
483
- ["planned", "intended", "retryable"].includes(phase) &&
484
- step.dependencies.every((dependency) => confirmed.has(dependency))
485
- );
486
- })
487
- .map(({ id }) => id)
488
- : [];
489
- const confirmedSteps = [...confirmed].sort();
490
- const phase =
491
- failedSteps.length > 0
492
- ? "blocked"
493
- : confirmedSteps.length === normalized.steps.length
494
- ? "complete"
495
- : "active";
496
- const payload = {
497
- schema: V4_RELEASE_ACTIVATION_STATE_CONTRACT,
498
- mode: "production",
499
- productionAuthority: "v4",
500
- planRoot: plan.planRoot,
501
- phase,
502
- stepStates,
503
- confirmedSteps,
504
- failedSteps,
505
- readbackSteps,
506
- eligibleSteps,
507
- };
508
- return {
509
- ...payload,
510
- stateRoot: v4ContentRoot("release-activation-state", payload),
511
- };
27
+ return project(request).state;
512
28
  }
513
29
 
514
30
  export function projectV4ReleaseActivation(request) {
515
- return {
516
- plan: planV4ReleaseActivation(request),
517
- state: foldV4ReleaseActivation(request),
518
- };
31
+ return project(request);
519
32
  }