forgeos 0.1.0-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 (540) hide show
  1. package/.npmignore +1 -0
  2. package/AGENTS.md +277 -0
  3. package/CHANGELOG.md +8 -0
  4. package/CONTRIBUTING.md +58 -0
  5. package/README.md +377 -0
  6. package/bin/forge-bun.mjs +110 -0
  7. package/bin/forge.mjs +19 -0
  8. package/package.json +96 -0
  9. package/packages/eslint-plugin-forge/index.ts +15 -0
  10. package/packages/eslint-plugin-forge/package.json +10 -0
  11. package/packages/eslint-plugin-forge/src/check-source.ts +95 -0
  12. package/packages/eslint-plugin-forge/src/load-artifacts.ts +24 -0
  13. package/packages/eslint-plugin-forge/src/rule-no-forge-guard-violation.ts +93 -0
  14. package/src/forge/_generated/actionSubscriptions.json +2 -0
  15. package/src/forge/_generated/actionSubscriptions.ts +10 -0
  16. package/src/forge/_generated/agentAdapterManifest.json +2 -0
  17. package/src/forge/_generated/agentAdapterManifest.ts +73 -0
  18. package/src/forge/_generated/agentContract.json +2 -0
  19. package/src/forge/_generated/agentContract.ts +912 -0
  20. package/src/forge/_generated/agentQuickstart.md +32 -0
  21. package/src/forge/_generated/aiContext.ts +59 -0
  22. package/src/forge/_generated/aiModels.json +2 -0
  23. package/src/forge/_generated/aiModels.ts +35 -0
  24. package/src/forge/_generated/aiProviders.json +2 -0
  25. package/src/forge/_generated/aiProviders.ts +23 -0
  26. package/src/forge/_generated/aiRegistry.json +2 -0
  27. package/src/forge/_generated/aiRegistry.ts +29 -0
  28. package/src/forge/_generated/api.json +2 -0
  29. package/src/forge/_generated/api.ts +8 -0
  30. package/src/forge/_generated/appGraph.json +2 -0
  31. package/src/forge/_generated/appGraph.ts +14511 -0
  32. package/src/forge/_generated/appMap.md +35 -0
  33. package/src/forge/_generated/artifactManifest.json +2 -0
  34. package/src/forge/_generated/artifactManifest.ts +7 -0
  35. package/src/forge/_generated/authClaims.json +2 -0
  36. package/src/forge/_generated/authClaims.ts +13 -0
  37. package/src/forge/_generated/authConfig.json +2 -0
  38. package/src/forge/_generated/authConfig.ts +17 -0
  39. package/src/forge/_generated/authContext.ts +23 -0
  40. package/src/forge/_generated/authRegistry.json +2 -0
  41. package/src/forge/_generated/authRegistry.ts +25 -0
  42. package/src/forge/_generated/buildInfo.json +2 -0
  43. package/src/forge/_generated/buildInfo.ts +9 -0
  44. package/src/forge/_generated/capabilityMap.json +2 -0
  45. package/src/forge/_generated/capabilityMap.md +15 -0
  46. package/src/forge/_generated/capabilityMap.ts +17 -0
  47. package/src/forge/_generated/client.ts +282 -0
  48. package/src/forge/_generated/clientApi.ts +9 -0
  49. package/src/forge/_generated/clientManifest.json +2 -0
  50. package/src/forge/_generated/clientManifest.ts +39 -0
  51. package/src/forge/_generated/clientTypes.ts +78 -0
  52. package/src/forge/_generated/configRegistry.json +2 -0
  53. package/src/forge/_generated/configRegistry.ts +4 -0
  54. package/src/forge/_generated/dataGraph.json +2 -0
  55. package/src/forge/_generated/dataGraph.ts +8 -0
  56. package/src/forge/_generated/db.json +2 -0
  57. package/src/forge/_generated/db.ts +2 -0
  58. package/src/forge/_generated/dbSecurityManifest.json +2 -0
  59. package/src/forge/_generated/dbSecurityManifest.ts +15 -0
  60. package/src/forge/_generated/dbSessionContext.json +2 -0
  61. package/src/forge/_generated/dbSessionContext.ts +39 -0
  62. package/src/forge/_generated/deployManifest.json +2 -0
  63. package/src/forge/_generated/deployManifest.ts +14 -0
  64. package/src/forge/_generated/devManifest.json +2 -0
  65. package/src/forge/_generated/devManifest.ts +47 -0
  66. package/src/forge/_generated/envSchema.json +2 -0
  67. package/src/forge/_generated/envSchema.ts +59 -0
  68. package/src/forge/_generated/frontendGraph.json +2 -0
  69. package/src/forge/_generated/frontendGraph.ts +27 -0
  70. package/src/forge/_generated/importGuards.json +2 -0
  71. package/src/forge/_generated/importGuards.ts +652 -0
  72. package/src/forge/_generated/index.ts +67 -0
  73. package/src/forge/_generated/liveProductionManifest.json +2 -0
  74. package/src/forge/_generated/liveProductionManifest.ts +23 -0
  75. package/src/forge/_generated/liveProtocol.json +2 -0
  76. package/src/forge/_generated/liveProtocol.ts +21 -0
  77. package/src/forge/_generated/liveQueryRegistry.json +2 -0
  78. package/src/forge/_generated/liveQueryRegistry.ts +9 -0
  79. package/src/forge/_generated/liveTransportConfig.json +2 -0
  80. package/src/forge/_generated/liveTransportConfig.ts +19 -0
  81. package/src/forge/_generated/makeRegistry.json +2 -0
  82. package/src/forge/_generated/makeRegistry.ts +163 -0
  83. package/src/forge/_generated/makeTemplates.json +2 -0
  84. package/src/forge/_generated/makeTemplates.ts +61 -0
  85. package/src/forge/_generated/mockMap.json +2 -0
  86. package/src/forge/_generated/mockMap.ts +7 -0
  87. package/src/forge/_generated/operationPlaybooks.md +145 -0
  88. package/src/forge/_generated/packageGraph.json +2 -0
  89. package/src/forge/_generated/packageGraph.ts +168569 -0
  90. package/src/forge/_generated/packageUpgradeRegistry.json +2 -0
  91. package/src/forge/_generated/packageUpgradeRegistry.ts +15 -0
  92. package/src/forge/_generated/permissionMatrix.json +2 -0
  93. package/src/forge/_generated/permissionMatrix.ts +7 -0
  94. package/src/forge/_generated/policyRegistry.json +2 -0
  95. package/src/forge/_generated/policyRegistry.ts +11 -0
  96. package/src/forge/_generated/queryRegistry.json +2 -0
  97. package/src/forge/_generated/queryRegistry.ts +9 -0
  98. package/src/forge/_generated/react.d.ts +22 -0
  99. package/src/forge/_generated/react.ts +29 -0
  100. package/src/forge/_generated/reactManifest.json +2 -0
  101. package/src/forge/_generated/reactManifest.ts +19 -0
  102. package/src/forge/_generated/releaseManifest.json +2 -0
  103. package/src/forge/_generated/releaseManifest.ts +25 -0
  104. package/src/forge/_generated/rlsPolicies.json +2 -0
  105. package/src/forge/_generated/rlsPolicies.sql +34 -0
  106. package/src/forge/_generated/rlsPolicies.ts +6 -0
  107. package/src/forge/_generated/runtimeGraph.json +2 -0
  108. package/src/forge/_generated/runtimeGraph.ts +8 -0
  109. package/src/forge/_generated/runtimeMatrix.json +2 -0
  110. package/src/forge/_generated/runtimeMatrix.ts +229125 -0
  111. package/src/forge/_generated/runtimeRegistry.ts +2 -0
  112. package/src/forge/_generated/runtimeRules.md +79 -0
  113. package/src/forge/_generated/secretRegistry.json +2 -0
  114. package/src/forge/_generated/secretRegistry.ts +50 -0
  115. package/src/forge/_generated/secretsContext.ts +11 -0
  116. package/src/forge/_generated/serverApi.ts +10 -0
  117. package/src/forge/_generated/sourceMapManifest.json +2 -0
  118. package/src/forge/_generated/sourceMapManifest.ts +7 -0
  119. package/src/forge/_generated/sqlPlan.json +2 -0
  120. package/src/forge/_generated/sqlPlan.ts +88 -0
  121. package/src/forge/_generated/subscriptionManifest.json +2 -0
  122. package/src/forge/_generated/subscriptionManifest.ts +7 -0
  123. package/src/forge/_generated/symbolicationManifest.json +2 -0
  124. package/src/forge/_generated/symbolicationManifest.ts +17 -0
  125. package/src/forge/_generated/telemetryRegistry.json +2 -0
  126. package/src/forge/_generated/telemetryRegistry.ts +9 -0
  127. package/src/forge/_generated/telemetrySinks.json +2 -0
  128. package/src/forge/_generated/telemetrySinks.ts +11 -0
  129. package/src/forge/_generated/tenantScope.json +2 -0
  130. package/src/forge/_generated/tenantScope.ts +8 -0
  131. package/src/forge/_generated/testGraph.json +2 -0
  132. package/src/forge/_generated/testGraph.ts +3054 -0
  133. package/src/forge/_generated/testPlanRegistry.json +2 -0
  134. package/src/forge/_generated/testPlanRegistry.ts +33 -0
  135. package/src/forge/_generated/uiRoutes.json +2 -0
  136. package/src/forge/_generated/uiRoutes.ts +16 -0
  137. package/src/forge/_generated/uiScenarios.json +2 -0
  138. package/src/forge/_generated/uiScenarios.ts +30 -0
  139. package/src/forge/_generated/uiTestManifest.json +2 -0
  140. package/src/forge/_generated/uiTestManifest.ts +27 -0
  141. package/src/forge/_generated/workflowRegistry.json +2 -0
  142. package/src/forge/_generated/workflowRegistry.ts +9 -0
  143. package/src/forge/_generated/workflowSubscriptions.json +2 -0
  144. package/src/forge/_generated/workflowSubscriptions.ts +10 -0
  145. package/src/forge/agent-adapters/index.ts +1002 -0
  146. package/src/forge/agent-adapters/types.ts +135 -0
  147. package/src/forge/cli/agent-contract.ts +50 -0
  148. package/src/forge/cli/ai.ts +148 -0
  149. package/src/forge/cli/auth.ts +198 -0
  150. package/src/forge/cli/build.ts +105 -0
  151. package/src/forge/cli/bun-exec.ts +4 -0
  152. package/src/forge/cli/commands.ts +1130 -0
  153. package/src/forge/cli/db.ts +316 -0
  154. package/src/forge/cli/deps.ts +277 -0
  155. package/src/forge/cli/dev.ts +529 -0
  156. package/src/forge/cli/doctor.ts +209 -0
  157. package/src/forge/cli/feature.ts +485 -0
  158. package/src/forge/cli/index.ts +25 -0
  159. package/src/forge/cli/lint-forge.ts +119 -0
  160. package/src/forge/cli/live.ts +179 -0
  161. package/src/forge/cli/main.ts +92 -0
  162. package/src/forge/cli/make.ts +133 -0
  163. package/src/forge/cli/new.ts +505 -0
  164. package/src/forge/cli/outbox.ts +297 -0
  165. package/src/forge/cli/output.ts +114 -0
  166. package/src/forge/cli/parse.ts +2211 -0
  167. package/src/forge/cli/policy.ts +204 -0
  168. package/src/forge/cli/query.ts +91 -0
  169. package/src/forge/cli/refactor.ts +221 -0
  170. package/src/forge/cli/release.ts +285 -0
  171. package/src/forge/cli/rls.ts +322 -0
  172. package/src/forge/cli/run.ts +76 -0
  173. package/src/forge/cli/secrets.ts +274 -0
  174. package/src/forge/cli/self-host.ts +468 -0
  175. package/src/forge/cli/serve.ts +93 -0
  176. package/src/forge/cli/telemetry.ts +219 -0
  177. package/src/forge/cli/verify.ts +587 -0
  178. package/src/forge/cli/version.ts +1 -0
  179. package/src/forge/cli/windows.ts +413 -0
  180. package/src/forge/cli/worker.ts +87 -0
  181. package/src/forge/cli/workflow.ts +424 -0
  182. package/src/forge/compiler/action-subscriptions/build.ts +116 -0
  183. package/src/forge/compiler/action-subscriptions/constants.ts +2 -0
  184. package/src/forge/compiler/action-subscriptions/index.ts +6 -0
  185. package/src/forge/compiler/action-subscriptions/parse.ts +6 -0
  186. package/src/forge/compiler/agent-contract/build.ts +1651 -0
  187. package/src/forge/compiler/agent-contract/types.ts +326 -0
  188. package/src/forge/compiler/ai-registry/build.ts +165 -0
  189. package/src/forge/compiler/ai-registry/constants.ts +2 -0
  190. package/src/forge/compiler/ai-registry/parse.ts +56 -0
  191. package/src/forge/compiler/api-surface/build.ts +107 -0
  192. package/src/forge/compiler/app-graph/build.ts +121 -0
  193. package/src/forge/compiler/app-graph/classify.ts +10 -0
  194. package/src/forge/compiler/app-graph/dup-symbol.ts +29 -0
  195. package/src/forge/compiler/app-graph/extract.ts +124 -0
  196. package/src/forge/compiler/app-graph/forge-apis.ts +29 -0
  197. package/src/forge/compiler/app-graph/index.ts +15 -0
  198. package/src/forge/compiler/app-graph/module-graph.ts +320 -0
  199. package/src/forge/compiler/app-graph/parser.ts +119 -0
  200. package/src/forge/compiler/app-graph/symbols.ts +48 -0
  201. package/src/forge/compiler/app-graph/tsconfig-hash.ts +62 -0
  202. package/src/forge/compiler/app-graph/types.ts +43 -0
  203. package/src/forge/compiler/app-graph/versions.ts +14 -0
  204. package/src/forge/compiler/cache/index.ts +17 -0
  205. package/src/forge/compiler/cache/key.ts +46 -0
  206. package/src/forge/compiler/cache/scheduler.ts +72 -0
  207. package/src/forge/compiler/cache/store.ts +78 -0
  208. package/src/forge/compiler/classifier/capabilities.ts +78 -0
  209. package/src/forge/compiler/classifier/classify.ts +113 -0
  210. package/src/forge/compiler/classifier/contexts.ts +188 -0
  211. package/src/forge/compiler/classifier/index.ts +18 -0
  212. package/src/forge/compiler/classifier/runtime-matrix.ts +45 -0
  213. package/src/forge/compiler/classifier/secrets.ts +41 -0
  214. package/src/forge/compiler/classifier/signals.ts +129 -0
  215. package/src/forge/compiler/client-sdk/build-manifest.ts +151 -0
  216. package/src/forge/compiler/client-sdk/render-client.ts +432 -0
  217. package/src/forge/compiler/data-graph/build.ts +131 -0
  218. package/src/forge/compiler/data-graph/constants.ts +5 -0
  219. package/src/forge/compiler/data-graph/index.ts +6 -0
  220. package/src/forge/compiler/data-graph/parse.ts +176 -0
  221. package/src/forge/compiler/data-graph/rls/build.ts +222 -0
  222. package/src/forge/compiler/data-graph/rls/types.ts +62 -0
  223. package/src/forge/compiler/data-graph/sql/ddl.ts +390 -0
  224. package/src/forge/compiler/data-graph/sql/naming.ts +10 -0
  225. package/src/forge/compiler/data-graph/sql/serialize.ts +85 -0
  226. package/src/forge/compiler/data-graph/sql/types.ts +37 -0
  227. package/src/forge/compiler/dev-manifest/build.ts +170 -0
  228. package/src/forge/compiler/dev-manifest/constants.ts +5 -0
  229. package/src/forge/compiler/diagnostics/codes.ts +611 -0
  230. package/src/forge/compiler/diagnostics/create.ts +245 -0
  231. package/src/forge/compiler/diagnostics/index.ts +55 -0
  232. package/src/forge/compiler/emitter/artifact-kind.ts +14 -0
  233. package/src/forge/compiler/emitter/barrel.ts +44 -0
  234. package/src/forge/compiler/emitter/constants.ts +7 -0
  235. package/src/forge/compiler/emitter/emit.ts +237 -0
  236. package/src/forge/compiler/emitter/index.ts +24 -0
  237. package/src/forge/compiler/emitter/lock.ts +62 -0
  238. package/src/forge/compiler/emitter/render.ts +73 -0
  239. package/src/forge/compiler/emitter/write.ts +35 -0
  240. package/src/forge/compiler/frontend-graph/build.ts +495 -0
  241. package/src/forge/compiler/fs/index.ts +23 -0
  242. package/src/forge/compiler/fs/memory.ts +233 -0
  243. package/src/forge/compiler/fs/node.ts +139 -0
  244. package/src/forge/compiler/fs/profile.ts +108 -0
  245. package/src/forge/compiler/fs/types.ts +52 -0
  246. package/src/forge/compiler/guards/artifacts.ts +96 -0
  247. package/src/forge/compiler/guards/check-ai-usage.ts +98 -0
  248. package/src/forge/compiler/guards/check-import-guards.ts +106 -0
  249. package/src/forge/compiler/guards/check-process-env.ts +98 -0
  250. package/src/forge/compiler/guards/check-query-usage.ts +76 -0
  251. package/src/forge/compiler/guards/index.ts +11 -0
  252. package/src/forge/compiler/guards/propagate-contexts.ts +57 -0
  253. package/src/forge/compiler/index.ts +17 -0
  254. package/src/forge/compiler/integration/add.ts +496 -0
  255. package/src/forge/compiler/integration/index.ts +17 -0
  256. package/src/forge/compiler/integration/plan.ts +283 -0
  257. package/src/forge/compiler/integration/render.ts +189 -0
  258. package/src/forge/compiler/integration/snapshot.ts +52 -0
  259. package/src/forge/compiler/integration/templates/ai.ts +131 -0
  260. package/src/forge/compiler/integration/templates/index.ts +8 -0
  261. package/src/forge/compiler/integration/templates/posthog.ts +145 -0
  262. package/src/forge/compiler/integration/templates/render.ts +113 -0
  263. package/src/forge/compiler/integration/templates/sentry.ts +151 -0
  264. package/src/forge/compiler/integration/templates/stripe.ts +109 -0
  265. package/src/forge/compiler/integration/templates/types.ts +14 -0
  266. package/src/forge/compiler/integration/templates/zod.ts +55 -0
  267. package/src/forge/compiler/live-production/types.ts +122 -0
  268. package/src/forge/compiler/live-query-registry/build.ts +150 -0
  269. package/src/forge/compiler/live-query-registry/constants.ts +2 -0
  270. package/src/forge/compiler/make-registry/build.ts +179 -0
  271. package/src/forge/compiler/orchestrator/discover.ts +214 -0
  272. package/src/forge/compiler/orchestrator/fast-check.ts +117 -0
  273. package/src/forge/compiler/orchestrator/generate-lock.ts +138 -0
  274. package/src/forge/compiler/orchestrator/guards.ts +5 -0
  275. package/src/forge/compiler/orchestrator/index.ts +27 -0
  276. package/src/forge/compiler/orchestrator/manifest-hashes.ts +21 -0
  277. package/src/forge/compiler/orchestrator/manifest.ts +92 -0
  278. package/src/forge/compiler/orchestrator/orphans.ts +51 -0
  279. package/src/forge/compiler/orchestrator/plan.ts +876 -0
  280. package/src/forge/compiler/orchestrator/profile.ts +36 -0
  281. package/src/forge/compiler/orchestrator/run.ts +277 -0
  282. package/src/forge/compiler/orchestrator/serialize.ts +886 -0
  283. package/src/forge/compiler/orchestrator/session.ts +96 -0
  284. package/src/forge/compiler/orchestrator/types.ts +31 -0
  285. package/src/forge/compiler/orchestrator/verify.ts +38 -0
  286. package/src/forge/compiler/orchestrator/workspace-index.ts +154 -0
  287. package/src/forge/compiler/package-graph/capabilities-stub.ts +33 -0
  288. package/src/forge/compiler/package-graph/checksum.ts +97 -0
  289. package/src/forge/compiler/package-graph/compiler.ts +392 -0
  290. package/src/forge/compiler/package-graph/constants.ts +4 -0
  291. package/src/forge/compiler/package-graph/dts-extractor.ts +142 -0
  292. package/src/forge/compiler/package-graph/exports-discovery.ts +84 -0
  293. package/src/forge/compiler/package-graph/extract-dts.ts +32 -0
  294. package/src/forge/compiler/package-graph/index.ts +33 -0
  295. package/src/forge/compiler/package-graph/jsdoc.ts +62 -0
  296. package/src/forge/compiler/package-graph/read-file.ts +21 -0
  297. package/src/forge/compiler/package-graph/resolve.ts +127 -0
  298. package/src/forge/compiler/package-manager/adapter.ts +237 -0
  299. package/src/forge/compiler/package-manager/bun-executable.ts +92 -0
  300. package/src/forge/compiler/package-manager/commands.ts +47 -0
  301. package/src/forge/compiler/package-manager/detect.ts +79 -0
  302. package/src/forge/compiler/package-manager/executor.ts +117 -0
  303. package/src/forge/compiler/package-manager/index.ts +22 -0
  304. package/src/forge/compiler/package-manager/parse-spec.ts +16 -0
  305. package/src/forge/compiler/package-manager/version.ts +27 -0
  306. package/src/forge/compiler/package-upgrades/apply.ts +195 -0
  307. package/src/forge/compiler/package-upgrades/comparator.ts +181 -0
  308. package/src/forge/compiler/package-upgrades/impact.ts +139 -0
  309. package/src/forge/compiler/package-upgrades/markdown.ts +97 -0
  310. package/src/forge/compiler/package-upgrades/planner.ts +532 -0
  311. package/src/forge/compiler/package-upgrades/risk.ts +208 -0
  312. package/src/forge/compiler/package-upgrades/types.ts +174 -0
  313. package/src/forge/compiler/policy-registry/build.ts +266 -0
  314. package/src/forge/compiler/policy-registry/constants.ts +2 -0
  315. package/src/forge/compiler/policy-registry/parse.ts +81 -0
  316. package/src/forge/compiler/primitives/compare.ts +26 -0
  317. package/src/forge/compiler/primitives/hash.ts +40 -0
  318. package/src/forge/compiler/primitives/header.ts +45 -0
  319. package/src/forge/compiler/primitives/index.ts +45 -0
  320. package/src/forge/compiler/primitives/paths.ts +24 -0
  321. package/src/forge/compiler/primitives/result.ts +164 -0
  322. package/src/forge/compiler/primitives/serialize.ts +66 -0
  323. package/src/forge/compiler/primitives/sort.ts +87 -0
  324. package/src/forge/compiler/query-registry/build.ts +114 -0
  325. package/src/forge/compiler/query-registry/constants.ts +2 -0
  326. package/src/forge/compiler/recipes/definitions.ts +289 -0
  327. package/src/forge/compiler/recipes/helpers.ts +37 -0
  328. package/src/forge/compiler/recipes/index.ts +21 -0
  329. package/src/forge/compiler/recipes/registry.ts +102 -0
  330. package/src/forge/compiler/release/build.ts +100 -0
  331. package/src/forge/compiler/release/types.ts +119 -0
  332. package/src/forge/compiler/runtime-graph/build.ts +137 -0
  333. package/src/forge/compiler/runtime-graph/constants.ts +5 -0
  334. package/src/forge/compiler/runtime-graph/index.ts +5 -0
  335. package/src/forge/compiler/sandbox/artifact-sanitize.ts +26 -0
  336. package/src/forge/compiler/sandbox/backends/child.ts +123 -0
  337. package/src/forge/compiler/sandbox/backends/docker.ts +173 -0
  338. package/src/forge/compiler/sandbox/index.ts +51 -0
  339. package/src/forge/compiler/sandbox/inspect.ts +143 -0
  340. package/src/forge/compiler/sandbox/inspector-entry.ts +115 -0
  341. package/src/forge/compiler/sandbox/limits.ts +31 -0
  342. package/src/forge/compiler/sandbox/scrub-env.ts +60 -0
  343. package/src/forge/compiler/sandbox/secret-scan.ts +54 -0
  344. package/src/forge/compiler/sandbox/serialize.ts +106 -0
  345. package/src/forge/compiler/sandbox/types.ts +7 -0
  346. package/src/forge/compiler/secret-registry/build.ts +123 -0
  347. package/src/forge/compiler/telemetry-registry/build.ts +89 -0
  348. package/src/forge/compiler/telemetry-registry/constants.ts +2 -0
  349. package/src/forge/compiler/telemetry-registry/parse.ts +13 -0
  350. package/src/forge/compiler/test-graph/build.ts +277 -0
  351. package/src/forge/compiler/types/action-subscriptions.ts +19 -0
  352. package/src/forge/compiler/types/ai-registry.ts +33 -0
  353. package/src/forge/compiler/types/app-graph.ts +80 -0
  354. package/src/forge/compiler/types/capability.ts +29 -0
  355. package/src/forge/compiler/types/classification.ts +9 -0
  356. package/src/forge/compiler/types/cli.ts +159 -0
  357. package/src/forge/compiler/types/data-graph.ts +24 -0
  358. package/src/forge/compiler/types/dev-manifest.ts +41 -0
  359. package/src/forge/compiler/types/diagnostic.ts +12 -0
  360. package/src/forge/compiler/types/emit.ts +25 -0
  361. package/src/forge/compiler/types/frontend-graph.ts +81 -0
  362. package/src/forge/compiler/types/import-guards.ts +19 -0
  363. package/src/forge/compiler/types/index.ts +98 -0
  364. package/src/forge/compiler/types/integration.ts +25 -0
  365. package/src/forge/compiler/types/json.ts +3 -0
  366. package/src/forge/compiler/types/live-query-registry.ts +32 -0
  367. package/src/forge/compiler/types/lock.ts +37 -0
  368. package/src/forge/compiler/types/package-graph.ts +84 -0
  369. package/src/forge/compiler/types/policy-registry.ts +69 -0
  370. package/src/forge/compiler/types/query-registry.ts +18 -0
  371. package/src/forge/compiler/types/runtime-graph.ts +30 -0
  372. package/src/forge/compiler/types/runtime-matrix.ts +16 -0
  373. package/src/forge/compiler/types/runtime.ts +30 -0
  374. package/src/forge/compiler/types/sandbox.ts +24 -0
  375. package/src/forge/compiler/types/secret-registry.ts +38 -0
  376. package/src/forge/compiler/types/telemetry-registry.ts +26 -0
  377. package/src/forge/compiler/types/test-graph.ts +45 -0
  378. package/src/forge/compiler/types/workflow-registry.ts +42 -0
  379. package/src/forge/compiler/workflow-registry/build.ts +180 -0
  380. package/src/forge/compiler/workflow-registry/constants.ts +2 -0
  381. package/src/forge/compiler/workflow-registry/index.ts +5 -0
  382. package/src/forge/compiler/workflow-registry/parse.ts +19 -0
  383. package/src/forge/dev/server.ts +1379 -0
  384. package/src/forge/dev/types.ts +49 -0
  385. package/src/forge/dev/watch.ts +109 -0
  386. package/src/forge/dev-console/cycle.ts +652 -0
  387. package/src/forge/dev-console/types.ts +99 -0
  388. package/src/forge/feature/compiler.ts +656 -0
  389. package/src/forge/feature/examples.ts +125 -0
  390. package/src/forge/feature/types.ts +177 -0
  391. package/src/forge/impact/index.ts +1160 -0
  392. package/src/forge/impact/types.ts +151 -0
  393. package/src/forge/intent/index.ts +490 -0
  394. package/src/forge/intent/types.ts +73 -0
  395. package/src/forge/make/fields.ts +146 -0
  396. package/src/forge/make/index.ts +1101 -0
  397. package/src/forge/make/naming.ts +42 -0
  398. package/src/forge/make/templates.ts +525 -0
  399. package/src/forge/make/types.ts +151 -0
  400. package/src/forge/platform/module.ts +20 -0
  401. package/src/forge/policy.ts +1 -0
  402. package/src/forge/react/index.ts +418 -0
  403. package/src/forge/refactor/index.ts +1936 -0
  404. package/src/forge/refactor/text-utils.ts +34 -0
  405. package/src/forge/refactor/types.ts +191 -0
  406. package/src/forge/refactor/workspace-fs.ts +171 -0
  407. package/src/forge/repair/index.ts +656 -0
  408. package/src/forge/repair/rules/index.ts +476 -0
  409. package/src/forge/repair/types.ts +175 -0
  410. package/src/forge/review/index.ts +992 -0
  411. package/src/forge/review/types.ts +196 -0
  412. package/src/forge/runtime/ai/check.ts +86 -0
  413. package/src/forge/runtime/ai/context.ts +394 -0
  414. package/src/forge/runtime/ai/cost-estimator.ts +41 -0
  415. package/src/forge/runtime/ai/mock.ts +49 -0
  416. package/src/forge/runtime/ai/providers.ts +78 -0
  417. package/src/forge/runtime/ai/state.ts +17 -0
  418. package/src/forge/runtime/ai/types.ts +67 -0
  419. package/src/forge/runtime/auth/authenticate.ts +58 -0
  420. package/src/forge/runtime/auth/claims.ts +119 -0
  421. package/src/forge/runtime/auth/config.ts +148 -0
  422. package/src/forge/runtime/auth/errors.ts +45 -0
  423. package/src/forge/runtime/auth/evaluate.ts +126 -0
  424. package/src/forge/runtime/auth/resolve.ts +74 -0
  425. package/src/forge/runtime/auth/types.ts +87 -0
  426. package/src/forge/runtime/auth/verifier.ts +138 -0
  427. package/src/forge/runtime/context/create-context.ts +204 -0
  428. package/src/forge/runtime/context/create-query-context.ts +34 -0
  429. package/src/forge/runtime/db/adapter.ts +31 -0
  430. package/src/forge/runtime/db/factory.ts +83 -0
  431. package/src/forge/runtime/db/generated-client.ts +294 -0
  432. package/src/forge/runtime/db/memory-adapter.ts +706 -0
  433. package/src/forge/runtime/db/migrate.ts +132 -0
  434. package/src/forge/runtime/db/outbox.ts +54 -0
  435. package/src/forge/runtime/db/pglite-adapter.ts +51 -0
  436. package/src/forge/runtime/db/postgres-adapter.ts +112 -0
  437. package/src/forge/runtime/db/read-only-client.ts +97 -0
  438. package/src/forge/runtime/db/session-context.ts +62 -0
  439. package/src/forge/runtime/executor.ts +446 -0
  440. package/src/forge/runtime/live/dependency-tracker.ts +57 -0
  441. package/src/forge/runtime/live/invalidation-log.ts +189 -0
  442. package/src/forge/runtime/live/live-query-runner.ts +267 -0
  443. package/src/forge/runtime/live/registry.ts +28 -0
  444. package/src/forge/runtime/live/sse.ts +75 -0
  445. package/src/forge/runtime/live/subscription-manager.ts +443 -0
  446. package/src/forge/runtime/live/types.ts +143 -0
  447. package/src/forge/runtime/outbox/claim.ts +153 -0
  448. package/src/forge/runtime/outbox/process.ts +298 -0
  449. package/src/forge/runtime/outbox/retry.ts +8 -0
  450. package/src/forge/runtime/outbox/subscriptions.ts +33 -0
  451. package/src/forge/runtime/outbox/types.ts +69 -0
  452. package/src/forge/runtime/policy/check.ts +157 -0
  453. package/src/forge/runtime/policy/load.ts +55 -0
  454. package/src/forge/runtime/query/registry.ts +19 -0
  455. package/src/forge/runtime/query/run-query.ts +347 -0
  456. package/src/forge/runtime/release/runtime.ts +322 -0
  457. package/src/forge/runtime/release/symbolicate.ts +175 -0
  458. package/src/forge/runtime/runner/command-transaction.ts +193 -0
  459. package/src/forge/runtime/runner/run-entry.ts +226 -0
  460. package/src/forge/runtime/secrets/check.ts +78 -0
  461. package/src/forge/runtime/secrets/create-context.ts +138 -0
  462. package/src/forge/runtime/secrets/env-loader.ts +94 -0
  463. package/src/forge/runtime/secrets/runtime-bundle.ts +47 -0
  464. package/src/forge/runtime/secrets/types.ts +31 -0
  465. package/src/forge/runtime/telemetry/buffer.ts +87 -0
  466. package/src/forge/runtime/telemetry/context.ts +192 -0
  467. package/src/forge/runtime/telemetry/correlation.ts +13 -0
  468. package/src/forge/runtime/telemetry/flush.ts +190 -0
  469. package/src/forge/runtime/telemetry/process.ts +20 -0
  470. package/src/forge/runtime/telemetry/scrubber.ts +115 -0
  471. package/src/forge/runtime/telemetry/sinks/local-jsonl.ts +39 -0
  472. package/src/forge/runtime/telemetry/sinks/posthog.ts +64 -0
  473. package/src/forge/runtime/telemetry/sinks/sentry.ts +60 -0
  474. package/src/forge/runtime/telemetry/spans.ts +58 -0
  475. package/src/forge/runtime/telemetry/types.ts +64 -0
  476. package/src/forge/runtime/workflows/cancel.ts +26 -0
  477. package/src/forge/runtime/workflows/create-run.ts +98 -0
  478. package/src/forge/runtime/workflows/process-run.ts +182 -0
  479. package/src/forge/runtime/workflows/process-step.ts +190 -0
  480. package/src/forge/runtime/workflows/process.ts +260 -0
  481. package/src/forge/runtime/workflows/registry.ts +51 -0
  482. package/src/forge/runtime/workflows/resolve-step.ts +46 -0
  483. package/src/forge/runtime/workflows/retry-run.ts +44 -0
  484. package/src/forge/runtime/workflows/retry.ts +8 -0
  485. package/src/forge/runtime/workflows/sanitize.ts +19 -0
  486. package/src/forge/runtime/workflows/start-from-outbox.ts +71 -0
  487. package/src/forge/runtime/workflows/types.ts +77 -0
  488. package/src/forge/server.ts +96 -0
  489. package/src/forge/ui/index.ts +770 -0
  490. package/src/forge/ui/types.ts +191 -0
  491. package/templates/b2b-support-web/.env.example +22 -0
  492. package/templates/b2b-support-web/.vscode/settings.json +14 -0
  493. package/templates/b2b-support-web/AGENTS.md +108 -0
  494. package/templates/b2b-support-web/README.md +48 -0
  495. package/templates/b2b-support-web/forge.config.ts +3 -0
  496. package/templates/b2b-support-web/package.json +34 -0
  497. package/templates/b2b-support-web/src/actions/captureTicketCreated.ts +14 -0
  498. package/templates/b2b-support-web/src/commands/closeTicket.ts +20 -0
  499. package/templates/b2b-support-web/src/commands/createTicket.ts +47 -0
  500. package/templates/b2b-support-web/src/commands/manageBilling.ts +9 -0
  501. package/templates/b2b-support-web/src/forge/schema.ts +35 -0
  502. package/templates/b2b-support-web/src/policies.ts +9 -0
  503. package/templates/b2b-support-web/src/queries/getTicket.ts +6 -0
  504. package/templates/b2b-support-web/src/queries/listTickets.ts +6 -0
  505. package/templates/b2b-support-web/src/queries/liveTickets.ts +9 -0
  506. package/templates/b2b-support-web/src/workflows/triageTicketWorkflow.ts +64 -0
  507. package/templates/b2b-support-web/tsconfig.json +14 -0
  508. package/templates/b2b-support-web/web/app/globals.css +77 -0
  509. package/templates/b2b-support-web/web/app/layout.tsx +13 -0
  510. package/templates/b2b-support-web/web/app/page.tsx +13 -0
  511. package/templates/b2b-support-web/web/app/providers.tsx +21 -0
  512. package/templates/b2b-support-web/web/app/tickets/page.tsx +21 -0
  513. package/templates/b2b-support-web/web/components/CreateTicketForm.tsx +43 -0
  514. package/templates/b2b-support-web/web/components/PolicyDeniedDemo.tsx +31 -0
  515. package/templates/b2b-support-web/web/components/TicketList.tsx +52 -0
  516. package/templates/b2b-support-web/web/components/TraceDetails.tsx +18 -0
  517. package/templates/b2b-support-web/web/components/TriageStatus.tsx +13 -0
  518. package/templates/b2b-support-web/web/lib/forge.ts +13 -0
  519. package/templates/b2b-support-web/web/next-env.d.ts +5 -0
  520. package/templates/b2b-support-web/web/next.config.ts +8 -0
  521. package/templates/b2b-support-web/web/package.json +21 -0
  522. package/templates/b2b-support-web/web/tsconfig.json +30 -0
  523. package/templates/minimal-web/.vscode/settings.json +14 -0
  524. package/templates/minimal-web/README.md +21 -0
  525. package/templates/minimal-web/forge.config.ts +3 -0
  526. package/templates/minimal-web/package.json +32 -0
  527. package/templates/minimal-web/src/actions/logNoteCreated.ts +11 -0
  528. package/templates/minimal-web/src/commands/createNote.ts +26 -0
  529. package/templates/minimal-web/src/forge/schema.ts +12 -0
  530. package/templates/minimal-web/src/policies.ts +6 -0
  531. package/templates/minimal-web/src/queries/listNotes.ts +8 -0
  532. package/templates/minimal-web/src/queries/liveNotes.ts +8 -0
  533. package/templates/minimal-web/tsconfig.json +15 -0
  534. package/templates/minimal-web/web/index.html +12 -0
  535. package/templates/minimal-web/web/package.json +21 -0
  536. package/templates/minimal-web/web/src/App.tsx +89 -0
  537. package/templates/minimal-web/web/src/lib/forge.ts +13 -0
  538. package/templates/minimal-web/web/src/main.tsx +13 -0
  539. package/templates/minimal-web/web/src/styles.css +156 -0
  540. package/templates/minimal-web/web/tsconfig.json +18 -0
