forgeos 0.1.0-alpha.7 → 0.1.0-alpha.70

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 (582) hide show
  1. package/.agents/skills/forge-agent-fabric/SKILL.md +169 -0
  2. package/.agents/skills/forge-agent-fabric/references/managed-workflows.md +95 -0
  3. package/.agents/skills/forge-agent-fabric/references/repository-analysis.md +102 -0
  4. package/.agents/skills/forge-agent-fabric/scripts/fabric.mjs +46 -0
  5. package/.agents/skills/forge-agent-fabric/scripts/repository.mjs +44 -0
  6. package/.npmignore +10 -0
  7. package/AGENTS.md +142 -90
  8. package/CHANGELOG.md +864 -9
  9. package/LICENSE +21 -0
  10. package/README.md +121 -6
  11. package/adapters/go/README.md +23 -0
  12. package/adapters/go/go.mod +3 -0
  13. package/adapters/go/http.go +149 -0
  14. package/adapters/go/registry.go +234 -0
  15. package/adapters/go/types.go +136 -0
  16. package/adapters/java/README.md +68 -0
  17. package/adapters/java/pom.xml +47 -0
  18. package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
  19. package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
  20. package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
  21. package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
  22. package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
  23. package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
  24. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
  25. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
  26. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
  27. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
  28. package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
  29. package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
  30. package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
  31. package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
  32. package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
  33. package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
  34. package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
  35. package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
  36. package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
  37. package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
  38. package/adapters/java-spring-boot-starter/README.md +32 -0
  39. package/adapters/java-spring-boot-starter/pom.xml +49 -0
  40. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
  41. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
  42. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
  43. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
  44. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
  45. package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
  46. package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
  47. package/bin/forge.mjs +18 -0
  48. package/docs/agent-fabric-programs.md +168 -0
  49. package/docs/agent-fabric.md +584 -0
  50. package/docs/architecture/agent-fabric/PORTABLE_PROJECTS_PLAN.md +136 -0
  51. package/docs/architecture/agent-fabric/README.md +180 -0
  52. package/docs/architecture/agent-fabric/REPOSITORY_MANIFEST_PLAN.md +284 -0
  53. package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_ADR.md +41 -0
  54. package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_EVIDENCE.md +109 -0
  55. package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_PLAN.md +550 -0
  56. package/docs/cair-protocol.md +103 -0
  57. package/docs/changelog.md +1070 -0
  58. package/docs/forge-protocol.md +189 -0
  59. package/docs/repository-agent-benchmark.md +179 -0
  60. package/docs/repository-analysis.md +139 -0
  61. package/docs/repository-context-quality.md +179 -0
  62. package/docs/repository-runtime-observation.md +82 -0
  63. package/examples/agent-fabric-v2/README.md +54 -0
  64. package/examples/agent-fabric-v2/make-request.mjs +4 -0
  65. package/examples/agent-fabric-v2/migrate.workflow.ts +35 -0
  66. package/examples/agent-fabric-v2/registry.example.json +256 -0
  67. package/examples/agent-fabric-v2/workers/check.mjs +2 -0
  68. package/examples/agent-fabric-v2/workers/common.mjs +7 -0
  69. package/examples/agent-fabric-v2/workers/discover.mjs +2 -0
  70. package/examples/agent-fabric-v2/workers/migrate.mjs +4 -0
  71. package/examples/agent-fabric-v2/workers/review.mjs +3 -0
  72. package/examples/go-billing/go.mod +7 -0
  73. package/examples/go-billing/main.go +120 -0
  74. package/examples/java-billing/pom.xml +60 -0
  75. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
  76. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
  77. package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
  78. package/package.json +58 -5
  79. package/schemas/agent-fabric/v0.1/control-event.schema.json +281 -0
  80. package/schemas/forge-manifest.schema.json +389 -0
  81. package/scripts/field-test-forgeos.mjs +1021 -0
  82. package/scripts/install-agent-fabric-skill.mjs +105 -0
  83. package/src/forge/_generated/releaseManifest.json +1 -2
  84. package/src/forge/_generated/releaseManifest.ts +3 -3
  85. package/src/forge/agent-adapters/index.ts +1592 -125
  86. package/src/forge/agent-adapters/types.ts +225 -1
  87. package/src/forge/agent-fabric/adapter.ts +131 -0
  88. package/src/forge/agent-fabric/attached-snapshot.ts +55 -0
  89. package/src/forge/agent-fabric/attached-task-contract.ts +105 -0
  90. package/src/forge/agent-fabric/attached-task-service.ts +127 -0
  91. package/src/forge/agent-fabric/attached-task-store.ts +109 -0
  92. package/src/forge/agent-fabric/authority.ts +298 -0
  93. package/src/forge/agent-fabric/canonical.ts +135 -0
  94. package/src/forge/agent-fabric/codex-adversarial-review.ts +229 -0
  95. package/src/forge/agent-fabric/codex-sdk-worker.ts +201 -0
  96. package/src/forge/agent-fabric/conductor.ts +754 -0
  97. package/src/forge/agent-fabric/dictionary.ts +12 -0
  98. package/src/forge/agent-fabric/errors.ts +32 -0
  99. package/src/forge/agent-fabric/hardened-conductor.ts +485 -0
  100. package/src/forge/agent-fabric/hardened-reducer.ts +211 -0
  101. package/src/forge/agent-fabric/index.ts +48 -0
  102. package/src/forge/agent-fabric/journal.ts +116 -0
  103. package/src/forge/agent-fabric/local-adaptive-digest-worker.mjs +26 -0
  104. package/src/forge/agent-fabric/local-adaptive-harness.ts +343 -0
  105. package/src/forge/agent-fabric/local-adaptive-service.ts +398 -0
  106. package/src/forge/agent-fabric/local-adaptive-worker.ts +146 -0
  107. package/src/forge/agent-fabric/local-approval-window.ts +211 -0
  108. package/src/forge/agent-fabric/local-change-review-service.ts +374 -0
  109. package/src/forge/agent-fabric/local-coding-worker.ts +285 -0
  110. package/src/forge/agent-fabric/local-control-store.ts +239 -0
  111. package/src/forge/agent-fabric/local-effect-broker.ts +348 -0
  112. package/src/forge/agent-fabric/local-evolution-approval.ts +81 -0
  113. package/src/forge/agent-fabric/local-evolution-profile.ts +87 -0
  114. package/src/forge/agent-fabric/local-evolution-registry.ts +427 -0
  115. package/src/forge/agent-fabric/local-evolution-service.ts +200 -0
  116. package/src/forge/agent-fabric/local-intelligence.ts +281 -0
  117. package/src/forge/agent-fabric/local-paths.ts +18 -0
  118. package/src/forge/agent-fabric/local-task-contract.ts +203 -0
  119. package/src/forge/agent-fabric/local-task-inbox.ts +543 -0
  120. package/src/forge/agent-fabric/local-task-server.ts +374 -0
  121. package/src/forge/agent-fabric/local-task-service.ts +982 -0
  122. package/src/forge/agent-fabric/local-verification.ts +551 -0
  123. package/src/forge/agent-fabric/managed-environment.ts +205 -0
  124. package/src/forge/agent-fabric/managed-run-contract.ts +103 -0
  125. package/src/forge/agent-fabric/managed-run-service.ts +401 -0
  126. package/src/forge/agent-fabric/managed-run-store.ts +165 -0
  127. package/src/forge/agent-fabric/managed-workspace.ts +253 -0
  128. package/src/forge/agent-fabric/p0a.ts +104 -0
  129. package/src/forge/agent-fabric/p0b-model-adapter.ts +434 -0
  130. package/src/forge/agent-fabric/planning.ts +155 -0
  131. package/src/forge/agent-fabric/program-contract.ts +229 -0
  132. package/src/forge/agent-fabric/program-dsl.ts +112 -0
  133. package/src/forge/agent-fabric/program-service.ts +619 -0
  134. package/src/forge/agent-fabric/program-store.ts +117 -0
  135. package/src/forge/agent-fabric/program-types.ts +98 -0
  136. package/src/forge/agent-fabric/program-worker.ts +91 -0
  137. package/src/forge/agent-fabric/project-profile.ts +50 -0
  138. package/src/forge/agent-fabric/project-registry.ts +120 -0
  139. package/src/forge/agent-fabric/project-runtime.ts +85 -0
  140. package/src/forge/agent-fabric/readiness.ts +26 -0
  141. package/src/forge/agent-fabric/reducer.ts +863 -0
  142. package/src/forge/agent-fabric/repository-context.ts +83 -0
  143. package/src/forge/agent-fabric/resource-ledger.ts +266 -0
  144. package/src/forge/agent-fabric/serialized-local-adapter.ts +60 -0
  145. package/src/forge/agent-fabric/types.ts +424 -0
  146. package/src/forge/agent-fabric/validation.ts +500 -0
  147. package/src/forge/agent-fabric/workflow-engine.ts +218 -0
  148. package/src/forge/agent-fabric/workflow-task-actions.ts +104 -0
  149. package/src/forge/agent-fabric/workflow-templates.ts +11 -0
  150. package/src/forge/agent-memory/bridge.ts +1728 -0
  151. package/src/forge/agent-memory/context-pack.ts +284 -0
  152. package/src/forge/agent-memory/hook-runner.ts +331 -0
  153. package/src/forge/agent-memory/mcp.ts +597 -0
  154. package/src/forge/agent-memory/normalize.ts +498 -0
  155. package/src/forge/agent-memory/redaction.ts +103 -0
  156. package/src/forge/agent-memory/sources/claude-code.ts +51 -0
  157. package/src/forge/agent-memory/sources/codex-hook-runner.mjs +343 -0
  158. package/src/forge/agent-memory/sources/codex.ts +161 -0
  159. package/src/forge/agent-memory/sources/cursor.ts +35 -0
  160. package/src/forge/agent-memory/types.ts +215 -0
  161. package/src/forge/bench.ts +248 -0
  162. package/src/forge/brownfield-import/index.ts +896 -0
  163. package/src/forge/brownfield-import/types.ts +127 -0
  164. package/src/forge/cair/action-journal.ts +61 -0
  165. package/src/forge/cair/action-parser.ts +314 -0
  166. package/src/forge/cair/action-validator.ts +40 -0
  167. package/src/forge/cair/actions.ts +1818 -0
  168. package/src/forge/cair/format.ts +77 -0
  169. package/src/forge/cair/index.ts +118 -0
  170. package/src/forge/cair/query.ts +478 -0
  171. package/src/forge/cair/snapshot.ts +315 -0
  172. package/src/forge/cair/types.ts +255 -0
  173. package/src/forge/cli/adaptive.ts +51 -0
  174. package/src/forge/cli/ai.ts +16 -1
  175. package/src/forge/cli/auth.ts +459 -15
  176. package/src/forge/cli/authmd.ts +441 -0
  177. package/src/forge/cli/baseline.ts +112 -0
  178. package/src/forge/cli/build.ts +20 -4
  179. package/src/forge/cli/changed.ts +418 -0
  180. package/src/forge/cli/codex-app-server.ts +877 -0
  181. package/src/forge/cli/commands.ts +1859 -20
  182. package/src/forge/cli/db.ts +209 -2
  183. package/src/forge/cli/deploy.ts +1339 -0
  184. package/src/forge/cli/deps.ts +150 -23
  185. package/src/forge/cli/dev.ts +1137 -53
  186. package/src/forge/cli/docs.ts +265 -0
  187. package/src/forge/cli/doctor.ts +297 -0
  188. package/src/forge/cli/env-placeholders.ts +62 -0
  189. package/src/forge/cli/evolution.ts +40 -0
  190. package/src/forge/cli/fabric.ts +253 -0
  191. package/src/forge/cli/field-test.ts +568 -0
  192. package/src/forge/cli/golden-path.ts +487 -0
  193. package/src/forge/cli/handoff.ts +336 -0
  194. package/src/forge/cli/index.ts +1 -0
  195. package/src/forge/cli/last-run.ts +84 -0
  196. package/src/forge/cli/main.ts +194 -3
  197. package/src/forge/cli/new.ts +169 -17
  198. package/src/forge/cli/next-actions.ts +23 -0
  199. package/src/forge/cli/output.ts +398 -6
  200. package/src/forge/cli/parse.ts +1377 -38
  201. package/src/forge/cli/progress.ts +51 -0
  202. package/src/forge/cli/query.ts +32 -0
  203. package/src/forge/cli/release.ts +35 -11
  204. package/src/forge/cli/repository.ts +151 -0
  205. package/src/forge/cli/run.ts +42 -0
  206. package/src/forge/cli/secrets.ts +137 -1
  207. package/src/forge/cli/seed.ts +581 -0
  208. package/src/forge/cli/self-host.ts +56 -14
  209. package/src/forge/cli/studio.ts +2282 -0
  210. package/src/forge/cli/verify.ts +1458 -32
  211. package/src/forge/cli/windows.ts +23 -0
  212. package/src/forge/cli/workos.ts +3509 -0
  213. package/src/forge/compiler/agent-contract/build.ts +728 -64
  214. package/src/forge/compiler/agent-contract/types.ts +45 -2
  215. package/src/forge/compiler/ai-registry/parse.ts +71 -2
  216. package/src/forge/compiler/api-surface/build.ts +47 -0
  217. package/src/forge/compiler/app-graph/build.ts +112 -9
  218. package/src/forge/compiler/app-graph/extract.ts +107 -0
  219. package/src/forge/compiler/app-graph/module-graph.ts +73 -78
  220. package/src/forge/compiler/app-graph/parser.ts +24 -24
  221. package/src/forge/compiler/app-graph/profile.ts +26 -0
  222. package/src/forge/compiler/app-graph/tsconfig-hash.ts +41 -4
  223. package/src/forge/compiler/app-graph/versions.ts +1 -1
  224. package/src/forge/compiler/classifier/capabilities.ts +3 -2
  225. package/src/forge/compiler/classifier/classify.ts +32 -8
  226. package/src/forge/compiler/classifier/secrets.ts +3 -2
  227. package/src/forge/compiler/classifier/signals.ts +91 -1
  228. package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
  229. package/src/forge/compiler/client-sdk/render-client.ts +295 -13
  230. package/src/forge/compiler/data-graph/build.ts +29 -1
  231. package/src/forge/compiler/data-graph/parse.ts +20 -4
  232. package/src/forge/compiler/data-graph/sql/ddl.ts +144 -31
  233. package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
  234. package/src/forge/compiler/data-graph/sql/types.ts +1 -0
  235. package/src/forge/compiler/diagnostics/codes.ts +38 -0
  236. package/src/forge/compiler/diagnostics/create.ts +28 -2
  237. package/src/forge/compiler/diagnostics/index.ts +2 -0
  238. package/src/forge/compiler/emitter/barrel.ts +3 -0
  239. package/src/forge/compiler/emitter/render.ts +9 -0
  240. package/src/forge/compiler/external-manifest/registry.ts +217 -0
  241. package/src/forge/compiler/external-manifest/types.ts +91 -0
  242. package/src/forge/compiler/external-manifest/validate.ts +373 -0
  243. package/src/forge/compiler/frontend-graph/build.ts +142 -14
  244. package/src/forge/compiler/integration/add.ts +991 -33
  245. package/src/forge/compiler/integration/plan.ts +43 -12
  246. package/src/forge/compiler/integration/render.ts +29 -0
  247. package/src/forge/compiler/integration/snapshot.ts +2 -0
  248. package/src/forge/compiler/integration/templates/convex.ts +70 -0
  249. package/src/forge/compiler/integration/templates/index.ts +1 -0
  250. package/src/forge/compiler/integration/templates/render.ts +38 -0
  251. package/src/forge/compiler/integration/templates/types.ts +3 -0
  252. package/src/forge/compiler/integration/templates/workos.ts +1439 -0
  253. package/src/forge/compiler/make-registry/build.ts +8 -9
  254. package/src/forge/compiler/orchestrator/fast-check.ts +4 -0
  255. package/src/forge/compiler/orchestrator/generate-lock.ts +14 -3
  256. package/src/forge/compiler/orchestrator/manifest.ts +1 -1
  257. package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
  258. package/src/forge/compiler/orchestrator/plan.ts +249 -10
  259. package/src/forge/compiler/orchestrator/profile.ts +65 -0
  260. package/src/forge/compiler/orchestrator/run.ts +101 -33
  261. package/src/forge/compiler/orchestrator/serialize.ts +33 -8
  262. package/src/forge/compiler/orchestrator/types.ts +1 -1
  263. package/src/forge/compiler/package-graph/compiler.ts +3 -1
  264. package/src/forge/compiler/package-graph/constants.ts +1 -1
  265. package/src/forge/compiler/package-graph/dts-extractor.ts +14 -1
  266. package/src/forge/compiler/package-manager/adapter.ts +4 -1
  267. package/src/forge/compiler/package-manager/commands.ts +4 -0
  268. package/src/forge/compiler/package-manager/executor.ts +30 -1
  269. package/src/forge/compiler/package-manager/version.ts +36 -12
  270. package/src/forge/compiler/package-upgrades/planner.ts +155 -18
  271. package/src/forge/compiler/package-upgrades/types.ts +2 -0
  272. package/src/forge/compiler/policy-registry/build.ts +47 -2
  273. package/src/forge/compiler/policy-registry/parse.ts +32 -2
  274. package/src/forge/compiler/recipes/definitions.ts +63 -0
  275. package/src/forge/compiler/recipes/index.ts +2 -0
  276. package/src/forge/compiler/recipes/profiles.ts +81 -0
  277. package/src/forge/compiler/recipes/registry.ts +6 -0
  278. package/src/forge/compiler/test-graph/build.ts +11 -3
  279. package/src/forge/compiler/types/app-graph.ts +8 -2
  280. package/src/forge/compiler/types/cli.ts +76 -1
  281. package/src/forge/compiler/types/dev-manifest.ts +4 -0
  282. package/src/forge/compiler/types/emit.ts +2 -0
  283. package/src/forge/compiler/types/frontend-graph.ts +2 -2
  284. package/src/forge/compiler/types/integration.ts +1 -0
  285. package/src/forge/compiler/types/package-graph.ts +6 -0
  286. package/src/forge/compiler/types/policy-registry.ts +3 -1
  287. package/src/forge/delta/broker-runner.mjs +5 -0
  288. package/src/forge/delta/broker.ts +429 -0
  289. package/src/forge/delta/classifier.ts +52 -0
  290. package/src/forge/delta/explain.ts +238 -0
  291. package/src/forge/delta/git-observer.ts +67 -0
  292. package/src/forge/delta/ids.ts +44 -0
  293. package/src/forge/delta/index.ts +25 -0
  294. package/src/forge/delta/process-identity.ts +37 -0
  295. package/src/forge/delta/queue-status.ts +190 -0
  296. package/src/forge/delta/recorder.ts +540 -0
  297. package/src/forge/delta/redaction.ts +50 -0
  298. package/src/forge/delta/schema.ts +240 -0
  299. package/src/forge/delta/session.ts +142 -0
  300. package/src/forge/delta/status.ts +1139 -0
  301. package/src/forge/delta/store.ts +3329 -0
  302. package/src/forge/delta/timeline.ts +178 -0
  303. package/src/forge/dev/server.ts +1061 -22
  304. package/src/forge/dev/types.ts +15 -1
  305. package/src/forge/dev/watch.ts +17 -7
  306. package/src/forge/dev-console/cycle.ts +285 -33
  307. package/src/forge/dev-console/types.ts +47 -1
  308. package/src/forge/impact/index.ts +222 -30
  309. package/src/forge/impact/types.ts +33 -1
  310. package/src/forge/intent/index.ts +35 -16
  311. package/src/forge/make/fields.ts +26 -0
  312. package/src/forge/make/index.ts +42 -6
  313. package/src/forge/make/templates.ts +211 -4
  314. package/src/forge/make/types.ts +2 -1
  315. package/src/forge/policy.ts +1 -1
  316. package/src/forge/react/index.ts +160 -2
  317. package/src/forge/refactor/index.ts +1 -0
  318. package/src/forge/repair/rules/index.ts +2 -2
  319. package/src/forge/repository-analysis/adapters/common.ts +72 -0
  320. package/src/forge/repository-analysis/adapters/docker.ts +185 -0
  321. package/src/forge/repository-analysis/adapters/java.ts +133 -0
  322. package/src/forge/repository-analysis/adapters/typescript.ts +350 -0
  323. package/src/forge/repository-analysis/adapters/vue.ts +71 -0
  324. package/src/forge/repository-analysis/analyze.ts +434 -0
  325. package/src/forge/repository-analysis/benchmark.ts +336 -0
  326. package/src/forge/repository-analysis/cache-gc.ts +154 -0
  327. package/src/forge/repository-analysis/check-selection.ts +123 -0
  328. package/src/forge/repository-analysis/context-node.ts +17 -0
  329. package/src/forge/repository-analysis/context.ts +456 -0
  330. package/src/forge/repository-analysis/http-resolution.ts +135 -0
  331. package/src/forge/repository-analysis/identity.ts +45 -0
  332. package/src/forge/repository-analysis/index.ts +18 -0
  333. package/src/forge/repository-analysis/nuxt-resolution.ts +188 -0
  334. package/src/forge/repository-analysis/quality.ts +60 -0
  335. package/src/forge/repository-analysis/retrieval.ts +309 -0
  336. package/src/forge/repository-analysis/runtime-artifacts.ts +195 -0
  337. package/src/forge/repository-analysis/runtime-observation.ts +325 -0
  338. package/src/forge/repository-analysis/scanner.ts +174 -0
  339. package/src/forge/repository-analysis/storage.ts +193 -0
  340. package/src/forge/repository-analysis/test-associations.ts +59 -0
  341. package/src/forge/repository-analysis/types.ts +99 -0
  342. package/src/forge/repository-manifest/index.ts +178 -0
  343. package/src/forge/repository-manifest/types.ts +63 -0
  344. package/src/forge/review/index.ts +162 -12
  345. package/src/forge/review/types.ts +15 -0
  346. package/src/forge/runtime/ai/providers.ts +19 -4
  347. package/src/forge/runtime/auth/config.ts +17 -0
  348. package/src/forge/runtime/auth/evaluate.ts +15 -2
  349. package/src/forge/runtime/auth/resolve.ts +61 -6
  350. package/src/forge/runtime/auth/types.ts +1 -0
  351. package/src/forge/runtime/db/factory.ts +1 -3
  352. package/src/forge/runtime/db/generated-client.ts +13 -2
  353. package/src/forge/runtime/db/memory-adapter.ts +139 -32
  354. package/src/forge/runtime/db/pglite-adapter.ts +285 -2
  355. package/src/forge/runtime/executor.ts +129 -16
  356. package/src/forge/runtime/external/bridge.ts +663 -0
  357. package/src/forge/runtime/runner/run-entry.ts +16 -7
  358. package/src/forge/runtime/telemetry/buffer.ts +4 -1
  359. package/src/forge/runtime/telemetry/scrubber.ts +35 -5
  360. package/src/forge/runtime/webhooks/security.ts +12 -7
  361. package/src/forge/server.ts +71 -7
  362. package/src/forge/ui/index.ts +831 -19
  363. package/src/forge/ui/types.ts +3 -1
  364. package/src/forge/version.ts +1 -1
  365. package/src/forge/vue/index.ts +422 -0
  366. package/src/forge/workspace/baseline.ts +112 -0
  367. package/src/forge/workspace/change-summary.ts +292 -0
  368. package/src/forge/workspace/forge-cli.ts +42 -0
  369. package/src/forge/workspace/git-summary.ts +393 -0
  370. package/templates/agent-workroom/AGENTS.md +29 -0
  371. package/templates/agent-workroom/README.md +34 -0
  372. package/templates/agent-workroom/forge.config.ts +3 -0
  373. package/templates/agent-workroom/package.json +34 -0
  374. package/templates/agent-workroom/pnpm-workspace.yaml +2 -0
  375. package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
  376. package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
  377. package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
  378. package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
  379. package/templates/agent-workroom/src/forge/schema.ts +54 -0
  380. package/templates/agent-workroom/src/policies.ts +6 -0
  381. package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
  382. package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
  383. package/templates/agent-workroom/tsconfig.json +16 -0
  384. package/templates/agent-workroom/web/index.html +13 -0
  385. package/templates/agent-workroom/web/package.json +21 -0
  386. package/templates/agent-workroom/web/src/App.tsx +345 -0
  387. package/templates/agent-workroom/web/src/lib/forge.ts +20 -0
  388. package/templates/agent-workroom/web/src/main.tsx +13 -0
  389. package/templates/agent-workroom/web/src/styles.css +545 -0
  390. package/templates/agent-workroom/web/tsconfig.json +27 -0
  391. package/templates/agent-workroom/web/vite.config.ts +36 -0
  392. package/templates/b2b-support-web/package.json +2 -0
  393. package/templates/b2b-support-web/pnpm-workspace.yaml +2 -0
  394. package/templates/b2b-support-web/web/app/page.tsx +2 -2
  395. package/templates/b2b-support-web/web/lib/forge.ts +9 -2
  396. package/templates/b2b-support-web/web/next.config.ts +24 -0
  397. package/templates/b2b-support-web/web/package.json +1 -1
  398. package/templates/minimal-web/package.json +2 -1
  399. package/templates/minimal-web/pnpm-workspace.yaml +2 -0
  400. package/templates/minimal-web/web/index.html +1 -0
  401. package/templates/minimal-web/web/src/App.tsx +12 -6
  402. package/templates/minimal-web/web/src/lib/forge.ts +9 -2
  403. package/templates/minimal-web/web/src/styles.css +34 -0
  404. package/templates/minimal-web/web/vite.config.ts +36 -0
  405. package/templates/nuxt-web/.vscode/settings.json +14 -0
  406. package/templates/nuxt-web/.yarnrc.yml +1 -0
  407. package/templates/nuxt-web/README.md +30 -0
  408. package/templates/nuxt-web/forge.config.ts +3 -0
  409. package/templates/nuxt-web/package.json +37 -0
  410. package/templates/nuxt-web/pnpm-workspace.yaml +2 -0
  411. package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -0
  412. package/templates/nuxt-web/src/commands/createNote.ts +26 -0
  413. package/templates/nuxt-web/src/forge/schema.ts +12 -0
  414. package/templates/nuxt-web/src/policies.ts +6 -0
  415. package/templates/nuxt-web/src/queries/listNotes.ts +8 -0
  416. package/templates/nuxt-web/src/queries/liveNotes.ts +8 -0
  417. package/templates/nuxt-web/tsconfig.json +17 -0
  418. package/templates/nuxt-web/web/app.vue +67 -0
  419. package/templates/nuxt-web/web/components/LiveNotes.vue +89 -0
  420. package/templates/nuxt-web/web/components/NoteComposer.vue +100 -0
  421. package/templates/nuxt-web/web/composables/forge.ts +13 -0
  422. package/templates/nuxt-web/web/composables/useNotes.ts +24 -0
  423. package/templates/nuxt-web/web/nuxt.config.ts +11 -0
  424. package/templates/nuxt-web/web/package.json +22 -0
  425. package/templates/nuxt-web/web/plugins/forge.client.ts +10 -0
  426. package/templates/nuxt-web/web/plugins/forge.server.ts +10 -0
  427. package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -0
  428. package/templates/nuxt-web/web/tsconfig.json +6 -0
  429. package/templates/vendor-access/.vscode/settings.json +14 -0
  430. package/templates/vendor-access/README.md +30 -0
  431. package/templates/vendor-access/forge.config.ts +3 -0
  432. package/templates/vendor-access/package.json +35 -0
  433. package/templates/vendor-access/pnpm-workspace.yaml +2 -0
  434. package/templates/vendor-access/src/commands/addEvidence.ts +42 -0
  435. package/templates/vendor-access/src/commands/approveAccessRequest.ts +43 -0
  436. package/templates/vendor-access/src/commands/createAccessRequest.ts +49 -0
  437. package/templates/vendor-access/src/commands/seedVendorAccessDemo.ts +200 -0
  438. package/templates/vendor-access/src/forge/schema.ts +74 -0
  439. package/templates/vendor-access/src/policies.ts +11 -0
  440. package/templates/vendor-access/src/queries/listVendorAccessDashboard.ts +24 -0
  441. package/templates/vendor-access/src/queries/liveVendorAccessDashboard.ts +24 -0
  442. package/templates/vendor-access/tsconfig.json +17 -0
  443. package/templates/vendor-access/web/index.html +13 -0
  444. package/templates/vendor-access/web/package.json +21 -0
  445. package/templates/vendor-access/web/src/App.tsx +573 -0
  446. package/templates/vendor-access/web/src/lib/forge.ts +20 -0
  447. package/templates/vendor-access/web/src/main.tsx +205 -0
  448. package/templates/vendor-access/web/src/styles.css +682 -0
  449. package/templates/vendor-access/web/tsconfig.json +18 -0
  450. package/templates/vendor-access/web/vite.config.ts +36 -0
  451. package/src/forge/_generated/actionSubscriptions.json +0 -2
  452. package/src/forge/_generated/actionSubscriptions.ts +0 -10
  453. package/src/forge/_generated/agentAdapterManifest.json +0 -2
  454. package/src/forge/_generated/agentAdapterManifest.ts +0 -73
  455. package/src/forge/_generated/agentContract.json +0 -2
  456. package/src/forge/_generated/agentContract.ts +0 -7829
  457. package/src/forge/_generated/agentQuickstart.md +0 -34
  458. package/src/forge/_generated/agentTools.json +0 -2
  459. package/src/forge/_generated/agentTools.md +0 -16
  460. package/src/forge/_generated/agentTools.ts +0 -12
  461. package/src/forge/_generated/aiContext.ts +0 -125
  462. package/src/forge/_generated/aiModels.json +0 -2
  463. package/src/forge/_generated/aiModels.ts +0 -51
  464. package/src/forge/_generated/aiProviders.json +0 -2
  465. package/src/forge/_generated/aiProviders.ts +0 -23
  466. package/src/forge/_generated/aiRegistry.json +0 -2
  467. package/src/forge/_generated/aiRegistry.ts +0 -31
  468. package/src/forge/_generated/api.json +0 -2
  469. package/src/forge/_generated/api.ts +0 -8
  470. package/src/forge/_generated/appGraph.json +0 -2
  471. package/src/forge/_generated/appGraph.ts +0 -14937
  472. package/src/forge/_generated/appMap.md +0 -55
  473. package/src/forge/_generated/artifactManifest.json +0 -2
  474. package/src/forge/_generated/artifactManifest.ts +0 -7
  475. package/src/forge/_generated/authClaims.json +0 -2
  476. package/src/forge/_generated/authClaims.ts +0 -13
  477. package/src/forge/_generated/authConfig.json +0 -2
  478. package/src/forge/_generated/authConfig.ts +0 -17
  479. package/src/forge/_generated/authContext.ts +0 -23
  480. package/src/forge/_generated/authRegistry.json +0 -2
  481. package/src/forge/_generated/authRegistry.ts +0 -25
  482. package/src/forge/_generated/buildInfo.json +0 -2
  483. package/src/forge/_generated/buildInfo.ts +0 -9
  484. package/src/forge/_generated/capabilityMap.json +0 -2
  485. package/src/forge/_generated/capabilityMap.md +0 -15
  486. package/src/forge/_generated/capabilityMap.ts +0 -17
  487. package/src/forge/_generated/client.ts +0 -282
  488. package/src/forge/_generated/clientApi.ts +0 -9
  489. package/src/forge/_generated/clientManifest.json +0 -2
  490. package/src/forge/_generated/clientManifest.ts +0 -39
  491. package/src/forge/_generated/clientTypes.ts +0 -78
  492. package/src/forge/_generated/configRegistry.json +0 -2
  493. package/src/forge/_generated/configRegistry.ts +0 -4
  494. package/src/forge/_generated/dataGraph.json +0 -2
  495. package/src/forge/_generated/dataGraph.ts +0 -8
  496. package/src/forge/_generated/db.json +0 -2
  497. package/src/forge/_generated/db.ts +0 -2
  498. package/src/forge/_generated/dbSecurityManifest.json +0 -2
  499. package/src/forge/_generated/dbSecurityManifest.ts +0 -15
  500. package/src/forge/_generated/dbSessionContext.json +0 -2
  501. package/src/forge/_generated/dbSessionContext.ts +0 -39
  502. package/src/forge/_generated/deployManifest.json +0 -2
  503. package/src/forge/_generated/deployManifest.ts +0 -14
  504. package/src/forge/_generated/devManifest.json +0 -2
  505. package/src/forge/_generated/devManifest.ts +0 -62
  506. package/src/forge/_generated/envSchema.json +0 -2
  507. package/src/forge/_generated/envSchema.ts +0 -59
  508. package/src/forge/_generated/frontendGraph.json +0 -2
  509. package/src/forge/_generated/frontendGraph.ts +0 -27
  510. package/src/forge/_generated/importGuards.json +0 -2
  511. package/src/forge/_generated/importGuards.ts +0 -686
  512. package/src/forge/_generated/index.ts +0 -68
  513. package/src/forge/_generated/liveProductionManifest.json +0 -2
  514. package/src/forge/_generated/liveProductionManifest.ts +0 -23
  515. package/src/forge/_generated/liveProtocol.json +0 -2
  516. package/src/forge/_generated/liveProtocol.ts +0 -21
  517. package/src/forge/_generated/liveQueryRegistry.json +0 -2
  518. package/src/forge/_generated/liveQueryRegistry.ts +0 -9
  519. package/src/forge/_generated/liveTransportConfig.json +0 -2
  520. package/src/forge/_generated/liveTransportConfig.ts +0 -19
  521. package/src/forge/_generated/makeRegistry.json +0 -2
  522. package/src/forge/_generated/makeRegistry.ts +0 -177
  523. package/src/forge/_generated/makeTemplates.json +0 -2
  524. package/src/forge/_generated/makeTemplates.ts +0 -66
  525. package/src/forge/_generated/mockMap.json +0 -2
  526. package/src/forge/_generated/mockMap.ts +0 -7
  527. package/src/forge/_generated/operationPlaybooks.md +0 -167
  528. package/src/forge/_generated/packageGraph.json +0 -2
  529. package/src/forge/_generated/packageGraph.ts +0 -249334
  530. package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
  531. package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
  532. package/src/forge/_generated/permissionMatrix.json +0 -2
  533. package/src/forge/_generated/permissionMatrix.ts +0 -7
  534. package/src/forge/_generated/policyRegistry.json +0 -2
  535. package/src/forge/_generated/policyRegistry.ts +0 -11
  536. package/src/forge/_generated/queryRegistry.json +0 -2
  537. package/src/forge/_generated/queryRegistry.ts +0 -9
  538. package/src/forge/_generated/react.d.ts +0 -22
  539. package/src/forge/_generated/react.ts +0 -29
  540. package/src/forge/_generated/reactManifest.json +0 -2
  541. package/src/forge/_generated/reactManifest.ts +0 -19
  542. package/src/forge/_generated/rlsPolicies.json +0 -2
  543. package/src/forge/_generated/rlsPolicies.sql +0 -34
  544. package/src/forge/_generated/rlsPolicies.ts +0 -6
  545. package/src/forge/_generated/runtimeGraph.json +0 -2
  546. package/src/forge/_generated/runtimeGraph.ts +0 -8
  547. package/src/forge/_generated/runtimeMatrix.json +0 -2
  548. package/src/forge/_generated/runtimeMatrix.ts +0 -334130
  549. package/src/forge/_generated/runtimeRegistry.ts +0 -2
  550. package/src/forge/_generated/runtimeRules.md +0 -91
  551. package/src/forge/_generated/secretRegistry.json +0 -2
  552. package/src/forge/_generated/secretRegistry.ts +0 -50
  553. package/src/forge/_generated/secretsContext.ts +0 -11
  554. package/src/forge/_generated/serverApi.ts +0 -10
  555. package/src/forge/_generated/sourceMapManifest.json +0 -2
  556. package/src/forge/_generated/sourceMapManifest.ts +0 -7
  557. package/src/forge/_generated/sqlPlan.json +0 -2
  558. package/src/forge/_generated/sqlPlan.ts +0 -88
  559. package/src/forge/_generated/subscriptionManifest.json +0 -2
  560. package/src/forge/_generated/subscriptionManifest.ts +0 -7
  561. package/src/forge/_generated/symbolicationManifest.json +0 -2
  562. package/src/forge/_generated/symbolicationManifest.ts +0 -17
  563. package/src/forge/_generated/telemetryRegistry.json +0 -2
  564. package/src/forge/_generated/telemetryRegistry.ts +0 -9
  565. package/src/forge/_generated/telemetrySinks.json +0 -2
  566. package/src/forge/_generated/telemetrySinks.ts +0 -11
  567. package/src/forge/_generated/tenantScope.json +0 -2
  568. package/src/forge/_generated/tenantScope.ts +0 -8
  569. package/src/forge/_generated/testGraph.json +0 -2
  570. package/src/forge/_generated/testGraph.ts +0 -3452
  571. package/src/forge/_generated/testPlanRegistry.json +0 -2
  572. package/src/forge/_generated/testPlanRegistry.ts +0 -33
  573. package/src/forge/_generated/uiRoutes.json +0 -2
  574. package/src/forge/_generated/uiRoutes.ts +0 -16
  575. package/src/forge/_generated/uiScenarios.json +0 -2
  576. package/src/forge/_generated/uiScenarios.ts +0 -30
  577. package/src/forge/_generated/uiTestManifest.json +0 -2
  578. package/src/forge/_generated/uiTestManifest.ts +0 -27
  579. package/src/forge/_generated/workflowRegistry.json +0 -2
  580. package/src/forge/_generated/workflowRegistry.ts +0 -9
  581. package/src/forge/_generated/workflowSubscriptions.json +0 -2
  582. package/src/forge/_generated/workflowSubscriptions.ts +0 -10
