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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/.npmignore +10 -0
  2. package/AGENTS.md +142 -90
  3. package/CHANGELOG.md +433 -0
  4. package/LICENSE +21 -0
  5. package/README.md +67 -8
  6. package/adapters/go/README.md +23 -0
  7. package/adapters/go/go.mod +3 -0
  8. package/adapters/go/http.go +149 -0
  9. package/adapters/go/registry.go +234 -0
  10. package/adapters/go/types.go +136 -0
  11. package/adapters/java/README.md +68 -0
  12. package/adapters/java/pom.xml +34 -0
  13. package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
  14. package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
  15. package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
  16. package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
  17. package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
  18. package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
  19. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
  20. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
  21. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
  22. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
  23. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
  24. package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
  25. package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
  26. package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
  27. package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
  28. package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
  29. package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
  30. package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
  31. package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
  32. package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
  33. package/adapters/java-spring-boot-starter/README.md +32 -0
  34. package/adapters/java-spring-boot-starter/pom.xml +36 -0
  35. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
  36. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
  37. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
  38. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
  39. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
  40. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
  41. package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  42. package/bin/forge.mjs +18 -0
  43. package/docs/cair-protocol.md +103 -0
  44. package/docs/changelog.md +548 -0
  45. package/docs/forge-protocol.md +189 -0
  46. package/examples/go-billing/go.mod +7 -0
  47. package/examples/go-billing/main.go +120 -0
  48. package/examples/java-billing/pom.xml +52 -0
  49. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
  50. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
  51. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
  52. package/package.json +31 -3
  53. package/schemas/forge-manifest.schema.json +57 -0
  54. package/src/forge/_generated/releaseManifest.json +1 -2
  55. package/src/forge/_generated/releaseManifest.ts +3 -3
  56. package/src/forge/agent-adapters/index.ts +1584 -125
  57. package/src/forge/agent-adapters/types.ts +224 -1
  58. package/src/forge/agent-memory/bridge.ts +1333 -0
  59. package/src/forge/agent-memory/context-pack.ts +277 -0
  60. package/src/forge/agent-memory/hook-runner.ts +312 -0
  61. package/src/forge/agent-memory/mcp.ts +224 -0
  62. package/src/forge/agent-memory/normalize.ts +498 -0
  63. package/src/forge/agent-memory/redaction.ts +103 -0
  64. package/src/forge/agent-memory/sources/claude-code.ts +51 -0
  65. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +273 -0
  66. package/src/forge/agent-memory/sources/codex.ts +119 -0
  67. package/src/forge/agent-memory/sources/cursor.ts +35 -0
  68. package/src/forge/agent-memory/types.ts +204 -0
  69. package/src/forge/bench.ts +248 -0
  70. package/src/forge/brownfield-import/index.ts +801 -0
  71. package/src/forge/brownfield-import/types.ts +127 -0
  72. package/src/forge/cair/action-journal.ts +61 -0
  73. package/src/forge/cair/action-parser.ts +314 -0
  74. package/src/forge/cair/action-validator.ts +40 -0
  75. package/src/forge/cair/actions.ts +1818 -0
  76. package/src/forge/cair/format.ts +77 -0
  77. package/src/forge/cair/index.ts +106 -0
  78. package/src/forge/cair/query.ts +478 -0
  79. package/src/forge/cair/snapshot.ts +315 -0
  80. package/src/forge/cair/types.ts +248 -0
  81. package/src/forge/cli/ai.ts +339 -21
  82. package/src/forge/cli/auth.ts +348 -10
  83. package/src/forge/cli/authmd.ts +441 -0
  84. package/src/forge/cli/baseline.ts +112 -0
  85. package/src/forge/cli/build.ts +20 -4
  86. package/src/forge/cli/changed.ts +437 -0
  87. package/src/forge/cli/codex-app-server.ts +877 -0
  88. package/src/forge/cli/commands.ts +1620 -20
  89. package/src/forge/cli/db.ts +209 -2
  90. package/src/forge/cli/deploy.ts +887 -0
  91. package/src/forge/cli/deps.ts +82 -13
  92. package/src/forge/cli/dev.ts +961 -46
  93. package/src/forge/cli/docs.ts +265 -0
  94. package/src/forge/cli/doctor.ts +297 -0
  95. package/src/forge/cli/field-test.ts +329 -0
  96. package/src/forge/cli/handoff.ts +336 -0
  97. package/src/forge/cli/index.ts +1 -0
  98. package/src/forge/cli/last-run.ts +84 -0
  99. package/src/forge/cli/main.ts +107 -3
  100. package/src/forge/cli/new.ts +152 -13
  101. package/src/forge/cli/next-actions.ts +23 -0
  102. package/src/forge/cli/output.ts +389 -6
  103. package/src/forge/cli/parse.ts +1050 -34
  104. package/src/forge/cli/progress.ts +51 -0
  105. package/src/forge/cli/query.ts +32 -0
  106. package/src/forge/cli/release.ts +35 -11
  107. package/src/forge/cli/rls.ts +43 -4
  108. package/src/forge/cli/run.ts +41 -0
  109. package/src/forge/cli/security.ts +112 -0
  110. package/src/forge/cli/self-host.ts +56 -14
  111. package/src/forge/cli/studio.ts +2218 -0
  112. package/src/forge/cli/verify.ts +1455 -32
  113. package/src/forge/cli/windows.ts +23 -0
  114. package/src/forge/cli/workos.ts +1020 -0
  115. package/src/forge/compiler/agent-contract/build.ts +670 -64
  116. package/src/forge/compiler/agent-contract/types.ts +45 -2
  117. package/src/forge/compiler/ai-registry/parse.ts +71 -2
  118. package/src/forge/compiler/api-surface/build.ts +47 -0
  119. package/src/forge/compiler/app-graph/build.ts +112 -9
  120. package/src/forge/compiler/app-graph/extract.ts +107 -0
  121. package/src/forge/compiler/app-graph/module-graph.ts +73 -78
  122. package/src/forge/compiler/app-graph/parser.ts +24 -24
  123. package/src/forge/compiler/app-graph/profile.ts +26 -0
  124. package/src/forge/compiler/app-graph/versions.ts +1 -1
  125. package/src/forge/compiler/classifier/capabilities.ts +3 -2
  126. package/src/forge/compiler/classifier/classify.ts +32 -8
  127. package/src/forge/compiler/classifier/secrets.ts +3 -2
  128. package/src/forge/compiler/classifier/signals.ts +91 -1
  129. package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
  130. package/src/forge/compiler/client-sdk/render-client.ts +295 -13
  131. package/src/forge/compiler/data-graph/parse.ts +20 -4
  132. package/src/forge/compiler/data-graph/sql/ddl.ts +144 -31
  133. package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
  134. package/src/forge/compiler/data-graph/sql/types.ts +1 -0
  135. package/src/forge/compiler/diagnostics/codes.ts +30 -0
  136. package/src/forge/compiler/diagnostics/create.ts +21 -2
  137. package/src/forge/compiler/diagnostics/index.ts +2 -0
  138. package/src/forge/compiler/emitter/barrel.ts +3 -0
  139. package/src/forge/compiler/emitter/render.ts +9 -0
  140. package/src/forge/compiler/external-manifest/registry.ts +205 -0
  141. package/src/forge/compiler/external-manifest/types.ts +91 -0
  142. package/src/forge/compiler/external-manifest/validate.ts +373 -0
  143. package/src/forge/compiler/frontend-graph/build.ts +142 -14
  144. package/src/forge/compiler/integration/add.ts +618 -24
  145. package/src/forge/compiler/integration/plan.ts +43 -12
  146. package/src/forge/compiler/integration/render.ts +29 -0
  147. package/src/forge/compiler/integration/snapshot.ts +2 -0
  148. package/src/forge/compiler/integration/templates/convex.ts +70 -0
  149. package/src/forge/compiler/integration/templates/index.ts +1 -0
  150. package/src/forge/compiler/integration/templates/render.ts +38 -0
  151. package/src/forge/compiler/integration/templates/types.ts +3 -0
  152. package/src/forge/compiler/integration/templates/workos.ts +1219 -0
  153. package/src/forge/compiler/make-registry/build.ts +8 -9
  154. package/src/forge/compiler/orchestrator/fast-check.ts +4 -0
  155. package/src/forge/compiler/orchestrator/generate-lock.ts +14 -3
  156. package/src/forge/compiler/orchestrator/manifest.ts +1 -1
  157. package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
  158. package/src/forge/compiler/orchestrator/plan.ts +247 -10
  159. package/src/forge/compiler/orchestrator/profile.ts +65 -0
  160. package/src/forge/compiler/orchestrator/run.ts +97 -31
  161. package/src/forge/compiler/orchestrator/serialize.ts +33 -8
  162. package/src/forge/compiler/orchestrator/types.ts +1 -1
  163. package/src/forge/compiler/package-graph/compiler.ts +3 -1
  164. package/src/forge/compiler/package-graph/constants.ts +1 -1
  165. package/src/forge/compiler/package-manager/adapter.ts +4 -1
  166. package/src/forge/compiler/package-manager/commands.ts +4 -0
  167. package/src/forge/compiler/package-manager/executor.ts +30 -1
  168. package/src/forge/compiler/package-manager/version.ts +36 -12
  169. package/src/forge/compiler/package-upgrades/planner.ts +155 -18
  170. package/src/forge/compiler/package-upgrades/types.ts +2 -0
  171. package/src/forge/compiler/policy-registry/build.ts +47 -2
  172. package/src/forge/compiler/policy-registry/parse.ts +32 -2
  173. package/src/forge/compiler/recipes/definitions.ts +63 -0
  174. package/src/forge/compiler/recipes/index.ts +2 -0
  175. package/src/forge/compiler/recipes/registry.ts +6 -0
  176. package/src/forge/compiler/test-graph/build.ts +11 -3
  177. package/src/forge/compiler/types/app-graph.ts +8 -2
  178. package/src/forge/compiler/types/cli.ts +75 -1
  179. package/src/forge/compiler/types/dev-manifest.ts +4 -0
  180. package/src/forge/compiler/types/emit.ts +2 -0
  181. package/src/forge/compiler/types/frontend-graph.ts +2 -2
  182. package/src/forge/compiler/types/integration.ts +1 -0
  183. package/src/forge/compiler/types/package-graph.ts +6 -0
  184. package/src/forge/compiler/types/policy-registry.ts +3 -1
  185. package/src/forge/delta/classifier.ts +52 -0
  186. package/src/forge/delta/explain.ts +238 -0
  187. package/src/forge/delta/git-observer.ts +43 -0
  188. package/src/forge/delta/ids.ts +44 -0
  189. package/src/forge/delta/index.ts +25 -0
  190. package/src/forge/delta/recorder.ts +540 -0
  191. package/src/forge/delta/redaction.ts +50 -0
  192. package/src/forge/delta/schema.ts +240 -0
  193. package/src/forge/delta/session.ts +142 -0
  194. package/src/forge/delta/status.ts +1202 -0
  195. package/src/forge/delta/store.ts +3284 -0
  196. package/src/forge/delta/timeline.ts +178 -0
  197. package/src/forge/dev/server.ts +808 -17
  198. package/src/forge/dev/types.ts +15 -1
  199. package/src/forge/dev/watch.ts +17 -7
  200. package/src/forge/dev-console/cycle.ts +280 -33
  201. package/src/forge/dev-console/types.ts +47 -1
  202. package/src/forge/impact/index.ts +204 -9
  203. package/src/forge/impact/types.ts +33 -1
  204. package/src/forge/intent/index.ts +35 -16
  205. package/src/forge/make/fields.ts +26 -0
  206. package/src/forge/make/index.ts +40 -6
  207. package/src/forge/make/templates.ts +155 -2
  208. package/src/forge/make/types.ts +2 -1
  209. package/src/forge/policy.ts +1 -1
  210. package/src/forge/react/index.ts +160 -2
  211. package/src/forge/refactor/index.ts +1 -0
  212. package/src/forge/repair/rules/index.ts +2 -2
  213. package/src/forge/review/index.ts +158 -12
  214. package/src/forge/review/types.ts +15 -0
  215. package/src/forge/runtime/auth/config.ts +17 -0
  216. package/src/forge/runtime/auth/evaluate.ts +15 -2
  217. package/src/forge/runtime/auth/resolve.ts +61 -6
  218. package/src/forge/runtime/auth/types.ts +1 -0
  219. package/src/forge/runtime/db/factory.ts +1 -3
  220. package/src/forge/runtime/db/generated-client.ts +13 -2
  221. package/src/forge/runtime/db/memory-adapter.ts +139 -32
  222. package/src/forge/runtime/db/pglite-adapter.ts +263 -2
  223. package/src/forge/runtime/db/postgres-adapter.ts +6 -3
  224. package/src/forge/runtime/executor.ts +129 -16
  225. package/src/forge/runtime/external/bridge.ts +649 -0
  226. package/src/forge/runtime/runner/run-entry.ts +16 -7
  227. package/src/forge/runtime/telemetry/buffer.ts +4 -1
  228. package/src/forge/runtime/telemetry/scrubber.ts +35 -5
  229. package/src/forge/runtime/webhooks/security.ts +12 -7
  230. package/src/forge/server.ts +17 -3
  231. package/src/forge/ui/index.ts +209 -0
  232. package/src/forge/ui/types.ts +1 -0
  233. package/src/forge/version.ts +1 -1
  234. package/src/forge/vue/index.ts +422 -0
  235. package/src/forge/workspace/baseline.ts +112 -0
  236. package/src/forge/workspace/change-summary.ts +250 -0
  237. package/src/forge/workspace/forge-cli.ts +42 -0
  238. package/src/forge/workspace/git-summary.ts +391 -0
  239. package/templates/agent-workroom/AGENTS.md +29 -0
  240. package/templates/agent-workroom/README.md +34 -0
  241. package/templates/agent-workroom/forge.config.ts +3 -0
  242. package/templates/agent-workroom/package.json +33 -0
  243. package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
  244. package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
  245. package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
  246. package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
  247. package/templates/agent-workroom/src/forge/schema.ts +54 -0
  248. package/templates/agent-workroom/src/policies.ts +6 -0
  249. package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
  250. package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
  251. package/templates/agent-workroom/tsconfig.json +16 -0
  252. package/templates/agent-workroom/web/index.html +12 -0
  253. package/templates/agent-workroom/web/package.json +21 -0
  254. package/templates/agent-workroom/web/src/App.tsx +345 -0
  255. package/templates/agent-workroom/web/src/lib/forge.ts +13 -0
  256. package/templates/agent-workroom/web/src/main.tsx +13 -0
  257. package/templates/agent-workroom/web/src/styles.css +545 -0
  258. package/templates/agent-workroom/web/tsconfig.json +27 -0
  259. package/templates/b2b-support-web/package.json +1 -0
  260. package/templates/b2b-support-web/web/package.json +1 -1
  261. package/templates/minimal-web/package.json +1 -1
  262. package/templates/minimal-web/web/package.json +2 -2
  263. package/templates/nuxt-web/.vscode/settings.json +14 -0
  264. package/templates/nuxt-web/README.md +30 -0
  265. package/templates/nuxt-web/forge.config.ts +3 -0
  266. package/templates/nuxt-web/package.json +33 -0
  267. package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -0
  268. package/templates/nuxt-web/src/commands/createNote.ts +26 -0
  269. package/templates/nuxt-web/src/forge/schema.ts +12 -0
  270. package/templates/nuxt-web/src/policies.ts +6 -0
  271. package/templates/nuxt-web/src/queries/listNotes.ts +8 -0
  272. package/templates/nuxt-web/src/queries/liveNotes.ts +8 -0
  273. package/templates/nuxt-web/tsconfig.json +17 -0
  274. package/templates/nuxt-web/web/app.vue +67 -0
  275. package/templates/nuxt-web/web/components/LiveNotes.vue +89 -0
  276. package/templates/nuxt-web/web/components/NoteComposer.vue +100 -0
  277. package/templates/nuxt-web/web/composables/forge.ts +13 -0
  278. package/templates/nuxt-web/web/composables/useNotes.ts +24 -0
  279. package/templates/nuxt-web/web/nuxt.config.ts +11 -0
  280. package/templates/nuxt-web/web/package.json +18 -0
  281. package/templates/nuxt-web/web/plugins/forge.client.ts +10 -0
  282. package/templates/nuxt-web/web/plugins/forge.server.ts +10 -0
  283. package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -0
  284. package/templates/nuxt-web/web/tsconfig.json +6 -0
  285. package/src/forge/_generated/actionSubscriptions.json +0 -2
  286. package/src/forge/_generated/actionSubscriptions.ts +0 -10
  287. package/src/forge/_generated/agentAdapterManifest.json +0 -2
  288. package/src/forge/_generated/agentAdapterManifest.ts +0 -73
  289. package/src/forge/_generated/agentContract.json +0 -2
  290. package/src/forge/_generated/agentContract.ts +0 -7829
  291. package/src/forge/_generated/agentQuickstart.md +0 -34
  292. package/src/forge/_generated/agentTools.json +0 -2
  293. package/src/forge/_generated/agentTools.md +0 -16
  294. package/src/forge/_generated/agentTools.ts +0 -12
  295. package/src/forge/_generated/aiContext.ts +0 -125
  296. package/src/forge/_generated/aiModels.json +0 -2
  297. package/src/forge/_generated/aiModels.ts +0 -51
  298. package/src/forge/_generated/aiProviders.json +0 -2
  299. package/src/forge/_generated/aiProviders.ts +0 -23
  300. package/src/forge/_generated/aiRegistry.json +0 -2
  301. package/src/forge/_generated/aiRegistry.ts +0 -31
  302. package/src/forge/_generated/api.json +0 -2
  303. package/src/forge/_generated/api.ts +0 -8
  304. package/src/forge/_generated/appGraph.json +0 -2
  305. package/src/forge/_generated/appGraph.ts +0 -14919
  306. package/src/forge/_generated/appMap.md +0 -55
  307. package/src/forge/_generated/artifactManifest.json +0 -2
  308. package/src/forge/_generated/artifactManifest.ts +0 -7
  309. package/src/forge/_generated/authClaims.json +0 -2
  310. package/src/forge/_generated/authClaims.ts +0 -13
  311. package/src/forge/_generated/authConfig.json +0 -2
  312. package/src/forge/_generated/authConfig.ts +0 -17
  313. package/src/forge/_generated/authContext.ts +0 -23
  314. package/src/forge/_generated/authRegistry.json +0 -2
  315. package/src/forge/_generated/authRegistry.ts +0 -25
  316. package/src/forge/_generated/buildInfo.json +0 -2
  317. package/src/forge/_generated/buildInfo.ts +0 -9
  318. package/src/forge/_generated/capabilityMap.json +0 -2
  319. package/src/forge/_generated/capabilityMap.md +0 -15
  320. package/src/forge/_generated/capabilityMap.ts +0 -17
  321. package/src/forge/_generated/client.ts +0 -282
  322. package/src/forge/_generated/clientApi.ts +0 -9
  323. package/src/forge/_generated/clientManifest.json +0 -2
  324. package/src/forge/_generated/clientManifest.ts +0 -39
  325. package/src/forge/_generated/clientTypes.ts +0 -78
  326. package/src/forge/_generated/configRegistry.json +0 -2
  327. package/src/forge/_generated/configRegistry.ts +0 -4
  328. package/src/forge/_generated/dataGraph.json +0 -2
  329. package/src/forge/_generated/dataGraph.ts +0 -8
  330. package/src/forge/_generated/db.json +0 -2
  331. package/src/forge/_generated/db.ts +0 -2
  332. package/src/forge/_generated/dbSecurityManifest.json +0 -2
  333. package/src/forge/_generated/dbSecurityManifest.ts +0 -15
  334. package/src/forge/_generated/dbSessionContext.json +0 -2
  335. package/src/forge/_generated/dbSessionContext.ts +0 -39
  336. package/src/forge/_generated/deployManifest.json +0 -2
  337. package/src/forge/_generated/deployManifest.ts +0 -14
  338. package/src/forge/_generated/devManifest.json +0 -2
  339. package/src/forge/_generated/devManifest.ts +0 -62
  340. package/src/forge/_generated/envSchema.json +0 -2
  341. package/src/forge/_generated/envSchema.ts +0 -59
  342. package/src/forge/_generated/frontendGraph.json +0 -2
  343. package/src/forge/_generated/frontendGraph.ts +0 -27
  344. package/src/forge/_generated/importGuards.json +0 -2
  345. package/src/forge/_generated/importGuards.ts +0 -686
  346. package/src/forge/_generated/index.ts +0 -68
  347. package/src/forge/_generated/liveProductionManifest.json +0 -2
  348. package/src/forge/_generated/liveProductionManifest.ts +0 -23
  349. package/src/forge/_generated/liveProtocol.json +0 -2
  350. package/src/forge/_generated/liveProtocol.ts +0 -21
  351. package/src/forge/_generated/liveQueryRegistry.json +0 -2
  352. package/src/forge/_generated/liveQueryRegistry.ts +0 -9
  353. package/src/forge/_generated/liveTransportConfig.json +0 -2
  354. package/src/forge/_generated/liveTransportConfig.ts +0 -19
  355. package/src/forge/_generated/makeRegistry.json +0 -2
  356. package/src/forge/_generated/makeRegistry.ts +0 -177
  357. package/src/forge/_generated/makeTemplates.json +0 -2
  358. package/src/forge/_generated/makeTemplates.ts +0 -66
  359. package/src/forge/_generated/mockMap.json +0 -2
  360. package/src/forge/_generated/mockMap.ts +0 -7
  361. package/src/forge/_generated/operationPlaybooks.md +0 -167
  362. package/src/forge/_generated/packageGraph.json +0 -2
  363. package/src/forge/_generated/packageGraph.ts +0 -249334
  364. package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
  365. package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
  366. package/src/forge/_generated/permissionMatrix.json +0 -2
  367. package/src/forge/_generated/permissionMatrix.ts +0 -7
  368. package/src/forge/_generated/policyRegistry.json +0 -2
  369. package/src/forge/_generated/policyRegistry.ts +0 -11
  370. package/src/forge/_generated/queryRegistry.json +0 -2
  371. package/src/forge/_generated/queryRegistry.ts +0 -9
  372. package/src/forge/_generated/react.d.ts +0 -22
  373. package/src/forge/_generated/react.ts +0 -29
  374. package/src/forge/_generated/reactManifest.json +0 -2
  375. package/src/forge/_generated/reactManifest.ts +0 -19
  376. package/src/forge/_generated/rlsPolicies.json +0 -2
  377. package/src/forge/_generated/rlsPolicies.sql +0 -34
  378. package/src/forge/_generated/rlsPolicies.ts +0 -6
  379. package/src/forge/_generated/runtimeGraph.json +0 -2
  380. package/src/forge/_generated/runtimeGraph.ts +0 -8
  381. package/src/forge/_generated/runtimeMatrix.json +0 -2
  382. package/src/forge/_generated/runtimeMatrix.ts +0 -334130
  383. package/src/forge/_generated/runtimeRegistry.ts +0 -2
  384. package/src/forge/_generated/runtimeRules.md +0 -91
  385. package/src/forge/_generated/secretRegistry.json +0 -2
  386. package/src/forge/_generated/secretRegistry.ts +0 -50
  387. package/src/forge/_generated/secretsContext.ts +0 -11
  388. package/src/forge/_generated/serverApi.ts +0 -10
  389. package/src/forge/_generated/sourceMapManifest.json +0 -2
  390. package/src/forge/_generated/sourceMapManifest.ts +0 -7
  391. package/src/forge/_generated/sqlPlan.json +0 -2
  392. package/src/forge/_generated/sqlPlan.ts +0 -88
  393. package/src/forge/_generated/subscriptionManifest.json +0 -2
  394. package/src/forge/_generated/subscriptionManifest.ts +0 -7
  395. package/src/forge/_generated/symbolicationManifest.json +0 -2
  396. package/src/forge/_generated/symbolicationManifest.ts +0 -17
  397. package/src/forge/_generated/telemetryRegistry.json +0 -2
  398. package/src/forge/_generated/telemetryRegistry.ts +0 -9
  399. package/src/forge/_generated/telemetrySinks.json +0 -2
  400. package/src/forge/_generated/telemetrySinks.ts +0 -11
  401. package/src/forge/_generated/tenantScope.json +0 -2
  402. package/src/forge/_generated/tenantScope.ts +0 -8
  403. package/src/forge/_generated/testGraph.json +0 -2
  404. package/src/forge/_generated/testGraph.ts +0 -3430
  405. package/src/forge/_generated/testPlanRegistry.json +0 -2
  406. package/src/forge/_generated/testPlanRegistry.ts +0 -33
  407. package/src/forge/_generated/uiRoutes.json +0 -2
  408. package/src/forge/_generated/uiRoutes.ts +0 -16
  409. package/src/forge/_generated/uiScenarios.json +0 -2
  410. package/src/forge/_generated/uiScenarios.ts +0 -30
  411. package/src/forge/_generated/uiTestManifest.json +0 -2
  412. package/src/forge/_generated/uiTestManifest.ts +0 -27
  413. package/src/forge/_generated/workflowRegistry.json +0 -2
  414. package/src/forge/_generated/workflowRegistry.ts +0 -9
  415. package/src/forge/_generated/workflowSubscriptions.json +0 -2
  416. package/src/forge/_generated/workflowSubscriptions.ts +0 -10
