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,7 +1,9 @@
1
1
  import type { DevRoute } from "../compiler/types/dev-manifest.ts";
2
2
  import type { DbAdapter } from "../runtime/db/adapter.ts";
3
+ import type { AmbientDeltaRecorder } from "../delta/recorder.ts";
4
+ import type { Diagnostic } from "../compiler/types/diagnostic.ts";
3
5
 
4
- export type DevDbMode = "pglite" | "postgres" | "none";
6
+ export type DevDbMode = "memory" | "pglite" | "postgres" | "none";
5
7
 
6
8
  export interface DevServerOptions {
7
9
  workspaceRoot: string;
@@ -18,6 +20,7 @@ export interface DevServerOptions {
18
20
  mode?: "dev" | "serve";
19
21
  allowDevAuth?: boolean;
20
22
  webUrl?: string;
23
+ deltaRecorder?: AmbientDeltaRecorder;
21
24
  }
22
25
 
23
26
  export interface DevServerDbState {
@@ -41,9 +44,20 @@ export interface DevServerHandle {
41
44
  routes: DevRoute[];
42
45
  state: DevServerState;
43
46
  outboxWorker?: DevServerState["outboxWorker"];
47
+ reload: (reason?: string) => Promise<DevServerReloadResult>;
44
48
  stop: () => void;
45
49
  }
46
50
 
51
+ export interface DevServerReloadResult {
52
+ ok: boolean;
53
+ reason: string;
54
+ migrated: boolean;
55
+ routes: number;
56
+ runtimeEntries: number;
57
+ worker: "running" | "stopped";
58
+ diagnostics: Diagnostic[];
59
+ }
60
+
47
61
  export interface DevWatchHandle {
48
62
  stop: () => void;
49
63
  }
@@ -21,28 +21,38 @@ export function shouldSkipWatchPath(absolutePath: string): boolean {
21
21
 
22
22
  export function createDebouncedCallback(
23
23
  debounceMs: number,
24
- callback: (changedCount: number) => void | Promise<void>,
25
- ): (increment?: number) => void {
24
+ callback: (changedCount: number, changedPaths: string[]) => void | Promise<void>,
25
+ ): (incrementOrPath?: number | string) => void {
26
26
  let pendingChanges = 0;
27
+ const pendingPaths = new Set<string>();
27
28
  let timer: ReturnType<typeof setTimeout> | null = null;
28
29
 
29
- return (increment = 1) => {
30
- pendingChanges += increment;
30
+ return (incrementOrPath) => {
31
+ if (typeof incrementOrPath === "number") {
32
+ pendingChanges += incrementOrPath;
33
+ } else {
34
+ pendingChanges += 1;
35
+ }
36
+ if (typeof incrementOrPath === "string") {
37
+ pendingPaths.add(incrementOrPath);
38
+ }
31
39
  if (timer !== null) {
32
40
  clearTimeout(timer);
33
41
  }
34
42
  timer = setTimeout(async () => {
35
43
  const count = pendingChanges;
44
+ const paths = [...pendingPaths].sort();
36
45
  pendingChanges = 0;
46
+ pendingPaths.clear();
37
47
  timer = null;
38
- await callback(count);
48
+ await callback(count, paths);
39
49
  }, debounceMs);
40
50
  };
41
51
  }
42
52
 
43
53
  export function startDevWatch(
44
54
  workspaceRoot: string,
45
- onRegenerate: (changedCount: number) => void | Promise<void>,
55
+ onRegenerate: (changedCount: number, changedPaths: string[]) => void | Promise<void>,
46
56
  ): DevWatchHandle {
47
57
  const roots = getSourceRoots(workspaceRoot);
48
58
  const watchers: FSWatcher[] = [];
@@ -71,7 +81,7 @@ export function startDevWatch(
71
81
  return;
72
82
  }
73
83
 
74
- debounced();
84
+ debounced(relativePath);
75
85
  },
76
86
  );
77
87
 
@@ -1,5 +1,5 @@
1
1
  import { nodeFileSystem } from "../compiler/fs/index.ts";
2
- import { join } from "node:path";
2
+ import { basename, join } from "node:path";
3
3
  import { buildAppGraph } from "../compiler/app-graph/build.ts";
4
4
  import { classify } from "../compiler/classifier/classify.ts";
5
5
  import { buildRuntimeMatrix } from "../compiler/classifier/runtime-matrix.ts";
@@ -26,8 +26,12 @@ import { runImpactCommand } from "../impact/index.ts";
26
26
  import type { TestRunRecord } from "../impact/types.ts";
27
27
  import { loadSecretRegistry } from "../runtime/secrets/check.ts";
28
28
  import type { UiRunReport } from "../ui/types.ts";
29
+ import { buildDiffPlanFromChangeSummary, categorizeFiles, summarizeChangeTypes } from "../workspace/change-summary.ts";
30
+ import { forgeCliCommandForWorkspace, forgeCliCommandsForWorkspace } from "../workspace/forge-cli.ts";
29
31
  import type {
30
32
  DevConsoleCycle,
33
+ DevConsoleAgentContext,
34
+ DevConsoleGeneratedSummary,
31
35
  DevConsoleNextAction,
32
36
  DevConsoleOptions,
33
37
  DevConsolePhase,
@@ -117,17 +121,30 @@ function skippedPhase(
117
121
  };
118
122
  }
119
123
 
124
+ function compactFileList(files: string[], sampleSize = 12): {
125
+ count: number;
126
+ sample: string[];
127
+ hidden: number;
128
+ } {
129
+ return {
130
+ count: files.length,
131
+ sample: files.slice(0, sampleSize),
132
+ hidden: Math.max(0, files.length - sampleSize),
133
+ };
134
+ }
135
+
120
136
  async function runGeneratedPhase(workspaceRoot: string): Promise<DevConsolePhase> {
121
137
  const start = performance.now();
122
138
  const result = await runGenerate({
123
139
  workspaceRoot,
124
- check: true,
140
+ check: false,
125
141
  dryRun: false,
126
142
  json: false,
127
143
  concurrency: 4,
128
144
  });
129
145
  const diagnostics = [...result.errors, ...result.warnings];
130
146
  const durationMs = msSince(start);
147
+ const changed = compactFileList(result.changed);
131
148
  return {
132
149
  name: "generated",
133
150
  ok: result.exitCode === 0,
@@ -135,11 +152,18 @@ async function runGeneratedPhase(workspaceRoot: string): Promise<DevConsolePhase
135
152
  diagnostics,
136
153
  durationMs,
137
154
  details: {
138
- changed: result.changed,
155
+ changed: changed.count,
156
+ sampleChanged: changed.sample,
157
+ hiddenChanged: changed.hidden,
139
158
  unchangedCount: result.unchanged.length,
159
+ fullCommand: forgeCliCommandForWorkspace(workspaceRoot, "forge generate --json"),
140
160
  ...(result.cache ? { cache: result.cache } : {}),
141
161
  },
142
- message: result.exitCode === 0 ? "generated artifacts are up to date" : "generated artifacts are stale",
162
+ message: result.exitCode === 0
163
+ ? result.changed.length > 0
164
+ ? `regenerated ${result.changed.length} generated artifacts`
165
+ : "generated artifacts are up to date"
166
+ : "generated artifacts could not be regenerated",
143
167
  };
144
168
  }
145
169
 
@@ -179,6 +203,8 @@ function requiredGeneratedArtifacts(workspaceRoot: string): Array<{ name: string
179
203
  { name: "agents-md", path: "AGENTS.md", ok: nodeFileSystem.exists(join(workspaceRoot, "AGENTS.md")) },
180
204
  { name: "forge-lock", path: "forge.lock", ok: nodeFileSystem.exists(join(workspaceRoot, "forge.lock")) },
181
205
  { name: "agent-contract", path: `${GENERATED_DIR}/agentContract.json`, ok: nodeFileSystem.exists(join(workspaceRoot, GENERATED_DIR, "agentContract.json")) },
206
+ { name: "agent-quickstart", path: `${GENERATED_DIR}/agentQuickstart.md`, ok: nodeFileSystem.exists(join(workspaceRoot, GENERATED_DIR, "agentQuickstart.md")) },
207
+ { name: "agent-cair-guide", path: `${GENERATED_DIR}/agentCairGuide.md`, ok: nodeFileSystem.exists(join(workspaceRoot, GENERATED_DIR, "agentCairGuide.md")) },
182
208
  { name: "capability-map", path: `${GENERATED_DIR}/capabilityMap.json`, ok: nodeFileSystem.exists(join(workspaceRoot, GENERATED_DIR, "capabilityMap.json")) },
183
209
  { name: "runtime-matrix", path: `${GENERATED_DIR}/runtimeMatrix.json`, ok: nodeFileSystem.exists(join(workspaceRoot, GENERATED_DIR, "runtimeMatrix.json")) },
184
210
  { name: "data-graph", path: `${GENERATED_DIR}/dataGraph.json`, ok: nodeFileSystem.exists(join(workspaceRoot, GENERATED_DIR, "dataGraph.json")) },
@@ -260,7 +286,21 @@ function runDoctorPhase(workspaceRoot: string): DevConsolePhase {
260
286
  );
261
287
  }
262
288
 
263
- function runFrontendPhase(workspaceRoot: string): DevConsolePhase {
289
+ function withRuntimeFrontendUrls(
290
+ summary: FrontendSummary,
291
+ options: { apiUrl?: string; webUrl?: string },
292
+ ): FrontendSummary {
293
+ return {
294
+ ...summary,
295
+ ...(options.apiUrl ? { apiUrl: options.apiUrl } : {}),
296
+ ...(options.webUrl ? { devUrl: options.webUrl } : {}),
297
+ };
298
+ }
299
+
300
+ function runFrontendPhase(
301
+ workspaceRoot: string,
302
+ options: { apiUrl?: string; webUrl?: string } = {},
303
+ ): DevConsolePhase {
264
304
  const start = performance.now();
265
305
  const frontend = readJson<FrontendGraph>(workspaceRoot, `${GENERATED_DIR}/frontendGraph.json`);
266
306
  if (!frontend) {
@@ -274,7 +314,7 @@ function runFrontendPhase(workspaceRoot: string): DevConsolePhase {
274
314
  };
275
315
  }
276
316
 
277
- const summary: FrontendSummary = {
317
+ const summary: FrontendSummary = withRuntimeFrontendUrls({
278
318
  present: frontend.present,
279
319
  framework: frontend.framework,
280
320
  routes: frontend.routes.map((route) => route.path),
@@ -282,7 +322,7 @@ function runFrontendPhase(workspaceRoot: string): DevConsolePhase {
282
322
  bridgeFiles: frontend.bridgeFiles,
283
323
  apiUrl: frontend.webManifest.urls.api,
284
324
  ...(frontend.dev ? { devUrl: frontend.dev.url, apiUrlEnv: frontend.dev.apiUrlEnv } : {}),
285
- };
325
+ }, options);
286
326
  const diagnostics = frontend.diagnostics ?? [];
287
327
  const message = frontend.present
288
328
  ? `frontend ${frontend.framework} with ${frontend.routes.length} routes and ${frontend.clientBindings.length} bindings`
@@ -305,23 +345,102 @@ function defaultFrontendSummary(workspaceRoot: string): FrontendSummary {
305
345
  };
306
346
  }
307
347
 
348
+ function nextPreviewPort(webUrl?: string): number {
349
+ if (!webUrl) {
350
+ return 5174;
351
+ }
352
+ try {
353
+ const parsed = new URL(webUrl);
354
+ const port = parsed.port ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80;
355
+ return Number.isFinite(port) && port > 0 ? port + 1 : 5174;
356
+ } catch {
357
+ return 5174;
358
+ }
359
+ }
360
+
361
+ function isForgeStudioWorkspace(workspaceRoot: string): boolean {
362
+ return basename(workspaceRoot).toLowerCase() === "forge-studio";
363
+ }
364
+
365
+ function previewSummaryFor(input: {
366
+ workspaceRoot: string;
367
+ webUrl?: string;
368
+ }): DevConsoleSummary["preview"] {
369
+ if (input.webUrl && !isForgeStudioWorkspace(input.workspaceRoot)) {
370
+ const parsed = new URL(input.webUrl);
371
+ const targetAppPort = parsed.port ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80;
372
+ return {
373
+ targetAppUrl: input.webUrl,
374
+ targetAppPort,
375
+ isStudioSelfPreview: false,
376
+ note: `Web app preview is running at ${input.webUrl}.`,
377
+ };
378
+ }
379
+
380
+ const targetAppPort = nextPreviewPort(input.webUrl);
381
+ const targetAppUrl = `http://127.0.0.1:${targetAppPort}`;
382
+ const isStudioSelfPreview = Boolean(input.webUrl && input.webUrl === targetAppUrl);
383
+ return {
384
+ ...(input.webUrl ? { studioUrl: input.webUrl } : {}),
385
+ targetAppUrl,
386
+ targetAppPort,
387
+ isStudioSelfPreview,
388
+ note: input.webUrl
389
+ ? `Use ${targetAppUrl} for the app being built when ${input.webUrl} is Forge Studio itself.`
390
+ : `No web app was detected; ${targetAppUrl} is the default target app preview URL for Studio attach flows.`,
391
+ };
392
+ }
393
+
394
+ function buildGeneratedSummary(workspaceRoot: string, phaseItem: DevConsolePhase | undefined): DevConsoleGeneratedSummary {
395
+ const changedFiles = Number(phaseItem?.details?.changed ?? 0);
396
+ const sampleChanged = Array.isArray(phaseItem?.details?.sampleChanged)
397
+ ? phaseItem.details.sampleChanged.filter((item): item is string => typeof item === "string")
398
+ : [];
399
+ const hiddenChanged = Number(phaseItem?.details?.hiddenChanged ?? 0);
400
+ return {
401
+ ok: phaseItem?.ok === true,
402
+ state: phaseItem?.ok === true
403
+ ? changedFiles > 0 ? "regenerated" : "fresh"
404
+ : "stale-risk",
405
+ changedFiles,
406
+ sampleChanged,
407
+ hiddenChanged,
408
+ message: phaseItem?.message ?? "generated phase did not report a message",
409
+ command: forgeCliCommandForWorkspace(workspaceRoot, "forge generate"),
410
+ checkCommand: forgeCliCommandForWorkspace(workspaceRoot, "forge generate --check --json"),
411
+ };
412
+ }
413
+
308
414
  function buildDevSummary(input: {
309
415
  workspaceRoot: string;
310
416
  ok: boolean;
311
417
  phases: DevConsolePhase[];
312
418
  diagnostics: Diagnostic[];
313
419
  nextActions: DevConsoleNextAction[];
420
+ apiUrl?: string;
421
+ webUrl?: string;
314
422
  }): DevConsoleSummary {
315
423
  const frontendPhase = input.phases.find((item) => item.name === "frontend");
316
- const frontend =
424
+ const frontendBase =
317
425
  (frontendPhase?.details?.summary as FrontendSummary | undefined) ??
318
426
  defaultFrontendSummary(input.workspaceRoot);
427
+ const frontend = withRuntimeFrontendUrls(frontendBase, {
428
+ ...(input.apiUrl ? { apiUrl: input.apiUrl } : {}),
429
+ ...(input.webUrl ? { webUrl: input.webUrl } : {}),
430
+ });
319
431
  const capabilityMap = readJson<AgentCapabilityMap>(
320
432
  input.workspaceRoot,
321
433
  `${GENERATED_DIR}/capabilityMap.json`,
322
434
  );
323
435
  const warnings = input.diagnostics.filter((diagnostic) => diagnostic.severity === "warning").length;
324
436
  const errors = input.diagnostics.filter((diagnostic) => diagnostic.severity === "error").length;
437
+ const apiUrl = input.apiUrl ?? frontend.apiUrl ?? "http://127.0.0.1:3765";
438
+ const webUrl = input.webUrl ?? frontend.devUrl;
439
+ const generated = buildGeneratedSummary(input.workspaceRoot, input.phases.find((item) => item.name === "generated"));
440
+ const preview = previewSummaryFor({
441
+ workspaceRoot: input.workspaceRoot,
442
+ ...(webUrl ? { webUrl } : {}),
443
+ });
325
444
  return {
326
445
  project: {
327
446
  root: input.workspaceRoot,
@@ -333,9 +452,12 @@ function buildDevSummary(input: {
333
452
  skipped: input.phases.filter((item) => item.status === "skipped").length,
334
453
  },
335
454
  urls: {
336
- api: frontend.apiUrl ?? "http://127.0.0.1:3765",
337
- ...(frontend.devUrl ? { web: frontend.devUrl } : {}),
455
+ api: apiUrl,
456
+ ...(webUrl ? { web: webUrl } : {}),
457
+ suggestedPreview: preview.targetAppUrl,
338
458
  },
459
+ preview,
460
+ generated,
339
461
  frontend,
340
462
  capabilities: capabilityMap?.summary ?? {
341
463
  covered: 0,
@@ -343,6 +465,12 @@ function buildDevSummary(input: {
343
465
  frontendOnly: 0,
344
466
  warnings: 0,
345
467
  },
468
+ agentContext: buildAgentContext({
469
+ workspaceRoot: input.workspaceRoot,
470
+ phases: input.phases,
471
+ diagnostics: input.diagnostics,
472
+ nextActions: input.nextActions,
473
+ }),
346
474
  ...(input.nextActions[0] ? { primaryAction: input.nextActions[0] } : {}),
347
475
  };
348
476
  }
@@ -370,18 +498,28 @@ function runImpactPhase(workspaceRoot: string): DevConsolePhase {
370
498
  }
371
499
  const report = result.report;
372
500
  const summary: ImpactSummary | undefined = report
373
- ? {
374
- changedFiles: report.changedFiles,
375
- risk: report.risk.level,
376
- recommendedChecks: report.recommendedChecks,
377
- }
501
+ ? (() => {
502
+ const changeSummary = categorizeFiles(report.changedFiles);
503
+ return {
504
+ changedFiles: report.changedFiles.length,
505
+ sampleChangedFiles: report.changedFiles.slice(0, 12),
506
+ hiddenChangedFiles: Math.max(0, report.changedFiles.length - 12),
507
+ changeSummary,
508
+ risk: report.risk.level,
509
+ recommendedChecks: report.recommendedChecks,
510
+ fullCommand: "forge impact --changed --json",
511
+ };
512
+ })()
378
513
  : undefined;
514
+ const changeTypes = summary ? summarizeChangeTypes(summary.changeSummary) : "";
379
515
  return phase(
380
516
  "impact",
381
517
  result.diagnostics,
382
518
  msSince(start),
383
519
  summary ? { summary } : undefined,
384
- summary && summary.changedFiles.length > 0 ? `${summary.changedFiles.length} changed files detected` : "no changed files detected",
520
+ summary && summary.changedFiles > 0
521
+ ? `${summary.changedFiles} changed files detected${changeTypes ? `: ${changeTypes}` : ""}`
522
+ : "no changed files detected",
385
523
  );
386
524
  }
387
525
 
@@ -469,7 +607,7 @@ function uniqueActions(actions: DevConsoleNextAction[]): DevConsoleNextAction[]
469
607
  return result;
470
608
  }
471
609
 
472
- function nextActionsFromPhases(phases: DevConsolePhase[]): DevConsoleNextAction[] {
610
+ function nextActionsFromPhases(workspaceRoot: string, phases: DevConsolePhase[]): DevConsoleNextAction[] {
473
611
  const actions: DevConsoleNextAction[] = [];
474
612
  const diagnostics = phases.flatMap((item) => item.diagnostics);
475
613
  if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
@@ -512,7 +650,12 @@ function nextActionsFromPhases(phases: DevConsolePhase[]): DevConsoleNextAction[
512
650
 
513
651
  const impact = phases.find((item) => item.name === "impact");
514
652
  const summary = impact?.details?.summary as ImpactSummary | undefined;
515
- if (summary && summary.changedFiles.length > 0) {
653
+ if (summary && summary.changedFiles > 0) {
654
+ actions.push({
655
+ command: "forge changed --json",
656
+ reason: "changed files were detected; inspect grouped human and generated changes first",
657
+ confidence: "high",
658
+ });
516
659
  actions.push({
517
660
  command: "forge do verify --json",
518
661
  reason: "changed files were detected; use the guided verification path",
@@ -538,7 +681,60 @@ function nextActionsFromPhases(phases: DevConsolePhase[]): DevConsoleNextAction[
538
681
  });
539
682
  }
540
683
 
541
- return uniqueActions(actions).slice(0, 12);
684
+ return uniqueActions(actions).slice(0, 12).map((action) => ({
685
+ ...action,
686
+ command: forgeCliCommandForWorkspace(workspaceRoot, action.command),
687
+ }));
688
+ }
689
+
690
+ function phaseDetails<T>(phases: DevConsolePhase[], name: DevConsolePhase["name"], key: string): T | undefined {
691
+ return phases.find((item) => item.name === name)?.details?.[key] as T | undefined;
692
+ }
693
+
694
+ function buildAgentContext(input: {
695
+ workspaceRoot: string;
696
+ phases: DevConsolePhase[];
697
+ diagnostics: Diagnostic[];
698
+ nextActions: DevConsoleNextAction[];
699
+ }): DevConsoleAgentContext {
700
+ const generated = input.phases.find((item) => item.name === "generated");
701
+ const frontend = phaseDetails<FrontendSummary>(input.phases, "frontend", "summary");
702
+ const impact = phaseDetails<ImpactSummary>(input.phases, "impact", "summary");
703
+ const errorDiagnostics = input.diagnostics.filter((diagnostic) => diagnostic.severity === "error");
704
+ const warningDiagnostics = input.diagnostics.filter((diagnostic) => diagnostic.severity === "warning");
705
+ const generatedChangedFiles = Number(generated?.details?.changed ?? 0);
706
+ const suggestedReadFiles = [
707
+ "AGENTS.md",
708
+ "src/forge/_generated/agentContract.json",
709
+ "src/forge/_generated/appMap.md",
710
+ "src/forge/_generated/runtimeRules.md",
711
+ "src/forge/_generated/operationPlaybooks.md",
712
+ ...(frontend?.present ? ["src/forge/_generated/frontendGraph.json"] : []),
713
+ ...input.diagnostics.flatMap((diagnostic) => diagnostic.docs ?? []),
714
+ ...input.diagnostics.flatMap((diagnostic) => diagnostic.file ? [diagnostic.file] : []),
715
+ ];
716
+ const fullCommands = forgeCliCommandsForWorkspace(input.workspaceRoot, [
717
+ "forge inspect all --full --json",
718
+ "forge changed --json",
719
+ "forge impact --changed --json",
720
+ "forge generate --json",
721
+ ]);
722
+ return {
723
+ safeToEdit: generated?.ok === true && errorDiagnostics.length === 0,
724
+ generatedFresh: generated?.ok === true,
725
+ generatedChanged: generatedChangedFiles > 0,
726
+ generatedChangedFiles,
727
+ frontendReady: frontend?.present ? frontend.bridgeFiles.length > 0 : false,
728
+ changedFiles: impact?.changedFiles ?? 0,
729
+ ...(impact?.changeSummary ? { changeSummary: impact.changeSummary } : {}),
730
+ ...(impact?.changeSummary ? { diffPlan: buildDiffPlanFromChangeSummary(impact.changeSummary) } : {}),
731
+ blockingIssues: errorDiagnostics.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`).slice(0, 8),
732
+ recommendedReadFiles: [...new Set(suggestedReadFiles)].slice(0, 12),
733
+ recommendedCommands: input.nextActions.map((action) => action.command).slice(0, 8),
734
+ useFullCommands: warningDiagnostics.length > 0 || (impact?.hiddenChangedFiles ?? 0) > 0
735
+ ? fullCommands
736
+ : fullCommands.slice(0, 1),
737
+ };
542
738
  }
543
739
 
544
740
  export async function runDevConsoleCycle(options: DevConsoleOptions): Promise<DevConsoleCycle> {
@@ -549,7 +745,10 @@ export async function runDevConsoleCycle(options: DevConsoleOptions): Promise<De
549
745
  phases.push(generated);
550
746
  if (generated.ok) {
551
747
  phases.push(await runCheckPhase(workspaceRoot, options.strictSecrets ?? false));
552
- phases.push(runFrontendPhase(workspaceRoot));
748
+ phases.push(runFrontendPhase(workspaceRoot, {
749
+ ...(options.apiUrl ? { apiUrl: options.apiUrl } : {}),
750
+ ...(options.webUrl ? { webUrl: options.webUrl } : {}),
751
+ }));
553
752
  } else {
554
753
  phases.push(
555
754
  skippedPhase(
@@ -573,13 +772,15 @@ export async function runDevConsoleCycle(options: DevConsoleOptions): Promise<De
573
772
 
574
773
  const diagnostics = phases.flatMap((item) => item.diagnostics);
575
774
  const ok = phases.every((item) => item.ok);
576
- const nextActions = nextActionsFromPhases(phases);
775
+ const nextActions = nextActionsFromPhases(workspaceRoot, phases);
577
776
  const summary = buildDevSummary({
578
777
  workspaceRoot,
579
778
  ok,
580
779
  phases,
581
780
  diagnostics,
582
781
  nextActions,
782
+ ...(options.apiUrl ? { apiUrl: options.apiUrl } : {}),
783
+ ...(options.webUrl ? { webUrl: options.webUrl } : {}),
583
784
  });
584
785
  return {
585
786
  schemaVersion: "0.1.0",
@@ -603,6 +804,17 @@ export function formatDevConsoleHuman(cycle: DevConsoleCycle): string {
603
804
  lines.push(`Project: ${cycle.summary.project.root}`);
604
805
  lines.push(`API: ${cycle.summary.urls.api}`);
605
806
  lines.push(`Web: ${cycle.summary.urls.web ?? "none detected"}`);
807
+ lines.push(`Target preview: ${cycle.summary.preview.targetAppUrl}`);
808
+ lines.push(
809
+ `Generated: ${cycle.summary.generated.state}` +
810
+ (cycle.summary.generated.changedFiles > 0 ? ` (${cycle.summary.generated.changedFiles} changed)` : ""),
811
+ );
812
+ if (cycle.summary.agentContext.diffPlan) {
813
+ lines.push(`Diff focus: ${cycle.summary.agentContext.diffPlan.summary}`);
814
+ }
815
+ if (cycle.summary.preview.isStudioSelfPreview) {
816
+ lines.push("Preview warning: target preview points at the Studio URL");
817
+ }
606
818
  lines.push(
607
819
  `Frontend: ${cycle.summary.frontend.present ? cycle.summary.frontend.framework : "none"} ` +
608
820
  `(${cycle.summary.frontend.routes.length} routes, ${cycle.summary.frontend.bindings.length} bindings)`,
@@ -1,5 +1,6 @@
1
1
  import type { Diagnostic } from "../compiler/types/diagnostic.ts";
2
2
  import type { ImpactRiskLevel } from "../impact/types.ts";
3
+ import type { CategorizedFileSummary, DiffPlan } from "../workspace/change-summary.ts";
3
4
 
4
5
  export type DevConsolePhaseName =
5
6
  | "generated"
@@ -39,7 +40,16 @@ export interface DevConsoleSummary {
39
40
  urls: {
40
41
  api: string;
41
42
  web?: string;
43
+ suggestedPreview?: string;
42
44
  };
45
+ preview: {
46
+ studioUrl?: string;
47
+ targetAppUrl: string;
48
+ targetAppPort: number;
49
+ isStudioSelfPreview: boolean;
50
+ note: string;
51
+ };
52
+ generated: DevConsoleGeneratedSummary;
43
53
  frontend: FrontendSummary;
44
54
  capabilities: {
45
55
  covered: number;
@@ -47,6 +57,7 @@ export interface DevConsoleSummary {
47
57
  frontendOnly: number;
48
58
  warnings: number;
49
59
  };
60
+ agentContext: DevConsoleAgentContext;
50
61
  primaryAction?: DevConsoleNextAction;
51
62
  }
52
63
 
@@ -66,6 +77,8 @@ export interface DevConsoleOptions {
66
77
  mode: DevConsoleCycle["mode"];
67
78
  strictSecrets?: boolean;
68
79
  includeImpact?: boolean;
80
+ apiUrl?: string;
81
+ webUrl?: string;
69
82
  }
70
83
 
71
84
  export interface LastTestRunSummary {
@@ -82,9 +95,41 @@ export interface LastUiRunSummary {
82
95
  }
83
96
 
84
97
  export interface ImpactSummary {
85
- changedFiles: string[];
98
+ changedFiles: number;
99
+ sampleChangedFiles: string[];
100
+ hiddenChangedFiles: number;
101
+ changeSummary: CategorizedFileSummary;
86
102
  risk: ImpactRiskLevel;
87
103
  recommendedChecks: string[];
104
+ fullCommand: string;
105
+ }
106
+
107
+ export interface DevConsoleGeneratedSummary {
108
+ ok: boolean;
109
+ state: "fresh" | "regenerated" | "stale-risk";
110
+ changedFiles: number;
111
+ sampleChanged: string[];
112
+ hiddenChanged: number;
113
+ message: string;
114
+ command: string;
115
+ checkCommand: string;
116
+ }
117
+
118
+ export type DevConsoleDiffPlan = DiffPlan;
119
+
120
+ export interface DevConsoleAgentContext {
121
+ safeToEdit: boolean;
122
+ generatedFresh: boolean;
123
+ generatedChanged: boolean;
124
+ generatedChangedFiles: number;
125
+ frontendReady: boolean;
126
+ changedFiles: number;
127
+ changeSummary?: CategorizedFileSummary;
128
+ diffPlan?: DevConsoleDiffPlan;
129
+ blockingIssues: string[];
130
+ recommendedReadFiles: string[];
131
+ recommendedCommands: string[];
132
+ useFullCommands: string[];
88
133
  }
89
134
 
90
135
  export interface FrontendSummary {