@@ -0,0 +1,62 @@
1
+ import ts from "typescript";
2
+ import type { JsDoc } from "../types/package-graph.ts";
3
+
4
+ function tagText(tag: ts.JSDocTag): string {
5
+ if (typeof tag.comment === "string") {
6
+ return tag.comment.trim();
7
+ }
8
+ if (tag.comment) {
9
+ return tag.comment
10
+ .map((part) => part.text)
11
+ .join("")
12
+ .trim();
13
+ }
14
+ return "";
15
+ }
16
+
17
+ export function extractJsDoc(
18
+ symbol: ts.Symbol,
19
+ checker: ts.TypeChecker,
20
+ ): JsDoc | null {
21
+ const parts = symbol.getDocumentationComment(checker);
22
+ const summary = ts.displayPartsToString(parts).trim();
23
+
24
+ const tags: { tag: string; text: string }[] = [];
25
+ for (const decl of symbol.declarations ?? []) {
26
+ for (const tag of ts.getJSDocTags(decl)) {
27
+ tags.push({
28
+ tag: tag.tagName.text,
29
+ text: tagText(tag),
30
+ });
31
+ }
32
+ }
33
+
34
+ if (summary.length === 0 && tags.length === 0) {
35
+ return null;
36
+ }
37
+
38
+ tags.sort((a, b) => {
39
+ const tagCmp = a.tag.localeCompare(b.tag);
40
+ if (tagCmp !== 0) return tagCmp;
41
+ return a.text.localeCompare(b.text);
42
+ });
43
+
44
+ return { summary, tags };
45
+ }
46
+
47
+ export function extractExamples(jsdoc: JsDoc | null): string[] {
48
+ if (jsdoc == null) {
49
+ return [];
50
+ }
51
+
52
+ const examples = jsdoc.tags
53
+ .filter((tag) => tag.tag.toLowerCase() === "example")
54
+ .map((tag) => normalizeExample(tag.text))
55
+ .filter((text) => text.length > 0);
56
+
57
+ return [...new Set(examples)].sort((a, b) => a.localeCompare(b));
58
+ }
59
+
60
+ function normalizeExample(text: string): string {
61
+ return text.replace(/\r\n/g, "\n").trim();
62
+ }
@@ -0,0 +1,21 @@
1
+ import { readFileSync } from "node:fs";
2
+
3
+ export interface ReadFileTracker {
4
+ recordRead(path: string): void;
5
+ }
6
+
7
+ let activeTracker: ReadFileTracker | undefined;
8
+
9
+ export function setReadFileTracker(tracker: ReadFileTracker | undefined): void {
10
+ activeTracker = tracker;
11
+ }
12
+
13
+ export function readTextFile(path: string): string {
14
+ activeTracker?.recordRead(path);
15
+ return readFileSync(path, "utf8");
16
+ }
17
+
18
+ export function readBinaryFile(path: string): Uint8Array {
19
+ activeTracker?.recordRead(path);
20
+ return readFileSync(path);
21
+ }
@@ -0,0 +1,127 @@
1
+ import { join } from "node:path";
2
+ import ts from "typescript";
3
+ import type { ResolutionMode } from "../types/runtime.ts";
4
+ import { readTextFile } from "./read-file.ts";
5
+
6
+ export interface ResolvedEntrypoint {
7
+ dtsPath: string | null;
8
+ conditions: string[];
9
+ }
10
+
11
+ export function createResolutionCompilerOptions(
12
+ mode: ResolutionMode,
13
+ ): ts.CompilerOptions {
14
+ return {
15
+ moduleResolution:
16
+ mode === "nodenext"
17
+ ? ts.ModuleResolutionKind.NodeNext
18
+ : ts.ModuleResolutionKind.Bundler,
19
+ resolvePackageJsonExports: true,
20
+ resolvePackageJsonImports: true,
21
+ customConditions: ["types"],
22
+ noEmit: true,
23
+ types: [],
24
+ skipLibCheck: true,
25
+ };
26
+ }
27
+
28
+ export function moduleSpecifierForSubpath(
29
+ packageName: string,
30
+ subpath: string,
31
+ ): string {
32
+ if (subpath === ".") {
33
+ return packageName;
34
+ }
35
+ const trimmed = subpath.startsWith("./") ? subpath.slice(2) : subpath;
36
+ return `${packageName}/${trimmed}`;
37
+ }
38
+
39
+ export function resolveEntrypointTypes(
40
+ installPath: string,
41
+ packageName: string,
42
+ subpath: string,
43
+ mode: ResolutionMode,
44
+ ): ResolvedEntrypoint {
45
+ const containingFile = join(installPath, "package.json");
46
+ const specifier = moduleSpecifierForSubpath(packageName, subpath);
47
+ const options = createResolutionCompilerOptions(mode);
48
+
49
+ const result = ts.resolveModuleName(
50
+ specifier,
51
+ containingFile,
52
+ options,
53
+ ts.sys,
54
+ );
55
+
56
+ const resolved = result.resolvedModule;
57
+ if (resolved == null) {
58
+ return { dtsPath: null, conditions: [] };
59
+ }
60
+
61
+ const dtsPath = pickTypesPath(resolved);
62
+ const conditions = extractConditions(resolved);
63
+
64
+ return { dtsPath, conditions };
65
+ }
66
+
67
+ function pickTypesPath(resolved: ts.ResolvedModuleFull): string | null {
68
+ if (resolved.extension === ts.Extension.Dts) {
69
+ return resolved.resolvedFileName;
70
+ }
71
+ if (resolved.extension === ts.Extension.Ts) {
72
+ return resolved.resolvedFileName;
73
+ }
74
+ if (resolved.extension === ts.Extension.Tsx) {
75
+ return resolved.resolvedFileName;
76
+ }
77
+ return resolved.resolvedFileName.endsWith(".d.ts")
78
+ ? resolved.resolvedFileName
79
+ : null;
80
+ }
81
+
82
+ function extractConditions(resolved: ts.ResolvedModuleFull): string[] {
83
+ const conditions = (resolved as { packageId?: { conditions?: string[] } })
84
+ .packageId?.conditions;
85
+ if (Array.isArray(conditions) && conditions.length > 0) {
86
+ return [...conditions];
87
+ }
88
+ return [];
89
+ }
90
+
91
+ export function typesPackageName(packageName: string): string {
92
+ if (packageName.startsWith("@")) {
93
+ return `@types/${packageName.slice(1).replace("/", "__")}`;
94
+ }
95
+ return `@types/${packageName}`;
96
+ }
97
+
98
+ export function resolveTypesPackage(
99
+ typesPackageName: string,
100
+ installPath: string,
101
+ mode: ResolutionMode,
102
+ ): string | null {
103
+ const typesInstallPath = join(installPath, "..", typesPackageName);
104
+ const packageJsonPath = join(typesInstallPath, "package.json");
105
+
106
+ try {
107
+ readTextFile(packageJsonPath);
108
+ } catch {
109
+ return null;
110
+ }
111
+
112
+ const directIndex = join(typesInstallPath, "index.d.ts");
113
+ try {
114
+ readTextFile(directIndex);
115
+ return directIndex;
116
+ } catch {
117
+ // fall through to module resolver
118
+ }
119
+
120
+ const resolved = resolveEntrypointTypes(
121
+ typesInstallPath,
122
+ typesPackageName,
123
+ ".",
124
+ mode,
125
+ );
126
+ return resolved.dtsPath;
127
+ }
@@ -0,0 +1,237 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { nodeFileSystem } from "../fs/index.ts";
5
+ import type { PackageManager } from "../types/runtime.ts";
6
+ import type { PmAddOptions, PmAddResult } from "../types/cli.ts";
7
+ import { buildAddCommand } from "./commands.ts";
8
+ import {
9
+ detectPackageManager,
10
+ getLockfileCandidates,
11
+ getLockfileForPm,
12
+ } from "./detect.ts";
13
+ import {
14
+ defaultCommandExecutor,
15
+ PackageManagerCommandError,
16
+ type CommandExecutor,
17
+ } from "./executor.ts";
18
+ import { parsePackageName } from "./parse-spec.ts";
19
+ import { readInstalledVersion } from "./version.ts";
20
+
21
+ export interface PackageManagerAdapter {
22
+ readonly name: PackageManager;
23
+ readonly lockfile: string;
24
+ add(spec: string, opts: PmAddOptions): Promise<PmAddResult>;
25
+ dryRunAdd(spec: string, opts: PmAddOptions): Promise<PmAddResult>;
26
+ /** Install into a temp dir; caller owns cleanup unless using dryRunAdd. */
27
+ dryRunAddWithPath(spec: string, opts: PmAddOptions): Promise<DryRunAddResult>;
28
+ detectResolvedVersion(spec: string, cwd: string): Promise<string>;
29
+ }
30
+
31
+ export interface DryRunAddResult extends PmAddResult {
32
+ /** Absolute path to the temp install directory (for downstream analysis). */
33
+ installPath: string;
34
+ }
35
+
36
+ export interface CreatePackageManagerAdapterOptions {
37
+ executor?: CommandExecutor;
38
+ /** When true, retain the temp directory after dryRunAdd (for debugging). */
39
+ retainDryRunDir?: boolean;
40
+ }
41
+
42
+ function hashFile(path: string): string | null {
43
+ if (!nodeFileSystem.exists(path)) {
44
+ return null;
45
+ }
46
+ const content = readFileSync(path);
47
+ return createHash("sha256").update(content).digest("hex");
48
+ }
49
+
50
+ function hashLockfiles(cwd: string, pm: PackageManager): string | null {
51
+ const hashes: string[] = [];
52
+ for (const file of getLockfileCandidates(pm)) {
53
+ const h = hashFile(join(cwd, file));
54
+ if (h !== null) {
55
+ hashes.push(`${file}:${h}`);
56
+ }
57
+ }
58
+ return hashes.length > 0 ? hashes.join("|") : null;
59
+ }
60
+
61
+ function lockfileChanged(
62
+ before: string | null,
63
+ after: string | null,
64
+ pm: PackageManager,
65
+ cwd: string,
66
+ ): boolean {
67
+ if (before !== after) {
68
+ return true;
69
+ }
70
+ // Lockfile may be created on first install.
71
+ if (before === null) {
72
+ return getLockfileCandidates(pm).some((f) =>
73
+ nodeFileSystem.exists(join(cwd, f)),
74
+ );
75
+ }
76
+ return false;
77
+ }
78
+
79
+ async function runInstall(
80
+ pm: PackageManager,
81
+ spec: string,
82
+ opts: PmAddOptions,
83
+ executor: CommandExecutor,
84
+ ): Promise<PmAddResult> {
85
+ const ignoreScripts = opts.ignoreScripts ?? true;
86
+ const argv = buildAddCommand(pm, spec, { ignoreScripts });
87
+ const lockBefore = hashLockfiles(opts.cwd, pm);
88
+
89
+ const result = await executor.run(argv, { cwd: opts.cwd });
90
+ if (result.exitCode !== 0) {
91
+ throw new PackageManagerCommandError(
92
+ `Package manager ${pm} failed to add ${spec}: ${result.stderr || result.stdout}`,
93
+ argv,
94
+ result,
95
+ );
96
+ }
97
+
98
+ const packageName = parsePackageName(spec);
99
+ const resolvedVersion = readInstalledVersion(packageName, opts.cwd);
100
+ if (!resolvedVersion) {
101
+ throw new Error(
102
+ `Could not detect installed version for ${packageName} in ${opts.cwd}`,
103
+ );
104
+ }
105
+
106
+ const lockAfter = hashLockfiles(opts.cwd, pm);
107
+
108
+ return {
109
+ resolvedVersion,
110
+ lockfileChanged: lockfileChanged(lockBefore, lockAfter, pm, opts.cwd),
111
+ };
112
+ }
113
+
114
+ class PackageManagerAdapterImpl implements PackageManagerAdapter {
115
+ readonly name: PackageManager;
116
+ readonly lockfile: string;
117
+ private readonly executor: CommandExecutor;
118
+ private readonly retainDryRunDir: boolean;
119
+
120
+ constructor(
121
+ name: PackageManager,
122
+ options: CreatePackageManagerAdapterOptions = {},
123
+ ) {
124
+ this.name = name;
125
+ this.lockfile = getLockfileForPm(name);
126
+ this.executor = options.executor ?? defaultCommandExecutor;
127
+ this.retainDryRunDir = options.retainDryRunDir ?? false;
128
+ }
129
+
130
+ async add(spec: string, opts: PmAddOptions): Promise<PmAddResult> {
131
+ return runInstall(this.name, spec, opts, this.executor);
132
+ }
133
+
134
+ async dryRunAdd(spec: string, opts: PmAddOptions): Promise<PmAddResult> {
135
+ const result = await this.dryRunAddWithPath(spec, opts);
136
+ if (!this.retainDryRunDir) {
137
+ try {
138
+ nodeFileSystem.remove(result.installPath);
139
+ } catch {
140
+ // best-effort cleanup
141
+ }
142
+ }
143
+ return {
144
+ resolvedVersion: result.resolvedVersion,
145
+ integrity: result.integrity,
146
+ lockfileChanged: false,
147
+ };
148
+ }
149
+
150
+ /** Internal: dry-run install returning the temp directory path. */
151
+ async dryRunAddWithPath(
152
+ spec: string,
153
+ opts: PmAddOptions,
154
+ ): Promise<DryRunAddResult> {
155
+ const cacheBase = join(opts.cwd, ".forge", "cache", "dry-run");
156
+ nodeFileSystem.mkdirp(cacheBase);
157
+ const tempDir = nodeFileSystem.makeTempDir(join(cacheBase, "add-"));
158
+
159
+ const minimalPkg = {
160
+ name: "forge-dry-run",
161
+ private: true,
162
+ version: "0.0.0",
163
+ };
164
+ writeFileSync(
165
+ join(tempDir, "package.json"),
166
+ `${JSON.stringify(minimalPkg, null, 2)}\n`,
167
+ "utf8",
168
+ );
169
+
170
+ const installResult = await runInstall(
171
+ this.name,
172
+ spec,
173
+ {
174
+ cwd: tempDir,
175
+ ignoreScripts: opts.ignoreScripts ?? true,
176
+ },
177
+ this.executor,
178
+ );
179
+
180
+ return {
181
+ ...installResult,
182
+ lockfileChanged: false,
183
+ installPath: tempDir,
184
+ };
185
+ }
186
+
187
+ async detectResolvedVersion(spec: string, cwd: string): Promise<string> {
188
+ const version = readInstalledVersion(spec, cwd);
189
+ if (!version) {
190
+ throw new Error(
191
+ `Package ${parsePackageName(spec)} is not installed in ${cwd}`,
192
+ );
193
+ }
194
+ return version;
195
+ }
196
+ }
197
+
198
+ export function createPackageManagerAdapter(
199
+ pm: PackageManager,
200
+ options?: CreatePackageManagerAdapterOptions,
201
+ ): PackageManagerAdapter {
202
+ return new PackageManagerAdapterImpl(pm, options);
203
+ }
204
+
205
+ export function detectAndCreatePackageManagerAdapter(
206
+ workspaceRoot: string,
207
+ options?: CreatePackageManagerAdapterOptions,
208
+ ): PackageManagerAdapter {
209
+ const pm = detectPackageManager(workspaceRoot);
210
+ return createPackageManagerAdapter(pm, options);
211
+ }
212
+
213
+ /** Fallback when dry-run install is unavailable: recipe-known plan placeholder. */
214
+ export function dryRunRecipeFallbackMessage(alias: string): string {
215
+ return (
216
+ `Dry-run for "${alias}": .d.ts analysis requires a real install. ` +
217
+ `Use dryRunAdd to install into a temp directory, or run forge add without --dry-run.`
218
+ );
219
+ }
220
+
221
+ export {
222
+ detectPackageManager,
223
+ detectPackageManagerFromLockfiles,
224
+ getLockfileForPm,
225
+ getLockfileCandidates,
226
+ parsePackageManagerField,
227
+ LOCKFILE_PM_MAP,
228
+ } from "./detect.ts";
229
+ export { buildAddCommand } from "./commands.ts";
230
+ export { parsePackageName } from "./parse-spec.ts";
231
+ export { readInstalledVersion } from "./version.ts";
232
+ export {
233
+ defaultCommandExecutor,
234
+ PackageManagerCommandError,
235
+ type CommandExecutor,
236
+ type CommandRunResult,
237
+ } from "./executor.ts";
@@ -0,0 +1,92 @@
1
+ import { homedir } from "node:os";
2
+ import { nodeFileSystem } from "../fs/index.ts";
3
+ import { basename, join, win32 } from "node:path";
4
+
5
+ export interface BunExecutableResolutionOptions {
6
+ env?: Record<string, string | undefined>;
7
+ execPath?: string;
8
+ exists?: (path: string) => boolean;
9
+ homeDir?: string;
10
+ platform?: NodeJS.Platform;
11
+ which?: (command: string) => string | null | undefined;
12
+ }
13
+
14
+ function isBunExecutablePath(path: string, platform: NodeJS.Platform): boolean {
15
+ const file = (platform === "win32" ? win32.basename(path) : basename(path)).toLowerCase();
16
+ return platform === "win32" ? file === "bun.exe" : file === "bun";
17
+ }
18
+
19
+ function normalizeWindowsBunCandidate(
20
+ candidate: string | null | undefined,
21
+ exists: (path: string) => boolean,
22
+ ): string | null {
23
+ if (!candidate) {
24
+ return null;
25
+ }
26
+
27
+ const normalizedForMatch = candidate.replace(/\//g, "\\").toLowerCase();
28
+ if (normalizedForMatch.includes("\\kiro-cli\\")) {
29
+ return null;
30
+ }
31
+
32
+ if (candidate.toLowerCase().endsWith(".exe")) {
33
+ return exists(candidate) ? candidate : null;
34
+ }
35
+
36
+ const exeCandidate = `${candidate}.exe`;
37
+ return exists(exeCandidate) ? exeCandidate : null;
38
+ }
39
+
40
+ function unresolvedWindowsBunError(): Error {
41
+ return new Error(
42
+ "Unable to resolve a safe Bun executable on Windows. Install Bun at ~/.bun/bin/bun.exe or set FORGE_BUN to an existing bun.exe. Refusing to spawn bare bun.exe because Windows may open an app picker.",
43
+ );
44
+ }
45
+
46
+ /** Resolve the Bun executable for spawning child processes (Windows-safe). */
47
+ export function resolveBunExecutable(options: BunExecutableResolutionOptions = {}): string {
48
+ const platform = options.platform ?? process.platform;
49
+ const exists = options.exists ?? nodeFileSystem.exists;
50
+ const execPath = options.execPath ?? process.execPath;
51
+ const configured = options.env?.FORGE_BUN ?? process.env.FORGE_BUN;
52
+
53
+ if (configured) {
54
+ if (platform === "win32") {
55
+ const normalized = normalizeWindowsBunCandidate(configured, exists);
56
+ if (normalized) {
57
+ return normalized;
58
+ }
59
+ } else if (exists(configured)) {
60
+ return configured;
61
+ }
62
+ throw new Error(`FORGE_BUN does not point to a safe Bun executable: ${configured}`);
63
+ }
64
+
65
+ if (isBunExecutablePath(execPath, platform) && exists(execPath)) {
66
+ return execPath;
67
+ }
68
+
69
+ const fromPath =
70
+ options.which?.("bun") ?? (typeof Bun !== "undefined" ? Bun.which("bun") : undefined);
71
+
72
+ if (platform === "win32") {
73
+ const normalized = normalizeWindowsBunCandidate(fromPath, exists);
74
+ if (normalized) {
75
+ return normalized;
76
+ }
77
+
78
+ const joinPath = platform === "win32" ? win32.join : join;
79
+ const homeBun = joinPath(options.homeDir ?? homedir(), ".bun", "bin", "bun.exe");
80
+ if (exists(homeBun)) {
81
+ return homeBun;
82
+ }
83
+
84
+ throw unresolvedWindowsBunError();
85
+ }
86
+
87
+ if (fromPath) {
88
+ return fromPath;
89
+ }
90
+
91
+ return "bun";
92
+ }
@@ -0,0 +1,47 @@
1
+ import type { PackageManager } from "../types/runtime.ts";
2
+
3
+ export interface BuildAddCommandOptions {
4
+ ignoreScripts: boolean;
5
+ }
6
+
7
+ /**
8
+ * Build argv for adding a dependency with lifecycle scripts disabled by default.
9
+ */
10
+ export function buildAddCommand(
11
+ pm: PackageManager,
12
+ spec: string,
13
+ options: BuildAddCommandOptions,
14
+ ): string[] {
15
+ const ignoreScripts = options.ignoreScripts;
16
+
17
+ switch (pm) {
18
+ case "bun": {
19
+ const args = ["bun", "add", spec];
20
+ if (ignoreScripts) {
21
+ args.push("--ignore-scripts");
22
+ }
23
+ return args;
24
+ }
25
+ case "npm": {
26
+ const args = ["npm", "install", spec, "--save", "--no-fund", "--no-audit"];
27
+ if (ignoreScripts) {
28
+ args.push("--ignore-scripts");
29
+ }
30
+ return args;
31
+ }
32
+ case "pnpm": {
33
+ const args = ["pnpm", "add", spec];
34
+ if (ignoreScripts) {
35
+ args.push("--ignore-scripts");
36
+ }
37
+ return args;
38
+ }
39
+ case "yarn": {
40
+ const args = ["yarn", "add", spec];
41
+ if (ignoreScripts) {
42
+ args.push("--ignore-scripts");
43
+ }
44
+ return args;
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,79 @@
1
+ import { join } from "node:path";
2
+ import { nodeFileSystem } from "../fs/index.ts";
3
+ import type { PackageManager } from "../types/runtime.ts";
4
+
5
+ /** Lockfiles checked in priority order when `packageManager` is absent. */
6
+ export const LOCKFILE_PM_MAP: readonly { file: string; pm: PackageManager }[] = [
7
+ { file: "bun.lockb", pm: "bun" },
8
+ { file: "bun.lock", pm: "bun" },
9
+ { file: "pnpm-lock.yaml", pm: "pnpm" },
10
+ { file: "yarn.lock", pm: "yarn" },
11
+ { file: "package-lock.json", pm: "npm" },
12
+ ] as const;
13
+
14
+ const PM_FROM_FIELD = /^(bun|npm|pnpm|yarn)(?:@|$)/;
15
+
16
+ export function parsePackageManagerField(value: string): PackageManager | null {
17
+ const match = value.trim().match(PM_FROM_FIELD);
18
+ return match ? (match[1] as PackageManager) : null;
19
+ }
20
+
21
+ export function getLockfileForPm(pm: PackageManager): string {
22
+ switch (pm) {
23
+ case "bun":
24
+ return "bun.lock";
25
+ case "npm":
26
+ return "package-lock.json";
27
+ case "pnpm":
28
+ return "pnpm-lock.yaml";
29
+ case "yarn":
30
+ return "yarn.lock";
31
+ }
32
+ }
33
+
34
+ /** All lockfile names that may exist for a given package manager. */
35
+ export function getLockfileCandidates(pm: PackageManager): readonly string[] {
36
+ if (pm === "bun") {
37
+ return ["bun.lock", "bun.lockb"];
38
+ }
39
+ return [getLockfileForPm(pm)];
40
+ }
41
+
42
+ export function detectPackageManagerFromLockfiles(
43
+ workspaceRoot: string,
44
+ ): PackageManager | null {
45
+ for (const { file, pm } of LOCKFILE_PM_MAP) {
46
+ if (nodeFileSystem.exists(join(workspaceRoot, file))) {
47
+ return pm;
48
+ }
49
+ }
50
+ return null;
51
+ }
52
+
53
+ /**
54
+ * Detect the active package manager via `package.json#packageManager` or lockfile presence.
55
+ * Defaults to `npm` when the project has not declared a package manager.
56
+ * Bun remains first-class when selected via `packageManager`, `bun.lock`, or
57
+ * `bun.lockb`; the neutral fallback avoids surprising Windows app-picker
58
+ * launches from ambiguous `bun` associations.
59
+ */
60
+ export function detectPackageManager(workspaceRoot: string): PackageManager {
61
+ const pkgPath = join(workspaceRoot, "package.json");
62
+ if (nodeFileSystem.exists(pkgPath)) {
63
+ try {
64
+ const pkg = JSON.parse((nodeFileSystem.readText(pkgPath) ?? "")) as {
65
+ packageManager?: string;
66
+ };
67
+ if (pkg.packageManager) {
68
+ const fromField = parsePackageManagerField(pkg.packageManager);
69
+ if (fromField) {
70
+ return fromField;
71
+ }
72
+ }
73
+ } catch {
74
+ // fall through to lockfile detection
75
+ }
76
+ }
77
+
78
+ return detectPackageManagerFromLockfiles(workspaceRoot) ?? "npm";
79
+ }