@@ -0,0 +1,265 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { dirname, join, normalize } from "node:path";
3
+ import { nodeFileSystem } from "../compiler/fs/index.ts";
4
+ import { createDiagnostic } from "../compiler/diagnostics/create.ts";
5
+ import type { Diagnostic } from "../compiler/types/diagnostic.ts";
6
+ import { docsReadyNextActions } from "./next-actions.ts";
7
+
8
+ export type DocsSubcommand = "check";
9
+
10
+ export interface DocsCheckOptions {
11
+ workspaceRoot: string;
12
+ json: boolean;
13
+ build?: boolean;
14
+ installVenv?: boolean;
15
+ }
16
+
17
+ export interface DocsCheck {
18
+ name: string;
19
+ ok: boolean;
20
+ status: "pass" | "fail" | "warning";
21
+ details?: unknown;
22
+ }
23
+
24
+ export interface DocsCheckResult {
25
+ ok: boolean;
26
+ checks: DocsCheck[];
27
+ diagnostics: Diagnostic[];
28
+ nextActions: string[];
29
+ exitCode: 0 | 1;
30
+ }
31
+
32
+ const REQUIRED_DOCS = [
33
+ "index.md",
34
+ "getting-started.md",
35
+ "agent-workflow.md",
36
+ "cli-reference.md",
37
+ "troubleshooting.md",
38
+ "production-readiness.md",
39
+ "self-host.md",
40
+ "release.md",
41
+ ] as const;
42
+
43
+ const CONTENT_CHECKS: Array<{ file: string; contains: string[] }> = [
44
+ { file: ".readthedocs.yaml", contains: ["version: 2", "configuration: mkdocs.yml", "fail_on_warning: true", "requirements: docs/requirements.txt"] },
45
+ { file: "mkdocs.yml", contains: ["name: material", "markdown_extensions:", "extra_css:", "javascripts/mermaid-init.js"] },
46
+ { file: "docs/getting-started.md", contains: ["npm create forgeos-app@alpha", "Open the web URL"] },
47
+ { file: "docs/agent-workflow.md", contains: ["forge do", "forge status --json", "forge handoff --json"] },
48
+ { file: "docs/troubleshooting.md", contains: ["FORGE_DELTA_BUSY", "waiting-for-user-trust", "Studio target preview issues"] },
49
+ { file: "docs/release.md", contains: ["release:verify-public-alpha", "Documentation checklist"] },
50
+ { file: "docs/self-host.md", contains: ["forge deploy check --production --json"] },
51
+ ];
52
+
53
+ function read(workspaceRoot: string, relative: string): string | null {
54
+ const path = join(workspaceRoot, relative);
55
+ if (!nodeFileSystem.exists(path)) {
56
+ return null;
57
+ }
58
+ return nodeFileSystem.readText(path) ?? "";
59
+ }
60
+
61
+ function checkFileExists(workspaceRoot: string, relative: string): DocsCheck {
62
+ return nodeFileSystem.exists(join(workspaceRoot, relative))
63
+ ? { name: relative, ok: true, status: "pass" }
64
+ : { name: relative, ok: false, status: "fail", details: { missing: true } };
65
+ }
66
+
67
+ function checkContains(workspaceRoot: string, file: string, contains: string[]): DocsCheck {
68
+ const content = read(workspaceRoot, file);
69
+ if (content === null) {
70
+ return { name: `${file}:content`, ok: false, status: "fail", details: { missing: true } };
71
+ }
72
+ const missing = contains.filter((needle) => !content.includes(needle));
73
+ return missing.length === 0
74
+ ? { name: `${file}:content`, ok: true, status: "pass" }
75
+ : { name: `${file}:content`, ok: false, status: "fail", details: { missing } };
76
+ }
77
+
78
+ function slugifyHeading(heading: string): string {
79
+ return heading
80
+ .trim()
81
+ .toLowerCase()
82
+ .replace(/[`*_]/g, "")
83
+ .replace(/[^a-z0-9\s-]/g, "")
84
+ .replace(/\s+/g, "-");
85
+ }
86
+
87
+ function anchorsFor(content: string): Set<string> {
88
+ const anchors = new Set<string>();
89
+ for (const line of content.split(/\r?\n/)) {
90
+ const match = /^(#{1,6})\s+(.+)$/.exec(line);
91
+ if (match) {
92
+ anchors.add(slugifyHeading(match[2] ?? ""));
93
+ }
94
+ }
95
+ return anchors;
96
+ }
97
+
98
+ function checkYamlShape(workspaceRoot: string, relative: string, requiredKeys: string[]): DocsCheck {
99
+ const content = read(workspaceRoot, relative);
100
+ if (content === null) {
101
+ return { name: `${relative}:yaml`, ok: false, status: "fail", details: { missing: true } };
102
+ }
103
+ const malformed = content
104
+ .split(/\r?\n/)
105
+ .filter((line) => line.trim() && !line.trimStart().startsWith("#"))
106
+ .filter((line) => !/^\s*-\s+/.test(line))
107
+ .filter((line) => !line.includes(":"));
108
+ const missingKeys = requiredKeys.filter((key) => !new RegExp(`^${key}:`, "m").test(content));
109
+ const ok = malformed.length === 0 && missingKeys.length === 0;
110
+ return ok
111
+ ? { name: `${relative}:yaml`, ok: true, status: "pass" }
112
+ : { name: `${relative}:yaml`, ok: false, status: "fail", details: { malformed, missingKeys } };
113
+ }
114
+
115
+ function checkInternalLinks(workspaceRoot: string): DocsCheck {
116
+ const missing: Array<{ file: string; target: string }> = [];
117
+ const docs = nodeFileSystem.exists(join(workspaceRoot, "docs"))
118
+ ? nodeFileSystem.readDir(join(workspaceRoot, "docs"))
119
+ .filter((entry) => entry.name.endsWith(".md"))
120
+ .map((entry) => `docs/${entry.name}`)
121
+ : [];
122
+ for (const file of docs) {
123
+ const content = read(workspaceRoot, file) ?? "";
124
+ const links = [...content.matchAll(/\[[^\]]+\]\(([^)]+)\)/g)]
125
+ .map((match) => match[1] ?? "")
126
+ .filter((target) =>
127
+ target &&
128
+ !target.startsWith("http://") &&
129
+ !target.startsWith("https://") &&
130
+ !target.startsWith("mailto:") &&
131
+ !target.startsWith("#") &&
132
+ !target.startsWith("`")
133
+ );
134
+ for (const target of links) {
135
+ const [pathPart, anchor] = target.split("#");
136
+ const resolved = normalize(join(dirname(file), decodeURIComponent(pathPart ?? ""))).replace(/\\/g, "/");
137
+ if (!nodeFileSystem.exists(join(workspaceRoot, resolved))) {
138
+ missing.push({ file, target });
139
+ continue;
140
+ }
141
+ if (anchor) {
142
+ const targetContent = read(workspaceRoot, resolved) ?? "";
143
+ if (!anchorsFor(targetContent).has(anchor)) {
144
+ missing.push({ file, target });
145
+ }
146
+ }
147
+ }
148
+ }
149
+ return missing.length === 0
150
+ ? { name: "docs-internal-links", ok: true, status: "pass" }
151
+ : { name: "docs-internal-links", ok: false, status: "fail", details: { missing } };
152
+ }
153
+
154
+ function checkMkdocsTooling(workspaceRoot: string): DocsCheck {
155
+ const result = spawnSync("python3", ["-m", "mkdocs", "--version"], {
156
+ cwd: workspaceRoot,
157
+ encoding: "utf8",
158
+ windowsHide: true,
159
+ stdio: ["ignore", "pipe", "pipe"],
160
+ });
161
+ if (result.status === 0) {
162
+ return {
163
+ name: "mkdocs-tooling",
164
+ ok: true,
165
+ status: "pass",
166
+ details: { version: (result.stdout ?? "").trim() },
167
+ };
168
+ }
169
+ return {
170
+ name: "mkdocs-tooling",
171
+ ok: true,
172
+ status: "warning",
173
+ details: {
174
+ message: "mkdocs is not importable in the current Python environment; install docs/requirements.txt before building docs locally",
175
+ },
176
+ };
177
+ }
178
+
179
+ function runOptionalDocsBuild(options: DocsCheckOptions): DocsCheck[] {
180
+ const checks: DocsCheck[] = [];
181
+ const python = process.platform === "win32"
182
+ ? join(options.workspaceRoot, ".venv-rtd", "Scripts", "python.exe")
183
+ : join(options.workspaceRoot, ".venv-rtd", "bin", "python");
184
+ if (options.installVenv) {
185
+ const venv = spawnSync("python3", ["-m", "venv", ".venv-rtd"], {
186
+ cwd: options.workspaceRoot,
187
+ encoding: "utf8",
188
+ windowsHide: true,
189
+ stdio: ["ignore", "pipe", "pipe"],
190
+ });
191
+ checks.push(venv.status === 0
192
+ ? { name: "mkdocs-venv-create", ok: true, status: "pass" }
193
+ : { name: "mkdocs-venv-create", ok: false, status: "fail", details: { stderr: venv.stderr } });
194
+ if (venv.status === 0) {
195
+ const install = spawnSync(python, ["-m", "pip", "install", "-r", "docs/requirements.txt"], {
196
+ cwd: options.workspaceRoot,
197
+ encoding: "utf8",
198
+ windowsHide: true,
199
+ stdio: ["ignore", "pipe", "pipe"],
200
+ });
201
+ checks.push(install.status === 0
202
+ ? { name: "mkdocs-venv-install", ok: true, status: "pass" }
203
+ : { name: "mkdocs-venv-install", ok: false, status: "fail", details: { stderr: install.stderr } });
204
+ }
205
+ }
206
+ if (options.build) {
207
+ const command = options.installVenv ? python : "python3";
208
+ const args = ["-m", "mkdocs", "build", "--strict"];
209
+ const build = spawnSync(command, args, {
210
+ cwd: options.workspaceRoot,
211
+ encoding: "utf8",
212
+ windowsHide: true,
213
+ stdio: ["ignore", "pipe", "pipe"],
214
+ });
215
+ checks.push(build.status === 0
216
+ ? { name: "mkdocs-build-strict", ok: true, status: "pass", details: { stdout: build.stdout?.trim() } }
217
+ : { name: "mkdocs-build-strict", ok: false, status: "fail", details: { stderr: build.stderr } });
218
+ }
219
+ return checks;
220
+ }
221
+
222
+ export function runDocsCheckCommand(options: DocsCheckOptions): DocsCheckResult {
223
+ const checks: DocsCheck[] = [
224
+ checkFileExists(options.workspaceRoot, ".readthedocs.yaml"),
225
+ checkFileExists(options.workspaceRoot, "mkdocs.yml"),
226
+ checkFileExists(options.workspaceRoot, "docs/requirements.txt"),
227
+ checkFileExists(options.workspaceRoot, "docs/stylesheets/forge.css"),
228
+ checkFileExists(options.workspaceRoot, "docs/javascripts/mermaid-init.js"),
229
+ ...REQUIRED_DOCS.map((file) => checkFileExists(options.workspaceRoot, `docs/${file}`)),
230
+ checkYamlShape(options.workspaceRoot, ".readthedocs.yaml", ["version", "build", "mkdocs"]),
231
+ checkYamlShape(options.workspaceRoot, "mkdocs.yml", ["site_name", "theme", "nav"]),
232
+ ...CONTENT_CHECKS.map((check) => checkContains(options.workspaceRoot, check.file, check.contains)),
233
+ checkInternalLinks(options.workspaceRoot),
234
+ checkMkdocsTooling(options.workspaceRoot),
235
+ ...runOptionalDocsBuild(options),
236
+ ];
237
+ const failed = checks.filter((check) => !check.ok);
238
+ const diagnostics = failed.map((check) => createDiagnostic({
239
+ severity: "error",
240
+ code: "FORGE_DOCS_CHECK_FAILED",
241
+ message: `documentation check failed: ${check.name}`,
242
+ suggestedCommands: ["forge docs check --json", "bun test tests/docs/readthedocs.test.ts"],
243
+ }));
244
+ const ok = failed.length === 0;
245
+ return {
246
+ ok,
247
+ checks,
248
+ diagnostics,
249
+ nextActions: ok
250
+ ? docsReadyNextActions()
251
+ : ["forge docs check --json", "bun test tests/docs/readthedocs.test.ts"],
252
+ exitCode: ok ? 0 : 1,
253
+ };
254
+ }
255
+
256
+ export function formatDocsCheckHuman(result: DocsCheckResult): string {
257
+ const lines = [
258
+ `docs check ${result.ok ? "ok" : "failed"}`,
259
+ ...result.checks.map((check) => `${check.status} ${check.name}`),
260
+ ];
261
+ if (result.nextActions.length > 0) {
262
+ lines.push("", "Next:", ...result.nextActions.map((action) => ` ${action}`));
263
+ }
264
+ return `${lines.join("\n")}\n`;
265
+ }
@@ -6,6 +6,12 @@ import { stripDeterministicHeader } from "../compiler/primitives/header.ts";
6
6
  import type { TableMapEntry } from "../compiler/data-graph/sql/serialize.ts";