@@ -0,0 +1,84 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ export interface LastRunRecord {
5
+ schemaVersion: "0.1.0";
6
+ command: string;
7
+ ok: boolean;
8
+ startedAt: string;
9
+ finishedAt: string;
10
+ durationMs: number;
11
+ code?: string;
12
+ failureKind?: string;
13
+ message?: string;
14
+ nextActions: string[];
15
+ details?: Record<string, unknown>;
16
+ }
17
+
18
+ export interface LastRunCommandResult {
19
+ ok: boolean;
20
+ record: LastRunRecord | null;
21
+ path: string;
22
+ exitCode: 0 | 1;
23
+ }
24
+
25
+ function lastRunPath(workspaceRoot: string): string {
26
+ return join(workspaceRoot, ".forge", "last-run.json");
27
+ }
28
+
29
+ export function writeLastRunRecord(workspaceRoot: string, record: LastRunRecord): void {
30
+ const file = lastRunPath(workspaceRoot);
31
+ mkdirSync(join(workspaceRoot, ".forge"), { recursive: true });
32
+ writeFileSync(file, `${JSON.stringify(record, null, 2)}\n`, "utf8");
33
+ }
34
+
35
+ export function readLastRunRecord(workspaceRoot: string): LastRunRecord | null {
36
+ const file = lastRunPath(workspaceRoot);
37
+ if (!existsSync(file)) {
38
+ return null;
39
+ }
40
+ return JSON.parse(readFileSync(file, "utf8")) as LastRunRecord;
41
+ }
42
+
43
+ export function runLastCommand(options: { workspaceRoot: string }): LastRunCommandResult {
44
+ const path = lastRunPath(options.workspaceRoot);
45
+ const record = readLastRunRecord(options.workspaceRoot);
46
+ return {
47
+ ok: record !== null,
48
+ record,
49
+ path,
50
+ exitCode: record ? 0 : 1,
51
+ };
52
+ }
53
+
54
+ export function formatLastJson(result: LastRunCommandResult): string {
55
+ return `${JSON.stringify(result, null, 2)}\n`;
56
+ }
57
+
58
+ export function formatLastHuman(result: LastRunCommandResult): string {
59
+ if (!result.record) {
60
+ return `No last run record found at ${result.path}\n`;
61
+ }
62
+ const lines = [
63
+ `Last Forge run: ${result.record.command}`,
64
+ `OK: ${result.record.ok}`,
65
+ `Finished: ${result.record.finishedAt}`,
66
+ `Duration: ${result.record.durationMs}ms`,
67
+ ];
68
+ if (result.record.code) {
69
+ lines.push(`Code: ${result.record.code}`);
70
+ }
71
+ if (result.record.failureKind) {
72
+ lines.push(`Failure: ${result.record.failureKind}`);
73
+ }
74
+ if (result.record.message) {
75
+ lines.push(`Message: ${result.record.message}`);
76
+ }
77
+ if (result.record.nextActions.length > 0) {
78
+ lines.push("Next actions:");
79
+ for (const action of result.record.nextActions) {
80
+ lines.push(` ${action}`);
81
+ }
82
+ }
83
+ return `${lines.join("\n")}\n`;
84
+ }
@@ -4,28 +4,124 @@ import { isMainModule } from "../platform/module.ts";
4
4
  import { executeCommand } from "./commands.ts";
