@kungfu-tech/buildchain 4.1.2-alpha.0 → 4.1.3-alpha.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.
Files changed (61) hide show
  1. package/CONTRIBUTING.md +7 -4
  2. package/architecture/action-taxonomy.json +4 -0
  3. package/architecture/agent-change-map.md +40 -0
  4. package/architecture/internal-capabilities.json +49 -0
  5. package/architecture/maintainability-debt.json +2 -1
  6. package/architecture/maintainability-policy.json +4 -4
  7. package/architecture/release-topology.json +11 -1
  8. package/architecture/universal-workflow-bootstrap.json +13 -2
  9. package/architecture/universal-workflow-capability-policy.json +15 -9
  10. package/contracts/promotion-invocation-v1.schema.json +6 -3
  11. package/contracts/promotion-request-v1.schema.json +6 -3
  12. package/contracts/release-discussion-v1.schema.json +140 -0
  13. package/dist/readers/release-discussion.cjs +203 -0
  14. package/dist/site/buildchain-contract.json +15 -11
  15. package/dist/site/buildchain-site.json +59 -8
  16. package/dist/site/capability-registry.json +3 -3
  17. package/dist/site/kfd-claims.json +95 -9
  18. package/dist/site/kfd-upstream-aggregate.json +1 -1
  19. package/dist/site/manual-registry.json +1 -1
  20. package/dist/site/node-api-registry.json +83 -1
  21. package/dist/site/page-registry.json +54 -3
  22. package/dist/site/public-surface-audit.json +53 -7
  23. package/dist/site/publication-registry.json +4 -4
  24. package/dist/site/release-provenance.json +2 -1
  25. package/dist/site/site-manifest.json +5 -5
  26. package/dist/site/workflow-registry.json +79 -7
  27. package/docs/node-api-reference.md +9 -0
  28. package/docs/release-discussions.md +154 -0
  29. package/package.json +10 -6
  30. package/packages/core/providers/github/discussions/materials.js +146 -0
  31. package/packages/core/providers/github/discussions/transport.js +115 -0
  32. package/packages/core/publication/binary/action.js +21 -7
  33. package/packages/core/release/discussion/actions.js +65 -0
  34. package/packages/core/release/discussion/binary.js +92 -0
  35. package/packages/core/release/discussion/checkpoints.js +241 -0
  36. package/packages/core/release/discussion/envelope.js +141 -0
  37. package/packages/core/release/discussion/publication.js +121 -0
  38. package/packages/core/release/discussion/qualification.js +121 -0
  39. package/packages/core/release/discussion/reader-entry.js +11 -0
  40. package/packages/core/release/discussion/reader.js +168 -0
  41. package/packages/core/release/discussion/recovery.js +132 -0
  42. package/packages/core/release/discussion/session.js +113 -0
  43. package/packages/core/release/discussion/store.js +169 -0
  44. package/packages/core/release/github-release.js +3 -1
  45. package/packages/core/release/promote-candidate/action.js +86 -6
  46. package/packages/core/release/promote-candidate/preparation.js +106 -0
  47. package/packages/core/release/promote-candidate/product-provider.js +4 -1
  48. package/packages/core/release/promote-candidate/provider-settlement.js +36 -23
  49. package/packages/core/release/promote-candidate/transaction.js +55 -97
  50. package/packages/core/release/promotion/candidate.js +11 -2
  51. package/packages/core/release/promotion/qualification.js +5 -2
  52. package/packages/core/release/promotion-request.js +8 -4
  53. package/packages/core/workflow/engine/execution.js +5 -1
  54. package/packages/core/workflow/engine/provider-context.js +2 -0
  55. package/packages/core/workflow/engine/release-observation.js +1 -0
  56. package/packages/core/workflow/engine/release-promotion.js +38 -26
  57. package/packages/core/workflow/universal-workflow-bootstrap.js +1 -0
  58. package/scripts/build-release-discussion-reader.mjs +34 -0
  59. package/scripts/inventory/binary.mjs +1 -1
  60. package/scripts/maintainability-metrics.mjs +1 -0
  61. package/scripts/site-capability-metadata.mjs +1 -0
