forgeos 0.1.0-alpha.4 → 0.1.0-alpha.41

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 (416) hide show
  1. package/.npmignore +10 -0
  2. package/AGENTS.md +142 -90
  3. package/CHANGELOG.md +433 -0
  4. package/LICENSE +21 -0
  5. package/README.md +67 -8
  6. package/adapters/go/README.md +23 -0
  7. package/adapters/go/go.mod +3 -0
  8. package/adapters/go/http.go +149 -0
  9. package/adapters/go/registry.go +234 -0
  10. package/adapters/go/types.go +136 -0
  11. package/adapters/java/README.md +68 -0
  12. package/adapters/java/pom.xml +34 -0
  13. package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
  14. package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
  15. package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
  16. package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
  17. package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
  18. package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
  19. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
  20. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
  21. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
  22. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
  23. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
  24. package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
  25. package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
  26. package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
  27. package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
  28. package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
  29. package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
  30. package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
  31. package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
  32. package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
  33. package/adapters/java-spring-boot-starter/README.md +32 -0
  34. package/adapters/java-spring-boot-starter/pom.xml +36 -0
  35. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
  36. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
  37. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
  38. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
  39. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
  40. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
  41. package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  42. package/bin/forge.mjs +18 -0
  43. package/docs/cair-protocol.md +103 -0
  44. package/docs/changelog.md +548 -0
  45. package/docs/forge-protocol.md +189 -0
  46. package/examples/go-billing/go.mod +7 -0
  47. package/examples/go-billing/main.go +120 -0
  48. package/examples/java-billing/pom.xml +52 -0
  49. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
  50. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
  51. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
  52. package/package.json +31 -3
  53. package/schemas/forge-manifest.schema.json +57 -0
  54. package/src/forge/_generated/releaseManifest.json +1 -2
  55. package/src/forge/_generated/releaseManifest.ts +3 -3
  56. package/src/forge/agent-adapters/index.ts +1584 -125
  57. package/src/forge/agent-adapters/types.ts +224 -1
  58. package/src/forge/agent-memory/bridge.ts +1333 -0
  59. package/src/forge/agent-memory/context-pack.ts +277 -0
  60. package/src/forge/agent-memory/hook-runner.ts +312 -0
  61. package/src/forge/agent-memory/mcp.ts +224 -0
  62. package/src/forge/agent-memory/normalize.ts +498 -0
  63. package/src/forge/agent-memory/redaction.ts +103 -0
  64. package/src/forge/agent-memory/sources/claude-code.ts +51 -0
  65. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +273 -0
  66. package/src/forge/agent-memory/sources/codex.ts +119 -0
  67. package/src/forge/agent-memory/sources/cursor.ts +35 -0
  68. package/src/forge/agent-memory/types.ts +204 -0
  69. package/src/forge/bench.ts +248 -0
  70. package/src/forge/brownfield-import/index.ts +801 -0
  71. package/src/forge/brownfield-import/types.ts +127 -0
  72. package/src/forge/cair/action-journal.ts +61 -0
  73. package/src/forge/cair/action-parser.ts +314 -0
  74. package/src/forge/cair/action-validator.ts +40 -0
  75. package/src/forge/cair/actions.ts +1818 -0
  76. package/src/forge/cair/format.ts +77 -0
  77. package/src/forge/cair/index.ts +106 -0
  78. package/src/forge/cair/query.ts +478 -0
  79. package/src/forge/cair/snapshot.ts +315 -0
  80. package/src/forge/cair/types.ts +248 -0
  81. package/src/forge/cli/ai.ts +339 -21
  82. package/src/forge/cli/auth.ts +348 -10
  83. package/src/forge/cli/authmd.ts +441 -0
  84. package/src/forge/cli/baseline.ts +112 -0
  85. package/src/forge/cli/build.ts +20 -4
  86. package/src/forge/cli/changed.ts +437 -0
  87. package/src/forge/cli/codex-app-server.ts +877 -0
  88. package/src/forge/cli/commands.ts +1620 -20
  89. package/src/forge/cli/db.ts +209 -2
  90. package/src/forge/cli/deploy.ts +887 -0
  91. package/src/forge/cli/deps.ts +82 -13
  92. package/src/forge/cli/dev.ts +961 -46
  93. package/src/forge/cli/docs.ts +265 -0
  94. package/src/forge/cli/doctor.ts +297 -0
  95. package/src/forge/cli/field-test.ts +329 -0
  96. package/src/forge/cli/handoff.ts +336 -0
  97. package/src/forge/cli/index.ts +1 -0
  98. package/src/forge/cli/last-run.ts +84 -0
  99. package/src/forge/cli/main.ts +107 -3
  100. package/src/forge/cli/new.ts +152 -13
  101. package/src/forge/cli/next-actions.ts +23 -0
  102. package/src/forge/cli/output.ts +389 -6
  103. package/src/forge/cli/parse.ts +1050 -34
  104. package/src/forge/cli/progress.ts +51 -0
  105. package/src/forge/cli/query.ts +32 -0
  106. package/src/forge/cli/release.ts +35 -11
  107. package/src/forge/cli/rls.ts +43 -4
  108. package/src/forge/cli/run.ts +41 -0
  109. package/src/forge/cli/security.ts +112 -0
  110. package/src/forge/cli/self-host.ts +56 -14
  111. package/src/forge/cli/studio.ts +2218 -0
  112. package/src/forge/cli/verify.ts +1455 -32
  113. package/src/forge/cli/windows.ts +23 -0
  114. package/src/forge/cli/workos.ts +1020 -0
  115. package/src/forge/compiler/agent-contract/build.ts +670 -64
  116. package/src/forge/compiler/agent-contract/types.ts +45 -2
  117. package/src/forge/compiler/ai-registry/parse.ts +71 -2
  118. package/src/forge/compiler/api-surface/build.ts +47 -0
  119. package/src/forge/compiler/app-graph/build.ts +112 -9
  120. package/src/forge/compiler/app-graph/extract.ts +107 -0
  121. package/src/forge/compiler/app-graph/module-graph.ts +73 -78
  122. package/src/forge/compiler/app-graph/parser.ts +24 -24
  123. package/src/forge/compiler/app-graph/profile.ts +26 -0
  124. package/src/forge/compiler/app-graph/versions.ts +1 -1
  125. package/src/forge/compiler/classifier/capabilities.ts +3 -2
  126. package/src/forge/compiler/classifier/classify.ts +32 -8
  127. package/src/forge/compiler/classifier/secrets.ts +3 -2
  128. package/src/forge/compiler/classifier/signals.ts +91 -1
  129. package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
  130. package/src/forge/compiler/client-sdk/render-client.ts +295 -13
  131. package/src/forge/compiler/data-graph/parse.ts +20 -4
  132. package/src/forge/compiler/data-graph/sql/ddl.ts +144 -31
  133. package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
  134. package/src/forge/compiler/data-graph/sql/types.ts +1 -0
  135. package/src/forge/compiler/diagnostics/codes.ts +30 -0
  136. package/src/forge/compiler/diagnostics/create.ts +21 -2
  137. package/src/forge/compiler/diagnostics/index.ts +2 -0
  138. package/src/forge/compiler/emitter/barrel.ts +3 -0
  139. package/src/forge/compiler/emitter/render.ts +9 -0
  140. package/src/forge/compiler/external-manifest/registry.ts +205 -0
  141. package/src/forge/compiler/external-manifest/types.ts +91 -0
  142. package/src/forge/compiler/external-manifest/validate.ts +373 -0
  143. package/src/forge/compiler/frontend-graph/build.ts +142 -14
  144. package/src/forge/compiler/integration/add.ts +618 -24
  145. package/src/forge/compiler/integration/plan.ts +43 -12
  146. package/src/forge/compiler/integration/render.ts +29 -0
  147. package/src/forge/compiler/integration/snapshot.ts +2 -0
  148. package/src/forge/compiler/integration/templates/convex.ts +70 -0
  149. package/src/forge/compiler/integration/templates/index.ts +1 -0
  150. package/src/forge/compiler/integration/templates/render.ts +38 -0
  151. package/src/forge/compiler/integration/templates/types.ts +3 -0
  152. package/src/forge/compiler/integration/templates/workos.ts +1219 -0
  153. package/src/forge/compiler/make-registry/build.ts +8 -9
  154. package/src/forge/compiler/orchestrator/fast-check.ts +4 -0
  155. package/src/forge/compiler/orchestrator/generate-lock.ts +14 -3
  156. package/src/forge/compiler/orchestrator/manifest.ts +1 -1
  157. package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
  158. package/src/forge/compiler/orchestrator/plan.ts +247 -10
  159. package/src/forge/compiler/orchestrator/profile.ts +65 -0
  160. package/src/forge/compiler/orchestrator/run.ts +97 -31
  161. package/src/forge/compiler/orchestrator/serialize.ts +33 -8
  162. package/src/forge/compiler/orchestrator/types.ts +1 -1
  163. package/src/forge/compiler/package-graph/compiler.ts +3 -1
  164. package/src/forge/compiler/package-graph/constants.ts +1 -1
  165. package/src/forge/compiler/package-manager/adapter.ts +4 -1
  166. package/src/forge/compiler/package-manager/commands.ts +4 -0
  167. package/src/forge/compiler/package-manager/executor.ts +30 -1
  168. package/src/forge/compiler/package-manager/version.ts +36 -12
  169. package/src/forge/compiler/package-upgrades/planner.ts +155 -18
  170. package/src/forge/compiler/package-upgrades/types.ts +2 -0
  171. package/src/forge/compiler/policy-registry/build.ts +47 -2
  172. package/src/forge/compiler/policy-registry/parse.ts +32 -2
  173. package/src/forge/compiler/recipes/definitions.ts +63 -0
  174. package/src/forge/compiler/recipes/index.ts +2 -0
  175. package/src/forge/compiler/recipes/registry.ts +6 -0
  176. package/src/forge/compiler/test-graph/build.ts +11 -3
  177. package/src/forge/compiler/types/app-graph.ts +8 -2
  178. package/src/forge/compiler/types/cli.ts +75 -1
  179. package/src/forge/compiler/types/dev-manifest.ts +4 -0
  180. package/src/forge/compiler/types/emit.ts +2 -0
  181. package/src/forge/compiler/types/frontend-graph.ts +2 -2
  182. package/src/forge/compiler/types/integration.ts +1 -0
  183. package/src/forge/compiler/types/package-graph.ts +6 -0
  184. package/src/forge/compiler/types/policy-registry.ts +3 -1
  185. package/src/forge/delta/classifier.ts +52 -0
  186. package/src/forge/delta/explain.ts +238 -0
  187. package/src/forge/delta/git-observer.ts +43 -0
  188. package/src/forge/delta/ids.ts +44 -0
  189. package/src/forge/delta/index.ts +25 -0
  190. package/src/forge/delta/recorder.ts +540 -0
  191. package/src/forge/delta/redaction.ts +50 -0
  192. package/src/forge/delta/schema.ts +240 -0
  193. package/src/forge/delta/session.ts +142 -0
  194. package/src/forge/delta/status.ts +1202 -0
  195. package/src/forge/delta/store.ts +3284 -0
  196. package/src/forge/delta/timeline.ts +178 -0
  197. package/src/forge/dev/server.ts +808 -17
  198. package/src/forge/dev/types.ts +15 -1
  199. package/src/forge/dev/watch.ts +17 -7
  200. package/src/forge/dev-console/cycle.ts +280 -33
  201. package/src/forge/dev-console/types.ts +47 -1
  202. package/src/forge/impact/index.ts +204 -9
  203. package/src/forge/impact/types.ts +33 -1
  204. package/src/forge/intent/index.ts +35 -16
  205. package/src/forge/make/fields.ts +26 -0
  206. package/src/forge/make/index.ts +40 -6
  207. package/src/forge/make/templates.ts +155 -2
  208. package/src/forge/make/types.ts +2 -1
  209. package/src/forge/policy.ts +1 -1
  210. package/src/forge/react/index.ts +160 -2
  211. package/src/forge/refactor/index.ts +1 -0
  212. package/src/forge/repair/rules/index.ts +2 -2
  213. package/src/forge/review/index.ts +158 -12
  214. package/src/forge/review/types.ts +15 -0
  215. package/src/forge/runtime/auth/config.ts +17 -0
  216. package/src/forge/runtime/auth/evaluate.ts +15 -2
  217. package/src/forge/runtime/auth/resolve.ts +61 -6
  218. package/src/forge/runtime/auth/types.ts +1 -0
  219. package/src/forge/runtime/db/factory.ts +1 -3
  220. package/src/forge/runtime/db/generated-client.ts +13 -2
  221. package/src/forge/runtime/db/memory-adapter.ts +139 -32
  222. package/src/forge/runtime/db/pglite-adapter.ts +263 -2
  223. package/src/forge/runtime/db/postgres-adapter.ts +6 -3
  224. package/src/forge/runtime/executor.ts +129 -16
  225. package/src/forge/runtime/external/bridge.ts +649 -0
  226. package/src/forge/runtime/runner/run-entry.ts +16 -7
  227. package/src/forge/runtime/telemetry/buffer.ts +4 -1
  228. package/src/forge/runtime/telemetry/scrubber.ts +35 -5
  229. package/src/forge/runtime/webhooks/security.ts +12 -7
  230. package/src/forge/server.ts +17 -3
  231. package/src/forge/ui/index.ts +209 -0
  232. package/src/forge/ui/types.ts +1 -0
  233. package/src/forge/version.ts +1 -1
  234. package/src/forge/vue/index.ts +422 -0
  235. package/src/forge/workspace/baseline.ts +112 -0
  236. package/src/forge/workspace/change-summary.ts +250 -0
  237. package/src/forge/workspace/forge-cli.ts +42 -0
  238. package/src/forge/workspace/git-summary.ts +391 -0
  239. package/templates/agent-workroom/AGENTS.md +29 -0
  240. package/templates/agent-workroom/README.md +34 -0
  241. package/templates/agent-workroom/forge.config.ts +3 -0
  242. package/templates/agent-workroom/package.json +33 -0
  243. package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
  244. package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
  245. package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
  246. package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
  247. package/templates/agent-workroom/src/forge/schema.ts +54 -0
  248. package/templates/agent-workroom/src/policies.ts +6 -0
  249. package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
  250. package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
  251. package/templates/agent-workroom/tsconfig.json +16 -0
  252. package/templates/agent-workroom/web/index.html +12 -0
  253. package/templates/agent-workroom/web/package.json +21 -0
  254. package/templates/agent-workroom/web/src/App.tsx +345 -0
  255. package/templates/agent-workroom/web/src/lib/forge.ts +13 -0
  256. package/templates/agent-workroom/web/src/main.tsx +13 -0
  257. package/templates/agent-workroom/web/src/styles.css +545 -0
  258. package/templates/agent-workroom/web/tsconfig.json +27 -0
  259. package/templates/b2b-support-web/package.json +1 -0
  260. package/templates/b2b-support-web/web/package.json +1 -1
  261. package/templates/minimal-web/package.json +1 -1
  262. package/templates/minimal-web/web/package.json +2 -2
  263. package/templates/nuxt-web/.vscode/settings.json +14 -0
  264. package/templates/nuxt-web/README.md +30 -0
  265. package/templates/nuxt-web/forge.config.ts +3 -0
  266. package/templates/nuxt-web/package.json +33 -0
  267. package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -0
  268. package/templates/nuxt-web/src/commands/createNote.ts +26 -0
  269. package/templates/nuxt-web/src/forge/schema.ts +12 -0
  270. package/templates/nuxt-web/src/policies.ts +6 -0
  271. package/templates/nuxt-web/src/queries/listNotes.ts +8 -0
  272. package/templates/nuxt-web/src/queries/liveNotes.ts +8 -0
  273. package/templates/nuxt-web/tsconfig.json +17 -0
  274. package/templates/nuxt-web/web/app.vue +67 -0
  275. package/templates/nuxt-web/web/components/LiveNotes.vue +89 -0
  276. package/templates/nuxt-web/web/components/NoteComposer.vue +100 -0
  277. package/templates/nuxt-web/web/composables/forge.ts +13 -0
  278. package/templates/nuxt-web/web/composables/useNotes.ts +24 -0
  279. package/templates/nuxt-web/web/nuxt.config.ts +11 -0
  280. package/templates/nuxt-web/web/package.json +18 -0
  281. package/templates/nuxt-web/web/plugins/forge.client.ts +10 -0
  282. package/templates/nuxt-web/web/plugins/forge.server.ts +10 -0
  283. package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -0
  284. package/templates/nuxt-web/web/tsconfig.json +6 -0
  285. package/src/forge/_generated/actionSubscriptions.json +0 -2
  286. package/src/forge/_generated/actionSubscriptions.ts +0 -10
  287. package/src/forge/_generated/agentAdapterManifest.json +0 -2
  288. package/src/forge/_generated/agentAdapterManifest.ts +0 -73
  289. package/src/forge/_generated/agentContract.json +0 -2
  290. package/src/forge/_generated/agentContract.ts +0 -7829
  291. package/src/forge/_generated/agentQuickstart.md +0 -34
  292. package/src/forge/_generated/agentTools.json +0 -2
  293. package/src/forge/_generated/agentTools.md +0 -16
  294. package/src/forge/_generated/agentTools.ts +0 -12
  295. package/src/forge/_generated/aiContext.ts +0 -125
  296. package/src/forge/_generated/aiModels.json +0 -2
  297. package/src/forge/_generated/aiModels.ts +0 -51
  298. package/src/forge/_generated/aiProviders.json +0 -2
  299. package/src/forge/_generated/aiProviders.ts +0 -23
  300. package/src/forge/_generated/aiRegistry.json +0 -2
  301. package/src/forge/_generated/aiRegistry.ts +0 -31
  302. package/src/forge/_generated/api.json +0 -2
  303. package/src/forge/_generated/api.ts +0 -8
  304. package/src/forge/_generated/appGraph.json +0 -2
  305. package/src/forge/_generated/appGraph.ts +0 -14919
  306. package/src/forge/_generated/appMap.md +0 -55
  307. package/src/forge/_generated/artifactManifest.json +0 -2
  308. package/src/forge/_generated/artifactManifest.ts +0 -7
  309. package/src/forge/_generated/authClaims.json +0 -2
  310. package/src/forge/_generated/authClaims.ts +0 -13
  311. package/src/forge/_generated/authConfig.json +0 -2
  312. package/src/forge/_generated/authConfig.ts +0 -17
  313. package/src/forge/_generated/authContext.ts +0 -23
  314. package/src/forge/_generated/authRegistry.json +0 -2
  315. package/src/forge/_generated/authRegistry.ts +0 -25
  316. package/src/forge/_generated/buildInfo.json +0 -2
  317. package/src/forge/_generated/buildInfo.ts +0 -9
  318. package/src/forge/_generated/capabilityMap.json +0 -2
  319. package/src/forge/_generated/capabilityMap.md +0 -15
  320. package/src/forge/_generated/capabilityMap.ts +0 -17
  321. package/src/forge/_generated/client.ts +0 -282
  322. package/src/forge/_generated/clientApi.ts +0 -9
  323. package/src/forge/_generated/clientManifest.json +0 -2
  324. package/src/forge/_generated/clientManifest.ts +0 -39
  325. package/src/forge/_generated/clientTypes.ts +0 -78
  326. package/src/forge/_generated/configRegistry.json +0 -2
  327. package/src/forge/_generated/configRegistry.ts +0 -4
  328. package/src/forge/_generated/dataGraph.json +0 -2
  329. package/src/forge/_generated/dataGraph.ts +0 -8
  330. package/src/forge/_generated/db.json +0 -2
  331. package/src/forge/_generated/db.ts +0 -2
  332. package/src/forge/_generated/dbSecurityManifest.json +0 -2
  333. package/src/forge/_generated/dbSecurityManifest.ts +0 -15
  334. package/src/forge/_generated/dbSessionContext.json +0 -2
  335. package/src/forge/_generated/dbSessionContext.ts +0 -39
  336. package/src/forge/_generated/deployManifest.json +0 -2
  337. package/src/forge/_generated/deployManifest.ts +0 -14
  338. package/src/forge/_generated/devManifest.json +0 -2
  339. package/src/forge/_generated/devManifest.ts +0 -62
  340. package/src/forge/_generated/envSchema.json +0 -2
  341. package/src/forge/_generated/envSchema.ts +0 -59
  342. package/src/forge/_generated/frontendGraph.json +0 -2
  343. package/src/forge/_generated/frontendGraph.ts +0 -27
  344. package/src/forge/_generated/importGuards.json +0 -2
  345. package/src/forge/_generated/importGuards.ts +0 -686
  346. package/src/forge/_generated/index.ts +0 -68
  347. package/src/forge/_generated/liveProductionManifest.json +0 -2
  348. package/src/forge/_generated/liveProductionManifest.ts +0 -23
  349. package/src/forge/_generated/liveProtocol.json +0 -2
  350. package/src/forge/_generated/liveProtocol.ts +0 -21
  351. package/src/forge/_generated/liveQueryRegistry.json +0 -2
  352. package/src/forge/_generated/liveQueryRegistry.ts +0 -9
  353. package/src/forge/_generated/liveTransportConfig.json +0 -2
  354. package/src/forge/_generated/liveTransportConfig.ts +0 -19
  355. package/src/forge/_generated/makeRegistry.json +0 -2
  356. package/src/forge/_generated/makeRegistry.ts +0 -177
  357. package/src/forge/_generated/makeTemplates.json +0 -2
  358. package/src/forge/_generated/makeTemplates.ts +0 -66
  359. package/src/forge/_generated/mockMap.json +0 -2
  360. package/src/forge/_generated/mockMap.ts +0 -7
  361. package/src/forge/_generated/operationPlaybooks.md +0 -167
  362. package/src/forge/_generated/packageGraph.json +0 -2
  363. package/src/forge/_generated/packageGraph.ts +0 -249334
  364. package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
  365. package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
  366. package/src/forge/_generated/permissionMatrix.json +0 -2
  367. package/src/forge/_generated/permissionMatrix.ts +0 -7
  368. package/src/forge/_generated/policyRegistry.json +0 -2
  369. package/src/forge/_generated/policyRegistry.ts +0 -11
  370. package/src/forge/_generated/queryRegistry.json +0 -2
  371. package/src/forge/_generated/queryRegistry.ts +0 -9
  372. package/src/forge/_generated/react.d.ts +0 -22
  373. package/src/forge/_generated/react.ts +0 -29
  374. package/src/forge/_generated/reactManifest.json +0 -2
  375. package/src/forge/_generated/reactManifest.ts +0 -19
  376. package/src/forge/_generated/rlsPolicies.json +0 -2
  377. package/src/forge/_generated/rlsPolicies.sql +0 -34
  378. package/src/forge/_generated/rlsPolicies.ts +0 -6
  379. package/src/forge/_generated/runtimeGraph.json +0 -2
  380. package/src/forge/_generated/runtimeGraph.ts +0 -8
  381. package/src/forge/_generated/runtimeMatrix.json +0 -2
  382. package/src/forge/_generated/runtimeMatrix.ts +0 -334130
  383. package/src/forge/_generated/runtimeRegistry.ts +0 -2
  384. package/src/forge/_generated/runtimeRules.md +0 -91
  385. package/src/forge/_generated/secretRegistry.json +0 -2
  386. package/src/forge/_generated/secretRegistry.ts +0 -50
  387. package/src/forge/_generated/secretsContext.ts +0 -11
  388. package/src/forge/_generated/serverApi.ts +0 -10
  389. package/src/forge/_generated/sourceMapManifest.json +0 -2
  390. package/src/forge/_generated/sourceMapManifest.ts +0 -7
  391. package/src/forge/_generated/sqlPlan.json +0 -2
  392. package/src/forge/_generated/sqlPlan.ts +0 -88
  393. package/src/forge/_generated/subscriptionManifest.json +0 -2
  394. package/src/forge/_generated/subscriptionManifest.ts +0 -7
  395. package/src/forge/_generated/symbolicationManifest.json +0 -2
  396. package/src/forge/_generated/symbolicationManifest.ts +0 -17
  397. package/src/forge/_generated/telemetryRegistry.json +0 -2
  398. package/src/forge/_generated/telemetryRegistry.ts +0 -9
  399. package/src/forge/_generated/telemetrySinks.json +0 -2
  400. package/src/forge/_generated/telemetrySinks.ts +0 -11
  401. package/src/forge/_generated/tenantScope.json +0 -2
  402. package/src/forge/_generated/tenantScope.ts +0 -8
  403. package/src/forge/_generated/testGraph.json +0 -2
  404. package/src/forge/_generated/testGraph.ts +0 -3430
  405. package/src/forge/_generated/testPlanRegistry.json +0 -2
  406. package/src/forge/_generated/testPlanRegistry.ts +0 -33
  407. package/src/forge/_generated/uiRoutes.json +0 -2
  408. package/src/forge/_generated/uiRoutes.ts +0 -16
  409. package/src/forge/_generated/uiScenarios.json +0 -2
  410. package/src/forge/_generated/uiScenarios.ts +0 -30
  411. package/src/forge/_generated/uiTestManifest.json +0 -2
  412. package/src/forge/_generated/uiTestManifest.ts +0 -27
  413. package/src/forge/_generated/workflowRegistry.json +0 -2
  414. package/src/forge/_generated/workflowRegistry.ts +0 -9
  415. package/src/forge/_generated/workflowSubscriptions.json +0 -2
  416. 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;
