forgeos 0.1.0-alpha.0 → 0.1.0-alpha.2

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 (283) hide show
  1. package/.npmignore +9 -1
  2. package/AGENTS.md +6 -1
  3. package/CHANGELOG.md +30 -0
  4. package/CONTRIBUTING.md +22 -1
  5. package/README.md +30 -3
  6. package/bin/forge.mjs +4 -3
  7. package/package.json +3 -1
  8. package/packages/eslint-plugin-forge/index.ts +15 -15
  9. package/packages/eslint-plugin-forge/package.json +10 -10
  10. package/packages/eslint-plugin-forge/src/check-source.ts +95 -95
  11. package/packages/eslint-plugin-forge/src/load-artifacts.ts +24 -24
  12. package/packages/eslint-plugin-forge/src/rule-no-forge-guard-violation.ts +93 -93
  13. package/src/forge/_generated/actionSubscriptions.json +2 -2
  14. package/src/forge/_generated/actionSubscriptions.ts +3 -3
  15. package/src/forge/_generated/agentAdapterManifest.json +2 -2
  16. package/src/forge/_generated/agentAdapterManifest.ts +3 -3
  17. package/src/forge/_generated/agentContract.json +2 -2
  18. package/src/forge/_generated/agentContract.ts +6786 -2
  19. package/src/forge/_generated/agentQuickstart.md +1 -1
  20. package/src/forge/_generated/aiContext.ts +1 -1
  21. package/src/forge/_generated/aiModels.json +1 -1
  22. package/src/forge/_generated/aiModels.ts +1 -1
  23. package/src/forge/_generated/aiProviders.json +1 -1
  24. package/src/forge/_generated/aiProviders.ts +1 -1
  25. package/src/forge/_generated/aiRegistry.json +2 -2
  26. package/src/forge/_generated/aiRegistry.ts +3 -3
  27. package/src/forge/_generated/api.json +2 -2
  28. package/src/forge/_generated/api.ts +1 -1
  29. package/src/forge/_generated/appGraph.json +2 -2
  30. package/src/forge/_generated/appGraph.ts +1297 -1141
  31. package/src/forge/_generated/appMap.md +1 -1
  32. package/src/forge/_generated/artifactManifest.json +2 -2
  33. package/src/forge/_generated/artifactManifest.ts +2 -2
  34. package/src/forge/_generated/authClaims.json +1 -1
  35. package/src/forge/_generated/authClaims.ts +1 -1
  36. package/src/forge/_generated/authConfig.json +1 -1
  37. package/src/forge/_generated/authConfig.ts +1 -1
  38. package/src/forge/_generated/authContext.ts +1 -1
  39. package/src/forge/_generated/authRegistry.json +1 -1
  40. package/src/forge/_generated/authRegistry.ts +1 -1
  41. package/src/forge/_generated/buildInfo.json +2 -2
  42. package/src/forge/_generated/buildInfo.ts +4 -4
  43. package/src/forge/_generated/capabilityMap.json +2 -2
  44. package/src/forge/_generated/capabilityMap.md +1 -1
  45. package/src/forge/_generated/capabilityMap.ts +2 -2
  46. package/src/forge/_generated/client.ts +1 -1
  47. package/src/forge/_generated/clientApi.ts +1 -1
  48. package/src/forge/_generated/clientManifest.json +2 -2
  49. package/src/forge/_generated/clientManifest.ts +3 -3
  50. package/src/forge/_generated/clientTypes.ts +1 -1
  51. package/src/forge/_generated/configRegistry.json +1 -1
  52. package/src/forge/_generated/configRegistry.ts +1 -1
  53. package/src/forge/_generated/dataGraph.json +2 -2
  54. package/src/forge/_generated/dataGraph.ts +3 -3
  55. package/src/forge/_generated/db.json +1 -1
  56. package/src/forge/_generated/db.ts +1 -1
  57. package/src/forge/_generated/dbSecurityManifest.json +1 -1
  58. package/src/forge/_generated/dbSecurityManifest.ts +1 -1
  59. package/src/forge/_generated/dbSessionContext.json +1 -1
  60. package/src/forge/_generated/dbSessionContext.ts +1 -1
  61. package/src/forge/_generated/deployManifest.json +2 -2
  62. package/src/forge/_generated/deployManifest.ts +7 -7
  63. package/src/forge/_generated/devManifest.json +2 -2
  64. package/src/forge/_generated/devManifest.ts +3 -3
  65. package/src/forge/_generated/envSchema.json +1 -1
  66. package/src/forge/_generated/envSchema.ts +1 -1
  67. package/src/forge/_generated/frontendGraph.json +1 -1
  68. package/src/forge/_generated/frontendGraph.ts +1 -1
  69. package/src/forge/_generated/importGuards.json +2 -2
  70. package/src/forge/_generated/importGuards.ts +35 -1
  71. package/src/forge/_generated/index.ts +1 -1
  72. package/src/forge/_generated/liveProductionManifest.json +1 -1
  73. package/src/forge/_generated/liveProductionManifest.ts +1 -1
  74. package/src/forge/_generated/liveProtocol.json +1 -1
  75. package/src/forge/_generated/liveProtocol.ts +1 -1
  76. package/src/forge/_generated/liveQueryRegistry.json +2 -2
  77. package/src/forge/_generated/liveQueryRegistry.ts +3 -3
  78. package/src/forge/_generated/liveTransportConfig.json +1 -1
  79. package/src/forge/_generated/liveTransportConfig.ts +1 -1
  80. package/src/forge/_generated/makeRegistry.json +2 -2
  81. package/src/forge/_generated/makeRegistry.ts +2 -2
  82. package/src/forge/_generated/makeTemplates.json +1 -1
  83. package/src/forge/_generated/makeTemplates.ts +1 -1
  84. package/src/forge/_generated/mockMap.json +1 -1
  85. package/src/forge/_generated/mockMap.ts +1 -1
  86. package/src/forge/_generated/operationPlaybooks.md +7 -5
  87. package/src/forge/_generated/packageGraph.json +2 -2
  88. package/src/forge/_generated/packageGraph.ts +90964 -14284
  89. package/src/forge/_generated/packageUpgradeRegistry.json +2 -2
  90. package/src/forge/_generated/packageUpgradeRegistry.ts +2 -2
  91. package/src/forge/_generated/permissionMatrix.json +2 -2
  92. package/src/forge/_generated/permissionMatrix.ts +3 -3
  93. package/src/forge/_generated/policyRegistry.json +2 -2
  94. package/src/forge/_generated/policyRegistry.ts +3 -3
  95. package/src/forge/_generated/queryRegistry.json +2 -2
  96. package/src/forge/_generated/queryRegistry.ts +3 -3
  97. package/src/forge/_generated/react.d.ts +1 -1
  98. package/src/forge/_generated/react.ts +1 -1
  99. package/src/forge/_generated/reactManifest.json +2 -2
  100. package/src/forge/_generated/reactManifest.ts +3 -3
  101. package/src/forge/_generated/releaseManifest.json +2 -2
  102. package/src/forge/_generated/releaseManifest.ts +3 -3
  103. package/src/forge/_generated/rlsPolicies.json +1 -1
  104. package/src/forge/_generated/rlsPolicies.sql +1 -1
  105. package/src/forge/_generated/rlsPolicies.ts +1 -1
  106. package/src/forge/_generated/runtimeGraph.json +2 -2
  107. package/src/forge/_generated/runtimeGraph.ts +3 -3
  108. package/src/forge/_generated/runtimeMatrix.json +2 -2
  109. package/src/forge/_generated/runtimeMatrix.ts +106177 -7917
  110. package/src/forge/_generated/runtimeRegistry.ts +1 -1
  111. package/src/forge/_generated/runtimeRules.md +1 -1
  112. package/src/forge/_generated/secretRegistry.json +1 -1
  113. package/src/forge/_generated/secretRegistry.ts +1 -1
  114. package/src/forge/_generated/secretsContext.ts +1 -1
  115. package/src/forge/_generated/serverApi.ts +1 -1
  116. package/src/forge/_generated/sourceMapManifest.json +2 -2
  117. package/src/forge/_generated/sourceMapManifest.ts +2 -2
  118. package/src/forge/_generated/sqlPlan.json +1 -1
  119. package/src/forge/_generated/sqlPlan.ts +1 -1
  120. package/src/forge/_generated/subscriptionManifest.json +2 -2
  121. package/src/forge/_generated/subscriptionManifest.ts +3 -3
  122. package/src/forge/_generated/symbolicationManifest.json +2 -2
  123. package/src/forge/_generated/symbolicationManifest.ts +2 -2
  124. package/src/forge/_generated/telemetryRegistry.json +2 -2
  125. package/src/forge/_generated/telemetryRegistry.ts +3 -3
  126. package/src/forge/_generated/telemetrySinks.json +2 -2
  127. package/src/forge/_generated/telemetrySinks.ts +2 -2
  128. package/src/forge/_generated/tenantScope.json +2 -2
  129. package/src/forge/_generated/tenantScope.ts +3 -3
  130. package/src/forge/_generated/testGraph.json +2 -2
  131. package/src/forge/_generated/testGraph.ts +129 -75
  132. package/src/forge/_generated/testPlanRegistry.json +2 -2
  133. package/src/forge/_generated/testPlanRegistry.ts +2 -2
  134. package/src/forge/_generated/uiRoutes.json +1 -1
  135. package/src/forge/_generated/uiRoutes.ts +1 -1
  136. package/src/forge/_generated/uiScenarios.json +1 -1
  137. package/src/forge/_generated/uiScenarios.ts +1 -1
  138. package/src/forge/_generated/uiTestManifest.json +2 -2
  139. package/src/forge/_generated/uiTestManifest.ts +2 -2
  140. package/src/forge/_generated/workflowRegistry.json +2 -2
  141. package/src/forge/_generated/workflowRegistry.ts +3 -3
  142. package/src/forge/_generated/workflowSubscriptions.json +2 -2
  143. package/src/forge/_generated/workflowSubscriptions.ts +3 -3
  144. package/src/forge/cli/commands.ts +861 -861
  145. package/src/forge/cli/deps.ts +178 -11
  146. package/src/forge/cli/dev.ts +32 -5
  147. package/src/forge/cli/index.ts +7 -7
  148. package/src/forge/cli/main.ts +54 -54
  149. package/src/forge/cli/new.ts +29 -1
  150. package/src/forge/cli/output.ts +97 -97
  151. package/src/forge/cli/parse.ts +679 -673
  152. package/src/forge/cli/version.ts +1 -1
  153. package/src/forge/compiler/agent-contract/build.ts +28 -0
  154. package/src/forge/compiler/agent-contract/types.ts +16 -0
  155. package/src/forge/compiler/app-graph/build.ts +112 -112
  156. package/src/forge/compiler/app-graph/classify.ts +10 -10
  157. package/src/forge/compiler/app-graph/dup-symbol.ts +29 -29
  158. package/src/forge/compiler/app-graph/extract.ts +123 -123
  159. package/src/forge/compiler/app-graph/forge-apis.ts +29 -29
  160. package/src/forge/compiler/app-graph/index.ts +11 -11
  161. package/src/forge/compiler/app-graph/module-graph.ts +316 -316
  162. package/src/forge/compiler/app-graph/parser.ts +119 -119
  163. package/src/forge/compiler/app-graph/symbols.ts +48 -48
  164. package/src/forge/compiler/app-graph/tsconfig-hash.ts +62 -62
  165. package/src/forge/compiler/app-graph/types.ts +43 -43
  166. package/src/forge/compiler/app-graph/versions.ts +14 -14
  167. package/src/forge/compiler/cache/index.ts +17 -17
  168. package/src/forge/compiler/cache/key.ts +46 -46
  169. package/src/forge/compiler/cache/scheduler.ts +72 -72
  170. package/src/forge/compiler/cache/store.ts +78 -78
  171. package/src/forge/compiler/classifier/capabilities.ts +78 -78
  172. package/src/forge/compiler/classifier/classify.ts +113 -113
  173. package/src/forge/compiler/classifier/contexts.ts +188 -188
  174. package/src/forge/compiler/classifier/index.ts +18 -18
  175. package/src/forge/compiler/classifier/runtime-matrix.ts +45 -45
  176. package/src/forge/compiler/classifier/secrets.ts +41 -41
  177. package/src/forge/compiler/classifier/signals.ts +129 -129
  178. package/src/forge/compiler/diagnostics/codes.ts +125 -120
  179. package/src/forge/compiler/diagnostics/create.ts +87 -87
  180. package/src/forge/compiler/diagnostics/index.ts +41 -41
  181. package/src/forge/compiler/emitter/artifact-kind.ts +14 -14
  182. package/src/forge/compiler/emitter/barrel.ts +38 -38
  183. package/src/forge/compiler/emitter/constants.ts +7 -7
  184. package/src/forge/compiler/emitter/emit.ts +234 -237
  185. package/src/forge/compiler/emitter/index.ts +24 -24
  186. package/src/forge/compiler/emitter/lock.ts +61 -61
  187. package/src/forge/compiler/emitter/render.ts +73 -73
  188. package/src/forge/compiler/guards/artifacts.ts +96 -96
  189. package/src/forge/compiler/guards/check-import-guards.ts +106 -106
  190. package/src/forge/compiler/guards/index.ts +11 -11
  191. package/src/forge/compiler/guards/propagate-contexts.ts +57 -57
  192. package/src/forge/compiler/index.ts +17 -17
  193. package/src/forge/compiler/integration/add.ts +493 -493
  194. package/src/forge/compiler/integration/index.ts +17 -17
  195. package/src/forge/compiler/integration/plan.ts +279 -279
  196. package/src/forge/compiler/integration/render.ts +189 -189
  197. package/src/forge/compiler/integration/snapshot.ts +52 -52
  198. package/src/forge/compiler/orchestrator/discover.ts +214 -214
  199. package/src/forge/compiler/orchestrator/guards.ts +5 -5
  200. package/src/forge/compiler/orchestrator/index.ts +27 -27
  201. package/src/forge/compiler/orchestrator/manifest.ts +69 -69
  202. package/src/forge/compiler/orchestrator/orphans.ts +51 -51
  203. package/src/forge/compiler/orchestrator/plan.ts +804 -804
  204. package/src/forge/compiler/orchestrator/run.ts +178 -178
  205. package/src/forge/compiler/orchestrator/serialize.ts +859 -859
  206. package/src/forge/compiler/orchestrator/types.ts +23 -23
  207. package/src/forge/compiler/orchestrator/verify.ts +35 -35
  208. package/src/forge/compiler/package-graph/capabilities-stub.ts +33 -33
  209. package/src/forge/compiler/package-graph/checksum.ts +107 -97
  210. package/src/forge/compiler/package-graph/compiler.ts +444 -363
  211. package/src/forge/compiler/package-graph/constants.ts +4 -4
  212. package/src/forge/compiler/package-graph/exports-discovery.ts +91 -84
  213. package/src/forge/compiler/package-graph/extract-dts.ts +32 -32
  214. package/src/forge/compiler/package-graph/index.ts +24 -24
  215. package/src/forge/compiler/package-graph/jsdoc.ts +50 -50
  216. package/src/forge/compiler/package-graph/oracle.ts +326 -0
  217. package/src/forge/compiler/package-graph/read-file.ts +21 -21
  218. package/src/forge/compiler/package-graph/resolve.ts +131 -127
  219. package/src/forge/compiler/package-manager/adapter.ts +232 -232
  220. package/src/forge/compiler/package-manager/commands.ts +47 -47
  221. package/src/forge/compiler/package-manager/detect.ts +65 -65
  222. package/src/forge/compiler/package-manager/executor.ts +29 -29
  223. package/src/forge/compiler/package-manager/index.ts +22 -22
  224. package/src/forge/compiler/package-manager/parse-spec.ts +16 -16
  225. package/src/forge/compiler/package-manager/version.ts +20 -20
  226. package/src/forge/compiler/primitives/compare.ts +26 -26
  227. package/src/forge/compiler/primitives/hash.ts +42 -33
  228. package/src/forge/compiler/primitives/header.ts +43 -43
  229. package/src/forge/compiler/primitives/index.ts +45 -45
  230. package/src/forge/compiler/primitives/paths.ts +24 -24
  231. package/src/forge/compiler/primitives/serialize.ts +66 -66
  232. package/src/forge/compiler/primitives/sort.ts +87 -87
  233. package/src/forge/compiler/recipes/definitions.ts +269 -269
  234. package/src/forge/compiler/recipes/helpers.ts +37 -37
  235. package/src/forge/compiler/recipes/index.ts +21 -21
  236. package/src/forge/compiler/recipes/registry.ts +87 -87
  237. package/src/forge/compiler/sandbox/artifact-sanitize.ts +26 -26
  238. package/src/forge/compiler/sandbox/backends/child.ts +123 -123
  239. package/src/forge/compiler/sandbox/backends/docker.ts +173 -173
  240. package/src/forge/compiler/sandbox/index.ts +51 -51
  241. package/src/forge/compiler/sandbox/inspect.ts +143 -143
  242. package/src/forge/compiler/sandbox/inspector-entry.ts +115 -115
  243. package/src/forge/compiler/sandbox/limits.ts +31 -31
  244. package/src/forge/compiler/sandbox/scrub-env.ts +60 -60
  245. package/src/forge/compiler/sandbox/secret-scan.ts +54 -54
  246. package/src/forge/compiler/sandbox/serialize.ts +106 -106
  247. package/src/forge/compiler/sandbox/types.ts +7 -7
  248. package/src/forge/compiler/types/app-graph.ts +71 -71
  249. package/src/forge/compiler/types/capability.ts +29 -29
  250. package/src/forge/compiler/types/classification.ts +9 -9
  251. package/src/forge/compiler/types/cli.ts +85 -85
  252. package/src/forge/compiler/types/diagnostic.ts +2 -2
  253. package/src/forge/compiler/types/emit.ts +25 -25
  254. package/src/forge/compiler/types/import-guards.ts +19 -19
  255. package/src/forge/compiler/types/index.ts +98 -98
  256. package/src/forge/compiler/types/integration.ts +25 -25
  257. package/src/forge/compiler/types/json.ts +3 -3
  258. package/src/forge/compiler/types/lock.ts +37 -37
  259. package/src/forge/compiler/types/package-graph.ts +122 -77
  260. package/src/forge/compiler/types/runtime-matrix.ts +16 -16
  261. package/src/forge/compiler/types/runtime.ts +30 -30
  262. package/src/forge/compiler/types/sandbox.ts +24 -24
  263. package/src/forge/dev/server.ts +16 -2
  264. package/src/forge/refactor/index.ts +10 -2
  265. package/src/forge/refactor/runtime-rename.ts +598 -0
  266. package/src/forge/runtime/executor.ts +3 -2
  267. package/src/forge/runtime/live/live-query-runner.ts +2 -1
  268. package/src/forge/runtime/outbox/process.ts +2 -1
  269. package/src/forge/runtime/query/run-query.ts +2 -1
  270. package/src/forge/runtime/runner/run-entry.ts +2 -1
  271. package/src/forge/runtime/telemetry/sinks/posthog.ts +4 -5
  272. package/src/forge/runtime/telemetry/sinks/sentry.ts +4 -5
  273. package/src/forge/runtime/workflows/resolve-step.ts +2 -1
  274. package/src/forge/version.ts +3 -0
  275. package/templates/b2b-support-web/src/actions/captureTicketCreated.ts +7 -2
  276. package/templates/b2b-support-web/src/commands/closeTicket.ts +6 -1
  277. package/templates/b2b-support-web/src/commands/createTicket.ts +8 -2
  278. package/templates/b2b-support-web/src/queries/getTicket.ts +8 -1
  279. package/templates/b2b-support-web/web/components/CreateTicketForm.tsx +1 -2
  280. package/templates/b2b-support-web/web/components/PolicyDeniedDemo.tsx +1 -2
  281. package/templates/b2b-support-web/web/components/TicketList.tsx +1 -2
  282. package/templates/b2b-support-web/web/components/TraceDetails.tsx +1 -1
  283. package/templates/b2b-support-web/web/lib/forge.ts +1 -0