@@ -0,0 +1,203 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // packages/core/release/discussion/reader-entry.js
30
+ var reader_entry_exports = {};
31
+ __export(reader_entry_exports, {
32
+ decodeRecord: () => decodeRecord,
33
+ readReleaseDiscussion: () => readReleaseDiscussion
34
+ });
35
+ module.exports = __toCommonJS(reader_entry_exports);
36
+ var import_node_fs = __toESM(require("fs"), 1);
37
+
38
+ // packages/core/release/discussion/envelope.js
39
+ var import_node_crypto = require("crypto");
40
+ var ENVELOPE_SCHEMA = "buildchain.discussion-record/v1";
41
+ var INTENT_SCHEMA = "buildchain.release-discussion/v1";
42
+ var PAYLOAD_SCHEMA = "buildchain.release-progress/v1";
43
+ var MARKER = "<!-- buildchain-transaction\n";
44
+ var MAX_RECORD_BYTES = 48e3;
45
+ function canonicalJson(value) {
46
+ if (typeof value === "number" && !Number.isFinite(value))
47
+ throw new Error("Transaction numbers must be finite");
48
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
49
+ if (value && typeof value === "object")
50
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
51
+ const encoded = JSON.stringify(value);
52
+ if (encoded === void 0)
53
+ throw new Error("Transaction records must contain JSON values");
54
+ return encoded;
55
+ }
56
+ function recordDigest(value) {
57
+ return `sha256:${(0, import_node_crypto.createHash)("sha256").update(canonicalJson(value)).digest("hex")}`;
58
+ }
59
+ function validateRuntime(runtime) {
60
+ if (!/^[\w.-]+\/[\w.-]+$/u.test(runtime?.repository || "") || !/^[a-f0-9]{40}$/u.test(runtime?.sha || "") || !/^sha256:[a-f0-9]{64}$/u.test(runtime?.readerDigest || ""))
61
+ throw new Error(
62
+ "Record requires selected runtime repository, exact revision and reader digest"
63
+ );
64
+ return runtime;
65
+ }
66
+ function decodeRecord(body) {
67
+ if (typeof body !== "string" || !body.includes(MARKER)) return void 0;
68
+ if (Buffer.byteLength(body) > MAX_RECORD_BYTES)
69
+ throw new Error("Oversized transaction record");
70
+ const start = body.indexOf(MARKER) + MARKER.length;
71
+ const end = body.indexOf("\n-->", start);
72
+ if (end < 0 || body.indexOf(MARKER, start) >= 0)
73
+ throw new Error("Malformed transaction envelope");
74
+ const record = JSON.parse(body.slice(start, end));
75
+ if (![ENVELOPE_SCHEMA, INTENT_SCHEMA].includes(record.schema))
76
+ throw new Error("Unsupported transaction envelope schema");
77
+ return record;
78
+ }
79
+
80
+ // packages/core/release/discussion/reader.js
81
+ function readReleaseDiscussion({ body, records }) {
82
+ const intent = decodeRecord(body);
83
+ if (intent?.schema !== INTENT_SCHEMA)
84
+ throw new Error("Missing release Discussion intent");
85
+ if (intent.id !== recordDigest({ repository: intent.repository, key: intent.key }))
86
+ throw new Error("Release intent identity mismatch");
87
+ if (!Array.isArray(intent.expectedNodes) || !intent.expectedNodes.length || new Set(intent.expectedNodes).size !== intent.expectedNodes.length)
88
+ throw new Error("Missing or duplicate expected nodes");
89
+ const attempts = groupAttempts(validateRecords(intent, records));
90
+ if (!attempts.size)
91
+ return {
92
+ intent,
93
+ status: "pending",
94
+ attempts: [],
95
+ missingNodes: intent.expectedNodes
96
+ };
97
+ const { head, lineage } = resolveLineage(attempts);
98
+ const nodes = currentNodes(attempts.get(head).events);
99
+ const missingNodes = intent.expectedNodes.filter((node) => !nodes[node]);
100
+ const complete = intent.expectedNodes.every(
101
+ (node) => nodes[node]?.status === "success"
102
+ );
103
+ const failed = Object.values(nodes).some(
104
+ (event) => ["failure", "cancelled"].includes(event.status)
105
+ );
106
+ return {
107
+ intent,
108
+ attempt: head,
109
+ attempts: lineage.reverse(),
110
+ nodes,
111
+ missingNodes,
112
+ status: complete ? "complete" : failed ? "failed" : "running",
113
+ handoff: {
114
+ schema: "buildchain.release-handoff/v1",
115
+ intent: intent.id,
116
+ predecessor: head,
117
+ completedNodes: intent.expectedNodes.filter(
118
+ (node) => nodes[node]?.status === "success"
119
+ )
120
+ }
121
+ };
122
+ }
123
+ function validateRecords(intent, records) {
124
+ const events = /* @__PURE__ */ new Map();
125
+ for (const raw of records) {
126
+ const event = typeof raw === "string" ? decodeRecord(raw) : raw;
127
+ if (!event) continue;
128
+ validateRuntime(event.runtime);
129
+ if (!["progress", "checkpoint"].includes(event.kind) || !event.writer || !event.attempt || typeof event.predecessor !== "string")
130
+ throw new Error("Invalid record ownership");
131
+ const { id, ...content } = event;
132
+ if (event.schema !== ENVELOPE_SCHEMA || event.payloadSchema !== PAYLOAD_SCHEMA)
133
+ throw new Error("Record requires its historical runtime reader");
134
+ if (event.intent !== intent.id || id !== recordDigest(content))
135
+ throw new Error("Release record identity mismatch");
136
+ if (event.node !== "attempt" && !intent.expectedNodes.includes(event.node))
137
+ throw new Error("Undeclared release node");
138
+ if (!["running", "success", "failure", "cancelled"].includes(event.status) || !Number.isSafeInteger(event.sequence) || event.sequence < 0)
139
+ throw new Error("Invalid release progress");
140
+ events.set(id, event);
141
+ }
142
+ return events;
143
+ }
144
+ function groupAttempts(events) {
145
+ const attempts = /* @__PURE__ */ new Map();
146
+ for (const event of events.values()) {
147
+ const attempt = attempts.get(event.attempt) || {
148
+ predecessor: event.predecessor,
149
+ events: []
150
+ };
151
+ if (attempt.predecessor !== event.predecessor)
152
+ throw new Error("Conflicting workflow attempt identity");
153
+ attempt.events.push(event);
154
+ attempts.set(event.attempt, attempt);
155
+ }
156
+ return attempts;
157
+ }
158
+ function resolveLineage(attempts) {
159
+ const predecessors = new Set(
160
+ [...attempts.values()].map((attempt) => attempt.predecessor).filter(Boolean)
161
+ );
162
+ for (const predecessor of predecessors)
163
+ if (!attempts.has(predecessor))
164
+ throw new Error("Recovery predecessor is missing");
165
+ const heads = [...attempts.keys()].filter((id) => !predecessors.has(id));
166
+ if (heads.length !== 1)
167
+ throw new Error("Release attempt succession is ambiguous or cyclic");
168
+ const lineage = [];
169
+ let current = heads[0];
170
+ while (current) {
171
+ if (lineage.includes(current)) throw new Error("Cyclic recovery chain");
172
+ lineage.push(current);
173
+ current = attempts.get(current).predecessor;
174
+ }
175
+ if (lineage.length !== attempts.size)
176
+ throw new Error("Disconnected recovery chain");
177
+ return { head: heads[0], lineage };
178
+ }
179
+ function currentNodes(events) {
180
+ const nodes = {}, sequences = /* @__PURE__ */ new Map();
181
+ for (const event of events) {
182
+ if (event.kind === "checkpoint") continue;
183
+ const key = `${event.node}:${event.sequence}`;
184
+ if (sequences.has(key) && sequences.get(key) !== event.id)
185
+ throw new Error("Conflicting node progress at the same sequence");
186
+ sequences.set(key, event.id);
187
+ const old = nodes[event.node];
188
+ if (!old || old.sequence < event.sequence) nodes[event.node] = event;
189
+ }
190
+ return nodes;
191
+ }
192
+
193
+ // packages/core/release/discussion/reader-entry.js
194
+ if (typeof require !== "undefined" && require.main === module) {
195
+ const input = JSON.parse(import_node_fs.default.readFileSync(0, "utf8"));
196
+ process.stdout.write(`${JSON.stringify(readReleaseDiscussion(input))}
197
+ `);
198
+ }
199
+ // Annotate the CommonJS export names for ESM import in node:
200
+ 0 && (module.exports = {
201
+ decodeRecord,
202
+ readReleaseDiscussion
203
+ });
@@ -4,7 +4,7 @@
4
4
  "product": {
5
5
  "name": "Buildchain",
6
6
  "package": "@kungfu-tech/buildchain",
7
- "version": "4.1.2-alpha.0",
7
+ "version": "4.1.3-alpha.0",
8
8
  "repository": "https://github.com/kungfu-systems/buildchain"
9
9
  },
