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
@@ -4,6 +4,7 @@ import {
4
4
  FORGE_TELEMETRY_SECRET_REDACTED,
5
5
  } from "../../compiler/diagnostics/codes.ts";
6
6
  import type { Diagnostic } from "../../compiler/types/diagnostic.ts";
7
+ import { hashStable } from "../../compiler/primitives/hash.ts";
7
8
 
8
9
  const SECRET_KEY_PATTERN =
9
10
  /password|secret|token|apikey|authorization|cookie/i;
@@ -101,6 +102,28 @@ function scrubObject(
101
102
  return result;
102
103
  }
103
104
 
105
+ function summarizeValue(value: unknown): Record<string, unknown> {
106
+ if (Array.isArray(value)) {
107
+ return { type: "array", length: value.length };
108
+ }
109
+ if (value && typeof value === "object") {
110
+ return {
111
+ type: "object",
112
+ keys: Object.keys(value as Record<string, unknown>).sort().slice(0, 20),
113
+ };
114
+ }
115
+ if (typeof value === "string") {
116
+ return { type: "string", length: value.length };
117
+ }
118
+ return { type: value === null ? "null" : typeof value };
119
+ }
120
+
121
+ function summarizePayload(payload: Record<string, unknown>): Record<string, unknown> {
122
+ return Object.fromEntries(
123
+ Object.entries(payload).map(([key, value]) => [key, summarizeValue(value)]),
124
+ );
125
+ }
126
+
104
127
  function truncateString(
105
128
  value: string,
106
129
  maxBytes: number,
@@ -148,7 +171,8 @@ export function scrubEnvelopePayload<T extends Record<string, unknown>>(
148
171
  }
149
172
 
150
173
  const serialized = JSON.stringify(scrubbed);
151
- if (Buffer.byteLength(serialized, "utf8") > MAX_PAYLOAD_BYTES) {
174
+ const originalBytes = Buffer.byteLength(serialized, "utf8");
175
+ if (originalBytes > MAX_PAYLOAD_BYTES) {
152
176
  diagnostics.push(
153
177
  createDiagnostic({
154
178
  severity: "warning",
@@ -156,10 +180,16 @@ export function scrubEnvelopePayload<T extends Record<string, unknown>>(
156
180
  message: `truncated telemetry payload to ${MAX_PAYLOAD_BYTES} bytes`,
157
181
  }),
158
182
  );
159
- const parsed = JSON.parse(
160
- truncateString(serialized, MAX_PAYLOAD_BYTES, diagnostics, "payload"),
161
- ) as T;
162
- return { value: parsed, diagnostics };
183
+ return {
184
+ value: {
185
+ truncated: true,
186
+ originalBytes,
187
+ maxBytes: MAX_PAYLOAD_BYTES,
188
+ hash: hashStable(serialized),
189
+ summary: summarizePayload(scrubbed),
190
+ } as unknown as T,
191
+ diagnostics,
192
+ };
163
193
  }
164
194
 
165
195
  return { value: scrubbed, diagnostics };
@@ -6,7 +6,7 @@ import {
6
6
  FORGE_WEBHOOK_TIMESTAMP_INVALID,
7
7
  } from "../../compiler/diagnostics/codes.ts";
8
8
 
9
- export type WebhookProvider = "generic" | "github" | "stripe";
9
+ export type WebhookProvider = "generic" | "github" | "stripe" | "workos";
10
10
 
11
11
  export interface WebhookReplayStore {
12
12
  has(eventId: string): boolean | Promise<boolean>;
@@ -69,12 +69,14 @@ function fail(
69
69
  return { ok: false, provider, code, reason };
70
70
  }
71
71
 
72
- function parseStripeHeader(header: string): { timestamp?: number; signatures: string[] } {
72
+ function parseTimestampedSignatureHeader(header: string): { timestampRaw?: string; timestamp?: number; signatures: string[] } {
73
73
  const signatures: string[] = [];
74
+ let timestampRaw: string | undefined;
74
75
  let timestamp: number | undefined;
75
76
  for (const part of header.split(",")) {
76
77
  const [key, value] = part.split("=", 2).map((item) => item.trim());
77
78
  if (key === "t") {
79
+ timestampRaw = value;
78
80
  const parsed = Number(value);
79
81
  if (Number.isFinite(parsed)) {
80
82
  timestamp = parsed;
@@ -84,7 +86,7 @@ function parseStripeHeader(header: string): { timestamp?: number; signatures: st
84
86
  signatures.push(value);
85
87
  }
86
88
  }
87
- return { timestamp, signatures };
89
+ return { timestampRaw, timestamp, signatures };
88
90
  }
89
91
 
90
92
  function validateTimestamp(input: {
@@ -131,9 +133,11 @@ export async function verifyWebhookSignature(
131
133
  let valid = false;
132
134
  let timestamp: number | undefined;
133
135
 
134
- if (input.provider === "stripe") {
135
- const parsed = parseStripeHeader(signatureHeader);
136
- timestamp = parsed.timestamp;
136
+ if (input.provider === "stripe" || input.provider === "workos") {
137
+ const parsed = parseTimestampedSignatureHeader(signatureHeader);
138
+ timestamp = input.provider === "workos" && parsed.timestamp !== undefined
139
+ ? parsed.timestamp / 1000
140
+ : parsed.timestamp;
137
141
  const timestampFailure = validateTimestamp({
138
142
  provider: input.provider,
139
143
  timestamp,
@@ -143,7 +147,8 @@ export async function verifyWebhookSignature(
143
147
  if (timestampFailure) {
144
148
  return timestampFailure;
145
149
  }
146
- const signedPayload = `${timestamp}.${Buffer.from(bytes(input.payload)).toString("utf8")}`;
150
+ const timestampForSignature = parsed.timestampRaw ?? String(parsed.timestamp);
151
+ const signedPayload = `${timestampForSignature}.${Buffer.from(bytes(input.payload)).toString("utf8")}`;
147
152
  const expected = hmacHex(input.secret, signedPayload);
148
153
  valid = parsed.signatures.some((signature) => safeEqualHex(signature, expected));
149
154
  } else if (input.provider === "github") {
@@ -1,6 +1,7 @@
1
1
  export type ForgeAuthRule =
2
2
  | { kind: "policy"; policy: string }
3
3
  | { kind: "roles"; roles: string[] }
4
+ | { kind: "permissions"; permissions: string[] }
4
5
  | { kind: "public" };
5
6
 
6
7
  export type ForgeDefinition<T extends Record<string, unknown>> = T;
@@ -134,11 +135,19 @@ export function canRole(...roles: string[]): ForgeAuthRule {
134
135
  return { kind: "roles", roles };
135
136
  }
136
137
 
138
+ export function canPermission(...permissions: string[]): ForgeAuthRule {
139
+ return { kind: "permissions", permissions };
140
+ }
141
+
137
142
  export function public_(): ForgeAuthRule {
138
143
  return { kind: "public" };
139
144
  }
140
145
 
141
- export function command<T extends ForgeCommandDefinition>(definition: T): ForgeDefinition<T> {
146
+ export function command<
147
+ TArgs = unknown,
148
+ TResult = unknown,
149
+ T extends ForgeCommandDefinition<TArgs, TResult> = ForgeCommandDefinition<TArgs, TResult>,
150
+ >(definition: T): ForgeDefinition<T> {
142
151
  return definition;
143
152
  }
144
153
 
@@ -173,8 +182,13 @@ export function step<T extends (...args: any[]) => unknown>(
173
182
  return { kind: "step", name, handler };
174
183
  }
175
184
 
176
- export function workflow<T extends Record<string, unknown>>(definition: T): ForgeDefinition<T> {
177
- return definition;
185
+ export function workflow<T extends Record<string, unknown>>(
186
+ definition: T,
187
+ ): ForgeDefinition<T & { __forge: { kind: "workflow" } }> {
188
+ return {
189
+ ...definition,
190
+ __forge: { kind: "workflow" },
191
+ };
178
192
  }
179
193
 
180
194
  export {
@@ -57,6 +57,120 @@ function uniqueSorted(values: Array<string | undefined>): string[] {
57
57
  return [...new Set(values.filter((value): value is string => Boolean(value)))].sort();
58
58
  }
59
59
 
60
+ function walkFiles(root: string, relative = ""): string[] {
61
+ const absolute = relative ? join(root, relative) : root;
62
+ return nodeFileSystem.readDir(absolute).flatMap((entry) => {
63
+ const child = relative ? `${relative}/${entry.name}` : entry.name;
64
+ const normalized = normalize(child);
65
+ if (entry.isDirectory) {
66
+ if (["node_modules", ".next", ".nuxt", "dist", "build", ".vite"].includes(entry.name)) {
67
+ return [];
68
+ }
69
+ return walkFiles(root, normalized);
70
+ }
71
+ return entry.isFile ? [normalized] : [];
72
+ });
73
+ }
74
+
75
+ function listWebSourceFiles(workspaceRoot: string, webRoot: string): Array<{ path: string; text: string }> {
76
+ if (!webRoot) return [];
77
+ const absoluteWebRoot = join(workspaceRoot, normalize(webRoot));
78
+ if (!nodeFileSystem.exists(absoluteWebRoot)) return [];
79
+ return walkFiles(absoluteWebRoot)
80
+ .filter((file) => /\.(tsx|jsx|vue|svelte|html)$/.test(file))
81
+ .map((file) => {
82
+ const path = `${normalize(webRoot)}/${file}`;
83
+ return { path, text: readText(workspaceRoot, path) };
84
+ })
85
+ .filter((source) => source.text.trim().length > 0);
86
+ }
87
+
88
+ function readOptionalGeneratedJson(workspaceRoot: string, name: string): unknown {
89
+ try {
90
+ return readJson<unknown>(workspaceRoot, `${GENERATED}/${name}`, null);
91
+ } catch {
92
+ return null;
93
+ }
94
+ }
95
+
96
+ function hasTenantScopedData(workspaceRoot: string): boolean {
97
+ const dataGraph = readOptionalGeneratedJson(workspaceRoot, "dataGraph.json") as { tables?: Array<Record<string, unknown>> } | null;
98
+ return (dataGraph?.tables ?? []).some((table) =>
99
+ table?.tenantScoped === true ||
100
+ table?.tenantScope === true ||
101
+ typeof table?.tenantField === "string" ||
102
+ (Array.isArray(table?.fields) && table.fields.some((field) =>
103
+ typeof field === "object" &&
104
+ field !== null &&
105
+ ("tenantId" === (field as { name?: string }).name || "tenant_id" === (field as { name?: string }).name)
106
+ ))
107
+ );
108
+ }
109
+
110
+ function hasProductionAuthMode(workspaceRoot: string): boolean {
111
+ const agentContract = readOptionalGeneratedJson(workspaceRoot, "agentContract.json") as { auth?: { modes?: string[]; production?: unknown } } | null;
112
+ const modes = agentContract?.auth?.modes ?? [];
113
+ return modes.includes("jwt") || modes.includes("oidc") || Boolean(agentContract?.auth?.production);
114
+ }
115
+
116
+ function looksLikeAuthFlow(text: string): boolean {
117
+ return /sign\s*in|signin|login|logout|authkit|organization|tenant|session|workos|clerk|auth0/i.test(text);
118
+ }
119
+
120
+ function hasWorkOSIntegration(workspaceRoot: string): boolean {
121
+ return nodeFileSystem.exists(join(workspaceRoot, `${GENERATED}/integrations/workos/authkit.ts`)) ||
122
+ nodeFileSystem.exists(join(workspaceRoot, `${GENERATED}/integrations/workos/auth-routes.ts`));
123
+ }
124
+
125
+ function webPackageHasAuthKit(workspaceRoot: string): boolean {
126
+ const path = join(workspaceRoot, "web/package.json");
127
+ if (!nodeFileSystem.exists(path)) return false;
128
+ try {
129
+ const packageJson = JSON.parse(nodeFileSystem.readText(path) ?? "{}") as {
130
+ dependencies?: Record<string, string>;
131
+ devDependencies?: Record<string, string>;
132
+ };
133
+ return Boolean(packageJson.dependencies?.["@workos-inc/authkit-react"] ?? packageJson.devDependencies?.["@workos-inc/authkit-react"]);
134
+ } catch {
135
+ return false;
136
+ }
137
+ }
138
+
139
+ function hasMainLandmark(text: string): boolean {
140
+ return /<main[\s>]|role=["']main["']|<header[\s>]|<nav[\s>]/i.test(text);
141
+ }
142
+
143
+ function hasRuntimeDataHook(text: string): boolean {
144
+ return /\b(useLiveQuery|useQuery|useForgeLiveQuery|useForgeQuery)\b/.test(text);
145
+ }
146
+
147
+ function hasStateText(text: string, pattern: RegExp): boolean {
148
+ return pattern.test(text);
149
+ }
150
+
151
+ function findFormWithoutLabel(text: string): boolean {
152
+ if (!/<(form|input|select|textarea)\b/i.test(text)) return false;
153
+ const controls = text.match(/<(input|select|textarea)\b[^>]*>/gi) ?? [];
154
+ return controls.some((control) => {
155
+ if (/\b(type=["']?(hidden|submit|button|checkbox|radio)["']?)/i.test(control)) return false;
156
+ if (/\b(aria-label|aria-labelledby|title)=/i.test(control)) return false;
157
+ const id = /\bid=["']([^"']+)["']/i.exec(control)?.[1];
158
+ if (id && new RegExp(`<label\\b[^>]*\\bfor=["']${id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`, "i").test(text)) {
159
+ return false;
160
+ }
161
+ return !/<label\b/i.test(text);
162
+ });
163
+ }
164
+
165
+ function findUnnamedButton(text: string): boolean {
166
+ const buttons = text.match(/<button\b[\s\S]*?<\/button>/gi) ?? [];
167
+ return buttons.some((button) => {
168
+ if (/\b(aria-label|aria-labelledby|title)=/i.test(button)) return false;
169
+ const inner = button.replace(/<button\b[^>]*>/i, "").replace(/<\/button>/i, "").replace(/<[^>]+>/g, "").trim();
170
+ return inner.length === 0;
171
+ });
172
+ }
173
+
60
174
  function routeName(path: string): string {
61
175
  if (path === "/") return "home";
62
176
  return path.replace(/^\//, "").replace(/[^a-zA-Z0-9]+/g, "-") || "route";
@@ -641,6 +755,9 @@ function selectScenarios(options: UiCommandOptions, scenarios: UiScenario[]): Ui
641
755
  }
642
756
 
643
757
  export async function runUiCommand(options: UiCommandOptions): Promise<UiCommandResult> {
758
+ if (options.subcommand === "audit") {
759
+ return runUiAudit(options);
760
+ }
644
761
  if (options.subcommand === "doctor") {
645
762
  return runUiDoctor(options);
646
763
  }
@@ -671,6 +788,98 @@ export async function runUiCommand(options: UiCommandOptions): Promise<UiCommand
671
788
  };
672
789
  }
673
790
 
791
+ function runUiAudit(options: UiCommandOptions): UiCommandResult {
792
+ const manifest = loadUiManifest(options.workspaceRoot);
793
+ const scenarios = loadUiScenarios(options.workspaceRoot);
794
+ const diagnostics: Diagnostic[] = [];
795
+ const webSources = listWebSourceFiles(options.workspaceRoot, manifest.webRoot);
796
+ const webText = webSources.map((source) => source.text).join("\n");
797
+ const appShellText = webSources
798
+ .filter((source) => !source.path.endsWith("/lib/workos-auth.tsx"))
799
+ .map((source) => source.text)
800
+ .join("\n");
801
+ const scenarioRoutes = new Set(scenarios.map((scenario) => scenario.route));
802
+ const scenarioNames = scenarios.map((scenario) => scenario.name);
803
+ const selectorSet = new Set(manifest.selectors);
804
+
805
+ if (manifest.routes.length === 0) {
806
+ diagnostics.push(diagnostic("warning", "FORGE_UI_ROUTE_FAILED", "No frontend routes are present in uiTestManifest."));
807
+ }
808
+ if (manifest.routes.length > 0 && scenarios.length === 0) {
809
+ diagnostics.push(diagnostic("error", "FORGE_UI_TESTID_MISSING", "Frontend routes exist but no UI scenarios were generated."));
810
+ }
811
+ for (const route of manifest.routes) {
812
+ if (!scenarioRoutes.has(route.path)) {
813
+ diagnostics.push(diagnostic("warning", "FORGE_UI_ROUTE_FAILED", `No UI scenario covers route '${route.path}'.`));
814
+ }
815
+ const usesRuntime = route.uses.commands.length > 0 || route.uses.queries.length > 0 || route.uses.liveQueries.length > 0;
816
+ if (usesRuntime && selectorSet.size === 0) {
817
+ diagnostics.push(diagnostic("warning", "FORGE_UI_TESTID_MISSING", `Route '${route.path}' uses Forge runtime bindings but no stable data-forge-testid selectors were detected.`));
818
+ }
819
+ }
820
+ const hasPolicySensitiveRuntime = scenarios.some((scenario) =>
821
+ scenario.requires.policies.length > 0 || scenario.requires.commands.length > 0
822
+ );
823
+ if (hasPolicySensitiveRuntime && !scenarioNames.some((name) => name.includes("policy-denied"))) {
824
+ diagnostics.push(diagnostic("warning", "FORGE_UI_POLICY_ERROR_MISSING", "Policy-sensitive UI flows should include a visible policy-denied scenario."));
825
+ }
826
+ if (manifest.routes.length > 0 && !manifest.selectors.some((selector) => selector.includes("data-forge-testid"))) {
827
+ diagnostics.push(diagnostic("warning", "FORGE_UI_TESTID_MISSING", "No data-forge-testid selectors were captured for UI smoke/audit stability."));
828
+ }
829
+ if (manifest.webRoot && manifest.routes.length > 0 && webSources.length === 0) {
830
+ diagnostics.push(diagnostic("warning", "FORGE_UI_SOURCE_MISSING", `No frontend source files were found under '${manifest.webRoot}' for static UX audit.`));
831
+ }
832
+ if (webSources.length > 0 && !webSources.some((source) => hasMainLandmark(source.text))) {
833
+ diagnostics.push(diagnostic("warning", "FORGE_UI_LANDMARK_MISSING", "Frontend source does not appear to include a main/header/nav landmark; add semantic landmarks for scanning and accessibility."));
834
+ }
835
+ for (const source of webSources) {
836
+ if (findFormWithoutLabel(source.text)) {
837
+ diagnostics.push(diagnostic("warning", "FORGE_UI_FORM_LABEL_MISSING", "Form controls should have labels or aria-label/aria-labelledby for accessible testing and real users.", source.path));
838
+ }
839
+ if (findUnnamedButton(source.text)) {
840
+ diagnostics.push(diagnostic("warning", "FORGE_UI_BUTTON_NAME_MISSING", "Icon-only or empty buttons should include aria-label/title text.", source.path));
841
+ }
842
+ }
843
+ if (webSources.some((source) => hasRuntimeDataHook(source.text))) {
844
+ if (!hasStateText(webText, /\b(isLoading|loading|pending|skeleton|spinner|carregando|loading\.\.\.)\b/i)) {
845
+ diagnostics.push(diagnostic("warning", "FORGE_UI_LOADING_STATE_MISSING", "Forge data-bound UI should expose a loading or pending state."));
846
+ }
847
+ if (!hasStateText(webText, /\b(error|erro|failed|failure|FORGE_|traceId|trace)\b/i)) {
848
+ diagnostics.push(diagnostic("warning", "FORGE_UI_ERROR_STATE_MISSING", "Forge data-bound UI should surface runtime/policy errors with enough context to debug."));
849
+ }
850
+ if (!hasStateText(webText, /\b(empty|no\s+\w+|none|vazio|sem\s+\w+|length\s*===\s*0)\b/i)) {
851
+ diagnostics.push(diagnostic("warning", "FORGE_UI_EMPTY_STATE_MISSING", "Forge data-bound UI should include an empty state so first-run apps do not look broken."));
852
+ }
853
+ }
854
+ if ((hasTenantScopedData(options.workspaceRoot) || hasProductionAuthMode(options.workspaceRoot)) && webSources.length > 0 && !looksLikeAuthFlow(webText)) {
855
+ diagnostics.push(diagnostic(
856
+ "warning",
857
+ "FORGE_UI_AUTH_FLOW_MISSING",
858
+ "Tenant-scoped or production-auth app has no obvious sign-in/session/organization UI; local devAuth is not a production auth flow.",
859
+ ));
860
+ }
861
+ if (
862
+ hasWorkOSIntegration(options.workspaceRoot) &&
863
+ manifest.webRoot &&
864
+ webSources.length > 0 &&
865
+ (!webPackageHasAuthKit(options.workspaceRoot) || !/AuthKitProvider/.test(appShellText) || !/getAccessToken/.test(appShellText))
866
+ ) {
867
+ diagnostics.push(diagnostic(
868
+ "warning",
869
+ "FORGE_UI_WORKOS_AUTHKIT_MISSING",
870
+ "WorkOS integration is present, but the web app does not appear to mount AuthKitProvider and pass getAccessToken into ForgeProvider.",
871
+ ));
872
+ }
873
+
874
+ return {
875
+ ok: diagnostics.every((item) => item.severity !== "error"),
876
+ manifest,
877
+ scenarios,
878
+ diagnostics,
879
+ exitCode: diagnostics.some((item) => item.severity === "error") ? 1 : 0,
880
+ };
881
+ }
882
+
674
883
  function runUiDoctor(options: UiCommandOptions): UiCommandResult {
675
884
  const manifest = loadUiManifest(options.workspaceRoot);
676
885
  const diagnostics: Diagnostic[] = [];
@@ -2,6 +2,7 @@ import type { Diagnostic } from "../compiler/types/diagnostic.ts";
2
2
  import type { TestCost } from "../compiler/types/test-graph.ts";
3
3
 
4
4
  export type UiSubcommand =
5
+ | "audit"
5
6
  | "smoke"
6
7
  | "test"
7
8
  | "scenario"
@@ -1,3 +1,3 @@
1
- export const FORGEOS_VERSION = "0.1.0-alpha.4";
1
+ export const FORGEOS_VERSION = "0.1.0-alpha.41";
2
2
  export const GENERATOR_VERSION = FORGEOS_VERSION;
3
3
  export const CLI_VERSION = FORGEOS_VERSION;