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,441 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { GENERATED_DIR } from "../compiler/emitter/constants.ts";
4
+ import { nodeFileSystem } from "../compiler/fs/index.ts";
5
+ import { stripDeterministicHeader } from "../compiler/primitives/header.ts";
6
+
7
+ export type AuthMdSubcommand = "generate" | "check";
8
+
9
+ export interface AuthMdCommandOptions {
10
+ subcommand: AuthMdSubcommand;
11
+ workspaceRoot: string;
12
+ json: boolean;
13
+ output?: string;
14
+ }
15
+
16
+ export interface AuthMdCommandResult {
17
+ ok: boolean;
18
+ path: string;
19
+ metadataPath: string;
20
+ changed: boolean;
21
+ diagnostics: Array<{ code: string; message: string }>;
22
+ data: {
23
+ commands: number;
24
+ queries: number;
25
+ liveQueries: number;
26
+ actions: number;
27
+ policies: number;
28
+ aiTools: number;
29
+ requiresTenant: boolean;
30
+ };
31
+ exitCode: 0 | 1;
32
+ }
33
+
34
+ interface RuntimeEntry {
35
+ name: string;
36
+ policy?: string;
37
+ requiresAuth?: boolean;
38
+ risk?: string;
39
+ needsApproval?: boolean;
40
+ }
41
+
42
+ interface AgentContractLike {
43
+ project?: { name?: string };
44
+ commands?: RuntimeEntry[];
45
+ queries?: RuntimeEntry[];
46
+ liveQueries?: RuntimeEntry[];
47
+ actions?: RuntimeEntry[];
48
+ policies?: Array<{ name: string; kind?: string; roles?: string[]; permissions?: string[] }>;
49
+ auth?: {
50
+ defaultMode?: string;
51
+ bearerTokenHeader?: string;
52
+ env?: Record<string, string>;
53
+ claims?: Record<string, string | undefined>;
54
+ requiresTenant?: boolean;
55
+ };
56
+ }
57
+
58
+ interface AgentToolsLike {
59
+ tools?: Array<{
60
+ name: string;
61
+ description?: string;
62
+ risk?: string;
63
+ needsApproval?: boolean | "dynamic";
64
+ }>;
65
+ }
66
+
67
+ type RuntimeEntryKind = "command" | "query" | "liveQuery" | "action";
68
+
69
+ function readGeneratedJson<T>(workspaceRoot: string, relativePath: string): T | null {
70
+ const absolute = join(workspaceRoot, relativePath);
71
+ if (!nodeFileSystem.exists(absolute)) {
72
+ return null;
73
+ }
74
+ return JSON.parse(stripDeterministicHeader(readFileSync(absolute, "utf8"))) as T;
75
+ }
76
+
77
+ function outputPath(options: AuthMdCommandOptions): string {
78
+ return options.output?.trim() || "public/auth.md";
79
+ }
80
+
81
+ function runtimeEntryRisk(kind: RuntimeEntryKind, entry: RuntimeEntry): string {
82
+ if (entry.risk) {
83
+ return entry.risk;
84
+ }
85
+ if (kind === "command") {
86
+ return "write";
87
+ }
88
+ if (kind === "action") {
89
+ return "external";
90
+ }
91
+ return "read";
92
+ }
93
+
94
+ function runtimeEntryNeedsApproval(kind: RuntimeEntryKind, entry: RuntimeEntry): boolean {
95
+ return entry.needsApproval ?? kind === "action";
96
+ }
97
+
98
+ function listRuntimeEntries(
99
+ title: string,
100
+ kind: RuntimeEntryKind,
101
+ entries: RuntimeEntry[] | undefined,
102
+ ): string[] {
103
+ const rows = (entries ?? []).map((entry) =>
104
+ `| \`${entry.name}\` | ${entry.policy ? `\`${entry.policy}\`` : "none"} | ${
105
+ entry.requiresAuth === false ? "no" : "yes"
106
+ } | ${runtimeEntryRisk(kind, entry)} | ${String(runtimeEntryNeedsApproval(kind, entry))} |`
107
+ );
108
+ return [
109
+ `## ${title}`,
110
+ "",
111
+ "| Name | Policy | Requires auth | Risk | Needs approval |",
112
+ "|------|--------|---------------|------|----------------|",
113
+ ...(rows.length > 0 ? rows : ["| none | none | no | none | false |"]),
114
+ "",
115
+ ];
116
+ }
117
+
118
+ function existingDocLinks(workspaceRoot: string): string[] {
119
+ const candidates = [
120
+ "README.md",
121
+ "docs/index.md",
122
+ "docs/security-and-data.md",
123
+ "docs/forge-add.md",
124
+ `${GENERATED_DIR}/capabilityMap.md`,
125
+ `${GENERATED_DIR}/operationPlaybooks.md`,
126
+ `${GENERATED_DIR}/docs/workos.md`,
127
+ ];
128
+ const docsDir = join(workspaceRoot, "docs");
129
+ if (existsSync(docsDir)) {
130
+ for (const entry of readdirSync(docsDir).slice(0, 20)) {
131
+ if (entry.endsWith(".md")) {
132
+ candidates.push(`docs/${entry}`);
133
+ }
134
+ }
135
+ }
136
+ return [...new Set(candidates)].filter((path) => existsSync(join(workspaceRoot, path)));
137
+ }
138
+
139
+ function riskMetadata(contract: AgentContractLike | null, tools: AgentToolsLike | null) {
140
+ const runtime = [
141
+ ...(contract?.commands ?? []).map((entry) => ({ kind: "command" as const, ...entry })),
142
+ ...(contract?.queries ?? []).map((entry) => ({ kind: "query" as const, ...entry })),
143
+ ...(contract?.liveQueries ?? []).map((entry) => ({ kind: "liveQuery" as const, ...entry })),
144
+ ...(contract?.actions ?? []).map((entry) => ({ kind: "action" as const, ...entry })),
145
+ ].map((entry) => ({
146
+ kind: entry.kind,
147
+ name: entry.name,
148
+ policy: entry.policy ?? null,
149
+ risk: runtimeEntryRisk(entry.kind, entry),
150
+ needs_approval: runtimeEntryNeedsApproval(entry.kind, entry),
151
+ requires_auth: entry.requiresAuth !== false,
152
+ }));
153
+ const aiTools = (tools?.tools ?? []).map((tool) => ({
154
+ kind: "aiTool",
155
+ name: tool.name,
156
+ risk: tool.risk ?? "read",
157
+ needs_approval: tool.needsApproval ?? false,
158
+ policy: null,
159
+ }));
160
+ return [...runtime, ...aiTools];
161
+ }
162
+
163
+ function metadataPathFor(markdownPath: string): string {
164
+ const publicPrefix = "public/";
165
+ return markdownPath.startsWith(publicPrefix)
166
+ ? "public/.well-known/oauth-protected-resource"
167
+ : `${dirname(markdownPath)}/.well-known/oauth-protected-resource`;
168
+ }
169
+
170
+ function parseEnvText(text: string): Record<string, string> {
171
+ const values: Record<string, string> = {};
172
+ for (const line of text.split(/\r?\n/)) {
173
+ const match = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/.exec(line);
174
+ if (!match) continue;
175
+ values[match[1]!] = (match[2] ?? "").trim().replace(/^["']|["']$/g, "");
176
+ }
177
+ return values;
178
+ }
179
+
180
+ function readRuntimeEnv(workspaceRoot: string): Record<string, string> {
181
+ const read = (path: string) => {
182
+ const absolute = join(workspaceRoot, path);
183
+ return existsSync(absolute) ? parseEnvText(readFileSync(absolute, "utf8")) : {};
184
+ };
185
+ return {
186
+ ...read(".env"),
187
+ ...read(".env.local"),
188
+ ...Object.fromEntries(
189
+ Object.entries(process.env)
190
+ .filter(([key]) => key.startsWith("FORGE_") || key.startsWith("WORKOS_") || key.startsWith("VITE_WORKOS_"))
191
+ .filter((entry): entry is [string, string] => typeof entry[1] === "string"),
192
+ ),
193
+ };
194
+ }
195
+
196
+ function valuePresent(env: Record<string, string>, name: string): boolean {
197
+ return typeof env[name] === "string" && env[name]!.trim().length > 0;
198
+ }
199
+
200
+ function authEnvDiagnostics(workspaceRoot: string): AuthMdCommandResult["diagnostics"] {
201
+ const env = readRuntimeEnv(workspaceRoot);
202
+ const mode = env.FORGE_AUTH_MODE;
203
+ if (mode !== "oidc" && mode !== "jwt") {
204
+ return [];
205
+ }
206
+ const diagnostics: AuthMdCommandResult["diagnostics"] = [];
207
+ if (!valuePresent(env, "FORGE_AUTH_ISSUER")) {
208
+ diagnostics.push({
209
+ code: "FORGE_AUTHMD_AUTH_ENV_MISSING",
210
+ message: "FORGE_AUTH_MODE uses production auth, but FORGE_AUTH_ISSUER is missing; for hosted WorkOS use https://api.workos.com",
211
+ });
212
+ }
213
+ if (!valuePresent(env, "FORGE_AUTH_JWKS_URI")) {
214
+ const clientId = env.WORKOS_CLIENT_ID || env.VITE_WORKOS_CLIENT_ID || "<WORKOS_CLIENT_ID>";
215
+ diagnostics.push({
216
+ code: "FORGE_AUTHMD_AUTH_ENV_MISSING",
217
+ message: `FORGE_AUTH_MODE uses production auth, but FORGE_AUTH_JWKS_URI is missing; for hosted WorkOS use https://api.workos.com/sso/jwks/${clientId}`,
218
+ });
219
+ }
220
+ return diagnostics;
221
+ }
222
+
223
+ function renderAuthMd(workspaceRoot: string): AuthMdCommandResult & { content: string; metadataContent: string } {
224
+ const contract = readGeneratedJson<AgentContractLike>(
225
+ workspaceRoot,
226
+ `${GENERATED_DIR}/agentContract.json`,
227
+ );
228
+ const tools = readGeneratedJson<AgentToolsLike>(
229
+ workspaceRoot,
230
+ `${GENERATED_DIR}/agentTools.json`,
231
+ );
232
+ const diagnostics: AuthMdCommandResult["diagnostics"] = [];
233
+ if (!contract) {
234
+ diagnostics.push({
235
+ code: "FORGE_AUTHMD_MISSING_AGENT_CONTRACT",
236
+ message: "missing src/forge/_generated/agentContract.json; run forge generate first",
237
+ });
238
+ }
239
+
240
+ const auth = contract?.auth;
241
+ const docLinks = existingDocLinks(workspaceRoot);
242
+ const riskRows = riskMetadata(contract, tools);
243
+ const toolRows = (tools?.tools ?? []).map((tool) =>
244
+ `| \`${tool.name}\` | ${tool.description ?? ""} | ${tool.risk ?? "read"} | ${
245
+ String(tool.needsApproval ?? false)
246
+ } |`
247
+ );
248
+ const policyRows = (contract?.policies ?? []).map((policy) =>
249
+ `| \`${policy.name}\` | ${policy.kind ?? "roles"} | ${
250
+ (policy.roles ?? []).map((role) => `\`${role}\``).join(", ") || "none"
251
+ } | ${(policy.permissions ?? []).map((permission) => `\`${permission}\``).join(", ") || "none"} |`
252
+ );
253
+ const scopes = (contract?.policies ?? []).map((policy) => policy.name).sort();
254
+ const actionNames = (contract?.actions ?? []).map((entry) => entry.name).sort();
255
+ const protectedResourceMetadata = {
256
+ resource: "/",
257
+ authorization_servers: ["configured via FORGE_AUTH_ISSUER"],
258
+ bearer_methods_supported: ["header"],
259
+ resource_documentation: "/auth.md",
260
+ scopes_supported: scopes,
261
+ resource_signing_alg_values_supported: auth?.env?.algorithms ? ["RS256"] : undefined,
262
+ forge: {
263
+ app: contract?.project?.name ?? "unknown",
264
+ tenant_required: auth?.requiresTenant ?? false,
265
+ commands: (contract?.commands ?? []).map((entry) => entry.name).sort(),
266
+ queries: (contract?.queries ?? []).map((entry) => entry.name).sort(),
267
+ live_queries: (contract?.liveQueries ?? []).map((entry) => entry.name).sort(),
268
+ actions: actionNames,
269
+ policies: scopes,
270
+ risks: riskRows,
271
+ docs: docLinks.map((path) => `/${path}`),
272
+ ai_tools: (tools?.tools ?? []).map((tool) => ({
273
+ name: tool.name,
274
+ risk: tool.risk ?? "read",
275
+ needs_approval: tool.needsApproval ?? false,
276
+ })),
277
+ },
278
+ };
279
+
280
+ const content = [
281
+ "# auth.md",
282
+ "",
283
+ `App: ${contract?.project?.name ?? "unknown"}`,
284
+ "",
285
+ "This file is generated by ForgeOS for agents and authorization-aware clients. It describes protected resource metadata, runtime capabilities, policy names, tenant requirements, and approval expectations without exposing secrets.",
286
+ "",
287
+ "## Protected Resource Metadata",
288
+ "",
289
+ `- Auth mode: \`${auth?.defaultMode ?? "dev-headers"}\` locally; production should use \`jwt\` or \`oidc\`.`,
290
+ `- Bearer header: \`${auth?.bearerTokenHeader ?? "Authorization"}\`.`,
291
+ `- Issuer env: \`${auth?.env?.issuer ?? "FORGE_AUTH_ISSUER"}\`.`,
292
+ `- Audience env: \`${auth?.env?.audience ?? "FORGE_AUTH_AUDIENCE"}\`.`,
293
+ `- JWKS env: \`${auth?.env?.jwksUri ?? "FORGE_AUTH_JWKS_URI"}\`.`,
294
+ `- Tenant required: \`${String(auth?.requiresTenant ?? false)}\`.`,
295
+ "",
296
+ "## OAuth 2.0 Protected Resource Metadata",
297
+ "",
298
+ "```json",
299
+ JSON.stringify(protectedResourceMetadata, null, 2),
300
+ "```",
301
+ "",
302
+ "## Claim Mapping",
303
+ "",
304
+ `- User: \`${auth?.claims?.userId ?? "sub"}\``,
305
+ `- Email: \`${auth?.claims?.email ?? "email"}\``,
306
+ `- Tenant/organization: \`${auth?.claims?.tenantId ?? "tenant_id"}\``,
307
+ `- Role: \`${auth?.claims?.role ?? "role"}\``,
308
+ `- Roles: \`${auth?.claims?.roles ?? "roles"}\``,
309
+ `- Permissions: \`${auth?.claims?.permissions ?? "permissions"}\``,
310
+ "",
311
+ ...listRuntimeEntries("Commands", "command", contract?.commands),
312
+ ...listRuntimeEntries("Queries", "query", contract?.queries),
313
+ ...listRuntimeEntries("Live Queries", "liveQuery", contract?.liveQueries),
314
+ ...listRuntimeEntries("Actions", "action", contract?.actions),
315
+ "## Policies",
316
+ "",
317
+ "| Policy | Kind | Roles | Permissions |",
318
+ "|--------|------|-------|-------------|",
319
+ ...(policyRows.length > 0 ? policyRows : ["| none | none | none | none |"]),
320
+ "",
321
+ "## Risk And Approval Metadata",
322
+ "",
323
+ "| Kind | Name | Risk | Needs approval | Policy |",
324
+ "|------|------|------|----------------|--------|",
325
+ ...(riskRows.length > 0
326
+ ? riskRows.map((entry) => `| ${entry.kind} | \`${entry.name}\` | ${entry.risk} | ${String(entry.needs_approval)} | ${entry.policy ? `\`${entry.policy}\`` : "none"} |`)
327
+ : ["| none | none | read | false | none |"]),
328
+ "",
329
+ "## Agent Tools",
330
+ "",
331
+ "| Tool | Description | Risk | Needs approval |",
332
+ "|------|-------------|------|----------------|",
333
+ ...(toolRows.length > 0 ? toolRows : ["| none | none | read | false |"]),
334
+ "",
335
+ "## Verification",
336
+ "",
337
+ "- Run `forge auth check --json` before production.",
338
+ "- Run `forge auth prove --json` before exposing tenant-scoped data.",
339
+ "- Run `forge authmd check --json` before publishing this file.",
340
+ "",
341
+ "## App Docs",
342
+ "",
343
+ "- `/auth.md` should be served as this public authorization summary when the web app has a public directory.",
344
+ "- `src/forge/_generated/agentContract.json` is the private source contract.",
345
+ "- `src/forge/_generated/capabilityMap.json` maps frontend/backend capabilities.",
346
+ "- `src/forge/_generated/policyRegistry.json` is the policy source of truth.",
347
+ ...docLinks.map((path) => `- \`${path}\``),
348
+ "",
349
+ ].join("\n");
350
+
351
+ return {
352
+ ok: diagnostics.length === 0,
353
+ path: "public/auth.md",
354
+ metadataPath: "public/.well-known/oauth-protected-resource",
355
+ changed: false,
356
+ diagnostics,
357
+ data: {
358
+ commands: contract?.commands?.length ?? 0,
359
+ queries: contract?.queries?.length ?? 0,
360
+ liveQueries: contract?.liveQueries?.length ?? 0,
361
+ actions: contract?.actions?.length ?? 0,
362
+ policies: contract?.policies?.length ?? 0,
363
+ aiTools: tools?.tools?.length ?? 0,
364
+ requiresTenant: auth?.requiresTenant ?? false,
365
+ },
366
+ content,
367
+ metadataContent: `${JSON.stringify(protectedResourceMetadata, null, 2)}\n`,
368
+ exitCode: diagnostics.length === 0 ? 0 : 1,
369
+ };
370
+ }
371
+
372
+ export function runAuthMdCommand(options: AuthMdCommandOptions): AuthMdCommandResult {
373
+ const rendered = renderAuthMd(options.workspaceRoot);
374
+ const path = outputPath(options);
375
+ const metadataPath = metadataPathFor(path);
376
+ const absolute = join(options.workspaceRoot, path);
377
+ const metadataAbsolute = join(options.workspaceRoot, metadataPath);
378
+ const current = nodeFileSystem.exists(absolute) ? readFileSync(absolute, "utf8") : null;
379
+ const currentMetadata = nodeFileSystem.exists(metadataAbsolute) ? readFileSync(metadataAbsolute, "utf8") : null;
380
+ const changed = current !== rendered.content || currentMetadata !== rendered.metadataContent;
381
+ const result = {
382
+ ...rendered,
383
+ path,
384
+ metadataPath,
385
+ changed,
386
+ exitCode: rendered.exitCode,
387
+ };
388
+ delete (result as { content?: string }).content;
389
+ delete (result as { metadataContent?: string }).metadataContent;
390
+
391
+ if (rendered.exitCode !== 0) {
392
+ return result;
393
+ }
394
+
395
+ if (options.subcommand === "check") {
396
+ const envDiagnostics = authEnvDiagnostics(options.workspaceRoot);
397
+ if (envDiagnostics.length > 0) {
398
+ return {
399
+ ...result,
400
+ ok: false,
401
+ diagnostics: envDiagnostics,
402
+ exitCode: 1,
403
+ };
404
+ }
405
+ return {
406
+ ...result,
407
+ ok: !changed,
408
+ diagnostics: changed
409
+ ? [
410
+ {
411
+ code: "FORGE_AUTHMD_DRIFT",
412
+ message: `${path} is missing or stale; run forge authmd generate`,
413
+ },
414
+ ]
415
+ : [],
416
+ exitCode: changed ? 1 : 0,
417
+ };
418
+ }
419
+
420
+ mkdirSync(dirname(absolute), { recursive: true });
421
+ mkdirSync(dirname(metadataAbsolute), { recursive: true });
422
+ writeFileSync(absolute, rendered.content, "utf8");
423
+ writeFileSync(metadataAbsolute, rendered.metadataContent, "utf8");
424
+ return {
425
+ ...result,
426
+ ok: true,
427
+ changed,
428
+ exitCode: 0,
429
+ };
430
+ }
431
+
432
+ export function formatAuthMdJson(result: AuthMdCommandResult): string {
433
+ return `${JSON.stringify(result, null, 2)}\n`;
434
+ }
435
+
436
+ export function formatAuthMdHuman(result: AuthMdCommandResult): string {
437
+ const status = result.ok ? "ok" : "failed";
438
+ const drift = result.changed ? "changed" : "unchanged";
439
+ const diagnostics = result.diagnostics.map((item) => `${item.code}: ${item.message}`).join("\n");
440
+ return `auth.md ${status}: ${result.path} (${drift})\n${diagnostics ? `${diagnostics}\n` : ""}`;
441
+ }
@@ -0,0 +1,112 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { createWorkspaceBaseline, readWorkspaceBaseline, writeWorkspaceBaseline, WORKSPACE_BASELINE_PATH } from "../workspace/baseline.ts";
3
+ import { listWorkspaceFiles } from "../workspace/git-summary.ts";
4
+
5
+ export type BaselineSubcommand = "create" | "status";
6
+
7
+ export interface BaselineCommandOptions {
8
+ subcommand: BaselineSubcommand;
9
+ workspaceRoot: string;
10
+ json: boolean;
11
+ reason?: string;
12
+ }
13
+
14
+ export interface BaselineCommandResult {
15
+ ok: boolean;
16
+ path: string;
17
+ required: boolean;
18
+ created?: boolean;
19
+ baseline?: ReturnType<typeof readWorkspaceBaseline>;
20
+ summary: {
21
+ files: number;
22
+ reason?: string;
23
+ tracking: "git" | "forge-baseline" | "missing";
24
+ };
25
+ nextActions: string[];
26
+ exitCode: 0 | 1;
27
+ }
28
+
29
+ function gitAvailable(workspaceRoot: string): boolean {
30
+ const result = spawnSync("git", ["rev-parse", "--show-toplevel"], {
31
+ cwd: workspaceRoot,
32
+ encoding: "utf8",
33
+ windowsHide: true,
34
+ });
35
+ return result.status === 0;
36
+ }
37
+
38
+ export function runBaselineCommand(options: BaselineCommandOptions): BaselineCommandResult {
39
+ if (options.subcommand === "create") {
40
+ const files = listWorkspaceFiles(options.workspaceRoot);
41
+ const baseline = createWorkspaceBaseline({
42
+ workspaceRoot: options.workspaceRoot,
43
+ files,
44
+ reason: options.reason,
45
+ });
46
+ writeWorkspaceBaseline(options.workspaceRoot, baseline);
47
+ return {
48
+ ok: true,
49
+ path: WORKSPACE_BASELINE_PATH,
50
+ required: false,
51
+ created: true,
52
+ baseline,
53
+ summary: {
54
+ files: Object.keys(baseline.files).length,
55
+ tracking: "forge-baseline",
56
+ ...(baseline.reason ? { reason: baseline.reason } : {}),
57
+ },
58
+ nextActions: ["forge changed --json", "forge handoff --json"],
59
+ exitCode: 0,
60
+ };
61
+ }
62
+
63
+ const baseline = readWorkspaceBaseline(options.workspaceRoot);
64
+ if (!baseline && gitAvailable(options.workspaceRoot)) {
65
+ return {
66
+ ok: true,
67
+ path: WORKSPACE_BASELINE_PATH,
68
+ required: false,
69
+ baseline: null,
70
+ summary: {
71
+ files: 0,
72
+ tracking: "git",
73
+ },
74
+ nextActions: ["forge changed --json", "git status --short"],
75
+ exitCode: 0,
76
+ };
77
+ }
78
+ return {
79
+ ok: baseline !== null,
80
+ path: WORKSPACE_BASELINE_PATH,
81
+ required: baseline === null,
82
+ baseline,
83
+ summary: {
84
+ files: baseline ? Object.keys(baseline.files).length : 0,
85
+ tracking: baseline ? "forge-baseline" : "missing",
86
+ ...(baseline?.reason ? { reason: baseline.reason } : {}),
87
+ },
88
+ nextActions: baseline
89
+ ? ["forge changed --json", "forge baseline create --reason refresh --json"]
90
+ : ["forge baseline create --reason initial-scaffold --json", "git init"],
91
+ exitCode: baseline ? 0 : 1,
92
+ };
93
+ }
94
+
95
+ export function formatBaselineJson(result: BaselineCommandResult): string {
96
+ return `${JSON.stringify(result, null, 2)}\n`;
97
+ }
98
+
99
+ export function formatBaselineHuman(result: BaselineCommandResult): string {
100
+ const label = result.required ? "missing" : result.summary.tracking === "git" ? "not required (git workspace)" : "ready";
101
+ const lines = [
102
+ `Forge baseline: ${label}`,
103
+ `Path: ${result.path}`,
104
+ `Tracking: ${result.summary.tracking}`,
105
+ `Files: ${result.summary.files}`,
106
+ ];
107
+ if (result.summary.reason) {
108
+ lines.push(`Reason: ${result.summary.reason}`);
109
+ }
110
+ lines.push("", "Next:", ...result.nextActions.map((action) => ` ${action}`));
111
+ return `${lines.join("\n")}\n`;
112
+ }
@@ -46,6 +46,22 @@ async function runOptionalScript(
46
46
  return { skipped: false, exitCode };
47
47
  }
