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,8 +1,10 @@
1
1
  import { nodeFileSystem } from "../compiler/fs/index.ts";
2
- import { join } from "node:path";
2
+ import { spawnSync } from "node:child_process";
3
+ import { join, resolve } from "node:path";
3
4
  import { stripDeterministicHeader } from "../compiler/primitives/header.ts";
4
5
  import { classify } from "../compiler/classifier/classify.ts";
5
6
  import { buildRuntimeMatrix } from "../compiler/classifier/runtime-matrix.ts";
7
+ import { FORGE_RELEASE_PACKAGE_PACK_FAILED } from "../compiler/diagnostics/codes.ts";
6
8
  import { createDiagnostic } from "../compiler/diagnostics/create.ts";
7
9
  import { forgeAdd } from "../compiler/integration/add.ts";
8
10
  import { checkImportGuards } from "../compiler/guards/check-import-guards.ts";
@@ -29,10 +31,14 @@ import type {
29
31
  } from "../compiler/types/cli.ts";
30
32
  import type { RuntimeMatrix } from "../compiler/types/runtime-matrix.ts";
31
33
  import type { FrontendGraph } from "../compiler/types/frontend-graph.ts";
34
+ import type { DataGraph } from "../compiler/types/data-graph.ts";
35
+ import type { SqlPlan } from "../compiler/data-graph/sql/types.ts";
36
+ import type { TableMapEntry } from "../compiler/data-graph/sql/serialize.ts";
32
37
  import { GENERATED_DIR } from "../compiler/emitter/constants.ts";