@@ -119,6 +344,104 @@ function dependencyFromInstall(
119
344
  };
120
345
  }
121
346
 
347
+ function fileHashOrNull(path: string): string | null {
348
+ if (!nodeFileSystem.exists(path)) {
349
+ return null;
350
+ }
351
+ return hashStable(nodeFileSystem.readText(path) ?? "");
352
+ }
353
+
354
+ function snapshotPackageManagerFiles(
355
+ workspaceRoot: string,
356
+ pm: PackageManagerAdapter,
357
+ extraPaths: string[] = [],
358
+ ): Map<string, string | null> {
359
+ const paths = [...new Set(["package.json", pm.lockfile, ...extraPaths])];
360
+ return new Map(
361
+ paths.map((path) => [
362
+ path,
363
+ fileHashOrNull(join(workspaceRoot, path)),
364
+ ]),
365
+ );
366
+ }
367
+
368
+ function changedPackageManagerFiles(
369
+ workspaceRoot: string,
370
+ before: Map<string, string | null>,
371
+ ): string[] {
372
+ const changed: string[] = [];
373
+ for (const [path, previousHash] of before) {
374
+ if (fileHashOrNull(join(workspaceRoot, path)) !== previousHash) {
375
+ changed.push(path);
376
+ }
377
+ }
378
+ return changed.sort();
379
+ }
380
+
381
+ function workosFrontendWorkspace(workspaceRoot: string): string | undefined {
382
+ return findFrontendWorkspace(workspaceRoot);
383
+ }
384
+
385
+ function connectWorkOSReactRoot(workspaceRoot: string, frontendWorkspace: string): {
386
+ changed: string[];
387
+ warnings: Diagnostic[];
388
+ } {
389
+ const mainRel = `${frontendWorkspace}/src/main.tsx`;
390
+ const mainPath = join(workspaceRoot, mainRel);
391
+ const current = nodeFileSystem.readText(mainPath);
392
+ if (current === null) {
393
+ return {
394
+ changed: [],
395
+ warnings: [
396
+ createDiagnostic({
397
+ severity: "warning",
398
+ code: "FORGE_WORKOS_AUTHKIT_ROOT_NOT_FOUND",
399
+ message: `generated WorkOS AuthKit bridge, but ${mainRel} was not found`,
400
+ fixHint: "Wrap the web app root with ForgeWorkOSAuthProvider from ./lib/workos-auth.",
401
+ suggestedCommands: ["forge workos doctor --json", "forge inspect ui --json"],
402
+ }),
403
+ ],
404
+ };
405
+ }
406
+ if (current.includes("ForgeWorkOSAuthProvider")) {
407
+ return { changed: [], warnings: [] };
408
+ }
409
+
410
+ const canRewriteDefaultViteRoot =
411
+ current.includes('import { ForgeProvider, forgeUrl } from "./lib/forge";') &&
412
+ current.includes("<ForgeProvider url={forgeUrl} devAuth>") &&
413
+ current.includes("</ForgeProvider>");
414
+
415
+ if (!canRewriteDefaultViteRoot) {
416
+ return {
417
+ changed: [],
418
+ warnings: [
419
+ createDiagnostic({
420
+ severity: "warning",
421
+ code: "FORGE_WORKOS_AUTHKIT_ROOT_CUSTOM",
422
+ message: `generated WorkOS AuthKit bridge, but ${mainRel} is custom and was not rewritten automatically`,
423
+ fixHint: "Import ForgeWorkOSAuthProvider from ./lib/workos-auth and wrap the app root with it so AuthKit tokens are passed to ForgeProvider.",
424
+ suggestedCommands: ["forge workos doctor --json", "forge inspect ui --json"],
425
+ }),
426
+ ],
427
+ };
428
+ }
429
+
430
+ const next = current
431
+ .replace(
432
+ 'import { ForgeProvider, forgeUrl } from "./lib/forge";',
433
+ 'import { ForgeWorkOSAuthProvider } from "./lib/workos-auth";',
434
+ )
435
+ .replace("<ForgeProvider url={forgeUrl} devAuth>", "<ForgeWorkOSAuthProvider>")
436
+ .replace("</ForgeProvider>", "</ForgeWorkOSAuthProvider>");
437
+
438
+ if (next !== current) {
439
+ nodeFileSystem.writeText(mainPath, next);
440
+ return { changed: [mainRel], warnings: [] };
441
+ }
442
+ return { changed: [], warnings: [] };
443
+ }
444
+
122
445
  async function analyzeRecipePackages(
123
446
  recipe: NonNullable<ReturnType<typeof resolveRecipe>>,
124
447
  ctx: ReturnType<typeof discover>,
@@ -258,24 +581,85 @@ export async function forgeAdd(
258
581
  alias: string,
259
582
  options: ForgeAddOptions,
260
583
  ): Promise<ForgeAddResult> {
261
- const normalized = alias.trim().toLowerCase();
584
+ const packageRequestResult = normalizePackageRequest(alias, options);
585
+ const packageRequest = packageRequestResult.request;
586
+ const effectiveOptions: ForgeAddOptions = {
587
+ ...options,
588
+ installWorkspace: packageRequest.installWorkspace,
589
+ };
590
+ const packageModeRequested =
591
+ options.mode === "package" ||
592
+ packageRequest.forcePackageMode ||
593
+ options.packageTarget !== undefined;
594
+ if (packageRequestResult.error && packageModeRequested) {
595
+ return finalizeAddResult({
596
+ alias: packageRequest.spec,
597
+ mode: "package",
598
+ target: packageRequest.installWorkspace ?? packageRequest.packageTarget,
599
+ packageTarget: packageRequest.packageTarget,
600
+ packageTargetReason: packageRequest.packageTargetReason,
601
+ packageSpec: packageRequest.spec,
602
+ packageName: parsePackageName(packageRequest.spec),
603
+ changed: [],
604
+ unchanged: [],
605
+ warnings: [],
606
+ errors: [packageRequestResult.error],
607
+ exitCode: 1,
608
+ failureKind: "invalid_workspace",
609
+ });
610
+ }
611
+ if (options.mode === "integration" && (packageRequest.forcePackageMode || options.packageTarget)) {
612
+ const error = createDiagnostic({
613
+ severity: "error",
614
+ code: "FORGE_ADD_SCOPED_INTEGRATION",
615
+ message: "frontend/backend package targets only apply to normal npm package installs, not explicit integration recipes",
616
+ fixHint: "Use forge add package <spec> --frontend, forge add frontend:<spec>, or remove the frontend/backend target for an integration recipe.",
617
+ suggestedCommands: [
618
+ `forge add package ${packageRequest.spec} --frontend --dry-run --json`,
619
+ `forge add integration ${packageRequest.spec} --dry-run --json`,
620
+ ],
621
+ });
622
+ return finalizeAddResult({
623
+ alias: packageRequest.spec,
624
+ mode: "integration",
625
+ changed: [],
626
+ unchanged: [],
627
+ warnings: [],
628
+ errors: [error],
629
+ exitCode: 1,
630
+ failureKind: "invalid_target",
631
+ });
632
+ }
633
+
634
+ const normalized = packageRequest.spec.trim().toLowerCase();
262
635
  const recipe = resolveRecipe(normalized);
636
+ const mode = options.mode ?? "auto";
637
+
638
+ if (packageModeRequested) {
639
+ return forgeAddPackage(packageRequest.spec, effectiveOptions, packageRequest);
640
+ }
641
+
642
+ if (mode === "auto" && (!isReferenceAlias(normalized) || recipe === null)) {
643
+ return forgeAddPackage(packageRequest.spec, effectiveOptions, packageRequest);
644
+ }
263
645
 
264
646
  if (!isReferenceAlias(normalized) || recipe === null) {
265
647
  const error = createDiagnostic({
266
648
  severity: "error",
267
649
  code: "FORGE_UNKNOWN_ALIAS",
268
- message: `unknown integration alias '${alias}'; supported: stripe, posthog, sentry, zod, ai`,
650
+ message: `unknown integration alias '${alias}'; supported: stripe, posthog, sentry, zod, convex, workos, ai. For npm packages, use 'forge add package ${alias}' or 'forge add ${alias}'.`,
651
+ suggestedCommands: [`forge add package ${alias} --dry-run --json`, "forge add --help"],
269
652
  });
270
- return {
653
+ return finalizeAddResult({
271
654
  alias: normalized,
655
+ mode: "integration",
272
656
  changed: [],
273
657
  unchanged: [],
274
658
  warnings: [],
275
659
  errors: [error],
276
660
  exitCode: 1,
277
661
  failureKind: "unknown_alias",
278
- };
662
+ });
279
663
  }
280
664
 
281
665
  const pm =
@@ -283,7 +667,7 @@ export async function forgeAdd(
283
667
  detectAndCreatePackageManagerAdapter(options.workspaceRoot);
284
668
 
285
669
  if (options.dryRun) {
286
- const ctx = discover({ workspaceRoot: options.workspaceRoot });
670
+ const ctx = discover({ workspaceRoot: effectiveOptions.workspaceRoot });
287
671
  let installRoot = options.workspaceRoot;
288
672
 
289
673
  try {
@@ -302,7 +686,7 @@ export async function forgeAdd(
302
686
  recipe,
303
687
  ctx,
304
688
  installRoot,
305
- options,
689
+ effectiveOptions,
306
690
  );
307
691
  warnings.push(
308
692
  createDiagnostic({
@@ -312,15 +696,17 @@ export async function forgeAdd(
312
696
  }),
313
697
  );
314
698
 
315
- return {
699
+ return finalizeAddResult({
316
700
  alias: normalized,
701
+ mode: "integration",
702
+ ...recipeResultMetadata(recipe),
317
703
  changed: [...emitPlan.files.map((file) => file.path), "forge.lock"],
318
704
  unchanged: [],
319
705
  warnings,
320
706
  errors,
321
707
  exitCode: errors.length > 0 ? 1 : 0,
322
708
  failureKind: failureKind(errors),
323
- };
709
+ });
324
710
  }
325
711
 
326
712
  const { emitPlan, warnings, errors } = await buildAddPlan(
@@ -328,29 +714,43 @@ export async function forgeAdd(
328
714
  recipe,
329
715
  ctx,
330
716
  installRoot,
331
- options,
717
+ effectiveOptions,
332
718
  );
333
719
 
334
- return {
720
+ return finalizeAddResult({
335
721
  alias: normalized,
722
+ mode: "integration",
723
+ ...recipeResultMetadata(recipe),
336
724
  changed: [...emitPlan.files.map((file) => file.path), "forge.lock"],
337
725
  unchanged: [],
338
726
  warnings,
339
727
  errors,
340
728
  exitCode: errors.length > 0 ? 1 : 0,
341
729
  failureKind: failureKind(errors),
342
- };
730
+ });
343
731
  }
344
732
 
345
733
  const snapshot = snapshotVersionControlled(options.workspaceRoot);
346
734
 
347
735
  try {
736
+ const frontendWorkspace = normalized === "workos" ? workosFrontendWorkspace(options.workspaceRoot) : undefined;
737
+ const packageManagerBefore = snapshotPackageManagerFiles(
738
+ options.workspaceRoot,
739
+ pm,
740
+ frontendWorkspace ? [packageJsonRelativeFor(frontendWorkspace)] : [],
741
+ );
348
742
  for (const pkg of recipe.packages) {
349
743
  await pm.add(pkg.packageName, {
350
744
  cwd: options.workspaceRoot,
351
745
  ignoreScripts: !options.allowScripts,
352
746
  });
353
747
  }
748
+ if (frontendWorkspace) {
749
+ await pm.add("@workos-inc/authkit-react", {
750
+ cwd: join(options.workspaceRoot, frontendWorkspace),
751
+ ignoreScripts: !options.allowScripts,
752
+ });
753
+ }
354
754
 
355
755
  const ctx = discover({ workspaceRoot: options.workspaceRoot });
356
756
  const { emitPlan, warnings, errors: analyzeErrors } = await buildAddPlan(
@@ -363,15 +763,17 @@ export async function forgeAdd(
363
763
 
364
764
  if (analyzeErrors.length > 0) {
365
765
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
366
- return {
766
+ return finalizeAddResult({
367
767
  alias: normalized,
768
+ mode: "integration",
769
+ ...recipeResultMetadata(recipe),
368
770
  changed: [],
369
771
  unchanged: [],
370
772
  warnings,
371
773
  errors: analyzeErrors,
372
774
  exitCode: 1,
373
775
  failureKind: failureKind(analyzeErrors),
374
- };
776
+ });
375
777
  }
376
778
 
377
779
  const emitResult = await emit(emitPlan, {
@@ -379,20 +781,26 @@ export async function forgeAdd(
379
781
  mode: "write",
380
782
  });
381
783
 
382
- const warningsCombined = [...warnings, ...emitResult.warnings];
784
+ const workosWeb = normalized === "workos" && frontendWorkspace
785
+ ? connectWorkOSReactRoot(options.workspaceRoot, frontendWorkspace)
786
+ : { changed: [] as string[], warnings: [] as Diagnostic[] };
787
+
788
+ const warningsCombined = [...warnings, ...emitResult.warnings, ...workosWeb.warnings];
383
789
  const errors = [...analyzeErrors, ...emitResult.errors];
384
790
 
385
791
  if (errors.length > 0) {
386
792
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
387
- return {
793
+ return finalizeAddResult({
388
794
  alias: normalized,
795
+ mode: "integration",
796
+ ...recipeResultMetadata(recipe),
389
797
  changed: [],
390
798
  unchanged: [],
391
799
  warnings: warningsCombined,
392
800
  errors,
393
801
  exitCode: 1,
394
802
  failureKind: failureKind(errors),
395
- };
803
+ });
396
804
  }
397
805
 
398
806
  const integrityErrors = verifyLockIntegrity(
@@ -401,15 +809,17 @@ export async function forgeAdd(
401
809
  );
402
810
  if (integrityErrors.length > 0) {
403
811
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
404
- return {
812
+ return finalizeAddResult({
405
813
  alias: normalized,
814
+ mode: "integration",
815
+ ...recipeResultMetadata(recipe),
406
816
  changed: [],
407
817
  unchanged: [],
408
818
  warnings: warningsCombined,
409
819
  errors: integrityErrors,
410
820
  exitCode: 1,
411
821
  failureKind: "lock_integrity",
412
- };
822
+ });
413
823
  }
414
824
 
415
825
  const manifest = loadManifest(ctx.cacheDir);
@@ -435,14 +845,20 @@ export async function forgeAdd(
435
845
  ),
436
846
  );
437
847
 
438
- return {
848
+ return finalizeAddResult({
439
849
  alias: normalized,
440
- changed: emitResult.changed,
850
+ mode: "integration",
851
+ ...recipeResultMetadata(recipe),
852
+ changed: [
853
+ ...changedPackageManagerFiles(options.workspaceRoot, packageManagerBefore),
854
+ ...emitResult.changed,
855
+ ...workosWeb.changed,
856
+ ],
441
857
  unchanged: emitResult.unchanged,
442
858
  warnings: warningsCombined,
443
859
  errors: [],
444
860
  exitCode: 0,
445
- };
861
+ });
446
862
  } catch (error) {
447
863
  restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
448
864
 
@@ -459,15 +875,193 @@ export async function forgeAdd(
459
875
  message: `forge add failed: ${message}`,
460
876
  });
461
877
 
462
- return {
878
+ return finalizeAddResult({
463
879
  alias: normalized,
880
+ mode: "integration",
881
+ ...recipeResultMetadata(recipe),
464
882
  changed: [],
465
883
  unchanged: [],
466
884
  warnings: [],
467
885
  errors: [diagnostic],
468
886
  exitCode: 1,
469
887
  failureKind: "install_failed",
470
- };
888
+ });
889
+ }
890
+ }
891
+
892
+ async function forgeAddPackage(
893
+ spec: string,
894
+ options: ForgeAddOptions,
895
+ request = normalizePackageRequest(spec, options).request,
896
+ ): Promise<ForgeAddResult> {
897
+ const normalized = request.spec.trim();
898
+ const packageName = parsePackageName(normalized);
899
+ const target = resolveInstallRoot(options);
900
+ if (target.error) {
901
+ return finalizeAddResult({
902
+ alias: normalized,
903
+ mode: "package",
904
+ target: target.target,
905
+ packageTarget: request.packageTarget,
906
+ packageTargetReason: request.packageTargetReason,
907
+ changed: [],
908
+ unchanged: [],
909
+ warnings: [],
910
+ errors: [target.error],
911
+ exitCode: 1,
912
+ failureKind: "invalid_workspace",
913
+ });
914
+ }
915
+
916
+ const pm =
917
+ options.pmAdapter ??
918
+ detectAndCreatePackageManagerAdapter(options.workspaceRoot);
919
+ const packageManagerCwd = target.installRoot;
920
+ const semanticInstallWorkspace = target.target === "root" ? undefined : target.target;
921
+ const installCommand = buildAddCommand(pm.name, normalized, {
922
+ ignoreScripts: !options.allowScripts,
923
+ workspace: undefined,
924
+ });
925
+ const avoidedManualCommand = installCommand.join(" ");
926
+ const installPlan = {
927
+ packageSpec: normalized,
928
+ packageName,
929
+ packageManager: pm.name,
930
+ installCommand,
931
+ nativeInstallCommand: installCommand,
932
+ avoidedManualCommand,
933
+ installCwd: packageManagerCwd.replace(/\\/g, "/"),
934
+ packageTarget: request.packageTarget,
935
+ packageTargetReason: request.packageTargetReason,
936
+ ...(semanticInstallWorkspace ? { installWorkspace: semanticInstallWorkspace } : {}),
937
+ };
938
+
939
+ if (options.dryRun) {
940
+ try {
941
+ await pm.dryRunAdd(normalized, {
942
+ cwd: packageManagerCwd,
943
+ ignoreScripts: !options.allowScripts,
944
+ workspace: undefined,
945
+ });
946
+ } catch (error) {
947
+ const message =
948
+ error instanceof PackageManagerCommandError
949
+ ? error.message
950
+ : error instanceof Error
951
+ ? error.message
952
+ : String(error);
953
+ const diagnostic = createDiagnostic({
954
+ severity: "error",
955
+ code: "FORGE_ADD_INSTALL_FAILED",
956
+ message: `forge add package dry-run failed: ${message}`,
957
+ });
958
+ return finalizeAddResult({
959
+ alias: normalized,
960
+ mode: "package",
961
+ target: target.target,
962
+ ...installPlan,
963
+ changed: [],
964
+ unchanged: [],
965
+ warnings: [],
966
+ errors: [diagnostic],
967
+ exitCode: 1,
968
+ failureKind: "install_failed",
969
+ });
970
+ }
971
+
972
+ return finalizeAddResult({
973
+ alias: normalized,
974
+ mode: "package",
975
+ target: target.target,
976
+ ...installPlan,
977
+ changed: [
978
+ packageJsonRelativeFor(target.target === "root" ? undefined : target.target),
979
+ ],
980
+ unchanged: [],
981
+ warnings: [],
982
+ errors: [],
983
+ exitCode: 0,
984
+ });
985
+ }
986
+
987
+ const snapshot = snapshotVersionControlled(
988
+ options.workspaceRoot,
989
+ target.extraSnapshotPaths,
990
+ );
991
+
992
+ try {
993
+ await pm.add(normalized, {
994
+ cwd: packageManagerCwd,
995
+ ignoreScripts: !options.allowScripts,
996
+ workspace: undefined,
997
+ });
998
+
999
+ const generated = await runGenerate({
1000
+ workspaceRoot: options.workspaceRoot,
1001
+ check: false,
1002
+ dryRun: false,
1003
+ json: options.json,
1004
+ concurrency: 4,
1005
+ });
1006
+
1007
+ if (generated.exitCode !== 0) {
1008
+ restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
1009
+ return finalizeAddResult({
1010
+ alias: normalized,
1011
+ mode: "package",
1012
+ target: target.target,
1013
+ ...installPlan,
1014
+ changed: [],
1015
+ unchanged: [],
1016
+ warnings: generated.warnings,
1017
+ errors: generated.errors,
1018
+ exitCode: 1,
1019
+ failureKind: generated.failureKind,
1020
+ });
1021
+ }
1022
+
1023
+ return finalizeAddResult({
1024
+ alias: normalized,
1025
+ mode: "package",
1026
+ target: target.target,
1027
+ ...installPlan,
1028
+ changed: [
1029
+ packageJsonRelativeFor(target.target === "root" ? undefined : target.target),
1030
+ ...generated.changed,
1031
+ ],
1032
+ unchanged: generated.unchanged,
1033
+ warnings: generated.warnings,
1034
+ errors: generated.errors,
1035
+ exitCode: 0,
1036
+ });
1037
+ } catch (error) {
1038
+ restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
1039
+
1040
+ const message =
1041
+ error instanceof PackageManagerCommandError
1042
+ ? error.message
1043
+ : error instanceof Error
1044
+ ? error.message
1045
+ : String(error);
1046
+
1047
+ const diagnostic = createDiagnostic({
1048
+ severity: "error",
1049
+ code: "FORGE_ADD_INSTALL_FAILED",
1050
+ message: `forge add package failed: ${message}`,
1051
+ });
1052
+
1053
+ return finalizeAddResult({
1054
+ alias: normalized,
1055
+ mode: "package",
1056
+ target: target.target,
1057
+ ...installPlan,
1058
+ changed: [],
1059
+ unchanged: [],
1060
+ warnings: [],
1061
+ errors: [diagnostic],
1062
+ exitCode: 1,
1063
+ failureKind: "install_failed",
1064
+ });
471
1065
  }
472
1066
  }
473
1067