@@ -1,62 +1,62 @@
1
- import type { ForgeLock, ForgeLockEntry } from "../types/lock.ts";
2
- import type { SecretRequirement } from "../types/capability.ts";
3
- import {
4
- compareBytes,
5
- serializeCanonical,
6
- stableSortByPath,
7
- stableSortStrings,
8
- } from "../primitives/index.ts";
9
-
10
- function compareLockEntries(a: ForgeLockEntry, b: ForgeLockEntry): number {
11
- return compareBytes(a.name, b.name);
12
- }
13
-
14
- function compareSecrets(a: SecretRequirement, b: SecretRequirement): number {
15
- return compareBytes(a.envVar, b.envVar);
16
- }
17
-
18
- function stableSortLockEntries(entries: ForgeLockEntry[]): ForgeLockEntry[] {
19
- return [...entries].sort(compareLockEntries);
20
- }
21
-
22
- function stableSortSecrets(secrets: SecretRequirement[]): SecretRequirement[] {
23
- return [...secrets].sort(compareSecrets);
24
- }
25
-
26
- function canonicalizeLockEntry(entry: ForgeLockEntry): ForgeLockEntry {
27
- return {
28
- name: entry.name,
29
- version: entry.version,
30
- ...(entry.recipeVersion !== undefined
31
- ? { recipeVersion: entry.recipeVersion }
32
- : {}),
1
+ import type { ForgeLock, ForgeLockEntry } from "../types/lock.ts";
2
+ import type { SecretRequirement } from "../types/capability.ts";
3
+ import {
4
+ compareBytes,
5
+ serializeCanonical,
6
+ stableSortByPath,
7
+ stableSortStrings,
8
+ } from "../primitives/index.ts";
9
+
10
+ function compareLockEntries(a: ForgeLockEntry, b: ForgeLockEntry): number {
11
+ return compareBytes(a.name, b.name);
12
+ }
13
+
14
+ function compareSecrets(a: SecretRequirement, b: SecretRequirement): number {
15
+ return compareBytes(a.envVar, b.envVar);
16
+ }
17
+
18
+ function stableSortLockEntries(entries: ForgeLockEntry[]): ForgeLockEntry[] {
19
+ return [...entries].sort(compareLockEntries);
20
+ }
21
+
22
+ function stableSortSecrets(secrets: SecretRequirement[]): SecretRequirement[] {
23
+ return [...secrets].sort(compareSecrets);
24
+ }
25
+
26
+ function canonicalizeLockEntry(entry: ForgeLockEntry): ForgeLockEntry {
27
+ return {
28
+ name: entry.name,
29
+ version: entry.version,
30
+ ...(entry.recipeVersion !== undefined
31
+ ? { recipeVersion: entry.recipeVersion }
32
+ : {}),
33
33
  runtimeContexts: stableSortStrings([...entry.runtimeContexts]) as ForgeLockEntry["runtimeContexts"],
34
- capabilities: {
35
- ...entry.capabilities,
36
- secrets: stableSortSecrets([...entry.capabilities.secrets]),
37
- },
38
- secrets: stableSortSecrets([...entry.secrets]),
39
- generatedFiles: stableSortByPath([...entry.generatedFiles]),
40
- contentChecksum: entry.contentChecksum,
41
- };
42
- }
43
-
44
- /**
45
- * Deterministic forge.lock serialization (no deterministic header).
46
- */
47
- export function serializeForgeLock(lock: ForgeLock): string {
48
- const canonical: ForgeLock = {
49
- schemaVersion: lock.schemaVersion,
50
- generatorVersion: lock.generatorVersion,
51
- analyzerVersion: lock.analyzerVersion,
52
- inputHash: lock.inputHash,
53
- lockfileHash: lock.lockfileHash,
54
- packageManager: lock.packageManager,
55
- ...(lock.recipeVersion !== undefined
56
- ? { recipeVersion: lock.recipeVersion }
57
- : {}),
58
- packages: stableSortLockEntries(lock.packages).map(canonicalizeLockEntry),
59
- };
60
-
61
- return serializeCanonical(canonical);
62
- }
34
+ capabilities: {
35
+ ...entry.capabilities,
36
+ secrets: stableSortSecrets([...entry.capabilities.secrets]),
37
+ },
38
+ secrets: stableSortSecrets([...entry.secrets]),
39
+ generatedFiles: stableSortByPath([...entry.generatedFiles]),
40
+ contentChecksum: entry.contentChecksum,
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Deterministic forge.lock serialization (no deterministic header).
46
+ */
47
+ export function serializeForgeLock(lock: ForgeLock): string {
48
+ const canonical: ForgeLock = {
49
+ schemaVersion: lock.schemaVersion,
50
+ generatorVersion: lock.generatorVersion,
51
+ analyzerVersion: lock.analyzerVersion,
52
+ inputHash: lock.inputHash,
53
+ lockfileHash: lock.lockfileHash,
54
+ packageManager: lock.packageManager,
55
+ ...(lock.recipeVersion !== undefined
56
+ ? { recipeVersion: lock.recipeVersion }
57
+ : {}),
58
+ packages: stableSortLockEntries(lock.packages).map(canonicalizeLockEntry),
59
+ };
60
+
61
+ return serializeCanonical(canonical);
62
+ }
@@ -1,73 +1,73 @@
1
- import type { EmitFile } from "../types/emit.ts";
2
- import {
3
- hashStable,
4
- prependDeterministicHeader,
5
- normalizeNewlines,
6
- serializeCanonical,
7
- } from "../primitives/index.ts";
8
- import { detectArtifactKind } from "./artifact-kind.ts";
9
-
10
- export interface RenderContext {
11
- generatorVersion: string;
12
- inputHash: string;
13
- }
14
-
15
- function renderJsonBody(content: string): string {
16
- try {
17
- const parsed: unknown = JSON.parse(content);
18
- return serializeCanonical(parsed);
19
- } catch {
20
- return normalizeNewlines(content);
21
- }
22
- }
23
-
24
- function renderTypeScriptBody(content: string): string {
25
- return normalizeNewlines(content);
26
- }
27
-
28
- function renderMarkdownBody(content: string): string {
29
- return normalizeNewlines(content);
30
- }
31
-
32
- function renderTextBody(content: string): string {
33
- return normalizeNewlines(content);
34
- }
35
-
36
- /**
37
- * Normalize file body bytes by artifact kind (no deterministic header).
38
- */
39
- export function renderBody(file: EmitFile): string {
40
- const kind = detectArtifactKind(file.path);
41
-
42
- switch (kind) {
43
- case "json":
44
- if (file.canonical) {
45
- return normalizeNewlines(file.content);
46
- }
47
- return renderJsonBody(file.content);
48
- case "typescript":
49
- return renderTypeScriptBody(file.content);
50
- case "markdown":
51
- return renderMarkdownBody(file.content);
52
- default:
53
- return renderTextBody(file.content);
54
- }
55
- }
56
-
57
- /**
58
- * Pure render: same EmitFile + context → same bytes (header included).
59
- */
60
- export function render(file: EmitFile, context: RenderContext): string {
61
- const body = renderBody(file);
62
-
63
- if (file.contentHash !== hashStable(body)) {
64
- throw new Error(
65
- `EmitFile contentHash mismatch for ${file.path}: expected ${hashStable(body)}, got ${file.contentHash}`,
66
- );
67
- }
68
-
69
- return prependDeterministicHeader(body, {
70
- generatorVersion: context.generatorVersion,
71
- inputHash: context.inputHash,
72
- });
73
- }
1
+ import type { EmitFile } from "../types/emit.ts";
2
+ import {
3
+ hashStable,
4
+ prependDeterministicHeader,
5
+ normalizeNewlines,
6
+ serializeCanonical,
7
+ } from "../primitives/index.ts";
8
+ import { detectArtifactKind } from "./artifact-kind.ts";
9
+
10
+ export interface RenderContext {
11
+ generatorVersion: string;
12
+ inputHash: string;
13
+ }
14
+
15
+ function renderJsonBody(content: string): string {
16
+ try {
17
+ const parsed: unknown = JSON.parse(content);
18
+ return serializeCanonical(parsed);
19
+ } catch {
20
+ return normalizeNewlines(content);
21
+ }
22
+ }
23
+
24
+ function renderTypeScriptBody(content: string): string {
25
+ return normalizeNewlines(content);
26
+ }
27
+
28
+ function renderMarkdownBody(content: string): string {
29
+ return normalizeNewlines(content);
30
+ }
31
+
32
+ function renderTextBody(content: string): string {
33
+ return normalizeNewlines(content);
34
+ }
35
+
36
+ /**
37
+ * Normalize file body bytes by artifact kind (no deterministic header).
38
+ */
39
+ export function renderBody(file: EmitFile): string {
40
+ const kind = detectArtifactKind(file.path);
41
+
42
+ switch (kind) {
43
+ case "json":
44
+ if (file.canonical) {
45
+ return normalizeNewlines(file.content);
46
+ }
47
+ return renderJsonBody(file.content);
48
+ case "typescript":
49
+ return renderTypeScriptBody(file.content);
50
+ case "markdown":
51
+ return renderMarkdownBody(file.content);
52
+ default:
53
+ return renderTextBody(file.content);
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Pure render: same EmitFile + context → same bytes (header included).
59
+ */
60
+ export function render(file: EmitFile, context: RenderContext): string {
61
+ const body = renderBody(file);
62
+
63
+ if (file.contentHash !== hashStable(body)) {
64
+ throw new Error(
65
+ `EmitFile contentHash mismatch for ${file.path}: expected ${hashStable(body)}, got ${file.contentHash}`,
66
+ );
67
+ }
68
+
69
+ return prependDeterministicHeader(body, {
70
+ generatorVersion: context.generatorVersion,
71
+ inputHash: context.inputHash,
72
+ });
73
+ }
@@ -1,96 +1,96 @@
1
- import { GENERATED_DIR } from "../emitter/constants.ts";
2
- import { hashStable, serializeCanonical } from "../primitives/index.ts";
3
- import type { EmitFile } from "../types/emit.ts";
4
- import type { ModuleGraph } from "../types/app-graph.ts";
5
- import type { ImportGuardsArtifact } from "../types/import-guards.ts";
6
- import type { RuntimeMatrix } from "../types/runtime-matrix.ts";
7
- import { propagateContexts } from "./propagate-contexts.ts";
8
-
9
- export function buildImportGuardsArtifact(
10
- matrix: RuntimeMatrix,
11
- moduleGraph?: ModuleGraph,
12
- ): ImportGuardsArtifact {
13
- const entries = matrix.entries.map((entry) => ({
14
- packageName: entry.packageName,
15
- alias: entry.alias,
16
- compatible: [...entry.compatible],
17
- incompatible: [...entry.incompatible],
18
- rationale: { ...entry.rationale },
19
- }));
20
-
21
- let moduleContexts: ImportGuardsArtifact["moduleContexts"] = [];
22
- if (moduleGraph) {
23
- propagateContexts(moduleGraph);
24
- moduleContexts = moduleGraph.nodes
25
- .filter((node) => node.effectiveContexts.length > 0)
26
- .map((node) => ({
27
- file: node.file,
28
- effectiveContexts: [...node.effectiveContexts],
29
- }))
30
- .sort((a, b) => (a.file < b.file ? -1 : a.file > b.file ? 1 : 0));
31
- }
32
-
33
- return {
34
- schemaVersion: matrix.schemaVersion,
35
- entries,
36
- moduleContexts,
37
- };
38
- }
39
-
40
- function renderRuntimeMatrixTs(matrix: RuntimeMatrix): string {
41
- return `export const runtimeMatrix = ${serializeCanonical(matrix).trim()} as const;\n`;
42
- }
43
-
44
- function renderImportGuardsTs(artifact: ImportGuardsArtifact): string {
45
- return `export const importGuards = ${serializeCanonical(artifact).trim()} as const;\n`;
46
- }
47
-
48
- export function buildRuntimeMatrixEmitFiles(matrix: RuntimeMatrix): EmitFile[] {
49
- const jsonBody = serializeCanonical(matrix);
50
- const tsBody = renderRuntimeMatrixTs(matrix);
51
-
52
- return [
53
- {
54
- path: `${GENERATED_DIR}/runtimeMatrix.json`,
55
- content: jsonBody,
56
- contentHash: hashStable(jsonBody),
57
- },
58
- {
59
- path: `${GENERATED_DIR}/runtimeMatrix.ts`,
60
- content: tsBody,
61
- contentHash: hashStable(tsBody),
62
- },
63
- ];
64
- }
65
-
66
- export function buildImportGuardsEmitFiles(
67
- matrix: RuntimeMatrix,
68
- moduleGraph?: ModuleGraph,
69
- ): EmitFile[] {
70
- const artifact = buildImportGuardsArtifact(matrix, moduleGraph);
71
- const jsonBody = serializeCanonical(artifact);
72
- const tsBody = renderImportGuardsTs(artifact);
73
-
74
- return [
75
- {
76
- path: `${GENERATED_DIR}/importGuards.json`,
77
- content: jsonBody,
78
- contentHash: hashStable(jsonBody),
79
- },
80
- {
81
- path: `${GENERATED_DIR}/importGuards.ts`,
82
- content: tsBody,
83
- contentHash: hashStable(tsBody),
84
- },
85
- ];
86
- }
87
-
88
- export function buildGuardArtifactEmitFiles(
89
- matrix: RuntimeMatrix,
90
- moduleGraph?: ModuleGraph,
91
- ): EmitFile[] {
92
- return [
93
- ...buildRuntimeMatrixEmitFiles(matrix),
94
- ...buildImportGuardsEmitFiles(matrix, moduleGraph),
95
- ];
96
- }
1
+ import { GENERATED_DIR } from "../emitter/constants.ts";
2
+ import { hashStable, serializeCanonical } from "../primitives/index.ts";
3
+ import type { EmitFile } from "../types/emit.ts";
4
+ import type { ModuleGraph } from "../types/app-graph.ts";
5
+ import type { ImportGuardsArtifact } from "../types/import-guards.ts";
6
+ import type { RuntimeMatrix } from "../types/runtime-matrix.ts";
7
+ import { propagateContexts } from "./propagate-contexts.ts";
8
+
9
+ export function buildImportGuardsArtifact(
10
+ matrix: RuntimeMatrix,
11
+ moduleGraph?: ModuleGraph,
12
+ ): ImportGuardsArtifact {
13
+ const entries = matrix.entries.map((entry) => ({
14
+ packageName: entry.packageName,
15
+ alias: entry.alias,
16
+ compatible: [...entry.compatible],
17
+ incompatible: [...entry.incompatible],
18
+ rationale: { ...entry.rationale },
19
+ }));
20
+
21
+ let moduleContexts: ImportGuardsArtifact["moduleContexts"] = [];
22
+ if (moduleGraph) {
23
+ propagateContexts(moduleGraph);
24
+ moduleContexts = moduleGraph.nodes
25
+ .filter((node) => node.effectiveContexts.length > 0)
26
+ .map((node) => ({
27
+ file: node.file,
28
+ effectiveContexts: [...node.effectiveContexts],
29
+ }))
30
+ .sort((a, b) => (a.file < b.file ? -1 : a.file > b.file ? 1 : 0));
31
+ }
32
+
33
+ return {
34
+ schemaVersion: matrix.schemaVersion,
35
+ entries,
36
+ moduleContexts,
37
+ };
38
+ }
39
+
40
+ function renderRuntimeMatrixTs(matrix: RuntimeMatrix): string {
41
+ return `export const runtimeMatrix = ${serializeCanonical(matrix).trim()} as const;\n`;
42
+ }
43
+
44
+ function renderImportGuardsTs(artifact: ImportGuardsArtifact): string {
45
+ return `export const importGuards = ${serializeCanonical(artifact).trim()} as const;\n`;
46
+ }
47
+
48
+ export function buildRuntimeMatrixEmitFiles(matrix: RuntimeMatrix): EmitFile[] {
49
+ const jsonBody = serializeCanonical(matrix);
50
+ const tsBody = renderRuntimeMatrixTs(matrix);
51
+
52
+ return [
53
+ {
54
+ path: `${GENERATED_DIR}/runtimeMatrix.json`,
55
+ content: jsonBody,
56
+ contentHash: hashStable(jsonBody),
57
+ },
58
+ {
59
+ path: `${GENERATED_DIR}/runtimeMatrix.ts`,
60
+ content: tsBody,
61
+ contentHash: hashStable(tsBody),
62
+ },
63
+ ];
64
+ }
65
+
66
+ export function buildImportGuardsEmitFiles(
67
+ matrix: RuntimeMatrix,
68
+ moduleGraph?: ModuleGraph,
69
+ ): EmitFile[] {
70
+ const artifact = buildImportGuardsArtifact(matrix, moduleGraph);
71
+ const jsonBody = serializeCanonical(artifact);
72
+ const tsBody = renderImportGuardsTs(artifact);
73
+
74
+ return [
75
+ {
76
+ path: `${GENERATED_DIR}/importGuards.json`,
77
+ content: jsonBody,
78
+ contentHash: hashStable(jsonBody),
79
+ },
80
+ {
81
+ path: `${GENERATED_DIR}/importGuards.ts`,
82
+ content: tsBody,
83
+ contentHash: hashStable(tsBody),
84
+ },
85
+ ];
86
+ }
87
+
88
+ export function buildGuardArtifactEmitFiles(
89
+ matrix: RuntimeMatrix,
90
+ moduleGraph?: ModuleGraph,
91
+ ): EmitFile[] {
92
+ return [
93
+ ...buildRuntimeMatrixEmitFiles(matrix),
94
+ ...buildImportGuardsEmitFiles(matrix, moduleGraph),
95
+ ];
96
+ }
@@ -1,106 +1,106 @@
1
- import { lookupMatrixEntry } from "../classifier/runtime-matrix.ts";
2
- import { forgeGuardViolation } from "../diagnostics/create.ts";
3
- import type { ModuleGraph } from "../types/app-graph.ts";
4
- import type { Diagnostic } from "../types/diagnostic.ts";
5
- import type { RuntimeContext } from "../types/runtime.ts";
6
- import type { RuntimeMatrix } from "../types/runtime-matrix.ts";
7
- import { comparePaths } from "../primitives/paths.ts";
8
- import { compareBytes } from "../primitives/compare.ts";
9
- import { propagateContexts } from "./propagate-contexts.ts";
10
-
11
- function compareDiagnostics(a: Diagnostic, b: Diagnostic): number {
12
- let cmp = comparePaths(a.file ?? "", b.file ?? "");
13
- if (cmp !== 0) {
14
- return cmp;
15
- }
16
-
17
- cmp = (a.span?.start ?? 0) - (b.span?.start ?? 0);
18
- if (cmp !== 0) {
19
- return cmp;
20
- }
21
-
22
- const aPackage = extractPackageName(a.message);
23
- const bPackage = extractPackageName(b.message);
24
- cmp = compareBytes(aPackage, bPackage);
25
- if (cmp !== 0) {
26
- return cmp;
27
- }
28
-
29
- const aContext = extractContext(a.message);
30
- const bContext = extractContext(b.message);
31
- return compareBytes(aContext, bContext);
32
- }
33
-
34
- function extractPackageName(message: string): string {
35
- const match = /^'([^']+)' is not allowed/.exec(message);
36
- return match?.[1] ?? "";
37
- }
38
-
39
- function extractContext(message: string): string {
40
- const match = /'([^']+)' context/.exec(message);
41
- return match?.[1] ?? "";
42
- }
43
-
44
- /**
45
- * Evaluate package imports against the runtime matrix after propagating effective contexts.
46
- */
47
- export function checkImportGuards(
48
- moduleGraph: ModuleGraph,
49
- matrix: RuntimeMatrix,
50
- ): Diagnostic[] {
51
- propagateContexts(moduleGraph);
52
-
53
- const diagnostics: Diagnostic[] = [];
54
- const recorded = new Set<string>();
55
-
56
- for (const node of moduleGraph.nodes) {
57
- if (node.effectiveContexts.length === 0) {
58
- continue;
59
- }
60
-
61
- for (const imp of node.directPackageImports) {
62
- const entry = lookupMatrixEntry(matrix, imp.packageName);
63
- if (entry == null) {
64
- continue;
65
- }
66
-
67
- for (const context of node.effectiveContexts) {
68
- if (!entry.compatible.includes(context)) {
69
- const key = `${node.file}\0${imp.packageName}\0${context}\0${imp.span.start}`;
70
- if (recorded.has(key)) {
71
- continue;
72
- }
73
- recorded.add(key);
74
-
75
- const rationale =
76
- entry.rationale[context] ??
77
- "package is incompatible with this runtime context";
78
- diagnostics.push(
79
- forgeGuardViolation(
80
- imp.packageName,
81
- context,
82
- rationale,
83
- node.file,
84
- imp.span,
85
- ),
86
- );
87
- }
88
- }
89
- }
90
- }
91
-
92
- diagnostics.sort(compareDiagnostics);
93
- return diagnostics;
94
- }
95
-
96
- export function isContextViolating(
97
- matrix: RuntimeMatrix,
98
- packageName: string,
99
- context: RuntimeContext,
100
- ): boolean {
101
- const entry = lookupMatrixEntry(matrix, packageName);
102
- if (entry == null) {
103
- return false;
104
- }
105
- return !entry.compatible.includes(context);
106
- }
1
+ import { lookupMatrixEntry } from "../classifier/runtime-matrix.ts";
2
+ import { forgeGuardViolation } from "../diagnostics/create.ts";
3
+ import type { ModuleGraph } from "../types/app-graph.ts";
4
+ import type { Diagnostic } from "../types/diagnostic.ts";
5
+ import type { RuntimeContext } from "../types/runtime.ts";
6
+ import type { RuntimeMatrix } from "../types/runtime-matrix.ts";
7
+ import { comparePaths } from "../primitives/paths.ts";
8
+ import { compareBytes } from "../primitives/compare.ts";
9
+ import { propagateContexts } from "./propagate-contexts.ts";
10
+
11
+ function compareDiagnostics(a: Diagnostic, b: Diagnostic): number {
12
+ let cmp = comparePaths(a.file ?? "", b.file ?? "");
13
+ if (cmp !== 0) {
14
+ return cmp;
15
+ }
16
+
17
+ cmp = (a.span?.start ?? 0) - (b.span?.start ?? 0);
18
+ if (cmp !== 0) {
19
+ return cmp;
20
+ }
21
+
22
+ const aPackage = extractPackageName(a.message);
23
+ const bPackage = extractPackageName(b.message);
24
+ cmp = compareBytes(aPackage, bPackage);
25
+ if (cmp !== 0) {
26
+ return cmp;
27
+ }
28
+
29
+ const aContext = extractContext(a.message);
30
+ const bContext = extractContext(b.message);
31
+ return compareBytes(aContext, bContext);
32
+ }
33
+
34
+ function extractPackageName(message: string): string {
35
+ const match = /^'([^']+)' is not allowed/.exec(message);
36
+ return match?.[1] ?? "";
37
+ }
38
+
39
+ function extractContext(message: string): string {
40
+ const match = /'([^']+)' context/.exec(message);
41
+ return match?.[1] ?? "";
42
+ }
43
+
44
+ /**
45
+ * Evaluate package imports against the runtime matrix after propagating effective contexts.
46
+ */
47
+ export function checkImportGuards(
48
+ moduleGraph: ModuleGraph,
49
+ matrix: RuntimeMatrix,
50
+ ): Diagnostic[] {
51
+ propagateContexts(moduleGraph);
52
+
53
+ const diagnostics: Diagnostic[] = [];
54
+ const recorded = new Set<string>();
55
+
56
+ for (const node of moduleGraph.nodes) {
57
+ if (node.effectiveContexts.length === 0) {
58
+ continue;
59
+ }
60
+
61
+ for (const imp of node.directPackageImports) {
62
+ const entry = lookupMatrixEntry(matrix, imp.packageName);
63
+ if (entry == null) {
64
+ continue;
65
+ }
66
+
67
+ for (const context of node.effectiveContexts) {
68
+ if (!entry.compatible.includes(context)) {
69
+ const key = `${node.file}\0${imp.packageName}\0${context}\0${imp.span.start}`;
70
+ if (recorded.has(key)) {
71
+ continue;
72
+ }
73
+ recorded.add(key);
74
+
75
+ const rationale =
76
+ entry.rationale[context] ??
77
+ "package is incompatible with this runtime context";
78
+ diagnostics.push(
79
+ forgeGuardViolation(
80
+ imp.packageName,
81
+ context,
82
+ rationale,
83
+ node.file,
84
+ imp.span,
85
+ ),
86
+ );
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ diagnostics.sort(compareDiagnostics);
93
+ return diagnostics;
94
+ }
95
+
96
+ export function isContextViolating(
97
+ matrix: RuntimeMatrix,
98
+ packageName: string,
99
+ context: RuntimeContext,
100
+ ): boolean {
101
+ const entry = lookupMatrixEntry(matrix, packageName);
102
+ if (entry == null) {
103
+ return false;
104
+ }
105
+ return !entry.compatible.includes(context);
106
+ }