5
5
  import { hasUnknownOption, parseCli } from "./parse.ts";
6
6
  import { formatJsonResult } from "./output.ts";
7
+ import { recordParsedCliCommand } from "../delta/index.ts";
7
8
 
8
9
  function formatHelp(): string {
9
10
  return [
10
11
  "ForgeOS",
11
12
  "",
12
13
  "Start with one of these:",
14
+ " forge status --json Compact project health, handoff state, and next actions",
15
+ " forge changed --json Group changed files into human, generated, and risk buckets",
16
+ " forge changed --authored --json Show only authored changed files, excluding generated artifacts",
17
+ " forge changed --review --json Show review-focused app/config/docs changes, excluding local agent/browser artifacts",
18
+ " forge changed --commit-ready --json Show files suitable for git add, excluding generated and operational artifacts",
19
+ " forge new my-app --template minimal-web --field-test Create an installed WorkOS/auth.md field-test app",
20
+ " forge field-test create vendor-access --auth workos --template minimal-web --json Create a real field-test app",
21
+ " forge field-test run --templates minimal-web,nuxt-web --package-managers npm,pnpm --runtime-probes --auth-probes --json",
22
+ " forge field-test report --json Summarize the machine-readable field-test report",
23
+ " forge diff authored Run the authored-only git diff pathspec",
24
+ " forge handoff --json Compact work handoff for the next external code agent",
25
+ " forge agent onboard --target codex --json Prepare adapter, hooks, memory, and dev snapshot",
26
+ " forge doctor agent --target codex --json Check adapter, hooks, and Agent Memory readiness",
27
+ " forge doctor delta --json Check DeltaDB writability, queue drain, redaction, and gitignore posture",
28
+ " forge doctor runtime --json Check generated freshness, local dev lifecycle, and PGlite posture",
29
+ " forge agent ingest codex --watch --file .forge/agent/events.ndjson --json",
30
+ " forge docs check --json Check public docs, ReadTheDocs config, links, and local MkDocs tooling",
31
+ " forge docs check --build --install-venv --json Build docs strictly in a local RTD-style venv",
32
+ " forge release doctor --json Check npm publish readiness plus separate production deploy readiness",
33
+ " forge authmd generate Write public/auth.md from the generated agent/auth contract",
34
+ " forge auth check --production --json Fail unless auth is jwt/oidc production-ready",
35
+ " forge authmd check --json Check public/auth.md drift for CI and agent-ready apps",
36
+ " forge workos install --yes --json Delegate AuthKit setup to npx --yes workos@latest install",
37
+ " forge workos doctor --json Check WorkOS AuthKit/FGA files, claims, seed, webhook, and tenant guards",
38
+ " forge workos doctor --yes --json Run local checks, then delegate to npx --yes workos@latest doctor",
39
+ " forge workos seed --file workos-seed.yml --dry-run --json Validate WorkOS seed without hosted changes",
40
+ " forge workos setup --real --file workos-seed.yml --json Apply redirect/CORS/homepage config and seed WorkOS without dashboard",
41
+ " forge deploy plan --target docker --json Explain production deploy gates and commands",
42
+ " forge deploy check --production --json Gate auth, DB, metadata, generated artifacts, and liveQuery readiness",
43
+ " forge deploy render docker Write Docker production deploy files under deploy/",
44
+ " forge deploy verify --production --url https://app.example.com --json Probe /health and validate public auth metadata",
45
+ " forge release check --allow-missing-local-release --json Gate release readiness without failing on unprepared local artifacts",
46
+ " forge self-host check --prepared-only --json Report compose readiness without creating deploy files",
47
+ " forge delta status --verbose --json Include Delta schema, lock, and aggregate count details",
48
+ " forge delta compact --json Compact redacted local agent queue history",
49
+ " forge delta prune --older-than 30d --dry-run --json Plan local Delta operational retention",
50
+ " forge delta export --redacted --json Export redacted Delta status, timeline, and agent memory",
51
+ " forge studio open <app-path> --preview-port 5174 --target codex --json",
52
+ " forge studio snapshot <app-path> --preview-port 5174 --target codex --probe-codex-server --json",
53
+ " forge studio bridge <app-path> --preview-port 5174 --target codex --studio-url http://127.0.0.1:3765 --probe-codex-server --json",
54
+ " forge studio doctor <app-path> --preview-port 5174 --target codex --json",
55
+ " forge studio codex-server <app-path> --probe --json",
56
+ " forge studio watch <app-path> --preview-port 5174 --target codex --json",
13
57
  " forge dev Run API, DB/worker, watch, and web app when present",
14
58
  " forge dev --once --json One-shot health/diagnostic loop for agents and CI",
15
59
  " forge do \"fix\" --json Ask ForgeOS for the right workflow and commands",
16
- " forge inspect all --json Read the generated machine contract",
60
+ " forge cair snapshot Compact CAIR project snapshot for agents",
61
+ " forge cair query \"Q REFS S#1\" Run a semantic CAIR query",
62
+ " forge cair action --plan \"A RN t=S#1 nn=renamed\" Plan a guarded semantic edit",
63
+ " forge cair action \"A APPLY plan=<P#|path>\" Apply a guarded CAIR plan",
64
+ " forge agent print-context --json Read the generated agent context pack",
65
+ " forge inspect all --brief --json Read the smallest aggregate project contract",
66
+ " forge inspect all --json Read the compact generated machine contract",
67
+ " forge mcp serve Serve ForgeOS Agent Memory tools over MCP stdio",
68
+ " forge agent context --current --json Read the Agent Memory context pack",
69
+ " forge agent timeline --json Read external-agent hook activity as a compact timeline",
17
70
  " forge doctor windows --json Diagnose native Windows setup and Bun shims",
71
+ " forge bench compiler --json Measure public compiler phase timings",
72
+ " forge manifest validate ./forge.manifest.json --json Validate an external runtime manifest",
18
73
  "",
19
74
  "Useful next commands:",
20
75
  " forge generate",
21
76
  " forge check --json",
77
+ " forge verify App-level default verification for the current project",
22
78
  " forge verify --standard",
23
- " forge verify --strict",
79
+ " forge verify quick Alias for smoke/fast local checks",
80
+ " forge verify agent Alias for standard agent-loop verification",
81
+ " forge verify release Alias for strict app release verification",
82
+ " forge verify framework Maintainer-only ForgeOS framework test gate",
83
+ " forge verify --strict --typechecker native --test-jobs 6",
84
+ " forge verify framework --test-plan --json",
85
+ "",
86
+ ].join("\n");
87
+ }
88
+
89
+ function formatDevHelp(): string {
90
+ return [
91
+ "ForgeOS dev",
92
+ "",
93
+ "Usage:",
94
+ " forge dev [status|stop] [options]",
95
+ "",
96
+ "Options:",
97
+ " --db memory|pglite|postgres|none Choose the development database adapter",
98
+ " --port <port> API runtime port; use 0 for an ephemeral port",
99
+ " --web-port <port> Web dev server port",
100
+ " --host <host> Bind host, default 127.0.0.1",
101
+ " --no-web Start API/runtime only",
102
+ " --api-only Start API/runtime only",
103
+ " --web-only Start web server only, expecting an API runtime",
104
+ " --no-worker Disable local worker",
105
+ " --no-watch Disable file watching",
106
+ " --once --json Run one-shot diagnostics without starting servers",
107
+ " --detach --json Start dev in the background with .forge/dev/dev.pid and .forge/dev/dev.log",
108
+ "",
109
+ "Examples:",
110
+ " forge dev --db memory --port 3777 --web-port 5174",
111
+ " forge dev --db pglite --once --json",
112
+ " forge dev --detach --db memory --port 0 --json",
113
+ " forge dev status --json",
114
+ " forge dev stop --json",
24
115
  "",
25
116
  ].join("\n");
26
117
  }