10
10
  "majorLine": "v4",
@@ -250,6 +250,8 @@
250
250
  "controller-receipt-digest",
251
251
  "controller-receipt-json",
252
252
  "controller-receipt-status",
253
+ "discussion-id",
254
+ "discussion-url",
253
255
  "github-artifact-attestation-evidence-root",
254
256
  "github-artifact-attestation-id",
255
257
  "github-artifact-attestation-publication-receipt-digest",
@@ -285,8 +287,8 @@
285
287
  "release-tail-transaction-state",
286
288
  "release-transaction-root"
287
289
  ],
288
- "breakingDigest": "sha256:a32cbccc2a4b6e1a16f9feba892a1e8d4b8db0098ff63ea2e9719e985da64a7c",
289
- "auditDigest": "sha256:93b4545f1b37650a575f8a7cd8d18410eb37549229b47a771912521ff030da79"
290
+ "breakingDigest": "sha256:c9727056289fc47fbd3bd5f1d0b39b9816f2d6828f3262587aec53e5062da7f1",
291
+ "auditDigest": "sha256:ba4112f3b5f9c896f61462cebe3f5458a13d315499aced829bddc30830ff6969"
290
292
  },
291
293
  {
292
294
  "contractVersion": 1,
@@ -322,6 +324,8 @@
322
324
  "controller-receipt-digest",
323
325
  "controller-receipt-json",
324
326
  "controller-receipt-status",
327
+ "discussion-id",
328
+ "discussion-url",
325
329
  "github-artifact-attestation-evidence-root",
326
330
  "github-artifact-attestation-id",
327
331
  "github-artifact-attestation-publication-receipt-digest",
@@ -346,8 +350,8 @@
346
350
  "release-tail-transaction-state",
347
351
  "release-transaction-root"
348
352
  ],
