forgeos 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (406) hide show
  1. package/.npmignore +4 -0
  2. package/AGENTS.md +168 -81
  3. package/CHANGELOG.md +211 -0
  4. package/README.md +88 -14
  5. package/adapters/go/README.md +23 -0
  6. package/adapters/go/go.mod +3 -0
  7. package/adapters/go/http.go +149 -0
  8. package/adapters/go/registry.go +234 -0
  9. package/adapters/go/types.go +136 -0
  10. package/adapters/java/README.md +68 -0
  11. package/adapters/java/pom.xml +34 -0
  12. package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
  13. package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
  14. package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
  15. package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
  16. package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
  17. package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
  18. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
  19. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
  20. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
  21. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
  22. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
  23. package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
  24. package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
  25. package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
  26. package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
  27. package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
  28. package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
  29. package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
  30. package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
  31. package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
  32. package/adapters/java/target/classes/dev/forgeos/adapter/Auth.class +0 -0
  33. package/adapters/java/target/classes/dev/forgeos/adapter/Diagnostic.class +0 -0
  34. package/adapters/java/target/classes/dev/forgeos/adapter/Entry.class +0 -0
  35. package/adapters/java/target/classes/dev/forgeos/adapter/EntryKind.class +0 -0
  36. package/adapters/java/target/classes/dev/forgeos/adapter/ErrorInfo.class +0 -0
  37. package/adapters/java/target/classes/dev/forgeos/adapter/Forge.class +0 -0
  38. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeCall.class +0 -0
  39. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeContext.class +0 -0
  40. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHandler.class +0 -0
  41. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHttpHandler.class +0 -0
  42. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$EntryOption.class +0 -0
  43. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegisteredEntry.class +0 -0
  44. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegistryOption.class +0 -0
  45. package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry.class +0 -0
  46. package/adapters/java/target/classes/dev/forgeos/adapter/Json.class +0 -0
  47. package/adapters/java/target/classes/dev/forgeos/adapter/Manifest.class +0 -0
  48. package/adapters/java/target/classes/dev/forgeos/adapter/RequestEnvelope.class +0 -0
  49. package/adapters/java/target/classes/dev/forgeos/adapter/ResponseEnvelope.class +0 -0
  50. package/adapters/java/target/classes/dev/forgeos/adapter/Risk.class +0 -0
  51. package/adapters/java/target/classes/dev/forgeos/adapter/Schemas.class +0 -0
  52. package/adapters/java/target/classes/dev/forgeos/adapter/Service.class +0 -0
  53. package/adapters/java/target/classes/dev/forgeos/adapter/TransactionMode.class +0 -0
  54. package/adapters/java/target/classes/dev/forgeos/adapter/TypedForgeHandler.class +0 -0
  55. package/adapters/java/target/forge-java-adapter-0.1.0-alpha.11.jar +0 -0
  56. package/adapters/java/target/maven-archiver/pom.properties +3 -0
  57. package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +23 -0
  58. package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +20 -0
  59. package/adapters/java-spring-boot-starter/README.md +32 -0
  60. package/adapters/java-spring-boot-starter/pom.xml +36 -0
  61. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
  62. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
  63. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
  64. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
  65. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
  66. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
  67. package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  68. package/adapters/java-spring-boot-starter/target/classes/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  69. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeCommand.class +0 -0
  70. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeExternalService.class +0 -0
  71. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeQuery.class +0 -0
  72. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.class +0 -0
  73. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.class +0 -0
  74. package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringRuntime.class +0 -0
  75. package/adapters/java-spring-boot-starter/target/forge-java-spring-boot-starter-0.1.0-alpha.11.jar +0 -0
  76. package/adapters/java-spring-boot-starter/target/maven-archiver/pom.properties +3 -0
  77. package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +6 -0
  78. package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +6 -0
  79. package/bin/forge.mjs +18 -0
  80. package/docs/changelog.md +242 -0
  81. package/docs/forge-protocol.md +189 -0
  82. package/examples/go-billing/go.mod +7 -0
  83. package/examples/go-billing/main.go +120 -0
  84. package/examples/java-billing/pom.xml +52 -0
  85. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
  86. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
  87. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
  88. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/CreateInvoiceInput.class +0 -0
  89. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Invoice.class +0 -0
  90. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$EmptyInput.class +0 -0
  91. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$Options.class +0 -0
  92. package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main.class +0 -0
  93. package/examples/java-billing/target/java-billing-0.1.0-alpha.11-all.jar +0 -0
  94. package/examples/java-billing/target/java-billing-0.1.0-alpha.11.jar +0 -0
  95. package/examples/java-billing/target/maven-archiver/pom.properties +3 -0
  96. package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +5 -0
  97. package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +3 -0
  98. package/package.json +29 -7
  99. package/schemas/forge-manifest.schema.json +57 -0
  100. package/src/forge/_generated/releaseManifest.json +1 -2
  101. package/src/forge/_generated/releaseManifest.ts +3 -3
  102. package/src/forge/agent-adapters/index.ts +1511 -123
  103. package/src/forge/agent-adapters/types.ts +216 -1
  104. package/src/forge/agent-memory/bridge.ts +1245 -0
  105. package/src/forge/agent-memory/context-pack.ts +151 -0
  106. package/src/forge/agent-memory/hook-runner.ts +312 -0
  107. package/src/forge/agent-memory/mcp.ts +224 -0
  108. package/src/forge/agent-memory/normalize.ts +498 -0
  109. package/src/forge/agent-memory/redaction.ts +103 -0
  110. package/src/forge/agent-memory/sources/claude-code.ts +51 -0
  111. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +273 -0
  112. package/src/forge/agent-memory/sources/codex.ts +119 -0
  113. package/src/forge/agent-memory/sources/cursor.ts +35 -0
  114. package/src/forge/agent-memory/types.ts +191 -0
  115. package/src/forge/bench.ts +248 -0
  116. package/src/forge/brownfield-import/index.ts +801 -0
  117. package/src/forge/brownfield-import/types.ts +127 -0
  118. package/src/forge/cair/action-journal.ts +61 -0
  119. package/src/forge/cair/action-parser.ts +314 -0
  120. package/src/forge/cair/action-validator.ts +40 -0
  121. package/src/forge/cair/actions.ts +1818 -0
  122. package/src/forge/cair/format.ts +77 -0
  123. package/src/forge/cair/index.ts +106 -0
  124. package/src/forge/cair/query.ts +478 -0
  125. package/src/forge/cair/snapshot.ts +315 -0
  126. package/src/forge/cair/types.ts +248 -0
  127. package/src/forge/cli/ai.ts +671 -3
  128. package/src/forge/cli/auth.ts +36 -1
  129. package/src/forge/cli/build.ts +20 -4
  130. package/src/forge/cli/changed.ts +300 -0
  131. package/src/forge/cli/codex-app-server.ts +877 -0
  132. package/src/forge/cli/commands.ts +1285 -7
  133. package/src/forge/cli/db.ts +121 -2
  134. package/src/forge/cli/deps.ts +79 -12
  135. package/src/forge/cli/dev.ts +502 -38
  136. package/src/forge/cli/docs.ts +265 -0
  137. package/src/forge/cli/handoff.ts +250 -0
  138. package/src/forge/cli/index.ts +1 -0
  139. package/src/forge/cli/main.ts +49 -3
  140. package/src/forge/cli/new.ts +3 -1
  141. package/src/forge/cli/next-actions.ts +23 -0
  142. package/src/forge/cli/output.ts +290 -1
  143. package/src/forge/cli/parse.ts +770 -36
  144. package/src/forge/cli/query.ts +32 -0
  145. package/src/forge/cli/release.ts +35 -11
  146. package/src/forge/cli/rls.ts +568 -17
  147. package/src/forge/cli/run.ts +41 -0
  148. package/src/forge/cli/secrets.ts +46 -1
  149. package/src/forge/cli/security.ts +381 -0
  150. package/src/forge/cli/self-host.ts +56 -14
  151. package/src/forge/cli/studio.ts +2163 -0
  152. package/src/forge/cli/verify.ts +1422 -32
  153. package/src/forge/compiler/agent-contract/build.ts +725 -41
  154. package/src/forge/compiler/agent-contract/types.ts +85 -0
  155. package/src/forge/compiler/ai-registry/build.ts +62 -1
  156. package/src/forge/compiler/ai-registry/constants.ts +1 -1
  157. package/src/forge/compiler/ai-registry/parse.ts +168 -5
  158. package/src/forge/compiler/api-surface/build.ts +47 -0
  159. package/src/forge/compiler/app-graph/build.ts +68 -8
  160. package/src/forge/compiler/app-graph/extract.ts +107 -0
  161. package/src/forge/compiler/app-graph/forge-apis.ts +1 -0
  162. package/src/forge/compiler/app-graph/module-graph.ts +73 -78
  163. package/src/forge/compiler/app-graph/parser.ts +24 -24
  164. package/src/forge/compiler/app-graph/profile.ts +26 -0
  165. package/src/forge/compiler/app-graph/versions.ts +1 -1
  166. package/src/forge/compiler/classifier/capabilities.ts +3 -2
  167. package/src/forge/compiler/classifier/classify.ts +32 -8
  168. package/src/forge/compiler/classifier/secrets.ts +3 -2
  169. package/src/forge/compiler/classifier/signals.ts +91 -1
  170. package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
  171. package/src/forge/compiler/client-sdk/render-client.ts +188 -13
  172. package/src/forge/compiler/data-graph/parse.ts +3 -3
  173. package/src/forge/compiler/data-graph/sql/ddl.ts +60 -2
  174. package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
  175. package/src/forge/compiler/data-graph/sql/types.ts +1 -0
  176. package/src/forge/compiler/dev-manifest/build.ts +3 -0
  177. package/src/forge/compiler/diagnostics/codes.ts +35 -0
  178. package/src/forge/compiler/diagnostics/create.ts +8 -3
  179. package/src/forge/compiler/diagnostics/index.ts +2 -0
  180. package/src/forge/compiler/emitter/barrel.ts +3 -0
  181. package/src/forge/compiler/emitter/render.ts +5 -0
  182. package/src/forge/compiler/external-manifest/registry.ts +205 -0
  183. package/src/forge/compiler/external-manifest/types.ts +91 -0
  184. package/src/forge/compiler/external-manifest/validate.ts +373 -0
  185. package/src/forge/compiler/frontend-graph/build.ts +85 -13
  186. package/src/forge/compiler/integration/add.ts +498 -22
  187. package/src/forge/compiler/integration/snapshot.ts +2 -0
  188. package/src/forge/compiler/make-registry/build.ts +19 -7
  189. package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
  190. package/src/forge/compiler/orchestrator/plan.ts +78 -7
  191. package/src/forge/compiler/orchestrator/profile.ts +65 -0
  192. package/src/forge/compiler/orchestrator/run.ts +97 -31
  193. package/src/forge/compiler/orchestrator/serialize.ts +101 -8
  194. package/src/forge/compiler/package-graph/compiler.ts +13 -3
  195. package/src/forge/compiler/package-manager/adapter.ts +4 -1
  196. package/src/forge/compiler/package-manager/commands.ts +4 -0
  197. package/src/forge/compiler/package-manager/executor.ts +30 -1
  198. package/src/forge/compiler/policy-registry/build.ts +44 -1
  199. package/src/forge/compiler/test-graph/build.ts +11 -3
  200. package/src/forge/compiler/types/ai-registry.ts +25 -1
  201. package/src/forge/compiler/types/app-graph.ts +9 -2
  202. package/src/forge/compiler/types/cli.ts +76 -1
  203. package/src/forge/compiler/types/dev-manifest.ts +3 -0
  204. package/src/forge/compiler/types/frontend-graph.ts +2 -2
  205. package/src/forge/delta/classifier.ts +52 -0
  206. package/src/forge/delta/explain.ts +126 -0
  207. package/src/forge/delta/git-observer.ts +43 -0
  208. package/src/forge/delta/ids.ts +44 -0
  209. package/src/forge/delta/index.ts +13 -0
  210. package/src/forge/delta/recorder.ts +402 -0
  211. package/src/forge/delta/redaction.ts +50 -0
  212. package/src/forge/delta/schema.ts +240 -0
  213. package/src/forge/delta/session.ts +142 -0
  214. package/src/forge/delta/status.ts +489 -0
  215. package/src/forge/delta/store.ts +2975 -0
  216. package/src/forge/delta/timeline.ts +104 -0
  217. package/src/forge/dev/server.ts +768 -15
  218. package/src/forge/dev/types.ts +15 -1
  219. package/src/forge/dev/watch.ts +17 -7
  220. package/src/forge/dev-console/cycle.ts +233 -21
  221. package/src/forge/dev-console/types.ts +46 -1
  222. package/src/forge/impact/index.ts +46 -8
  223. package/src/forge/impact/types.ts +6 -0
  224. package/src/forge/intent/index.ts +35 -16
  225. package/src/forge/make/index.ts +149 -6
  226. package/src/forge/make/templates.ts +343 -2
  227. package/src/forge/make/types.ts +3 -1
  228. package/src/forge/refactor/index.ts +1 -0
  229. package/src/forge/repair/rules/index.ts +2 -2
  230. package/src/forge/review/index.ts +158 -12
  231. package/src/forge/review/types.ts +15 -0
  232. package/src/forge/runtime/ai/context.ts +210 -5
  233. package/src/forge/runtime/ai/types.ts +70 -0
  234. package/src/forge/runtime/auth/claims.ts +32 -0
  235. package/src/forge/runtime/auth/errors.ts +2 -0
  236. package/src/forge/runtime/context/create-context.ts +30 -6
  237. package/src/forge/runtime/db/generated-client.ts +13 -2
  238. package/src/forge/runtime/db/memory-adapter.ts +2 -2
  239. package/src/forge/runtime/db/pglite-adapter.ts +77 -2
  240. package/src/forge/runtime/db/postgres-adapter.ts +6 -3
  241. package/src/forge/runtime/executor.ts +112 -2
  242. package/src/forge/runtime/external/bridge.ts +649 -0
  243. package/src/forge/runtime/runner/run-entry.ts +16 -7
  244. package/src/forge/runtime/telemetry/scrubber.ts +91 -10
  245. package/src/forge/runtime/webhooks/security.ts +184 -0
  246. package/src/forge/server.ts +100 -2
  247. package/src/forge/version.ts +1 -1
  248. package/src/forge/vue/index.ts +407 -0
  249. package/src/forge/workspace/change-summary.ts +209 -0
  250. package/src/forge/workspace/forge-cli.ts +14 -0
  251. package/src/forge/workspace/git-summary.ts +279 -0
  252. package/templates/agent-workroom/AGENTS.md +29 -0
  253. package/templates/agent-workroom/README.md +34 -0
  254. package/templates/agent-workroom/forge.config.ts +3 -0
  255. package/templates/agent-workroom/package.json +33 -0
  256. package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
  257. package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
  258. package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
  259. package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
  260. package/templates/agent-workroom/src/forge/schema.ts +54 -0
  261. package/templates/agent-workroom/src/policies.ts +6 -0
  262. package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
  263. package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
  264. package/templates/agent-workroom/tsconfig.json +16 -0
  265. package/templates/agent-workroom/web/index.html +12 -0
  266. package/templates/agent-workroom/web/package.json +21 -0
  267. package/templates/agent-workroom/web/src/App.tsx +345 -0
  268. package/templates/agent-workroom/web/src/lib/forge.ts +13 -0
  269. package/templates/agent-workroom/web/src/main.tsx +13 -0
  270. package/templates/agent-workroom/web/src/styles.css +545 -0
  271. package/templates/agent-workroom/web/tsconfig.json +27 -0
  272. package/templates/b2b-support-web/package.json +2 -0
  273. package/templates/b2b-support-web/tsconfig.json +4 -1
  274. package/templates/b2b-support-web/web/package.json +1 -1
  275. package/templates/minimal-web/package.json +2 -1
  276. package/templates/minimal-web/tsconfig.json +3 -1
  277. package/templates/minimal-web/web/package.json +2 -2
  278. package/src/forge/_generated/actionSubscriptions.json +0 -2
  279. package/src/forge/_generated/actionSubscriptions.ts +0 -10
  280. package/src/forge/_generated/agentAdapterManifest.json +0 -2
  281. package/src/forge/_generated/agentAdapterManifest.ts +0 -73
  282. package/src/forge/_generated/agentContract.json +0 -2
  283. package/src/forge/_generated/agentContract.ts +0 -7696
  284. package/src/forge/_generated/agentQuickstart.md +0 -32
  285. package/src/forge/_generated/aiContext.ts +0 -59
  286. package/src/forge/_generated/aiModels.json +0 -2
  287. package/src/forge/_generated/aiModels.ts +0 -35
  288. package/src/forge/_generated/aiProviders.json +0 -2
  289. package/src/forge/_generated/aiProviders.ts +0 -23
  290. package/src/forge/_generated/aiRegistry.json +0 -2
  291. package/src/forge/_generated/aiRegistry.ts +0 -29
  292. package/src/forge/_generated/api.json +0 -2
  293. package/src/forge/_generated/api.ts +0 -8
  294. package/src/forge/_generated/appGraph.json +0 -2
  295. package/src/forge/_generated/appGraph.ts +0 -14667
  296. package/src/forge/_generated/appMap.md +0 -35
  297. package/src/forge/_generated/artifactManifest.json +0 -2
  298. package/src/forge/_generated/artifactManifest.ts +0 -7
  299. package/src/forge/_generated/authClaims.json +0 -2
  300. package/src/forge/_generated/authClaims.ts +0 -13
  301. package/src/forge/_generated/authConfig.json +0 -2
  302. package/src/forge/_generated/authConfig.ts +0 -17
  303. package/src/forge/_generated/authContext.ts +0 -23
  304. package/src/forge/_generated/authRegistry.json +0 -2
  305. package/src/forge/_generated/authRegistry.ts +0 -25
  306. package/src/forge/_generated/buildInfo.json +0 -2
  307. package/src/forge/_generated/buildInfo.ts +0 -9
  308. package/src/forge/_generated/capabilityMap.json +0 -2
  309. package/src/forge/_generated/capabilityMap.md +0 -15
  310. package/src/forge/_generated/capabilityMap.ts +0 -17
  311. package/src/forge/_generated/client.ts +0 -282
  312. package/src/forge/_generated/clientApi.ts +0 -9
  313. package/src/forge/_generated/clientManifest.json +0 -2
  314. package/src/forge/_generated/clientManifest.ts +0 -39
  315. package/src/forge/_generated/clientTypes.ts +0 -78
  316. package/src/forge/_generated/configRegistry.json +0 -2
  317. package/src/forge/_generated/configRegistry.ts +0 -4
  318. package/src/forge/_generated/dataGraph.json +0 -2
  319. package/src/forge/_generated/dataGraph.ts +0 -8
  320. package/src/forge/_generated/db.json +0 -2
  321. package/src/forge/_generated/db.ts +0 -2
  322. package/src/forge/_generated/dbSecurityManifest.json +0 -2
  323. package/src/forge/_generated/dbSecurityManifest.ts +0 -15
  324. package/src/forge/_generated/dbSessionContext.json +0 -2
  325. package/src/forge/_generated/dbSessionContext.ts +0 -39
  326. package/src/forge/_generated/deployManifest.json +0 -2
  327. package/src/forge/_generated/deployManifest.ts +0 -14
  328. package/src/forge/_generated/devManifest.json +0 -2
  329. package/src/forge/_generated/devManifest.ts +0 -47
  330. package/src/forge/_generated/envSchema.json +0 -2
  331. package/src/forge/_generated/envSchema.ts +0 -59
  332. package/src/forge/_generated/frontendGraph.json +0 -2
  333. package/src/forge/_generated/frontendGraph.ts +0 -27
  334. package/src/forge/_generated/importGuards.json +0 -2
  335. package/src/forge/_generated/importGuards.ts +0 -686
  336. package/src/forge/_generated/index.ts +0 -67
  337. package/src/forge/_generated/liveProductionManifest.json +0 -2
  338. package/src/forge/_generated/liveProductionManifest.ts +0 -23
  339. package/src/forge/_generated/liveProtocol.json +0 -2
  340. package/src/forge/_generated/liveProtocol.ts +0 -21
  341. package/src/forge/_generated/liveQueryRegistry.json +0 -2
  342. package/src/forge/_generated/liveQueryRegistry.ts +0 -9
  343. package/src/forge/_generated/liveTransportConfig.json +0 -2
  344. package/src/forge/_generated/liveTransportConfig.ts +0 -19
  345. package/src/forge/_generated/makeRegistry.json +0 -2
  346. package/src/forge/_generated/makeRegistry.ts +0 -163
  347. package/src/forge/_generated/makeTemplates.json +0 -2
  348. package/src/forge/_generated/makeTemplates.ts +0 -61
  349. package/src/forge/_generated/mockMap.json +0 -2
  350. package/src/forge/_generated/mockMap.ts +0 -7
  351. package/src/forge/_generated/operationPlaybooks.md +0 -147
  352. package/src/forge/_generated/packageGraph.json +0 -2
  353. package/src/forge/_generated/packageGraph.ts +0 -245249
  354. package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
  355. package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
  356. package/src/forge/_generated/permissionMatrix.json +0 -2
  357. package/src/forge/_generated/permissionMatrix.ts +0 -7
  358. package/src/forge/_generated/policyRegistry.json +0 -2
  359. package/src/forge/_generated/policyRegistry.ts +0 -11
  360. package/src/forge/_generated/queryRegistry.json +0 -2
  361. package/src/forge/_generated/queryRegistry.ts +0 -9
  362. package/src/forge/_generated/react.d.ts +0 -22
  363. package/src/forge/_generated/react.ts +0 -29
  364. package/src/forge/_generated/reactManifest.json +0 -2
  365. package/src/forge/_generated/reactManifest.ts +0 -19
  366. package/src/forge/_generated/rlsPolicies.json +0 -2
  367. package/src/forge/_generated/rlsPolicies.sql +0 -34
  368. package/src/forge/_generated/rlsPolicies.ts +0 -6
  369. package/src/forge/_generated/runtimeGraph.json +0 -2
  370. package/src/forge/_generated/runtimeGraph.ts +0 -8
  371. package/src/forge/_generated/runtimeMatrix.json +0 -2
  372. package/src/forge/_generated/runtimeMatrix.ts +0 -327385
  373. package/src/forge/_generated/runtimeRegistry.ts +0 -2
  374. package/src/forge/_generated/runtimeRules.md +0 -79
  375. package/src/forge/_generated/secretRegistry.json +0 -2
  376. package/src/forge/_generated/secretRegistry.ts +0 -50
  377. package/src/forge/_generated/secretsContext.ts +0 -11
  378. package/src/forge/_generated/serverApi.ts +0 -10
  379. package/src/forge/_generated/sourceMapManifest.json +0 -2
  380. package/src/forge/_generated/sourceMapManifest.ts +0 -7
  381. package/src/forge/_generated/sqlPlan.json +0 -2
  382. package/src/forge/_generated/sqlPlan.ts +0 -88
  383. package/src/forge/_generated/subscriptionManifest.json +0 -2
  384. package/src/forge/_generated/subscriptionManifest.ts +0 -7
  385. package/src/forge/_generated/symbolicationManifest.json +0 -2
  386. package/src/forge/_generated/symbolicationManifest.ts +0 -17
  387. package/src/forge/_generated/telemetryRegistry.json +0 -2
  388. package/src/forge/_generated/telemetryRegistry.ts +0 -9
  389. package/src/forge/_generated/telemetrySinks.json +0 -2
  390. package/src/forge/_generated/telemetrySinks.ts +0 -11
  391. package/src/forge/_generated/tenantScope.json +0 -2
  392. package/src/forge/_generated/tenantScope.ts +0 -8
  393. package/src/forge/_generated/testGraph.json +0 -2
  394. package/src/forge/_generated/testGraph.ts +0 -3108
  395. package/src/forge/_generated/testPlanRegistry.json +0 -2
  396. package/src/forge/_generated/testPlanRegistry.ts +0 -33
  397. package/src/forge/_generated/uiRoutes.json +0 -2
  398. package/src/forge/_generated/uiRoutes.ts +0 -16
  399. package/src/forge/_generated/uiScenarios.json +0 -2
  400. package/src/forge/_generated/uiScenarios.ts +0 -30
  401. package/src/forge/_generated/uiTestManifest.json +0 -2
  402. package/src/forge/_generated/uiTestManifest.ts +0 -27
  403. package/src/forge/_generated/workflowRegistry.json +0 -2
  404. package/src/forge/_generated/workflowRegistry.ts +0 -9
  405. package/src/forge/_generated/workflowSubscriptions.json +0 -2
  406. package/src/forge/_generated/workflowSubscriptions.ts +0 -10
