forgeos 0.1.0-alpha.7 → 0.1.0-alpha.71
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.
- package/.agents/skills/forge-agent-fabric/SKILL.md +178 -0
- package/.agents/skills/forge-agent-fabric/references/managed-workflows.md +95 -0
- package/.agents/skills/forge-agent-fabric/references/repository-analysis.md +102 -0
- package/.agents/skills/forge-agent-fabric/scripts/fabric.mjs +46 -0
- package/.agents/skills/forge-agent-fabric/scripts/repository.mjs +44 -0
- package/.npmignore +10 -0
- package/AGENTS.md +142 -90
- package/CHANGELOG.md +870 -9
- package/LICENSE +21 -0
- package/README.md +121 -6
- package/adapters/go/README.md +23 -0
- package/adapters/go/go.mod +3 -0
- package/adapters/go/http.go +149 -0
- package/adapters/go/registry.go +234 -0
- package/adapters/go/types.go +136 -0
- package/adapters/java/README.md +68 -0
- package/adapters/java/pom.xml +47 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
- package/adapters/java-spring-boot-starter/README.md +32 -0
- package/adapters/java-spring-boot-starter/pom.xml +49 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
- package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
- package/bin/forge.mjs +18 -0
- package/docs/agent-fabric-programs.md +151 -0
- package/docs/agent-fabric.md +582 -0
- package/docs/architecture/agent-fabric/PORTABLE_PROJECTS_PLAN.md +136 -0
- package/docs/architecture/agent-fabric/README.md +180 -0
- package/docs/architecture/agent-fabric/REPOSITORY_MANIFEST_PLAN.md +284 -0
- package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_ADR.md +81 -0
- package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_CORRECTIONS.md +39 -0
- package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_CORRECTIONS_EVIDENCE.md +53 -0
- package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_EVIDENCE.md +49 -0
- package/docs/architecture/agent-fabric/WORKFLOW_PROGRAM_V2_PLAN.md +590 -0
- package/docs/cair-protocol.md +103 -0
- package/docs/changelog.md +1070 -0
- package/docs/forge-protocol.md +189 -0
- package/docs/repository-agent-benchmark.md +179 -0
- package/docs/repository-analysis.md +139 -0
- package/docs/repository-context-quality.md +179 -0
- package/docs/repository-runtime-observation.md +82 -0
- package/examples/agent-fabric-v2/README.md +70 -0
- package/examples/agent-fabric-v2/item-child.workflow.ts +11 -0
- package/examples/agent-fabric-v2/make-request.mjs +4 -0
- package/examples/agent-fabric-v2/map-child.workflow.ts +10 -0
- package/examples/agent-fabric-v2/migrate.workflow.ts +35 -0
- package/examples/agent-fabric-v2/registry.example.json +256 -0
- package/examples/agent-fabric-v2/run-ui-fixture.ts +48 -0
- package/examples/agent-fabric-v2/ui-audit.workflow.ts +28 -0
- package/examples/agent-fabric-v2/ui-fixture-worker.cjs +36 -0
- package/examples/agent-fabric-v2/visual-population.json +13 -0
- package/examples/agent-fabric-v2/workers/check.mjs +2 -0
- package/examples/agent-fabric-v2/workers/common.mjs +7 -0
- package/examples/agent-fabric-v2/workers/discover.mjs +2 -0
- package/examples/agent-fabric-v2/workers/migrate.mjs +4 -0
- package/examples/agent-fabric-v2/workers/review.mjs +3 -0
- package/examples/go-billing/go.mod +7 -0
- package/examples/go-billing/main.go +120 -0
- package/examples/java-billing/pom.xml +60 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
- package/package.json +60 -5
- package/schemas/agent-fabric/v0.1/control-event.schema.json +281 -0
- package/schemas/forge-manifest.schema.json +389 -0
- package/scripts/field-test-forgeos.mjs +1021 -0
- package/scripts/install-agent-fabric-skill.mjs +105 -0
- package/src/forge/_generated/releaseManifest.json +1 -2
- package/src/forge/_generated/releaseManifest.ts +3 -3
- package/src/forge/agent-adapters/index.ts +1592 -125
- package/src/forge/agent-adapters/types.ts +225 -1
- package/src/forge/agent-fabric/adapter.ts +131 -0
- package/src/forge/agent-fabric/attached-snapshot.ts +55 -0
- package/src/forge/agent-fabric/attached-task-contract.ts +105 -0
- package/src/forge/agent-fabric/attached-task-service.ts +127 -0
- package/src/forge/agent-fabric/attached-task-store.ts +109 -0
- package/src/forge/agent-fabric/authority.ts +298 -0
- package/src/forge/agent-fabric/canonical.ts +135 -0
- package/src/forge/agent-fabric/codex-adversarial-review.ts +229 -0
- package/src/forge/agent-fabric/codex-sdk-worker.ts +203 -0
- package/src/forge/agent-fabric/conductor.ts +754 -0
- package/src/forge/agent-fabric/dictionary.ts +12 -0
- package/src/forge/agent-fabric/errors.ts +32 -0
- package/src/forge/agent-fabric/hardened-conductor.ts +485 -0
- package/src/forge/agent-fabric/hardened-reducer.ts +211 -0
- package/src/forge/agent-fabric/index.ts +48 -0
- package/src/forge/agent-fabric/journal.ts +116 -0
- package/src/forge/agent-fabric/local-adaptive-digest-worker.mjs +26 -0
- package/src/forge/agent-fabric/local-adaptive-harness.ts +343 -0
- package/src/forge/agent-fabric/local-adaptive-service.ts +398 -0
- package/src/forge/agent-fabric/local-adaptive-worker.ts +146 -0
- package/src/forge/agent-fabric/local-approval-window.ts +211 -0
- package/src/forge/agent-fabric/local-change-review-service.ts +374 -0
- package/src/forge/agent-fabric/local-coding-worker.ts +285 -0
- package/src/forge/agent-fabric/local-control-store.ts +239 -0
- package/src/forge/agent-fabric/local-effect-broker.ts +348 -0
- package/src/forge/agent-fabric/local-evolution-approval.ts +81 -0
- package/src/forge/agent-fabric/local-evolution-profile.ts +87 -0
- package/src/forge/agent-fabric/local-evolution-registry.ts +427 -0
- package/src/forge/agent-fabric/local-evolution-service.ts +200 -0
- package/src/forge/agent-fabric/local-intelligence.ts +281 -0
- package/src/forge/agent-fabric/local-paths.ts +18 -0
- package/src/forge/agent-fabric/local-task-contract.ts +203 -0
- package/src/forge/agent-fabric/local-task-inbox.ts +543 -0
- package/src/forge/agent-fabric/local-task-server.ts +374 -0
- package/src/forge/agent-fabric/local-task-service.ts +982 -0
- package/src/forge/agent-fabric/local-verification.ts +551 -0
- package/src/forge/agent-fabric/managed-environment.ts +205 -0
- package/src/forge/agent-fabric/managed-run-contract.ts +103 -0
- package/src/forge/agent-fabric/managed-run-service.ts +401 -0
- package/src/forge/agent-fabric/managed-run-store.ts +165 -0
- package/src/forge/agent-fabric/managed-workspace.ts +253 -0
- package/src/forge/agent-fabric/p0a.ts +104 -0
- package/src/forge/agent-fabric/p0b-model-adapter.ts +434 -0
- package/src/forge/agent-fabric/planning.ts +155 -0
- package/src/forge/agent-fabric/program-api.ts +37 -0
- package/src/forge/agent-fabric/program-contract.ts +283 -0
- package/src/forge/agent-fabric/program-dsl.ts +126 -0
- package/src/forge/agent-fabric/program-evidence.ts +22 -0
- package/src/forge/agent-fabric/program-image.ts +15 -0
- package/src/forge/agent-fabric/program-lock.ts +50 -0
- package/src/forge/agent-fabric/program-owner.ts +16 -0
- package/src/forge/agent-fabric/program-scheduler.ts +38 -0
- package/src/forge/agent-fabric/program-service.ts +793 -0
- package/src/forge/agent-fabric/program-store.ts +142 -0
- package/src/forge/agent-fabric/program-structure.ts +65 -0
- package/src/forge/agent-fabric/program-types.ts +110 -0
- package/src/forge/agent-fabric/program-view.ts +12 -0
- package/src/forge/agent-fabric/program-worker.ts +108 -0
- package/src/forge/agent-fabric/project-profile.ts +50 -0
- package/src/forge/agent-fabric/project-registry.ts +120 -0
- package/src/forge/agent-fabric/project-runtime.ts +85 -0
- package/src/forge/agent-fabric/readiness.ts +26 -0
- package/src/forge/agent-fabric/reducer.ts +863 -0
- package/src/forge/agent-fabric/repository-context.ts +83 -0
- package/src/forge/agent-fabric/resource-ledger.ts +266 -0
- package/src/forge/agent-fabric/serialized-local-adapter.ts +60 -0
- package/src/forge/agent-fabric/types.ts +424 -0
- package/src/forge/agent-fabric/validation.ts +500 -0
- package/src/forge/agent-fabric/workflow-engine.ts +218 -0
- package/src/forge/agent-fabric/workflow-task-actions.ts +104 -0
- package/src/forge/agent-fabric/workflow-templates.ts +11 -0
- package/src/forge/agent-memory/bridge.ts +1728 -0
- package/src/forge/agent-memory/context-pack.ts +284 -0
- package/src/forge/agent-memory/hook-runner.ts +331 -0
- package/src/forge/agent-memory/mcp.ts +597 -0
- package/src/forge/agent-memory/normalize.ts +498 -0
- package/src/forge/agent-memory/redaction.ts +103 -0
- package/src/forge/agent-memory/sources/claude-code.ts +51 -0
- package/src/forge/agent-memory/sources/codex-hook-runner.mjs +343 -0
- package/src/forge/agent-memory/sources/codex.ts +161 -0
- package/src/forge/agent-memory/sources/cursor.ts +35 -0
- package/src/forge/agent-memory/types.ts +215 -0
- package/src/forge/bench.ts +248 -0
- package/src/forge/brownfield-import/index.ts +896 -0
- package/src/forge/brownfield-import/types.ts +127 -0
- package/src/forge/cair/action-journal.ts +61 -0
- package/src/forge/cair/action-parser.ts +314 -0
- package/src/forge/cair/action-validator.ts +40 -0
- package/src/forge/cair/actions.ts +1818 -0
- package/src/forge/cair/format.ts +77 -0
- package/src/forge/cair/index.ts +118 -0
- package/src/forge/cair/query.ts +478 -0
- package/src/forge/cair/snapshot.ts +315 -0
- package/src/forge/cair/types.ts +255 -0
- package/src/forge/cli/adaptive.ts +51 -0
- package/src/forge/cli/ai.ts +16 -1
- package/src/forge/cli/auth.ts +459 -15
- package/src/forge/cli/authmd.ts +441 -0
- package/src/forge/cli/baseline.ts +112 -0
- package/src/forge/cli/build.ts +20 -4
- package/src/forge/cli/changed.ts +418 -0
- package/src/forge/cli/codex-app-server.ts +877 -0
- package/src/forge/cli/commands.ts +1859 -20
- package/src/forge/cli/db.ts +209 -2
- package/src/forge/cli/deploy.ts +1339 -0
- package/src/forge/cli/deps.ts +150 -23
- package/src/forge/cli/dev.ts +1137 -53
- package/src/forge/cli/docs.ts +265 -0
- package/src/forge/cli/doctor.ts +297 -0
- package/src/forge/cli/env-placeholders.ts +62 -0
- package/src/forge/cli/evolution.ts +40 -0
- package/src/forge/cli/fabric.ts +253 -0
- package/src/forge/cli/field-test.ts +568 -0
- package/src/forge/cli/golden-path.ts +487 -0
- package/src/forge/cli/handoff.ts +336 -0
- package/src/forge/cli/index.ts +1 -0
- package/src/forge/cli/last-run.ts +84 -0
- package/src/forge/cli/main.ts +196 -3
- package/src/forge/cli/new.ts +169 -17
- package/src/forge/cli/next-actions.ts +23 -0
- package/src/forge/cli/output.ts +398 -6
- package/src/forge/cli/parse.ts +1377 -38
- package/src/forge/cli/progress.ts +51 -0
- package/src/forge/cli/query.ts +32 -0
- package/src/forge/cli/release.ts +35 -11
- package/src/forge/cli/repository.ts +151 -0
- package/src/forge/cli/run.ts +42 -0
- package/src/forge/cli/secrets.ts +137 -1
- package/src/forge/cli/seed.ts +581 -0
- package/src/forge/cli/self-host.ts +56 -14
- package/src/forge/cli/studio.ts +2282 -0
- package/src/forge/cli/verify.ts +1458 -32
- package/src/forge/cli/windows.ts +23 -0
- package/src/forge/cli/workos.ts +3509 -0
- package/src/forge/compiler/agent-contract/build.ts +728 -64
- package/src/forge/compiler/agent-contract/types.ts +45 -2
- package/src/forge/compiler/ai-registry/parse.ts +71 -2
- package/src/forge/compiler/api-surface/build.ts +47 -0
- package/src/forge/compiler/app-graph/build.ts +112 -9
- package/src/forge/compiler/app-graph/extract.ts +107 -0
- package/src/forge/compiler/app-graph/module-graph.ts +73 -78
- package/src/forge/compiler/app-graph/parser.ts +24 -24
- package/src/forge/compiler/app-graph/profile.ts +26 -0
- package/src/forge/compiler/app-graph/tsconfig-hash.ts +41 -4
- package/src/forge/compiler/app-graph/versions.ts +1 -1
- package/src/forge/compiler/classifier/capabilities.ts +3 -2
- package/src/forge/compiler/classifier/classify.ts +32 -8
- package/src/forge/compiler/classifier/secrets.ts +3 -2
- package/src/forge/compiler/classifier/signals.ts +91 -1
- package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
- package/src/forge/compiler/client-sdk/render-client.ts +295 -13
- package/src/forge/compiler/data-graph/build.ts +29 -1
- package/src/forge/compiler/data-graph/parse.ts +20 -4
- package/src/forge/compiler/data-graph/sql/ddl.ts +144 -31
- package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
- package/src/forge/compiler/data-graph/sql/types.ts +1 -0
- package/src/forge/compiler/diagnostics/codes.ts +38 -0
- package/src/forge/compiler/diagnostics/create.ts +28 -2
- package/src/forge/compiler/diagnostics/index.ts +2 -0
- package/src/forge/compiler/emitter/barrel.ts +3 -0
- package/src/forge/compiler/emitter/render.ts +9 -0
- package/src/forge/compiler/external-manifest/registry.ts +217 -0
- package/src/forge/compiler/external-manifest/types.ts +91 -0
- package/src/forge/compiler/external-manifest/validate.ts +373 -0
- package/src/forge/compiler/frontend-graph/build.ts +142 -14
- package/src/forge/compiler/integration/add.ts +991 -33
- package/src/forge/compiler/integration/plan.ts +43 -12
- package/src/forge/compiler/integration/render.ts +29 -0
- package/src/forge/compiler/integration/snapshot.ts +2 -0
- package/src/forge/compiler/integration/templates/convex.ts +70 -0
- package/src/forge/compiler/integration/templates/index.ts +1 -0
- package/src/forge/compiler/integration/templates/render.ts +38 -0
- package/src/forge/compiler/integration/templates/types.ts +3 -0
- package/src/forge/compiler/integration/templates/workos.ts +1439 -0
- package/src/forge/compiler/make-registry/build.ts +8 -9
- package/src/forge/compiler/orchestrator/fast-check.ts +4 -0
- package/src/forge/compiler/orchestrator/generate-lock.ts +14 -3
- package/src/forge/compiler/orchestrator/manifest.ts +1 -1
- package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
- package/src/forge/compiler/orchestrator/plan.ts +249 -10
- package/src/forge/compiler/orchestrator/profile.ts +65 -0
- package/src/forge/compiler/orchestrator/run.ts +101 -33
- package/src/forge/compiler/orchestrator/serialize.ts +33 -8
- package/src/forge/compiler/orchestrator/types.ts +1 -1
- package/src/forge/compiler/package-graph/compiler.ts +3 -1
- package/src/forge/compiler/package-graph/constants.ts +1 -1
- package/src/forge/compiler/package-graph/dts-extractor.ts +14 -1
- package/src/forge/compiler/package-manager/adapter.ts +4 -1
- package/src/forge/compiler/package-manager/commands.ts +4 -0
- package/src/forge/compiler/package-manager/executor.ts +30 -1
- package/src/forge/compiler/package-manager/version.ts +36 -12
- package/src/forge/compiler/package-upgrades/planner.ts +155 -18
- package/src/forge/compiler/package-upgrades/types.ts +2 -0
- package/src/forge/compiler/policy-registry/build.ts +47 -2
- package/src/forge/compiler/policy-registry/parse.ts +32 -2
- package/src/forge/compiler/recipes/definitions.ts +63 -0
- package/src/forge/compiler/recipes/index.ts +2 -0
- package/src/forge/compiler/recipes/profiles.ts +81 -0
- package/src/forge/compiler/recipes/registry.ts +6 -0
- package/src/forge/compiler/test-graph/build.ts +11 -3
- package/src/forge/compiler/types/app-graph.ts +8 -2
- package/src/forge/compiler/types/cli.ts +76 -1
- package/src/forge/compiler/types/dev-manifest.ts +4 -0
- package/src/forge/compiler/types/emit.ts +2 -0
- package/src/forge/compiler/types/frontend-graph.ts +2 -2
- package/src/forge/compiler/types/integration.ts +1 -0
- package/src/forge/compiler/types/package-graph.ts +6 -0
- package/src/forge/compiler/types/policy-registry.ts +3 -1
- package/src/forge/delta/broker-runner.mjs +5 -0
- package/src/forge/delta/broker.ts +429 -0
- package/src/forge/delta/classifier.ts +52 -0
- package/src/forge/delta/explain.ts +238 -0
- package/src/forge/delta/git-observer.ts +67 -0
- package/src/forge/delta/ids.ts +44 -0
- package/src/forge/delta/index.ts +25 -0
- package/src/forge/delta/process-identity.ts +37 -0
- package/src/forge/delta/queue-status.ts +190 -0
- package/src/forge/delta/recorder.ts +540 -0
- package/src/forge/delta/redaction.ts +50 -0
- package/src/forge/delta/schema.ts +240 -0
- package/src/forge/delta/session.ts +142 -0
- package/src/forge/delta/status.ts +1139 -0
- package/src/forge/delta/store.ts +3329 -0
- package/src/forge/delta/timeline.ts +178 -0
- package/src/forge/dev/server.ts +1061 -22
- package/src/forge/dev/types.ts +15 -1
- package/src/forge/dev/watch.ts +17 -7
- package/src/forge/dev-console/cycle.ts +285 -33
- package/src/forge/dev-console/types.ts +47 -1
- package/src/forge/impact/index.ts +222 -30
- package/src/forge/impact/types.ts +33 -1
- package/src/forge/intent/index.ts +35 -16
- package/src/forge/make/fields.ts +26 -0
- package/src/forge/make/index.ts +42 -6
- package/src/forge/make/templates.ts +211 -4
- package/src/forge/make/types.ts +2 -1
- package/src/forge/policy.ts +1 -1
- package/src/forge/react/index.ts +160 -2
- package/src/forge/refactor/index.ts +1 -0
- package/src/forge/repair/rules/index.ts +2 -2
- package/src/forge/repository-analysis/adapters/common.ts +72 -0
- package/src/forge/repository-analysis/adapters/docker.ts +185 -0
- package/src/forge/repository-analysis/adapters/java.ts +133 -0
- package/src/forge/repository-analysis/adapters/typescript.ts +350 -0
- package/src/forge/repository-analysis/adapters/vue.ts +71 -0
- package/src/forge/repository-analysis/analyze.ts +434 -0
- package/src/forge/repository-analysis/benchmark.ts +336 -0
- package/src/forge/repository-analysis/cache-gc.ts +154 -0
- package/src/forge/repository-analysis/check-selection.ts +123 -0
- package/src/forge/repository-analysis/context-node.ts +17 -0
- package/src/forge/repository-analysis/context.ts +456 -0
- package/src/forge/repository-analysis/http-resolution.ts +135 -0
- package/src/forge/repository-analysis/identity.ts +45 -0
- package/src/forge/repository-analysis/index.ts +18 -0
- package/src/forge/repository-analysis/nuxt-resolution.ts +188 -0
- package/src/forge/repository-analysis/quality.ts +60 -0
- package/src/forge/repository-analysis/retrieval.ts +309 -0
- package/src/forge/repository-analysis/runtime-artifacts.ts +195 -0
- package/src/forge/repository-analysis/runtime-observation.ts +325 -0
- package/src/forge/repository-analysis/scanner.ts +174 -0
- package/src/forge/repository-analysis/storage.ts +193 -0
- package/src/forge/repository-analysis/test-associations.ts +59 -0
- package/src/forge/repository-analysis/types.ts +99 -0
- package/src/forge/repository-manifest/index.ts +178 -0
- package/src/forge/repository-manifest/types.ts +63 -0
- package/src/forge/review/index.ts +162 -12
- package/src/forge/review/types.ts +15 -0
- package/src/forge/runtime/ai/providers.ts +19 -4
- package/src/forge/runtime/auth/config.ts +17 -0
- package/src/forge/runtime/auth/evaluate.ts +15 -2
- package/src/forge/runtime/auth/resolve.ts +61 -6
- package/src/forge/runtime/auth/types.ts +1 -0
- package/src/forge/runtime/db/factory.ts +1 -3
- package/src/forge/runtime/db/generated-client.ts +13 -2
- package/src/forge/runtime/db/memory-adapter.ts +139 -32
- package/src/forge/runtime/db/pglite-adapter.ts +285 -2
- package/src/forge/runtime/executor.ts +129 -16
- package/src/forge/runtime/external/bridge.ts +663 -0
- package/src/forge/runtime/runner/run-entry.ts +16 -7
- package/src/forge/runtime/telemetry/buffer.ts +4 -1
- package/src/forge/runtime/telemetry/scrubber.ts +35 -5
- package/src/forge/runtime/webhooks/security.ts +12 -7
- package/src/forge/server.ts +71 -7
- package/src/forge/ui/index.ts +831 -19
- package/src/forge/ui/types.ts +3 -1
- package/src/forge/version.ts +1 -1
- package/src/forge/vue/index.ts +422 -0
- package/src/forge/workspace/baseline.ts +112 -0
- package/src/forge/workspace/change-summary.ts +292 -0
- package/src/forge/workspace/forge-cli.ts +42 -0
- package/src/forge/workspace/git-summary.ts +393 -0
- package/templates/agent-workroom/AGENTS.md +29 -0
- package/templates/agent-workroom/README.md +34 -0
- package/templates/agent-workroom/forge.config.ts +3 -0
- package/templates/agent-workroom/package.json +34 -0
- package/templates/agent-workroom/pnpm-workspace.yaml +2 -0
- package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
- package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
- package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
- package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
- package/templates/agent-workroom/src/forge/schema.ts +54 -0
- package/templates/agent-workroom/src/policies.ts +6 -0
- package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
- package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
- package/templates/agent-workroom/tsconfig.json +16 -0
- package/templates/agent-workroom/web/index.html +13 -0
- package/templates/agent-workroom/web/package.json +21 -0
- package/templates/agent-workroom/web/src/App.tsx +345 -0
- package/templates/agent-workroom/web/src/lib/forge.ts +20 -0
- package/templates/agent-workroom/web/src/main.tsx +13 -0
- package/templates/agent-workroom/web/src/styles.css +545 -0
- package/templates/agent-workroom/web/tsconfig.json +27 -0
- package/templates/agent-workroom/web/vite.config.ts +36 -0
- package/templates/b2b-support-web/package.json +2 -0
- package/templates/b2b-support-web/pnpm-workspace.yaml +2 -0
- package/templates/b2b-support-web/web/app/page.tsx +2 -2
- package/templates/b2b-support-web/web/lib/forge.ts +9 -2
- package/templates/b2b-support-web/web/next.config.ts +24 -0
- package/templates/b2b-support-web/web/package.json +1 -1
- package/templates/minimal-web/package.json +2 -1
- package/templates/minimal-web/pnpm-workspace.yaml +2 -0
- package/templates/minimal-web/web/index.html +1 -0
- package/templates/minimal-web/web/src/App.tsx +12 -6
- package/templates/minimal-web/web/src/lib/forge.ts +9 -2
- package/templates/minimal-web/web/src/styles.css +34 -0
- package/templates/minimal-web/web/vite.config.ts +36 -0
- package/templates/nuxt-web/.vscode/settings.json +14 -0
- package/templates/nuxt-web/.yarnrc.yml +1 -0
- package/templates/nuxt-web/README.md +30 -0
- package/templates/nuxt-web/forge.config.ts +3 -0
- package/templates/nuxt-web/package.json +37 -0
- package/templates/nuxt-web/pnpm-workspace.yaml +2 -0
- package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -0
- package/templates/nuxt-web/src/commands/createNote.ts +26 -0
- package/templates/nuxt-web/src/forge/schema.ts +12 -0
- package/templates/nuxt-web/src/policies.ts +6 -0
- package/templates/nuxt-web/src/queries/listNotes.ts +8 -0
- package/templates/nuxt-web/src/queries/liveNotes.ts +8 -0
- package/templates/nuxt-web/tsconfig.json +17 -0
- package/templates/nuxt-web/web/app.vue +67 -0
- package/templates/nuxt-web/web/components/LiveNotes.vue +89 -0
- package/templates/nuxt-web/web/components/NoteComposer.vue +100 -0
- package/templates/nuxt-web/web/composables/forge.ts +13 -0
- package/templates/nuxt-web/web/composables/useNotes.ts +24 -0
- package/templates/nuxt-web/web/nuxt.config.ts +11 -0
- package/templates/nuxt-web/web/package.json +22 -0
- package/templates/nuxt-web/web/plugins/forge.client.ts +10 -0
- package/templates/nuxt-web/web/plugins/forge.server.ts +10 -0
- package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -0
- package/templates/nuxt-web/web/tsconfig.json +6 -0
- package/templates/vendor-access/.vscode/settings.json +14 -0
- package/templates/vendor-access/README.md +30 -0
- package/templates/vendor-access/forge.config.ts +3 -0
- package/templates/vendor-access/package.json +35 -0
- package/templates/vendor-access/pnpm-workspace.yaml +2 -0
- package/templates/vendor-access/src/commands/addEvidence.ts +42 -0
- package/templates/vendor-access/src/commands/approveAccessRequest.ts +43 -0
- package/templates/vendor-access/src/commands/createAccessRequest.ts +49 -0
- package/templates/vendor-access/src/commands/seedVendorAccessDemo.ts +200 -0
- package/templates/vendor-access/src/forge/schema.ts +74 -0
- package/templates/vendor-access/src/policies.ts +11 -0
- package/templates/vendor-access/src/queries/listVendorAccessDashboard.ts +24 -0
- package/templates/vendor-access/src/queries/liveVendorAccessDashboard.ts +24 -0
- package/templates/vendor-access/tsconfig.json +17 -0
- package/templates/vendor-access/web/index.html +13 -0
- package/templates/vendor-access/web/package.json +21 -0
- package/templates/vendor-access/web/src/App.tsx +573 -0
- package/templates/vendor-access/web/src/lib/forge.ts +20 -0
- package/templates/vendor-access/web/src/main.tsx +205 -0
- package/templates/vendor-access/web/src/styles.css +682 -0
- package/templates/vendor-access/web/tsconfig.json +18 -0
- package/templates/vendor-access/web/vite.config.ts +36 -0
- package/src/forge/_generated/actionSubscriptions.json +0 -2
- package/src/forge/_generated/actionSubscriptions.ts +0 -10
- package/src/forge/_generated/agentAdapterManifest.json +0 -2
- package/src/forge/_generated/agentAdapterManifest.ts +0 -73
- package/src/forge/_generated/agentContract.json +0 -2
- package/src/forge/_generated/agentContract.ts +0 -7829
- package/src/forge/_generated/agentQuickstart.md +0 -34
- package/src/forge/_generated/agentTools.json +0 -2
- package/src/forge/_generated/agentTools.md +0 -16
- package/src/forge/_generated/agentTools.ts +0 -12
- package/src/forge/_generated/aiContext.ts +0 -125
- package/src/forge/_generated/aiModels.json +0 -2
- package/src/forge/_generated/aiModels.ts +0 -51
- package/src/forge/_generated/aiProviders.json +0 -2
- package/src/forge/_generated/aiProviders.ts +0 -23
- package/src/forge/_generated/aiRegistry.json +0 -2
- package/src/forge/_generated/aiRegistry.ts +0 -31
- package/src/forge/_generated/api.json +0 -2
- package/src/forge/_generated/api.ts +0 -8
- package/src/forge/_generated/appGraph.json +0 -2
- package/src/forge/_generated/appGraph.ts +0 -14937
- package/src/forge/_generated/appMap.md +0 -55
- package/src/forge/_generated/artifactManifest.json +0 -2
- package/src/forge/_generated/artifactManifest.ts +0 -7
- package/src/forge/_generated/authClaims.json +0 -2
- package/src/forge/_generated/authClaims.ts +0 -13
- package/src/forge/_generated/authConfig.json +0 -2
- package/src/forge/_generated/authConfig.ts +0 -17
- package/src/forge/_generated/authContext.ts +0 -23
- package/src/forge/_generated/authRegistry.json +0 -2
- package/src/forge/_generated/authRegistry.ts +0 -25
- package/src/forge/_generated/buildInfo.json +0 -2
- package/src/forge/_generated/buildInfo.ts +0 -9
- package/src/forge/_generated/capabilityMap.json +0 -2
- package/src/forge/_generated/capabilityMap.md +0 -15
- package/src/forge/_generated/capabilityMap.ts +0 -17
- package/src/forge/_generated/client.ts +0 -282
- package/src/forge/_generated/clientApi.ts +0 -9
- package/src/forge/_generated/clientManifest.json +0 -2
- package/src/forge/_generated/clientManifest.ts +0 -39
- package/src/forge/_generated/clientTypes.ts +0 -78
- package/src/forge/_generated/configRegistry.json +0 -2
- package/src/forge/_generated/configRegistry.ts +0 -4
- package/src/forge/_generated/dataGraph.json +0 -2
- package/src/forge/_generated/dataGraph.ts +0 -8
- package/src/forge/_generated/db.json +0 -2
- package/src/forge/_generated/db.ts +0 -2
- package/src/forge/_generated/dbSecurityManifest.json +0 -2
- package/src/forge/_generated/dbSecurityManifest.ts +0 -15
- package/src/forge/_generated/dbSessionContext.json +0 -2
- package/src/forge/_generated/dbSessionContext.ts +0 -39
- package/src/forge/_generated/deployManifest.json +0 -2
- package/src/forge/_generated/deployManifest.ts +0 -14
- package/src/forge/_generated/devManifest.json +0 -2
- package/src/forge/_generated/devManifest.ts +0 -62
- package/src/forge/_generated/envSchema.json +0 -2
- package/src/forge/_generated/envSchema.ts +0 -59
- package/src/forge/_generated/frontendGraph.json +0 -2
- package/src/forge/_generated/frontendGraph.ts +0 -27
- package/src/forge/_generated/importGuards.json +0 -2
- package/src/forge/_generated/importGuards.ts +0 -686
- package/src/forge/_generated/index.ts +0 -68
- package/src/forge/_generated/liveProductionManifest.json +0 -2
- package/src/forge/_generated/liveProductionManifest.ts +0 -23
- package/src/forge/_generated/liveProtocol.json +0 -2
- package/src/forge/_generated/liveProtocol.ts +0 -21
- package/src/forge/_generated/liveQueryRegistry.json +0 -2
- package/src/forge/_generated/liveQueryRegistry.ts +0 -9
- package/src/forge/_generated/liveTransportConfig.json +0 -2
- package/src/forge/_generated/liveTransportConfig.ts +0 -19
- package/src/forge/_generated/makeRegistry.json +0 -2
- package/src/forge/_generated/makeRegistry.ts +0 -177
- package/src/forge/_generated/makeTemplates.json +0 -2
- package/src/forge/_generated/makeTemplates.ts +0 -66
- package/src/forge/_generated/mockMap.json +0 -2
- package/src/forge/_generated/mockMap.ts +0 -7
- package/src/forge/_generated/operationPlaybooks.md +0 -167
- package/src/forge/_generated/packageGraph.json +0 -2
- package/src/forge/_generated/packageGraph.ts +0 -249334
- package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
- package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
- package/src/forge/_generated/permissionMatrix.json +0 -2
- package/src/forge/_generated/permissionMatrix.ts +0 -7
- package/src/forge/_generated/policyRegistry.json +0 -2
- package/src/forge/_generated/policyRegistry.ts +0 -11
- package/src/forge/_generated/queryRegistry.json +0 -2
- package/src/forge/_generated/queryRegistry.ts +0 -9
- package/src/forge/_generated/react.d.ts +0 -22
- package/src/forge/_generated/react.ts +0 -29
- package/src/forge/_generated/reactManifest.json +0 -2
- package/src/forge/_generated/reactManifest.ts +0 -19
- package/src/forge/_generated/rlsPolicies.json +0 -2
- package/src/forge/_generated/rlsPolicies.sql +0 -34
- package/src/forge/_generated/rlsPolicies.ts +0 -6
- package/src/forge/_generated/runtimeGraph.json +0 -2
- package/src/forge/_generated/runtimeGraph.ts +0 -8
- package/src/forge/_generated/runtimeMatrix.json +0 -2
- package/src/forge/_generated/runtimeMatrix.ts +0 -334130
- package/src/forge/_generated/runtimeRegistry.ts +0 -2
- package/src/forge/_generated/runtimeRules.md +0 -91
- package/src/forge/_generated/secretRegistry.json +0 -2
- package/src/forge/_generated/secretRegistry.ts +0 -50
- package/src/forge/_generated/secretsContext.ts +0 -11
- package/src/forge/_generated/serverApi.ts +0 -10
- package/src/forge/_generated/sourceMapManifest.json +0 -2
- package/src/forge/_generated/sourceMapManifest.ts +0 -7
- package/src/forge/_generated/sqlPlan.json +0 -2
- package/src/forge/_generated/sqlPlan.ts +0 -88
- package/src/forge/_generated/subscriptionManifest.json +0 -2
- package/src/forge/_generated/subscriptionManifest.ts +0 -7
- package/src/forge/_generated/symbolicationManifest.json +0 -2
- package/src/forge/_generated/symbolicationManifest.ts +0 -17
- package/src/forge/_generated/telemetryRegistry.json +0 -2
- package/src/forge/_generated/telemetryRegistry.ts +0 -9
- package/src/forge/_generated/telemetrySinks.json +0 -2
- package/src/forge/_generated/telemetrySinks.ts +0 -11
- package/src/forge/_generated/tenantScope.json +0 -2
- package/src/forge/_generated/tenantScope.ts +0 -8
- package/src/forge/_generated/testGraph.json +0 -2
- package/src/forge/_generated/testGraph.ts +0 -3452
- package/src/forge/_generated/testPlanRegistry.json +0 -2
- package/src/forge/_generated/testPlanRegistry.ts +0 -33
- package/src/forge/_generated/uiRoutes.json +0 -2
- package/src/forge/_generated/uiRoutes.ts +0 -16
- package/src/forge/_generated/uiScenarios.json +0 -2
- package/src/forge/_generated/uiScenarios.ts +0 -30
- package/src/forge/_generated/uiTestManifest.json +0 -2
- package/src/forge/_generated/uiTestManifest.ts +0 -27
- package/src/forge/_generated/workflowRegistry.json +0 -2
- package/src/forge/_generated/workflowRegistry.ts +0 -9
- package/src/forge/_generated/workflowSubscriptions.json +0 -2
- package/src/forge/_generated/workflowSubscriptions.ts +0 -10
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import { nodeFileSystem } from "../compiler/fs/index.ts";
|
|
2
|
-
import {
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
3
4
|
import { stripDeterministicHeader } from "../compiler/primitives/header.ts";
|
|
4
5
|
import { classify } from "../compiler/classifier/classify.ts";
|
|
5
6
|
import { buildRuntimeMatrix } from "../compiler/classifier/runtime-matrix.ts";
|
|
7
|
+
import {
|
|
8
|
+
FORGE_DB_EMPTY_TIMESTAMP_LITERAL,
|
|
9
|
+
FORGE_RELEASE_NPM_DIST_TAG_CHECK_FAILED,
|
|
10
|
+
FORGE_RELEASE_NPM_DIST_TAG_STALE,
|
|
11
|
+
FORGE_RELEASE_PACKAGE_PACK_FAILED,
|
|
12
|
+
} from "../compiler/diagnostics/codes.ts";
|
|
6
13
|
import { createDiagnostic } from "../compiler/diagnostics/create.ts";
|
|
7
14
|
import { forgeAdd } from "../compiler/integration/add.ts";
|
|
8
15
|
import { checkImportGuards } from "../compiler/guards/check-import-guards.ts";
|
|
9
16
|
import { checkDirectProcessEnvUsage } from "../compiler/guards/check-process-env.ts";
|
|
10
17
|
import { checkAiUsageInApp } from "../compiler/guards/check-ai-usage.ts";
|
|
11
18
|
import { checkQueryUsageInApp } from "../compiler/guards/check-query-usage.ts";
|
|
19
|
+
import { buildDataGraph } from "../compiler/data-graph/build.ts";
|
|
20
|
+
import { buildSqlPlan } from "../compiler/data-graph/sql/ddl.ts";
|
|
12
21
|
import { loadSecretRegistry } from "../runtime/secrets/check.ts";
|
|
13
22
|
import { run } from "../compiler/orchestrator/run.ts";
|
|
14
23
|
import {
|
|
@@ -29,10 +38,14 @@ import type {
|
|
|
29
38
|
} from "../compiler/types/cli.ts";
|
|
30
39
|
import type { RuntimeMatrix } from "../compiler/types/runtime-matrix.ts";
|
|
31
40
|
import type { FrontendGraph } from "../compiler/types/frontend-graph.ts";
|
|
41
|
+
import type { DataGraph } from "../compiler/types/data-graph.ts";
|
|
42
|
+
import type { SqlPlan } from "../compiler/data-graph/sql/types.ts";
|
|
43
|
+
import type { TableMapEntry } from "../compiler/data-graph/sql/serialize.ts";
|
|
32
44
|
import { GENERATED_DIR } from "../compiler/emitter/constants.ts";
|
|
33
45
|
import {
|
|
34
46
|
attachFailureKind,
|
|
35
47
|
buildAddJson,
|
|
48
|
+
buildCheckJson,
|
|
36
49
|
buildGenerateJson,
|
|
37
50
|
buildInspectJson,
|
|
38
51
|
formatJsonResult,
|
|
@@ -44,6 +57,28 @@ import {
|
|
|
44
57
|
} from "./output.ts";
|
|
45
58
|
import { INSPECT_TARGETS, TOP_LEVEL_COMMANDS, type ForgeCommand } from "./parse.ts";
|
|
46
59
|
import { runVerifyCommand } from "./verify.ts";
|
|
60
|
+
import {
|
|
61
|
+
buildExternalServiceGraph,
|
|
62
|
+
importExternalManifest,
|
|
63
|
+
readExternalManifestFile,
|
|
64
|
+
} from "../compiler/external-manifest/registry.ts";
|
|
65
|
+
import {
|
|
66
|
+
resolveExternalQualifiedName,
|
|
67
|
+
runExternalEntry,
|
|
68
|
+
} from "../runtime/external/bridge.ts";
|
|
69
|
+
import {
|
|
70
|
+
formatCompilerBenchHuman,
|
|
71
|
+
formatCompilerBenchJson,
|
|
72
|
+
runCompilerBenchCommand,
|
|
73
|
+
} from "../bench.ts";
|
|
74
|
+
import {
|
|
75
|
+
formatCairHuman,
|
|
76
|
+
formatCairJson,
|
|
77
|
+
runCairCommand,
|
|
78
|
+
} from "../cair/index.ts";
|
|
79
|
+
import { runRepositoryCommand } from "./repository.ts";
|
|
80
|
+
import { readRepositoryManifest, resolveRepositoryRoot } from "../repository-manifest/index.ts";
|
|
81
|
+
import { uniqueNextActions } from "./next-actions.ts";
|
|
47
82
|
import {
|
|
48
83
|
formatRunJson,
|
|
49
84
|
formatRunListHuman,
|
|
@@ -51,6 +86,41 @@ import {
|
|
|
51
86
|
runRunCommand,
|
|
52
87
|
} from "./run.ts";
|
|
53
88
|
import { runDevCommand } from "./dev.ts";
|
|
89
|
+
import {
|
|
90
|
+
formatHandoffHuman,
|
|
91
|
+
formatHandoffJson,
|
|
92
|
+
runHandoffCommand,
|
|
93
|
+
} from "./handoff.ts";
|
|
94
|
+
import {
|
|
95
|
+
formatStudioAttachHuman,
|
|
96
|
+
formatStudioAttachJson,
|
|
97
|
+
formatStudioBridgeEventJson,
|
|
98
|
+
formatStudioBridgeHuman,
|
|
99
|
+
formatStudioBridgeJson,
|
|
100
|
+
formatStudioCodexServerHuman,
|
|
101
|
+
formatStudioCodexServerJson,
|
|
102
|
+
formatStudioDoctorHuman,
|
|
103
|
+
formatStudioDoctorJson,
|
|
104
|
+
formatStudioOpenHuman,
|
|
105
|
+
formatStudioOpenJson,
|
|
106
|
+
formatStudioSnapshotHuman,
|
|
107
|
+
formatStudioSnapshotJson,
|
|
108
|
+
formatStudioWatchHuman,
|
|
109
|
+
formatStudioWatchJson,
|
|
110
|
+
runStudioAttachCommand,
|
|
111
|
+
runStudioBridgeCommand,
|
|
112
|
+
runStudioBridgeLoop,
|
|
113
|
+
runStudioCodexServerCommand,
|
|
114
|
+
runStudioDoctorCommand,
|
|
115
|
+
runStudioOpenCommand,
|
|
116
|
+
runStudioSnapshotCommand,
|
|
117
|
+
runStudioWatchCommand,
|
|
118
|
+
runStudioWatchLoop,
|
|
119
|
+
} from "./studio.ts";
|
|
120
|
+
import {
|
|
121
|
+
formatChangedHuman,
|
|
122
|
+
runChangedCommand,
|
|
123
|
+
} from "./changed.ts";
|
|
54
124
|
import { initializeRuntimeEnv } from "../runtime/context/create-context.ts";
|
|
55
125
|
import { formatDbHuman, formatDbJson, runDbCommand } from "./db.ts";
|
|
56
126
|
import { formatOutboxHuman, formatOutboxJson, runOutboxCommand } from "./outbox.ts";
|
|
@@ -64,6 +134,35 @@ import {
|
|
|
64
134
|
formatTelemetryJson,
|
|
65
135
|
runTelemetryCommand,
|
|
66
136
|
} from "./telemetry.ts";
|
|
137
|
+
import {
|
|
138
|
+
formatDeltaExplainHuman,
|
|
139
|
+
formatDeltaExplainJson,
|
|
140
|
+
formatDeltaCompactHuman,
|
|
141
|
+
formatDeltaCompactJson,
|
|
142
|
+
formatDeltaDoctorHuman,
|
|
143
|
+
formatDeltaDoctorJson,
|
|
144
|
+
formatDeltaExportHuman,
|
|
145
|
+
formatDeltaExportJson,
|
|
146
|
+
formatDeltaPruneHuman,
|
|
147
|
+
formatDeltaPruneJson,
|
|
148
|
+
formatDeltaRepairHuman,
|
|
149
|
+
formatDeltaRepairJson,
|
|
150
|
+
formatDeltaStatusHuman,
|
|
151
|
+
formatDeltaStatusJson,
|
|
152
|
+
formatDeltaSessionHuman,
|
|
153
|
+
formatDeltaSessionJson,
|
|
154
|
+
formatDeltaTimelineHuman,
|
|
155
|
+
formatDeltaTimelineJson,
|
|
156
|
+
runDeltaExplain,
|
|
157
|
+
runDeltaCompact,
|
|
158
|
+
runDeltaDoctor,
|
|
159
|
+
runDeltaExport,
|
|
160
|
+
runDeltaPrune,
|
|
161
|
+
runDeltaRepair,
|
|
162
|
+
runDeltaSessionCommand,
|
|
163
|
+
runDeltaStatus,
|
|
164
|
+
runDeltaTimeline,
|
|
165
|
+
} from "../delta/index.ts";
|
|
67
166
|
import {
|
|
68
167
|
formatPolicyHuman,
|
|
69
168
|
formatPolicyJson,
|
|
@@ -78,11 +177,12 @@ import {
|
|
|
78
177
|
runSecretsCommand,
|
|
79
178
|
} from "./secrets.ts";
|
|
80
179
|
import { formatAiHuman, formatAiJson, runAiCommand } from "./ai.ts";
|
|
81
|
-
import { formatNewHuman, runNewCommand } from "./new.ts";
|
|
180
|
+
import { formatNewHuman, formatNewJson, runNewCommand } from "./new.ts";
|
|
82
181
|
import { formatBuildHuman, runBuildCommand } from "./build.ts";
|
|
83
182
|
import { runServeCommand } from "./serve.ts";
|
|
84
183
|
import { runWorkerCommand } from "./worker.ts";
|
|
85
|
-
import { formatSelfHostHuman, runSelfHostCommand } from "./self-host.ts";
|
|
184
|
+
import { formatSelfHostHuman, runSelfHostCommand, type SelfHostCommandResult } from "./self-host.ts";
|
|
185
|
+
import { formatDocsCheckHuman, runDocsCheckCommand, type DocsCheckResult } from "./docs.ts";
|
|
86
186
|
import {
|
|
87
187
|
formatAgentContractHuman,
|
|
88
188
|
runAgentContractPrint,
|
|
@@ -90,7 +190,13 @@ import {
|
|
|
90
190
|
import {
|
|
91
191
|
formatDoctorHuman,
|
|
92
192
|
formatDoctorJson,
|
|
193
|
+
formatPgliteDoctorHuman,
|
|
194
|
+
formatPgliteDoctorJson,
|
|
195
|
+
formatRuntimeDoctorHuman,
|
|
196
|
+
formatRuntimeDoctorJson,
|
|
197
|
+
runPgliteDoctorCommand,
|
|
93
198
|
runDoctorCommand,
|
|
199
|
+
runRuntimeDoctorCommand,
|
|
94
200
|
} from "./doctor.ts";
|
|
95
201
|
import {
|
|
96
202
|
formatWindowsDoctorHuman,
|
|
@@ -101,6 +207,47 @@ import {
|
|
|
101
207
|
runWindowsSetupCommand,
|
|
102
208
|
} from "./windows.ts";
|
|
103
209
|
import { formatAuthHuman, formatAuthJson, runAuthCommand } from "./auth.ts";
|
|
210
|
+
import {
|
|
211
|
+
formatAuthMdHuman,
|
|
212
|
+
formatAuthMdJson,
|
|
213
|
+
runAuthMdCommand,
|
|
214
|
+
} from "./authmd.ts";
|
|
215
|
+
import {
|
|
216
|
+
formatWorkOSHuman,
|
|
217
|
+
formatWorkOSJson,
|
|
218
|
+
runWorkOSCommand,
|
|
219
|
+
} from "./workos.ts";
|
|
220
|
+
import {
|
|
221
|
+
formatDeployHuman,
|
|
222
|
+
formatDeployJson,
|
|
223
|
+
type DeployCommandResult,
|
|
224
|
+
runDeployCommand,
|
|
225
|
+
} from "./deploy.ts";
|
|
226
|
+
import {
|
|
227
|
+
formatFieldTestHuman,
|
|
228
|
+
formatFieldTestJson,
|
|
229
|
+
runFieldTestCommand,
|
|
230
|
+
} from "./field-test.ts";
|
|
231
|
+
import {
|
|
232
|
+
formatGoldenPathHuman,
|
|
233
|
+
formatGoldenPathJson,
|
|
234
|
+
runGoldenPathCommand,
|
|
235
|
+
} from "./golden-path.ts";
|
|
236
|
+
import {
|
|
237
|
+
formatSeedHuman,
|
|
238
|
+
formatSeedJson,
|
|
239
|
+
runSeedCommand,
|
|
240
|
+
} from "./seed.ts";
|
|
241
|
+
import {
|
|
242
|
+
formatLastHuman,
|
|
243
|
+
formatLastJson,
|
|
244
|
+
runLastCommand,
|
|
245
|
+
} from "./last-run.ts";
|
|
246
|
+
import {
|
|
247
|
+
formatBaselineHuman,
|
|
248
|
+
formatBaselineJson,
|
|
249
|
+
runBaselineCommand,
|
|
250
|
+
} from "./baseline.ts";
|
|
104
251
|
import { formatRlsHuman, formatRlsJson, runRlsCommand } from "./rls.ts";
|
|
105
252
|
import {
|
|
106
253
|
formatSecurityHuman,
|
|
@@ -111,6 +258,7 @@ import { formatDepsHuman, formatDepsJson, runDepsCommand } from "./deps.ts";
|
|
|
111
258
|
import {
|
|
112
259
|
formatReleaseHuman,
|
|
113
260
|
formatReleaseJson,
|
|
261
|
+
type ReleaseCommandResult,
|
|
114
262
|
runReleaseCommand,
|
|
115
263
|
} from "./release.ts";
|
|
116
264
|
import { formatMakeHuman, formatMakeJson, runMakeCommand } from "./make.ts";
|
|
@@ -132,11 +280,20 @@ import {
|
|
|
132
280
|
formatForgeDoJson,
|
|
133
281
|
runForgeDoCommand,
|
|
134
282
|
} from "../intent/index.ts";
|
|
283
|
+
import {
|
|
284
|
+
formatBrownfieldImportHuman,
|
|
285
|
+
formatBrownfieldImportJson,
|
|
286
|
+
inspectBrownfieldImport,
|
|
287
|
+
runBrownfieldImportCommand,
|
|
288
|
+
} from "../brownfield-import/index.ts";
|
|
135
289
|
import {
|
|
136
290
|
formatAgentHuman,
|
|
137
291
|
formatAgentJson,
|
|
138
292
|
runAgentCommand,
|
|
139
293
|
} from "../agent-adapters/index.ts";
|
|
294
|
+
import { runMcpServe } from "../agent-memory/mcp.ts";
|
|
295
|
+
import { runFabricCommand } from "./fabric.ts";
|
|
296
|
+
import { runEvolutionCommand } from "./evolution.ts";
|
|
140
297
|
import {
|
|
141
298
|
formatReviewHuman,
|
|
142
299
|
formatReviewJson,
|
|
@@ -161,6 +318,10 @@ import { runQuery } from "../runtime/query/run-query.ts";
|
|
|
161
318
|
import { resolveAuthFromCli } from "../runtime/auth/resolve.ts";
|
|
162
319
|
import { getActiveDbAdapter } from "../runtime/executor.ts";
|
|
163
320
|
import { CLI_VERSION, FORGEOS_VERSION } from "../version.ts";
|
|
321
|
+
import { authoredChangePaths, type CategorizedFileSummary } from "../workspace/change-summary.ts";
|
|
322
|
+
import { forgeCliCommandsForWorkspace } from "../workspace/forge-cli.ts";
|
|
323
|
+
import { buildWorkspaceGitSummary } from "../workspace/git-summary.ts";
|
|
324
|
+
import { startCommandHeartbeat } from "./progress.ts";
|
|
164
325
|
|
|
165
326
|
function readGeneratedJson<T>(workspaceRoot: string, relative: string): T | null {
|
|
166
327
|
const absolute = join(workspaceRoot, relative);
|
|
@@ -244,9 +405,14 @@ function buildFrameworkInspect(workspaceRoot: string): Record<string, unknown> {
|
|
|
244
405
|
topLevelCommands: [...TOP_LEVEL_COMMANDS],
|
|
245
406
|
inspectTargets: [...INSPECT_TARGETS],
|
|
246
407
|
preferredEntryPoints: [
|
|
408
|
+
"forge status --json",
|
|
409
|
+
"forge changed --json",
|
|
410
|
+
"forge agent onboard --target codex --json",
|
|
247
411
|
"forge do <objective> --json",
|
|
248
412
|
"forge dev --once --json",
|
|
413
|
+
"forge inspect all --brief --json",
|
|
249
414
|
"forge inspect all --json",
|
|
415
|
+
"forge agent print-context --json",
|
|
250
416
|
"forge inspect framework --json",
|
|
251
417
|
"forge verify --strict",
|
|
252
418
|
],
|
|
@@ -276,13 +442,571 @@ function buildFrameworkInspect(workspaceRoot: string): Record<string, unknown> {
|
|
|
276
442
|
};
|
|
277
443
|
}
|
|
278
444
|
|
|
445
|
+
function readGeneratedArtifactStatus(workspaceRoot: string): Array<{ name: string; path: string; present: boolean }> {
|
|
446
|
+
const artifacts = [
|
|
447
|
+
["app", `${GENERATED_DIR}/appGraph.json`],
|
|
448
|
+
["data", `${GENERATED_DIR}/dataGraph.json`],
|
|
449
|
+
["sql", `${GENERATED_DIR}/sqlPlan.json`],
|
|
450
|
+
["db", `${GENERATED_DIR}/db.json`],
|
|
451
|
+
["runtime", `${GENERATED_DIR}/runtimeGraph.json`],
|
|
452
|
+
["frontend", `${GENERATED_DIR}/frontendGraph.json`],
|
|
453
|
+
["client", `${GENERATED_DIR}/clientManifest.json`],
|
|
454
|
+
["agent-contract", `${GENERATED_DIR}/agentContract.json`],
|
|
455
|
+
["agent-adapters", `${GENERATED_DIR}/agentAdapterManifest.json`],
|
|
456
|
+
["capability-map", `${GENERATED_DIR}/capabilityMap.json`],
|
|
457
|
+
["test-graph", `${GENERATED_DIR}/testGraph.json`],
|
|
458
|
+
["agents-md", "AGENTS.md"],
|
|
459
|
+
["forge-lock", "forge.lock"],
|
|
460
|
+
] as const;
|
|
461
|
+
|
|
462
|
+
return artifacts.map(([name, path]) => ({
|
|
463
|
+
name,
|
|
464
|
+
path,
|
|
465
|
+
present: hasPath(workspaceRoot, path),
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function buildInspectSummary(workspaceRoot: string): Record<string, unknown> {
|
|
470
|
+
const framework = buildFrameworkInspect(workspaceRoot);
|
|
471
|
+
const dataGraph = readGeneratedJson<DataGraph>(workspaceRoot, `${GENERATED_DIR}/dataGraph.json`);
|
|
472
|
+
const frontend = readGeneratedJson<FrontendGraph>(workspaceRoot, `${GENERATED_DIR}/frontendGraph.json`);
|
|
473
|
+
const agentAdapters = readGeneratedJson<{ targets?: Array<{ name?: string; files?: string[]; default?: boolean; optional?: boolean }> }>(
|
|
474
|
+
workspaceRoot,
|
|
475
|
+
`${GENERATED_DIR}/agentAdapterManifest.json`,
|
|
476
|
+
);
|
|
477
|
+
const artifacts = readGeneratedArtifactStatus(workspaceRoot);
|
|
478
|
+
const missingArtifacts = artifacts.filter((artifact) => !artifact.present);
|
|
479
|
+
|
|
480
|
+
return {
|
|
481
|
+
schemaVersion: "0.1.0",
|
|
482
|
+
summary: {
|
|
483
|
+
project: (framework.project as Record<string, unknown> | undefined)?.name ?? "unknown",
|
|
484
|
+
tables: dataGraph?.tables.length ?? 0,
|
|
485
|
+
frontendPresent: frontend?.present === true,
|
|
486
|
+
routes: frontend?.routes.length ?? 0,
|
|
487
|
+
agentTargets: agentAdapters?.targets?.map((target) => target.name).filter(Boolean) ?? [],
|
|
488
|
+
missingArtifacts: missingArtifacts.length,
|
|
489
|
+
},
|
|
490
|
+
artifacts,
|
|
491
|
+
nextActions: [
|
|
492
|
+
"forge inspect schema --json",
|
|
493
|
+
"forge inspect handoff --json",
|
|
494
|
+
"forge inspect drift --json",
|
|
495
|
+
"forge check --json",
|
|
496
|
+
],
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function buildInspectBrief(workspaceRoot: string): Record<string, unknown> {
|
|
501
|
+
const summary = buildInspectSummary(workspaceRoot);
|
|
502
|
+
const framework = buildFrameworkInspect(workspaceRoot);
|
|
503
|
+
const cli = framework.cli as { preferredEntryPoints?: string[]; inspectTargets?: string[] } | undefined;
|
|
504
|
+
const artifacts = readGeneratedArtifactStatus(workspaceRoot);
|
|
505
|
+
const missingArtifacts = artifacts.filter((artifact) => !artifact.present);
|
|
506
|
+
return {
|
|
507
|
+
schemaVersion: "0.1.0",
|
|
508
|
+
brief: true,
|
|
509
|
+
payload: {
|
|
510
|
+
mode: "brief",
|
|
511
|
+
purpose: "orientation",
|
|
512
|
+
includes: ["summary", "entrypoints", "refs", "artifact counts"],
|
|
513
|
+
omitted: ["schema table details", "framework module lists", "generated registries"],
|
|
514
|
+
fullCommand: "forge inspect all --full --json",
|
|
515
|
+
compactCommand: "forge inspect all --json",
|
|
516
|
+
},
|
|
517
|
+
summary: summary.summary,
|
|
518
|
+
entrypoints: {
|
|
519
|
+
preferred: cli?.preferredEntryPoints ?? [],
|
|
520
|
+
inspect: [
|
|
521
|
+
"forge inspect summary --json",
|
|
522
|
+
"forge inspect schema --json",
|
|
523
|
+
"forge inspect handoff --json",
|
|
524
|
+
"forge inspect all --json",
|
|
525
|
+
"forge inspect all --full --json",
|
|
526
|
+
],
|
|
527
|
+
},
|
|
528
|
+
refs: [
|
|
529
|
+
"AGENTS.md",
|
|
530
|
+
`${GENERATED_DIR}/agentContract.json`,
|
|
531
|
+
`${GENERATED_DIR}/appMap.md`,
|
|
532
|
+
`${GENERATED_DIR}/runtimeRules.md`,
|
|
533
|
+
`${GENERATED_DIR}/operationPlaybooks.md`,
|
|
534
|
+
`${GENERATED_DIR}/frontendGraph.json`,
|
|
535
|
+
],
|
|
536
|
+
artifacts: {
|
|
537
|
+
total: artifacts.length,
|
|
538
|
+
present: artifacts.length - missingArtifacts.length,
|
|
539
|
+
missing: missingArtifacts,
|
|
540
|
+
},
|
|
541
|
+
nextActions: [
|
|
542
|
+
"forge status --json",
|
|
543
|
+
"forge changed --json",
|
|
544
|
+
"forge agent onboard --target codex --json",
|
|
545
|
+
"forge dev --once --json",
|
|
546
|
+
"forge inspect all --json",
|
|
547
|
+
],
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function buildSchemaInspect(workspaceRoot: string): { data: Record<string, unknown>; errors: ReturnType<typeof createDiagnostic>[] } {
|
|
552
|
+
const dataGraph = readGeneratedJson<DataGraph>(workspaceRoot, `${GENERATED_DIR}/dataGraph.json`);
|
|
553
|
+
const sqlPlan = readGeneratedJson<SqlPlan>(workspaceRoot, `${GENERATED_DIR}/sqlPlan.json`);
|
|
554
|
+
const db = readGeneratedJson<{ tableMap?: Record<string, TableMapEntry> }>(workspaceRoot, `${GENERATED_DIR}/db.json`);
|
|
555
|
+
const errors: ReturnType<typeof createDiagnostic>[] = [];
|
|
556
|
+
|
|
557
|
+
if (!dataGraph) {
|
|
558
|
+
errors.push(createDiagnostic({
|
|
559
|
+
severity: "error",
|
|
560
|
+
code: "FORGE_INSPECT_MISSING",
|
|
561
|
+
message: `missing generated artifact: ${GENERATED_DIR}/dataGraph.json; run forge generate first`,
|
|
562
|
+
file: `${GENERATED_DIR}/dataGraph.json`,
|
|
563
|
+
}));
|
|
564
|
+
}
|
|
565
|
+
if (!sqlPlan) {
|
|
566
|
+
errors.push(createDiagnostic({
|
|
567
|
+
severity: "error",
|
|
568
|
+
code: "FORGE_INSPECT_MISSING",
|
|
569
|
+
message: `missing generated artifact: ${GENERATED_DIR}/sqlPlan.json; run forge generate first`,
|
|
570
|
+
file: `${GENERATED_DIR}/sqlPlan.json`,
|
|
571
|
+
}));
|
|
572
|
+
}
|
|
573
|
+
if (!db?.tableMap) {
|
|
574
|
+
errors.push(createDiagnostic({
|
|
575
|
+
severity: "error",
|
|
576
|
+
code: "FORGE_INSPECT_MISSING",
|
|
577
|
+
message: `missing generated artifact: ${GENERATED_DIR}/db.json; run forge generate first`,
|
|
578
|
+
file: `${GENERATED_DIR}/db.json`,
|
|
579
|
+
}));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const sqlByAccessName = new Map(
|
|
583
|
+
(sqlPlan?.tables ?? [])
|
|
584
|
+
.filter((table) => table.kind === "create_table")
|
|
585
|
+
.map((table) => [table.accessName ?? table.table ?? "", table]),
|
|
586
|
+
);
|
|
587
|
+
const tableMap = db?.tableMap ?? {};
|
|
588
|
+
const dataGraphDiagnostics = dataGraph?.diagnostics ?? [];
|
|
589
|
+
const sqlPlanDiagnostics = sqlPlan?.diagnostics ?? [];
|
|
590
|
+
const tables = (dataGraph?.tables ?? []).map((table) => {
|
|
591
|
+
const sql = sqlByAccessName.get(table.name);
|
|
592
|
+
const runtime = sql?.table ? tableMap[sql.table] ?? tableMap[table.name] : tableMap[table.name];
|
|
593
|
+
const sourceFields = table.fields.map((field) => field.name).sort();
|
|
594
|
+
const sqlColumns = (sql?.columns ?? []).map((column) => ({
|
|
595
|
+
name: column.name,
|
|
596
|
+
fieldName: column.fieldName,
|
|
597
|
+
sqlType: column.sqlType,
|
|
598
|
+
primaryKey: column.primaryKey === true,
|
|
599
|
+
}));
|
|
600
|
+
const runtimeFields = (runtime?.columns ?? []).map((column) => column.fieldName ?? column.name).sort();
|
|
601
|
+
const missingRuntimeFields = sourceFields.filter((field) => !runtimeFields.includes(field));
|
|
602
|
+
|
|
603
|
+
return {
|
|
604
|
+
name: table.name,
|
|
605
|
+
file: table.file,
|
|
606
|
+
sourceFields,
|
|
607
|
+
sqlTable: sql?.table ?? null,
|
|
608
|
+
sqlColumns,
|
|
609
|
+
runtimeAccessors: Object.entries(tableMap)
|
|
610
|
+
.filter(([, entry]) => entry.tableName === (sql?.table ?? table.name))
|
|
611
|
+
.map(([name]) => name)
|
|
612
|
+
.sort(),
|
|
613
|
+
missingRuntimeFields,
|
|
614
|
+
};
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
return {
|
|
618
|
+
data: {
|
|
619
|
+
schemaVersion: "0.1.0",
|
|
620
|
+
summary: {
|
|
621
|
+
tables: tables.length,
|
|
622
|
+
missingRuntimeFields: tables.reduce(
|
|
623
|
+
(count, table) => count + (table.missingRuntimeFields as string[]).length,
|
|
624
|
+
0,
|
|
625
|
+
),
|
|
626
|
+
diagnostics: dataGraphDiagnostics.length + sqlPlanDiagnostics.length + errors.length,
|
|
627
|
+
},
|
|
628
|
+
tables,
|
|
629
|
+
diagnostics: [
|
|
630
|
+
...dataGraphDiagnostics,
|
|
631
|
+
...sqlPlanDiagnostics,
|
|
632
|
+
...errors,
|
|
633
|
+
],
|
|
634
|
+
},
|
|
635
|
+
errors,
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function buildDriftInspect(workspaceRoot: string): Record<string, unknown> {
|
|
640
|
+
const schema = buildSchemaInspect(workspaceRoot);
|
|
641
|
+
const artifacts = readGeneratedArtifactStatus(workspaceRoot);
|
|
642
|
+
const missingArtifacts = artifacts.filter((artifact) => !artifact.present);
|
|
643
|
+
const tableDrift = ((schema.data.tables as Array<{ name: string; missingRuntimeFields: string[] }> | undefined) ?? [])
|
|
644
|
+
.filter((table) => table.missingRuntimeFields.length > 0)
|
|
645
|
+
.map((table) => ({
|
|
646
|
+
table: table.name,
|
|
647
|
+
missingRuntimeFields: table.missingRuntimeFields,
|
|
648
|
+
suggestedCommand: "forge generate && forge check --json",
|
|
649
|
+
}));
|
|
650
|
+
const staleAgentContext = hasPath(workspaceRoot, ".forge/agent/context.json")
|
|
651
|
+
? "run forge agent check --target codex --json or forge agent export --target codex"
|
|
652
|
+
: null;
|
|
653
|
+
|
|
654
|
+
return {
|
|
655
|
+
schemaVersion: "0.1.0",
|
|
656
|
+
summary: {
|
|
657
|
+
ok: missingArtifacts.length === 0 && tableDrift.length === 0,
|
|
658
|
+
missingArtifacts: missingArtifacts.length,
|
|
659
|
+
tableDrift: tableDrift.length,
|
|
660
|
+
agentContextPresent: hasPath(workspaceRoot, ".forge/agent/context.json"),
|
|
661
|
+
},
|
|
662
|
+
missingArtifacts,
|
|
663
|
+
tableDrift,
|
|
664
|
+
agentContext: staleAgentContext,
|
|
665
|
+
nextActions: [
|
|
666
|
+
...(missingArtifacts.length > 0 || tableDrift.length > 0 ? ["forge generate", "forge check --json"] : []),
|
|
667
|
+
"forge agent check --target codex --json",
|
|
668
|
+
],
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
function buildHandoffInspect(workspaceRoot: string): Record<string, unknown> {
|
|
673
|
+
const manifest = readGeneratedJson<{
|
|
674
|
+
targets?: Array<{
|
|
675
|
+
name?: string;
|
|
676
|
+
files?: string[];
|
|
677
|
+
default?: boolean;
|
|
678
|
+
optional?: boolean;
|
|
679
|
+
formatVersion?: string;
|
|
680
|
+
adapterVersion?: string;
|
|
681
|
+
}>;
|
|
682
|
+
}>(workspaceRoot, `${GENERATED_DIR}/agentAdapterManifest.json`);
|
|
683
|
+
const targets = (manifest?.targets ?? []).map((target) => {
|
|
684
|
+
const files = target.files ?? [];
|
|
685
|
+
const missingFiles = files.filter((file) => !hasPath(workspaceRoot, file));
|
|
686
|
+
return {
|
|
687
|
+
name: target.name,
|
|
688
|
+
default: target.default === true,
|
|
689
|
+
optional: target.optional === true,
|
|
690
|
+
formatVersion: target.formatVersion,
|
|
691
|
+
adapterVersion: target.adapterVersion,
|
|
692
|
+
files,
|
|
693
|
+
filesPresent: files.length - missingFiles.length,
|
|
694
|
+
missingFiles,
|
|
695
|
+
exportCommand: target.name ? `forge agent export --target ${target.name}` : null,
|
|
696
|
+
checkCommand: target.name ? `forge agent check --target ${target.name} --json` : null,
|
|
697
|
+
prepareCommand: target.name ? `forge agent prepare --target ${target.name} --json` : null,
|
|
698
|
+
};
|
|
699
|
+
});
|
|
700
|
+
const missingRequiredFiles = targets.reduce(
|
|
701
|
+
(count, target) => count + (target.optional ? 0 : target.missingFiles.length),
|
|
702
|
+
0,
|
|
703
|
+
);
|
|
704
|
+
const missingOptionalFiles = targets.reduce(
|
|
705
|
+
(count, target) => count + (target.optional ? target.missingFiles.length : 0),
|
|
706
|
+
0,
|
|
707
|
+
);
|
|
708
|
+
const defaultTarget = targets.find((target) => target.default);
|
|
709
|
+
const defaultTargetMissingFiles = defaultTarget?.missingFiles.length ?? missingRequiredFiles;
|
|
710
|
+
|
|
711
|
+
return {
|
|
712
|
+
schemaVersion: "0.1.0",
|
|
713
|
+
summary: {
|
|
714
|
+
targets: targets.length,
|
|
715
|
+
defaultTarget: defaultTarget?.name ?? "generic",
|
|
716
|
+
missingFiles: missingRequiredFiles + missingOptionalFiles,
|
|
717
|
+
missingDefaultFiles: defaultTargetMissingFiles,
|
|
718
|
+
missingRequiredFiles,
|
|
719
|
+
missingOptionalFiles,
|
|
720
|
+
defaultReady: defaultTargetMissingFiles === 0,
|
|
721
|
+
requiredReady: missingRequiredFiles === 0,
|
|
722
|
+
},
|
|
723
|
+
targets,
|
|
724
|
+
commands: [
|
|
725
|
+
"forge agent list-targets --json",
|
|
726
|
+
"forge agent prepare --target codex --json",
|
|
727
|
+
"forge agent hooks smoke --target codex --json",
|
|
728
|
+
"forge agent ingest codex --event PostToolUse --json",
|
|
729
|
+
],
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
export interface StatusCommandResult {
|
|
734
|
+
ok: boolean;
|
|
735
|
+
data: Record<string, unknown>;
|
|
736
|
+
exitCode: 0 | 1;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
export async function runStatusCommand(workspaceRoot: string): Promise<StatusCommandResult> {
|
|
740
|
+
const summary = buildInspectSummary(workspaceRoot);
|
|
741
|
+
const drift = buildDriftInspect(workspaceRoot);
|
|
742
|
+
const handoff = buildHandoffInspect(workspaceRoot);
|
|
743
|
+
const gitSummary = buildWorkspaceGitSummary(workspaceRoot);
|
|
744
|
+
const generatedVerification = await runGenerateCommand({
|
|
745
|
+
workspaceRoot,
|
|
746
|
+
check: true,
|
|
747
|
+
dryRun: false,
|
|
748
|
+
json: true,
|
|
749
|
+
concurrency: 4,
|
|
750
|
+
});
|
|
751
|
+
const git = {
|
|
752
|
+
available: gitSummary.available,
|
|
753
|
+
...(gitSummary.error ? { error: gitSummary.error } : {}),
|
|
754
|
+
changed: gitSummary.changeSummary.changed,
|
|
755
|
+
staged: gitSummary.changeSummary.staged,
|
|
756
|
+
unstaged: gitSummary.changeSummary.unstaged,
|
|
757
|
+
untracked: gitSummary.changeSummary.untracked,
|
|
758
|
+
};
|
|
759
|
+
const summaryBlock = summary.summary as Record<string, unknown>;
|
|
760
|
+
const driftSummary = drift.summary as Record<string, unknown>;
|
|
761
|
+
const handoffSummary = handoff.summary as Record<string, unknown>;
|
|
762
|
+
const missingArtifacts = Number(summaryBlock.missingArtifacts ?? 0);
|
|
763
|
+
const tableDrift = Number(driftSummary.tableDrift ?? 0);
|
|
764
|
+
const generatedReady = missingArtifacts === 0;
|
|
765
|
+
const generatedFresh = generatedVerification.exitCode === 0;
|
|
766
|
+
const driftClean = driftSummary.ok === true && generatedFresh;
|
|
767
|
+
const ok = driftClean && generatedReady;
|
|
768
|
+
const handoffDefaultReady = handoffSummary.defaultReady === true;
|
|
769
|
+
const changed = gitSummary.changeSummary.changed;
|
|
770
|
+
const generatedGitFiles = changed.byType.generated.count;
|
|
771
|
+
const authoredGitFiles = changed.total.count - generatedGitFiles;
|
|
772
|
+
const authoredGeneratedInputs =
|
|
773
|
+
changed.byType.source.count +
|
|
774
|
+
changed.byType.config.count +
|
|
775
|
+
changed.byType.operational.count;
|
|
776
|
+
const generatedState = !generatedReady
|
|
777
|
+
? "missing-artifacts"
|
|
778
|
+
: driftClean
|
|
779
|
+
? "ready"
|
|
780
|
+
: "drift";
|
|
781
|
+
const generatedNextActionsRaw = generatedState === "ready"
|
|
782
|
+
? ["forge dev", "forge dev --once --json", "forge generate --check --json"]
|
|
783
|
+
: ["forge generate", "forge check --json", "forge inspect drift --json"];
|
|
784
|
+
const generatedNextActions = forgeCliCommandsForWorkspace(workspaceRoot, generatedNextActionsRaw);
|
|
785
|
+
const generatedGitExplanation = !generatedFresh
|
|
786
|
+
? "deterministic generation verification found stale artifacts; git cleanliness does not prove generated freshness"
|
|
787
|
+
: generatedGitFiles === 0
|
|
788
|
+
? "git status has no generated artifact changes and deterministic generation verification passed"
|
|
789
|
+
: authoredGitFiles === 0
|
|
790
|
+
? "forge generate --check can be clean while git shows generated artifacts changed: generated files match current workspace inputs but differ from HEAD"
|
|
791
|
+
: "git status includes generated artifacts alongside authored changes; review authored inputs first";
|
|
792
|
+
const [safeDevCommand, generatedCheckCommand, generatedRepairCommand] = forgeCliCommandsForWorkspace(workspaceRoot, [
|
|
793
|
+
"forge dev",
|
|
794
|
+
"forge generate --check --json",
|
|
795
|
+
"forge generate",
|
|
796
|
+
]);
|
|
797
|
+
const frontendPresent = summaryBlock.frontendPresent === true;
|
|
798
|
+
const [
|
|
799
|
+
studioOpenCommand,
|
|
800
|
+
studioAttachCommand,
|
|
801
|
+
studioSnapshotCommand,
|
|
802
|
+
studioWatchCommand,
|
|
803
|
+
studioBridgeCommand,
|
|
804
|
+
studioDoctorCommand,
|
|
805
|
+
studioStartTargetAppCommand,
|
|
806
|
+
studioProbeCommand,
|
|
807
|
+
] = forgeCliCommandsForWorkspace(workspaceRoot, [
|
|
808
|
+
"forge studio open . --preview-port 5174 --target codex --json",
|
|
809
|
+
"forge studio attach . --preview-port 5174 --target codex --json",
|
|
810
|
+
"forge studio snapshot . --preview-port 5174 --target codex --json",
|
|
811
|
+
"forge studio watch . --preview-port 5174 --target codex --json",
|
|
812
|
+
"forge studio bridge . --preview-port 5174 --target codex --studio-url http://127.0.0.1:3765 --json",
|
|
813
|
+
"forge studio doctor . --preview-port 5174 --target codex --json",
|
|
814
|
+
"forge dev --port 3766 --web-port 5174",
|
|
815
|
+
"forge dev --once --json",
|
|
816
|
+
]);
|
|
817
|
+
const studio = {
|
|
818
|
+
openCommand: studioOpenCommand,
|
|
819
|
+
attachCommand: studioAttachCommand,
|
|
820
|
+
snapshotCommand: studioSnapshotCommand,
|
|
821
|
+
watchCommand: studioWatchCommand,
|
|
822
|
+
bridgeCommand: studioBridgeCommand,
|
|
823
|
+
doctorCommand: studioDoctorCommand,
|
|
824
|
+
targetPreviewUrl: "http://127.0.0.1:5174",
|
|
825
|
+
startTargetAppCommand: studioStartTargetAppCommand,
|
|
826
|
+
probeCommand: studioProbeCommand,
|
|
827
|
+
useful: frontendPresent,
|
|
828
|
+
note: frontendPresent
|
|
829
|
+
? "Attach this app to Forge Studio as an external-agent workroom; Studio should preview the target app on 5174."
|
|
830
|
+
: "No frontend was detected, but Studio can still attach for hooks, posture, and agent context.",
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
return {
|
|
834
|
+
ok,
|
|
835
|
+
data: {
|
|
836
|
+
schemaVersion: "0.1.0",
|
|
837
|
+
ok,
|
|
838
|
+
generated: {
|
|
839
|
+
state: generatedState,
|
|
840
|
+
ready: generatedReady,
|
|
841
|
+
driftClean,
|
|
842
|
+
freshness: generatedState === "ready" ? "verified" : generatedFresh ? "attention" : "stale",
|
|
843
|
+
authoredGeneratedInputs,
|
|
844
|
+
missingArtifacts,
|
|
845
|
+
tableDrift,
|
|
846
|
+
verification: {
|
|
847
|
+
checked: true,
|
|
848
|
+
fresh: generatedFresh,
|
|
849
|
+
changedFiles: generatedVerification.changed.length,
|
|
850
|
+
sampleChanged: generatedVerification.changed.slice(0, 8),
|
|
851
|
+
hiddenChanged: Math.max(0, generatedVerification.changed.length - 8),
|
|
852
|
+
diagnosticCodes: [...new Set(generatedVerification.errors.map((diagnostic) => diagnostic.code))],
|
|
853
|
+
},
|
|
854
|
+
safeDevCommand,
|
|
855
|
+
checkCommand: generatedCheckCommand,
|
|
856
|
+
repairCommand: generatedRepairCommand,
|
|
857
|
+
git: {
|
|
858
|
+
changedFiles: changed.total.count,
|
|
859
|
+
authoredFiles: authoredGitFiles,
|
|
860
|
+
generatedFiles: generatedGitFiles,
|
|
861
|
+
explanation: generatedGitExplanation,
|
|
862
|
+
},
|
|
863
|
+
nextActions: generatedNextActions,
|
|
864
|
+
},
|
|
865
|
+
studio,
|
|
866
|
+
summary: {
|
|
867
|
+
project: summaryBlock.project,
|
|
868
|
+
generated: generatedState,
|
|
869
|
+
tables: summaryBlock.tables,
|
|
870
|
+
frontendPresent,
|
|
871
|
+
routes: summaryBlock.routes,
|
|
872
|
+
drift: driftClean ? "clean" : "attention",
|
|
873
|
+
agentTargets: summaryBlock.agentTargets,
|
|
874
|
+
missingAgentFiles: handoffSummary.missingRequiredFiles,
|
|
875
|
+
missingDefaultAgentFiles: handoffSummary.missingDefaultFiles,
|
|
876
|
+
missingRequiredAgentFiles: handoffSummary.missingRequiredFiles,
|
|
877
|
+
missingOptionalAgentFiles: handoffSummary.missingOptionalFiles,
|
|
878
|
+
},
|
|
879
|
+
checks: {
|
|
880
|
+
artifacts: {
|
|
881
|
+
missing: missingArtifacts,
|
|
882
|
+
},
|
|
883
|
+
schema: {
|
|
884
|
+
tableDrift,
|
|
885
|
+
},
|
|
886
|
+
handoff: {
|
|
887
|
+
targets: handoffSummary.targets,
|
|
888
|
+
missingFiles: handoffSummary.missingFiles,
|
|
889
|
+
missingDefaultFiles: handoffSummary.missingDefaultFiles,
|
|
890
|
+
missingRequiredFiles: handoffSummary.missingRequiredFiles,
|
|
891
|
+
missingOptionalFiles: handoffSummary.missingOptionalFiles,
|
|
892
|
+
defaultReady: handoffSummary.defaultReady,
|
|
893
|
+
requiredReady: handoffSummary.requiredReady,
|
|
894
|
+
},
|
|
895
|
+
},
|
|
896
|
+
git,
|
|
897
|
+
nextActions: forgeCliCommandsForWorkspace(
|
|
898
|
+
workspaceRoot,
|
|
899
|
+
ok
|
|
900
|
+
? [
|
|
901
|
+
"forge handoff --json",
|
|
902
|
+
"forge changed --json",
|
|
903
|
+
"forge dev",
|
|
904
|
+
...(frontendPresent ? [studio.openCommand, studio.bridgeCommand, studio.doctorCommand] : []),
|
|
905
|
+
...(!handoffDefaultReady ? ["forge agent prepare --target generic --json"] : []),
|
|
906
|
+
"forge inspect handoff --json",
|
|
907
|
+
"forge verify --changed",
|
|
908
|
+
]
|
|
909
|
+
: [
|
|
910
|
+
"forge generate",
|
|
911
|
+
"forge handoff --json",
|
|
912
|
+
"forge changed --json",
|
|
913
|
+
...(frontendPresent ? [studio.openCommand, studio.bridgeCommand, studio.doctorCommand] : []),
|
|
914
|
+
"forge inspect drift --json",
|
|
915
|
+
"forge agent prepare --target codex --json",
|
|
916
|
+
],
|
|
917
|
+
),
|
|
918
|
+
},
|
|
919
|
+
exitCode: ok ? 0 : 1,
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
export function formatStatusHuman(result: StatusCommandResult): string {
|
|
924
|
+
const summary = result.data.summary as Record<string, unknown>;
|
|
925
|
+
const generated = result.data.generated as
|
|
926
|
+
| {
|
|
927
|
+
state?: string;
|
|
928
|
+
missingArtifacts?: number;
|
|
929
|
+
tableDrift?: number;
|
|
930
|
+
safeDevCommand?: string;
|
|
931
|
+
checkCommand?: string;
|
|
932
|
+
repairCommand?: string;
|
|
933
|
+
}
|
|
934
|
+
| undefined;
|
|
935
|
+
const git = result.data.git as
|
|
936
|
+
| {
|
|
937
|
+
available?: boolean;
|
|
938
|
+
changed?: CategorizedFileSummary;
|
|
939
|
+
}
|
|
940
|
+
| undefined;
|
|
941
|
+
const studio = result.data.studio as
|
|
942
|
+
| {
|
|
943
|
+
attachCommand?: string;
|
|
944
|
+
openCommand?: string;
|
|
945
|
+
doctorCommand?: string;
|
|
946
|
+
bridgeCommand?: string;
|
|
947
|
+
targetPreviewUrl?: string;
|
|
948
|
+
startTargetAppCommand?: string;
|
|
949
|
+
useful?: boolean;
|
|
950
|
+
}
|
|
951
|
+
| undefined;
|
|
952
|
+
const lines = [
|
|
953
|
+
`Forge status: ${result.ok ? "ready" : "needs attention"}`,
|
|
954
|
+
`Project: ${summary.project ?? "unknown"}`,
|
|
955
|
+
`Generated: ${summary.generated}`,
|
|
956
|
+
...(generated
|
|
957
|
+
? [
|
|
958
|
+
`Generated detail: missing artifacts ${generated.missingArtifacts ?? 0}, table drift ${generated.tableDrift ?? 0}`,
|
|
959
|
+
`Generated check: ${generated.checkCommand ?? "forge generate --check --json"}`,
|
|
960
|
+
`Generated repair: ${generated.repairCommand ?? "forge generate"}`,
|
|
961
|
+
`Generated dev: ${generated.safeDevCommand ?? "forge dev"}`,
|
|
962
|
+
]
|
|
963
|
+
: []),
|
|
964
|
+
`Drift: ${summary.drift}`,
|
|
965
|
+
`Frontend: ${summary.frontendPresent ? `${summary.routes ?? 0} routes` : "none"}`,
|
|
966
|
+
...(studio
|
|
967
|
+
? [
|
|
968
|
+
`Studio open: ${studio.openCommand ?? "forge studio open . --preview-port 5174 --target codex --json"}`,
|
|
969
|
+
`Studio attach: ${studio.attachCommand ?? "forge studio attach . --preview-port 5174 --target codex --json"}`,
|
|
970
|
+
`Studio bridge: ${studio.bridgeCommand ?? "forge studio bridge . --preview-port 5174 --target codex --studio-url http://127.0.0.1:3765 --json"}`,
|
|
971
|
+
`Studio doctor: ${studio.doctorCommand ?? "forge studio doctor . --preview-port 5174 --target codex --json"}`,
|
|
972
|
+
`Studio preview: ${studio.targetPreviewUrl ?? "http://127.0.0.1:5174"}`,
|
|
973
|
+
`Studio start: ${studio.startTargetAppCommand ?? "forge dev --port 3766 --web-port 5174"}`,
|
|
974
|
+
]
|
|
975
|
+
: []),
|
|
976
|
+
...(git?.available && git.changed
|
|
977
|
+
? [`Changed: ${git.changed.total.count}${git.changed.total.count > 0 ? ` (${git.changed.primaryTypes.slice(0, 5).join(", ")})` : ""}`]
|
|
978
|
+
: []),
|
|
979
|
+
`Agent default missing files: ${summary.missingDefaultAgentFiles ?? 0}`,
|
|
980
|
+
`Agent required missing files: ${summary.missingRequiredAgentFiles ?? summary.missingAgentFiles ?? 0}`,
|
|
981
|
+
`Agent optional missing files: ${summary.missingOptionalAgentFiles ?? 0}`,
|
|
982
|
+
"",
|
|
983
|
+
"Next:",
|
|
984
|
+
...((result.data.nextActions as string[] | undefined) ?? []).map((command) => ` ${command}`),
|
|
985
|
+
];
|
|
986
|
+
return `${lines.join("\n")}\n`;
|
|
987
|
+
}
|
|
988
|
+
|
|
279
989
|
export async function runGenerateCommand(
|
|
280
990
|
options: GenerateOptions,
|
|
281
991
|
): Promise<GenerateResult> {
|
|
282
|
-
const result = await run(options);
|
|
992
|
+
const result = await withWorkspaceCwd(options.workspaceRoot, () => run(options));
|
|
283
993
|
return attachFailureKind(result);
|
|
284
994
|
}
|
|
285
995
|
|
|
996
|
+
async function withWorkspaceCwd<T>(workspaceRoot: string, fn: () => Promise<T>): Promise<T> {
|
|
997
|
+
const previous = process.cwd();
|
|
998
|
+
const target = resolve(workspaceRoot);
|
|
999
|
+
if (resolve(previous).toLowerCase() === target.toLowerCase()) {
|
|
1000
|
+
return fn();
|
|
1001
|
+
}
|
|
1002
|
+
process.chdir(target);
|
|
1003
|
+
try {
|
|
1004
|
+
return await fn();
|
|
1005
|
+
} finally {
|
|
1006
|
+
process.chdir(previous);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
286
1010
|
export async function runAddCommand(
|
|
287
1011
|
alias: string,
|
|
288
1012
|
options: Extract<ForgeCommand, { kind: "add" }>["options"],
|
|
@@ -324,12 +1048,70 @@ async function loadRuntimeMatrixForCheck(
|
|
|
324
1048
|
return buildRuntimeMatrix(classified);
|
|
325
1049
|
}
|
|
326
1050
|
|
|
1051
|
+
function normalizeSchemaType(type: string): string {
|
|
1052
|
+
return type.trim().replace(/\?$/, "").toLowerCase();
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
function timestampFieldNames(dataGraph: DataGraph): Set<string> {
|
|
1056
|
+
const fields = new Set<string>();
|
|
1057
|
+
for (const table of dataGraph.tables) {
|
|
1058
|
+
for (const field of table.fields) {
|
|
1059
|
+
if (["timestamp", "timestamptz"].includes(normalizeSchemaType(field.type))) {
|
|
1060
|
+
fields.add(field.name);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
return fields;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
function checkEmptyTimestampLiterals(
|
|
1068
|
+
appGraph: Awaited<ReturnType<typeof buildAppGraphForSession>>,
|
|
1069
|
+
dataGraph: DataGraph,
|
|
1070
|
+
): ReturnType<typeof createDiagnostic>[] {
|
|
1071
|
+
const fields = timestampFieldNames(dataGraph);
|
|
1072
|
+
if (fields.size === 0) {
|
|
1073
|
+
return [];
|
|
1074
|
+
}
|
|
1075
|
+
const diagnostics: ReturnType<typeof createDiagnostic>[] = [];
|
|
1076
|
+
const runtimeKinds = new Set(["command", "query", "liveQuery", "action", "workflow"]);
|
|
1077
|
+
for (const symbol of appGraph.symbols) {
|
|
1078
|
+
if (!runtimeKinds.has(symbol.kind)) {
|
|
1079
|
+
continue;
|
|
1080
|
+
}
|
|
1081
|
+
const sourceSlice = typeof symbol.meta.sourceSlice === "string" ? symbol.meta.sourceSlice : "";
|
|
1082
|
+
if (!sourceSlice) {
|
|
1083
|
+
continue;
|
|
1084
|
+
}
|
|
1085
|
+
for (const field of fields) {
|
|
1086
|
+
const escaped = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1087
|
+
const pattern = new RegExp(`\\b${escaped}\\s*:\\s*(["']{2})`);
|
|
1088
|
+
const emptyTemplatePattern = new RegExp(`\\b${escaped}\\s*:\\s*\`\``);
|
|
1089
|
+
if (!pattern.test(sourceSlice) && !emptyTemplatePattern.test(sourceSlice)) {
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
diagnostics.push(
|
|
1093
|
+
createDiagnostic({
|
|
1094
|
+
severity: "error",
|
|
1095
|
+
code: FORGE_DB_EMPTY_TIMESTAMP_LITERAL,
|
|
1096
|
+
message:
|
|
1097
|
+
`Forge timestamp field '${field}' is assigned an empty string in ${symbol.kind} '${symbol.name}'.`,
|
|
1098
|
+
file: symbol.file,
|
|
1099
|
+
span: symbol.span,
|
|
1100
|
+
}),
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
return diagnostics;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
327
1107
|
export async function runCheckCommand(
|
|
328
1108
|
workspaceRoot: string,
|
|
329
1109
|
options?: { strictSecrets?: boolean },
|
|
330
1110
|
): Promise<GenerateResult> {
|
|
331
1111
|
const session = getCompileSession(workspaceRoot);
|
|
332
1112
|
const appGraph = await buildAppGraphForSession(session);
|
|
1113
|
+
const dataGraph = buildDataGraph(appGraph);
|
|
1114
|
+
const sqlPlan = buildSqlPlan(dataGraph);
|
|
333
1115
|
|
|
334
1116
|
const matrix = await loadRuntimeMatrixForCheck(workspaceRoot);
|
|
335
1117
|
const guardDiagnostics = checkImportGuards(appGraph.moduleGraph, matrix);
|
|
@@ -349,14 +1131,21 @@ export async function runCheckCommand(
|
|
|
349
1131
|
workspaceRoot,
|
|
350
1132
|
`${GENERATED_DIR}/capabilityMap.json`,
|
|
351
1133
|
)?.diagnostics ?? [];
|
|
1134
|
+
const externalDiagnostics = buildExternalServiceGraph(workspaceRoot).diagnostics;
|
|
1135
|
+
const timestampLiteralDiagnostics = checkEmptyTimestampLiterals(appGraph, dataGraph);
|
|
352
1136
|
|
|
353
1137
|
const allDiagnostics = [
|
|
1138
|
+
...appGraph.diagnostics,
|
|
1139
|
+
...dataGraph.diagnostics,
|
|
1140
|
+
...sqlPlan.diagnostics,
|
|
354
1141
|
...guardDiagnostics,
|
|
355
1142
|
...processEnvDiagnostics,
|
|
356
1143
|
...aiDiagnostics,
|
|
357
1144
|
...queryDiagnostics,
|
|
1145
|
+
...timestampLiteralDiagnostics,
|
|
358
1146
|
...frontendDiagnostics,
|
|
359
1147
|
...capabilityDiagnostics,
|
|
1148
|
+
...externalDiagnostics,
|
|
360
1149
|
];
|
|
361
1150
|
const errors = allDiagnostics.filter(
|
|
362
1151
|
(diagnostic) => diagnostic.severity === "error",
|
|
@@ -375,9 +1164,474 @@ export async function runCheckCommand(
|
|
|
375
1164
|
});
|
|
376
1165
|
}
|
|
377
1166
|
|
|
1167
|
+
interface ReleaseDoctorCheck {
|
|
1168
|
+
name: string;
|
|
1169
|
+
ok: boolean;
|
|
1170
|
+
requiredForPublish: boolean;
|
|
1171
|
+
requiredForProduction?: boolean;
|
|
1172
|
+
state?: string;
|
|
1173
|
+
result: ReleaseCommandResult | SelfHostCommandResult | DocsCheckResult | DeployCommandResult | PackagePackCheckResult | NpmDistTagCheckResult;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
interface PackagePackCheckResult {
|
|
1177
|
+
ok: boolean;
|
|
1178
|
+
data: {
|
|
1179
|
+
command: "npm pack --dry-run --json";
|
|
1180
|
+
dryRun: true;
|
|
1181
|
+
tarball: string | null;
|
|
1182
|
+
fileCount: number;
|
|
1183
|
+
};
|
|
1184
|
+
diagnostics: ReturnType<typeof createDiagnostic>[];
|
|
1185
|
+
nextActions?: string[];
|
|
1186
|
+
failureKind?: string;
|
|
1187
|
+
exitCode: 0 | 1;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
interface NpmDistTagCheckResult {
|
|
1191
|
+
ok: boolean;
|
|
1192
|
+
data: {
|
|
1193
|
+
command: string;
|
|
1194
|
+
packageName: string | null;
|
|
1195
|
+
packageVersion: string | null;
|
|
1196
|
+
alphaVersion: string | null;
|
|
1197
|
+
latestVersion: string | null;
|
|
1198
|
+
alphaMatches: boolean;
|
|
1199
|
+
latestMatches: boolean;
|
|
1200
|
+
source: "npm-view" | "env-fixture" | "skipped";
|
|
1201
|
+
};
|
|
1202
|
+
diagnostics: ReturnType<typeof createDiagnostic>[];
|
|
1203
|
+
nextActions?: string[];
|
|
1204
|
+
failureKind?: string;
|
|
1205
|
+
exitCode: 0 | 1;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
interface ReleaseDoctorResult {
|
|
1209
|
+
schemaVersion: "0.1.0";
|
|
1210
|
+
ok: boolean;
|
|
1211
|
+
readyToPublish: boolean;
|
|
1212
|
+
readyForProductionDeploy: boolean;
|
|
1213
|
+
summary: {
|
|
1214
|
+
checks: number;
|
|
1215
|
+
failed: string[];
|
|
1216
|
+
notPrepared: string[];
|
|
1217
|
+
publishBlockers: string[];
|
|
1218
|
+
productionBlockers: string[];
|
|
1219
|
+
};
|
|
1220
|
+
checks: ReleaseDoctorCheck[];
|
|
1221
|
+
nextActions: string[];
|
|
1222
|
+
exitCode: 0 | 1;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
function runPackagePackDryRun(workspaceRoot: string): PackagePackCheckResult {
|
|
1226
|
+
const result = spawnSync("npm", ["pack", "--dry-run", "--json"], {
|
|
1227
|
+
cwd: workspaceRoot,
|
|
1228
|
+
encoding: "utf8",
|
|
1229
|
+
windowsHide: true,
|
|
1230
|
+
});
|
|
1231
|
+
const command = "npm pack --dry-run --json" as const;
|
|
1232
|
+
if (result.status !== 0) {
|
|
1233
|
+
const failureDetail = result.error instanceof Error ? result.error.message : null;
|
|
1234
|
+
return {
|
|
1235
|
+
ok: false,
|
|
1236
|
+
data: { command, dryRun: true, tarball: null, fileCount: 0 },
|
|
1237
|
+
diagnostics: [
|
|
1238
|
+
createDiagnostic({
|
|
1239
|
+
severity: "error",
|
|
1240
|
+
code: FORGE_RELEASE_PACKAGE_PACK_FAILED,
|
|
1241
|
+
message: "npm pack dry-run failed; release package contents could not be validated",
|
|
1242
|
+
fixHint: (result.stderr || result.stdout || failureDetail || "Run npm pack --dry-run --json locally for details.").trim(),
|
|
1243
|
+
suggestedCommands: ["npm pack --dry-run --json"],
|
|
1244
|
+
}),
|
|
1245
|
+
],
|
|
1246
|
+
nextActions: ["npm pack --dry-run --json"],
|
|
1247
|
+
failureKind: "package-pack-failed",
|
|
1248
|
+
exitCode: 1,
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
try {
|
|
1252
|
+
const parsed = JSON.parse(result.stdout || "[]") as unknown;
|
|
1253
|
+
const pack = Array.isArray(parsed)
|
|
1254
|
+
? (parsed[0] as { filename?: unknown; files?: unknown[] } | undefined)
|
|
1255
|
+
: undefined;
|
|
1256
|
+
if (typeof pack?.filename !== "string" || !Array.isArray(pack.files)) {
|
|
1257
|
+
return {
|
|
1258
|
+
ok: false,
|
|
1259
|
+
data: { command, dryRun: true, tarball: null, fileCount: 0 },
|
|
1260
|
+
diagnostics: [
|
|
1261
|
+
createDiagnostic({
|
|
1262
|
+
severity: "error",
|
|
1263
|
+
code: FORGE_RELEASE_PACKAGE_PACK_FAILED,
|
|
1264
|
+
message: "npm pack dry-run did not report package contents",
|
|
1265
|
+
fixHint: "Run npm pack --dry-run --json locally and confirm it returns a tarball with file entries.",
|
|
1266
|
+
suggestedCommands: ["npm pack --dry-run --json"],
|
|
1267
|
+
}),
|
|
1268
|
+
],
|
|
1269
|
+
nextActions: ["npm pack --dry-run --json"],
|
|
1270
|
+
failureKind: "package-pack-missing-contents",
|
|
1271
|
+
exitCode: 1,
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
return {
|
|
1275
|
+
ok: true,
|
|
1276
|
+
data: {
|
|
1277
|
+
command,
|
|
1278
|
+
dryRun: true,
|
|
1279
|
+
tarball: pack.filename,
|
|
1280
|
+
fileCount: pack.files.length,
|
|
1281
|
+
},
|
|
1282
|
+
diagnostics: [],
|
|
1283
|
+
exitCode: 0,
|
|
1284
|
+
};
|
|
1285
|
+
} catch (error) {
|
|
1286
|
+
return {
|
|
1287
|
+
ok: false,
|
|
1288
|
+
data: { command, dryRun: true, tarball: null, fileCount: 0 },
|
|
1289
|
+
diagnostics: [
|
|
1290
|
+
createDiagnostic({
|
|
1291
|
+
severity: "error",
|
|
1292
|
+
code: FORGE_RELEASE_PACKAGE_PACK_FAILED,
|
|
1293
|
+
message: "npm pack dry-run returned invalid JSON",
|
|
1294
|
+
fixHint: error instanceof Error ? error.message : String(error),
|
|
1295
|
+
suggestedCommands: ["npm pack --dry-run --json"],
|
|
1296
|
+
}),
|
|
1297
|
+
],
|
|
1298
|
+
nextActions: ["npm pack --dry-run --json"],
|
|
1299
|
+
failureKind: "package-pack-invalid-json",
|
|
1300
|
+
exitCode: 1,
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
function parseNpmDistTagsJson(raw: string): Record<string, string> | null {
|
|
1306
|
+
try {
|
|
1307
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
1308
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1309
|
+
return null;
|
|
1310
|
+
}
|
|
1311
|
+
const tags: Record<string, string> = {};
|
|
1312
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
1313
|
+
if (typeof value === "string") {
|
|
1314
|
+
tags[key] = value;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
return tags;
|
|
1318
|
+
} catch {
|
|
1319
|
+
return null;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
function runNpmDistTagCheck(workspaceRoot: string): NpmDistTagCheckResult {
|
|
1324
|
+
const pkg = readPackageJson(workspaceRoot) as {
|
|
1325
|
+
name?: unknown;
|
|
1326
|
+
version?: unknown;
|
|
1327
|
+
private?: unknown;
|
|
1328
|
+
};
|
|
1329
|
+
const packageName = typeof pkg.name === "string" ? pkg.name : null;
|
|
1330
|
+
const packageVersion = typeof pkg.version === "string" ? pkg.version : null;
|
|
1331
|
+
const command = packageName ? `npm view ${packageName} dist-tags --json` : "npm view <package> dist-tags --json";
|
|
1332
|
+
const baseData = {
|
|
1333
|
+
command,
|
|
1334
|
+
packageName,
|
|
1335
|
+
packageVersion,
|
|
1336
|
+
alphaVersion: null,
|
|
1337
|
+
latestVersion: null,
|
|
1338
|
+
alphaMatches: false,
|
|
1339
|
+
latestMatches: false,
|
|
1340
|
+
source: "skipped" as const,
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
if (pkg.private === true) {
|
|
1344
|
+
return {
|
|
1345
|
+
ok: true,
|
|
1346
|
+
data: baseData,
|
|
1347
|
+
diagnostics: [],
|
|
1348
|
+
exitCode: 0,
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
if (!packageName || !packageVersion) {
|
|
1352
|
+
return {
|
|
1353
|
+
ok: false,
|
|
1354
|
+
data: baseData,
|
|
1355
|
+
diagnostics: [
|
|
1356
|
+
createDiagnostic({
|
|
1357
|
+
severity: "warning",
|
|
1358
|
+
code: FORGE_RELEASE_NPM_DIST_TAG_CHECK_FAILED,
|
|
1359
|
+
message: "release doctor could not check npm dist-tags because package.json is missing name or version",
|
|
1360
|
+
fixHint: "Set package.json name and version before publishing, then rerun forge release doctor.",
|
|
1361
|
+
suggestedCommands: ["node bin/forge.mjs release doctor --json"],
|
|
1362
|
+
}),
|
|
1363
|
+
],
|
|
1364
|
+
nextActions: ["node bin/forge.mjs release doctor --json"],
|
|
1365
|
+
failureKind: "npm-dist-tags-package-metadata-missing",
|
|
1366
|
+
exitCode: 1,
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
const fixture = process.env.FORGE_RELEASE_NPM_DIST_TAGS_JSON;
|
|
1371
|
+
const source = fixture ? "env-fixture" as const : "npm-view" as const;
|
|
1372
|
+
const stdout = fixture ?? spawnSync("npm", ["view", packageName, "dist-tags", "--json"], {
|
|
1373
|
+
cwd: workspaceRoot,
|
|
1374
|
+
encoding: "utf8",
|
|
1375
|
+
timeout: 10_000,
|
|
1376
|
+
windowsHide: true,
|
|
1377
|
+
}).stdout;
|
|
1378
|
+
const tags = parseNpmDistTagsJson(stdout || "");
|
|
1379
|
+
if (!tags) {
|
|
1380
|
+
return {
|
|
1381
|
+
ok: false,
|
|
1382
|
+
data: { ...baseData, source },
|
|
1383
|
+
diagnostics: [
|
|
1384
|
+
createDiagnostic({
|
|
1385
|
+
severity: "warning",
|
|
1386
|
+
code: FORGE_RELEASE_NPM_DIST_TAG_CHECK_FAILED,
|
|
1387
|
+
message: `release doctor could not read npm dist-tags for ${packageName}`,
|
|
1388
|
+
fixHint: `Run ${command}. If the package has not been published yet, publish it with the alpha tag first.`,
|
|
1389
|
+
suggestedCommands: [command, "npm run release:publish-alpha"],
|
|
1390
|
+
}),
|
|
1391
|
+
],
|
|
1392
|
+
nextActions: [command, "npm run release:publish-alpha"],
|
|
1393
|
+
failureKind: "npm-dist-tags-unavailable",
|
|
1394
|
+
exitCode: 1,
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
const alphaVersion = tags.alpha ?? null;
|
|
1399
|
+
const latestVersion = tags.latest ?? null;
|
|
1400
|
+
const alphaMatches = alphaVersion === packageVersion;
|
|
1401
|
+
const latestMatches = latestVersion === packageVersion;
|
|
1402
|
+
const data = {
|
|
1403
|
+
command,
|
|
1404
|
+
packageName,
|
|
1405
|
+
packageVersion,
|
|
1406
|
+
alphaVersion,
|
|
1407
|
+
latestVersion,
|
|
1408
|
+
alphaMatches,
|
|
1409
|
+
latestMatches,
|
|
1410
|
+
source,
|
|
1411
|
+
};
|
|
1412
|
+
if (alphaMatches && latestMatches) {
|
|
1413
|
+
return {
|
|
1414
|
+
ok: true,
|
|
1415
|
+
data,
|
|
1416
|
+
diagnostics: [],
|
|
1417
|
+
exitCode: 0,
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
const nextActions: string[] = [];
|
|
1422
|
+
const diagnostics: ReturnType<typeof createDiagnostic>[] = [];
|
|
1423
|
+
if (!alphaMatches) {
|
|
1424
|
+
nextActions.push("npm run release:publish-alpha");
|
|
1425
|
+
diagnostics.push(createDiagnostic({
|
|
1426
|
+
severity: "warning",
|
|
1427
|
+
code: FORGE_RELEASE_NPM_DIST_TAG_STALE,
|
|
1428
|
+
message: `${packageName}@alpha points to ${alphaVersion ?? "none"}, not local version ${packageVersion}`,
|
|
1429
|
+
fixHint: "Publish the current package with the alpha tag before asking users to install forgeos@alpha.",
|
|
1430
|
+
suggestedCommands: ["npm run release:publish-alpha", command],
|
|
1431
|
+
}));
|
|
1432
|
+
}
|
|
1433
|
+
if (!latestMatches) {
|
|
1434
|
+
const promote = `npm dist-tag add ${packageName}@${packageVersion} latest`;
|
|
1435
|
+
nextActions.push(promote);
|
|
1436
|
+
nextActions.push("configure NPM_TOKEN in GitHub Actions secrets, or run npm login locally before promoting latest");
|
|
1437
|
+
diagnostics.push(createDiagnostic({
|
|
1438
|
+
severity: "warning",
|
|
1439
|
+
code: FORGE_RELEASE_NPM_DIST_TAG_STALE,
|
|
1440
|
+
message: `${packageName}@latest points to ${latestVersion ?? "none"}, not local version ${packageVersion}`,
|
|
1441
|
+
fixHint: `Promote latest after the alpha package is verified: ${promote}`,
|
|
1442
|
+
suggestedCommands: [promote, command],
|
|
1443
|
+
}));
|
|
1444
|
+
}
|
|
1445
|
+
return {
|
|
1446
|
+
ok: false,
|
|
1447
|
+
data,
|
|
1448
|
+
diagnostics,
|
|
1449
|
+
nextActions,
|
|
1450
|
+
failureKind: !alphaMatches ? "npm-alpha-dist-tag-stale" : "npm-latest-dist-tag-stale",
|
|
1451
|
+
exitCode: 1,
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
export async function runReleaseDoctorCommand(command: Extract<ForgeCommand, { kind: "release" }>): Promise<ReleaseDoctorResult> {
|
|
1456
|
+
const release = await runReleaseCommand({
|
|
1457
|
+
...command,
|
|
1458
|
+
action: "check",
|
|
1459
|
+
allowMissingLocalRelease: true,
|
|
1460
|
+
provider: command.provider as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
|
|
1461
|
+
target: command.target as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
|
|
1462
|
+
});
|
|
1463
|
+
const sourcemaps = await runReleaseCommand({
|
|
1464
|
+
...command,
|
|
1465
|
+
area: "sourcemaps",
|
|
1466
|
+
action: "check",
|
|
1467
|
+
provider: command.provider as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
|
|
1468
|
+
target: command.target as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
|
|
1469
|
+
});
|
|
1470
|
+
const selfHost = await runSelfHostCommand({
|
|
1471
|
+
subcommand: "check",
|
|
1472
|
+
workspaceRoot: command.workspaceRoot,
|
|
1473
|
+
json: command.json,
|
|
1474
|
+
withWeb: true,
|
|
1475
|
+
postgresVersion: "16",
|
|
1476
|
+
runtimePort: 3765,
|
|
1477
|
+
webPort: 3000,
|
|
1478
|
+
preparedOnly: true,
|
|
1479
|
+
});
|
|
1480
|
+
const docs = runDocsCheckCommand({
|
|
1481
|
+
workspaceRoot: command.workspaceRoot,
|
|
1482
|
+
json: command.json,
|
|
1483
|
+
});
|
|
1484
|
+
const deployProduction = await runDeployCommand({
|
|
1485
|
+
subcommand: "check",
|
|
1486
|
+
workspaceRoot: command.workspaceRoot,
|
|
1487
|
+
json: command.json,
|
|
1488
|
+
target: "docker",
|
|
1489
|
+
production: true,
|
|
1490
|
+
});
|
|
1491
|
+
const packagePack = runPackagePackDryRun(command.workspaceRoot);
|
|
1492
|
+
const npmDistTags = runNpmDistTagCheck(command.workspaceRoot);
|
|
1493
|
+
const checks: ReleaseDoctorCheck[] = [
|
|
1494
|
+
{
|
|
1495
|
+
name: "release-prepared",
|
|
1496
|
+
ok: release.ok,
|
|
1497
|
+
requiredForPublish: true,
|
|
1498
|
+
state: (release.data as { state?: string } | undefined)?.state,
|
|
1499
|
+
result: release,
|
|
1500
|
+
},
|
|
1501
|
+
{
|
|
1502
|
+
name: "sourcemaps",
|
|
1503
|
+
ok: sourcemaps.ok,
|
|
1504
|
+
requiredForPublish: true,
|
|
1505
|
+
result: sourcemaps,
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
name: "self-host",
|
|
1509
|
+
ok: selfHost.ok,
|
|
1510
|
+
requiredForPublish: false,
|
|
1511
|
+
state: selfHost.state,
|
|
1512
|
+
result: selfHost,
|
|
1513
|
+
},
|
|
1514
|
+
{
|
|
1515
|
+
name: "deploy-production",
|
|
1516
|
+
ok: deployProduction.ok,
|
|
1517
|
+
requiredForPublish: false,
|
|
1518
|
+
requiredForProduction: true,
|
|
1519
|
+
result: deployProduction,
|
|
1520
|
+
},
|
|
1521
|
+
{
|
|
1522
|
+
name: "docs",
|
|
1523
|
+
ok: docs.ok,
|
|
1524
|
+
requiredForPublish: true,
|
|
1525
|
+
result: docs,
|
|
1526
|
+
},
|
|
1527
|
+
{
|
|
1528
|
+
name: "npm-pack-dry-run",
|
|
1529
|
+
ok: packagePack.ok,
|
|
1530
|
+
requiredForPublish: true,
|
|
1531
|
+
result: packagePack,
|
|
1532
|
+
},
|
|
1533
|
+
{
|
|
1534
|
+
name: "npm-dist-tags",
|
|
1535
|
+
ok: npmDistTags.ok,
|
|
1536
|
+
requiredForPublish: false,
|
|
1537
|
+
state: npmDistTags.failureKind ?? (npmDistTags.data.source === "skipped" ? "skipped" : "current"),
|
|
1538
|
+
result: npmDistTags,
|
|
1539
|
+
},
|
|
1540
|
+
];
|
|
1541
|
+
const failed = checks.filter((check) => !check.ok).map((check) => check.name);
|
|
1542
|
+
const notPrepared = checks
|
|
1543
|
+
.filter((check) => check.state === "missing-prepared-release" || check.state === "not-prepared")
|
|
1544
|
+
.map((check) => check.name);
|
|
1545
|
+
const publishBlockers = checks
|
|
1546
|
+
.filter((check) => check.requiredForPublish && !check.ok)
|
|
1547
|
+
.map((check) => check.name);
|
|
1548
|
+
const productionBlockers = checks
|
|
1549
|
+
.filter((check) => check.requiredForProduction && !check.ok)
|
|
1550
|
+
.map((check) => check.name);
|
|
1551
|
+
const notPreparedPublishBlockers = checks
|
|
1552
|
+
.filter((check) => check.requiredForPublish && (check.state === "missing-prepared-release" || check.state === "not-prepared"))
|
|
1553
|
+
.map((check) => check.name);
|
|
1554
|
+
const readyToPublish = publishBlockers.length === 0 && notPreparedPublishBlockers.length === 0;
|
|
1555
|
+
const readyForProductionDeploy = productionBlockers.length === 0;
|
|
1556
|
+
return {
|
|
1557
|
+
schemaVersion: "0.1.0",
|
|
1558
|
+
ok: readyToPublish,
|
|
1559
|
+
readyToPublish,
|
|
1560
|
+
readyForProductionDeploy,
|
|
1561
|
+
summary: {
|
|
1562
|
+
checks: checks.length,
|
|
1563
|
+
failed,
|
|
1564
|
+
notPrepared,
|
|
1565
|
+
publishBlockers,
|
|
1566
|
+
productionBlockers,
|
|
1567
|
+
},
|
|
1568
|
+
checks,
|
|
1569
|
+
nextActions: uniqueNextActions(checks.flatMap((check) => check.result.nextActions ?? [])),
|
|
1570
|
+
exitCode: readyToPublish ? 0 : 1,
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
function formatManifestHuman(result: {
|
|
1575
|
+
subcommand: "validate" | "import";
|
|
1576
|
+
path: string;
|
|
1577
|
+
imported?: boolean;
|
|
1578
|
+
serviceCount?: number;
|
|
1579
|
+
diagnostics: import("../compiler/types/diagnostic.ts").Diagnostic[];
|
|
1580
|
+
exitCode: number;
|
|
1581
|
+
}): string {
|
|
1582
|
+
const errors = result.diagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
1583
|
+
const warnings = result.diagnostics.filter((diagnostic) => diagnostic.severity === "warning");
|
|
1584
|
+
const lines = [
|
|
1585
|
+
`manifest: ${result.subcommand}`,
|
|
1586
|
+
`path: ${result.path}`,
|
|
1587
|
+
result.subcommand === "import" ? `imported: ${result.imported ? "yes" : "no"}` : null,
|
|
1588
|
+
result.serviceCount !== undefined ? `external services: ${result.serviceCount}` : null,
|
|
1589
|
+
`errors: ${errors.length}`,
|
|
1590
|
+
`warnings: ${warnings.length}`,
|
|
1591
|
+
].filter((line): line is string => line !== null);
|
|
1592
|
+
for (const diagnostic of result.diagnostics) {
|
|
1593
|
+
lines.push(`${diagnostic.severity} ${diagnostic.code}: ${diagnostic.message}`);
|
|
1594
|
+
}
|
|
1595
|
+
return `${lines.join("\n")}\n`;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
function runManifestCommand(command: Extract<ForgeCommand, { kind: "manifest" }>): {
|
|
1599
|
+
subcommand: "validate" | "import";
|
|
1600
|
+
path: string;
|
|
1601
|
+
imported?: boolean;
|
|
1602
|
+
serviceCount?: number;
|
|
1603
|
+
diagnostics: import("../compiler/types/diagnostic.ts").Diagnostic[];
|
|
1604
|
+
exitCode: number;
|
|
1605
|
+
} {
|
|
1606
|
+
if (command.subcommand === "validate") {
|
|
1607
|
+
const checked = readRepositoryManifest(command.workspaceRoot, { manifestPath: command.path });
|
|
1608
|
+
if (checked.manifest || checked.diagnostics.length) return { subcommand: "validate", path: command.path, diagnostics: checked.diagnostics.map(message => createDiagnostic({ severity: "error", code: "FORGE_REPOSITORY_MANIFEST", message })), exitCode: checked.manifest ? 0 : 1 };
|
|
1609
|
+
const result = readExternalManifestFile(command.path);
|
|
1610
|
+
const hasErrors = result.diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
1611
|
+
return {
|
|
1612
|
+
subcommand: "validate",
|
|
1613
|
+
path: command.path,
|
|
1614
|
+
diagnostics: result.diagnostics,
|
|
1615
|
+
exitCode: hasErrors ? 1 : 0,
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
const result = importExternalManifest(command.workspaceRoot, command.path);
|
|
1620
|
+
const hasErrors = result.diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
1621
|
+
return {
|
|
1622
|
+
subcommand: "import",
|
|
1623
|
+
path: result.path,
|
|
1624
|
+
imported: result.imported,
|
|
1625
|
+
serviceCount: result.graph.services.length,
|
|
1626
|
+
diagnostics: result.diagnostics,
|
|
1627
|
+
exitCode: hasErrors ? 1 : 0,
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
|
|
378
1631
|
export async function runInspectCommand(
|
|
379
1632
|
target: InspectTarget,
|
|
380
1633
|
workspaceRoot: string,
|
|
1634
|
+
options: { full?: boolean; brief?: boolean; ergonomics?: boolean } = {},
|
|
381
1635
|
): Promise<InspectResult> {
|
|
382
1636
|
const dataPaths: Partial<Record<InspectTarget, string>> = {
|
|
383
1637
|
app: `${GENERATED_DIR}/appGraph.json`,
|
|
@@ -396,6 +1650,7 @@ export async function runInspectCommand(
|
|
|
396
1650
|
ai: `${GENERATED_DIR}/aiRegistry.json`,
|
|
397
1651
|
queries: `${GENERATED_DIR}/queryRegistry.json`,
|
|
398
1652
|
api: `${GENERATED_DIR}/api.json`,
|
|
1653
|
+
external: `${GENERATED_DIR}/externalServices.json`,
|
|
399
1654
|
client: `${GENERATED_DIR}/clientManifest.json`,
|
|
400
1655
|
frontend: `${GENERATED_DIR}/frontendGraph.json`,
|
|
401
1656
|
auth: `${GENERATED_DIR}/authRegistry.json`,
|
|
@@ -431,7 +1686,155 @@ export async function runInspectCommand(
|
|
|
431
1686
|
};
|
|
432
1687
|
}
|
|
433
1688
|
|
|
1689
|
+
if (target === "summary") {
|
|
1690
|
+
return {
|
|
1691
|
+
target,
|
|
1692
|
+
data: buildInspectSummary(workspaceRoot),
|
|
1693
|
+
warnings: [],
|
|
1694
|
+
errors: [],
|
|
1695
|
+
exitCode: 0,
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
if (target === "schema") {
|
|
1700
|
+
const result = buildSchemaInspect(workspaceRoot);
|
|
1701
|
+
return {
|
|
1702
|
+
target,
|
|
1703
|
+
data: result.data,
|
|
1704
|
+
warnings: [],
|
|
1705
|
+
errors: result.errors,
|
|
1706
|
+
exitCode: result.errors.length > 0 ? 1 : 0,
|
|
1707
|
+
failureKind: result.errors.length > 0 ? "missing_artifact" : undefined,
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
if (target === "drift") {
|
|
1712
|
+
return {
|
|
1713
|
+
target,
|
|
1714
|
+
data: buildDriftInspect(workspaceRoot),
|
|
1715
|
+
warnings: [],
|
|
1716
|
+
errors: [],
|
|
1717
|
+
exitCode: 0,
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
if (target === "handoff") {
|
|
1722
|
+
return {
|
|
1723
|
+
target,
|
|
1724
|
+
data: buildHandoffInspect(workspaceRoot),
|
|
1725
|
+
warnings: [],
|
|
1726
|
+
errors: [],
|
|
1727
|
+
exitCode: 0,
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
if (target === "ui" && options.ergonomics) {
|
|
1732
|
+
const result = await runUiCommand({
|
|
1733
|
+
subcommand: "audit",
|
|
1734
|
+
workspaceRoot,
|
|
1735
|
+
json: true,
|
|
1736
|
+
headed: false,
|
|
1737
|
+
browser: "chromium",
|
|
1738
|
+
trace: "off",
|
|
1739
|
+
screenshot: "off",
|
|
1740
|
+
video: "off",
|
|
1741
|
+
baseUrl: "http://127.0.0.1:3000",
|
|
1742
|
+
runtimeUrl: "http://127.0.0.1:3765",
|
|
1743
|
+
reuseServers: false,
|
|
1744
|
+
startServers: false,
|
|
1745
|
+
all: true,
|
|
1746
|
+
changed: false,
|
|
1747
|
+
ci: false,
|
|
1748
|
+
timeoutMs: 30_000,
|
|
1749
|
+
});
|
|
1750
|
+
return {
|
|
1751
|
+
target,
|
|
1752
|
+
data: {
|
|
1753
|
+
schemaVersion: "0.1.0",
|
|
1754
|
+
mode: "ergonomics",
|
|
1755
|
+
ok: result.ok,
|
|
1756
|
+
manifest: result.manifest,
|
|
1757
|
+
scenarios: result.scenarios ?? [],
|
|
1758
|
+
diagnostics: result.diagnostics,
|
|
1759
|
+
nextActions: [
|
|
1760
|
+
"forge ui audit --json",
|
|
1761
|
+
"forge inspect frontend --json",
|
|
1762
|
+
"forge inspect capabilities --json",
|
|
1763
|
+
],
|
|
1764
|
+
},
|
|
1765
|
+
warnings: result.diagnostics.filter((diagnostic) => diagnostic.severity === "warning"),
|
|
1766
|
+
errors: result.diagnostics.filter((diagnostic) => diagnostic.severity === "error"),
|
|
1767
|
+
exitCode: result.exitCode,
|
|
1768
|
+
failureKind: result.exitCode === 0 ? undefined : "ui_ergonomics",
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
if (target === "imported") {
|
|
1773
|
+
const result = inspectBrownfieldImport(workspaceRoot);
|
|
1774
|
+
return {
|
|
1775
|
+
target,
|
|
1776
|
+
data: formatBrownfieldImportJson(result),
|
|
1777
|
+
warnings: [],
|
|
1778
|
+
errors: [],
|
|
1779
|
+
exitCode: result.exitCode,
|
|
1780
|
+
failureKind: result.failureKind,
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
|
|
434
1784
|
if (target === "all") {
|
|
1785
|
+
if (options.brief) {
|
|
1786
|
+
const brief = buildInspectBrief(workspaceRoot);
|
|
1787
|
+
return {
|
|
1788
|
+
target,
|
|
1789
|
+
data: brief,
|
|
1790
|
+
warnings: [],
|
|
1791
|
+
errors: [],
|
|
1792
|
+
exitCode: 0,
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
if (!options.full) {
|
|
1796
|
+
const summary = buildInspectSummary(workspaceRoot);
|
|
1797
|
+
const schema = buildSchemaInspect(workspaceRoot);
|
|
1798
|
+
const drift = buildDriftInspect(workspaceRoot);
|
|
1799
|
+
const handoff = buildHandoffInspect(workspaceRoot);
|
|
1800
|
+
const framework = buildFrameworkInspect(workspaceRoot);
|
|
1801
|
+
const errors = [
|
|
1802
|
+
...schema.errors,
|
|
1803
|
+
];
|
|
1804
|
+
return {
|
|
1805
|
+
target,
|
|
1806
|
+
data: {
|
|
1807
|
+
schemaVersion: "0.1.0",
|
|
1808
|
+
compact: true,
|
|
1809
|
+
payload: {
|
|
1810
|
+
mode: "compact",
|
|
1811
|
+
purpose: "agent diagnostic bundle",
|
|
1812
|
+
includes: ["summary", "schema", "drift", "handoff", "framework"],
|
|
1813
|
+
omitted: ["large generated registries", "module graph", "full runtime graph payloads"],
|
|
1814
|
+
fullCommand: "forge inspect all --full --json",
|
|
1815
|
+
briefCommand: "forge inspect all --brief --json",
|
|
1816
|
+
},
|
|
1817
|
+
summary: summary.summary,
|
|
1818
|
+
inspections: {
|
|
1819
|
+
summary,
|
|
1820
|
+
schema: schema.data,
|
|
1821
|
+
drift,
|
|
1822
|
+
handoff,
|
|
1823
|
+
framework,
|
|
1824
|
+
},
|
|
1825
|
+
nextActions: [
|
|
1826
|
+
"forge inspect summary --json",
|
|
1827
|
+
"forge inspect schema --json",
|
|
1828
|
+
"forge inspect handoff --json",
|
|
1829
|
+
"forge inspect all --full --json",
|
|
1830
|
+
],
|
|
1831
|
+
},
|
|
1832
|
+
warnings: [],
|
|
1833
|
+
errors,
|
|
1834
|
+
exitCode: errors.length > 0 ? 1 : 0,
|
|
1835
|
+
failureKind: errors.length > 0 ? "missing_artifact" : undefined,
|
|
1836
|
+
};
|
|
1837
|
+
}
|
|
435
1838
|
const aggregatePaths: Array<[string, string]> = [
|
|
436
1839
|
["app", `${GENERATED_DIR}/appGraph.json`],
|
|
437
1840
|
["data", `${GENERATED_DIR}/dataGraph.json`],
|
|
@@ -443,6 +1846,7 @@ export async function runInspectCommand(
|
|
|
443
1846
|
["workflows", `${GENERATED_DIR}/workflowRegistry.json`],
|
|
444
1847
|
["telemetry", `${GENERATED_DIR}/telemetryRegistry.json`],
|
|
445
1848
|
["ai", `${GENERATED_DIR}/aiRegistry.json`],
|
|
1849
|
+
["externalServices", `${GENERATED_DIR}/externalServices.json`],
|
|
446
1850
|
["client", `${GENERATED_DIR}/clientManifest.json`],
|
|
447
1851
|
["frontend", `${GENERATED_DIR}/frontendGraph.json`],
|
|
448
1852
|
["auth", `${GENERATED_DIR}/authRegistry.json`],
|
|
@@ -467,6 +1871,7 @@ export async function runInspectCommand(
|
|
|
467
1871
|
];
|
|
468
1872
|
const data: Record<string, unknown> = {};
|
|
469
1873
|
const errors = [];
|
|
1874
|
+
data.summary = buildInspectSummary(workspaceRoot).summary;
|
|
470
1875
|
for (const [key, relative] of aggregatePaths) {
|
|
471
1876
|
const value = readGeneratedJson<unknown>(workspaceRoot, relative);
|
|
472
1877
|
if (value === null) {
|
|
@@ -484,6 +1889,17 @@ export async function runInspectCommand(
|
|
|
484
1889
|
}
|
|
485
1890
|
data.framework = buildFrameworkInspect(workspaceRoot);
|
|
486
1891
|
data.diagnostics = errors;
|
|
1892
|
+
data.compact = false;
|
|
1893
|
+
data.payload = {
|
|
1894
|
+
mode: "full",
|
|
1895
|
+
purpose: "complete generated machine contract",
|
|
1896
|
+
includes: aggregatePaths.map(([key]) => key),
|
|
1897
|
+
compactCommand: "forge inspect all --json",
|
|
1898
|
+
briefCommand: "forge inspect all --brief --json",
|
|
1899
|
+
};
|
|
1900
|
+
data.nextActions = errors.length > 0
|
|
1901
|
+
? ["forge status --json", "forge generate", "forge check --json"]
|
|
1902
|
+
: ["forge inspect all --json", "forge check --json"];
|
|
487
1903
|
return {
|
|
488
1904
|
target,
|
|
489
1905
|
data,
|
|
@@ -557,6 +1973,16 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
557
1973
|
}
|
|
558
1974
|
return 0;
|
|
559
1975
|
}
|
|
1976
|
+
case "last": {
|
|
1977
|
+
const result = runLastCommand({ workspaceRoot: command.workspaceRoot });
|
|
1978
|
+
process.stdout.write(command.json ? formatLastJson(result) : formatLastHuman(result));
|
|
1979
|
+
return result.exitCode;
|
|
1980
|
+
}
|
|
1981
|
+
case "baseline": {
|
|
1982
|
+
const result = runBaselineCommand(command);
|
|
1983
|
+
process.stdout.write(command.json ? formatBaselineJson(result) : formatBaselineHuman(result));
|
|
1984
|
+
return result.exitCode;
|
|
1985
|
+
}
|
|
560
1986
|
case "new": {
|
|
561
1987
|
const result = await runNewCommand({
|
|
562
1988
|
name: command.name,
|
|
@@ -564,11 +1990,12 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
564
1990
|
packageManager: command.packageManager,
|
|
565
1991
|
install: command.install,
|
|
566
1992
|
git: command.git,
|
|
1993
|
+
fieldTest: command.fieldTest,
|
|
567
1994
|
forgePackageSpec: command.forgePackageSpec,
|
|
568
1995
|
localForge: command.localForge,
|
|
569
1996
|
workspaceRoot: command.workspaceRoot,
|
|
570
1997
|
});
|
|
571
|
-
process.stdout.write(formatNewHuman(result));
|
|
1998
|
+
process.stdout.write(command.json ? formatNewJson(result) : formatNewHuman(result));
|
|
572
1999
|
return result.exitCode;
|
|
573
2000
|
}
|
|
574
2001
|
case "build": {
|
|
@@ -598,6 +2025,15 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
598
2025
|
}
|
|
599
2026
|
return result.exitCode;
|
|
600
2027
|
}
|
|
2028
|
+
case "docs": {
|
|
2029
|
+
const result = runDocsCheckCommand(command);
|
|
2030
|
+
if (command.json) {
|
|
2031
|
+
process.stdout.write(formatJsonResult(result));
|
|
2032
|
+
} else {
|
|
2033
|
+
process.stdout.write(formatDocsCheckHuman(result));
|
|
2034
|
+
}
|
|
2035
|
+
return result.exitCode;
|
|
2036
|
+
}
|
|
601
2037
|
case "agent-contract": {
|
|
602
2038
|
if (command.subcommand === "print") {
|
|
603
2039
|
const result = runAgentContractPrint(command.workspaceRoot);
|
|
@@ -617,7 +2053,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
617
2053
|
concurrency: 4,
|
|
618
2054
|
});
|
|
619
2055
|
if (command.json) {
|
|
620
|
-
process.stdout.write(formatJsonResult(buildGenerateJson(result)));
|
|
2056
|
+
process.stdout.write(formatJsonResult(buildGenerateJson(result, { workspaceRoot: command.workspaceRoot })));
|
|
621
2057
|
} else {
|
|
622
2058
|
process.stdout.write(formatAgentContractHuman(command.subcommand, result));
|
|
623
2059
|
writeHumanGenerate(result);
|
|
@@ -625,6 +2061,25 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
625
2061
|
return result.exitCode;
|
|
626
2062
|
}
|
|
627
2063
|
case "doctor": {
|
|
2064
|
+
if (command.target === "agent") {
|
|
2065
|
+
const result = await runAgentCommand({
|
|
2066
|
+
subcommand: "doctor",
|
|
2067
|
+
workspaceRoot: command.workspaceRoot,
|
|
2068
|
+
json: command.json,
|
|
2069
|
+
target: command.agentTarget ?? "codex",
|
|
2070
|
+
dryRun: false,
|
|
2071
|
+
force: false,
|
|
2072
|
+
preserveUserSections: true,
|
|
2073
|
+
skills: true,
|
|
2074
|
+
rules: true,
|
|
2075
|
+
});
|
|
2076
|
+
if (command.json) {
|
|
2077
|
+
process.stdout.write(formatAgentJson(result));
|
|
2078
|
+
} else {
|
|
2079
|
+
process.stdout.write(formatAgentHuman(result));
|
|
2080
|
+
}
|
|
2081
|
+
return result.exitCode;
|
|
2082
|
+
}
|
|
628
2083
|
if (command.target === "windows") {
|
|
629
2084
|
const result = await runWindowsDoctorCommand({ workspaceRoot: command.workspaceRoot });
|
|
630
2085
|
if (command.json) {
|
|
@@ -634,6 +2089,21 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
634
2089
|
}
|
|
635
2090
|
return result.exitCode;
|
|
636
2091
|
}
|
|
2092
|
+
if (command.target === "delta") {
|
|
2093
|
+
const result = await runDeltaDoctor(command.workspaceRoot);
|
|
2094
|
+
process.stdout.write(command.json ? formatDeltaDoctorJson(result) : formatDeltaDoctorHuman(result));
|
|
2095
|
+
return result.exitCode;
|
|
2096
|
+
}
|
|
2097
|
+
if (command.target === "pglite") {
|
|
2098
|
+
const result = await runPgliteDoctorCommand({ workspaceRoot: command.workspaceRoot });
|
|
2099
|
+
process.stdout.write(command.json ? formatPgliteDoctorJson(result) : formatPgliteDoctorHuman(result));
|
|
2100
|
+
return result.exitCode;
|
|
2101
|
+
}
|
|
2102
|
+
if (command.target === "runtime") {
|
|
2103
|
+
const result = await runRuntimeDoctorCommand({ workspaceRoot: command.workspaceRoot });
|
|
2104
|
+
process.stdout.write(command.json ? formatRuntimeDoctorJson(result) : formatRuntimeDoctorHuman(result));
|
|
2105
|
+
return result.exitCode;
|
|
2106
|
+
}
|
|
637
2107
|
const result = await runDoctorCommand({ workspaceRoot: command.workspaceRoot });
|
|
638
2108
|
if (command.json) {
|
|
639
2109
|
process.stdout.write(formatDoctorJson(result));
|
|
@@ -672,6 +2142,44 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
672
2142
|
}
|
|
673
2143
|
return result.exitCode;
|
|
674
2144
|
}
|
|
2145
|
+
case "authmd": {
|
|
2146
|
+
const result = runAuthMdCommand(command);
|
|
2147
|
+
if (command.json) {
|
|
2148
|
+
process.stdout.write(formatAuthMdJson(result));
|
|
2149
|
+
} else {
|
|
2150
|
+
process.stdout.write(formatAuthMdHuman(result));
|
|
2151
|
+
}
|
|
2152
|
+
return result.exitCode;
|
|
2153
|
+
}
|
|
2154
|
+
case "workos": {
|
|
2155
|
+
const result = runWorkOSCommand(command);
|
|
2156
|
+
if (command.json) {
|
|
2157
|
+
process.stdout.write(formatWorkOSJson(result));
|
|
2158
|
+
} else {
|
|
2159
|
+
process.stdout.write(formatWorkOSHuman(result));
|
|
2160
|
+
}
|
|
2161
|
+
return result.exitCode;
|
|
2162
|
+
}
|
|
2163
|
+
case "deploy": {
|
|
2164
|
+
const result = await runDeployCommand(command);
|
|
2165
|
+
process.stdout.write(command.json ? formatDeployJson(result) : formatDeployHuman(result));
|
|
2166
|
+
return result.exitCode;
|
|
2167
|
+
}
|
|
2168
|
+
case "golden-path": {
|
|
2169
|
+
const result = await runGoldenPathCommand(command);
|
|
2170
|
+
process.stdout.write(command.json ? formatGoldenPathJson(result) : formatGoldenPathHuman(result));
|
|
2171
|
+
return result.exitCode;
|
|
2172
|
+
}
|
|
2173
|
+
case "field-test": {
|
|
2174
|
+
const result = await runFieldTestCommand(command);
|
|
2175
|
+
process.stdout.write(command.json ? formatFieldTestJson(result) : formatFieldTestHuman(result));
|
|
2176
|
+
return result.exitCode;
|
|
2177
|
+
}
|
|
2178
|
+
case "seed": {
|
|
2179
|
+
const result = await runSeedCommand(command);
|
|
2180
|
+
process.stdout.write(command.json ? formatSeedJson(result) : formatSeedHuman(result));
|
|
2181
|
+
return result.exitCode;
|
|
2182
|
+
}
|
|
675
2183
|
case "rls": {
|
|
676
2184
|
const result = await runRlsCommand(command);
|
|
677
2185
|
if (command.json) {
|
|
@@ -691,6 +2199,30 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
691
2199
|
return result.exitCode;
|
|
692
2200
|
}
|
|
693
2201
|
case "release": {
|
|
2202
|
+
if (command.action === "doctor") {
|
|
2203
|
+
const result = await runReleaseDoctorCommand(command);
|
|
2204
|
+
if (command.json) {
|
|
2205
|
+
process.stdout.write(formatJsonResult(result));
|
|
2206
|
+
} else {
|
|
2207
|
+
process.stdout.write(
|
|
2208
|
+
[
|
|
2209
|
+
`release doctor ${result.ok ? "ok" : "failed"}`,
|
|
2210
|
+
`ready to publish: ${result.readyToPublish ? "yes" : "no"}`,
|
|
2211
|
+
`ready for production deploy: ${result.readyForProductionDeploy ? "yes" : "no"}`,
|
|
2212
|
+
...result.checks.map((check) => {
|
|
2213
|
+
const scope = check.requiredForPublish
|
|
2214
|
+
? "publish"
|
|
2215
|
+
: check.requiredForProduction
|
|
2216
|
+
? "production"
|
|
2217
|
+
: "optional";
|
|
2218
|
+
return `${check.ok ? "ok" : "fail"} ${check.name} [${scope}]${check.state ? ` (${check.state})` : ""}`;
|
|
2219
|
+
}),
|
|
2220
|
+
...(result.nextActions.length > 0 ? ["", "Next:", ...result.nextActions.map((action) => ` ${action}`)] : []),
|
|
2221
|
+
].join("\n").concat("\n"),
|
|
2222
|
+
);
|
|
2223
|
+
}
|
|
2224
|
+
return result.exitCode;
|
|
2225
|
+
}
|
|
694
2226
|
const result = await runReleaseCommand({
|
|
695
2227
|
...command,
|
|
696
2228
|
provider: command.provider as import("../compiler/release/types.ts").ReleaseExportProvider | undefined,
|
|
@@ -766,19 +2298,143 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
766
2298
|
}
|
|
767
2299
|
return result.exitCode;
|
|
768
2300
|
}
|
|
769
|
-
case "
|
|
770
|
-
const result = await
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
2301
|
+
case "bench": {
|
|
2302
|
+
const result = await runCompilerBenchCommand(command.options);
|
|
2303
|
+
process.stdout.write(
|
|
2304
|
+
command.options.json
|
|
2305
|
+
? formatCompilerBenchJson(result)
|
|
2306
|
+
: formatCompilerBenchHuman(result),
|
|
2307
|
+
);
|
|
2308
|
+
return result.exitCode;
|
|
2309
|
+
}
|
|
2310
|
+
case "cair": {
|
|
2311
|
+
let root: string;
|
|
2312
|
+
try { root = await resolveRepositoryRoot({ cwd: command.options.workspaceRoot, root: command.options.root, projectId: command.options.projectId, manifestPath: command.options.manifestPath }); }
|
|
2313
|
+
catch (error) {
|
|
2314
|
+
const diagnostic = createDiagnostic({ severity: "error", code: "FORGE_REPOSITORY_ROOT", message: (error as Error).message });
|
|
2315
|
+
if (command.options.json || command.options.format === "json") process.stdout.write(formatJsonResult({ ok: false, diagnostics: [diagnostic], exitCode: 1 }));
|
|
2316
|
+
else console.error(`error ${diagnostic.code}: ${diagnostic.message}`);
|
|
2317
|
+
return 1;
|
|
2318
|
+
}
|
|
2319
|
+
const repository = readRepositoryManifest(root, { manifestPath: command.options.manifestPath });
|
|
2320
|
+
if (repository.manifest || repository.diagnostics.length || command.options.root || command.options.projectId) command.options.workspaceRoot = root;
|
|
2321
|
+
const result = runCairCommand(command.options);
|
|
2322
|
+
process.stdout.write(
|
|
2323
|
+
command.options.json || command.options.format === "json"
|
|
2324
|
+
? formatCairJson(result)
|
|
2325
|
+
: formatCairHuman(result),
|
|
2326
|
+
);
|
|
2327
|
+
return result.exitCode;
|
|
2328
|
+
}
|
|
2329
|
+
case "delta": {
|
|
2330
|
+
if (command.subcommand === "compact") {
|
|
2331
|
+
const result = await runDeltaCompact({
|
|
2332
|
+
workspaceRoot: command.workspaceRoot,
|
|
2333
|
+
dryRun: command.dryRun,
|
|
2334
|
+
});
|
|
2335
|
+
process.stdout.write(command.json ? formatDeltaCompactJson(result) : formatDeltaCompactHuman(result));
|
|
2336
|
+
return result.exitCode;
|
|
2337
|
+
}
|
|
2338
|
+
if (command.subcommand === "prune") {
|
|
2339
|
+
const result = await runDeltaPrune({
|
|
2340
|
+
workspaceRoot: command.workspaceRoot,
|
|
2341
|
+
olderThan: command.olderThan,
|
|
2342
|
+
dryRun: command.dryRun,
|
|
2343
|
+
yes: command.yes,
|
|
2344
|
+
});
|
|
2345
|
+
process.stdout.write(command.json ? formatDeltaPruneJson(result) : formatDeltaPruneHuman(result));
|
|
2346
|
+
return result.exitCode;
|
|
775
2347
|
}
|
|
2348
|
+
if (command.subcommand === "export") {
|
|
2349
|
+
const result = await runDeltaExport({
|
|
2350
|
+
workspaceRoot: command.workspaceRoot,
|
|
2351
|
+
redacted: command.redacted,
|
|
2352
|
+
output: command.output,
|
|
2353
|
+
limit: command.limit,
|
|
2354
|
+
});
|
|
2355
|
+
process.stdout.write(command.json ? formatDeltaExportJson(result) : formatDeltaExportHuman(result));
|
|
2356
|
+
return result.exitCode;
|
|
2357
|
+
}
|
|
2358
|
+
if (command.subcommand === "repair") {
|
|
2359
|
+
const result = await runDeltaRepair({
|
|
2360
|
+
workspaceRoot: command.workspaceRoot,
|
|
2361
|
+
dryRun: command.dryRun,
|
|
2362
|
+
yes: command.yes,
|
|
2363
|
+
});
|
|
2364
|
+
process.stdout.write(command.json ? formatDeltaRepairJson(result) : formatDeltaRepairHuman(result));
|
|
2365
|
+
return result.exitCode;
|
|
2366
|
+
}
|
|
2367
|
+
const result = await runDeltaStatus(command.workspaceRoot, { verbose: command.verbose });
|
|
2368
|
+
process.stdout.write(command.json ? formatDeltaStatusJson(result) : formatDeltaStatusHuman(result));
|
|
2369
|
+
return result.exitCode;
|
|
2370
|
+
}
|
|
2371
|
+
case "session": {
|
|
2372
|
+
const result = await runDeltaSessionCommand({
|
|
2373
|
+
workspaceRoot: command.workspaceRoot,
|
|
2374
|
+
subcommand: command.subcommand,
|
|
2375
|
+
sessionId: command.sessionId,
|
|
2376
|
+
sourceSessionId: command.sourceSessionId,
|
|
2377
|
+
operationId: command.operationId,
|
|
2378
|
+
title: command.title,
|
|
2379
|
+
limit: command.limit,
|
|
2380
|
+
});
|
|
2381
|
+
process.stdout.write(command.json ? formatDeltaSessionJson(result) : formatDeltaSessionHuman(result));
|
|
776
2382
|
return result.exitCode;
|
|
777
2383
|
}
|
|
2384
|
+
case "timeline": {
|
|
2385
|
+
const result = await runDeltaTimeline({
|
|
2386
|
+
workspaceRoot: command.workspaceRoot,
|
|
2387
|
+
target: command.target,
|
|
2388
|
+
kind: command.kindFilter,
|
|
2389
|
+
session: command.sessionId,
|
|
2390
|
+
limit: command.limit,
|
|
2391
|
+
rebuild: command.rebuild,
|
|
2392
|
+
causal: command.causal,
|
|
2393
|
+
staleProofs: command.staleProofs,
|
|
2394
|
+
});
|
|
2395
|
+
process.stdout.write(command.json ? formatDeltaTimelineJson(result) : formatDeltaTimelineHuman(result));
|
|
2396
|
+
return result.exitCode;
|
|
2397
|
+
}
|
|
2398
|
+
case "explain": {
|
|
2399
|
+
const result = await runDeltaExplain({
|
|
2400
|
+
workspaceRoot: command.workspaceRoot,
|
|
2401
|
+
thing: command.thing,
|
|
2402
|
+
});
|
|
2403
|
+
process.stdout.write(command.json ? formatDeltaExplainJson(result) : formatDeltaExplainHuman(result));
|
|
2404
|
+
return result.exitCode;
|
|
2405
|
+
}
|
|
2406
|
+
case "agent": {
|
|
2407
|
+
const heartbeat = command.options.subcommand === "onboard"
|
|
2408
|
+
? startCommandHeartbeat({
|
|
2409
|
+
label: `agent onboard ${command.options.target ?? "codex"}`,
|
|
2410
|
+
initialPhase: "prepare-hooks-memory-and-dev-snapshot",
|
|
2411
|
+
})
|
|
2412
|
+
: null;
|
|
2413
|
+
try {
|
|
2414
|
+
const result = await runAgentCommand(command.options);
|
|
2415
|
+
if (command.options.json) {
|
|
2416
|
+
process.stdout.write(formatAgentJson(result));
|
|
2417
|
+
} else {
|
|
2418
|
+
process.stdout.write(formatAgentHuman(result));
|
|
2419
|
+
}
|
|
2420
|
+
return result.exitCode;
|
|
2421
|
+
} finally {
|
|
2422
|
+
heartbeat?.stop();
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
case "fabric": {
|
|
2426
|
+
return runFabricCommand(command);
|
|
2427
|
+
}
|
|
2428
|
+
case "evolution": {
|
|
2429
|
+
return runEvolutionCommand(command);
|
|
2430
|
+
}
|
|
2431
|
+
case "mcp": {
|
|
2432
|
+
return runMcpServe(command.workspaceRoot);
|
|
2433
|
+
}
|
|
778
2434
|
case "review": {
|
|
779
2435
|
const result = runReviewCommand(command.options);
|
|
780
2436
|
if (command.options.json) {
|
|
781
|
-
process.stdout.write(formatReviewJson(result));
|
|
2437
|
+
process.stdout.write(formatReviewJson(result, { full: command.options.full }));
|
|
782
2438
|
} else if (command.options.md && result.report) {
|
|
783
2439
|
process.stdout.write(renderReviewMarkdown(result.report));
|
|
784
2440
|
} else if (command.options.sarif && result.report && !command.options.write) {
|
|
@@ -802,7 +2458,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
802
2458
|
}
|
|
803
2459
|
case "generate": {
|
|
804
2460
|
const result = await runGenerateCommand({
|
|
805
|
-
workspaceRoot:
|
|
2461
|
+
workspaceRoot: command.workspaceRoot,
|
|
806
2462
|
check: command.check,
|
|
807
2463
|
dryRun: command.dryRun,
|
|
808
2464
|
json: command.json,
|
|
@@ -810,7 +2466,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
810
2466
|
});
|
|
811
2467
|
|
|
812
2468
|
if (command.json) {
|
|
813
|
-
process.stdout.write(formatJsonResult(buildGenerateJson(result)));
|
|
2469
|
+
process.stdout.write(formatJsonResult(buildGenerateJson(result, { workspaceRoot: command.workspaceRoot })));
|
|
814
2470
|
} else {
|
|
815
2471
|
writeHumanGenerate(result);
|
|
816
2472
|
}
|
|
@@ -820,16 +2476,162 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
820
2476
|
case "add": {
|
|
821
2477
|
const result = await runAddCommand(command.alias, command.options);
|
|
822
2478
|
if (command.options.json) {
|
|
823
|
-
process.stdout.write(formatJsonResult(buildAddJson(result)));
|
|
2479
|
+
process.stdout.write(formatJsonResult(buildAddJson(result, { workspaceRoot: command.options.workspaceRoot })));
|
|
824
2480
|
} else {
|
|
825
2481
|
writeHumanAdd(result);
|
|
826
2482
|
}
|
|
827
2483
|
return result.exitCode;
|
|
828
2484
|
}
|
|
2485
|
+
case "manifest": {
|
|
2486
|
+
const result = runManifestCommand(command);
|
|
2487
|
+
if (command.json) {
|
|
2488
|
+
process.stdout.write(formatJsonResult(result));
|
|
2489
|
+
} else {
|
|
2490
|
+
process.stdout.write(formatManifestHuman(result));
|
|
2491
|
+
}
|
|
2492
|
+
return result.exitCode;
|
|
2493
|
+
}
|
|
2494
|
+
case "repository": {
|
|
2495
|
+
const result = await runRepositoryCommand(command.options);
|
|
2496
|
+
process.stdout.write(`${JSON.stringify(result, null, command.options.json ? 2 : 2)}\n`);
|
|
2497
|
+
return result.exitCode;
|
|
2498
|
+
}
|
|
2499
|
+
case "import": {
|
|
2500
|
+
const result = runBrownfieldImportCommand(command.options);
|
|
2501
|
+
if (command.options.json) {
|
|
2502
|
+
process.stdout.write(formatJsonResult(formatBrownfieldImportJson(result)));
|
|
2503
|
+
} else {
|
|
2504
|
+
process.stdout.write(formatBrownfieldImportHuman(result));
|
|
2505
|
+
}
|
|
2506
|
+
return result.exitCode;
|
|
2507
|
+
}
|
|
2508
|
+
case "status": {
|
|
2509
|
+
const result = await runStatusCommand(command.workspaceRoot);
|
|
2510
|
+
if (command.json) {
|
|
2511
|
+
process.stdout.write(formatJsonResult(result.data));
|
|
2512
|
+
} else {
|
|
2513
|
+
process.stdout.write(formatStatusHuman(result));
|
|
2514
|
+
}
|
|
2515
|
+
return result.exitCode;
|
|
2516
|
+
}
|
|
2517
|
+
case "changed": {
|
|
2518
|
+
const result = runChangedCommand(command.workspaceRoot, {
|
|
2519
|
+
authoredOnly: command.authoredOnly,
|
|
2520
|
+
reviewOnly: command.reviewOnly,
|
|
2521
|
+
commitReady: command.commitReady,
|
|
2522
|
+
});
|
|
2523
|
+
if (command.json) {
|
|
2524
|
+
process.stdout.write(formatJsonResult(result.data));
|
|
2525
|
+
} else {
|
|
2526
|
+
process.stdout.write(formatChangedHuman(result));
|
|
2527
|
+
}
|
|
2528
|
+
return result.exitCode;
|
|
2529
|
+
}
|
|
2530
|
+
case "diff": {
|
|
2531
|
+
const changed = runChangedCommand(command.workspaceRoot);
|
|
2532
|
+
const diffPlan = changed.data.diffPlan as { authoredDiffCommand: string; generatedDiffCommand: string; fullDiffCommand: string };
|
|
2533
|
+
const gitSummary = command.target === "authored" ? buildWorkspaceGitSummary(command.workspaceRoot) : null;
|
|
2534
|
+
const authoredPaths = gitSummary ? authoredChangePaths(gitSummary.changeSummary.changed) : null;
|
|
2535
|
+
const authoredAvailable = command.target !== "authored" || (gitSummary?.available === true && authoredPaths !== null);
|
|
2536
|
+
const exitCode = changed.exitCode === 0 && authoredAvailable ? 0 : 1;
|
|
2537
|
+
const commandText = command.target === "generated"
|
|
2538
|
+
? diffPlan.generatedDiffCommand
|
|
2539
|
+
: command.target === "full"
|
|
2540
|
+
? diffPlan.fullDiffCommand
|
|
2541
|
+
: diffPlan.authoredDiffCommand;
|
|
2542
|
+
if (command.json) {
|
|
2543
|
+
process.stdout.write(formatJsonResult({
|
|
2544
|
+
schemaVersion: "0.1.0",
|
|
2545
|
+
ok: exitCode === 0,
|
|
2546
|
+
target: command.target,
|
|
2547
|
+
command: commandText,
|
|
2548
|
+
exitCode,
|
|
2549
|
+
}));
|
|
2550
|
+
return exitCode;
|
|
2551
|
+
}
|
|
2552
|
+
if (command.target === "authored") {
|
|
2553
|
+
if (!authoredAvailable || !authoredPaths) return 1;
|
|
2554
|
+
if (authoredPaths.length === 0) return 0;
|
|
2555
|
+
const result = spawnSync("git", ["diff", "--", ...authoredPaths.map((file) => `:(top,literal)${file}`)], {
|
|
2556
|
+
cwd: command.workspaceRoot,
|
|
2557
|
+
stdio: "inherit",
|
|
2558
|
+
windowsHide: true,
|
|
2559
|
+
});
|
|
2560
|
+
return result.status === 0 ? 0 : 1;
|
|
2561
|
+
}
|
|
2562
|
+
const result = spawnSync(commandText, {
|
|
2563
|
+
cwd: command.workspaceRoot,
|
|
2564
|
+
shell: true,
|
|
2565
|
+
stdio: "inherit",
|
|
2566
|
+
windowsHide: true,
|
|
2567
|
+
});
|
|
2568
|
+
return result.status === 0 ? 0 : 1;
|
|
2569
|
+
}
|
|
2570
|
+
case "handoff": {
|
|
2571
|
+
const result = await runHandoffCommand(command);
|
|
2572
|
+
process.stdout.write(command.json ? formatHandoffJson(result) : formatHandoffHuman(result));
|
|
2573
|
+
return result.exitCode;
|
|
2574
|
+
}
|
|
2575
|
+
case "studio": {
|
|
2576
|
+
if (command.subcommand === "bridge" && !command.once && !command.dryRun) {
|
|
2577
|
+
return runStudioBridgeLoop(command, (result) => {
|
|
2578
|
+
process.stdout.write(command.json ? formatStudioBridgeEventJson(result) : formatStudioBridgeHuman(result));
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
if (command.subcommand === "watch" && !command.once && !command.dryRun) {
|
|
2582
|
+
return runStudioWatchLoop(command, (result) => {
|
|
2583
|
+
process.stdout.write(command.json ? formatStudioWatchJson(result) : formatStudioWatchHuman(result));
|
|
2584
|
+
});
|
|
2585
|
+
}
|
|
2586
|
+
const result = command.subcommand === "snapshot"
|
|
2587
|
+
? await runStudioSnapshotCommand(command)
|
|
2588
|
+
: command.subcommand === "watch"
|
|
2589
|
+
? await runStudioWatchCommand(command)
|
|
2590
|
+
: command.subcommand === "bridge"
|
|
2591
|
+
? await runStudioBridgeCommand(command)
|
|
2592
|
+
: command.subcommand === "codex-server"
|
|
2593
|
+
? await runStudioCodexServerCommand(command)
|
|
2594
|
+
: command.subcommand === "doctor"
|
|
2595
|
+
? await runStudioDoctorCommand(command)
|
|
2596
|
+
: command.subcommand === "open"
|
|
2597
|
+
? await runStudioOpenCommand(command)
|
|
2598
|
+
: await runStudioAttachCommand(command);
|
|
2599
|
+
process.stdout.write(
|
|
2600
|
+
command.json
|
|
2601
|
+
? command.subcommand === "snapshot"
|
|
2602
|
+
? formatStudioSnapshotJson(result as Awaited<ReturnType<typeof runStudioSnapshotCommand>>)
|
|
2603
|
+
: command.subcommand === "watch"
|
|
2604
|
+
? formatStudioWatchJson(result as Awaited<ReturnType<typeof runStudioWatchCommand>>)
|
|
2605
|
+
: command.subcommand === "bridge"
|
|
2606
|
+
? formatStudioBridgeJson(result as Awaited<ReturnType<typeof runStudioBridgeCommand>>)
|
|
2607
|
+
: command.subcommand === "codex-server"
|
|
2608
|
+
? formatStudioCodexServerJson(result as Awaited<ReturnType<typeof runStudioCodexServerCommand>>)
|
|
2609
|
+
: command.subcommand === "doctor"
|
|
2610
|
+
? formatStudioDoctorJson(result as Awaited<ReturnType<typeof runStudioDoctorCommand>>)
|
|
2611
|
+
: command.subcommand === "open"
|
|
2612
|
+
? formatStudioOpenJson(result as Awaited<ReturnType<typeof runStudioOpenCommand>>)
|
|
2613
|
+
: formatStudioAttachJson(result as Awaited<ReturnType<typeof runStudioAttachCommand>>)
|
|
2614
|
+
: command.subcommand === "snapshot"
|
|
2615
|
+
? formatStudioSnapshotHuman(result as Awaited<ReturnType<typeof runStudioSnapshotCommand>>)
|
|
2616
|
+
: command.subcommand === "watch"
|
|
2617
|
+
? formatStudioWatchHuman(result as Awaited<ReturnType<typeof runStudioWatchCommand>>)
|
|
2618
|
+
: command.subcommand === "bridge"
|
|
2619
|
+
? formatStudioBridgeHuman(result as Awaited<ReturnType<typeof runStudioBridgeCommand>>)
|
|
2620
|
+
: command.subcommand === "codex-server"
|
|
2621
|
+
? formatStudioCodexServerHuman(result as Awaited<ReturnType<typeof runStudioCodexServerCommand>>)
|
|
2622
|
+
: command.subcommand === "doctor"
|
|
2623
|
+
? formatStudioDoctorHuman(result as Awaited<ReturnType<typeof runStudioDoctorCommand>>)
|
|
2624
|
+
: command.subcommand === "open"
|
|
2625
|
+
? formatStudioOpenHuman(result as Awaited<ReturnType<typeof runStudioOpenCommand>>)
|
|
2626
|
+
: formatStudioAttachHuman(result as Awaited<ReturnType<typeof runStudioAttachCommand>>),
|
|
2627
|
+
);
|
|
2628
|
+
return result.exitCode;
|
|
2629
|
+
}
|
|
829
2630
|
case "inspect": {
|
|
830
2631
|
const result = await runInspectCommand(
|
|
831
2632
|
command.target,
|
|
832
|
-
|
|
2633
|
+
command.workspaceRoot,
|
|
2634
|
+
{ full: command.full, brief: command.brief, ergonomics: command.ergonomics },
|
|
833
2635
|
);
|
|
834
2636
|
if (command.json) {
|
|
835
2637
|
process.stdout.write(formatJsonResult(buildInspectJson(result)));
|
|
@@ -841,11 +2643,12 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
841
2643
|
return result.exitCode;
|
|
842
2644
|
}
|
|
843
2645
|
case "check": {
|
|
844
|
-
const
|
|
2646
|
+
const checkWorkspaceRoot = process.cwd();
|
|
2647
|
+
const result = await runCheckCommand(checkWorkspaceRoot, {
|
|
845
2648
|
strictSecrets: command.strictSecrets,
|
|
846
2649
|
});
|
|
847
2650
|
if (command.json) {
|
|
848
|
-
process.stdout.write(formatJsonResult(
|
|
2651
|
+
process.stdout.write(formatJsonResult(buildCheckJson(result, { workspaceRoot: checkWorkspaceRoot })));
|
|
849
2652
|
} else {
|
|
850
2653
|
writeHumanGenerate(result);
|
|
851
2654
|
}
|
|
@@ -867,6 +2670,32 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
867
2670
|
);
|
|
868
2671
|
|
|
869
2672
|
if (command.queryMode && command.name) {
|
|
2673
|
+
const external = resolveExternalQualifiedName(command.workspaceRoot, command.name, "query");
|
|
2674
|
+
if (external) {
|
|
2675
|
+
const run = await runExternalEntry(command.workspaceRoot, {
|
|
2676
|
+
kind: "query",
|
|
2677
|
+
serviceName: external.serviceName,
|
|
2678
|
+
entryName: external.entryName,
|
|
2679
|
+
args: command.args,
|
|
2680
|
+
auth: resolveAuthFromCli({
|
|
2681
|
+
userId: command.userId,
|
|
2682
|
+
tenantId: command.tenantId,
|
|
2683
|
+
role: command.role,
|
|
2684
|
+
}),
|
|
2685
|
+
});
|
|
2686
|
+
const payload = { run };
|
|
2687
|
+
if (command.json) {
|
|
2688
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
2689
|
+
} else {
|
|
2690
|
+
process.stdout.write(
|
|
2691
|
+
run.ok
|
|
2692
|
+
? `${JSON.stringify(run.result, null, 2)}\n`
|
|
2693
|
+
: `${run.diagnostics.map((diagnostic) => `error ${diagnostic.code}: ${diagnostic.message}`).join("\n")}\n`,
|
|
2694
|
+
);
|
|
2695
|
+
}
|
|
2696
|
+
return run.exitCode;
|
|
2697
|
+
}
|
|
2698
|
+
|
|
870
2699
|
const tableMap = readGeneratedJson<{ tableMap: Record<string, import("../compiler/data-graph/sql/serialize.ts").TableMapEntry> }>(
|
|
871
2700
|
command.workspaceRoot,
|
|
872
2701
|
`${GENERATED_DIR}/db.json`,
|
|
@@ -905,6 +2734,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
905
2734
|
userId: command.userId,
|
|
906
2735
|
tenantId: command.tenantId,
|
|
907
2736
|
role: command.role,
|
|
2737
|
+
args: command.args,
|
|
908
2738
|
workspaceRoot: command.workspaceRoot,
|
|
909
2739
|
});
|
|
910
2740
|
|
|
@@ -940,8 +2770,15 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
940
2770
|
webOnly: command.webOnly,
|
|
941
2771
|
open: command.open,
|
|
942
2772
|
webPort: command.webPort,
|
|
2773
|
+
publicApiUrl: command.publicApiUrl,
|
|
943
2774
|
telemetry: command.telemetry,
|
|
944
2775
|
envFile: command.envFile,
|
|
2776
|
+
skipStartupConsole: command.skipStartupConsole,
|
|
2777
|
+
detach: command.detach,
|
|
2778
|
+
seed: command.seed,
|
|
2779
|
+
seedCommand: command.seedCommand,
|
|
2780
|
+
seedAllTenants: command.seedAllTenants,
|
|
2781
|
+
lifecycle: command.lifecycle,
|
|
945
2782
|
});
|
|
946
2783
|
return result.exitCode;
|
|
947
2784
|
}
|
|
@@ -967,6 +2804,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
967
2804
|
workspaceRoot: command.workspaceRoot,
|
|
968
2805
|
db: command.db,
|
|
969
2806
|
databaseUrl: command.databaseUrl,
|
|
2807
|
+
local: command.local,
|
|
970
2808
|
json: command.json,
|
|
971
2809
|
});
|
|
972
2810
|
|
|
@@ -1087,6 +2925,7 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
1087
2925
|
workspaceRoot: command.workspaceRoot,
|
|
1088
2926
|
json: command.json,
|
|
1089
2927
|
redacted: command.redacted,
|
|
2928
|
+
target: command.target,
|
|
1090
2929
|
});
|
|
1091
2930
|
|
|
1092
2931
|
if (command.json) {
|
|
@@ -1160,5 +2999,5 @@ export async function executeCommand(command: ForgeCommand): Promise<number> {
|
|
|
1160
2999
|
}
|
|
1161
3000
|
}
|
|
1162
3001
|
|
|
1163
|
-
export { runVerifyCommand };
|
|
3002
|
+
export { runChangedCommand, runVerifyCommand };
|
|
1164
3003
|
export type { VerifyOptions, VerifyResult };
|