349
- "breakingDigest": "sha256:3130cd971f83ef8fb44cbe3ea0e25c95b65693aaab15b6cc4e5a1e3657f2b6ee",
350
- "auditDigest": "sha256:0db2252d311d3db96afb72636fb76c17229800aa1c1cde202ee6a097c36c534a"
353
+ "breakingDigest": "sha256:64b800e0189286f5bc8615f8f1a0ee1ba2420a79dc6ec77b14e96619ef4dd094",
354
+ "auditDigest": "sha256:212545ad11011e703d17bb346787362730167743c2110e81a8b32d6c0493d509"
351
355
  },
352
356
  {
353
357
  "contractVersion": 1,
@@ -598,7 +602,7 @@
598
602
  "no consumer command, script, shell, checkout, or executable tail hook is accepted"
599
603
  ],
600
604
  "breakingDigest": "sha256:930a8c3bb97347aea40ab19c4ee1dc29c1f4b75897e19bc0d56da1018fa382c8",
601
- "auditDigest": "sha256:17c4a1b24c1afb1c5e6b2226489878de5158287c931ef5e5c690221f594fd98f"
605
+ "auditDigest": "sha256:5d3a78e4f2499a8638f20dd4adfa976d0bd82f4f4cdf619dce080c22b5188336"
602
606
  },