@@ -1,4 +1,4 @@
1
- import { join } from "node:path";
1
+ import { join, relative, resolve } from "node:path";
2
2
  import { nodeFileSystem } from "../fs/index.ts";
3
3
  import type { AddOptions } from "../types/cli.ts";
4
4
  import type { Diagnostic } from "../types/diagnostic.ts";
@@ -16,11 +16,14 @@ import { PACKAGE_ANALYZER_VERSION } from "../package-graph/constants.ts";
16
16
  import { renderBody } from "../emitter/render.ts";
17
17
  import { hashStable } from "../primitives/hash.ts";
18
18
  import { PackageGraphCompiler } from "../package-graph/compiler.ts";
19
+ import { run as runGenerate } from "../orchestrator/run.ts";
19
20
  import {
21
+ buildAddCommand,
20
22
  detectAndCreatePackageManagerAdapter,
21
23
  dryRunRecipeFallbackMessage,
22
24
  type PackageManagerAdapter,
23
25
  } from "../package-manager/adapter.ts";
26
+ import { parsePackageName } from "../package-manager/parse-spec.ts";
24
27
  import { PackageManagerCommandError } from "../package-manager/executor.ts";
25
28
  import {
26
29
  isReferenceAlias,
@@ -50,6 +53,24 @@ export interface ForgeAddOptions extends AddOptions {
50
53
 
51
54
  export interface ForgeAddResult {
52
55
  alias: string;
56
+ mode?: "integration" | "package";
57
+ targetKind?: "forge-integration" | "npm-package";
58
+ target?: string;
59
+ packageTarget?: "root" | "frontend" | "backend" | "workspace";
60
+ packageTargetReason?: string;
61
+ explanation?: string;
62
+ recipeVersion?: string;
63
+ recipePackages?: string[];
64
+ requiredSecrets?: string[];
65
+ optionalSecrets?: string[];
66
+ packageSpec?: string;
67
+ packageName?: string;
68
+ packageManager?: string;
69
+ installCommand?: string[];
70
+ nativeInstallCommand?: string[];
71
+ avoidedManualCommand?: string;
72
+ installCwd?: string;
73
+ installWorkspace?: string;
53
74
  changed: string[];
54
75
  unchanged: string[];
55
76
  warnings: Diagnostic[];
@@ -58,6 +79,210 @@ export interface ForgeAddResult {
58
79
  failureKind?: string;
59
80
  }
60
81
 
82
+ function recipeResultMetadata(recipe: NonNullable<ReturnType<typeof resolveRecipe>>): Pick<
83
+ ForgeAddResult,
84
+ "recipeVersion" | "recipePackages" | "requiredSecrets" | "optionalSecrets"
85
+ > {
86
+ return {
87
+ recipeVersion: recipe.recipeVersion,
88
+ recipePackages: recipe.packages.map((pkg) => pkg.packageName),
89
+ requiredSecrets: recipe.secrets.filter((secret) => secret.required !== false).map((secret) => secret.envVar),
90
+ optionalSecrets: recipe.secrets.filter((secret) => secret.required === false).map((secret) => secret.envVar),
91
+ };
92
+ }
93
+
94
+ function addExplanation(result: ForgeAddResult): string {
95
+ if (result.mode === "package") {
96
+ const location = result.target && result.target !== "root" ? `${result.target}/package.json` : "package.json";
97
+ const command = result.installCommand?.join(" ") ?? `package manager add ${result.packageSpec ?? result.alias}`;
98
+ const target = result.packageTarget && result.packageTarget !== "root" ? ` (${result.packageTarget})` : "";
99
+ return `Adds npm package '${result.packageSpec ?? result.alias}' to ${location}${target}, then refreshes Forge package evidence. Forge runs the native install command for you: ${command}.`;
100
+ }
101
+
102
+ if (result.failureKind === "unknown_alias") {
103
+ return `No Forge integration recipe exists for '${result.alias}'. Use 'forge add ${result.alias}' or 'forge add package ${result.alias}' for a normal npm package, or choose a supported integration alias.`;
104
+ }
105
+
106
+ return `Applies the Forge integration recipe '${result.alias}', including package install, generated adapters, secret-name metadata, runtime guards, and Forge lock evidence.`;
107
+ }
108
+
109
+ function finalizeAddResult(result: Omit<ForgeAddResult, "targetKind" | "explanation">): ForgeAddResult {
110
+ const mode = result.mode ?? "integration";
111
+ const withMode: ForgeAddResult = {
112
+ ...result,
113
+ mode,
114
+ targetKind: mode === "package" ? "npm-package" : "forge-integration",
115
+ };
116
+ return {
117
+ ...withMode,
118
+ explanation: addExplanation(withMode),
119
+ };
120
+ }
121
+
122
+ function packageJsonRelativeFor(workspace?: string): string {
123
+ return workspace ? `${workspace.replace(/\\/g, "/")}/package.json` : "package.json";
124
+ }
125
+
126
+ type PackageAddScope = "root" | "frontend" | "backend" | "workspace";
127
+
128
+ interface NormalizedPackageRequest {
129
+ spec: string;
130
+ packageTarget: PackageAddScope;
131
+ packageTargetReason: string;
132
+ installWorkspace?: string;
133
+ forcePackageMode: boolean;
134
+ }
135
+
136
+ function parseScopedPackageSpec(spec: string): {
137
+ spec: string;
138
+ target?: "frontend" | "backend";
139
+ forcePackageMode: boolean;
140
+ } {
141
+ const trimmed = spec.trim();
142
+ const match = /^(frontend|front|web|client|backend|back|server|api|root):(.+)$/i.exec(trimmed);
143
+ if (!match) {
144
+ return { spec: trimmed, forcePackageMode: false };
145
+ }
146
+ const scope = match[1]!.toLowerCase();
147
+ return {
148
+ spec: match[2]!.trim(),
149
+ target: scope === "frontend" || scope === "front" || scope === "web" || scope === "client"
150
+ ? "frontend"
151
+ : "backend",
152
+ forcePackageMode: true,
153
+ };
154
+ }
155
+
156
+ function findFrontendWorkspace(workspaceRoot: string): string | undefined {
157
+ for (const candidate of ["web", "frontend", "client", "apps/web", "packages/web"]) {
158
+ if (nodeFileSystem.exists(join(workspaceRoot, candidate, "package.json"))) {
159
+ return candidate;
160
+ }
161
+ }
162
+ return undefined;
163
+ }
164
+
165
+ function normalizePackageRequest(
166
+ spec: string,
167
+ options: ForgeAddOptions,
168
+ ): { request: NormalizedPackageRequest; error?: Diagnostic } {
169
+ const scoped = parseScopedPackageSpec(spec);
170
+ const requestedTarget = options.packageTarget ?? scoped.target;
171
+ if (options.installWorkspace?.trim()) {
172
+ return {
173
+ request: {
174
+ spec: scoped.spec,
175
+ packageTarget: "workspace",
176
+ packageTargetReason: `explicit --workspace ${options.installWorkspace.trim()}`,
177
+ installWorkspace: options.installWorkspace.trim(),
178
+ forcePackageMode: scoped.forcePackageMode,
179
+ },
180
+ };
181
+ }
182
+ if (requestedTarget === "frontend") {
183
+ const workspace = findFrontendWorkspace(options.workspaceRoot);
184
+ if (!workspace) {
185
+ return {
186
+ request: {
187
+ spec: scoped.spec,
188
+ packageTarget: "frontend",
189
+ packageTargetReason: "frontend target requested, but no frontend package.json was detected",
190
+ forcePackageMode: true,
191
+ },
192
+ error: createDiagnostic({
193
+ severity: "error",
194
+ code: "FORGE_ADD_FRONTEND_WORKSPACE_MISSING",
195
+ message: "frontend package target requested, but no frontend package.json was found under web, frontend, client, apps/web, or packages/web",
196
+ fixHint: "Create a frontend with forge make ui, pass --workspace <path>, or install as a backend/root package.",
197
+ suggestedCommands: [
198
+ "forge make ui --framework vite --dry-run --json",
199
+ `forge add ${scoped.spec} --workspace web --dry-run --json`,
200
+ `forge add backend:${scoped.spec} --dry-run --json`,
201
+ ],
202
+ }),
203
+ };
204
+ }
205
+ return {
206
+ request: {
207
+ spec: scoped.spec,
208
+ packageTarget: "frontend",
209
+ packageTargetReason: `frontend target resolved to ${workspace}/package.json`,
210
+ installWorkspace: workspace,
211
+ forcePackageMode: true,
212
+ },
213
+ };
214
+ }
215
+ if (requestedTarget === "backend") {
216
+ return {
217
+ request: {
218
+ spec: scoped.spec,
219
+ packageTarget: "backend",
220
+ packageTargetReason: "backend target resolves to the Forge app root package.json",
221
+ forcePackageMode: true,
222
+ },
223
+ };
224
+ }
225
+ return {
226
+ request: {
227
+ spec: scoped.spec,
228
+ packageTarget: "root",
229
+ packageTargetReason: "default package target resolves to the Forge app root package.json",
230
+ forcePackageMode: scoped.forcePackageMode,
231
+ },
232
+ };
233
+ }
234
+
235
+ function resolveInstallRoot(options: ForgeAddOptions): {
236
+ installRoot: string;
237
+ target: string;
238
+ extraSnapshotPaths: string[];
239
+ error?: Diagnostic;
240
+ } {
241
+ const workspace = options.installWorkspace?.trim();
242
+ if (!workspace) {
243
+ return {
244
+ installRoot: options.workspaceRoot,
245
+ target: "root",
246
+ extraSnapshotPaths: [],
247
+ };
248
+ }
249
+
250
+ const workspaceRoot = resolve(options.workspaceRoot);
251
+ const installRoot = resolve(workspaceRoot, workspace);
252
+ const rel = relative(workspaceRoot, installRoot).replace(/\\/g, "/");
253
+ if (rel.startsWith("..") || rel === "") {
254
+ return {
255
+ installRoot,
256
+ target: workspace,
257
+ extraSnapshotPaths: [],
258
+ error: createDiagnostic({
259
+ severity: "error",
260
+ code: "FORGE_ADD_INVALID_WORKSPACE",
261
+ message: `workspace '${workspace}' must resolve inside the Forge app`,
262
+ }),
263
+ };
264
+ }
265
+
266
+ if (!nodeFileSystem.exists(join(installRoot, "package.json"))) {
267
+ return {
268
+ installRoot,
269
+ target: rel,
270
+ extraSnapshotPaths: [],
271
+ error: createDiagnostic({
272
+ severity: "error",
273
+ code: "FORGE_ADD_INVALID_WORKSPACE",
274
+ message: `workspace '${workspace}' does not contain a package.json`,
275
+ }),
276
+ };
277
+ }
278
+
279
+ return {
280
+ installRoot,
281
+ target: rel,
282
+ extraSnapshotPaths: [packageJsonRelativeFor(rel)],
283
+ };
284
+ }
285
+
61
286
  function failureKind(errors: Diagnostic[]): string | undefined {
62
287
  if (errors.length === 0) {
63
288
  return undefined;
@@ -258,24 +483,85 @@ export async function forgeAdd(
258
483
  alias: string,
259
484
  options: ForgeAddOptions,
260
485
  ): Promise<ForgeAddResult> {
261
- const normalized = alias.trim().toLowerCase();
486
+ const packageRequestResult = normalizePackageRequest(alias, options);
487
+ const packageRequest = packageRequestResult.request;
488
+ const effectiveOptions: ForgeAddOptions = {
489
+ ...options,
490
+ installWorkspace: packageRequest.installWorkspace,
491
+ };
492
+ const packageModeRequested =
493
+ options.mode === "package" ||
494
+ packageRequest.forcePackageMode ||
495
+ options.packageTarget !== undefined;
496
+ if (packageRequestResult.error && packageModeRequested) {
497
+ return finalizeAddResult({
498
+ alias: packageRequest.spec,
499
+ mode: "package",
500
+ target: packageRequest.installWorkspace ?? packageRequest.packageTarget,
501
+ packageTarget: packageRequest.packageTarget,
502
+ packageTargetReason: packageRequest.packageTargetReason,
503
+ packageSpec: packageRequest.spec,
504
+ packageName: parsePackageName(packageRequest.spec),
505
+ changed: [],
506
+ unchanged: [],
507
+ warnings: [],
508
+ errors: [packageRequestResult.error],
509
+ exitCode: 1,
510
+ failureKind: "invalid_workspace",
511
+ });
512
+ }
513
+ if (options.mode === "integration" && (packageRequest.forcePackageMode || options.packageTarget)) {
514
+ const error = createDiagnostic({
515
+ severity: "error",
516
+ code: "FORGE_ADD_SCOPED_INTEGRATION",
517
+ message: "frontend/backend package targets only apply to normal npm package installs, not explicit integration recipes",
518
+ fixHint: "Use forge add package <spec> --frontend, forge add frontend:<spec>, or remove the frontend/backend target for an integration recipe.",
519
+ suggestedCommands: [
520
+ `forge add package ${packageRequest.spec} --frontend --dry-run --json`,
521
+ `forge add integration ${packageRequest.spec} --dry-run --json`,
522
+ ],
523
+ });
524
+ return finalizeAddResult({
525
+ alias: packageRequest.spec,
526
+ mode: "integration",
527
+ changed: [],
528
+ unchanged: [],
529
+ warnings: [],
530
+ errors: [error],
531
+ exitCode: 1,
532
+ failureKind: "invalid_target",
533
+ });
534
+ }
535
+
536
+ const normalized = packageRequest.spec.trim().toLowerCase();
262
537
  const recipe = resolveRecipe(normalized);
538
+ const mode = options.mode ?? "auto";
539
+
540
+ if (packageModeRequested) {
541
+ return forgeAddPackage(packageRequest.spec, effectiveOptions, packageRequest);
542
+ }
543
+
544
+ if (mode === "auto" && (!isReferenceAlias(normalized) || recipe === null)) {
545
+ return forgeAddPackage(packageRequest.spec, effectiveOptions, packageRequest);
546
+ }
263
547
 
264
548
  if (!isReferenceAlias(normalized) || recipe === null) {
265
549
  const error = createDiagnostic({
266
550
  severity: "error",
267
551
  code: "FORGE_UNKNOWN_ALIAS",
268
- message: `unknown integration alias '${alias}'; supported: stripe, posthog, sentry, zod, ai`,
552
+ message: `unknown integration alias '${alias}'; supported: stripe, posthog, sentry, zod, ai. For npm packages, use 'forge add package ${alias}' or 'forge add ${alias}'.`,
553
+ suggestedCommands: [`forge add package ${alias} --dry-run --json`, "forge add --help"],
269
554
  });
270
- return {
555
+ return finalizeAddResult({
271
556
  alias: normalized,
557
+ mode: "integration",
272
558
  changed: [],
273
559
  unchanged: [],
274
560
  warnings: [],
275
561
  errors: [error],
276
562
  exitCode: 1,
277
563
  failureKind: "unknown_alias",
278
- };
564
+ });
279
565
  }
280
566
 
281
567
  const pm =
@@ -283,7 +569,7 @@ export async function forgeAdd(
283
569
  detectAndCreatePackageManagerAdapter(options.workspaceRoot);
284
570
 
285
571
  if (options.dryRun) {
286
- const ctx = discover({ workspaceRoot: options.workspaceRoot });
572
+ const ctx = discover({ workspaceRoot: effectiveOptions.workspaceRoot });
287
573
  let installRoot = options.workspaceRoot;
288
574
 
289
575
  try {
@@ -302,7 +588,7 @@ export async function forgeAdd(
302
588
  recipe,
303
589
  ctx,
304
590
  installRoot,
305
- options,
591
+ effectiveOptions,
306
592
  );
307
593
  warnings.push(
308
594
  createDiagnostic({
@@ -312,15 +598,17 @@ export async function forgeAdd(
312
598
  }),
313
599
  );
314
600
 
315
- return {
601
+ return finalizeAddResult({
316
602
  alias: normalized,
603
+ mode: "integration",
604
+ ...recipeResultMetadata(recipe),
317
605
  changed: [...emitPlan.files.map((file) => file.path), "forge.lock"],
318
606
  unchanged: [],
319
607
  warnings,
320
608
  errors,
321
609
  exitCode: errors.length > 0 ? 1 : 0,
322
610
  failureKind: failureKind(errors),
323
- };
611
+ });
324
612
  }
325
613
 
326
614
  const { emitPlan, warnings, errors } = await buildAddPlan(
@@ -328,18 +616,20 @@ export async function forgeAdd(
328
616
  recipe,
329
617
  ctx,
330
618
  installRoot,
331
- options,
619
+ effectiveOptions,
332
620
  );
333
621
 
334
- return {
622
+ return finalizeAddResult({
335
623
  alias: normalized,
624
+ mode: "integration",
625
+ ...recipeResultMetadata(recipe),
336
626
  changed: [...emitPlan.files.map((file) => file.path), "forge.lock"],
337
627
  unchanged: [],
338
628
  warnings,
339
629
  errors,
340
630
  exitCode: errors.length > 0 ? 1 : 0,
341
631
  failureKind: failureKind(errors),
342
- };
632
+ });
343
633
  }
344
634
 
345
635
  const snapshot = snapshotVersionControlled(options.workspaceRoot);
@@ -363,15 +653,17 @@ export async function forgeAdd(
363
653
 
364
654
  if (analyzeErrors.length > 0) {
365
655
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
366
- return {
656
+ return finalizeAddResult({
367
657
  alias: normalized,
658
+ mode: "integration",
659
+ ...recipeResultMetadata(recipe),
368
660
  changed: [],
369
661
  unchanged: [],
370
662
  warnings,
371
663
  errors: analyzeErrors,
372
664
  exitCode: 1,
373
665
  failureKind: failureKind(analyzeErrors),
374
- };
666
+ });
375
667
  }
376
668
 
377
669
  const emitResult = await emit(emitPlan, {
@@ -384,15 +676,17 @@ export async function forgeAdd(
384
676
 
385
677
  if (errors.length > 0) {
386
678
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
387
- return {
679
+ return finalizeAddResult({
388
680
  alias: normalized,
681
+ mode: "integration",
682
+ ...recipeResultMetadata(recipe),
389
683
  changed: [],
390
684
  unchanged: [],
391
685
  warnings: warningsCombined,
392
686
  errors,
393
687
  exitCode: 1,
394
688
  failureKind: failureKind(errors),
395
- };
689
+ });
396
690
  }
397
691
 
398
692
  const integrityErrors = verifyLockIntegrity(
@@ -401,15 +695,17 @@ export async function forgeAdd(
401
695
  );
402
696
  if (integrityErrors.length > 0) {
403
697
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
404
- return {
698
+ return finalizeAddResult({
405
699
  alias: normalized,
700
+ mode: "integration",
701
+ ...recipeResultMetadata(recipe),
406
702
  changed: [],
407
703
  unchanged: [],
408
704
  warnings: warningsCombined,
409
705
  errors: integrityErrors,
410
706
  exitCode: 1,
411
707
  failureKind: "lock_integrity",
412
- };
708
+ });
413
709
  }
414
710
 
415
711
  const manifest = loadManifest(ctx.cacheDir);
@@ -435,14 +731,16 @@ export async function forgeAdd(
435
731
  ),
436
732
  );
437
733
 
438
- return {
734
+ return finalizeAddResult({
439
735
  alias: normalized,
736
+ mode: "integration",
737
+ ...recipeResultMetadata(recipe),
440
738
  changed: emitResult.changed,
441
739
  unchanged: emitResult.unchanged,
442
740
  warnings: warningsCombined,
443
741
  errors: [],
444
742
  exitCode: 0,
445
- };
743
+ });
446
744
  } catch (error) {
447
745
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
448
746
 
@@ -459,15 +757,193 @@ export async function forgeAdd(
459
757
  message: `forge add failed: ${message}`,
460
758
  });
461
759
 
462
- return {
760
+ return finalizeAddResult({
463
761
  alias: normalized,
762
+ mode: "integration",
763
+ ...recipeResultMetadata(recipe),
464
764
  changed: [],
465
765
  unchanged: [],
466
766
  warnings: [],
467
767
  errors: [diagnostic],
468
768
  exitCode: 1,
469
769
  failureKind: "install_failed",
470
- };
770
+ });
771
+ }
772
+ }
773
+
774
+ async function forgeAddPackage(
775
+ spec: string,
776
+ options: ForgeAddOptions,
777
+ request = normalizePackageRequest(spec, options).request,
778
+ ): Promise<ForgeAddResult> {
779
+ const normalized = request.spec.trim();
780
+ const packageName = parsePackageName(normalized);
781
+ const target = resolveInstallRoot(options);
782
+ if (target.error) {
783
+ return finalizeAddResult({
784
+ alias: normalized,
785
+ mode: "package",
786
+ target: target.target,
787
+ packageTarget: request.packageTarget,
788
+ packageTargetReason: request.packageTargetReason,
789
+ changed: [],
790
+ unchanged: [],
791
+ warnings: [],
792
+ errors: [target.error],
793
+ exitCode: 1,
794
+ failureKind: "invalid_workspace",
795
+ });
796
+ }
797
+
798
+ const pm =
799
+ options.pmAdapter ??
800
+ detectAndCreatePackageManagerAdapter(options.workspaceRoot);
801
+ const packageManagerCwd = target.installRoot;
802
+ const semanticInstallWorkspace = target.target === "root" ? undefined : target.target;
803
+ const installCommand = buildAddCommand(pm.name, normalized, {
804
+ ignoreScripts: !options.allowScripts,
805
+ workspace: undefined,
806
+ });
807
+ const avoidedManualCommand = installCommand.join(" ");
808
+ const installPlan = {
809
+ packageSpec: normalized,
810
+ packageName,
811
+ packageManager: pm.name,
812
+ installCommand,
813
+ nativeInstallCommand: installCommand,
814
+ avoidedManualCommand,
815
+ installCwd: packageManagerCwd.replace(/\\/g, "/"),
816
+ packageTarget: request.packageTarget,
817
+ packageTargetReason: request.packageTargetReason,
818
+ ...(semanticInstallWorkspace ? { installWorkspace: semanticInstallWorkspace } : {}),
819
+ };
820
+
821
+ if (options.dryRun) {
822
+ try {
823
+ await pm.dryRunAdd(normalized, {
824
+ cwd: packageManagerCwd,
825
+ ignoreScripts: !options.allowScripts,
826
+ workspace: undefined,
827
+ });
828
+ } catch (error) {
829
+ const message =
830
+ error instanceof PackageManagerCommandError
831
+ ? error.message
832
+ : error instanceof Error
833
+ ? error.message
834
+ : String(error);
835
+ const diagnostic = createDiagnostic({
836
+ severity: "error",
837
+ code: "FORGE_ADD_INSTALL_FAILED",
838
+ message: `forge add package dry-run failed: ${message}`,
839
+ });
840
+ return finalizeAddResult({
841
+ alias: normalized,
842
+ mode: "package",
843
+ target: target.target,
844
+ ...installPlan,
845
+ changed: [],
846
+ unchanged: [],
847
+ warnings: [],
848
+ errors: [diagnostic],
849
+ exitCode: 1,
850
+ failureKind: "install_failed",
851
+ });
852
+ }
853
+
854
+ return finalizeAddResult({
855
+ alias: normalized,
856
+ mode: "package",
857
+ target: target.target,
858
+ ...installPlan,
859
+ changed: [
860
+ packageJsonRelativeFor(target.target === "root" ? undefined : target.target),
861
+ ],
862
+ unchanged: [],
863
+ warnings: [],
864
+ errors: [],
865
+ exitCode: 0,
866
+ });
867
+ }
868
+
869
+ const snapshot = snapshotVersionControlled(
870
+ options.workspaceRoot,
871
+ target.extraSnapshotPaths,
872
+ );
873
+
874
+ try {
875
+ await pm.add(normalized, {
876
+ cwd: packageManagerCwd,
877
+ ignoreScripts: !options.allowScripts,
878
+ workspace: undefined,
879
+ });
880
+
881
+ const generated = await runGenerate({
882
+ workspaceRoot: options.workspaceRoot,
883
+ check: false,
884
+ dryRun: false,
885
+ json: options.json,
886
+ concurrency: 4,
887
+ });
888
+
889
+ if (generated.exitCode !== 0) {
890
+ restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
891
+ return finalizeAddResult({
892
+ alias: normalized,
893
+ mode: "package",
894
+ target: target.target,
895
+ ...installPlan,
896
+ changed: [],
897
+ unchanged: [],
898
+ warnings: generated.warnings,
899
+ errors: generated.errors,
900
+ exitCode: 1,
901
+ failureKind: generated.failureKind,
902
+ });
903
+ }
904
+
905
+ return finalizeAddResult({
906
+ alias: normalized,
907
+ mode: "package",
908
+ target: target.target,
909
+ ...installPlan,
910
+ changed: [
911
+ packageJsonRelativeFor(target.target === "root" ? undefined : target.target),
912
+ ...generated.changed,
913
+ ],
914
+ unchanged: generated.unchanged,
915
+ warnings: generated.warnings,
916
+ errors: generated.errors,
917
+ exitCode: 0,
918
+ });
919
+ } catch (error) {
920
+ restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
921
+
922
+ const message =
923
+ error instanceof PackageManagerCommandError
924
+ ? error.message
925
+ : error instanceof Error
926
+ ? error.message
927
+ : String(error);
928
+
929
+ const diagnostic = createDiagnostic({
930
+ severity: "error",
931
+ code: "FORGE_ADD_INSTALL_FAILED",
932
+ message: `forge add package failed: ${message}`,
933
+ });
934
+
935
+ return finalizeAddResult({
936
+ alias: normalized,
937
+ mode: "package",
938
+ target: target.target,
939
+ ...installPlan,
940
+ changed: [],
941
+ unchanged: [],
942
+ warnings: [],
943
+ errors: [diagnostic],
944
+ exitCode: 1,
945
+ failureKind: "install_failed",
946
+ });
471
947
  }
472
948
  }
473
949
 
@@ -14,6 +14,7 @@ function readOptional(path: string): string | null {
14
14
 
15
15
  export function snapshotVersionControlled(
16
16
  workspaceRoot: string,
17
+ extraRelativePaths: string[] = [],
17
18
  ): VersionControlledSnapshot {
18
19
  const pm = detectPackageManager(workspaceRoot);
19
20
  const lockfile = getLockfileForPm(pm);
@@ -25,6 +26,7 @@ export function snapshotVersionControlled(
25
26
  `${workspaceRoot.replace(/\\/g, "/")}/`,
26
27
  "",
27
28
  ),
29
+ ...extraRelativePaths,
28
30
  ];
29
31
 
30
32
  const files = new Map<string, string | null>();