7
7
  import type { FrontendGraph } from "../compiler/types/frontend-graph.ts";
8
8
  import type { Diagnostic } from "../compiler/types/diagnostic.ts";
9
+ import {
10
+ DEFAULT_PGLITE_DIR,
11
+ inspectPgliteStore,
12
+ type PgliteStoreInspection,
13
+ } from "../runtime/db/pglite-adapter.ts";
14
+ import { normalizeForgeCliCommandsInValue } from "../workspace/forge-cli.ts";
9
15
 
10
16
  export interface DoctorCheck {
11
17
  name: string;
@@ -20,6 +26,49 @@ export interface DoctorResult {
20
26
  exitCode: 0 | 1;
21
27
  }
22
28
 
29
+ export interface PgliteDoctorResult {
30
+ ok: boolean;
31
+ inspection: PgliteStoreInspection;
32
+ checks: DoctorCheck[];
33
+ dbGuide: LocalDbModeGuide;
34
+ nextActions: string[];
35
+ exitCode: 0 | 1;
36
+ }
37
+
38
+ export interface LocalDbModeGuide {
39
+ recommendedForCurrentState: "pglite" | "memory" | "stop-active-process" | "repair-pglite";
40
+ memory: {
41
+ command: string;
42
+ useWhen: string[];
43
+ tradeoff: string;
44
+ };
45
+ pglite: {
46
+ command: string;
47
+ useWhen: string[];
48
+ tradeoff: string;
49
+ };
50
+ repair?: {
51
+ command: string;
52
+ safeWhen: string;
53
+ preservesDataByArchiving: boolean;
54
+ };
55
+ }
56
+
57
+ export interface RuntimeDoctorResult {
58
+ ok: boolean;
59
+ checks: DoctorCheck[];
60
+ dev: {
61
+ pidFile: string;
62
+ logFile: string;
63
+ running: boolean;
64
+ pid?: number;
65
+ };
66
+ pglite: PgliteStoreInspection;
67
+ dbGuide: LocalDbModeGuide;
68
+ nextActions: string[];
69
+ exitCode: 0 | 1;
70
+ }
71
+
23
72
  function present(workspaceRoot: string, name: string, relative: string): DoctorCheck {
24
73
  const ok = nodeFileSystem.exists(join(workspaceRoot, relative));
25
74
  return {
@@ -92,6 +141,50 @@ function frontendDevAuthChecks(
92
141
  }));
93
142
  }