603
607
  {
604
608
  "contractVersion": 1,
@@ -981,7 +985,7 @@
981
985
  "manual entries carry source file digests so downstream sites and agents can detect stale hand-written documentation"
982
986
  ],
983
987
  "breakingDigest": "sha256:7d0d2819e3a3e72989d9c57b5efe9d0bc0a79bc0f2c82a0c7b9d6c5a211a91f2",
984
- "auditDigest": "sha256:83c04bec0c94e01071310ce4526f9059ccc88333dcdd29bc3d0c737d607d87d1"
988
+ "auditDigest": "sha256:0a81bae0763d7f3cbff96a0d46fc1d1e8030a2ac644136c138e857369e9fe7e1"
985
989
  },
986
990
  {
987
991
  "contractVersion": 1,
@@ -1003,7 +1007,7 @@
1003
1007
  "agents can discover supported Node APIs without importing internal file paths"
1004
1008
  ],
1005
1009
  "breakingDigest": "sha256:48f925608d3e2131d90936b07dc2a30341204cae3e6e785c0f77d61ad755c945",
1006
- "auditDigest": "sha256:e88cb115ee4261b72b5dc8a6f7c21d39e2f62a2bba3a39e9042cf96b053f4c36"
1010
+ "auditDigest": "sha256:21f345bfa78b36f65004d826035e1f113bf4ab46818076421d5b4fea7ff12f2a"
1007
1011
  },
1008
1012
  {
1009
1013
  "contractVersion": 1,
@@ -2182,7 +2186,7 @@
2182
2186
  "missing receipts are non-qualifying and must not be represented as a successful controller run"
2183
2187
  ],
2184
2188
  "breakingDigest": "sha256:884bc7c4dccbc561b1d22a20cc5f7f50172c9691775aa2b84179e036a138cb20",
2185
- "auditDigest": "sha256:0db2252d311d3db96afb72636fb76c17229800aa1c1cde202ee6a097c36c534a"
2189
+ "auditDigest": "sha256:212545ad11011e703d17bb346787362730167743c2110e81a8b32d6c0493d509"
2186
2190
  },
2187
2191
  {
2188
2192
  "contractVersion": 1,
@@ -2403,6 +2407,6 @@
2403
2407
  "compatibilityFactRegistryRoot": "sha256:ea8f656c9fd74aa2d2fb9b7807e7daa39a708f6a7cd37ab7d154eac7be5605a6",
2404
2408
  "compatibilityFactCutRoot": "sha256:58f33e498596505a26b6fc3c7ae5acef847ff699eee6c7e17a7b318a40bdf0d6",
2405
2409
  "compatibilityProofRegistryRoot": "sha256:2f6477405c7891b754b33ad6515d55618bd320e7cdc59330d7cc645e17201e72",
2406
- "compatibilityDigest": "sha256:b1088f1c224329b16cd23c285bc69334aa1ee102e5b44d5c09aaf156d76821b6",
2407
- "contractDigest": "sha256:c07ea3b02cc7d09eaf46b691f9f995968d85786339726e3ae58614d1ab91d82a"
2410
+ "compatibilityDigest": "sha256:14368a3f99f38a8c9c1e053f7ec3651766e3535237f4c551cc75417cf7ef97b3",
2411
+ "contractDigest": "sha256:279ca245e3de6aa314261c4452b228bc5518d4fdb9e79c447d996140c9326f8d"
2408
2412
  }