48
48
 
49
+ function readPackageScripts(workspaceRoot: string): Record<string, string> {
50
+ const packageJsonPath = join(workspaceRoot, "package.json");
51
+ if (!nodeFileSystem.exists(packageJsonPath)) {
52
+ return {};
53
+ }
54
+ const pkg = JSON.parse(nodeFileSystem.readText(packageJsonPath) ?? "{}") as {
55
+ scripts?: Record<string, string>;
56
+ };
57
+ return pkg.scripts ?? {};
58
+ }
59
+
60
+ function shouldTypecheckBuild(workspaceRoot: string): boolean {
61
+ const scripts = readPackageScripts(workspaceRoot);
62
+ return Boolean(scripts.typecheck || nodeFileSystem.exists(join(workspaceRoot, "tsconfig.json")));
63
+ }
64
+
49
65
  export async function runBuildCommand(options: BuildCommandOptions): Promise<BuildCommandResult> {
50
66
  const steps: BuildCommandResult["steps"] = [];
51
67
  const generate = await runGenerateCommand({
@@ -63,10 +79,10 @@ export async function runBuildCommand(options: BuildCommandOptions): Promise<Bui
63
79
  const verify = await runVerifyCommand({
64
80
  workspaceRoot: options.workspaceRoot,
65
81
  json: false,
66
- skipTests: false,
67
- skipTypecheck: false,
68
- skipEslint: false,
69
- strict: true,
82
+ skipTests: true,
83
+ skipTypecheck: !shouldTypecheckBuild(options.workspaceRoot),
84
+ skipEslint: true,
85
+ strict: false,
70
86
  });
71
87
  steps.push({ name: "verify", ok: verify.exitCode === 0, exitCode: verify.exitCode });
72
88
  if (verify.exitCode !== 0) {