94
143
 
144
+ function buildLocalDbModeGuide(workspaceRoot: string, pglite: PgliteStoreInspection): LocalDbModeGuide {
145
+ const memoryCommand = "forge dev --db memory --json";
146
+ const pgliteCommand = "forge dev --db pglite --json";
147
+ const repairCommand = "forge db repair --local --adapter pglite --json";
148
+ const recommendedForCurrentState: LocalDbModeGuide["recommendedForCurrentState"] =
149
+ pglite.state === "active"
150
+ ? "stop-active-process"
151
+ : pglite.state === "aborted" || pglite.state === "unhealthy"
152
+ ? "repair-pglite"
153
+ : pglite.openable
154
+ ? "pglite"
155
+ : "memory";
156
+ return normalizeForgeCliCommandsInValue(workspaceRoot, {
157
+ recommendedForCurrentState,
158
+ memory: {
159
+ command: memoryCommand,
160
+ useWhen: [
161
+ "you need a clean isolated smoke test",
162
+ "PGlite is active, aborted, or suspected corrupt",
163
+ "you do not need local data to persist after the process exits",
164
+ ],
165
+ tradeoff: "Fast and isolated, but data disappears when the dev process exits.",
166
+ },
167
+ pglite: {
168
+ command: pgliteCommand,
169
+ useWhen: [
170
+ "you want local data to persist between dev runs",
171
+ "you are reproducing real database behavior more closely than memory",
172
+ "doctor pglite reports the store is missing or healthy",
173
+ ],
174
+ tradeoff: "Persists local state, but a stale/corrupt .forge/pglite store can require repair.",
175
+ },
176
+ ...(pglite.state === "aborted" || pglite.state === "unhealthy"
177
+ ? {
178
+ repair: {
179
+ command: repairCommand,
180
+ safeWhen: "PGlite is not owned by a live forge dev process and doctor reports aborted/unhealthy.",
181
+ preservesDataByArchiving: true,
182
+ },
183
+ }
184
+ : {}),
185
+ }) as LocalDbModeGuide;
186
+ }
187
+
95
188
  export async function runDoctorCommand(options: {
96
189
  workspaceRoot: string;
97
190
  }): Promise<DoctorResult> {
@@ -193,6 +286,151 @@ export async function runDoctorCommand(options: {
193
286
  };
194
287
  }
195
288
 
289
+ export async function runPgliteDoctorCommand(options: {
290
+ workspaceRoot: string;
291
+ }): Promise<PgliteDoctorResult> {
292
+ const dataDir = join(options.workspaceRoot, DEFAULT_PGLITE_DIR);
293
+ const inspection = await inspectPgliteStore(dataDir);
294
+ const ok = inspection.state === "missing" || inspection.state === "healthy";
295
+ const checks: DoctorCheck[] = [
296
+ {
297
+ name: "pglite-store",
298
+ ok,
299
+ severity: inspection.state === "active" ? "warning" : "error",
300
+ message: ok
301
+ ? `PGlite store is ${inspection.state}`
302
+ : inspection.error ?? `PGlite store is ${inspection.state}`,
303
+ },
304
+ {
305
+ name: "pglite-openable",
306
+ ok: inspection.openable,
307
+ severity: inspection.state === "active" ? "warning" : "error",
308
+ message: inspection.openable
309
+ ? undefined
310
+ : "local PGlite store cannot be opened by Forge dev",
311
+ },
312
+ ];
313
+
314
+ if (inspection.lockFiles.length > 0) {
315
+ checks.push({
316
+ name: "pglite-lock-files",
317
+ ok: inspection.state === "healthy",
318
+ severity: inspection.state === "active" ? "warning" : "error",
319
+ message: `lock files present: ${inspection.lockFiles.join(", ")}`,
320
+ });
321
+ }
322
+
323
+ const exitOk = checks.every((check) => check.ok || check.severity === "warning");
324
+ const dbGuide = buildLocalDbModeGuide(options.workspaceRoot, inspection);
325
+ return normalizeForgeCliCommandsInValue(options.workspaceRoot, {
326
+ ok: exitOk,
327
+ inspection,
328
+ checks,
329
+ dbGuide,
330
+ nextActions: inspection.nextActions,
331
+ exitCode: exitOk ? 0 : 1,
332
+ });
333
+ }
334
+
335
+ function isProcessRunning(pid: number): boolean {
336
+ try {
337
+ process.kill(pid, 0);
338
+ return true;
339
+ } catch (error) {
340
+ return error instanceof Error && "code" in error && error.code === "EPERM";
341
+ }
342
+ }
343
+
344
+ function readPid(path: string): number | undefined {
345
+ const text = nodeFileSystem.readText(path);
346
+ if (text === null) return undefined;
347
+ const pid = Number(text.trim());
348
+ return Number.isInteger(pid) && pid > 0 ? pid : undefined;
349
+ }
350
+
351
+ export async function runRuntimeDoctorCommand(options: {
352
+ workspaceRoot: string;
353
+ }): Promise<RuntimeDoctorResult> {
354
+ const checks: DoctorCheck[] = [];
355
+ const generated = await runGenerate({
356
+ workspaceRoot: options.workspaceRoot,
357
+ check: true,
358
+ dryRun: false,
359
+ json: false,
360
+ concurrency: 4,
361
+ });
362
+ checks.push({
363
+ name: "generated",
364
+ ok: generated.exitCode === 0,
365
+ severity: "error",
366
+ message: generated.exitCode === 0 ? "generated artifacts are fresh" : "generated artifacts are stale; run forge generate",
367
+ });
368
+
369
+ const devDir = join(options.workspaceRoot, ".forge", "dev");
370
+ const pidFile = join(devDir, "dev.pid");
371
+ const logFile = join(devDir, "dev.log");
372
+ const pid = readPid(pidFile);
373
+ const running = pid !== undefined && isProcessRunning(pid);
374
+ checks.push({
375
+ name: "dev-lifecycle",
376
+ ok: true,
377
+ severity: "warning",
378
+ message: running
379
+ ? `detached forge dev is running with pid ${pid}`
380
+ : "no detached forge dev server is running",
381
+ });
382
+
383
+ const pglite = await inspectPgliteStore(join(options.workspaceRoot, DEFAULT_PGLITE_DIR));
384
+ const pgliteOk = pglite.state === "missing" || pglite.state === "healthy" || pglite.state === "active";
385
+ checks.push({
386
+ name: "pglite-store",
387
+ ok: pgliteOk,
388
+ severity: pglite.state === "active" ? "warning" : "error",
389
+ message: pglite.error ?? `PGlite store is ${pglite.state}`,
390
+ });
391
+ checks.push({
392
+ name: "pglite-openable",
393
+ ok: pglite.openable || pglite.state === "active",
394
+ severity: pglite.state === "active" ? "warning" : "error",
395
+ message: pglite.openable
396
+ ? "PGlite store is openable"
397
+ : pglite.state === "active"
398
+ ? "PGlite store is owned by a live process"
399
+ : "PGlite store cannot be opened",
400
+ });
401
+
402
+ const ok = checks.every((check) => check.ok || check.severity === "warning");
403
+ const dbGuide = buildLocalDbModeGuide(options.workspaceRoot, pglite);
404
+ const nextActions = ok
405
+ ? ["forge dev --once --json", "forge dev status --json"]
406
+ : [
407
+ ...(generated.exitCode === 0 ? [] : ["forge generate"]),
408
+ ...(pglite.state === "active"
409
+ ? ["stop the running forge dev process that owns .forge/pglite", "forge doctor pglite --json"]
410
+ : []),
411
+ ...(pglite.state === "aborted" || pglite.state === "unhealthy"
412
+ ? ["forge doctor pglite --json", "forge db repair --local --adapter pglite --json", "forge dev --db memory --json"]
413
+ : []),
414
+ ...(!pglite.openable && pglite.state !== "active" && pglite.state !== "aborted" && pglite.state !== "unhealthy"
415
+ ? ["forge doctor pglite --json", "forge dev --db memory --json"]
416
+ : []),
417
+ ];
418
+ return normalizeForgeCliCommandsInValue(options.workspaceRoot, {
419
+ ok,
420
+ checks,
421
+ dev: {
422
+ pidFile,
423
+ logFile,
424
+ running,
425
+ ...(pid !== undefined ? { pid } : {}),
426
+ },
427
+ pglite,
428
+ dbGuide,
429
+ nextActions: [...new Set(nextActions)],
430
+ exitCode: ok ? 0 : 1,
431
+ });
432
+ }
433
+
196
434
  export function formatDoctorJson(result: DoctorResult): string {
197
435
  return `${JSON.stringify(result, null, 2)}\n`;
198
436
  }
@@ -207,3 +445,62 @@ export function formatDoctorHuman(result: DoctorResult): string {
207
445
  lines.push(result.ok ? "Project is coherent." : "Project needs attention.");
208
446
  return `${lines.join("\n")}\n`;
209
447
  }
448
+
449
+ export function formatPgliteDoctorJson(result: PgliteDoctorResult): string {
450
+ return `${JSON.stringify(result, null, 2)}\n`;
451
+ }
452
+
453
+ export function formatPgliteDoctorHuman(result: PgliteDoctorResult): string {
454
+ const lines = ["Forge PGlite Doctor", ""];
455
+ for (const check of result.checks) {
456
+ const marker = check.ok ? "OK" : check.severity === "warning" ? "WARN" : "FAIL";
457
+ lines.push(`${marker} ${check.name}${check.message ? ` - ${check.message}` : ""}`);
458
+ }
459
+ lines.push("");
460
+ lines.push(`Store: ${result.inspection.dataDir}`);
461
+ lines.push(`State: ${result.inspection.state}`);
462
+ lines.push(`Recommended DB mode: ${result.dbGuide.recommendedForCurrentState}`);
463
+ lines.push(`Memory: ${result.dbGuide.memory.command} - ${result.dbGuide.memory.tradeoff}`);
464
+ lines.push(`PGlite: ${result.dbGuide.pglite.command} - ${result.dbGuide.pglite.tradeoff}`);
465
+ if (result.dbGuide.repair) {
466
+ lines.push(`Repair: ${result.dbGuide.repair.command}`);
467
+ }
468
+ if (result.nextActions.length > 0) {
469
+ lines.push("");
470
+ lines.push("Next actions:");
471
+ for (const action of result.nextActions) {
472
+ lines.push(` ${action}`);
473
+ }
474
+ }
475
+ return `${lines.join("\n")}\n`;
476
+ }
477
+
478
+ export function formatRuntimeDoctorJson(result: RuntimeDoctorResult): string {
479
+ return `${JSON.stringify(result, null, 2)}\n`;
480
+ }
481
+
482
+ export function formatRuntimeDoctorHuman(result: RuntimeDoctorResult): string {
483
+ const lines = ["Forge Runtime Doctor", ""];
484
+ for (const check of result.checks) {
485
+ const marker = check.ok ? "OK" : check.severity === "warning" ? "WARN" : "FAIL";
486
+ lines.push(`${marker} ${check.name}${check.message ? ` - ${check.message}` : ""}`);
487
+ }
488
+ lines.push("");
489
+ lines.push(`Dev pid file: ${result.dev.pidFile}`);
490
+ lines.push(`Dev log file: ${result.dev.logFile}`);
491
+ lines.push(`PGlite state: ${result.pglite.state}`);
492
+ lines.push(`Recommended DB mode: ${result.dbGuide.recommendedForCurrentState}`);
493
+ lines.push(`Memory: ${result.dbGuide.memory.command} - ${result.dbGuide.memory.tradeoff}`);
494
+ lines.push(`PGlite: ${result.dbGuide.pglite.command} - ${result.dbGuide.pglite.tradeoff}`);
495
+ if (result.dbGuide.repair) {
496
+ lines.push(`Repair: ${result.dbGuide.repair.command}`);
497
+ }
498
+ if (result.nextActions.length > 0) {
499
+ lines.push("");
500
+ lines.push("Next actions:");
501
+ for (const action of result.nextActions) {
502
+ lines.push(` ${action}`);
503
+ }
504
+ }
505
+ return `${lines.join("\n")}\n`;
506
+ }
@@ -0,0 +1,62 @@
1
+ export interface PlaceholderEnvProblem {
2
+ key: string;
3
+ reason: string;
4
+ }
5
+
6
+ const GENERIC_PLACEHOLDER_PATTERNS: Array<{ pattern: RegExp; reason: string }> = [
7
+ { pattern: /\bexample\.(com|test|org|net)\b/, reason: "example domain" },
8
+ { pattern: /\bdummy\b/, reason: "dummy marker" },
9
+ { pattern: /\bplaceholder\b/, reason: "placeholder marker" },
10
+ { pattern: /\bchange[-_]?me\b/, reason: "change-me marker" },
11
+ { pattern: /\bdo[-_]?not[-_]?use\b/, reason: "do-not-use marker" },
12
+ { pattern: /^<.*>$/, reason: "angle-bracket placeholder" },
13
+ { pattern: /^your[-_]/, reason: "your-value placeholder" },
14
+ ];
15
+
16
+ const KEY_PLACEHOLDER_PATTERNS: Record<string, Array<{ pattern: RegExp; reason: string }>> = {
17
+ DATABASE_URL: [
18
+ { pattern: /^postgres:\/\/forge:forge@postgres:5432\/forge_app$/i, reason: "generated Docker example database URL" },
19
+ { pattern: /^postgres:\/\/forge:forge@db:5432\/forge$/i, reason: "local dummy database URL" },
20
+ { pattern: /^postgres:\/\/local-only\b/i, reason: "local-only database URL" },
21
+ ],
22
+ WORKOS_API_KEY: [
23
+ { pattern: /^sk_test_dummy/i, reason: "dummy WorkOS API key" },
24
+ { pattern: /^sk_test_?\.\.\.$/i, reason: "placeholder WorkOS API key" },
25
+ ],
26
+ WORKOS_CLIENT_ID: [
27
+ { pattern: /^client_?\.\.\.$/i, reason: "placeholder WorkOS client id" },
28
+ { pattern: /^client_test_local$/i, reason: "local fake WorkOS client id" },
29
+ ],
30
+ WORKOS_COOKIE_PASSWORD: [
31
+ { pattern: /dummy/i, reason: "dummy cookie password" },
32
+ { pattern: /change[-_]?me/i, reason: "change-me cookie password" },
33
+ ],
34
+ FORGE_AUTH_AUDIENCE: [
35
+ { pattern: /^client_test_local$/i, reason: "local fake auth audience" },
36
+ ],
37
+ FORGE_AUTH_JWKS_URI: [
38
+ { pattern: /\/client_test_local$/i, reason: "local fake JWKS client id" },
39
+ ],
40
+ };
41
+
42
+ export function placeholderEnvProblem(key: string, value: string | undefined): PlaceholderEnvProblem | null {
43
+ const trimmed = value?.trim() ?? "";
44
+ if (!trimmed) return null;
45
+ const normalized = trimmed.toLowerCase();
46
+ for (const { pattern, reason } of KEY_PLACEHOLDER_PATTERNS[key] ?? []) {
47
+ if (pattern.test(trimmed)) return { key, reason };
48
+ }
49
+ for (const { pattern, reason } of GENERIC_PLACEHOLDER_PATTERNS) {
50
+ if (pattern.test(normalized)) return { key, reason };
51
+ }
52
+ return null;
53
+ }
54
+
55
+ export function productionPlaceholderEnvProblems(
56
+ values: Record<string, string>,
57
+ keys = Object.keys(values),
58
+ ): PlaceholderEnvProblem[] {
59
+ return keys
60
+ .map((key) => placeholderEnvProblem(key, values[key]))
61
+ .filter((problem): problem is PlaceholderEnvProblem => Boolean(problem));
62
+ }
@@ -0,0 +1,40 @@
1
+ import { realpathSync } from "node:fs";
2
+ import { LocalEvolutionService } from "../agent-fabric/local-evolution-service.ts";
3
+ import type { EvolutionChannel, EvolutionDecisionAction } from "../agent-fabric/local-evolution-registry.ts";
4
+
5
+ export interface EvolutionCliOptions {
6
+ subcommand: "register" | "evaluate" | "status" | "review" | "load";
7
+ workspaceRoot: string;
8
+ json: boolean;
9
+ manifest?: string;
10
+ versionId?: string;
11
+ action?: EvolutionDecisionAction;
12
+ extensionKey?: string;
13
+ channel?: EvolutionChannel;
14
+ }
15
+
16
+ export async function runEvolutionCommand(options: EvolutionCliOptions): Promise<number> {
17
+ let service: LocalEvolutionService | undefined;
18
+ try {
19
+ service = await LocalEvolutionService.open(realpathSync(options.workspaceRoot));
20
+ const result = options.subcommand === "register"
21
+ ? await service.register(options.manifest!)
22
+ : options.subcommand === "evaluate"
23
+ ? await service.evaluate(options.versionId!)
24
+ : options.subcommand === "status"
25
+ ? await service.status(options.versionId!)
26
+ : options.subcommand === "review"
27
+ ? await service.decide(options.action!, options.versionId!)
28
+ : await service.loadSelected(options.extensionKey!, options.channel!);
29
+ // The CLI loader reports verified metadata. Library callers can consume the verified bytes.
30
+ const output = "artifact" in result ? { versionId: result.versionId,
31
+ extensionKey: result.manifest.extensionKey, artifactBytes: result.artifact.length } : result;
32
+ process.stdout.write(options.json ? `${JSON.stringify({ ok: true, result: output }, null, 2)}\n` :
33
+ `${JSON.stringify(output, null, 2)}\n`);
34
+ return 0;
35
+ } catch (error) {
36
+ const message = error instanceof Error ? error.message : String(error);
37
+ process.stdout.write(options.json ? `${JSON.stringify({ ok: false, error: message }, null, 2)}\n` : `error: ${message}\n`);
38
+ return 1;
39
+ } finally { await service?.close(); }
40
+ }