27
118
 
28
119
  export async function main(argv: string[] = process.argv.slice(2)): Promise<number> {
120
+ if (argv[0] === "dev" && (argv.includes("--help") || argv.includes("-h"))) {
121
+ process.stdout.write(formatDevHelp());
122
+ return 0;
123
+ }
124
+
29
125
  if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
30
126
  process.stdout.write(formatHelp());
31
127
  return 0;
@@ -83,7 +179,15 @@ export async function main(argv: string[] = process.argv.slice(2)): Promise<numb
83
179
  return 1;
84
180
  }
85
181
 
86
- return executeCommand(parsed.command);
182
+ const startedAt = Date.now();
183
+ const exitCode = await executeCommand(parsed.command);
184
+ await recordParsedCliCommand({
185
+ command: parsed.command,
186
+ argv,
187
+ exitCode,
188
+ durationMs: Date.now() - startedAt,
189
+ });
190
+ return exitCode;
87
191
  }
88
192
 
89
193
  if (isMainModule(import.meta)) {
@@ -1,6 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { cpSync, statSync } from "node:fs";
3
- import { dirname, join, parse, relative, resolve } from "node:path";
3
+ import { basename, dirname, join, parse, relative, resolve } from "node:path";
4
4
  import { setTimeout as sleep } from "node:timers/promises";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import { nodeFileSystem } from "../compiler/fs/index.ts";
@@ -8,7 +8,7 @@ import { run as runGenerate } from "../compiler/orchestrator/run.ts";
8
8
  import { resolvePackageManagerArgv } from "../compiler/package-manager/executor.ts";
9
9
  import { moduleDir } from "../platform/module.ts";
10
10
 
11
- export type NewTemplateName = "b2b-support-web" | "minimal-web";
11
+ export type NewTemplateName = "agent-workroom" | "b2b-support-web" | "minimal-web" | "nuxt-web";
12
12
  export type NewPackageManager = "bun" | "npm" | "pnpm" | "yarn";
13
13
 
14
14
  export interface NewCommandOptions {
@@ -17,6 +17,7 @@ export interface NewCommandOptions {
17
17
  packageManager: NewPackageManager;
18
18
  install: boolean;
19
19
  git: boolean;
20
+ fieldTest?: boolean;
20
21
  forgePackageSpec?: string;
21
22
  localForge?: boolean;
22
23
  workspaceRoot: string;
@@ -29,6 +30,11 @@ export interface NewCommandResult {
29
30
  packageManager: NewPackageManager;
30
31
  installed: boolean;
31
32
  gitInitialized: boolean;
33
+ fieldTest: {
34
+ requested: boolean;
35
+ ok: boolean;
36
+ steps: Array<{ name: string; ok: boolean; command: string }>;
37
+ };
32
38
  generated: boolean;
33
39
  gitHygiene: {
34
40
  ok: boolean;
@@ -43,9 +49,16 @@ export interface NewCommandResult {
43
49
  const REQUIRED_GITIGNORE_PATHS = [
44
50
  "src/forge/_generated/",
45
51
  "forge.lock",
52
+ ".codex/",
46
53
  ".forge/cache/",
47
54
  ".forge/pglite/",
55
+ ".forge/delta/",
56
+ ".forge/agent/",
57
+ ".forge/agent/*.ndjson",
58
+ ".forge/agent/*.history",
59
+ ".forge/last-run.json",
48
60
  ".forge/local/",
61
+ ".forge/runtime-cache/",
49
62
  ".forge/test-cache/",
50
63
  ".forge/test-runs/",
51
64
  ".forge/ui-runs/",
@@ -55,6 +68,8 @@ const REQUIRED_GITIGNORE_PATHS = [
55
68
  ".forge/reviews/",
56
69
  ".forge/impact/",
57
70
  ".forge/agent-adapters/",
71
+ ".forge/studio/",
72
+ ".workos-seed-state.json",
58
73
  ] as const;
59
74
 
60
75
  const DEFAULT_FORGE_PACKAGE_SPEC = "npm:forgeos@alpha";
@@ -191,12 +206,49 @@ function ensureProjectName(name: string): string | null {
191
206
  if (!name.trim()) {
192
207
  return "forge new requires a project name";
193
208
  }
194
- if (name.includes("/") || name.includes("\\") || name === "." || name === "..") {
209
+ if (name === ".") {
210
+ return null;
211
+ }
212
+ if (name.includes("/") || name.includes("\\") || name === "..") {
195
213
  return "project name must be a directory name, not a path";
196
214
  }
197
215
  return null;
198
216
  }
199
217
 
218
+ function isCurrentDirectoryTarget(name: string): boolean {
219
+ return name === ".";
220
+ }
221
+
222
+ function targetDirectoryFor(options: NewCommandOptions): string {
223
+ return isCurrentDirectoryTarget(options.name)
224
+ ? resolve(options.workspaceRoot)
225
+ : resolve(options.workspaceRoot, options.name);
226
+ }
227
+
228
+ function sanitizePackageName(name: string): string {
229
+ return name
230
+ .trim()
231
+ .toLowerCase()
232
+ .replace(/[^a-z0-9._-]+/g, "-")
233
+ .replace(/-+/g, "-")
234
+ .replace(/^[._-]+|[._-]+$/g, "") || "forge-app";
235
+ }
236
+
237
+ function projectNameForTarget(options: NewCommandOptions, targetDir: string): string {
238
+ return isCurrentDirectoryTarget(options.name)
239
+ ? sanitizePackageName(basename(targetDir))
240
+ : options.name;
241
+ }
242
+
243
+ function blockingExistingEntries(targetDir: string): string[] {
244
+ const allowed = new Set([".git", ".DS_Store", "Thumbs.db"]);
245
+ return nodeFileSystem
246
+ .readDir(targetDir)
247
+ .map((entry) => entry.name)
248
+ .filter((name) => !allowed.has(name))
249
+ .sort();
250
+ }
251
+
200
252
  function analyzeGitHygiene(targetDir: string): NewCommandResult["gitHygiene"] {
201
253
  const gitignorePath = join(targetDir, ".gitignore");
202
254
  const gitignore = nodeFileSystem.exists(gitignorePath)
@@ -376,6 +428,7 @@ export async function runNewCommand(options: NewCommandOptions): Promise<NewComm
376
428
  packageManager: options.packageManager,
377
429
  installed: false,
378
430
  gitInitialized: false,
431
+ fieldTest: { requested: Boolean(options.fieldTest), ok: false, steps: [] },
379
432
  generated: false,
380
433
  gitHygiene: { ok: false, ignoredPaths: [], missingPaths: [] },
381
434
  exitCode: 1,
@@ -393,6 +446,7 @@ export async function runNewCommand(options: NewCommandOptions): Promise<NewComm
393
446
  packageManager: options.packageManager,
394
447
  installed: false,
395
448
  gitInitialized: false,
449
+ fieldTest: { requested: Boolean(options.fieldTest), ok: false, steps: [] },
396
450
  generated: false,
397
451
  gitHygiene: { ok: false, ignoredPaths: [], missingPaths: [] },
398
452
  exitCode: 1,
@@ -401,15 +455,18 @@ export async function runNewCommand(options: NewCommandOptions): Promise<NewComm
401
455
  };
402
456
  }
403
457
 
404
- const targetDir = resolve(options.workspaceRoot, options.name);
405
- if (nodeFileSystem.exists(targetDir)) {
458
+ const targetDir = targetDirectoryFor(options);
459
+ const appName = projectNameForTarget(options, targetDir);
460
+ const currentDirectoryTarget = isCurrentDirectoryTarget(options.name);
461
+ if (nodeFileSystem.exists(targetDir) && !currentDirectoryTarget) {
406
462
  return {
407
- name: options.name,
463
+ name: appName,
408
464
  template: options.template,
409
465
  targetDir,
410
466
  packageManager: options.packageManager,
411
467
  installed: false,
412
468
  gitInitialized: false,
469
+ fieldTest: { requested: Boolean(options.fieldTest), ok: false, steps: [] },
413
470
  generated: false,
414
471
  gitHygiene: { ok: false, ignoredPaths: [], missingPaths: [] },
415
472
  exitCode: 1,
@@ -417,13 +474,32 @@ export async function runNewCommand(options: NewCommandOptions): Promise<NewComm
417
474
  nextSteps: [],
418
475
  };
419
476
  }
477
+ if (nodeFileSystem.exists(targetDir) && currentDirectoryTarget) {
478
+ const blocking = blockingExistingEntries(targetDir);
479
+ if (blocking.length > 0) {
480
+ return {
481
+ name: appName,
482
+ template: options.template,
483
+ targetDir,
484
+ packageManager: options.packageManager,
485
+ installed: false,
486
+ gitInitialized: false,
487
+ fieldTest: { requested: Boolean(options.fieldTest), ok: false, steps: [] },
488
+ generated: false,
489
+ gitHygiene: { ok: false, ignoredPaths: [], missingPaths: [] },
490
+ exitCode: 1,
491
+ message: `current directory is not empty: ${blocking.slice(0, 6).join(", ")}${blocking.length > 6 ? ` (+${blocking.length - 6})` : ""}`,
492
+ nextSteps: [],
493
+ };
494
+ }
495
+ }
420
496
 
421
497
  nodeFileSystem.mkdirp(targetDir);
422
498
  cpSync(source, targetDir, { recursive: true, force: true });
423
499
  ensureGitignore(targetDir);
424
500
  replaceTokens(
425
501
  targetDir,
426
- options.name,
502
+ appName,
427
503
  options.packageManager,
428
504
  forgePackageSpec(targetDir, options),
429
505
  );
@@ -434,12 +510,13 @@ export async function runNewCommand(options: NewCommandOptions): Promise<NewComm
434
510
  installed = installCode === 0;
435
511
  if (!installed) {
436
512
  return {
437
- name: options.name,
513
+ name: appName,
438
514
  template: options.template,
439
515
  targetDir,
440
516
  packageManager: options.packageManager,
441
517
  installed,
442
518
  gitInitialized: false,
519
+ fieldTest: { requested: Boolean(options.fieldTest), ok: false, steps: [] },
443
520
  generated: false,
444
521
  gitHygiene: analyzeGitHygiene(targetDir),
445
522
  exitCode: 1,
@@ -468,12 +545,13 @@ export async function runNewCommand(options: NewCommandOptions): Promise<NewComm
468
545
  }
469
546
  if (!generated) {
470
547
  return {
471
- name: options.name,
548
+ name: appName,
472
549
  template: options.template,
473
550
  targetDir,
474
551
  packageManager: options.packageManager,
475
552
  installed,
476
553
  gitInitialized: false,
554
+ fieldTest: { requested: Boolean(options.fieldTest), ok: false, steps: [] },
477
555
  generated,
478
556
  gitHygiene: analyzeGitHygiene(targetDir),
479
557
  exitCode: 1,
@@ -489,26 +567,72 @@ export async function runNewCommand(options: NewCommandOptions): Promise<NewComm
489
567
  gitInitialized = gitCode === 0;
490
568
  }
491
569
 
570
+ const fieldTestSteps: NewCommandResult["fieldTest"]["steps"] = [];
571
+ if (options.fieldTest && installed) {
572
+ const steps: Array<{ name: string; command: string; args: string[] }> = [
573
+ { name: "workos", command: options.packageManager, args: ["run", "forge", "--", "add", "auth", "workos", "--json"] },
574
+ { name: "generate-workos", command: options.packageManager, args: ["run", "forge", "--", "generate"] },
575
+ { name: "authmd", command: options.packageManager, args: ["run", "forge", "--", "authmd", "generate", "--json"] },
576
+ { name: "authmd-check", command: options.packageManager, args: ["run", "forge", "--", "authmd", "check", "--json"] },
577
+ { name: "workos-doctor", command: options.packageManager, args: ["run", "forge", "--", "workos", "doctor", "--json"] },
578
+ { name: "workos-seed", command: options.packageManager, args: ["run", "forge", "--", "workos", "seed", "--file", "workos-seed.yml", "--dry-run", "--json"] },
579
+ { name: "check", command: options.packageManager, args: ["run", "forge", "--", "check", "--json"] },
580
+ ];
581
+ for (const step of steps) {
582
+ const code = await spawnCommand(step.command, step.args, targetDir);
583
+ fieldTestSteps.push({ name: step.name, ok: code === 0, command: [step.command, ...step.args].join(" ") });
584
+ if (code !== 0) {
585
+ break;
586
+ }
587
+ }
588
+ if (gitInitialized && fieldTestSteps.every((step) => step.ok)) {
589
+ const addCode = await spawnCommand("git", ["add", "-A"], targetDir);
590
+ const commitCode = addCode === 0
591
+ ? await spawnCommand("git", [
592
+ "-c",
593
+ "user.name=ForgeOS",
594
+ "-c",
595
+ "user.email=forgeos@example.invalid",
596
+ "commit",
597
+ "-m",
598
+ "Initial ForgeOS field-test scaffold",
599
+ ], targetDir)
600
+ : 1;
601
+ fieldTestSteps.push({
602
+ name: "baseline-commit",
603
+ ok: addCode === 0 && commitCode === 0,
604
+ command: 'git add -A && git commit -m "Initial ForgeOS field-test scaffold"',
605
+ });
606
+ }
607
+ }
608
+ const fieldTest = {
609
+ requested: Boolean(options.fieldTest),
610
+ ok: !options.fieldTest || (installed && fieldTestSteps.length > 0 && fieldTestSteps.every((step) => step.ok)),
611
+ steps: fieldTestSteps,
612
+ };
613
+
492
614
  const nextSteps = [
493
- `cd ${options.name}`,
615
+ ...(currentDirectoryTarget ? [] : [`cd ${options.name}`]),
494
616
  ...(installed ? [] : [`${options.packageManager} install`]),
495
617
  ...(generated ? [] : [`${options.packageManager} run generate`]),
618
+ ...(options.fieldTest ? [`${options.packageManager} run forge -- agent onboard --target codex --json`] : []),
496
619
  `${options.packageManager} run dev -- --open`,
497
620
  `${options.packageManager} run verify`,
498
621
  ];
499
622
  const gitHygiene = analyzeGitHygiene(targetDir);
500
623
 
501
624
  return {
502
- name: options.name,
625
+ name: appName,
503
626
  template: options.template,
504
627
  targetDir,
505
628
  packageManager: options.packageManager,
506
629
  installed,
507
630
  gitInitialized,
631
+ fieldTest,
508
632
  generated,
509
633
  gitHygiene,
510
- exitCode: 0,
511
- message: `Created ${options.name} from template ${options.template}.`,
634
+ exitCode: fieldTest.ok ? 0 : 1,
635
+ message: `Created ${appName} from template ${options.template}.`,
512
636
  nextSteps,
513
637
  };
514
638
  }
@@ -520,6 +644,13 @@ export function formatNewHuman(result: NewCommandResult): string {
520
644
 
521
645
  return [
522
646
  result.message,
647
+ ...(result.fieldTest.requested
648
+ ? [
649
+ result.fieldTest.ok
650
+ ? "Field-test setup completed: WorkOS, auth.md, check, and baseline commit are ready."
651
+ : `warning: field-test setup did not complete: ${result.fieldTest.steps.find((step) => !step.ok)?.name ?? "not-run"}`,
652
+ ]
653
+ : []),
523
654
  ...(result.gitHygiene.ok
524
655
  ? ["Generated and operational Forge files are ignored by git."]
525
656
  : [
@@ -531,3 +662,11 @@ export function formatNewHuman(result: NewCommandResult): string {
531
662
  "",
532
663
  ].join("\n");
533
664
  }
665
+
666
+ export function formatNewJson(result: NewCommandResult): string {
667
+ return `${JSON.stringify({
668
+ schemaVersion: "0.1.0",
669
+ ok: result.exitCode === 0,
670
+ ...result,
671
+ }, null, 2)}\n`;
672
+ }
@@ -0,0 +1,23 @@
1
+ export function uniqueNextActions(actions: string[]): string[] {
2
+ return [...new Set(actions)].filter(Boolean);
3
+ }
4
+
5
+ export function releasePrepareNextActions(): string[] {
6
+ return ["forge release prepare --env production", "forge release check --json"];
7
+ }
8
+
9
+ export function releaseReadyNextActions(): string[] {
10
+ return ["forge artifacts verify --json", "forge sourcemaps check --json"];
11
+ }
12
+
13
+ export function selfHostPrepareNextActions(): string[] {
14
+ return ["forge self-host compose", "forge self-host env", "forge self-host check --json"];
15
+ }
16
+
17
+ export function selfHostReadyNextActions(): string[] {
18
+ return ["docker compose -f deploy/docker-compose.yml config", "forge release prepare --env production"];
19
+ }
20
+
21
+ export function docsReadyNextActions(): string[] {
22
+ return ["bun test tests/docs/readthedocs.test.ts", "mkdocs build --strict"];
23
+ }