@kungfu-tech/buildchain 4.1.3 → 4.1.4

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 (199) hide show
  1. package/AGENTS.md +11 -13
  2. package/CONTRIBUTING.md +32 -9
  3. package/README.md +56 -140
  4. package/actions/release/promotion/ref/README.md +1 -1
  5. package/architecture/action-taxonomy.json +1 -1
  6. package/architecture/agent-change-map.md +32 -45
  7. package/architecture/build-orchestration.json +1 -1
  8. package/architecture/capability-state-machine-manifest.json +5 -5
  9. package/architecture/ci-lane-change-budget.json +92 -92
  10. package/architecture/code-layout.json +2 -12
  11. package/architecture/core-mechanisms.json +38 -39
  12. package/architecture/cross-platform-adopter-qualification.json +1 -1
  13. package/architecture/dev-delivery-orchestration.json +2 -2
  14. package/architecture/floating-consumer-policy.json +3 -3
  15. package/architecture/internal-capabilities.json +27 -28
  16. package/architecture/maintainability-debt.json +60 -94
  17. package/architecture/maintainability-policy.json +7 -13
  18. package/architecture/minimal-consumer-migration.json +43 -5014
  19. package/architecture/platform-stage-checkpoints.json +1 -1
  20. package/architecture/release-tail-contract.json +2 -2
  21. package/architecture/release-topology.json +31 -25
  22. package/architecture/stage-capsule-qualification.json +1 -1
  23. package/architecture/universal-workflow-bootstrap.json +60 -60
  24. package/architecture/universal-workflow-capability-policy.json +3 -3
  25. package/architecture/universal-workflow-fault-campaign.json +7 -7
  26. package/architecture/workflow-taxonomy.json +59 -60
  27. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  28. package/dist/site/buildchain-contract.json +138 -66
  29. package/dist/site/buildchain-site.json +257 -331
  30. package/dist/site/capability-registry.json +4 -4
  31. package/dist/site/cli-registry.json +6 -142
  32. package/dist/site/controller-registry.json +19 -19
  33. package/dist/site/kfd-claims.json +481 -529
  34. package/dist/site/kfd-upstream-aggregate.json +1 -1
  35. package/dist/site/manual-registry.json +22 -22
  36. package/dist/site/node-api-registry.json +82 -339
  37. package/dist/site/page-registry.json +229 -304
  38. package/dist/site/public-surface-audit.json +544 -754
  39. package/dist/site/publication-authority-registry.json +316 -316
  40. package/dist/site/publication-registry.json +1 -1
  41. package/dist/site/site-manifest.json +23 -23
  42. package/dist/site/workflow-registry.json +1071 -1027
  43. package/docs/MAP.md +28 -20
  44. package/docs/auditable-demo.md +17 -49
  45. package/docs/bootstrap-recovery.md +46 -37
  46. package/docs/cli-reference.md +2 -46
  47. package/docs/cli.md +97 -186
  48. package/docs/code-organization.md +7 -5
  49. package/docs/dev-alpha-candidate-patrol.md +19 -42
  50. package/docs/dev-delivery-orchestration.md +15 -11
  51. package/docs/dev-delivery-qualification-landing-adr.md +10 -9
  52. package/docs/dev-delivery-warrant.md +17 -16
  53. package/docs/dev-qualification-patrol.md +25 -20
  54. package/docs/getting-started.md +80 -139
  55. package/docs/github-artifact-attestation.md +31 -81
  56. package/docs/install.md +66 -30
  57. package/docs/lifecycle-protocol.md +19 -57
  58. package/docs/migration-inventory.md +17 -45
  59. package/docs/next-development-transition.md +13 -13
  60. package/docs/node-api-reference.md +122 -138
  61. package/docs/oci-publication.md +13 -10
  62. package/docs/publication-artifacts.md +128 -486
  63. package/docs/publication-authority.md +15 -45
  64. package/docs/publish-transaction.md +13 -11
  65. package/docs/release-candidate.md +126 -355
  66. package/docs/release-discussions.md +36 -67
  67. package/docs/release-flow.md +80 -339
  68. package/docs/release-governance.md +114 -962
  69. package/docs/release-promotion-request.md +45 -43
  70. package/docs/release-propagation.md +13 -27
  71. package/docs/release-tail-provider-plane.md +38 -65
  72. package/docs/reusable-build-surface.md +78 -196
  73. package/docs/runtime-train-validation.md +8 -6
  74. package/docs/stable-candidate-patrol.md +13 -66
  75. package/docs/v4-adopter-delivery.md +15 -15
  76. package/docs/v4-declarative-release-tail-migration.md +19 -17
  77. package/docs/v4-production-release.md +11 -6
  78. package/docs/v4-publication-rehearsal.md +12 -27
  79. package/docs/v4-stage-capsule.md +14 -20
  80. package/docs/v4-tail-reseal.md +34 -20
  81. package/docs/web-surface-deployments.md +26 -264
  82. package/docs/workflow-catalog.md +31 -31
  83. package/docs/workflow-path-migration.md +10 -4
  84. package/package.json +5 -4
  85. package/packages/core/adoption/buildchain-kfd-claims.js +7 -7
  86. package/packages/core/adoption/cli/output.mjs +1 -9
  87. package/packages/core/adoption/cli/product-gate.mjs +1 -15
  88. package/packages/core/adoption/cli/project.mjs +9 -10
  89. package/packages/core/adoption/cli/standards.mjs +1 -14
  90. package/packages/core/adoption/cli/support.mjs +0 -2
  91. package/packages/core/adoption/cli/surface-register.mjs +0 -2
  92. package/packages/core/adoption/commands/init-repo.mjs +77 -485
  93. package/packages/core/adoption/consumer-init.js +279 -0
  94. package/packages/core/adoption/qualification/admission.js +1 -1
  95. package/packages/core/build/cli/cache.mjs +0 -2
  96. package/packages/core/build/cli/facts.mjs +0 -3
  97. package/packages/core/build/cli/homebrew.mjs +0 -4
  98. package/packages/core/build/cli/lifecycle.mjs +0 -3
  99. package/packages/core/build/github-artifact-attestation.js +2 -2
  100. package/packages/core/build/platform-stage-checkpoints.js +1 -1
  101. package/packages/core/build/signing/dispatch.js +1 -1
  102. package/packages/core/consumer/buildchain-config.js +9 -0
  103. package/packages/core/consumer/contract/inspection.js +351 -9
  104. package/packages/core/consumer/contract/javascript-syntax.js +439 -0
  105. package/packages/core/consumer/contract/javascript-values.js +61 -0
  106. package/packages/core/consumer/contract/javascript.js +555 -0
  107. package/packages/core/consumer/contract/local-validation.js +84 -0
  108. package/packages/core/contracts/buildchain-contract.js +39 -8
  109. package/packages/core/contracts/cli/introspection.mjs +1 -9
  110. package/packages/core/contracts/public-surface-cli.js +0 -1
  111. package/packages/core/dev-delivery/dev-delivery-contract-surface.js +2 -2
  112. package/packages/core/governance/buildchain-publication-authority.js +24 -24
  113. package/packages/core/governance/cli/doctor.mjs +58 -42
  114. package/packages/core/governance/commands/architecture.mjs +6 -1
  115. package/packages/core/governance/commands/audit-publication-control-plane.mjs +1 -1
  116. package/packages/core/governance/commands/workflow-friction-report.mjs +1 -1
  117. package/packages/core/governance/github-governance-authority.js +2 -2
  118. package/packages/core/governance/publication/collection.js +1 -1
  119. package/packages/core/index.js +1 -3
  120. package/packages/core/observability/cli/candidate.mjs +0 -2
  121. package/packages/core/observability/cli/context.mjs +0 -5
  122. package/packages/core/observability/cli/diagnostics.mjs +0 -7
  123. package/packages/core/observability/cli/events.mjs +2 -10
  124. package/packages/core/paper/commands/paper-work-fleet-cli.mjs +1 -1
  125. package/packages/core/paper/commands/paper.mjs +33 -422
  126. package/packages/core/paper/consumer-status.js +72 -0
  127. package/packages/core/paper/operations/identity.js +0 -3
  128. package/packages/core/paper/operations/migration.js +460 -0
  129. package/packages/core/paper/operations/preflight-checks.js +8 -68
  130. package/packages/core/paper/operations/scaffold.js +16 -326
  131. package/packages/core/paper/operations/status.js +27 -53
  132. package/packages/core/paper/paper-agent-entry.js +36 -147
  133. package/packages/core/paper/paper-fleet.js +24 -39
  134. package/packages/core/paper/paper-repository.js +16 -0
  135. package/packages/core/paper/paper-runtime-channels.js +1 -1
  136. package/packages/core/paper/paper-scaffold-content.js +153 -162
  137. package/packages/core/paper/paper-work.js +3 -10
  138. package/packages/core/paper/paper.js +43 -5
  139. package/packages/core/providers/github/artifact-attestation.js +1 -1
  140. package/packages/core/providers/github/pipeline-context-artifacts.js +172 -0
  141. package/packages/core/publication/authority/control-plane.js +2 -2
  142. package/packages/core/publication/authority/seal.js +1 -1
  143. package/packages/core/publication/cli/dispatch.mjs +1 -12
  144. package/packages/core/publication/pipeline/actions.js +16 -9
  145. package/packages/core/publication/pipeline/apply.js +17 -9
  146. package/packages/core/publication/pipeline/context.js +29 -0
  147. package/packages/core/publication/pipeline/prepare.js +15 -6
  148. package/packages/core/publication/pipeline/recovery-materials.js +63 -1
  149. package/packages/core/publication/pipeline/recovery-prepare.js +21 -9
  150. package/packages/core/publication/pipeline/stable-entry.js +12 -7
  151. package/packages/core/publication/pipeline/stable-products.js +21 -19
  152. package/packages/core/publication/pipeline/version-actions.js +15 -6
  153. package/packages/core/publication/publication-rehearsal-projection.js +0 -9
  154. package/packages/core/release/cli/dispatch.mjs +1 -4
  155. package/packages/core/release/cli/inspection-handlers.mjs +1 -33
  156. package/packages/core/release/cli/release-handlers.mjs +2 -19
  157. package/packages/core/release/cli/verification-handlers.mjs +4 -25
  158. package/packages/core/release/next-development-projection.js +13 -13
  159. package/packages/core/release/passport/locations.js +13 -8
  160. package/packages/core/release/release-passport.js +70 -5
  161. package/packages/core/web/cli/badges.mjs +0 -4
  162. package/packages/core/web/publication-admission.js +1 -1
  163. package/packages/core/web/publication-capability.js +1 -1
  164. package/packages/core/web/readme-badges.js +1 -1
  165. package/packages/core/workflow/cli/main.mjs +1 -4
  166. package/packages/core/workflow/cli/process.mjs +1 -1
  167. package/packages/core/workflow/commands/buildchain-cli-help.mjs +2 -8
  168. package/packages/core/workflow/engine/conformance.js +1 -1
  169. package/packages/core/workflow/pipeline/build.js +21 -1
  170. package/packages/core/workflow/pipeline/delivery-observation.js +6 -2
  171. package/packages/core/workflow/workflow-taxonomy.mjs +61 -17
  172. package/scripts/check-code-layout.mjs +2 -0
  173. package/scripts/check-core-mechanism-inventory.mjs +29 -13
  174. package/scripts/check-floating-consumer-policy-contract.mjs +3 -3
  175. package/scripts/check-inventory.mjs +27 -27
  176. package/scripts/check-maintainability.mjs +28 -5
  177. package/scripts/check-public-dogfood-contract.mjs +3 -3
  178. package/scripts/check-release-topology.mjs +1 -1
  179. package/scripts/check-self-consumer-contract.mjs +7 -7
  180. package/scripts/check-universal-workflow-bootstrap.mjs +1 -1
  181. package/scripts/generate-channel-promotion-workflow.mjs +1 -1
  182. package/scripts/generate-minimal-consumer-contract.mjs +21 -1
  183. package/scripts/generate-site-bundle.mjs +2 -1
  184. package/scripts/generate-tail-reseal-fixture.mjs +3 -3
  185. package/scripts/inventory/promotion.mjs +1 -1
  186. package/scripts/next-development-self-dogfood-harness.mjs +1 -1
  187. package/scripts/next-development-self-dogfood.mjs +4 -4
  188. package/scripts/site-capability-metadata.mjs +2 -6
  189. package/scripts/source-metric-lineage.mjs +62 -7
  190. package/scripts/verify-golden-path.mjs +31 -35
  191. package/templates/native-dev-delivery.yml +1 -1
  192. package/templates/universal-buildchain-bootstrap.yml +1 -1
  193. package/packages/core/paper/operations/bootstrap.js +0 -75
  194. package/packages/core/paper/operations/plans.js +0 -213
  195. package/packages/core/paper/operations/provisioning.js +0 -113
  196. package/packages/core/paper/operations/scaffold-config.js +0 -77
  197. package/packages/core/paper/operations/scaffold-workflows.js +0 -116
  198. package/packages/core/paper/operations/workspace.js +0 -60
  199. package/packages/core/paper/paper-npm-bootstrap.js +0 -492