33
38
  import {
34
39
  attachFailureKind,
35
40
  buildAddJson,
41
+ buildCheckJson,
36
42
  buildGenerateJson,
37
43
  buildInspectJson,
38
44
  formatJsonResult,
@@ -44,6 +50,26 @@ import {
44
50
  } from "./output.ts";
45
51
  import { INSPECT_TARGETS, TOP_LEVEL_COMMANDS, type ForgeCommand } from "./parse.ts";
46
52
  import { runVerifyCommand } from "./verify.ts";
53
+ import {
54
+ buildExternalServiceGraph,
55
+ importExternalManifest,
56
+ readExternalManifestFile,
57
+ } from "../compiler/external-manifest/registry.ts";
58
+ import {
59
+ resolveExternalQualifiedName,
60
+ runExternalEntry,
61
+ } from "../runtime/external/bridge.ts";
62
+ import {
63
+ formatCompilerBenchHuman,
64
+ formatCompilerBenchJson,
65
+ runCompilerBenchCommand,
66
+ } from "../bench.ts";
67
+ import {
68
+ formatCairHuman,
69
+ formatCairJson,
70
+ runCairCommand,
71
+ } from "../cair/index.ts";
72
+ import { uniqueNextActions } from "./next-actions.ts";
47
73
  import {
48
74
  formatRunJson,
49
75
  formatRunListHuman,
@@ -51,6 +77,41 @@ import {
51
77
  runRunCommand,
52
78
  } from "./run.ts";
53
79
  import { runDevCommand } from "./dev.ts";
80
+ import {
81
+ formatHandoffHuman,
82
+ formatHandoffJson,
83
+ runHandoffCommand,
84
+ } from "./handoff.ts";
85
+ import {
86
+ formatStudioAttachHuman,
87
+ formatStudioAttachJson,
88
+ formatStudioBridgeEventJson,
89
+ formatStudioBridgeHuman,
90
+ formatStudioBridgeJson,
91
+ formatStudioCodexServerHuman,
92
+ formatStudioCodexServerJson,
93
+ formatStudioDoctorHuman,
94
+ formatStudioDoctorJson,
95
+ formatStudioOpenHuman,
96
+ formatStudioOpenJson,
97
+ formatStudioSnapshotHuman,
98
+ formatStudioSnapshotJson,
99
+ formatStudioWatchHuman,
100
+ formatStudioWatchJson,
101
+ runStudioAttachCommand,
102
+ runStudioBridgeCommand,
103
+ runStudioBridgeLoop,
104
+ runStudioCodexServerCommand,
105
+ runStudioDoctorCommand,
106
+ runStudioOpenCommand,
107
+ runStudioSnapshotCommand,
108
+ runStudioWatchCommand,
109
+ runStudioWatchLoop,
110
+ } from "./studio.ts";
111
+ import {
112
+ formatChangedHuman,
113
+ runChangedCommand,
114
+ } from "./changed.ts";
54
115
  import { initializeRuntimeEnv } from "../runtime/context/create-context.ts";
55
116
  import { formatDbHuman, formatDbJson, runDbCommand } from "./db.ts";
56
117
  import { formatOutboxHuman, formatOutboxJson, runOutboxCommand } from "./outbox.ts";
@@ -64,6 +125,23 @@ import {
64
125
  formatTelemetryJson,
65
126
  runTelemetryCommand,
66
127
  } from "./telemetry.ts";
128
+ import {
129
+ formatDeltaExplainHuman,
130
+ formatDeltaExplainJson,
131
+ formatDeltaRepairHuman,
132
+ formatDeltaRepairJson,
133
+ formatDeltaStatusHuman,
134
+ formatDeltaStatusJson,
135
+ formatDeltaSessionHuman,
136
+ formatDeltaSessionJson,
137
+ formatDeltaTimelineHuman,
138
+ formatDeltaTimelineJson,
139
+ runDeltaExplain,
140
+ runDeltaRepair,
141
+ runDeltaSessionCommand,
142
+ runDeltaStatus,
143
+ runDeltaTimeline,
144
+ } from "../delta/index.ts";
67
145
  import {
68
146
  formatPolicyHuman,
69
147
  formatPolicyJson,
@@ -82,7 +160,8 @@ import { formatNewHuman, runNewCommand } from "./new.ts";
82
160
  import { formatBuildHuman, runBuildCommand } from "./build.ts";
83
161
  import { runServeCommand } from "./serve.ts";
84
162
  import { runWorkerCommand } from "./worker.ts";
85
- import { formatSelfHostHuman, runSelfHostCommand } from "./self-host.ts";
163
+ import { formatSelfHostHuman, runSelfHostCommand, type SelfHostCommandResult } from "./self-host.ts";
164
+ import { formatDocsCheckHuman, runDocsCheckCommand, type DocsCheckResult } from "./docs.ts";
86
165
  import {
87
166
  formatAgentContractHuman,
88
167
  runAgentContractPrint,
@@ -102,10 +181,16 @@ import {
102
181
  } from "./windows.ts";
103
182
  import { formatAuthHuman, formatAuthJson, runAuthCommand } from "./auth.ts";
104
183
  import { formatRlsHuman, formatRlsJson, runRlsCommand } from "./rls.ts";
184
+ import {
185
+ formatSecurityHuman,
186
+ formatSecurityJson,
187
+ runSecurityCommand,
188
+ } from "./security.ts";
105
189
  import { formatDepsHuman, formatDepsJson, runDepsCommand } from "./deps.ts";
106
190
  import {
107
191
  formatReleaseHuman,
108
192
  formatReleaseJson,
193
+ type ReleaseCommandResult,
109
194
  runReleaseCommand,
110
195
  } from "./release.ts";
111
196
  import { formatMakeHuman, formatMakeJson, runMakeCommand } from "./make.ts";
@@ -127,11 +212,18 @@ import {
127
212
  formatForgeDoJson,
128
213
  runForgeDoCommand,
129
214
  } from "../intent/index.ts";
215
+ import {
216
+ formatBrownfieldImportHuman,
217
+ formatBrownfieldImportJson,
218
+ inspectBrownfieldImport,
219
+ runBrownfieldImportCommand,
220
+ } from "../brownfield-import/index.ts";
130
221
  import {
131
222
  formatAgentHuman,
132
223
  formatAgentJson,
133
224
  runAgentCommand,
134
225
  } from "../agent-adapters/index.ts";
226
+ import { runMcpServe } from "../agent-memory/mcp.ts";
135
227
  import {
136
228
  formatReviewHuman,
137
229
  formatReviewJson,
@@ -155,6 +247,9 @@ import { runLiveCommand } from "./live.ts";
155
247
  import { runQuery } from "../runtime/query/run-query.ts";
156
248
  import { resolveAuthFromCli } from "../runtime/auth/resolve.ts";
157
249
  import { getActiveDbAdapter } from "../runtime/executor.ts";
250
+ import { CLI_VERSION, FORGEOS_VERSION } from "../version.ts";
251
+ import type { CategorizedFileSummary } from "../workspace/change-summary.ts";
252
+ import { buildWorkspaceGitSummary } from "../workspace/git-summary.ts";
158
253
 
159
254
  function readGeneratedJson<T>(workspaceRoot: string, relative: string): T | null {
160
255
  const absolute = join(workspaceRoot, relative);
@@ -238,9 +333,14 @@ function buildFrameworkInspect(workspaceRoot: string): Record<string, unknown> {
238
333
  topLevelCommands: [...TOP_LEVEL_COMMANDS],
239
334
  inspectTargets: [...INSPECT_TARGETS],
240
335
  preferredEntryPoints: [
336
+ "forge status --json",
337
+ "forge changed --json",
338
+ "forge agent onboard --target codex --json",
241
339
  "forge do <objective> --json",
242
340
  "forge dev --once --json",
341
+ "forge inspect all --brief --json",
243
342
  "forge inspect all --json",
343
+ "forge agent print-context --json",
244
344
  "forge inspect framework --json",
245
345
  "forge verify --strict",
246
346
  ],
@@ -270,13 +370,519 @@ function buildFrameworkInspect(workspaceRoot: string): Record<string, unknown> {
270
370
  };
271
371
  }
272
372
 
373
+ function readGeneratedArtifactStatus(workspaceRoot: string): Array<{ name: string; path: string; present: boolean }> {
374
+ const artifacts = [
375
+ ["app", `${GENERATED_DIR}/appGraph.json`],
376
+ ["data", `${GENERATED_DIR}/dataGraph.json`],
377
+ ["sql", `${GENERATED_DIR}/sqlPlan.json`],
378
+ ["db", `${GENERATED_DIR}/db.json`],
379
+ ["runtime", `${GENERATED_DIR}/runtimeGraph.json`],
380
+ ["frontend", `${GENERATED_DIR}/frontendGraph.json`],
381
+ ["client", `${GENERATED_DIR}/clientManifest.json`],
382
+ ["agent-contract", `${GENERATED_DIR}/agentContract.json`],
383
+ ["agent-adapters", `${GENERATED_DIR}/agentAdapterManifest.json`],
384
+ ["capability-map", `${GENERATED_DIR}/capabilityMap.json`],
385
+ ["test-graph", `${GENERATED_DIR}/testGraph.json`],
386
+ ["agents-md", "AGENTS.md"],
387
+ ["forge-lock", "forge.lock"],
388
+ ] as const;
389
+
390
+ return artifacts.map(([name, path]) => ({
391
+ name,
392
+ path,
393
+ present: hasPath(workspaceRoot, path),
394
+ }));
395
+ }
396
+
397
+ function buildInspectSummary(workspaceRoot: string): Record<string, unknown> {
398
+ const framework = buildFrameworkInspect(workspaceRoot);
399
+ const dataGraph = readGeneratedJson<DataGraph>(workspaceRoot, `${GENERATED_DIR}/dataGraph.json`);
400
+ const frontend = readGeneratedJson<FrontendGraph>(workspaceRoot, `${GENERATED_DIR}/frontendGraph.json`);
401
+ const agentAdapters = readGeneratedJson<{ targets?: Array<{ name?: string; files?: string[]; default?: boolean; optional?: boolean }> }>(
402
+ workspaceRoot,
403
+ `${GENERATED_DIR}/agentAdapterManifest.json`,
404
+ );
405
+ const artifacts = readGeneratedArtifactStatus(workspaceRoot);
406
+ const missingArtifacts = artifacts.filter((artifact) => !artifact.present);
407
+
408
+ return {
409
+ schemaVersion: "0.1.0",
410
+ summary: {
411
+ project: (framework.project as Record<string, unknown> | undefined)?.name ?? "unknown",
412
+ tables: dataGraph?.tables.length ?? 0,
413
+ frontendPresent: frontend?.present === true,
414
+ routes: frontend?.routes.length ?? 0,
415
+ agentTargets: agentAdapters?.targets?.map((target) => target.name).filter(Boolean) ?? [],
416
+ missingArtifacts: missingArtifacts.length,
417
+ },
418
+ artifacts,
419
+ nextActions: [
420
+ "forge inspect schema --json",
421
+ "forge inspect handoff --json",
422
+ "forge inspect drift --json",
423
+ "forge check --json",
424
+ ],
425
+ };
426
+ }
427
+
428
+ function buildInspectBrief(workspaceRoot: string): Record<string, unknown> {
429
+ const summary = buildInspectSummary(workspaceRoot);
430
+ const framework = buildFrameworkInspect(workspaceRoot);
431
+ const cli = framework.cli as { preferredEntryPoints?: string[]; inspectTargets?: string[] } | undefined;
432
+ const artifacts = readGeneratedArtifactStatus(workspaceRoot);
433
+ const missingArtifacts = artifacts.filter((artifact) => !artifact.present);
434
+ return {
435
+ schemaVersion: "0.1.0",
436
+ brief: true,
437
+ payload: {
438
+ mode: "brief",
439
+ purpose: "orientation",
440
+ includes: ["summary", "entrypoints", "refs", "artifact counts"],
441
+ omitted: ["schema table details", "framework module lists", "generated registries"],
442
+ fullCommand: "forge inspect all --full --json",
443
+ compactCommand: "forge inspect all --json",
444
+ },
445
+ summary: summary.summary,
446
+ entrypoints: {
447
+ preferred: cli?.preferredEntryPoints ?? [],
448
+ inspect: [
449
+ "forge inspect summary --json",
450
+ "forge inspect schema --json",
451
+ "forge inspect handoff --json",
452
+ "forge inspect all --json",
453
+ "forge inspect all --full --json",
454
+ ],
455
+ },
456
+ refs: [
457
+ "AGENTS.md",
458
+ `${GENERATED_DIR}/agentContract.json`,
459
+ `${GENERATED_DIR}/appMap.md`,
460
+ `${GENERATED_DIR}/runtimeRules.md`,
461
+ `${GENERATED_DIR}/operationPlaybooks.md`,
462
+ `${GENERATED_DIR}/frontendGraph.json`,
463
+ ],
464
+ artifacts: {
465
+ total: artifacts.length,
466
+ present: artifacts.length - missingArtifacts.length,
467
+ missing: missingArtifacts,
468
+ },
469
+ nextActions: [
470
+ "forge status --json",
471
+ "forge changed --json",
472
+ "forge agent onboard --target codex --json",
473
+ "forge dev --once --json",
474
+ "forge inspect all --json",
475
+ ],
476
+ };
477
+ }
478
+
479
+ function buildSchemaInspect(workspaceRoot: string): { data: Record<string, unknown>; errors: ReturnType<typeof createDiagnostic>[] } {
480
+ const dataGraph = readGeneratedJson<DataGraph>(workspaceRoot, `${GENERATED_DIR}/dataGraph.json`);
481
+ const sqlPlan = readGeneratedJson<SqlPlan>(workspaceRoot, `${GENERATED_DIR}/sqlPlan.json`);
482
+ const db = readGeneratedJson<{ tableMap?: Record<string, TableMapEntry> }>(workspaceRoot, `${GENERATED_DIR}/db.json`);
483
+ const errors: ReturnType<typeof createDiagnostic>[] = [];
484
+
485
+ if (!dataGraph) {
486
+ errors.push(createDiagnostic({
487
+ severity: "error",
488
+ code: "FORGE_INSPECT_MISSING",
489
+ message: `missing generated artifact: ${GENERATED_DIR}/dataGraph.json; run forge generate first`,
490
+ file: `${GENERATED_DIR}/dataGraph.json`,
491
+ }));
492
+ }
493
+ if (!sqlPlan) {
494
+ errors.push(createDiagnostic({
495
+ severity: "error",
496
+ code: "FORGE_INSPECT_MISSING",
497
+ message: `missing generated artifact: ${GENERATED_DIR}/sqlPlan.json; run forge generate first`,
498
+ file: `${GENERATED_DIR}/sqlPlan.json`,
499
+ }));
500
+ }
501
+ if (!db?.tableMap) {
502
+ errors.push(createDiagnostic({
503
+ severity: "error",
504
+ code: "FORGE_INSPECT_MISSING",
505
+ message: `missing generated artifact: ${GENERATED_DIR}/db.json; run forge generate first`,
506
+ file: `${GENERATED_DIR}/db.json`,
507
+ }));
508
+ }
509
+
510
+ const sqlByAccessName = new Map(
511
+ (sqlPlan?.tables ?? [])
512
+ .filter((table) => table.kind === "create_table")
513
+ .map((table) => [table.accessName ?? table.table ?? "", table]),
514
+ );
515
+ const tableMap = db?.tableMap ?? {};
516
+ const dataGraphDiagnostics = dataGraph?.diagnostics ?? [];
517
+ const sqlPlanDiagnostics = sqlPlan?.diagnostics ?? [];
518
+ const tables = (dataGraph?.tables ?? []).map((table) => {
519
+ const sql = sqlByAccessName.get(table.name);
520
+ const runtime = sql?.table ? tableMap[sql.table] ?? tableMap[table.name] : tableMap[table.name];
521
+ const sourceFields = table.fields.map((field) => field.name).sort();
522
+ const sqlColumns = (sql?.columns ?? []).map((column) => ({
523
+ name: column.name,
524
+ fieldName: column.fieldName,
525
+ sqlType: column.sqlType,
526
+ primaryKey: column.primaryKey === true,
527
+ }));
528
+ const runtimeFields = (runtime?.columns ?? []).map((column) => column.fieldName ?? column.name).sort();
529
+ const missingRuntimeFields = sourceFields.filter((field) => !runtimeFields.includes(field));
530
+
531
+ return {
532
+ name: table.name,
533
+ file: table.file,
534
+ sourceFields,
535
+ sqlTable: sql?.table ?? null,
536
+ sqlColumns,
537
+ runtimeAccessors: Object.entries(tableMap)
538
+ .filter(([, entry]) => entry.tableName === (sql?.table ?? table.name))
539
+ .map(([name]) => name)
540
+ .sort(),
541
+ missingRuntimeFields,
542
+ };
543
+ });
544
+
545
+ return {
546
+ data: {
547
+ schemaVersion: "0.1.0",
548
+ summary: {
549
+ tables: tables.length,
550
+ missingRuntimeFields: tables.reduce(
551
+ (count, table) => count + (table.missingRuntimeFields as string[]).length,
552
+ 0,
553
+ ),
554
+ diagnostics: dataGraphDiagnostics.length + sqlPlanDiagnostics.length + errors.length,
555
+ },
556
+ tables,
557
+ diagnostics: [
558
+ ...dataGraphDiagnostics,
559
+ ...sqlPlanDiagnostics,
560
+ ...errors,
561
+ ],
562
+ },
563
+ errors,
564
+ };
565
+ }
566
+
567
+ function buildDriftInspect(workspaceRoot: string): Record<string, unknown> {
568
+ const schema = buildSchemaInspect(workspaceRoot);
569
+ const artifacts = readGeneratedArtifactStatus(workspaceRoot);
570
+ const missingArtifacts = artifacts.filter((artifact) => !artifact.present);
571
+ const tableDrift = ((schema.data.tables as Array<{ name: string; missingRuntimeFields: string[] }> | undefined) ?? [])
572
+ .filter((table) => table.missingRuntimeFields.length > 0)
573
+ .map((table) => ({
574
+ table: table.name,
575
+ missingRuntimeFields: table.missingRuntimeFields,
576
+ suggestedCommand: "forge generate && forge check --json",
577
+ }));
578
+ const staleAgentContext = hasPath(workspaceRoot, ".forge/agent/context.json")
579
+ ? "run forge agent check --target codex --json or forge agent export --target codex"
580
+ : null;
581
+
582
+ return {
583
+ schemaVersion: "0.1.0",
584
+ summary: {
585
+ ok: missingArtifacts.length === 0 && tableDrift.length === 0,
586
+ missingArtifacts: missingArtifacts.length,
587
+ tableDrift: tableDrift.length,
588
+ agentContextPresent: hasPath(workspaceRoot, ".forge/agent/context.json"),
589
+ },
590
+ missingArtifacts,
591
+ tableDrift,
592
+ agentContext: staleAgentContext,
593
+ nextActions: [
594
+ ...(missingArtifacts.length > 0 || tableDrift.length > 0 ? ["forge generate", "forge check --json"] : []),
595
+ "forge agent check --target codex --json",
596
+ ],
597
+ };
598
+ }
599
+
600
+ function buildHandoffInspect(workspaceRoot: string): Record<string, unknown> {
601
+ const manifest = readGeneratedJson<{
602
+ targets?: Array<{
603
+ name?: string;
604
+ files?: string[];
605
+ default?: boolean;
606
+ optional?: boolean;
607
+ formatVersion?: string;
608
+ adapterVersion?: string;
609
+ }>;
610
+ }>(workspaceRoot, `${GENERATED_DIR}/agentAdapterManifest.json`);
611
+ const targets = (manifest?.targets ?? []).map((target) => {
612
+ const files = target.files ?? [];
613
+ const missingFiles = files.filter((file) => !hasPath(workspaceRoot, file));
614
+ return {
615
+ name: target.name,
616
+ default: target.default === true,
617
+ optional: target.optional === true,
618
+ formatVersion: target.formatVersion,
619
+ adapterVersion: target.adapterVersion,
620
+ files,
621
+ filesPresent: files.length - missingFiles.length,
622
+ missingFiles,
623
+ exportCommand: target.name ? `forge agent export --target ${target.name}` : null,
624
+ checkCommand: target.name ? `forge agent check --target ${target.name} --json` : null,
625
+ prepareCommand: target.name ? `forge agent prepare --target ${target.name} --json` : null,
626
+ };
627
+ });
628
+ const missingRequiredFiles = targets.reduce(
629
+ (count, target) => count + (target.optional ? 0 : target.missingFiles.length),
630
+ 0,
631
+ );
632
+ const missingOptionalFiles = targets.reduce(
633
+ (count, target) => count + (target.optional ? target.missingFiles.length : 0),
634
+ 0,
635
+ );
636
+ const defaultTarget = targets.find((target) => target.default);
637
+ const defaultTargetMissingFiles = defaultTarget?.missingFiles.length ?? missingRequiredFiles;
638
+
639
+ return {
640
+ schemaVersion: "0.1.0",
641
+ summary: {
642
+ targets: targets.length,
643
+ defaultTarget: defaultTarget?.name ?? "generic",
644
+ missingFiles: missingRequiredFiles + missingOptionalFiles,
645
+ missingDefaultFiles: defaultTargetMissingFiles,
646
+ missingRequiredFiles,
647
+ missingOptionalFiles,
648
+ defaultReady: defaultTargetMissingFiles === 0,
649
+ requiredReady: missingRequiredFiles === 0,
650
+ },
651
+ targets,
652
+ commands: [
653
+ "forge agent list-targets --json",
654
+ "forge agent prepare --target codex --json",
655
+ "forge agent hooks smoke --target codex --json",
656
+ "forge agent ingest codex --event PostToolUse --json",
657
+ ],
658
+ };
659
+ }
660
+
661
+ export interface StatusCommandResult {
662
+ ok: boolean;
663
+ data: Record<string, unknown>;
664
+ exitCode: 0 | 1;
665
+ }
666
+
667
+ export function runStatusCommand(workspaceRoot: string): StatusCommandResult {
668
+ const summary = buildInspectSummary(workspaceRoot);
669
+ const drift = buildDriftInspect(workspaceRoot);
670
+ const handoff = buildHandoffInspect(workspaceRoot);
671
+ const gitSummary = buildWorkspaceGitSummary(workspaceRoot);
672
+ const git = {
673
+ available: gitSummary.available,
674
+ ...(gitSummary.error ? { error: gitSummary.error } : {}),
675
+ changed: gitSummary.changeSummary.changed,
676
+ staged: gitSummary.changeSummary.staged,
677
+ unstaged: gitSummary.changeSummary.unstaged,
678
+ untracked: gitSummary.changeSummary.untracked,
679
+ };
680
+ const summaryBlock = summary.summary as Record<string, unknown>;
681
+ const driftSummary = drift.summary as Record<string, unknown>;
682
+ const handoffSummary = handoff.summary as Record<string, unknown>;
683
+ const missingArtifacts = Number(summaryBlock.missingArtifacts ?? 0);
684
+ const tableDrift = Number(driftSummary.tableDrift ?? 0);
685
+ const generatedReady = missingArtifacts === 0;
686
+ const driftClean = driftSummary.ok === true;
687
+ const ok = driftClean && generatedReady;
688
+ const handoffDefaultReady = handoffSummary.defaultReady === true;
689
+ const generatedState = !generatedReady
690
+ ? "missing-artifacts"
691
+ : driftClean
692
+ ? "ready"
693
+ : "drift";
694
+ const generatedNextActions = generatedState === "ready"
695
+ ? ["forge dev", "forge generate --check --json"]
696
+ : ["forge generate", "forge check --json", "forge inspect drift --json"];
697
+ const changed = gitSummary.changeSummary.changed;
698
+ const generatedGitFiles = changed.byType.generated.count;
699
+ const authoredGitFiles = changed.total.count - generatedGitFiles;
700
+ const generatedGitExplanation = generatedGitFiles === 0
701
+ ? "git status has no generated artifact changes"
702
+ : authoredGitFiles === 0
703
+ ? "forge generate --check can be clean while git shows generated artifacts changed: generated files match current workspace inputs but differ from HEAD"
704
+ : "git status includes generated artifacts alongside authored changes; review authored inputs first";
705
+ const frontendPresent = summaryBlock.frontendPresent === true;
706
+ const studio = {
707
+ openCommand: "forge studio open . --preview-port 5174 --target codex --json",
708
+ attachCommand: "forge studio attach . --preview-port 5174 --target codex --json",
709
+ snapshotCommand: "forge studio snapshot . --preview-port 5174 --target codex --json",
710
+ watchCommand: "forge studio watch . --preview-port 5174 --target codex --json",
711
+ bridgeCommand: "forge studio bridge . --preview-port 5174 --target codex --studio-url http://127.0.0.1:3765 --json",
712
+ doctorCommand: "forge studio doctor . --preview-port 5174 --target codex --json",
713
+ targetPreviewUrl: "http://127.0.0.1:5174",
714
+ startTargetAppCommand: "forge dev --port 3766 --web-port 5174",
715
+ probeCommand: "forge dev --once --json",
716
+ useful: frontendPresent,
717
+ note: frontendPresent
718
+ ? "Attach this app to Forge Studio as an external-agent workroom; Studio should preview the target app on 5174."
719
+ : "No frontend was detected, but Studio can still attach for hooks, posture, and agent context.",
720
+ };
721
+
722
+ return {
723
+ ok,
724
+ data: {
725
+ schemaVersion: "0.1.0",
726
+ ok,
727
+ generated: {
728
+ state: generatedState,
729
+ ready: generatedReady,
730
+ driftClean,
731
+ missingArtifacts,
732
+ tableDrift,
733
+ safeDevCommand: "forge dev",
734
+ checkCommand: "forge generate --check --json",
735
+ repairCommand: "forge generate",
736
+ git: {
737
+ changedFiles: changed.total.count,
738
+ authoredFiles: authoredGitFiles,
739
+ generatedFiles: generatedGitFiles,
740
+ explanation: generatedGitExplanation,
741
+ },
742
+ nextActions: generatedNextActions,
743
+ },
744
+ studio,
745
+ summary: {
746
+ project: summaryBlock.project,
747
+ generated: generatedState,
748
+ tables: summaryBlock.tables,
749
+ frontendPresent,
750
+ routes: summaryBlock.routes,
751
+ drift: driftClean ? "clean" : "attention",
752
+ agentTargets: summaryBlock.agentTargets,
753
+ missingAgentFiles: handoffSummary.missingRequiredFiles,
754
+ missingDefaultAgentFiles: handoffSummary.missingDefaultFiles,
755
+ missingRequiredAgentFiles: handoffSummary.missingRequiredFiles,
756
+ missingOptionalAgentFiles: handoffSummary.missingOptionalFiles,
757
+ },
758
+ checks: {
759
+ artifacts: {
760
+ missing: missingArtifacts,
761
+ },
762
+ schema: {
763
+ tableDrift,
764
+ },
765
+ handoff: {
766
+ targets: handoffSummary.targets,
767
+ missingFiles: handoffSummary.missingFiles,
768
+ missingDefaultFiles: handoffSummary.missingDefaultFiles,
769
+ missingRequiredFiles: handoffSummary.missingRequiredFiles,
770
+ missingOptionalFiles: handoffSummary.missingOptionalFiles,
771
+ defaultReady: handoffSummary.defaultReady,
772
+ requiredReady: handoffSummary.requiredReady,
773
+ },
774
+ },
775
+ git,
776
+ nextActions: ok
777
+ ? [
778
+ "forge handoff --json",
779
+ "forge changed --json",
780
+ "forge dev",
781
+ ...(frontendPresent ? [studio.openCommand, studio.bridgeCommand, studio.doctorCommand] : []),
782
+ ...(!handoffDefaultReady ? ["forge agent prepare --target generic --json"] : []),
783
+ "forge inspect handoff --json",
784
+ "forge verify --changed",
785
+ ]
786
+ : [
787
+ "forge generate",
788
+ "forge handoff --json",
789
+ "forge changed --json",
790
+ ...(frontendPresent ? [studio.openCommand, studio.bridgeCommand, studio.doctorCommand] : []),
791
+ "forge inspect drift --json",
792
+ "forge agent prepare --target codex --json",
793
+ ],
794
+ },
795
+ exitCode: ok ? 0 : 1,
796
+ };
797
+ }
798
+
799
+ export function formatStatusHuman(result: StatusCommandResult): string {
800
+ const summary = result.data.summary as Record<string, unknown>;
801
+ const generated = result.data.generated as
802
+ | {
803
+ state?: string;
804
+ missingArtifacts?: number;
805
+ tableDrift?: number;
806
+ safeDevCommand?: string;
807
+ checkCommand?: string;
808
+ repairCommand?: string;
809
+ }
810
+ | undefined;
811
+ const git = result.data.git as
812
+ | {
813
+ available?: boolean;
814
+ changed?: CategorizedFileSummary;
815
+ }
816
+ | undefined;
817
+ const studio = result.data.studio as
818
+ | {
819
+ attachCommand?: string;
820
+ openCommand?: string;
821
+ doctorCommand?: string;
822
+ bridgeCommand?: string;
823
+ targetPreviewUrl?: string;
824
+ startTargetAppCommand?: string;
825
+ useful?: boolean;
826
+ }
827
+ | undefined;
828
+ const lines = [
829
+ `Forge status: ${result.ok ? "ready" : "needs attention"}`,
830
+ `Project: ${summary.project ?? "unknown"}`,
831
+ `Generated: ${summary.generated}`,
832
+ ...(generated
833
+ ? [
834
+ `Generated detail: missing artifacts ${generated.missingArtifacts ?? 0}, table drift ${generated.tableDrift ?? 0}`,
835
+ `Generated check: ${generated.checkCommand ?? "forge generate --check --json"}`,
836
+ `Generated repair: ${generated.repairCommand ?? "forge generate"}`,
837
+ `Generated dev: ${generated.safeDevCommand ?? "forge dev"}`,
838
+ ]
839
+ : []),
840
+ `Drift: ${summary.drift}`,
841
+ `Frontend: ${summary.frontendPresent ? `${summary.routes ?? 0} routes` : "none"}`,
842
+ ...(studio
843
+ ? [
844
+ `Studio open: ${studio.openCommand ?? "forge studio open . --preview-port 5174 --target codex --json"}`,
845
+ `Studio attach: ${studio.attachCommand ?? "forge studio attach . --preview-port 5174 --target codex --json"}`,
846
+ `Studio bridge: ${studio.bridgeCommand ?? "forge studio bridge . --preview-port 5174 --target codex --studio-url http://127.0.0.1:3765 --json"}`,
847
+ `Studio doctor: ${studio.doctorCommand ?? "forge studio doctor . --preview-port 5174 --target codex --json"}`,
848
+ `Studio preview: ${studio.targetPreviewUrl ?? "http://127.0.0.1:5174"}`,
849
+ `Studio start: ${studio.startTargetAppCommand ?? "forge dev --port 3766 --web-port 5174"}`,
850
+ ]
851
+ : []),
852
+ ...(git?.available && git.changed
853
+ ? [`Changed: ${git.changed.total.count}${git.changed.total.count > 0 ? ` (${git.changed.primaryTypes.slice(0, 5).join(", ")})` : ""}`]
854
+ : []),
855
+ `Agent default missing files: ${summary.missingDefaultAgentFiles ?? 0}`,
856
+ `Agent required missing files: ${summary.missingRequiredAgentFiles ?? summary.missingAgentFiles ?? 0}`,
857
+ `Agent optional missing files: ${summary.missingOptionalAgentFiles ?? 0}`,
858
+ "",
859
+ "Next:",
860
+ ...((result.data.nextActions as string[] | undefined) ?? []).map((command) => ` ${command}`),
861
+ ];
862
+ return `${lines.join("\n")}\n`;
863
+ }
864
+
273
865
  export async function runGenerateCommand(
274
866
  options: GenerateOptions,
275
867
  ): Promise<GenerateResult> {
276
- const result = await run(options);
868
+ const result = await withWorkspaceCwd(options.workspaceRoot, () => run(options));
277
869
  return attachFailureKind(result);
278
870
  }
279
871
 
872
+ async function withWorkspaceCwd<T>(workspaceRoot: string, fn: () => Promise<T>): Promise<T> {
873
+ const previous = process.cwd();
874
+ const target = resolve(workspaceRoot);
875
+ if (resolve(previous).toLowerCase() === target.toLowerCase()) {
876
+ return fn();
877
+ }
878
+ process.chdir(target);
879
+ try {
880
+ return await fn();
881
+ } finally {
882
+ process.chdir(previous);
883
+ }
884
+ }
885
+
280
886
  export async function runAddCommand(
281
887
  alias: string,
282
888
  options: Extract<ForgeCommand, { kind: "add" }>["options"],
@@ -343,6 +949,7 @@ export async function runCheckCommand(
343
949
  workspaceRoot,
344
950
  `${GENERATED_DIR}/capabilityMap.json`,
345
951
  )?.diagnostics ?? [];
952
+ const externalDiagnostics = buildExternalServiceGraph(workspaceRoot).diagnostics;
346
953
 
347
954
  const allDiagnostics = [
348
955
  ...guardDiagnostics,
@@ -351,6 +958,7 @@ export async function runCheckCommand(
351
958
  ...queryDiagnostics,
352
959
  ...frontendDiagnostics,
353
960
  ...capabilityDiagnostics,
961
+ ...externalDiagnostics,
354
962
  ];
355
963
  const errors = allDiagnostics.filter(
356
964
  (diagnostic) => diagnostic.severity === "error",
@@ -369,9 +977,265 @@ export async function runCheckCommand(
369
977
  });
370
978
  }
371
979
 
980
+ interface ReleaseDoctorCheck {
981
+ name: string;
982
+ ok: boolean;
983
+ requiredForPublish: boolean;
984
+ state?: string;
985
+ result: ReleaseCommandResult | SelfHostCommandResult | DocsCheckResult | PackagePackCheckResult;
986
+ }
987
+
988
+ interface PackagePackCheckResult {
989
+ ok: boolean;
990
+ data: {
991
+ command: "npm pack --dry-run --json";
992
+ dryRun: true;
993
+ tarball: string | null;
994
+ fileCount: number;
995
+ };
996
+ diagnostics: ReturnType<typeof createDiagnostic>[];
997
+ nextActions?: string[];
998
+ failureKind?: string;
999
+ exitCode: 0 | 1;
1000
+ }
1001
+
1002
+ interface ReleaseDoctorResult {
1003
+ schemaVersion: "0.1.0";
1004
+ ok: boolean;
1005
+ readyToPublish: boolean;
1006
+ summary: {
1007
+ checks: number;
1008
+ failed: string[];
1009
+ notPrepared: string[];
1010
+ };
1011
+ checks: ReleaseDoctorCheck[];
1012
+ nextActions: string[];
1013
+ exitCode: 0 | 1;
1014
+ }
1015
+
1016
+ function runPackagePackDryRun(workspaceRoot: string): PackagePackCheckResult {
1017
+ const result = spawnSync("npm", ["pack", "--dry-run", "--json"], {
1018
+ cwd: workspaceRoot,
1019
+ encoding: "utf8",
1020
+ windowsHide: true,
1021
+ });
1022
+ const command = "npm pack --dry-run --json" as const;
1023
+ if (result.status !== 0) {
1024
+ const failureDetail = result.error instanceof Error ? result.error.message : null;
1025
+ return {
1026
+ ok: false,
1027
+ data: { command, dryRun: true, tarball: null, fileCount: 0 },
1028
+ diagnostics: [
1029
+ createDiagnostic({
1030
+ severity: "error",
1031
+ code: FORGE_RELEASE_PACKAGE_PACK_FAILED,
1032
+ message: "npm pack dry-run failed; release package contents could not be validated",
1033
+ fixHint: (result.stderr || result.stdout || failureDetail || "Run npm pack --dry-run --json locally for details.").trim(),
1034
+ suggestedCommands: ["npm pack --dry-run --json"],
1035
+ }),
1036
+ ],
1037
+ nextActions: ["npm pack --dry-run --json"],
1038
+ failureKind: "package-pack-failed",
1039
+ exitCode: 1,
1040
+ };
1041
+ }
1042
+ try {
1043
+ const parsed = JSON.parse(result.stdout || "[]") as unknown;
1044
+ const pack = Array.isArray(parsed)
1045
+ ? (parsed[0] as { filename?: unknown; files?: unknown[] } | undefined)
1046
+ : undefined;
1047
+ if (typeof pack?.filename !== "string" || !Array.isArray(pack.files)) {
1048
+ return {
1049
+ ok: false,
1050
+ data: { command, dryRun: true, tarball: null, fileCount: 0 },
1051
+ diagnostics: [
1052
+ createDiagnostic({
1053
+ severity: "error",
1054
+ code: FORGE_RELEASE_PACKAGE_PACK_FAILED,
1055
+ message: "npm pack dry-run did not report package contents",
1056
+ fixHint: "Run npm pack --dry-run --json locally and confirm it returns a tarball with file entries.",
1057
+ suggestedCommands: ["npm pack --dry-run --json"],
1058
+ }),
1059
+ ],
1060
+ nextActions: ["npm pack --dry-run --json"],
1061
+ failureKind: "package-pack-missing-contents",
1062
+ exitCode: 1,
1063
+ };
1064
+ }
1065
+ return {
1066
+ ok: true,
1067
+ data: {
1068
+ command,
1069
+ dryRun: true,
1070
+ tarball: pack.filename,
1071
+ fileCount: pack.files.length,
1072
+ },
1073
+ diagnostics: [],
1074
+ exitCode: 0,
1075
+ };
1076
+ } catch (error) {
1077
+ return {
1078
+ ok: false,
1079
+ data: { command, dryRun: true, tarball: null, fileCount: 0 },
1080
+ diagnostics: [
1081
+ createDiagnostic({
1082
+ severity: "error",
1083
+ code: FORGE_RELEASE_PACKAGE_PACK_FAILED,
1084
+ message: "npm pack dry-run returned invalid JSON",
1085
+ fixHint: error instanceof Error ? error.message : String(error),
1086
+ suggestedCommands: ["npm pack --dry-run --json"],
1087
+ }),
1088
+ ],
1089
+ nextActions: ["npm pack --dry-run --json"],
1090
+ failureKind: "package-pack-invalid-json",
1091
+ exitCode: 1,
1092
+ };
1093
+ }
1094
+ }
1095
+
1096
+ export async function runReleaseDoctorCommand(command: Extract<ForgeCommand, { kind: "release" }>): Promise<ReleaseDoctorResult> {
1097
+ const release = await runReleaseCommand({
1098
+ ...command,
1099
+ action: "check",
1100
+ allowMissingLocalRelease: true,
1101
+ provider: command.provider as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
1102
+ target: command.target as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
1103
+ });
1104
+ const sourcemaps = await runReleaseCommand({
1105
+ ...command,
1106
+ area: "sourcemaps",
1107
+ action: "check",
1108
+ provider: command.provider as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
1109
+ target: command.target as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
1110
+ });
1111
+ const selfHost = await runSelfHostCommand({
1112
+ subcommand: "check",
1113
+ workspaceRoot: command.workspaceRoot,
1114
+ json: command.json,
1115
+ withWeb: true,
1116
+ postgresVersion: "16",
1117
+ runtimePort: 3765,
1118
+ webPort: 3000,
1119
+ preparedOnly: true,
1120
+ });
1121
+ const docs = runDocsCheckCommand({
1122
+ workspaceRoot: command.workspaceRoot,
1123
+ json: command.json,
1124
+ });
1125
+ const packagePack = runPackagePackDryRun(command.workspaceRoot);
1126
+ const checks: ReleaseDoctorCheck[] = [
1127
+ {
1128
+ name: "release-prepared",
1129
+ ok: release.ok,
1130
+ requiredForPublish: true,
1131
+ state: (release.data as { state?: string } | undefined)?.state,
1132
+ result: release,
1133
+ },
1134
+ {
1135
+ name: "sourcemaps",
1136
+ ok: sourcemaps.ok,
1137
+ requiredForPublish: true,
1138
+ result: sourcemaps,
1139
+ },
1140
+ {
1141
+ name: "self-host",
1142
+ ok: selfHost.ok,
1143
+ requiredForPublish: false,
1144
+ state: selfHost.state,
1145
+ result: selfHost,
1146
+ },
1147
+ {
1148
+ name: "docs",
1149
+ ok: docs.ok,
1150
+ requiredForPublish: true,
1151
+ result: docs,
1152
+ },
1153
+ {
1154
+ name: "npm-pack-dry-run",
1155
+ ok: packagePack.ok,
1156
+ requiredForPublish: true,
1157
+ result: packagePack,
1158
+ },
1159
+ ];
1160
+ const failed = checks.filter((check) => !check.ok).map((check) => check.name);
1161
+ const notPrepared = checks
1162
+ .filter((check) => check.state === "missing-prepared-release" || check.state === "not-prepared")
1163
+ .map((check) => check.name);
1164
+ const readyToPublish = failed.length === 0 && notPrepared.length === 0;
1165
+ return {
1166
+ schemaVersion: "0.1.0",
1167
+ ok: failed.length === 0,
1168
+ readyToPublish,
1169
+ summary: {
1170
+ checks: checks.length,
1171
+ failed,
1172
+ notPrepared,
1173
+ },
1174
+ checks,
1175
+ nextActions: uniqueNextActions(checks.flatMap((check) => check.result.nextActions ?? [])),
1176
+ exitCode: failed.length === 0 ? 0 : 1,
1177
+ };
1178
+ }
1179
+
1180
+ function formatManifestHuman(result: {
1181
+ subcommand: "validate" | "import";
1182
+ path: string;
1183
+ imported?: boolean;
1184
+ serviceCount?: number;
1185
+ diagnostics: import("../compiler/types/diagnostic.ts").Diagnostic[];
1186
+ exitCode: number;
1187
+ }): string {
1188
+ const errors = result.diagnostics.filter((diagnostic) => diagnostic.severity === "error");
1189
+ const warnings = result.diagnostics.filter((diagnostic) => diagnostic.severity === "warning");
1190
+ const lines = [
1191
+ `manifest: ${result.subcommand}`,
1192
+ `path: ${result.path}`,
1193
+ result.subcommand === "import" ? `imported: ${result.imported ? "yes" : "no"}` : null,
1194
+ result.serviceCount !== undefined ? `external services: ${result.serviceCount}` : null,
1195
+ `errors: ${errors.length}`,
1196
+ `warnings: ${warnings.length}`,
1197
+ ].filter((line): line is string => line !== null);
1198
+ for (const diagnostic of result.diagnostics) {
1199
+ lines.push(`${diagnostic.severity} ${diagnostic.code}: ${diagnostic.message}`);
1200
+ }
1201
+ return `${lines.join("\n")}\n`;
1202
+ }
1203
+
1204
+ function runManifestCommand(command: Extract<ForgeCommand, { kind: "manifest" }>): {
1205
+ subcommand: "validate" | "import";
1206
+ path: string;
1207
+ imported?: boolean;
1208
+ serviceCount?: number;
1209
+ diagnostics: import("../compiler/types/diagnostic.ts").Diagnostic[];
1210
+ exitCode: number;
1211
+ } {
1212
+ if (command.subcommand === "validate") {
1213
+ const result = readExternalManifestFile(command.path);
1214
+ const hasErrors = result.diagnostics.some((diagnostic) => diagnostic.severity === "error");
1215
+ return {
1216
+ subcommand: "validate",
1217
+ path: command.path,
1218
+ diagnostics: result.diagnostics,
1219
+ exitCode: hasErrors ? 1 : 0,
1220
+ };
1221
+ }
1222
+
1223
+ const result = importExternalManifest(command.workspaceRoot, command.path);
1224
+ const hasErrors = result.diagnostics.some((diagnostic) => diagnostic.severity === "error");
1225
+ return {
1226
+ subcommand: "import",
1227
+ path: result.path,
1228
+ imported: result.imported,
1229
+ serviceCount: result.graph.services.length,
1230
+ diagnostics: result.diagnostics,
1231
+ exitCode: hasErrors ? 1 : 0,
1232
+ };
1233
+ }
1234
+
372
1235
  export async function runInspectCommand(
373
1236
  target: InspectTarget,
374
1237
  workspaceRoot: string,
1238
+ options: { full?: boolean; brief?: boolean } = {},
375
1239
  ): Promise<InspectResult> {
376
1240
  const dataPaths: Partial<Record<InspectTarget, string>> = {
377
1241
  app: `${GENERATED_DIR}/appGraph.json`,
@@ -390,6 +1254,7 @@ export async function runInspectCommand(
390
1254
  ai: `${GENERATED_DIR}/aiRegistry.json`,
391
1255
  queries: `${GENERATED_DIR}/queryRegistry.json`,
392
1256
  api: `${GENERATED_DIR}/api.json`,
1257
+ external: `${GENERATED_DIR}/externalServices.json`,
393
1258
  client: `${GENERATED_DIR}/clientManifest.json`,
394
1259
  frontend: `${GENERATED_DIR}/frontendGraph.json`,
395
1260
  auth: `${GENERATED_DIR}/authRegistry.json`,
@@ -405,6 +1270,7 @@ export async function runInspectCommand(
405
1270
  "test-graph": `${GENERATED_DIR}/testGraph.json`,
406
1271
  "test-plans": `${GENERATED_DIR}/testPlanRegistry.json`,
407
1272
  "agent-contract": `${GENERATED_DIR}/agentContract.json`,
1273
+ "agent-tools": `${GENERATED_DIR}/agentTools.json`,
408
1274
  "agent-adapters": `${GENERATED_DIR}/agentAdapterManifest.json`,
409
1275
  "capability-map": `${GENERATED_DIR}/capabilityMap.json`,
410
1276
  ui: `${GENERATED_DIR}/uiTestManifest.json`,
@@ -424,7 +1290,114 @@ export async function runInspectCommand(
424
1290
  };
425
1291
  }
426
1292
 
1293
+ if (target === "summary") {
1294
+ return {
1295
+ target,
1296
+ data: buildInspectSummary(workspaceRoot),
1297
+ warnings: [],
1298
+ errors: [],
1299
+ exitCode: 0,
1300
+ };
1301
+ }
1302
+
1303
+ if (target === "schema") {
1304
+ const result = buildSchemaInspect(workspaceRoot);
1305
+ return {
1306
+ target,
1307
+ data: result.data,
1308
+ warnings: [],
1309
+ errors: result.errors,
1310
+ exitCode: result.errors.length > 0 ? 1 : 0,
1311
+ failureKind: result.errors.length > 0 ? "missing_artifact" : undefined,
1312
+ };
1313
+ }
1314
+
1315
+ if (target === "drift") {
1316
+ return {
1317
+ target,
1318
+ data: buildDriftInspect(workspaceRoot),
1319
+ warnings: [],
1320
+ errors: [],
1321
+ exitCode: 0,
1322
+ };
1323
+ }
1324
+
1325
+ if (target === "handoff") {
1326
+ return {
1327
+ target,
1328
+ data: buildHandoffInspect(workspaceRoot),
1329
+ warnings: [],
1330
+ errors: [],
1331
+ exitCode: 0,
1332
+ };
1333
+ }
1334
+
1335
+ if (target === "imported") {
1336
+ const result = inspectBrownfieldImport(workspaceRoot);
1337
+ return {
1338
+ target,
1339
+ data: formatBrownfieldImportJson(result),
1340
+ warnings: [],
1341
+ errors: [],
1342
+ exitCode: result.exitCode,
1343
+ failureKind: result.failureKind,
1344
+ };
1345
+ }
1346
+
427
1347
  if (target === "all") {
1348
+ if (options.brief) {
1349
+ const brief = buildInspectBrief(workspaceRoot);
1350
+ return {
1351
+ target,
1352
+ data: brief,
1353
+ warnings: [],
1354
+ errors: [],
1355
+ exitCode: 0,
1356
+ };
1357
+ }
1358
+ if (!options.full) {
1359
+ const summary = buildInspectSummary(workspaceRoot);
1360
+ const schema = buildSchemaInspect(workspaceRoot);
1361
+ const drift = buildDriftInspect(workspaceRoot);
1362
+ const handoff = buildHandoffInspect(workspaceRoot);
1363
+ const framework = buildFrameworkInspect(workspaceRoot);
1364
+ const errors = [
1365
+ ...schema.errors,
1366
+ ];
1367
+ return {
1368
+ target,
1369
+ data: {
1370
+ schemaVersion: "0.1.0",
1371
+ compact: true,
1372
+ payload: {
1373
+ mode: "compact",
1374
+ purpose: "agent diagnostic bundle",
1375
+ includes: ["summary", "schema", "drift", "handoff", "framework"],
1376
+ omitted: ["large generated registries", "module graph", "full runtime graph payloads"],
1377
+ fullCommand: "forge inspect all --full --json",
1378
+ briefCommand: "forge inspect all --brief --json",
1379
+ },
1380
+ summary: summary.summary,
1381
+ inspections: {
1382
+ summary,
1383
+ schema: schema.data,
1384
+ drift,
1385
+ handoff,
1386
+ framework,
1387
+ },
1388
+ nextActions: [
1389
+ "forge inspect summary --json",
1390
+ "forge inspect schema --json",
1391
+ "forge inspect handoff --json",
1392
+ "forge inspect all --full --json",
1393
+ ],
1394
+ },
1395
+ warnings: [],
1396
+ errors,
1397
+ exitCode: errors.length > 0 ? 1 : 0,
1398
+ failureKind: errors.length > 0 ? "missing_artifact" : undefined,
1399
+ };
1400
+ }
428
1401
  const aggregatePaths: Array<[string, string]> = [
429
1402
  ["app", `${GENERATED_DIR}/appGraph.json`],
430
1403
  ["data", `${GENERATED_DIR}/dataGraph.json`],
@@ -436,6 +1409,7 @@ export async function runInspectCommand(
436
1409
  ["workflows", `${GENERATED_DIR}/workflowRegistry.json`],
437
1410
  ["telemetry", `${GENERATED_DIR}/telemetryRegistry.json`],
438
1411
  ["ai", `${GENERATED_DIR}/aiRegistry.json`],
1412
+ ["externalServices", `${GENERATED_DIR}/externalServices.json`],
439
1413
  ["client", `${GENERATED_DIR}/clientManifest.json`],
440
1414
  ["frontend", `${GENERATED_DIR}/frontendGraph.json`],
441
1415
  ["auth", `${GENERATED_DIR}/authRegistry.json`],
@@ -451,6 +1425,7 @@ export async function runInspectCommand(
451
1425
  ["testGraph", `${GENERATED_DIR}/testGraph.json`],
452
1426
  ["testPlanRegistry", `${GENERATED_DIR}/testPlanRegistry.json`],
453
1427
  ["agentContract", `${GENERATED_DIR}/agentContract.json`],
1428
+ ["agentTools", `${GENERATED_DIR}/agentTools.json`],
454
1429
  ["agentAdapters", `${GENERATED_DIR}/agentAdapterManifest.json`],
455
1430
  ["capabilityMap", `${GENERATED_DIR}/capabilityMap.json`],
456
1431
  ["ui", `${GENERATED_DIR}/uiTestManifest.json`],
@@ -459,6 +1434,7 @@ export async function runInspectCommand(
459
1434
  ];
460
1435
  const data: Record<string, unknown> = {};
461
1436
  const errors = [];
1437
+ data.summary = buildInspectSummary(workspaceRoot).summary;
462
1438
  for (const [key, relative] of aggregatePaths) {
463
1439
  const value = readGeneratedJson<unknown>(workspaceRoot, relative);
464
1440
  if (value === null) {
@@ -476,6 +1452,17 @@ export async function runInspectCommand(
476
1452
  }
477
1453
  data.framework = buildFrameworkInspect(workspaceRoot);
478
1454
  data.diagnostics = errors;
1455
+ data.compact = false;
1456
+ data.payload = {
1457
+ mode: "full",
1458
+ purpose: "complete generated machine contract",
1459
+ includes: aggregatePaths.map(([key]) => key),
1460
+ compactCommand: "forge inspect all --json",
1461
+ briefCommand: "forge inspect all --brief --json",
1462
+ };
1463
+ data.nextActions = errors.length > 0
1464
+ ? ["forge status --json", "forge generate", "forge check --json"]
1465
+ : ["forge inspect all --json", "forge check --json"];
479
1466
  return {
480
1467
  target,
481
1468
  data,
@@ -537,6 +1524,18 @@ export async function runInspectCommand(
537
1524
 
538
1525
  export async function executeCommand(command: ForgeCommand): Promise<number> {
539
1526
  switch (command.kind) {
1527
+ case "version": {
1528
+ if (command.json) {
1529
+ process.stdout.write(`${JSON.stringify({
1530
+ version: CLI_VERSION,
1531
+ cliVersion: CLI_VERSION,
1532
+ forgeosVersion: FORGEOS_VERSION,
1533
+ }, null, 2)}\n`);
1534
+ } else {
1535
+ process.stdout.write(`${CLI_VERSION}\n`);
1536
+ }
1537
+ return 0;
1538
+ }
540
1539
  case "new": {
541
1540
  const result = await runNewCommand({
542
1541
  name: command.name,
@@ -578,6 +1577,15 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
578
1577
  }
579
1578
  return result.exitCode;
580
1579
  }
1580
+ case "docs": {
1581
+ const result = runDocsCheckCommand(command);
1582
+ if (command.json) {
1583
+ process.stdout.write(formatJsonResult(result));
1584
+ } else {
1585
+ process.stdout.write(formatDocsCheckHuman(result));
1586
+ }
1587
+ return result.exitCode;
1588
+ }
581
1589
  case "agent-contract": {
582
1590
  if (command.subcommand === "print") {
583
1591
  const result = runAgentContractPrint(command.workspaceRoot);
@@ -605,6 +1613,25 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
605
1613
  return result.exitCode;
606
1614
  }
607
1615
  case "doctor": {
1616
+ if (command.target === "agent") {
1617
+ const result = await runAgentCommand({
1618
+ subcommand: "doctor",
1619
+ workspaceRoot: command.workspaceRoot,
1620
+ json: command.json,
1621
+ target: command.agentTarget ?? "codex",
1622
+ dryRun: false,
1623
+ force: false,
1624
+ preserveUserSections: true,
1625
+ skills: true,
1626
+ rules: true,
1627
+ });
1628
+ if (command.json) {
1629
+ process.stdout.write(formatAgentJson(result));
1630
+ } else {
1631
+ process.stdout.write(formatAgentHuman(result));
1632
+ }
1633
+ return result.exitCode;
1634
+ }
608
1635
  if (command.target === "windows") {
609
1636
  const result = await runWindowsDoctorCommand({ workspaceRoot: command.workspaceRoot });
610
1637
  if (command.json) {
@@ -634,6 +1661,15 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
634
1661
  }
635
1662
  return result.exitCode;
636
1663
  }
1664
+ case "security": {
1665
+ const result = await runSecurityCommand(command);
1666
+ if (command.json) {
1667
+ process.stdout.write(formatSecurityJson(result));
1668
+ } else {
1669
+ process.stdout.write(formatSecurityHuman(result));
1670
+ }
1671
+ return result.exitCode;
1672
+ }
637
1673
  case "auth": {
638
1674
  const result = await runAuthCommand(command);
639
1675
  if (command.json) {
@@ -662,6 +1698,22 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
662
1698
  return result.exitCode;
663
1699
  }
664
1700
  case "release": {
1701
+ if (command.action === "doctor") {
1702
+ const result = await runReleaseDoctorCommand(command);
1703
+ if (command.json) {
1704
+ process.stdout.write(formatJsonResult(result));
1705
+ } else {
1706
+ process.stdout.write(
1707
+ [
1708
+ `release doctor ${result.ok ? "ok" : "failed"}`,
1709
+ `ready to publish: ${result.readyToPublish ? "yes" : "no"}`,
1710
+ ...result.checks.map((check) => `${check.ok ? "ok" : "fail"} ${check.name}${check.state ? ` (${check.state})` : ""}`),
1711
+ ...(result.nextActions.length > 0 ? ["", "Next:", ...result.nextActions.map((action) => ` ${action}`)] : []),
1712
+ ].join("\n").concat("\n"),
1713
+ );
1714
+ }
1715
+ return result.exitCode;
1716
+ }
665
1717
  const result = await runReleaseCommand({
666
1718
  ...command,
667
1719
  provider: command.provider as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
@@ -737,6 +1789,71 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
737
1789
  }
738
1790
  return result.exitCode;
739
1791
  }
1792
+ case "bench": {
1793
+ const result = await runCompilerBenchCommand(command.options);
1794
+ process.stdout.write(
1795
+ command.options.json
1796
+ ? formatCompilerBenchJson(result)
1797
+ : formatCompilerBenchHuman(result),
1798
+ );
1799
+ return result.exitCode;
1800
+ }
1801
+ case "cair": {
1802
+ const result = runCairCommand(command.options);
1803
+ process.stdout.write(
1804
+ command.options.json || command.options.format === "json"
1805
+ ? formatCairJson(result)
1806
+ : formatCairHuman(result),
1807
+ );
1808
+ return result.exitCode;
1809
+ }
1810
+ case "delta": {
1811
+ if (command.subcommand === "repair") {
1812
+ const result = await runDeltaRepair({
1813
+ workspaceRoot: command.workspaceRoot,
1814
+ dryRun: command.dryRun,
1815
+ yes: command.yes,
1816
+ });
1817
+ process.stdout.write(command.json ? formatDeltaRepairJson(result) : formatDeltaRepairHuman(result));
1818
+ return result.exitCode;
1819
+ }
1820
+ const result = await runDeltaStatus(command.workspaceRoot, { verbose: command.verbose });
1821
+ process.stdout.write(command.json ? formatDeltaStatusJson(result) : formatDeltaStatusHuman(result));
1822
+ return result.exitCode;
1823
+ }
1824
+ case "session": {
1825
+ const result = await runDeltaSessionCommand({
1826
+ workspaceRoot: command.workspaceRoot,
1827
+ subcommand: command.subcommand,
1828
+ sessionId: command.sessionId,
1829
+ sourceSessionId: command.sourceSessionId,
1830
+ operationId: command.operationId,
1831
+ title: command.title,
1832
+ limit: command.limit,
1833
+ });
1834
+ process.stdout.write(command.json ? formatDeltaSessionJson(result) : formatDeltaSessionHuman(result));
1835
+ return result.exitCode;
1836
+ }
1837
+ case "timeline": {
1838
+ const result = await runDeltaTimeline({
1839
+ workspaceRoot: command.workspaceRoot,
1840
+ target: command.target,
1841
+ kind: command.kindFilter,
1842
+ session: command.sessionId,
1843
+ limit: command.limit,
1844
+ rebuild: command.rebuild,
1845
+ });
1846
+ process.stdout.write(command.json ? formatDeltaTimelineJson(result) : formatDeltaTimelineHuman(result));
1847
+ return result.exitCode;
1848
+ }
1849
+ case "explain": {
1850
+ const result = await runDeltaExplain({
1851
+ workspaceRoot: command.workspaceRoot,
1852
+ thing: command.thing,
1853
+ });
1854
+ process.stdout.write(command.json ? formatDeltaExplainJson(result) : formatDeltaExplainHuman(result));
1855
+ return result.exitCode;
1856
+ }
740
1857
  case "agent": {
741
1858
  const result = await runAgentCommand(command.options);
742
1859
  if (command.options.json) {
@@ -746,10 +1863,13 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
746
1863
  }
747
1864
  return result.exitCode;
748
1865
  }
1866
+ case "mcp": {
1867
+ return runMcpServe(command.workspaceRoot);
1868
+ }
749
1869
  case "review": {
750
1870
  const result = runReviewCommand(command.options);
751
1871
  if (command.options.json) {
752
- process.stdout.write(formatReviewJson(result));
1872
+ process.stdout.write(formatReviewJson(result, { full: command.options.full }));
753
1873
  } else if (command.options.md && result.report) {
754
1874
  process.stdout.write(renderReviewMarkdown(result.report));
755
1875
  } else if (command.options.sarif && result.report && !command.options.write) {
@@ -773,7 +1893,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
773
1893
  }
774
1894
  case "generate": {
775
1895
  const result = await runGenerateCommand({
776
- workspaceRoot: process.cwd(),
1896
+ workspaceRoot: command.workspaceRoot,
777
1897
  check: command.check,
778
1898
  dryRun: command.dryRun,
779
1899
  json: command.json,
@@ -797,10 +1917,135 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
797
1917
  }
798
1918
  return result.exitCode;
799
1919
  }
1920
+ case "manifest": {
1921
+ const result = runManifestCommand(command);
1922
+ if (command.json) {
1923
+ process.stdout.write(formatJsonResult(result));
1924
+ } else {
1925
+ process.stdout.write(formatManifestHuman(result));
1926
+ }
1927
+ return result.exitCode;
1928
+ }
1929
+ case "import": {
1930
+ const result = runBrownfieldImportCommand(command.options);
1931
+ if (command.options.json) {
1932
+ process.stdout.write(formatJsonResult(formatBrownfieldImportJson(result)));
1933
+ } else {
1934
+ process.stdout.write(formatBrownfieldImportHuman(result));
1935
+ }
1936
+ return result.exitCode;
1937
+ }
1938
+ case "status": {
1939
+ const result = runStatusCommand(command.workspaceRoot);
1940
+ if (command.json) {
1941
+ process.stdout.write(formatJsonResult(result.data));
1942
+ } else {
1943
+ process.stdout.write(formatStatusHuman(result));
1944
+ }
1945
+ return result.exitCode;
1946
+ }
1947
+ case "changed": {
1948
+ const result = runChangedCommand(command.workspaceRoot, {
1949
+ authoredOnly: command.authoredOnly,
1950
+ });
1951
+ if (command.json) {
1952
+ process.stdout.write(formatJsonResult(result.data));
1953
+ } else {
1954
+ process.stdout.write(formatChangedHuman(result));
1955
+ }
1956
+ return result.exitCode;
1957
+ }
1958
+ case "diff": {
1959
+ const changed = runChangedCommand(command.workspaceRoot);
1960
+ const diffPlan = changed.data.diffPlan as { authoredDiffCommand: string; generatedDiffCommand: string; fullDiffCommand: string };
1961
+ const commandText = command.target === "generated"
1962
+ ? diffPlan.generatedDiffCommand
1963
+ : command.target === "full"
1964
+ ? diffPlan.fullDiffCommand
1965
+ : diffPlan.authoredDiffCommand;
1966
+ if (command.json) {
1967
+ process.stdout.write(formatJsonResult({
1968
+ schemaVersion: "0.1.0",
1969
+ ok: changed.ok,
1970
+ target: command.target,
1971
+ command: commandText,
1972
+ exitCode: changed.exitCode,
1973
+ }));
1974
+ return changed.exitCode;
1975
+ }
1976
+ const result = spawnSync(commandText, {
1977
+ cwd: command.workspaceRoot,
1978
+ shell: true,
1979
+ stdio: "inherit",
1980
+ windowsHide: true,
1981
+ });
1982
+ return result.status === 0 ? 0 : 1;
1983
+ }
1984
+ case "handoff": {
1985
+ const result = await runHandoffCommand(command);
1986
+ process.stdout.write(command.json ? formatHandoffJson(result) : formatHandoffHuman(result));
1987
+ return result.exitCode;
1988
+ }
1989
+ case "studio": {
1990
+ if (command.subcommand === "bridge" && !command.once && !command.dryRun) {
1991
+ return runStudioBridgeLoop(command, (result) => {
1992
+ process.stdout.write(command.json ? formatStudioBridgeEventJson(result) : formatStudioBridgeHuman(result));
1993
+ });
1994
+ }
1995
+ if (command.subcommand === "watch" && !command.once && !command.dryRun) {
1996
+ return runStudioWatchLoop(command, (result) => {
1997
+ process.stdout.write(command.json ? formatStudioWatchJson(result) : formatStudioWatchHuman(result));
1998
+ });
1999
+ }
2000
+ const result = command.subcommand === "snapshot"
2001
+ ? await runStudioSnapshotCommand(command)
2002
+ : command.subcommand === "watch"
2003
+ ? await runStudioWatchCommand(command)
2004
+ : command.subcommand === "bridge"
2005
+ ? await runStudioBridgeCommand(command)
2006
+ : command.subcommand === "codex-server"
2007
+ ? await runStudioCodexServerCommand(command)
2008
+ : command.subcommand === "doctor"
2009
+ ? await runStudioDoctorCommand(command)
2010
+ : command.subcommand === "open"
2011
+ ? await runStudioOpenCommand(command)
2012
+ : await runStudioAttachCommand(command);
2013
+ process.stdout.write(
2014
+ command.json
2015
+ ? command.subcommand === "snapshot"
2016
+ ? formatStudioSnapshotJson(result as Awaited<ReturnType<typeof runStudioSnapshotCommand>>)
2017
+ : command.subcommand === "watch"
2018
+ ? formatStudioWatchJson(result as Awaited<ReturnType<typeof runStudioWatchCommand>>)
2019
+ : command.subcommand === "bridge"
2020
+ ? formatStudioBridgeJson(result as Awaited<ReturnType<typeof runStudioBridgeCommand>>)
2021
+ : command.subcommand === "codex-server"
2022
+ ? formatStudioCodexServerJson(result as Awaited<ReturnType<typeof runStudioCodexServerCommand>>)
2023
+ : command.subcommand === "doctor"
2024
+ ? formatStudioDoctorJson(result as Awaited<ReturnType<typeof runStudioDoctorCommand>>)
2025
+ : command.subcommand === "open"
2026
+ ? formatStudioOpenJson(result as Awaited<ReturnType<typeof runStudioOpenCommand>>)
2027
+ : formatStudioAttachJson(result as Awaited<ReturnType<typeof runStudioAttachCommand>>)
2028
+ : command.subcommand === "snapshot"
2029
+ ? formatStudioSnapshotHuman(result as Awaited<ReturnType<typeof runStudioSnapshotCommand>>)
2030
+ : command.subcommand === "watch"
2031
+ ? formatStudioWatchHuman(result as Awaited<ReturnType<typeof runStudioWatchCommand>>)
2032
+ : command.subcommand === "bridge"
2033
+ ? formatStudioBridgeHuman(result as Awaited<ReturnType<typeof runStudioBridgeCommand>>)
2034
+ : command.subcommand === "codex-server"
2035
+ ? formatStudioCodexServerHuman(result as Awaited<ReturnType<typeof runStudioCodexServerCommand>>)
2036
+ : command.subcommand === "doctor"
2037
+ ? formatStudioDoctorHuman(result as Awaited<ReturnType<typeof runStudioDoctorCommand>>)
2038
+ : command.subcommand === "open"
2039
+ ? formatStudioOpenHuman(result as Awaited<ReturnType<typeof runStudioOpenCommand>>)
2040
+ : formatStudioAttachHuman(result as Awaited<ReturnType<typeof runStudioAttachCommand>>),
2041
+ );
2042
+ return result.exitCode;
2043
+ }
800
2044
  case "inspect": {
801
2045
  const result = await runInspectCommand(
802
2046
  command.target,
803
2047
  process.cwd(),
2048
+ { full: command.full, brief: command.brief },
804
2049
  );
805
2050
  if (command.json) {
806
2051
  process.stdout.write(formatJsonResult(buildInspectJson(result)));
@@ -816,7 +2061,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
816
2061
  strictSecrets: command.strictSecrets,
817
2062
  });
818
2063
  if (command.json) {
819
- process.stdout.write(formatJsonResult(buildGenerateJson(result)));
2064
+ process.stdout.write(formatJsonResult(buildCheckJson(result)));
820
2065
  } else {
821
2066
  writeHumanGenerate(result);
822
2067
  }
@@ -838,6 +2083,32 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
838
2083
  );
839
2084
 
840
2085
  if (command.queryMode && command.name) {
2086
+ const external = resolveExternalQualifiedName(command.workspaceRoot, command.name, "query");
2087
+ if (external) {
2088
+ const run = await runExternalEntry(command.workspaceRoot, {
2089
+ kind: "query",
2090
+ serviceName: external.serviceName,
2091
+ entryName: external.entryName,
2092
+ args: command.args,
2093
+ auth: resolveAuthFromCli({
2094
+ userId: command.userId,
2095
+ tenantId: command.tenantId,
2096
+ role: command.role,
2097
+ }),
2098
+ });
2099
+ const payload = { run };
2100
+ if (command.json) {
2101
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
2102
+ } else {
2103
+ process.stdout.write(
2104
+ run.ok
2105
+ ? `${JSON.stringify(run.result, null, 2)}\n`
2106
+ : `${run.diagnostics.map((diagnostic) => `error ${diagnostic.code}: ${diagnostic.message}`).join("\n")}\n`,
2107
+ );
2108
+ }
2109
+ return run.exitCode;
2110
+ }
2111
+
841
2112
  const tableMap = readGeneratedJson<{ tableMap: Record<string, import("../compiler/data-graph/sql/serialize.ts").TableMapEntry> }>(
842
2113
  command.workspaceRoot,
843
2114
  `${GENERATED_DIR}/db.json`,
@@ -876,6 +2147,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
876
2147
  userId: command.userId,
877
2148
  tenantId: command.tenantId,
878
2149
  role: command.role,
2150
+ args: command.args,
879
2151
  workspaceRoot: command.workspaceRoot,
880
2152
  });
881
2153
 
@@ -913,6 +2185,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
913
2185
  webPort: command.webPort,
914
2186
  telemetry: command.telemetry,
915
2187
  envFile: command.envFile,
2188
+ skipStartupConsole: command.skipStartupConsole,
916
2189
  });
917
2190
  return result.exitCode;
918
2191
  }
@@ -1111,6 +2384,11 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
1111
2384
  model: command.model,
1112
2385
  prompt: command.prompt,
1113
2386
  mock: command.mock,
2387
+ modelLevel: command.modelLevel,
2388
+ live: command.live,
2389
+ traceId: command.traceId,
2390
+ db: command.db,
2391
+ databaseUrl: command.databaseUrl,
1114
2392
  });
1115
2393
 
1116
2394
  if (command.json) {
@@ -1126,5 +2404,5 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
1126
2404
  }
1127
2405
  }
1128
2406
 
1129
- export { runVerifyCommand };
2407
+ export { runChangedCommand, runVerifyCommand };
1130
2408
  export type { VerifyOptions, VerifyResult };