forgeos 0.1.0-alpha.2 → 0.1.0-alpha.21
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/.npmignore +4 -0
- package/AGENTS.md +168 -81
- package/CHANGELOG.md +211 -0
- package/README.md +88 -14
- 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 +34 -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/target/classes/dev/forgeos/adapter/Auth.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Diagnostic.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Entry.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/EntryKind.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ErrorInfo.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Forge.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeCall.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeContext.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHandler.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeHttpHandler.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$EntryOption.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegisteredEntry.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry$RegistryOption.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ForgeRegistry.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Json.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Manifest.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/RequestEnvelope.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/ResponseEnvelope.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Risk.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Schemas.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/Service.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/TransactionMode.class +0 -0
- package/adapters/java/target/classes/dev/forgeos/adapter/TypedForgeHandler.class +0 -0
- package/adapters/java/target/forge-java-adapter-0.1.0-alpha.11.jar +0 -0
- package/adapters/java/target/maven-archiver/pom.properties +3 -0
- package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +23 -0
- package/adapters/java/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +20 -0
- package/adapters/java-spring-boot-starter/README.md +32 -0
- package/adapters/java-spring-boot-starter/pom.xml +36 -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/adapters/java-spring-boot-starter/target/classes/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeCommand.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeExternalService.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeQuery.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.class +0 -0
- package/adapters/java-spring-boot-starter/target/classes/dev/forgeos/adapter/spring/ForgeSpringRuntime.class +0 -0
- package/adapters/java-spring-boot-starter/target/forge-java-spring-boot-starter-0.1.0-alpha.11.jar +0 -0
- package/adapters/java-spring-boot-starter/target/maven-archiver/pom.properties +3 -0
- package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +6 -0
- package/adapters/java-spring-boot-starter/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +6 -0
- package/bin/forge.mjs +18 -0
- package/docs/changelog.md +242 -0
- package/docs/forge-protocol.md +189 -0
- package/examples/go-billing/go.mod +7 -0
- package/examples/go-billing/main.go +120 -0
- package/examples/java-billing/pom.xml +52 -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/examples/java-billing/target/classes/dev/forgeos/examples/billing/CreateInvoiceInput.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Invoice.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$EmptyInput.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main$Options.class +0 -0
- package/examples/java-billing/target/classes/dev/forgeos/examples/billing/Main.class +0 -0
- package/examples/java-billing/target/java-billing-0.1.0-alpha.11-all.jar +0 -0
- package/examples/java-billing/target/java-billing-0.1.0-alpha.11.jar +0 -0
- package/examples/java-billing/target/maven-archiver/pom.properties +3 -0
- package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +5 -0
- package/examples/java-billing/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +3 -0
- package/package.json +29 -7
- package/schemas/forge-manifest.schema.json +57 -0
- package/src/forge/_generated/releaseManifest.json +1 -2
- package/src/forge/_generated/releaseManifest.ts +3 -3
- package/src/forge/agent-adapters/index.ts +1511 -123
- package/src/forge/agent-adapters/types.ts +216 -1
- package/src/forge/agent-memory/bridge.ts +1245 -0
- package/src/forge/agent-memory/context-pack.ts +151 -0
- package/src/forge/agent-memory/hook-runner.ts +312 -0
- package/src/forge/agent-memory/mcp.ts +224 -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 +273 -0
- package/src/forge/agent-memory/sources/codex.ts +119 -0
- package/src/forge/agent-memory/sources/cursor.ts +35 -0
- package/src/forge/agent-memory/types.ts +191 -0
- package/src/forge/bench.ts +248 -0
- package/src/forge/brownfield-import/index.ts +801 -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 +106 -0
- package/src/forge/cair/query.ts +478 -0
- package/src/forge/cair/snapshot.ts +315 -0
- package/src/forge/cair/types.ts +248 -0
- package/src/forge/cli/ai.ts +671 -3
- package/src/forge/cli/auth.ts +36 -1
- package/src/forge/cli/build.ts +20 -4
- package/src/forge/cli/changed.ts +300 -0
- package/src/forge/cli/codex-app-server.ts +877 -0
- package/src/forge/cli/commands.ts +1285 -7
- package/src/forge/cli/db.ts +121 -2
- package/src/forge/cli/deps.ts +79 -12
- package/src/forge/cli/dev.ts +502 -38
- package/src/forge/cli/docs.ts +265 -0
- package/src/forge/cli/handoff.ts +250 -0
- package/src/forge/cli/index.ts +1 -0
- package/src/forge/cli/main.ts +49 -3
- package/src/forge/cli/new.ts +3 -1
- package/src/forge/cli/next-actions.ts +23 -0
- package/src/forge/cli/output.ts +290 -1
- package/src/forge/cli/parse.ts +770 -36
- package/src/forge/cli/query.ts +32 -0
- package/src/forge/cli/release.ts +35 -11
- package/src/forge/cli/rls.ts +568 -17
- package/src/forge/cli/run.ts +41 -0
- package/src/forge/cli/secrets.ts +46 -1
- package/src/forge/cli/security.ts +381 -0
- package/src/forge/cli/self-host.ts +56 -14
- package/src/forge/cli/studio.ts +2163 -0
- package/src/forge/cli/verify.ts +1422 -32
- package/src/forge/compiler/agent-contract/build.ts +725 -41
- package/src/forge/compiler/agent-contract/types.ts +85 -0
- package/src/forge/compiler/ai-registry/build.ts +62 -1
- package/src/forge/compiler/ai-registry/constants.ts +1 -1
- package/src/forge/compiler/ai-registry/parse.ts +168 -5
- package/src/forge/compiler/api-surface/build.ts +47 -0
- package/src/forge/compiler/app-graph/build.ts +68 -8
- package/src/forge/compiler/app-graph/extract.ts +107 -0
- package/src/forge/compiler/app-graph/forge-apis.ts +1 -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/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 +188 -13
- package/src/forge/compiler/data-graph/parse.ts +3 -3
- package/src/forge/compiler/data-graph/sql/ddl.ts +60 -2
- 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/dev-manifest/build.ts +3 -0
- package/src/forge/compiler/diagnostics/codes.ts +35 -0
- package/src/forge/compiler/diagnostics/create.ts +8 -3
- 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 +5 -0
- package/src/forge/compiler/external-manifest/registry.ts +205 -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 +85 -13
- package/src/forge/compiler/integration/add.ts +498 -22
- package/src/forge/compiler/integration/snapshot.ts +2 -0
- package/src/forge/compiler/make-registry/build.ts +19 -7
- package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
- package/src/forge/compiler/orchestrator/plan.ts +78 -7
- package/src/forge/compiler/orchestrator/profile.ts +65 -0
- package/src/forge/compiler/orchestrator/run.ts +97 -31
- package/src/forge/compiler/orchestrator/serialize.ts +101 -8
- package/src/forge/compiler/package-graph/compiler.ts +13 -3
- 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/policy-registry/build.ts +44 -1
- package/src/forge/compiler/test-graph/build.ts +11 -3
- package/src/forge/compiler/types/ai-registry.ts +25 -1
- package/src/forge/compiler/types/app-graph.ts +9 -2
- package/src/forge/compiler/types/cli.ts +76 -1
- package/src/forge/compiler/types/dev-manifest.ts +3 -0
- package/src/forge/compiler/types/frontend-graph.ts +2 -2
- package/src/forge/delta/classifier.ts +52 -0
- package/src/forge/delta/explain.ts +126 -0
- package/src/forge/delta/git-observer.ts +43 -0
- package/src/forge/delta/ids.ts +44 -0
- package/src/forge/delta/index.ts +13 -0
- package/src/forge/delta/recorder.ts +402 -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 +489 -0
- package/src/forge/delta/store.ts +2975 -0
- package/src/forge/delta/timeline.ts +104 -0
- package/src/forge/dev/server.ts +768 -15
- package/src/forge/dev/types.ts +15 -1
- package/src/forge/dev/watch.ts +17 -7
- package/src/forge/dev-console/cycle.ts +233 -21
- package/src/forge/dev-console/types.ts +46 -1
- package/src/forge/impact/index.ts +46 -8
- package/src/forge/impact/types.ts +6 -0
- package/src/forge/intent/index.ts +35 -16
- package/src/forge/make/index.ts +149 -6
- package/src/forge/make/templates.ts +343 -2
- package/src/forge/make/types.ts +3 -1
- package/src/forge/refactor/index.ts +1 -0
- package/src/forge/repair/rules/index.ts +2 -2
- package/src/forge/review/index.ts +158 -12
- package/src/forge/review/types.ts +15 -0
- package/src/forge/runtime/ai/context.ts +210 -5
- package/src/forge/runtime/ai/types.ts +70 -0
- package/src/forge/runtime/auth/claims.ts +32 -0
- package/src/forge/runtime/auth/errors.ts +2 -0
- package/src/forge/runtime/context/create-context.ts +30 -6
- package/src/forge/runtime/db/generated-client.ts +13 -2
- package/src/forge/runtime/db/memory-adapter.ts +2 -2
- package/src/forge/runtime/db/pglite-adapter.ts +77 -2
- package/src/forge/runtime/db/postgres-adapter.ts +6 -3
- package/src/forge/runtime/executor.ts +112 -2
- package/src/forge/runtime/external/bridge.ts +649 -0
- package/src/forge/runtime/runner/run-entry.ts +16 -7
- package/src/forge/runtime/telemetry/scrubber.ts +91 -10
- package/src/forge/runtime/webhooks/security.ts +184 -0
- package/src/forge/server.ts +100 -2
- package/src/forge/version.ts +1 -1
- package/src/forge/vue/index.ts +407 -0
- package/src/forge/workspace/change-summary.ts +209 -0
- package/src/forge/workspace/forge-cli.ts +14 -0
- package/src/forge/workspace/git-summary.ts +279 -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 +33 -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 +12 -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 +13 -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/b2b-support-web/package.json +2 -0
- package/templates/b2b-support-web/tsconfig.json +4 -1
- package/templates/b2b-support-web/web/package.json +1 -1
- package/templates/minimal-web/package.json +2 -1
- package/templates/minimal-web/tsconfig.json +3 -1
- package/templates/minimal-web/web/package.json +2 -2
- 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 -7696
- package/src/forge/_generated/agentQuickstart.md +0 -32
- package/src/forge/_generated/aiContext.ts +0 -59
- package/src/forge/_generated/aiModels.json +0 -2
- package/src/forge/_generated/aiModels.ts +0 -35
- 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 -29
- 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 -14667
- package/src/forge/_generated/appMap.md +0 -35
- 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 -47
- 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 -67
- 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 -163
- package/src/forge/_generated/makeTemplates.json +0 -2
- package/src/forge/_generated/makeTemplates.ts +0 -61
- package/src/forge/_generated/mockMap.json +0 -2
- package/src/forge/_generated/mockMap.ts +0 -7
- package/src/forge/_generated/operationPlaybooks.md +0 -147
- package/src/forge/_generated/packageGraph.json +0 -2
- package/src/forge/_generated/packageGraph.ts +0 -245249
- 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 -327385
- package/src/forge/_generated/runtimeRegistry.ts +0 -2
- package/src/forge/_generated/runtimeRules.md +0 -79
- 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 -3108
- 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
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { dirname, join, normalize } from "node:path";
|
|
3
|
+
import { nodeFileSystem } from "../compiler/fs/index.ts";
|
|
4
|
+
import { createDiagnostic } from "../compiler/diagnostics/create.ts";
|
|
5
|
+
import type { Diagnostic } from "../compiler/types/diagnostic.ts";
|
|
6
|
+
import { docsReadyNextActions } from "./next-actions.ts";
|
|
7
|
+
|
|
8
|
+
export type DocsSubcommand = "check";
|
|
9
|
+
|
|
10
|
+
export interface DocsCheckOptions {
|
|
11
|
+
workspaceRoot: string;
|
|
12
|
+
json: boolean;
|
|
13
|
+
build?: boolean;
|
|
14
|
+
installVenv?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface DocsCheck {
|
|
18
|
+
name: string;
|
|
19
|
+
ok: boolean;
|
|
20
|
+
status: "pass" | "fail" | "warning";
|
|
21
|
+
details?: unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DocsCheckResult {
|
|
25
|
+
ok: boolean;
|
|
26
|
+
checks: DocsCheck[];
|
|
27
|
+
diagnostics: Diagnostic[];
|
|
28
|
+
nextActions: string[];
|
|
29
|
+
exitCode: 0 | 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const REQUIRED_DOCS = [
|
|
33
|
+
"index.md",
|
|
34
|
+
"getting-started.md",
|
|
35
|
+
"agent-workflow.md",
|
|
36
|
+
"cli-reference.md",
|
|
37
|
+
"troubleshooting.md",
|
|
38
|
+
"production-readiness.md",
|
|
39
|
+
"self-host.md",
|
|
40
|
+
"release.md",
|
|
41
|
+
] as const;
|
|
42
|
+
|
|
43
|
+
const CONTENT_CHECKS: Array<{ file: string; contains: string[] }> = [
|
|
44
|
+
{ file: ".readthedocs.yaml", contains: ["version: 2", "configuration: mkdocs.yml", "fail_on_warning: true", "requirements: docs/requirements.txt"] },
|
|
45
|
+
{ file: "mkdocs.yml", contains: ["name: material", "markdown_extensions:", "extra_css:", "javascripts/mermaid-init.js"] },
|
|
46
|
+
{ file: "docs/getting-started.md", contains: ["npm create forgeos-app@alpha", "Open the web URL"] },
|
|
47
|
+
{ file: "docs/agent-workflow.md", contains: ["forge do", "forge status --json", "forge handoff --json"] },
|
|
48
|
+
{ file: "docs/troubleshooting.md", contains: ["FORGE_DELTA_BUSY", "waiting-for-user-trust", "Studio target preview issues"] },
|
|
49
|
+
{ file: "docs/release.md", contains: ["release:verify-public-alpha", "Documentation checklist"] },
|
|
50
|
+
{ file: "docs/self-host.md", contains: ["forge self-host check"] },
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
function read(workspaceRoot: string, relative: string): string | null {
|
|
54
|
+
const path = join(workspaceRoot, relative);
|
|
55
|
+
if (!nodeFileSystem.exists(path)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return nodeFileSystem.readText(path) ?? "";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function checkFileExists(workspaceRoot: string, relative: string): DocsCheck {
|
|
62
|
+
return nodeFileSystem.exists(join(workspaceRoot, relative))
|
|
63
|
+
? { name: relative, ok: true, status: "pass" }
|
|
64
|
+
: { name: relative, ok: false, status: "fail", details: { missing: true } };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function checkContains(workspaceRoot: string, file: string, contains: string[]): DocsCheck {
|
|
68
|
+
const content = read(workspaceRoot, file);
|
|
69
|
+
if (content === null) {
|
|
70
|
+
return { name: `${file}:content`, ok: false, status: "fail", details: { missing: true } };
|
|
71
|
+
}
|
|
72
|
+
const missing = contains.filter((needle) => !content.includes(needle));
|
|
73
|
+
return missing.length === 0
|
|
74
|
+
? { name: `${file}:content`, ok: true, status: "pass" }
|
|
75
|
+
: { name: `${file}:content`, ok: false, status: "fail", details: { missing } };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function slugifyHeading(heading: string): string {
|
|
79
|
+
return heading
|
|
80
|
+
.trim()
|
|
81
|
+
.toLowerCase()
|
|
82
|
+
.replace(/[`*_]/g, "")
|
|
83
|
+
.replace(/[^a-z0-9\s-]/g, "")
|
|
84
|
+
.replace(/\s+/g, "-");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function anchorsFor(content: string): Set<string> {
|
|
88
|
+
const anchors = new Set<string>();
|
|
89
|
+
for (const line of content.split(/\r?\n/)) {
|
|
90
|
+
const match = /^(#{1,6})\s+(.+)$/.exec(line);
|
|
91
|
+
if (match) {
|
|
92
|
+
anchors.add(slugifyHeading(match[2] ?? ""));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return anchors;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function checkYamlShape(workspaceRoot: string, relative: string, requiredKeys: string[]): DocsCheck {
|
|
99
|
+
const content = read(workspaceRoot, relative);
|
|
100
|
+
if (content === null) {
|
|
101
|
+
return { name: `${relative}:yaml`, ok: false, status: "fail", details: { missing: true } };
|
|
102
|
+
}
|
|
103
|
+
const malformed = content
|
|
104
|
+
.split(/\r?\n/)
|
|
105
|
+
.filter((line) => line.trim() && !line.trimStart().startsWith("#"))
|
|
106
|
+
.filter((line) => !/^\s*-\s+/.test(line))
|
|
107
|
+
.filter((line) => !line.includes(":"));
|
|
108
|
+
const missingKeys = requiredKeys.filter((key) => !new RegExp(`^${key}:`, "m").test(content));
|
|
109
|
+
const ok = malformed.length === 0 && missingKeys.length === 0;
|
|
110
|
+
return ok
|
|
111
|
+
? { name: `${relative}:yaml`, ok: true, status: "pass" }
|
|
112
|
+
: { name: `${relative}:yaml`, ok: false, status: "fail", details: { malformed, missingKeys } };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function checkInternalLinks(workspaceRoot: string): DocsCheck {
|
|
116
|
+
const missing: Array<{ file: string; target: string }> = [];
|
|
117
|
+
const docs = nodeFileSystem.exists(join(workspaceRoot, "docs"))
|
|
118
|
+
? nodeFileSystem.readDir(join(workspaceRoot, "docs"))
|
|
119
|
+
.filter((entry) => entry.name.endsWith(".md"))
|
|
120
|
+
.map((entry) => `docs/${entry.name}`)
|
|
121
|
+
: [];
|
|
122
|
+
for (const file of docs) {
|
|
123
|
+
const content = read(workspaceRoot, file) ?? "";
|
|
124
|
+
const links = [...content.matchAll(/\[[^\]]+\]\(([^)]+)\)/g)]
|
|
125
|
+
.map((match) => match[1] ?? "")
|
|
126
|
+
.filter((target) =>
|
|
127
|
+
target &&
|
|
128
|
+
!target.startsWith("http://") &&
|
|
129
|
+
!target.startsWith("https://") &&
|
|
130
|
+
!target.startsWith("mailto:") &&
|
|
131
|
+
!target.startsWith("#") &&
|
|
132
|
+
!target.startsWith("`")
|
|
133
|
+
);
|
|
134
|
+
for (const target of links) {
|
|
135
|
+
const [pathPart, anchor] = target.split("#");
|
|
136
|
+
const resolved = normalize(join(dirname(file), decodeURIComponent(pathPart ?? ""))).replace(/\\/g, "/");
|
|
137
|
+
if (!nodeFileSystem.exists(join(workspaceRoot, resolved))) {
|
|
138
|
+
missing.push({ file, target });
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (anchor) {
|
|
142
|
+
const targetContent = read(workspaceRoot, resolved) ?? "";
|
|
143
|
+
if (!anchorsFor(targetContent).has(anchor)) {
|
|
144
|
+
missing.push({ file, target });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return missing.length === 0
|
|
150
|
+
? { name: "docs-internal-links", ok: true, status: "pass" }
|
|
151
|
+
: { name: "docs-internal-links", ok: false, status: "fail", details: { missing } };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function checkMkdocsTooling(workspaceRoot: string): DocsCheck {
|
|
155
|
+
const result = spawnSync("python3", ["-m", "mkdocs", "--version"], {
|
|
156
|
+
cwd: workspaceRoot,
|
|
157
|
+
encoding: "utf8",
|
|
158
|
+
windowsHide: true,
|
|
159
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
160
|
+
});
|
|
161
|
+
if (result.status === 0) {
|
|
162
|
+
return {
|
|
163
|
+
name: "mkdocs-tooling",
|
|
164
|
+
ok: true,
|
|
165
|
+
status: "pass",
|
|
166
|
+
details: { version: (result.stdout ?? "").trim() },
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
name: "mkdocs-tooling",
|
|
171
|
+
ok: true,
|
|
172
|
+
status: "warning",
|
|
173
|
+
details: {
|
|
174
|
+
message: "mkdocs is not importable in the current Python environment; install docs/requirements.txt before building docs locally",
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function runOptionalDocsBuild(options: DocsCheckOptions): DocsCheck[] {
|
|
180
|
+
const checks: DocsCheck[] = [];
|
|
181
|
+
const python = process.platform === "win32"
|
|
182
|
+
? join(options.workspaceRoot, ".venv-rtd", "Scripts", "python.exe")
|
|
183
|
+
: join(options.workspaceRoot, ".venv-rtd", "bin", "python");
|
|
184
|
+
if (options.installVenv) {
|
|
185
|
+
const venv = spawnSync("python3", ["-m", "venv", ".venv-rtd"], {
|
|
186
|
+
cwd: options.workspaceRoot,
|
|
187
|
+
encoding: "utf8",
|
|
188
|
+
windowsHide: true,
|
|
189
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
190
|
+
});
|
|
191
|
+
checks.push(venv.status === 0
|
|
192
|
+
? { name: "mkdocs-venv-create", ok: true, status: "pass" }
|
|
193
|
+
: { name: "mkdocs-venv-create", ok: false, status: "fail", details: { stderr: venv.stderr } });
|
|
194
|
+
if (venv.status === 0) {
|
|
195
|
+
const install = spawnSync(python, ["-m", "pip", "install", "-r", "docs/requirements.txt"], {
|
|
196
|
+
cwd: options.workspaceRoot,
|
|
197
|
+
encoding: "utf8",
|
|
198
|
+
windowsHide: true,
|
|
199
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
200
|
+
});
|
|
201
|
+
checks.push(install.status === 0
|
|
202
|
+
? { name: "mkdocs-venv-install", ok: true, status: "pass" }
|
|
203
|
+
: { name: "mkdocs-venv-install", ok: false, status: "fail", details: { stderr: install.stderr } });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (options.build) {
|
|
207
|
+
const command = options.installVenv ? python : "python3";
|
|
208
|
+
const args = ["-m", "mkdocs", "build", "--strict"];
|
|
209
|
+
const build = spawnSync(command, args, {
|
|
210
|
+
cwd: options.workspaceRoot,
|
|
211
|
+
encoding: "utf8",
|
|
212
|
+
windowsHide: true,
|
|
213
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
214
|
+
});
|
|
215
|
+
checks.push(build.status === 0
|
|
216
|
+
? { name: "mkdocs-build-strict", ok: true, status: "pass", details: { stdout: build.stdout?.trim() } }
|
|
217
|
+
: { name: "mkdocs-build-strict", ok: false, status: "fail", details: { stderr: build.stderr } });
|
|
218
|
+
}
|
|
219
|
+
return checks;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function runDocsCheckCommand(options: DocsCheckOptions): DocsCheckResult {
|
|
223
|
+
const checks: DocsCheck[] = [
|
|
224
|
+
checkFileExists(options.workspaceRoot, ".readthedocs.yaml"),
|
|
225
|
+
checkFileExists(options.workspaceRoot, "mkdocs.yml"),
|
|
226
|
+
checkFileExists(options.workspaceRoot, "docs/requirements.txt"),
|
|
227
|
+
checkFileExists(options.workspaceRoot, "docs/stylesheets/forge.css"),
|
|
228
|
+
checkFileExists(options.workspaceRoot, "docs/javascripts/mermaid-init.js"),
|
|
229
|
+
...REQUIRED_DOCS.map((file) => checkFileExists(options.workspaceRoot, `docs/${file}`)),
|
|
230
|
+
checkYamlShape(options.workspaceRoot, ".readthedocs.yaml", ["version", "build", "mkdocs"]),
|
|
231
|
+
checkYamlShape(options.workspaceRoot, "mkdocs.yml", ["site_name", "theme", "nav"]),
|
|
232
|
+
...CONTENT_CHECKS.map((check) => checkContains(options.workspaceRoot, check.file, check.contains)),
|
|
233
|
+
checkInternalLinks(options.workspaceRoot),
|
|
234
|
+
checkMkdocsTooling(options.workspaceRoot),
|
|
235
|
+
...runOptionalDocsBuild(options),
|
|
236
|
+
];
|
|
237
|
+
const failed = checks.filter((check) => !check.ok);
|
|
238
|
+
const diagnostics = failed.map((check) => createDiagnostic({
|
|
239
|
+
severity: "error",
|
|
240
|
+
code: "FORGE_DOCS_CHECK_FAILED",
|
|
241
|
+
message: `documentation check failed: ${check.name}`,
|
|
242
|
+
suggestedCommands: ["forge docs check --json", "bun test tests/docs/readthedocs.test.ts"],
|
|
243
|
+
}));
|
|
244
|
+
const ok = failed.length === 0;
|
|
245
|
+
return {
|
|
246
|
+
ok,
|
|
247
|
+
checks,
|
|
248
|
+
diagnostics,
|
|
249
|
+
nextActions: ok
|
|
250
|
+
? docsReadyNextActions()
|
|
251
|
+
: ["forge docs check --json", "bun test tests/docs/readthedocs.test.ts"],
|
|
252
|
+
exitCode: ok ? 0 : 1,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function formatDocsCheckHuman(result: DocsCheckResult): string {
|
|
257
|
+
const lines = [
|
|
258
|
+
`docs check ${result.ok ? "ok" : "failed"}`,
|
|
259
|
+
...result.checks.map((check) => `${check.status} ${check.name}`),
|
|
260
|
+
];
|
|
261
|
+
if (result.nextActions.length > 0) {
|
|
262
|
+
lines.push("", "Next:", ...result.nextActions.map((action) => ` ${action}`));
|
|
263
|
+
}
|
|
264
|
+
return `${lines.join("\n")}\n`;
|
|
265
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { nodeFileSystem } from "../compiler/fs/index.ts";
|
|
3
|
+
import type { Diagnostic } from "../compiler/types/diagnostic.ts";
|
|
4
|
+
import { runDevConsoleCycle } from "../dev-console/cycle.ts";
|
|
5
|
+
import type { DevConsoleCycle, DevConsolePhase } from "../dev-console/types.ts";
|
|
6
|
+
import type { TestRunRecord } from "../impact/types.ts";
|
|
7
|
+
import type { UiRunReport } from "../ui/types.ts";
|
|
8
|
+
import { summarizeChangeTypes, type CategorizedFileSummary } from "../workspace/change-summary.ts";
|
|
9
|
+
import { buildWorkspaceGitSummary } from "../workspace/git-summary.ts";
|
|
10
|
+
|
|
11
|
+
export interface HandoffCommandOptions {
|
|
12
|
+
workspaceRoot: string;
|
|
13
|
+
json: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface HandoffCommandResult {
|
|
17
|
+
schemaVersion: "0.1.0";
|
|
18
|
+
ok: boolean;
|
|
19
|
+
summary: {
|
|
20
|
+
projectRoot: string;
|
|
21
|
+
safeToEdit: boolean;
|
|
22
|
+
generatedFresh: boolean;
|
|
23
|
+
generatedChanged: boolean;
|
|
24
|
+
generatedChangedFiles: number;
|
|
25
|
+
frontendReady: boolean;
|
|
26
|
+
changedFiles: number;
|
|
27
|
+
stagedFiles: number;
|
|
28
|
+
unstagedFiles: number;
|
|
29
|
+
untrackedFiles: number;
|
|
30
|
+
lastTestRun: "passed" | "failed" | "missing";
|
|
31
|
+
lastUiRun: "passed" | "failed" | "missing";
|
|
32
|
+
};
|
|
33
|
+
dev: {
|
|
34
|
+
ok: boolean;
|
|
35
|
+
primaryAction?: DevConsoleCycle["summary"]["primaryAction"];
|
|
36
|
+
agentContext: DevConsoleCycle["summary"]["agentContext"];
|
|
37
|
+
phases: Array<Pick<DevConsolePhase, "name" | "status" | "message">>;
|
|
38
|
+
};
|
|
39
|
+
git: {
|
|
40
|
+
available: boolean;
|
|
41
|
+
branch?: string;
|
|
42
|
+
commit?: string;
|
|
43
|
+
changed: {
|
|
44
|
+
count: number;
|
|
45
|
+
sample: string[];
|
|
46
|
+
hidden: number;
|
|
47
|
+
};
|
|
48
|
+
staged: {
|
|
49
|
+
count: number;
|
|
50
|
+
sample: string[];
|
|
51
|
+
hidden: number;
|
|
52
|
+
};
|
|
53
|
+
unstaged: {
|
|
54
|
+
count: number;
|
|
55
|
+
sample: string[];
|
|
56
|
+
hidden: number;
|
|
57
|
+
};
|
|
58
|
+
untracked: {
|
|
59
|
+
count: number;
|
|
60
|
+
sample: string[];
|
|
61
|
+
hidden: number;
|
|
62
|
+
};
|
|
63
|
+
changeSummary: {
|
|
64
|
+
changed: CategorizedFileSummary;
|
|
65
|
+
staged: CategorizedFileSummary;
|
|
66
|
+
unstaged: CategorizedFileSummary;
|
|
67
|
+
untracked: CategorizedFileSummary;
|
|
68
|
+
};
|
|
69
|
+
error?: string;
|
|
70
|
+
};
|
|
71
|
+
recentRuns: {
|
|
72
|
+
test?: {
|
|
73
|
+
id?: string;
|
|
74
|
+
ok: boolean;
|
|
75
|
+
failed: string[];
|
|
76
|
+
durationMs?: number;
|
|
77
|
+
};
|
|
78
|
+
ui?: {
|
|
79
|
+
id?: string;
|
|
80
|
+
ok: boolean;
|
|
81
|
+
failedScenarios: string[];
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
nextAgent: {
|
|
85
|
+
openingBrief: string;
|
|
86
|
+
recommendedReadFiles: string[];
|
|
87
|
+
recommendedCommands: string[];
|
|
88
|
+
risks: string[];
|
|
89
|
+
};
|
|
90
|
+
diagnostics: Diagnostic[];
|
|
91
|
+
nextActions: string[];
|
|
92
|
+
exitCode: 0 | 1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function readJson<T>(workspaceRoot: string, relativePath: string): T | null {
|
|
96
|
+
const absolute = join(workspaceRoot, relativePath);
|
|
97
|
+
if (!nodeFileSystem.exists(absolute)) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
return JSON.parse(nodeFileSystem.readText(absolute) ?? "null") as T;
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function summarizeRecentRuns(workspaceRoot: string): HandoffCommandResult["recentRuns"] {
|
|
108
|
+
const test = readJson<TestRunRecord>(workspaceRoot, ".forge/test-runs/last.json");
|
|
109
|
+
const ui = readJson<UiRunReport>(workspaceRoot, ".forge/ui-runs/last.json");
|
|
110
|
+
const failedScenarios = (ui?.scenarios ?? [])
|
|
111
|
+
.filter((scenario) => !scenario.ok)
|
|
112
|
+
.map((scenario) => scenario.name);
|
|
113
|
+
return {
|
|
114
|
+
...(test
|
|
115
|
+
? {
|
|
116
|
+
test: {
|
|
117
|
+
id: test.id,
|
|
118
|
+
ok: test.failed.length === 0,
|
|
119
|
+
failed: test.failed,
|
|
120
|
+
durationMs: test.durationMs,
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
: {}),
|
|
124
|
+
...(ui
|
|
125
|
+
? {
|
|
126
|
+
ui: {
|
|
127
|
+
id: ui.id,
|
|
128
|
+
ok: failedScenarios.length === 0 && ui.diagnostics.every((diagnostic) => diagnostic.severity !== "error"),
|
|
129
|
+
failedScenarios,
|
|
130
|
+
},
|
|
131
|
+
}
|
|
132
|
+
: {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function buildOpeningBrief(input: {
|
|
137
|
+
dev: DevConsoleCycle;
|
|
138
|
+
git: HandoffCommandResult["git"];
|
|
139
|
+
recentRuns: HandoffCommandResult["recentRuns"];
|
|
140
|
+
}): string {
|
|
141
|
+
const agent = input.dev.summary.agentContext;
|
|
142
|
+
const changedByType = summarizeChangeTypes(input.git.changeSummary.changed);
|
|
143
|
+
const tests = input.recentRuns.test
|
|
144
|
+
? input.recentRuns.test.ok
|
|
145
|
+
? "last test run passed"
|
|
146
|
+
: "last test run failed"
|
|
147
|
+
: "no last test run";
|
|
148
|
+
const blockers = agent.blockingIssues.length > 0
|
|
149
|
+
? `${agent.blockingIssues.length} blocking issue(s)`
|
|
150
|
+
: "no blocking issues";
|
|
151
|
+
return [
|
|
152
|
+
`ForgeOS handoff: ${input.dev.ok ? "dev diagnostics are clean" : "dev diagnostics need attention"}.`,
|
|
153
|
+
`${agent.changedFiles} changed file(s)${changedByType ? `: ${changedByType}` : ""}; ${input.git.staged.count} staged, ${input.git.untracked.count} untracked.`,
|
|
154
|
+
`${tests}; ${blockers}.`,
|
|
155
|
+
`Next command: ${input.dev.summary.primaryAction?.command ?? input.dev.nextActions[0]?.command ?? "forge dev"}.`,
|
|
156
|
+
].join(" ");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export async function runHandoffCommand(options: HandoffCommandOptions): Promise<HandoffCommandResult> {
|
|
160
|
+
const workspaceRoot = options.workspaceRoot.replace(/\\/g, "/");
|
|
161
|
+
const dev = await runDevConsoleCycle({
|
|
162
|
+
workspaceRoot,
|
|
163
|
+
mode: "once",
|
|
164
|
+
includeImpact: true,
|
|
165
|
+
});
|
|
166
|
+
const git = buildWorkspaceGitSummary(workspaceRoot);
|
|
167
|
+
const recentRuns = summarizeRecentRuns(workspaceRoot);
|
|
168
|
+
const agent = dev.summary.agentContext;
|
|
169
|
+
const risks = [
|
|
170
|
+
...agent.blockingIssues,
|
|
171
|
+
...(git.untracked.count > 0 ? [`${git.untracked.count} untracked file(s) are not in git history`] : []),
|
|
172
|
+
...(recentRuns.test && !recentRuns.test.ok ? ["last test run failed"] : []),
|
|
173
|
+
...(recentRuns.ui && !recentRuns.ui.ok ? ["last UI run failed"] : []),
|
|
174
|
+
];
|
|
175
|
+
const nextActions = [
|
|
176
|
+
...agent.recommendedCommands,
|
|
177
|
+
...(git.changed.count > 0 ? ["forge review run --changed --json"] : []),
|
|
178
|
+
"forge handoff --json",
|
|
179
|
+
];
|
|
180
|
+
const ok = dev.ok &&
|
|
181
|
+
agent.blockingIssues.length === 0 &&
|
|
182
|
+
(!recentRuns.test || recentRuns.test.ok) &&
|
|
183
|
+
(!recentRuns.ui || recentRuns.ui.ok);
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
schemaVersion: "0.1.0",
|
|
187
|
+
ok,
|
|
188
|
+
summary: {
|
|
189
|
+
projectRoot: workspaceRoot,
|
|
190
|
+
safeToEdit: agent.safeToEdit,
|
|
191
|
+
generatedFresh: agent.generatedFresh,
|
|
192
|
+
generatedChanged: agent.generatedChanged,
|
|
193
|
+
generatedChangedFiles: agent.generatedChangedFiles,
|
|
194
|
+
frontendReady: agent.frontendReady,
|
|
195
|
+
changedFiles: agent.changedFiles,
|
|
196
|
+
stagedFiles: git.staged.count,
|
|
197
|
+
unstagedFiles: git.unstaged.count,
|
|
198
|
+
untrackedFiles: git.untracked.count,
|
|
199
|
+
lastTestRun: recentRuns.test ? (recentRuns.test.ok ? "passed" : "failed") : "missing",
|
|
200
|
+
lastUiRun: recentRuns.ui ? (recentRuns.ui.ok ? "passed" : "failed") : "missing",
|
|
201
|
+
},
|
|
202
|
+
dev: {
|
|
203
|
+
ok: dev.ok,
|
|
204
|
+
...(dev.summary.primaryAction ? { primaryAction: dev.summary.primaryAction } : {}),
|
|
205
|
+
agentContext: agent,
|
|
206
|
+
phases: dev.phases.map((phase) => ({
|
|
207
|
+
name: phase.name,
|
|
208
|
+
status: phase.status,
|
|
209
|
+
...(phase.message ? { message: phase.message } : {}),
|
|
210
|
+
})),
|
|
211
|
+
},
|
|
212
|
+
git,
|
|
213
|
+
recentRuns,
|
|
214
|
+
nextAgent: {
|
|
215
|
+
openingBrief: buildOpeningBrief({ dev, git, recentRuns }),
|
|
216
|
+
recommendedReadFiles: agent.recommendedReadFiles,
|
|
217
|
+
recommendedCommands: [...new Set(nextActions)].slice(0, 10),
|
|
218
|
+
risks,
|
|
219
|
+
},
|
|
220
|
+
diagnostics: dev.diagnostics,
|
|
221
|
+
nextActions: [...new Set(nextActions)].slice(0, 10),
|
|
222
|
+
exitCode: ok ? 0 : 1,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function formatHandoffJson(result: HandoffCommandResult): string {
|
|
227
|
+
return `${JSON.stringify(result, null, 2)}\n`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function formatHandoffHuman(result: HandoffCommandResult): string {
|
|
231
|
+
const lines = [
|
|
232
|
+
`Forge handoff: ${result.ok ? "ready" : "needs attention"}`,
|
|
233
|
+
result.nextAgent.openingBrief,
|
|
234
|
+
"",
|
|
235
|
+
"Read first:",
|
|
236
|
+
...result.nextAgent.recommendedReadFiles.slice(0, 6).map((file) => ` ${file}`),
|
|
237
|
+
"",
|
|
238
|
+
"Next commands:",
|
|
239
|
+
...result.nextActions.slice(0, 6).map((command) => ` ${command}`),
|
|
240
|
+
];
|
|
241
|
+
if (result.nextAgent.risks.length > 0) {
|
|
242
|
+
lines.push("", "Risks:");
|
|
243
|
+
lines.push(...result.nextAgent.risks.slice(0, 6).map((risk) => ` ${risk}`));
|
|
244
|
+
}
|
|
245
|
+
const changedTypes = summarizeChangeTypes(result.git.changeSummary.changed);
|
|
246
|
+
if (changedTypes) {
|
|
247
|
+
lines.push("", "Change types:", ` ${changedTypes}`);
|
|
248
|
+
}
|
|
249
|
+
return `${lines.join("\n")}\n`;
|
|
250
|
+
}
|
package/src/forge/cli/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { CLI_VERSION } from "./version.ts";
|
|
|
2
2
|
export { parseCli, hasUnknownOption, type ParsedCli, type ForgeCommand } from "./parse.ts";
|
|
3
3
|
export { runNewCommand, type NewCommandOptions, type NewCommandResult } from "./new.ts";
|
|
4
4
|
export { runSelfHostCommand, type SelfHostCommandOptions } from "./self-host.ts";
|
|
5
|
+
export { runDocsCheckCommand, type DocsCheckResult } from "./docs.ts";
|
|
5
6
|
export { runBuildCommand, type BuildCommandOptions } from "./build.ts";
|
|
6
7
|
export { runServeCommand, type ServeCommandOptions } from "./serve.ts";
|
|
7
8
|
export { runWorkerCommand, type WorkerCommandOptions } from "./worker.ts";
|
package/src/forge/cli/main.ts
CHANGED
|
@@ -4,23 +4,61 @@ import { isMainModule } from "../platform/module.ts";
|
|
|
4
4
|
import { executeCommand } from "./commands.ts";
|
|
5
5
|
import { hasUnknownOption, parseCli } from "./parse.ts";
|
|
6
6
|
import { formatJsonResult } from "./output.ts";
|
|
7
|
+
import { recordParsedCliCommand } from "../delta/index.ts";
|
|
7
8
|
|
|
8
9
|
function formatHelp(): string {
|
|
9
10
|
return [
|
|
10
11
|
"ForgeOS",
|
|
11
12
|
"",
|
|
12
13
|
"Start with one of these:",
|
|
14
|
+
" forge status --json Compact project health, handoff state, and next actions",
|
|
15
|
+
" forge changed --json Group changed files into human, generated, and risk buckets",
|
|
16
|
+
" forge changed --authored --json Show only authored changed files, excluding generated artifacts",
|
|
17
|
+
" forge diff authored Run the authored-only git diff pathspec",
|
|
18
|
+
" forge handoff --json Compact work handoff for the next external code agent",
|
|
19
|
+
" forge agent onboard --target codex --json Prepare adapter, hooks, memory, and dev snapshot",
|
|
20
|
+
" forge doctor agent --target codex --json Check adapter, hooks, and Agent Memory readiness",
|
|
21
|
+
" forge agent ingest codex --watch --file .forge/agent/events.ndjson --json",
|
|
22
|
+
" forge docs check --json Check public docs, ReadTheDocs config, links, and local MkDocs tooling",
|
|
23
|
+
" forge docs check --build --install-venv --json Build docs strictly in a local RTD-style venv",
|
|
24
|
+
" forge release doctor --json Aggregate release, sourcemaps, self-host, and docs readiness",
|
|
25
|
+
" forge release check --allow-missing-local-release --json Gate release readiness without failing on unprepared local artifacts",
|
|
26
|
+
" forge self-host check --prepared-only --json Report compose readiness without creating deploy files",
|
|
27
|
+
" forge delta status --verbose --json Include Delta schema, lock, and aggregate count details",
|
|
28
|
+
" forge studio open <app-path> --preview-port 5174 --target codex --json",
|
|
29
|
+
" forge studio snapshot <app-path> --preview-port 5174 --target codex --probe-codex-server --json",
|
|
30
|
+
" forge studio bridge <app-path> --preview-port 5174 --target codex --studio-url http://127.0.0.1:3765 --probe-codex-server --json",
|
|
31
|
+
" forge studio doctor <app-path> --preview-port 5174 --target codex --json",
|
|
32
|
+
" forge studio codex-server <app-path> --probe --json",
|
|
33
|
+
" forge studio watch <app-path> --preview-port 5174 --target codex --json",
|
|
13
34
|
" forge dev Run API, DB/worker, watch, and web app when present",
|
|
14
35
|
" forge dev --once --json One-shot health/diagnostic loop for agents and CI",
|
|
15
36
|
" forge do \"fix\" --json Ask ForgeOS for the right workflow and commands",
|
|
16
|
-
" forge
|
|
37
|
+
" forge cair snapshot Compact CAIR project snapshot for agents",
|
|
38
|
+
" forge cair query \"Q REFS S#1\" Run a semantic CAIR query",
|
|
39
|
+
" forge cair action --plan \"A RN t=S#1 nn=renamed\" Plan a guarded semantic edit",
|
|
40
|
+
" forge cair action \"A APPLY plan=<P#|path>\" Apply a guarded CAIR plan",
|
|
41
|
+
" forge agent print-context --json Read the generated agent context pack",
|
|
42
|
+
" forge inspect all --brief --json Read the smallest aggregate project contract",
|
|
43
|
+
" forge inspect all --json Read the compact generated machine contract",
|
|
44
|
+
" forge mcp serve Serve ForgeOS Agent Memory tools over MCP stdio",
|
|
45
|
+
" forge agent context --current --json Read the Agent Memory context pack",
|
|
46
|
+
" forge agent timeline --json Read external-agent hook activity as a compact timeline",
|
|
17
47
|
" forge doctor windows --json Diagnose native Windows setup and Bun shims",
|
|
48
|
+
" forge bench compiler --json Measure public compiler phase timings",
|
|
49
|
+
" forge manifest validate ./forge.manifest.json --json Validate an external runtime manifest",
|
|
18
50
|
"",
|
|
19
51
|
"Useful next commands:",
|
|
20
52
|
" forge generate",
|
|
21
53
|
" forge check --json",
|
|
54
|
+
" forge verify App-level default verification for the current project",
|
|
22
55
|
" forge verify --standard",
|
|
23
|
-
" forge verify
|
|
56
|
+
" forge verify quick Alias for smoke/fast local checks",
|
|
57
|
+
" forge verify agent Alias for standard agent-loop verification",
|
|
58
|
+
" forge verify release Alias for strict app release verification",
|
|
59
|
+
" forge verify framework Maintainer-only ForgeOS framework test gate",
|
|
60
|
+
" forge verify --strict --typechecker native --test-jobs 6",
|
|
61
|
+
" forge verify framework --test-plan --json",
|
|
24
62
|
"",
|
|
25
63
|
].join("\n");
|
|
26
64
|
}
|
|
@@ -83,7 +121,15 @@ export async function main(argv: string[] = process.argv.slice(2)): Promise<numb
|
|
|
83
121
|
return 1;
|
|
84
122
|
}
|
|
85
123
|
|
|
86
|
-
|
|
124
|
+
const startedAt = Date.now();
|
|
125
|
+
const exitCode = await executeCommand(parsed.command);
|
|
126
|
+
await recordParsedCliCommand({
|
|
127
|
+
command: parsed.command,
|
|
128
|
+
argv,
|
|
129
|
+
exitCode,
|
|
130
|
+
durationMs: Date.now() - startedAt,
|
|
131
|
+
});
|
|
132
|
+
return exitCode;
|
|
87
133
|
}
|
|
88
134
|
|
|
89
135
|
if (isMainModule(import.meta)) {
|
package/src/forge/cli/new.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { run as runGenerate } from "../compiler/orchestrator/run.ts";
|
|
|
8
8
|
import { resolvePackageManagerArgv } from "../compiler/package-manager/executor.ts";
|
|
9
9
|
import { moduleDir } from "../platform/module.ts";
|
|
10
10
|
|
|
11
|
-
export type NewTemplateName = "b2b-support-web" | "minimal-web";
|
|
11
|
+
export type NewTemplateName = "agent-workroom" | "b2b-support-web" | "minimal-web";
|
|
12
12
|
export type NewPackageManager = "bun" | "npm" | "pnpm" | "yarn";
|
|
13
13
|
|
|
14
14
|
export interface NewCommandOptions {
|
|
@@ -45,6 +45,7 @@ const REQUIRED_GITIGNORE_PATHS = [
|
|
|
45
45
|
"forge.lock",
|
|
46
46
|
".forge/cache/",
|
|
47
47
|
".forge/pglite/",
|
|
48
|
+
".forge/delta/",
|
|
48
49
|
".forge/local/",
|
|
49
50
|
".forge/test-cache/",
|
|
50
51
|
".forge/test-runs/",
|
|
@@ -55,6 +56,7 @@ const REQUIRED_GITIGNORE_PATHS = [
|
|
|
55
56
|
".forge/reviews/",
|
|
56
57
|
".forge/impact/",
|
|
57
58
|
".forge/agent-adapters/",
|
|
59
|
+
".forge/studio/",
|
|
58
60
|
] as const;
|
|
59
61
|
|
|
60
62
|
const DEFAULT_FORGE_PACKAGE_SPEC = "npm:forgeos@alpha";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function uniqueNextActions(actions: string[]): string[] {
|
|
2
|
+
return [...new Set(actions)].filter(Boolean);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function releasePrepareNextActions(): string[] {
|
|
6
|
+
return ["forge release prepare --env production", "forge release check --json"];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function releaseReadyNextActions(): string[] {
|
|
10
|
+
return ["forge artifacts verify --json", "forge sourcemaps check --json"];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function selfHostPrepareNextActions(): string[] {
|
|
14
|
+
return ["forge self-host compose", "forge self-host env", "forge self-host check --json"];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function selfHostReadyNextActions(): string[] {
|
|
18
|
+
return ["docker compose -f deploy/docker-compose.yml config", "forge release prepare --env production"];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function docsReadyNextActions(): string[] {
|
|
22
|
+
return ["bun test tests/docs/readthedocs.test.ts", "mkdocs build --strict"];
|
|
23
|
+
}
|