@@ -0,0 +1,439 @@
1
+ import { UNKNOWN, TAG, tagged, namespace } from "./javascript-values.js";
2
+
3
+ function expressionLiteral(ctx, node, scope) {
4
+ return node.value;
5
+ }
6
+ function expressionIdentifier(ctx, node, scope) {
7
+ const { get } = ctx;
8
+ return get(scope, node.name);
9
+ }
10
+ function expressionFunctionExpression(ctx, node, scope) {
11
+ return tagged("function", { node, scope });
12
+ }
13
+ function expressionArrayExpression(ctx, node, scope) {
14
+ const { expression } = ctx;
15
+ return node.elements.map((item) => expression(item, scope));
16
+ }
17
+ function expressionObjectExpression(ctx, node, scope) {
18
+ const { expression, report, get } = ctx;
19
+ {
20
+ const value = Object.create(null);
21
+ for (const property of node.properties) {
22
+ if (property.type === "SpreadElement") {
23
+ expression(property.argument, scope);
24
+ report(
25
+ property,
26
+ "unsupported-spread",
27
+ "Object spread requires resolved property execution",
28
+ );
29
+ continue;
30
+ }
31
+ if (property.kind === "get" || property.kind === "set")
32
+ report(
33
+ property,
34
+ "unsupported-accessor",
35
+ "Accessor execution must be resolved explicitly",
36
+ );
37
+ const key = property.computed
38
+ ? expression(property.key, scope)
39
+ : (property.key.name ?? property.key.value);
40
+ if (typeof key !== "string" && typeof key !== "number") {
41
+ report(
42
+ property,
43
+ "unresolved-property",
44
+ "Computed property must resolve",
45
+ );
46
+ expression(property.value, scope);
47
+ continue;
48
+ }
49
+ value[key] = expression(property.value, scope);
50
+ }
51
+ return value;
52
+ }
53
+ }
54
+ function expressionMemberExpression(ctx, node, scope) {
55
+ const { member, expression, report } = ctx;
56
+ {
57
+ const object = expression(node.object, scope),
58
+ key = node.computed
59
+ ? expression(node.property, scope)
60
+ : node.property.name;
61
+ if (["constructor", "prototype", "__proto__"].includes(key))
62
+ report(
63
+ node,
64
+ "dynamic-prototype",
65
+ "Prototype execution is outside the static invocation subset",
66
+ );
67
+ return member(object, key);
68
+ }
69
+ }
70
+ function expressionCallExpression(ctx, node, scope) {
71
+ const { invoke, expression } = ctx;
72
+ const result = invoke(
73
+ node,
74
+ expression(node.callee, scope),
75
+ node.arguments.map((argument) => expression(argument, scope)),
76
+ );
77
+ if (node.type === "NewExpression") {
78
+ ctx.report(
79
+ node,
80
+ "unsupported-construction",
81
+ "Constructor result and prototype behavior must be resolved explicitly",
82
+ );
83
+ return UNKNOWN;
84
+ }
85
+ return result;
86
+ }
87
+ function expressionImportExpression(ctx, node, scope) {
88
+ const { imported, expression } = ctx;
89
+ return imported(node, expression(node.source, scope));
90
+ }
91
+ function expressionAwaitExpression(ctx, node, scope) {
92
+ const { invoke, expression, report } = ctx;
93
+ {
94
+ const value = expression(node.argument, scope);
95
+ if (value && typeof value === "object" && !value[TAG])
96
+ report(
97
+ node,
98
+ "unresolved-await",
99
+ "Await may invoke a user-defined thenable",
100
+ );
101
+ return value;
102
+ }
103
+ }
104
+ function expressionChainExpression(ctx, node, scope) {
105
+ const { expression } = ctx;
106
+ return expression(node.argument || node.expression, scope);
107
+ }
108
+ function expressionBinaryExpression(ctx, node, scope) {
109
+ const { expression, data, checkCoercion } = ctx;
110
+ {
111
+ const left = expression(node.left, scope),
112
+ right = expression(node.right, scope);
113
+ if (
114
+ node.operator === "+" &&
115
+ [left, right].every((value) =>
116
+ ["string", "number"].includes(typeof value),
117
+ )
118
+ )
119
+ return left + right;
120
+ if (
121
+ left !== UNKNOWN &&
122
+ right !== UNKNOWN &&
123
+ !left?.[TAG] &&
124
+ !right?.[TAG] &&
125
+ ["===", "!=="].includes(node.operator)
126
+ )
127
+ return node.operator === "===" ? left === right : left !== right;
128
+ if (!["===", "!=="].includes(node.operator))
129
+ checkCoercion(node, [left, right]);
130
+ return data();
131
+ }
132
+ }
133
+ function expressionTemplateLiteral(ctx, node, scope) {
134
+ const { expression, data, checkCoercion } = ctx;
135
+ {
136
+ const values = node.expressions.map((value) => expression(value, scope));
137
+ checkCoercion(node, values);
138
+ return values.every((value) => ["string", "number"].includes(typeof value))
139
+ ? node.quasis
140
+ .map(
141
+ (part, index) =>
142
+ part.value.cooked + (index < values.length ? values[index] : ""),
143
+ )
144
+ .join("")
145
+ : data();
146
+ }
147
+ }
148
+ function expressionConditionalExpression(ctx, node, scope) {
149
+ const { expression, report } = ctx;
150
+ {
151
+ const value = expression(node.test || node.left, scope);
152
+ if (value === UNKNOWN || value?.[TAG]) {
153
+ report(
154
+ node,
155
+ "unresolved-condition",
156
+ "Conditional expression requires a resolved condition",
157
+ );
158
+ expression(node.consequent || node.right, scope);
159
+ if (node.alternate) expression(node.alternate, scope);
160
+ return UNKNOWN;
161
+ }
162
+ if (node.test)
163
+ return expression(value ? node.consequent : node.alternate, scope);
164
+ const useRight =
165
+ node.operator === "&&"
166
+ ? Boolean(value)
167
+ : node.operator === "||"
168
+ ? !value
169
+ : value == null;
170
+ return useRight ? expression(node.right, scope) : value;
171
+ }
172
+ }
173
+ function expressionAssignmentExpression(ctx, node, scope) {
174
+ const { expression, data, report, get, checkCoercion } = ctx;
175
+ {
176
+ const value = expression(node.right, scope);
177
+ if (node.left.type !== "Identifier" || !scope.has(node.left.name)) {
178
+ report(
179
+ node,
180
+ "unsupported-assignment",
181
+ "Assignment requires a resolved lexical binding",
182
+ );
183
+ return UNKNOWN;
184
+ }
185
+ const previous = get(scope, node.left.name);
186
+ let assigned = value;
187
+ if (node.operator === "+=") {
188
+ checkCoercion(node, [previous, value]);
189
+ assigned = [previous, value].every((item) =>
190
+ ["string", "number"].includes(typeof item),
191
+ )
192
+ ? previous + value
193
+ : data();
194
+ } else if (node.operator !== "=") {
195
+ report(
196
+ node,
197
+ "unsupported-assignment",
198
+ `Unsupported assignment operator: ${node.operator}`,
199
+ );
200
+ assigned = UNKNOWN;
201
+ }
202
+ scope.get(node.left.name).value = assigned;
203
+ return assigned;
204
+ }
205
+ }
206
+ function expressionSequenceExpression(ctx, node, scope) {
207
+ const { expression } = ctx;
208
+ return node.expressions.map((value) => expression(value, scope)).at(-1);
209
+ }
210
+ function expressionUnaryExpression(ctx, node, scope) {
211
+ const { expression, report, checkCoercion } = ctx;
212
+ checkCoercion(node, [expression(node.argument, scope)]);
213
+ report(
214
+ node,
215
+ "unsupported-operator",
216
+ `Unsupported unary operator: ${node.operator}`,
217
+ );
218
+ return UNKNOWN;
219
+ }
220
+ function expressionUnknown(ctx, node, scope) {
221
+ const { expression, report } = ctx;
222
+ report(
223
+ node,
224
+ "unsupported-expression",
225
+ `Unsupported executable syntax: ${node.type}`,
226
+ );
227
+ return UNKNOWN;
228
+ }
229
+ const expressionHandlers = {
230
+ Literal: expressionLiteral,
231
+ Identifier: expressionIdentifier,
232
+ FunctionExpression: expressionFunctionExpression,
233
+ ArrowFunctionExpression: expressionFunctionExpression,
234
+ ArrayExpression: expressionArrayExpression,
235
+ ObjectExpression: expressionObjectExpression,
236
+ MemberExpression: expressionMemberExpression,
237
+ CallExpression: expressionCallExpression,
238
+ NewExpression: expressionCallExpression,
239
+ ImportExpression: expressionImportExpression,
240
+ AwaitExpression: expressionAwaitExpression,
241
+ ChainExpression: expressionChainExpression,
242
+ BinaryExpression: expressionBinaryExpression,
243
+ TemplateLiteral: expressionTemplateLiteral,
244
+ ConditionalExpression: expressionConditionalExpression,
245
+ LogicalExpression: expressionConditionalExpression,
246
+ AssignmentExpression: expressionAssignmentExpression,
247
+ SequenceExpression: expressionSequenceExpression,
248
+ UnaryExpression: expressionUnaryExpression,
249
+ UpdateExpression: expressionUnaryExpression,
250
+ };
251
+ export function evaluateExpression(ctx, node, scope) {
252
+ if (!node) return undefined;
253
+ ctx.visit();
254
+ return (expressionHandlers[node.type] || expressionUnknown)(ctx, node, scope);
255
+ }
256
+
257
+ function statementsFunctionDeclaration(ctx, node, scope) {}
258
+ function statementsImportDeclaration(ctx, node, scope) {
259
+ const { member, imported, declare } = ctx;
260
+ {
261
+ imported(node, node.source.value);
262
+ for (const item of node.specifiers)
263
+ declare(
264
+ scope,
265
+ item.local.name,
266
+ item.type === "ImportSpecifier"
267
+ ? member(
268
+ namespace(node.source.value),
269
+ item.imported.name ?? item.imported.value,
270
+ )
271
+ : item.type === "ImportDefaultSpecifier" &&
272
+ node.source.value.startsWith(".")
273
+ ? member(namespace(node.source.value), "default")
274
+ : namespace(node.source.value),
275
+ );
276
+ return;
277
+ }
278
+ }
279
+ function statementsVariableDeclaration(ctx, node, scope) {
280
+ const { bind, expression } = ctx;
281
+ for (const item of node.declarations)
282
+ bind(item.id, expression(item.init, scope), scope);
283
+ }
284
+ function statementsExpressionStatement(ctx, node, scope) {
285
+ const { expression } = ctx;
286
+ expression(node.expression, scope);
287
+ }
288
+ function statementsReturnStatement(ctx, node, scope) {
289
+ const { expression } = ctx;
290
+ return { returned: true, value: expression(node.argument, scope) };
291
+ }
292
+ function statementsThrowStatement(ctx, node, scope) {
293
+ const { expression } = ctx;
294
+ expression(node.argument, scope);
295
+ }
296
+ function statementsBlockStatement(ctx, node, scope) {
297
+ const { statements } = ctx;
298
+ {
299
+ const result = statements(node.body, new Map(scope));
300
+ if (result.returned) return result;
301
+ return;
302
+ }
303
+ }
304
+ function statementsIfStatement(ctx, node, scope) {
305
+ const { expression, statements, report } = ctx;
306
+ {
307
+ const value = expression(node.test, scope);
308
+ if (value === UNKNOWN || value?.[TAG])
309
+ report(
310
+ node,
311
+ "unresolved-condition",
312
+ "Conditional execution requires a resolved condition",
313
+ );
314
+ const branches =
315
+ value === UNKNOWN || value?.[TAG]
316
+ ? [node.consequent, node.alternate]
317
+ : [value ? node.consequent : node.alternate];
318
+ const results = branches
319
+ .filter(Boolean)
320
+ .map((branch) => statements([branch], new Map(scope)));
321
+ if (
322
+ results.length &&
323
+ results.every((result) => result.returned) &&
324
+ results.every((result) => result.value === results[0].value)
325
+ )
326
+ return results[0];
327
+ return;
328
+ }
329
+ }
330
+ function statementsForStatement(ctx, node, scope) {
331
+ const { bind, expression, statements, report } = ctx;
332
+ {
333
+ const loop = new Map(scope);
334
+ if (node.type === "ForOfStatement") {
335
+ const values = expression(node.right, scope);
336
+ if (!Array.isArray(values) || values.length > 1000)
337
+ report(
338
+ node,
339
+ "unresolved-iteration",
340
+ "Iteration requires a bounded resolved array",
341
+ );
342
+ else
343
+ for (const value of values) {
344
+ const iteration = new Map(scope);
345
+ bind(node.left.declarations?.[0]?.id || node.left, value, iteration);
346
+ const result = statements([node.body], iteration);
347
+ if (result.returned) return result;
348
+ }
349
+ return;
350
+ }
351
+ report(node, "unresolved-iteration", "Loop expansion is not resolved");
352
+ if (node.init?.type === "VariableDeclaration")
353
+ statements([node.init], loop);
354
+ else expression(node.init, loop);
355
+ if (node.left?.type === "VariableDeclaration")
356
+ for (const item of node.left.declarations) bind(item.id, UNKNOWN, loop);
357
+ expression(node.right || node.test, loop);
358
+ statements([node.body], loop);
359
+ expression(node.update, loop);
360
+ return;
361
+ }
362
+ }
363
+ function statementsTryStatement(ctx, node, scope) {
364
+ const { statements } = ctx;
365
+ ctx.report(
366
+ node,
367
+ "unresolved-exception-path",
368
+ "Exception paths cannot share a resolved mutable environment",
369
+ );
370
+ statements([node.block], new Map(scope));
371
+ if (node.handler) statements([node.handler.body], new Map(scope));
372
+ if (node.finalizer) statements([node.finalizer], new Map(scope));
373
+ }
374
+ function statementsExportNamedDeclaration(ctx, node, scope) {
375
+ const { imported, expression, statements, get, declare, exports } = ctx;
376
+ {
377
+ if (node.declaration?.type === "FunctionDeclaration") {
378
+ const name = node.declaration.id?.name || "default",
379
+ value = tagged("function", { node: node.declaration, scope });
380
+ declare(scope, name, value);
381
+ exports.set(
382
+ node.type === "ExportDefaultDeclaration" ? "default" : name,
383
+ value,
384
+ );
385
+ } else if (node.declaration?.type === "VariableDeclaration") {
386
+ statements([node.declaration], scope);
387
+ for (const item of node.declaration.declarations)
388
+ if (item.id.type === "Identifier")
389
+ exports.set(item.id.name, get(scope, item.id.name));
390
+ } else if (node.declaration)
391
+ exports.set("default", expression(node.declaration, scope));
392
+ if (node.source) imported(node, node.source.value);
393
+ for (const item of node.specifiers || [])
394
+ exports.set(item.exported.name, get(scope, item.local.name));
395
+ return;
396
+ }
397
+ }
398
+ function statementsUnknown(ctx, node, scope) {
399
+ const { report } = ctx;
400
+ report(
401
+ node,
402
+ "unsupported-statement",
403
+ `Unsupported executable syntax: ${node.type}`,
404
+ );
405
+ }
406
+ const statementsHandlers = {
407
+ FunctionDeclaration: statementsFunctionDeclaration,
408
+ EmptyStatement: statementsFunctionDeclaration,
409
+ ImportDeclaration: statementsImportDeclaration,
410
+ VariableDeclaration: statementsVariableDeclaration,
411
+ ExpressionStatement: statementsExpressionStatement,
412
+ ReturnStatement: statementsReturnStatement,
413
+ ThrowStatement: statementsThrowStatement,
414
+ BlockStatement: statementsBlockStatement,
415
+ IfStatement: statementsIfStatement,
416
+ ForStatement: statementsForStatement,
417
+ ForOfStatement: statementsForStatement,
418
+ ForInStatement: statementsForStatement,
419
+ WhileStatement: statementsForStatement,
420
+ DoWhileStatement: statementsForStatement,
421
+ TryStatement: statementsTryStatement,
422
+ ExportNamedDeclaration: statementsExportNamedDeclaration,
423
+ ExportDefaultDeclaration: statementsExportNamedDeclaration,
424
+ };
425
+ export function evaluateStatements(ctx, nodes, scope) {
426
+ for (const node of nodes)
427
+ if (node.type === "FunctionDeclaration")
428
+ ctx.declare(scope, node.id.name, tagged("function", { node, scope }));
429
+ for (const node of nodes) {
430
+ ctx.visit();
431
+ const result = (statementsHandlers[node.type] || statementsUnknown)(
432
+ ctx,
433
+ node,
434
+ scope,
435
+ );
436
+ if (result?.returned) return result;
437
+ }
438
+ return { returned: false, value: undefined };
439
+ }
@@ -0,0 +1,61 @@
1
+ export const UNKNOWN = Symbol("unresolved value"),
2
+ TAG = Symbol("analyzer value");
3
+ export const tagged = (kind, value) => ({ [TAG]: kind, ...value });
4
+ export const namespace = (specifier) => tagged("namespace", { specifier });
5
+
6
+ // Edges cross module boundaries as data, never as interpreter objects. A
7
+ // callback or opaque runtime value requires analysis at its real call site.
8
+ export function concreteArguments(values, seen = new Set()) {
9
+ if (values === null || values === undefined) return true;
10
+ if (["string", "number", "boolean", "bigint"].includes(typeof values))
11
+ return true;
12
+ if (typeof values !== "object" || values[TAG] || seen.has(values))
13
+ return false;
14
+ seen.add(values);
15
+ const result = Object.values(values).every((value) =>
16
+ concreteArguments(value, seen),
17
+ );
18
+ seen.delete(values);
19
+ return result;
20
+ }
21
+ export const processCalls = new Set([
22
+ "exec",
23
+ "execSync",
24
+ "execFile",
25
+ "execFileSync",
26
+ "spawn",
27
+ "spawnSync",
28
+ "fork",
29
+ ]);
30
+ export const inertModules = new Set([
31
+ "fs",
32
+ "fs/promises",
33
+ "assert",
34
+ "assert/strict",
35
+ "buffer",
36
+ "crypto",
37
+ "os",
38
+ "util",
39
+ "events",
40
+ "stream",
41
+ "zlib",
42
+ "url",
43
+ "path",
44
+ "path/posix",
45
+ "path/win32",
46
+ ]);
47
+ export const inertGlobals = new Set([
48
+ "String",
49
+ "Number",
50
+ "Boolean",
51
+ "BigInt",
52
+ "Object",
53
+ "Array",
54
+ "JSON",
55
+ "Math",
56
+ "Buffer",
57
+ "console",
58
+ "Error",
59
+ "TypeError",
60
+ "RangeError",
61
+ ]);