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
|
@@ -34,24 +34,38 @@ import type { QueryRegistry } from "../types/query-registry.ts";
|
|
|
34
34
|
import type { LiveQueryRegistry } from "../types/live-query-registry.ts";
|
|
35
35
|
import type { ClientManifest } from "../client-sdk/build-manifest.ts";
|
|
36
36
|
import type { FrontendGraph } from "../types/frontend-graph.ts";
|
|
37
|
+
import type {
|
|
38
|
+
ForgeExternalServiceEntry,
|
|
39
|
+
ForgeExternalServiceGraph,
|
|
40
|
+
} from "../external-manifest/types.ts";
|
|
37
41
|
import { createDiagnostic } from "../diagnostics/create.ts";
|
|
42
|
+
import { CAIR_SCHEMA_VERSION } from "../../cair/types.ts";
|
|
38
43
|
import { AUTH_ENV, DEFAULT_AUTH_CLAIMS } from "../../runtime/auth/config.ts";
|
|
44
|
+
import {
|
|
45
|
+
forgeCliCommandForWorkspace,
|
|
46
|
+
forgeCliCommandsForWorkspace,
|
|
47
|
+
shouldUseLocalForgeCli,
|
|
48
|
+
} from "../../workspace/forge-cli.ts";
|
|
39
49
|
import type {
|
|
40
50
|
AgentCapabilityMap,
|
|
41
51
|
AgentCapabilityMapEntry,
|
|
42
52
|
AgentContract,
|
|
43
53
|
AgentDependencyApiInfo,
|
|
54
|
+
AgentExternalEntryInfo,
|
|
44
55
|
AgentFrontendRuntimeBindingInfo,
|
|
45
56
|
AgentFrontendUsageInfo,
|
|
46
57
|
AgentHttpEndpointInfo,
|
|
47
58
|
AgentIntegrationInfo,
|
|
48
59
|
AgentRuntimeRule,
|
|
60
|
+
AgentProtocolInfo,
|
|
61
|
+
AgentToolRegistry,
|
|
49
62
|
AgentPlaybook,
|
|
50
63
|
} from "./types.ts";
|
|
51
64
|
|
|
52
65
|
const AGENTS_USER_START = "<!-- user-notes:start -->";
|
|
53
66
|
const AGENTS_USER_END = "<!-- user-notes:end -->";
|
|
54
67
|
const DEFAULT_USER_NOTES = "Project-specific notes can go here.";
|
|
68
|
+
const AGENTS_USER_NOTES_TOKEN = "__FORGE_AGENTS_USER_NOTES__";
|
|
55
69
|
|
|
56
70
|
export interface AgentContractInput {
|
|
57
71
|
workspaceRoot: string;
|
|
@@ -73,17 +87,21 @@ export interface AgentContractInput {
|
|
|
73
87
|
apiSurface: ApiSurface;
|
|
74
88
|
clientManifest: ClientManifest;
|
|
75
89
|
frontendGraph: FrontendGraph;
|
|
90
|
+
externalServices?: ForgeExternalServiceGraph;
|
|
76
91
|
}
|
|
77
92
|
|
|
78
93
|
export interface AgentContractArtifacts {
|
|
79
94
|
contract: AgentContract;
|
|
80
95
|
capabilityMap: AgentCapabilityMap;
|
|
96
|
+
toolRegistry: AgentToolRegistry;
|
|
81
97
|
agentsMd: string;
|
|
82
98
|
appMapMd: string;
|
|
83
99
|
capabilityMapMd: string;
|
|
100
|
+
agentToolsMd: string;
|
|
84
101
|
runtimeRulesMd: string;
|
|
85
102
|
operationPlaybooksMd: string;
|
|
86
103
|
agentQuickstartMd: string;
|
|
104
|
+
agentCairGuideMd: string;
|
|
87
105
|
diagnostics: Diagnostic[];
|
|
88
106
|
}
|
|
89
107
|
|
|
@@ -245,31 +263,100 @@ function runtimeRules(): AgentRuntimeRule[] {
|
|
|
245
263
|
{
|
|
246
264
|
context: "command",
|
|
247
265
|
allowed: ["ctx.db writes", "ctx.emit", "ctx.telemetry buffered events"],
|
|
248
|
-
forbidden: ["network packages", "ctx.secrets", "ctx.ai", "
|
|
266
|
+
forbidden: ["network packages", "ctx.secrets", "ctx.ai", "ctx.ai.runAgent", "ctx.agent.run", "direct secret/env access", "filesystem access"],
|
|
249
267
|
},
|
|
250
268
|
{
|
|
251
269
|
context: "query",
|
|
252
270
|
allowed: ["ctx.db reads", "ctx.telemetry buffered events"],
|
|
253
|
-
forbidden: ["insert/update/delete", "ctx.emit", "ctx.secrets", "ctx.ai", "network integrations"],
|
|
271
|
+
forbidden: ["insert/update/delete", "ctx.emit", "ctx.secrets", "ctx.ai", "ctx.ai.runAgent", "ctx.agent.run", "network integrations"],
|
|
254
272
|
},
|
|
255
273
|
{
|
|
256
274
|
context: "liveQuery",
|
|
257
275
|
allowed: ["ctx.db reads", "tenant-scoped subscriptions"],
|
|
258
|
-
forbidden: ["insert/update/delete", "ctx.emit", "ctx.secrets", "ctx.ai", "network integrations"],
|
|
276
|
+
forbidden: ["insert/update/delete", "ctx.emit", "ctx.secrets", "ctx.ai", "ctx.ai.runAgent", "ctx.agent.run", "network integrations"],
|
|
259
277
|
},
|
|
260
278
|
{
|
|
261
279
|
context: "action",
|
|
262
|
-
allowed: ["ctx.secrets", "integrations", "ctx.ai", "ctx.db reads/writes", "network packages"],
|
|
280
|
+
allowed: ["ctx.secrets", "integrations", "ctx.ai", "ctx.ai.runAgent", "ctx.agent.run", "AI SDK tools", "ctx.db reads/writes", "network packages"],
|
|
263
281
|
forbidden: ["uncommitted transactional side effects"],
|
|
264
282
|
},
|
|
265
283
|
{
|
|
266
284
|
context: "workflow",
|
|
267
|
-
allowed: ["durable steps", "ctx.secrets", "integrations", "ctx.ai", "retries"],
|
|
285
|
+
allowed: ["durable steps", "ctx.secrets", "integrations", "ctx.ai", "ctx.ai.runAgent", "ctx.agent.run", "AI SDK ToolLoopAgent", "retries"],
|
|
268
286
|
forbidden: ["non-idempotent step behavior without guards"],
|
|
269
287
|
},
|
|
270
288
|
];
|
|
271
289
|
}
|
|
272
290
|
|
|
291
|
+
function agentProtocols(workspaceRoot: string): AgentProtocolInfo[] {
|
|
292
|
+
return [
|
|
293
|
+
{
|
|
294
|
+
id: "cair",
|
|
295
|
+
kind: "agent-protocol",
|
|
296
|
+
version: CAIR_SCHEMA_VERSION,
|
|
297
|
+
guide: "src/forge/_generated/agentCairGuide.md",
|
|
298
|
+
commands: forgeCliCommandsForWorkspace(workspaceRoot, [
|
|
299
|
+
"forge cair snapshot",
|
|
300
|
+
"forge cair query \"Q ST\"",
|
|
301
|
+
"forge cair query \"Q S name=<symbol>\"",
|
|
302
|
+
"forge cair query \"Q D S#1\"",
|
|
303
|
+
"forge cair query \"Q R S#1\"",
|
|
304
|
+
"forge cair query \"Q I S#1\"",
|
|
305
|
+
"forge cair action --plan \"A RN t=S#1 nn=<newName>\"",
|
|
306
|
+
"forge cair action \"A APPLY plan=<P#|path>\"",
|
|
307
|
+
"forge cair action \"A ROLLBACK journal=<path>\"",
|
|
308
|
+
]),
|
|
309
|
+
preferredFor: [
|
|
310
|
+
"compact repository orientation",
|
|
311
|
+
"symbol lookup before file reads",
|
|
312
|
+
"semantic code edits",
|
|
313
|
+
"guarded refactors",
|
|
314
|
+
"Forge-native feature creation",
|
|
315
|
+
"impact-aware test selection",
|
|
316
|
+
"token-efficient programming",
|
|
317
|
+
],
|
|
318
|
+
readQueries: [
|
|
319
|
+
"Q ST",
|
|
320
|
+
"Q S name=<symbol>",
|
|
321
|
+
"Q D S#1",
|
|
322
|
+
"Q R S#1",
|
|
323
|
+
"Q I S#1",
|
|
324
|
+
"Q T S#1",
|
|
325
|
+
"Q DEP.API package=<pkg> symbol=<export>",
|
|
326
|
+
],
|
|
327
|
+
mutationActions: [
|
|
328
|
+
"A RN t=S#1 nn=<newName>",
|
|
329
|
+
"A MV t=S#1 to=<path>",
|
|
330
|
+
"A OI f=M#1",
|
|
331
|
+
"A FMT f=M#1",
|
|
332
|
+
"A MC n=<command>",
|
|
333
|
+
"A MQ n=<query>",
|
|
334
|
+
"A MA n=<action>",
|
|
335
|
+
"A MT n=<table> fields=<fields>",
|
|
336
|
+
"A AT t=S#1 kind=unit",
|
|
337
|
+
"A WX t=S#1 file=src/index.ts",
|
|
338
|
+
"A APPLY plan=<P#|path>",
|
|
339
|
+
"A ROLLBACK journal=<path>",
|
|
340
|
+
],
|
|
341
|
+
compactAliases: [
|
|
342
|
+
"Q ST=Q STATUS",
|
|
343
|
+
"Q S=Q SYMBOL",
|
|
344
|
+
"Q D=Q DEF",
|
|
345
|
+
"Q R=Q REFS",
|
|
346
|
+
"Q I=Q IMPACT",
|
|
347
|
+
"A RN=A RENAME.SYMBOL",
|
|
348
|
+
"A MV=A MOVE.SYMBOL",
|
|
349
|
+
"A OI=A ORGANIZE.IMPORTS",
|
|
350
|
+
"A FMT=A FORMAT",
|
|
351
|
+
"A MC=A MAKE.COMMAND",
|
|
352
|
+
"A MT=A MAKE.TABLE",
|
|
353
|
+
"A AT=A ADD.TEST",
|
|
354
|
+
"A WX=A WIRE.EXPORT",
|
|
355
|
+
],
|
|
356
|
+
},
|
|
357
|
+
];
|
|
358
|
+
}
|
|
359
|
+
|
|
273
360
|
function playbooks(): AgentPlaybook[] {
|
|
274
361
|
return [
|
|
275
362
|
{
|
|
@@ -320,6 +407,28 @@ function playbooks(): AgentPlaybook[] {
|
|
|
320
407
|
"Reconnect with Last-Event-ID or ?lastRevision=<revision> to verify resume behavior.",
|
|
321
408
|
],
|
|
322
409
|
},
|
|
410
|
+
{
|
|
411
|
+
title: "Add an AI tool",
|
|
412
|
+
steps: [
|
|
413
|
+
"Add a server-only file under src/ai or src/tools.",
|
|
414
|
+
"Export aiTool({ description, inputSchema, outputSchema, risk, needsApproval, handler }).",
|
|
415
|
+
"Use zod schemas for inputSchema and outputSchema.",
|
|
416
|
+
"Access secrets through the tool context, not process.env.",
|
|
417
|
+
"Mark destructive or external side effects with risk and needsApproval.",
|
|
418
|
+
"Run forge generate and inspect src/forge/_generated/aiRegistry.json.",
|
|
419
|
+
],
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
title: "Add an agent",
|
|
423
|
+
steps: [
|
|
424
|
+
"Export agent({ provider, model, instructions, tools, stopWhen }) from server-only source.",
|
|
425
|
+
"Prefer AI SDK ToolLoopAgent semantics through ctx.agent.run or ctx.ai.runAgent instead of custom loops.",
|
|
426
|
+
"Use stopWhen with stepCount or terminal tool calls to prevent unbounded loops.",
|
|
427
|
+
"Run agents only in actions, workflows, endpoints, or server code.",
|
|
428
|
+
"Run forge inspect ai --json or forge agent print-context --json and confirm the generated context lists the agent.",
|
|
429
|
+
"Use forge ai trace <traceId> --json to inspect agent runs and tool calls.",
|
|
430
|
+
],
|
|
431
|
+
},
|
|
323
432
|
{
|
|
324
433
|
title: "Add a table",
|
|
325
434
|
steps: [
|
|
@@ -355,7 +464,8 @@ function playbooks(): AgentPlaybook[] {
|
|
|
355
464
|
title: "Safely refactor a feature",
|
|
356
465
|
steps: [
|
|
357
466
|
"Run forge refactor rename field <table.field> <table.field> --dry-run --json.",
|
|
358
|
-
"
|
|
467
|
+
"Run forge refactor rename command <oldName> <newName> --dry-run --json when renaming runtime entrypoints.",
|
|
468
|
+
"Rename codemods are AST-aware for extract-action, rename command, rename field, and rename table.",
|
|
359
469
|
"Field renames are scoped to the target table, so tickets.priority only rewrites references linked to tickets.",
|
|
360
470
|
"Review filesToModify, migrationPlan, diagnostics, and risk.",
|
|
361
471
|
"Use --allow-high-risk only for intentional high-risk refactors.",
|
|
@@ -421,16 +531,17 @@ function playbooks(): AgentPlaybook[] {
|
|
|
421
531
|
"Run forge dev --once --json for a one-shot diagnostic cycle.",
|
|
422
532
|
"Use --api-only, --web-only, --no-watch, or --no-worker only when narrowing the loop intentionally.",
|
|
423
533
|
"When a web app exists, forge dev starts the API runtime and the web dev server together and prints both URLs.",
|
|
424
|
-
"Use generated client
|
|
534
|
+
"Use generated client bindings through web/lib/forge.ts, web/src/lib/forge.ts, or Nuxt web/composables/forge.ts.",
|
|
425
535
|
],
|
|
426
536
|
},
|
|
427
537
|
{
|
|
428
538
|
title: "Add or update frontend",
|
|
429
539
|
steps: [
|
|
430
|
-
"Run forge make ui --framework vite --dry-run --json when the app does not have a web root.",
|
|
431
|
-
"
|
|
432
|
-
"
|
|
433
|
-
"
|
|
540
|
+
"Run forge make ui --framework vite --dry-run --json or forge make ui --framework nuxt --dry-run --json when the app does not have a web root.",
|
|
541
|
+
"Run forge make ai-chat support --dry-run --json to add a chat surface backed by /ai/agents/chat streaming and /ai/agents/run JSON automation.",
|
|
542
|
+
"Use web/lib/forge.ts, web/src/lib/forge.ts, or web/composables/forge.ts as the generated client bridge.",
|
|
543
|
+
"Mount ForgeProvider or install the Nuxt Forge plugin once in the web app provider/layout layer; use devAuth for local development.",
|
|
544
|
+
"Use useQuery/useCommand/useLiveQuery or useForgeQuery/useForgeCommand/useForgeLiveQuery instead of raw /commands or /queries fetches.",
|
|
434
545
|
"Run forge generate so frontendGraph and agentContract include routes and bindings.",
|
|
435
546
|
"Run forge inspect capabilities --json to confirm UI actions map to runtime capabilities.",
|
|
436
547
|
"Run forge dev --once --json and forge doctor --json.",
|
|
@@ -509,7 +620,11 @@ function runtimeEntriesWithoutFrontend(contract: AgentContract): AgentCapability
|
|
|
509
620
|
emits: commandEntry.emits,
|
|
510
621
|
dependencies: [],
|
|
511
622
|
},
|
|
512
|
-
notes: [
|
|
623
|
+
notes: [
|
|
624
|
+
commandEntry.source === "external"
|
|
625
|
+
? "External runtime entry is imported from a Forge manifest; execution requires an external runtime bridge."
|
|
626
|
+
: "Runtime entry is available to agents even though no frontend usage was detected.",
|
|
627
|
+
],
|
|
513
628
|
});
|
|
514
629
|
}
|
|
515
630
|
}
|
|
@@ -530,7 +645,11 @@ function runtimeEntriesWithoutFrontend(contract: AgentContract): AgentCapability
|
|
|
530
645
|
emits: [],
|
|
531
646
|
dependencies: [],
|
|
532
647
|
},
|
|
533
|
-
notes: [
|
|
648
|
+
notes: [
|
|
649
|
+
queryEntry.source === "external"
|
|
650
|
+
? "External runtime entry is imported from a Forge manifest; execution requires an external runtime bridge."
|
|
651
|
+
: "Runtime entry is available to agents even though no frontend usage was detected.",
|
|
652
|
+
],
|
|
534
653
|
});
|
|
535
654
|
}
|
|
536
655
|
}
|
|
@@ -656,6 +775,89 @@ function buildCapabilityMap(contract: AgentContract): AgentCapabilityMap {
|
|
|
656
775
|
};
|
|
657
776
|
}
|
|
658
777
|
|
|
778
|
+
function autoToolName(kind: "command" | "query" | "liveQuery", name: string): string {
|
|
779
|
+
return `forge_${kind}_${name}`.replace(/[^A-Za-z0-9_$]/g, "_");
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function buildAgentToolRegistry(contract: AgentContract): AgentToolRegistry {
|
|
783
|
+
const autoTools: AgentToolRegistry["autoTools"] = [
|
|
784
|
+
...contract.commands.map((command) => ({
|
|
785
|
+
name: autoToolName("command", command.name),
|
|
786
|
+
sourceKind: "command" as const,
|
|
787
|
+
sourceName: command.name,
|
|
788
|
+
...(command.policy ? { policy: command.policy } : {}),
|
|
789
|
+
file: command.file,
|
|
790
|
+
http: command.http,
|
|
791
|
+
frontend: command.frontend,
|
|
792
|
+
tablesRead: command.tablesRead,
|
|
793
|
+
tablesWritten: command.tablesWritten,
|
|
794
|
+
emits: command.emits,
|
|
795
|
+
dependencies: [],
|
|
796
|
+
readOnly: false,
|
|
797
|
+
risk: "write" as const,
|
|
798
|
+
needsApproval: command.source === "external"
|
|
799
|
+
? command.external?.needsApproval ?? (command.external?.risk !== "read")
|
|
800
|
+
: true,
|
|
801
|
+
requiresAuth: command.policy !== undefined && command.policy !== "public",
|
|
802
|
+
...(command.source ? { source: command.source } : {}),
|
|
803
|
+
...(command.external ? { external: command.external } : {}),
|
|
804
|
+
execution: command.source === "external"
|
|
805
|
+
? "external-runtime-endpoint" as const
|
|
806
|
+
: "forge-runtime-endpoint" as const,
|
|
807
|
+
})),
|
|
808
|
+
...contract.queries.map((query) => ({
|
|
809
|
+
name: autoToolName("query", query.name),
|
|
810
|
+
sourceKind: "query" as const,
|
|
811
|
+
sourceName: query.name,
|
|
812
|
+
...(query.policy ? { policy: query.policy } : {}),
|
|
813
|
+
file: query.file,
|
|
814
|
+
http: query.http,
|
|
815
|
+
frontend: query.frontend,
|
|
816
|
+
tablesRead: query.tablesRead,
|
|
817
|
+
tablesWritten: [],
|
|
818
|
+
emits: [],
|
|
819
|
+
dependencies: [],
|
|
820
|
+
readOnly: true,
|
|
821
|
+
risk: "read" as const,
|
|
822
|
+
needsApproval: false,
|
|
823
|
+
requiresAuth: query.policy !== undefined && query.policy !== "public",
|
|
824
|
+
...(query.source ? { source: query.source } : {}),
|
|
825
|
+
...(query.external ? { external: query.external } : {}),
|
|
826
|
+
execution: query.source === "external"
|
|
827
|
+
? "external-runtime-endpoint" as const
|
|
828
|
+
: "forge-runtime-endpoint" as const,
|
|
829
|
+
})),
|
|
830
|
+
...contract.liveQueries.map((liveQuery) => ({
|
|
831
|
+
name: autoToolName("liveQuery", liveQuery.name),
|
|
832
|
+
sourceKind: "liveQuery" as const,
|
|
833
|
+
sourceName: liveQuery.name,
|
|
834
|
+
...(liveQuery.policy ? { policy: liveQuery.policy } : {}),
|
|
835
|
+
file: liveQuery.file,
|
|
836
|
+
http: liveQuery.http,
|
|
837
|
+
frontend: liveQuery.frontend,
|
|
838
|
+
tablesRead: liveQuery.tablesRead,
|
|
839
|
+
tablesWritten: [],
|
|
840
|
+
emits: [],
|
|
841
|
+
dependencies: liveQuery.dependencies,
|
|
842
|
+
readOnly: true,
|
|
843
|
+
risk: "read" as const,
|
|
844
|
+
needsApproval: false,
|
|
845
|
+
requiresAuth: liveQuery.policy !== undefined && liveQuery.policy !== "public",
|
|
846
|
+
source: "local" as const,
|
|
847
|
+
execution: "forge-runtime-endpoint" as const,
|
|
848
|
+
})),
|
|
849
|
+
].sort((a, b) => a.name.localeCompare(b.name));
|
|
850
|
+
|
|
851
|
+
return {
|
|
852
|
+
schemaVersion: "0.1.0",
|
|
853
|
+
generatorVersion: GENERATOR_VERSION,
|
|
854
|
+
project: contract.project,
|
|
855
|
+
explicitTools: contract.ai.tools,
|
|
856
|
+
autoTools,
|
|
857
|
+
agents: contract.ai.agents,
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
|
|
659
861
|
function jsAccess(group: string, name: string): string {
|
|
660
862
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)
|
|
661
863
|
? `api.${group}.${name}`
|
|
@@ -695,6 +897,39 @@ function httpEndpointFor(
|
|
|
695
897
|
};
|
|
696
898
|
}
|
|
697
899
|
|
|
900
|
+
function externalEndpointFor(entry: ForgeExternalServiceEntry): AgentHttpEndpointInfo {
|
|
901
|
+
const encodedService = encodeURIComponent(entry.service);
|
|
902
|
+
const encodedName = encodeURIComponent(entry.name);
|
|
903
|
+
const collection = entry.kind === "query" ? "queries" : "commands";
|
|
904
|
+
return {
|
|
905
|
+
method: entry.method ?? "POST",
|
|
906
|
+
path: entry.path ?? `/external/${encodedService}/${collection}/${encodedName}`,
|
|
907
|
+
exampleBody: { args: {} },
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function externalEntryInfo(entry: ForgeExternalServiceEntry): AgentExternalEntryInfo {
|
|
912
|
+
return {
|
|
913
|
+
service: entry.service,
|
|
914
|
+
language: entry.language,
|
|
915
|
+
...(entry.framework ? { framework: entry.framework } : {}),
|
|
916
|
+
transport: entry.transport,
|
|
917
|
+
...(entry.transaction ? { transaction: entry.transaction } : {}),
|
|
918
|
+
...(entry.risk ? { risk: entry.risk } : {}),
|
|
919
|
+
...(typeof entry.needsApproval === "boolean" ? { needsApproval: entry.needsApproval } : {}),
|
|
920
|
+
effects: entry.effects ?? [],
|
|
921
|
+
...(entry.description ? { description: entry.description } : {}),
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
function externalFrontendUsage(entry: ForgeExternalServiceEntry): AgentFrontendUsageInfo {
|
|
926
|
+
return {
|
|
927
|
+
hook: `external manifest '${entry.service}.${entry.name}'; runtime bridge required before client invocation`,
|
|
928
|
+
routes: [],
|
|
929
|
+
components: [],
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
|
|
698
933
|
function frontendUsageFor(
|
|
699
934
|
frontendGraph: FrontendGraph,
|
|
700
935
|
kind: "command" | "query" | "liveQuery" | "action",
|
|
@@ -817,12 +1052,14 @@ export function buildAgentContractArtifacts(
|
|
|
817
1052
|
|
|
818
1053
|
const runtimeEntries = new Map(input.runtimeGraph.entries.map((entry) => [entry.name, entry]));
|
|
819
1054
|
const tableNames = new Set(input.dataGraph.tables.map((table) => table.name));
|
|
820
|
-
const
|
|
1055
|
+
const externalEntries = input.externalServices?.services.flatMap((service) => service.entries) ?? [];
|
|
1056
|
+
const localCommandInfos: AgentContract["commands"] = sorted(Object.keys(input.apiSurface.commands), (name) => name).map((name) => {
|
|
821
1057
|
const entry = runtimeEntries.get(name);
|
|
822
1058
|
const file = entry?.file ?? "";
|
|
823
1059
|
return {
|
|
824
1060
|
name,
|
|
825
1061
|
file,
|
|
1062
|
+
source: "local" as const,
|
|
826
1063
|
policy: authPolicy(commandAuth.get(name)),
|
|
827
1064
|
tablesRead: dbTablesForFile(input.workspaceRoot, file, tableNames, DB_READ_OPS),
|
|
828
1065
|
tablesWritten: dbTablesForFile(input.workspaceRoot, file, tableNames, DB_WRITE_OPS),
|
|
@@ -833,9 +1070,30 @@ export function buildAgentContractArtifacts(
|
|
|
833
1070
|
frontend: frontendUsageFor(input.frontendGraph, "command", name),
|
|
834
1071
|
};
|
|
835
1072
|
});
|
|
836
|
-
const
|
|
1073
|
+
const externalCommandInfos: AgentContract["commands"] = externalEntries
|
|
1074
|
+
.filter((entry) => entry.kind === "command")
|
|
1075
|
+
.map((entry) => ({
|
|
1076
|
+
name: `${entry.service}.${entry.name}`,
|
|
1077
|
+
file: `external:${entry.service}`,
|
|
1078
|
+
source: "external" as const,
|
|
1079
|
+
external: externalEntryInfo(entry),
|
|
1080
|
+
...(entry.policy ? { policy: entry.policy } : {}),
|
|
1081
|
+
tablesRead: [],
|
|
1082
|
+
tablesWritten: entry.transaction === "read-only" ? [] : [`external:${entry.service}`],
|
|
1083
|
+
emits: entry.effects ?? [],
|
|
1084
|
+
allowedPackages: [],
|
|
1085
|
+
forbiddenCapabilities: [],
|
|
1086
|
+
http: externalEndpointFor(entry),
|
|
1087
|
+
frontend: externalFrontendUsage(entry),
|
|
1088
|
+
}));
|
|
1089
|
+
const commandInfos: AgentContract["commands"] = sorted(
|
|
1090
|
+
[...localCommandInfos, ...externalCommandInfos],
|
|
1091
|
+
(command) => command.name,
|
|
1092
|
+
);
|
|
1093
|
+
const localQueryInfos: AgentContract["queries"] = sorted(input.queryRegistry.queries, (query) => query.name).map((query) => ({
|
|
837
1094
|
name: query.name,
|
|
838
1095
|
file: query.file,
|
|
1096
|
+
source: "local" as const,
|
|
839
1097
|
policy: authPolicy(queryAuth.get(query.name)),
|
|
840
1098
|
readOnly: true,
|
|
841
1099
|
tenantScoped: input.tenantScope.tables.length > 0,
|
|
@@ -845,6 +1103,26 @@ export function buildAgentContractArtifacts(
|
|
|
845
1103
|
http: httpEndpointFor("query", query.name),
|
|
846
1104
|
frontend: frontendUsageFor(input.frontendGraph, "query", query.name),
|
|
847
1105
|
}));
|
|
1106
|
+
const externalQueryInfos: AgentContract["queries"] = externalEntries
|
|
1107
|
+
.filter((entry) => entry.kind === "query")
|
|
1108
|
+
.map((entry) => ({
|
|
1109
|
+
name: `${entry.service}.${entry.name}`,
|
|
1110
|
+
file: `external:${entry.service}`,
|
|
1111
|
+
source: "external" as const,
|
|
1112
|
+
external: externalEntryInfo(entry),
|
|
1113
|
+
...(entry.policy ? { policy: entry.policy } : {}),
|
|
1114
|
+
readOnly: true as const,
|
|
1115
|
+
tenantScoped: entry.tenantScoped ?? false,
|
|
1116
|
+
tablesRead: [`external:${entry.service}`],
|
|
1117
|
+
allowedPackages: [],
|
|
1118
|
+
forbiddenCapabilities: [],
|
|
1119
|
+
http: externalEndpointFor(entry),
|
|
1120
|
+
frontend: externalFrontendUsage(entry),
|
|
1121
|
+
}));
|
|
1122
|
+
const queryInfos: AgentContract["queries"] = sorted(
|
|
1123
|
+
[...localQueryInfos, ...externalQueryInfos],
|
|
1124
|
+
(query) => query.name,
|
|
1125
|
+
);
|
|
848
1126
|
const liveQueryInfos: AgentContract["liveQueries"] = sorted(input.liveQueryRegistry.liveQueries, (liveQuery) => liveQuery.name).map(
|
|
849
1127
|
(liveQuery) => {
|
|
850
1128
|
const tablesRead = dbTablesForFile(input.workspaceRoot, liveQuery.file, tableNames, DB_READ_OPS);
|
|
@@ -869,6 +1147,7 @@ export function buildAgentContractArtifacts(
|
|
|
869
1147
|
queries: queryInfos,
|
|
870
1148
|
liveQueries: liveQueryInfos,
|
|
871
1149
|
});
|
|
1150
|
+
const protocols = agentProtocols(input.workspaceRoot);
|
|
872
1151
|
const contract: AgentContract = {
|
|
873
1152
|
schemaVersion: "0.1.0",
|
|
874
1153
|
generatorVersion: GENERATOR_VERSION,
|
|
@@ -929,6 +1208,19 @@ export function buildAgentContractArtifacts(
|
|
|
929
1208
|
}),
|
|
930
1209
|
dependencyApis: buildDependencyApis(input.packageGraph),
|
|
931
1210
|
integrations: buildIntegrations(input.classified),
|
|
1211
|
+
externalServices: (input.externalServices?.services ?? []).map((service) => ({
|
|
1212
|
+
name: service.name,
|
|
1213
|
+
language: service.language,
|
|
1214
|
+
...(service.framework ? { framework: service.framework } : {}),
|
|
1215
|
+
transport: service.transport,
|
|
1216
|
+
...(service.baseUrl ? { baseUrl: service.baseUrl } : {}),
|
|
1217
|
+
...(service.command ? { command: service.command } : {}),
|
|
1218
|
+
...(service.health ? { health: service.health } : {}),
|
|
1219
|
+
commands: sorted(service.entries.filter((entry) => entry.kind === "command"), (entry) => entry.name)
|
|
1220
|
+
.map((entry) => `${service.name}.${entry.name}`),
|
|
1221
|
+
queries: sorted(service.entries.filter((entry) => entry.kind === "query"), (entry) => entry.name)
|
|
1222
|
+
.map((entry) => `${service.name}.${entry.name}`),
|
|
1223
|
+
})),
|
|
932
1224
|
secrets: sorted(input.secretRegistry.secrets, (secret) => secret.name).map((secret) => ({
|
|
933
1225
|
name: secret.name,
|
|
934
1226
|
integration: secret.integration,
|
|
@@ -951,6 +1243,23 @@ export function buildAgentContractArtifacts(
|
|
|
951
1243
|
...(generation.purpose ? { purpose: generation.purpose } : {}),
|
|
952
1244
|
}))
|
|
953
1245
|
.sort((a, b) => `${a.file}:${a.method}:${a.model}`.localeCompare(`${b.file}:${b.method}:${b.model}`)),
|
|
1246
|
+
tools: input.aiRegistry.tools.map((tool) => ({
|
|
1247
|
+
name: tool.name,
|
|
1248
|
+
file: tool.file,
|
|
1249
|
+
...(tool.description ? { description: tool.description } : {}),
|
|
1250
|
+
risk: tool.risk,
|
|
1251
|
+
strict: tool.strict,
|
|
1252
|
+
needsApproval: tool.needsApproval,
|
|
1253
|
+
})),
|
|
1254
|
+
agents: input.aiRegistry.agents.map((agent) => ({
|
|
1255
|
+
name: agent.name,
|
|
1256
|
+
file: agent.file,
|
|
1257
|
+
provider: agent.provider,
|
|
1258
|
+
model: agent.model,
|
|
1259
|
+
...(agent.instructions ? { instructions: agent.instructions } : {}),
|
|
1260
|
+
tools: agent.tools,
|
|
1261
|
+
stopWhen: agent.stopWhen,
|
|
1262
|
+
})),
|
|
954
1263
|
},
|
|
955
1264
|
client: {
|
|
956
1265
|
queries: input.clientManifest.queries,
|
|
@@ -1025,10 +1334,11 @@ export function buildAgentContractArtifacts(
|
|
|
1025
1334
|
},
|
|
1026
1335
|
rules: runtimeRules(),
|
|
1027
1336
|
playbooks: playbooks(),
|
|
1337
|
+
agentProtocols: protocols,
|
|
1028
1338
|
commandsToRun: {
|
|
1029
|
-
beforeEditing: ["forge do inspect --json", "forge dev --once --json", "forge
|
|
1030
|
-
afterEditing: ["forge generate", "forge check", "forge verify --standard",
|
|
1031
|
-
dev: ["forge dev", "forge dev --once --json", "forge do fix --json", "forge do verify --json", "forge dev --api-only", "forge dev --web-only"],
|
|
1339
|
+
beforeEditing: forgeCliCommandsForWorkspace(input.workspaceRoot, ["forge agent onboard --target codex --json", "forge status --json", "forge changed --json", "forge handoff --json", "forge do inspect --json", "forge cair snapshot", "forge cair query \"Q ST\"", "forge dev --once --json", "forge agent print-context --json", "forge check --json"]),
|
|
1340
|
+
afterEditing: forgeCliCommandsForWorkspace(input.workspaceRoot, ["forge generate", "forge check", "forge verify --standard", finalVerifyCommand(input.workspaceRoot)]),
|
|
1341
|
+
dev: forgeCliCommandsForWorkspace(input.workspaceRoot, ["forge dev", "forge dev --once --json", "forge handoff --json", "forge do fix --json", "forge do verify --json", "forge dev --api-only", "forge dev --web-only"]),
|
|
1032
1342
|
},
|
|
1033
1343
|
};
|
|
1034
1344
|
|
|
@@ -1037,31 +1347,39 @@ export function buildAgentContractArtifacts(
|
|
|
1037
1347
|
? (nodeFileSystem.readText(existingAgentsPath) ?? "")
|
|
1038
1348
|
: null;
|
|
1039
1349
|
const userNotes = extractUserNotes(existingAgents);
|
|
1040
|
-
const agentsMd = renderAgentsMd(contract, userNotes);
|
|
1350
|
+
const agentsMd = renderAgentsMd(contract, userNotes, input.workspaceRoot);
|
|
1351
|
+
const toolRegistry = buildAgentToolRegistry(contract);
|
|
1041
1352
|
const capabilityMap = buildCapabilityMap(contract);
|
|
1042
1353
|
const capabilityMapMd = renderCapabilityMapMd(capabilityMap);
|
|
1354
|
+
const agentToolsMd = renderAgentToolsMd(toolRegistry);
|
|
1043
1355
|
const appMapMd = renderAppMapMd(contract);
|
|
1044
1356
|
const runtimeRulesMd = renderRuntimeRulesMd(contract.rules);
|
|
1045
1357
|
const operationPlaybooksMd = renderOperationPlaybooksMd(contract.playbooks);
|
|
1046
|
-
const agentQuickstartMd = renderAgentQuickstartMd();
|
|
1358
|
+
const agentQuickstartMd = renderAgentQuickstartMd(input.workspaceRoot);
|
|
1359
|
+
const agentCairGuideMd = renderAgentCairGuideMd(contract, input.workspaceRoot);
|
|
1047
1360
|
const diagnostics = scanAgentContractForLeaks(contract, [
|
|
1048
1361
|
agentsMd,
|
|
1362
|
+
agentToolsMd,
|
|
1049
1363
|
capabilityMapMd,
|
|
1050
1364
|
appMapMd,
|
|
1051
1365
|
runtimeRulesMd,
|
|
1052
1366
|
operationPlaybooksMd,
|
|
1053
1367
|
agentQuickstartMd,
|
|
1368
|
+
agentCairGuideMd,
|
|
1054
1369
|
]);
|
|
1055
1370
|
|
|
1056
1371
|
return {
|
|
1057
1372
|
contract,
|
|
1058
1373
|
capabilityMap,
|
|
1374
|
+
toolRegistry,
|
|
1059
1375
|
agentsMd,
|
|
1060
1376
|
appMapMd,
|
|
1061
1377
|
capabilityMapMd,
|
|
1378
|
+
agentToolsMd,
|
|
1062
1379
|
runtimeRulesMd,
|
|
1063
1380
|
operationPlaybooksMd,
|
|
1064
1381
|
agentQuickstartMd,
|
|
1382
|
+
agentCairGuideMd,
|
|
1065
1383
|
diagnostics: [...diagnostics, ...capabilityMap.diagnostics],
|
|
1066
1384
|
};
|
|
1067
1385
|
}
|
|
@@ -1099,7 +1417,31 @@ export function serializeCapabilityMapTs(capabilityMap: AgentCapabilityMap): str
|
|
|
1099
1417
|
return `export const capabilityMap = ${JSON.stringify(parsed, null, 2)} as const;\n`;
|
|
1100
1418
|
}
|
|
1101
1419
|
|
|
1102
|
-
function
|
|
1420
|
+
export function serializeAgentToolRegistryJson(registry: AgentToolRegistry): string {
|
|
1421
|
+
return serializeCanonical(registry);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
export function serializeAgentToolRegistryTs(registry: AgentToolRegistry): string {
|
|
1425
|
+
const parsed = JSON.parse(serializeAgentToolRegistryJson(registry)) as unknown;
|
|
1426
|
+
return `export const agentTools = ${JSON.stringify(parsed, null, 2)} as const;\n`;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
function localizeForgeCliMarkdown(workspaceRoot: string, markdown: string): string {
|
|
1430
|
+
return shouldUseLocalForgeCli(workspaceRoot)
|
|
1431
|
+
? markdown.replace(/\bforge (?=[a-z])/g, "node bin/forge.mjs ")
|
|
1432
|
+
: markdown;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
function finalVerifyCommand(workspaceRoot: string): string {
|
|
1436
|
+
const command = shouldUseLocalForgeCli(workspaceRoot) ? "forge verify framework" : "forge verify --strict";
|
|
1437
|
+
return forgeCliCommandForWorkspace(workspaceRoot, command);
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
function renderAgentsMd(contract: AgentContract, userNotes: string, workspaceRoot: string): string {
|
|
1441
|
+
const finalVerify = finalVerifyCommand(workspaceRoot);
|
|
1442
|
+
const cliEntrypoint = shouldUseLocalForgeCli(workspaceRoot)
|
|
1443
|
+
? "This is the ForgeOS framework checkout. Use `node bin/forge.mjs ...` so maintainer commands run against this source tree; reserve the global `forge` command for installed-package smoke tests."
|
|
1444
|
+
: "Use the installed `forge` command for app workflows.";
|
|
1103
1445
|
const tenantTables = contract.data.tables
|
|
1104
1446
|
.filter((table) => table.tenantScoped)
|
|
1105
1447
|
.map((table) => `${table.name} via ${table.tenantField}`);
|
|
@@ -1107,8 +1449,14 @@ function renderAgentsMd(contract: AgentContract, userNotes: string): string {
|
|
|
1107
1449
|
`${policy.name}: ${policy.roles.length > 0 ? policy.roles.join(", ") : policy.kind}`,
|
|
1108
1450
|
);
|
|
1109
1451
|
const secrets = contract.secrets.map((secret) => `${secret.name}${secret.required ? " (required)" : " (optional)"}`);
|
|
1452
|
+
const aiTools = contract.ai.tools.map((tool) =>
|
|
1453
|
+
`${tool.name}: ${tool.description ?? "no description"} (${tool.risk}${tool.needsApproval ? ", approval" : ""})`,
|
|
1454
|
+
);
|
|
1455
|
+
const aiAgents = contract.ai.agents.map((agent) =>
|
|
1456
|
+
`${agent.name}: ${agent.provider}/${agent.model} with ${agent.tools.length > 0 ? agent.tools.join(", ") : "no tools"}`,
|
|
1457
|
+
);
|
|
1110
1458
|
|
|
1111
|
-
|
|
1459
|
+
const generated = localizeForgeCliMarkdown(workspaceRoot, `# AGENTS.md
|
|
1112
1460
|
|
|
1113
1461
|
<!-- forge-generated:start -->
|
|
1114
1462
|
|
|
@@ -1116,23 +1464,51 @@ function renderAgentsMd(contract: AgentContract, userNotes: string): string {
|
|
|
1116
1464
|
|
|
1117
1465
|
This is a ForgeOS application named \`${contract.project.name}\`.
|
|
1118
1466
|
|
|
1467
|
+
## CLI entrypoint
|
|
1468
|
+
|
|
1469
|
+
${cliEntrypoint}
|
|
1470
|
+
|
|
1119
1471
|
## Required workflow
|
|
1120
1472
|
|
|
1121
1473
|
Before editing:
|
|
1122
1474
|
|
|
1123
1475
|
\`\`\`bash
|
|
1476
|
+
forge agent onboard --target codex --json
|
|
1477
|
+
forge status --json
|
|
1478
|
+
forge changed --json
|
|
1479
|
+
forge handoff --json
|
|
1124
1480
|
forge do inspect --json
|
|
1125
1481
|
forge dev --once --json
|
|
1126
|
-
forge
|
|
1482
|
+
forge agent print-context --json
|
|
1127
1483
|
forge check --json
|
|
1128
1484
|
\`\`\`
|
|
1129
1485
|
|
|
1486
|
+
## CAIR first
|
|
1487
|
+
|
|
1488
|
+
Before reading large files or hand-writing patches, prefer the generated CAIR guide:
|
|
1489
|
+
|
|
1490
|
+
\`\`\`bash
|
|
1491
|
+
forge cair snapshot
|
|
1492
|
+
forge cair query "Q ST"
|
|
1493
|
+
forge cair query "Q S name=<symbol>"
|
|
1494
|
+
forge cair query "Q D S#1"
|
|
1495
|
+
forge cair query "Q R S#1"
|
|
1496
|
+
forge cair query "Q I S#1"
|
|
1497
|
+
\`\`\`
|
|
1498
|
+
|
|
1499
|
+
Use \`src/forge/_generated/agentCairGuide.md\` for the full compact protocol. Plan CAIR mutations before applying them:
|
|
1500
|
+
|
|
1501
|
+
\`\`\`bash
|
|
1502
|
+
forge cair action --plan "A RN t=S#1 nn=<newName>"
|
|
1503
|
+
forge cair action "A APPLY plan=<returned-plan-path>"
|
|
1504
|
+
\`\`\`
|
|
1505
|
+
|
|
1130
1506
|
After editing:
|
|
1131
1507
|
|
|
1132
1508
|
\`\`\`bash
|
|
1133
1509
|
forge generate
|
|
1134
1510
|
forge check
|
|
1135
|
-
|
|
1511
|
+
${finalVerify}
|
|
1136
1512
|
\`\`\`
|
|
1137
1513
|
|
|
1138
1514
|
## Do not edit
|
|
@@ -1160,7 +1536,7 @@ Template apps may ignore \`src/forge/_generated/**\` and \`forge.lock\` in git t
|
|
|
1160
1536
|
## Runtime rules
|
|
1161
1537
|
|
|
1162
1538
|
- Do not import network packages inside \`command\`, \`query\`, or \`liveQuery\`.
|
|
1163
|
-
- Do not
|
|
1539
|
+
- Do not read secrets or server runtime config through \`process.env\` in Forge runtime code; use \`ctx.secrets\` or generated config context. Public frontend bridge env such as \`NEXT_PUBLIC_*\` and \`NUXT_PUBLIC_*\` is allowed in web bridge files.
|
|
1164
1540
|
- Do not access cross-tenant data.
|
|
1165
1541
|
- Commands must use \`ctx.emit\` for side effects.
|
|
1166
1542
|
- Actions and workflows handle side effects after commit.
|
|
@@ -1174,10 +1550,13 @@ forge do fix --json
|
|
|
1174
1550
|
forge do verify --json
|
|
1175
1551
|
forge dev --once --json
|
|
1176
1552
|
forge dev
|
|
1553
|
+
forge handoff --json
|
|
1177
1554
|
forge inspect app --json
|
|
1178
1555
|
forge inspect all --json
|
|
1556
|
+
forge inspect all --full --json
|
|
1179
1557
|
forge inspect frontend --json
|
|
1180
1558
|
forge inspect capabilities --json
|
|
1559
|
+
forge inspect agent-tools --json
|
|
1181
1560
|
forge deps inspect <package> --json
|
|
1182
1561
|
forge deps api <package> <symbol> --json
|
|
1183
1562
|
forge deps trace <package> --json
|
|
@@ -1191,9 +1570,13 @@ forge doctor
|
|
|
1191
1570
|
forge doctor windows --json
|
|
1192
1571
|
forge setup windows --json
|
|
1193
1572
|
forge agent print-context --json
|
|
1573
|
+
forge agent doctor --target codex --json
|
|
1574
|
+
forge ai tools --json
|
|
1575
|
+
forge ai agents --json
|
|
1576
|
+
forge ai trace <traceId> --json
|
|
1194
1577
|
forge verify --smoke
|
|
1195
1578
|
forge verify --standard
|
|
1196
|
-
|
|
1579
|
+
${finalVerify}
|
|
1197
1580
|
\`\`\`
|
|
1198
1581
|
|
|
1199
1582
|
## Data
|
|
@@ -1210,6 +1593,21 @@ ${renderList(policies)}
|
|
|
1210
1593
|
|
|
1211
1594
|
${renderList(secrets)}
|
|
1212
1595
|
|
|
1596
|
+
## AI Tools And Agents
|
|
1597
|
+
|
|
1598
|
+
- AI SDK engine: Vercel AI SDK v6.
|
|
1599
|
+
- Forge layer: generated registry, runtime rules, telemetry, secrets, tenant/auth context, and agent contract.
|
|
1600
|
+
- Use \`ctx.agent.run\` or \`ctx.ai.runAgent\` only in actions, workflows, endpoints, and server code.
|
|
1601
|
+
- Do not create custom tool loops; use Forge tools and AI SDK \`ToolLoopAgent\` through the Forge runtime.
|
|
1602
|
+
|
|
1603
|
+
Tools:
|
|
1604
|
+
|
|
1605
|
+
${renderList(aiTools)}
|
|
1606
|
+
|
|
1607
|
+
Agents:
|
|
1608
|
+
|
|
1609
|
+
${renderList(aiAgents)}
|
|
1610
|
+
|
|
1213
1611
|
## Auth
|
|
1214
1612
|
|
|
1215
1613
|
- Modes: ${contract.auth.modes.join(", ")}
|
|
@@ -1233,9 +1631,9 @@ ${contract.frontend.dev ? `- Web URL: ${contract.frontend.dev.url}
|
|
|
1233
1631
|
|
|
1234
1632
|
Rules:
|
|
1235
1633
|
|
|
1236
|
-
- Use the local \`web/**/lib/forge.ts\` bridge to generated
|
|
1237
|
-
- Mount \`<ForgeProvider devAuth>\` in local development.
|
|
1238
|
-
- Use \`useQuery
|
|
1634
|
+
- Use the local \`web/**/lib/forge.ts\` or Nuxt \`web/composables/forge.ts\` bridge to generated bindings.
|
|
1635
|
+
- Mount \`<ForgeProvider devAuth>\` or install the Nuxt Forge plugin in local development.
|
|
1636
|
+
- Use \`useQuery\`/\`useCommand\`/\`useLiveQuery\` or \`useForgeQuery\`/\`useForgeCommand\`/\`useForgeLiveQuery\` instead of raw Forge endpoint fetches in components.
|
|
1239
1637
|
- Keep frontend routes reflected in \`src/forge/_generated/frontendGraph.json\`.
|
|
1240
1638
|
|
|
1241
1639
|
## Common tasks
|
|
@@ -1258,7 +1656,7 @@ forge do verify --json
|
|
|
1258
1656
|
1. Add file in \`src/commands\`.
|
|
1259
1657
|
2. Declare \`auth: can("...")\`.
|
|
1260
1658
|
3. Run \`forge generate\`.
|
|
1261
|
-
4. Run
|
|
1659
|
+
4. Run \`${finalVerify}\`.
|
|
1262
1660
|
|
|
1263
1661
|
### Scaffold a resource
|
|
1264
1662
|
|
|
@@ -1268,6 +1666,8 @@ Use:
|
|
|
1268
1666
|
forge make resource <name> --fields title:text,status:enum(open,closed) --dry-run --json
|
|
1269
1667
|
forge make resource <name> --fields title:text,status:enum(open,closed) --with-ui --yes
|
|
1270
1668
|
forge make ui --framework vite --dry-run --json
|
|
1669
|
+
forge make ui --framework nuxt --dry-run --json
|
|
1670
|
+
forge make ai-chat support --dry-run --json
|
|
1271
1671
|
\`\`\`
|
|
1272
1672
|
|
|
1273
1673
|
Review the plan before applying when the resource touches schema or policies.
|
|
@@ -1283,7 +1683,7 @@ forge inspect frontend --json
|
|
|
1283
1683
|
forge inspect capabilities --json
|
|
1284
1684
|
\`\`\`
|
|
1285
1685
|
|
|
1286
|
-
\`forge dev\` starts the API runtime and web app together when \`web/\` exists. \`forge dev --once --json\` reports routes, components,
|
|
1686
|
+
\`forge dev\` starts the API runtime and web app together when \`web/\` exists. \`forge dev --once --json\` reports routes, components, providers/plugins, bridge files, generated client bindings, direct runtime fetch warnings, capability-map parity warnings, and fix hints.
|
|
1287
1687
|
|
|
1288
1688
|
### Apply a feature blueprint
|
|
1289
1689
|
|
|
@@ -1304,11 +1704,13 @@ Use:
|
|
|
1304
1704
|
\`\`\`bash
|
|
1305
1705
|
forge refactor rename field tickets.priority tickets.urgency --dry-run --json
|
|
1306
1706
|
forge refactor rename field tickets.priority tickets.urgency --yes
|
|
1707
|
+
forge refactor rename command createTicket openTicket --dry-run --json
|
|
1708
|
+
forge refactor rename command createTicket openTicket --yes
|
|
1307
1709
|
\`\`\`
|
|
1308
1710
|
|
|
1309
|
-
These codemods are AST-aware for \`extract-action\`, \`rename field\`, and \`rename table\`. Field renames are scoped to the target table, so \`tickets.priority\` only rewrites references linked to \`tickets\`.
|
|
1711
|
+
These codemods are AST-aware for \`extract-action\`, \`rename command\`, \`rename field\`, and \`rename table\`. Command renames update runtime registries, generated client references, frontend hooks, tests, and string references where safe. Field renames are scoped to the target table, so \`tickets.priority\` only rewrites references linked to \`tickets\`.
|
|
1310
1712
|
|
|
1311
|
-
Never edit \`src/forge/_generated/**\` directly. Review migration hints before applying field or table renames.
|
|
1713
|
+
Never edit \`src/forge/_generated/**\` directly. Review migration hints before applying command, field, or table renames.
|
|
1312
1714
|
|
|
1313
1715
|
### Plan impact-based tests
|
|
1314
1716
|
|
|
@@ -1321,7 +1723,7 @@ forge test run --changed --timeout-ms 120000 --json
|
|
|
1321
1723
|
forge verify --standard
|
|
1322
1724
|
\`\`\`
|
|
1323
1725
|
|
|
1324
|
-
Use \`forge verify --standard\` for the normal agent development loop. Finish handoffs with \`
|
|
1726
|
+
Use \`forge verify --standard\` for the normal agent development loop. Finish handoffs with \`${finalVerify}\` when the change is ready.
|
|
1325
1727
|
|
|
1326
1728
|
### Repair a failing check
|
|
1327
1729
|
|
|
@@ -1334,6 +1736,20 @@ forge repair plan --from-last-test-run --write
|
|
|
1334
1736
|
|
|
1335
1737
|
Apply only high-confidence deterministic repairs automatically. Review medium or low confidence repairs before changing code.
|
|
1336
1738
|
|
|
1739
|
+
### Add AI tools or agents
|
|
1740
|
+
|
|
1741
|
+
Use:
|
|
1742
|
+
|
|
1743
|
+
\`\`\`bash
|
|
1744
|
+
forge generate
|
|
1745
|
+
forge inspect ai --json
|
|
1746
|
+
forge agent print-context --json
|
|
1747
|
+
forge ai check --json
|
|
1748
|
+
forge ai trace <traceId> --json
|
|
1749
|
+
\`\`\`
|
|
1750
|
+
|
|
1751
|
+
Define tools with \`aiTool({ inputSchema, outputSchema, risk, needsApproval, handler })\` and agents with \`agent({ provider, model, instructions, tools, stopWhen })\`. Execute agents with \`ctx.agent.run\` or \`ctx.ai.runAgent\` only from actions, workflows, endpoints, or server code. In dev, POST \`/ai/agents/run\` returns JSON for automation and POST \`/ai/agents/chat\` returns an AI SDK UIMessage stream for React \`useChat\`; both accept \`agent: "<exportedAgentName>"\` and use generated auto-tools from \`agentTools.json\`.
|
|
1752
|
+
|
|
1337
1753
|
### Export agent adapters
|
|
1338
1754
|
|
|
1339
1755
|
Use:
|
|
@@ -1366,7 +1782,7 @@ forge deps upgrade-plan <package> --to latest
|
|
|
1366
1782
|
forge deps inspect <package> --json
|
|
1367
1783
|
forge deps api <package> <symbol> --json
|
|
1368
1784
|
forge deps upgrade-apply <plan>
|
|
1369
|
-
|
|
1785
|
+
${finalVerify}
|
|
1370
1786
|
\`\`\`
|
|
1371
1787
|
|
|
1372
1788
|
Do not manually edit \`package.json\` for package upgrades unless necessary.
|
|
@@ -1387,10 +1803,11 @@ Durable invalidations live in \`_forge_live_invalidations\`.
|
|
|
1387
1803
|
|
|
1388
1804
|
${AGENTS_USER_START}
|
|
1389
1805
|
|
|
1390
|
-
${
|
|
1806
|
+
${AGENTS_USER_NOTES_TOKEN}
|
|
1391
1807
|
|
|
1392
1808
|
${AGENTS_USER_END}
|
|
1393
1809
|
`);
|
|
1810
|
+
return normalizeNewlines(generated.replace(AGENTS_USER_NOTES_TOKEN, () => userNotes));
|
|
1394
1811
|
}
|
|
1395
1812
|
|
|
1396
1813
|
function renderAppMapMd(contract: AgentContract): string {
|
|
@@ -1471,6 +1888,48 @@ function renderAppMapMd(contract: AgentContract): string {
|
|
|
1471
1888
|
lines.push(`### ${workflow.name}`, `Trigger: ${workflow.trigger ?? "manual"}`, "Steps:", ...renderList(workflow.steps).split("\n"), "");
|
|
1472
1889
|
}
|
|
1473
1890
|
|
|
1891
|
+
lines.push("## AI", "");
|
|
1892
|
+
lines.push("### Providers", "", ...renderList(contract.ai.providers).split("\n"), "");
|
|
1893
|
+
lines.push("### Generations", "");
|
|
1894
|
+
for (const generation of contract.ai.generations) {
|
|
1895
|
+
lines.push(
|
|
1896
|
+
`- ${generation.method}: ${generation.provider}/${generation.model} in ${generation.file}${generation.purpose ? ` (${generation.purpose})` : ""}`,
|
|
1897
|
+
);
|
|
1898
|
+
}
|
|
1899
|
+
if (contract.ai.generations.length === 0) {
|
|
1900
|
+
lines.push("- none");
|
|
1901
|
+
}
|
|
1902
|
+
lines.push("", "### Tools", "");
|
|
1903
|
+
for (const tool of contract.ai.tools) {
|
|
1904
|
+
lines.push(
|
|
1905
|
+
`#### ${tool.name}`,
|
|
1906
|
+
`File: ${tool.file}`,
|
|
1907
|
+
`Risk: ${tool.risk}`,
|
|
1908
|
+
`Strict: ${tool.strict ? "yes" : "no"}`,
|
|
1909
|
+
`Needs approval: ${String(tool.needsApproval)}`,
|
|
1910
|
+
`Description: ${tool.description ?? "none"}`,
|
|
1911
|
+
"",
|
|
1912
|
+
);
|
|
1913
|
+
}
|
|
1914
|
+
if (contract.ai.tools.length === 0) {
|
|
1915
|
+
lines.push("- none", "");
|
|
1916
|
+
}
|
|
1917
|
+
lines.push("### Agents", "");
|
|
1918
|
+
for (const agent of contract.ai.agents) {
|
|
1919
|
+
lines.push(
|
|
1920
|
+
`#### ${agent.name}`,
|
|
1921
|
+
`File: ${agent.file}`,
|
|
1922
|
+
`Model: ${agent.provider}/${agent.model}`,
|
|
1923
|
+
"Tools:",
|
|
1924
|
+
...renderList(agent.tools).split("\n"),
|
|
1925
|
+
`Stop when: ${JSON.stringify(agent.stopWhen)}`,
|
|
1926
|
+
"",
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
if (contract.ai.agents.length === 0) {
|
|
1930
|
+
lines.push("- none", "");
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1474
1933
|
lines.push("## Frontend", "");
|
|
1475
1934
|
lines.push(`Present: ${contract.frontend.present ? "yes" : "no"}`);
|
|
1476
1935
|
lines.push(`Framework: ${contract.frontend.framework}`);
|
|
@@ -1631,6 +2090,72 @@ function renderCapabilityMapMd(capabilityMap: AgentCapabilityMap): string {
|
|
|
1631
2090
|
return normalizeNewlines(lines.join("\n"));
|
|
1632
2091
|
}
|
|
1633
2092
|
|
|
2093
|
+
function renderAgentToolsMd(registry: AgentToolRegistry): string {
|
|
2094
|
+
const lines = [
|
|
2095
|
+
"# Agent Tools",
|
|
2096
|
+
"",
|
|
2097
|
+
`Project: ${registry.project.name}`,
|
|
2098
|
+
"",
|
|
2099
|
+
"## Explicit AI Tools",
|
|
2100
|
+
"",
|
|
2101
|
+
];
|
|
2102
|
+
|
|
2103
|
+
for (const tool of registry.explicitTools) {
|
|
2104
|
+
lines.push(
|
|
2105
|
+
`### ${tool.name}`,
|
|
2106
|
+
`File: ${tool.file}`,
|
|
2107
|
+
`Risk: ${tool.risk}`,
|
|
2108
|
+
`Strict: ${tool.strict ? "yes" : "no"}`,
|
|
2109
|
+
`Needs approval: ${String(tool.needsApproval)}`,
|
|
2110
|
+
`Description: ${tool.description ?? "none"}`,
|
|
2111
|
+
"",
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
if (registry.explicitTools.length === 0) {
|
|
2115
|
+
lines.push("- none", "");
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
lines.push("## Auto Tools From Forge Runtime", "");
|
|
2119
|
+
for (const tool of registry.autoTools) {
|
|
2120
|
+
lines.push(
|
|
2121
|
+
`### ${tool.name}`,
|
|
2122
|
+
`Source: ${tool.sourceKind} ${tool.sourceName}`,
|
|
2123
|
+
`File: ${tool.file}`,
|
|
2124
|
+
`HTTP: ${tool.http.method} ${tool.http.path}`,
|
|
2125
|
+
`Policy: ${tool.policy ?? "none"}`,
|
|
2126
|
+
`Requires auth: ${tool.requiresAuth ? "yes" : "no"}`,
|
|
2127
|
+
`Read-only: ${tool.readOnly ? "yes" : "no"}`,
|
|
2128
|
+
`Risk: ${tool.risk}`,
|
|
2129
|
+
`Needs approval: ${String(tool.needsApproval)}`,
|
|
2130
|
+
`Frontend hook: \`${tool.frontend.hook}\``,
|
|
2131
|
+
`Reads: ${tool.tablesRead.length > 0 ? tool.tablesRead.join(", ") : "none"}`,
|
|
2132
|
+
`Writes: ${tool.tablesWritten.length > 0 ? tool.tablesWritten.join(", ") : "none"}`,
|
|
2133
|
+
`Emits: ${tool.emits.length > 0 ? tool.emits.join(", ") : "none"}`,
|
|
2134
|
+
"",
|
|
2135
|
+
);
|
|
2136
|
+
}
|
|
2137
|
+
if (registry.autoTools.length === 0) {
|
|
2138
|
+
lines.push("- none", "");
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
lines.push("## Agents", "");
|
|
2142
|
+
for (const agent of registry.agents) {
|
|
2143
|
+
lines.push(
|
|
2144
|
+
`### ${agent.name}`,
|
|
2145
|
+
`File: ${agent.file}`,
|
|
2146
|
+
`Model: ${agent.provider}/${agent.model}`,
|
|
2147
|
+
`Tools: ${agent.tools.length > 0 ? agent.tools.join(", ") : "none"}`,
|
|
2148
|
+
`Stop when: ${JSON.stringify(agent.stopWhen)}`,
|
|
2149
|
+
"",
|
|
2150
|
+
);
|
|
2151
|
+
}
|
|
2152
|
+
if (registry.agents.length === 0) {
|
|
2153
|
+
lines.push("- none", "");
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
return normalizeNewlines(lines.join("\n"));
|
|
2157
|
+
}
|
|
2158
|
+
|
|
1634
2159
|
function renderOperationPlaybooksMd(playbookEntries: AgentPlaybook[]): string {
|
|
1635
2160
|
const lines = ["# Operation Playbooks", ""];
|
|
1636
2161
|
for (const playbook of playbookEntries) {
|
|
@@ -1643,21 +2168,29 @@ function renderOperationPlaybooksMd(playbookEntries: AgentPlaybook[]): string {
|
|
|
1643
2168
|
return normalizeNewlines(lines.join("\n"));
|
|
1644
2169
|
}
|
|
1645
2170
|
|
|
1646
|
-
function renderAgentQuickstartMd(): string {
|
|
1647
|
-
|
|
2171
|
+
function renderAgentQuickstartMd(workspaceRoot: string): string {
|
|
2172
|
+
const finalVerify = finalVerifyCommand(workspaceRoot);
|
|
2173
|
+
return normalizeNewlines(localizeForgeCliMarkdown(workspaceRoot, `# Agent Quickstart
|
|
1648
2174
|
|
|
1649
2175
|
Run:
|
|
1650
2176
|
|
|
1651
2177
|
\`\`\`bash
|
|
2178
|
+
forge agent onboard --target codex --json
|
|
2179
|
+
forge status --json
|
|
2180
|
+
forge changed --json
|
|
2181
|
+
forge handoff --json
|
|
1652
2182
|
forge do inspect --json
|
|
1653
2183
|
forge do fix --json
|
|
1654
2184
|
forge do verify --json
|
|
1655
2185
|
forge dev --once --json
|
|
1656
2186
|
forge dev
|
|
1657
|
-
forge
|
|
2187
|
+
forge agent print-context --json
|
|
1658
2188
|
forge inspect frontend --json
|
|
1659
2189
|
forge inspect capabilities --json
|
|
2190
|
+
forge inspect agent-tools --json
|
|
2191
|
+
forge inspect all --json
|
|
1660
2192
|
forge check --json
|
|
2193
|
+
forge ai trace <traceId> --json
|
|
1661
2194
|
\`\`\`
|
|
1662
2195
|
|
|
1663
2196
|
Never edit:
|
|
@@ -1673,7 +2206,158 @@ Always finish with:
|
|
|
1673
2206
|
|
|
1674
2207
|
\`\`\`bash
|
|
1675
2208
|
forge generate
|
|
1676
|
-
|
|
2209
|
+
${finalVerify}
|
|
1677
2210
|
\`\`\`
|
|
1678
|
-
`);
|
|
2211
|
+
`));
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
function renderAgentCairGuideMd(contract: AgentContract, workspaceRoot: string): string {
|
|
2215
|
+
const cair = contract.agentProtocols.find((protocol) => protocol.id === "cair");
|
|
2216
|
+
const finalVerify = finalVerifyCommand(workspaceRoot);
|
|
2217
|
+
const summary = [
|
|
2218
|
+
`commands=${contract.commands.length}`,
|
|
2219
|
+
`queries=${contract.queries.length}`,
|
|
2220
|
+
`liveQueries=${contract.liveQueries.length}`,
|
|
2221
|
+
`actions=${contract.actions.length}`,
|
|
2222
|
+
`workflows=${contract.workflows.length}`,
|
|
2223
|
+
`tables=${contract.data.tables.length}`,
|
|
2224
|
+
].join(" ");
|
|
2225
|
+
return normalizeNewlines(localizeForgeCliMarkdown(workspaceRoot, `# CAIR Agent Guide
|
|
2226
|
+
|
|
2227
|
+
Project: ${contract.project.name}
|
|
2228
|
+
CAIR version: ${cair?.version ?? CAIR_SCHEMA_VERSION}
|
|
2229
|
+
Surface: ${summary}
|
|
2230
|
+
|
|
2231
|
+
CAIR is the compact agent protocol for reading and changing this Forge workspace. Use it before opening whole files when symbol, module, dependency, test, or impact context is enough.
|
|
2232
|
+
|
|
2233
|
+
## First commands
|
|
2234
|
+
|
|
2235
|
+
\`\`\`bash
|
|
2236
|
+
forge cair snapshot
|
|
2237
|
+
forge cair query "Q ST"
|
|
2238
|
+
\`\`\`
|
|
2239
|
+
|
|
2240
|
+
The snapshot emits compact ids:
|
|
2241
|
+
|
|
2242
|
+
- \`M#\` modules/files
|
|
2243
|
+
- \`S#\` symbols
|
|
2244
|
+
- \`P#\` packages
|
|
2245
|
+
- \`API#\` dependency APIs
|
|
2246
|
+
- \`T#\` tests
|
|
2247
|
+
|
|
2248
|
+
## Read before editing
|
|
2249
|
+
|
|
2250
|
+
\`\`\`bash
|
|
2251
|
+
forge cair query "Q S name=<symbol>"
|
|
2252
|
+
forge cair query "Q D S#1"
|
|
2253
|
+
forge cair query "Q R S#1"
|
|
2254
|
+
forge cair query "Q I S#1"
|
|
2255
|
+
forge cair query "Q T S#1"
|
|
2256
|
+
forge cair query "Q DEP.API package=<pkg> symbol=<export>"
|
|
2257
|
+
\`\`\`
|
|
2258
|
+
|
|
2259
|
+
Only open source files after CAIR shows that the exact file or body is needed.
|
|
2260
|
+
|
|
2261
|
+
## Plan, apply, rollback
|
|
2262
|
+
|
|
2263
|
+
Never apply semantic mutations first. Create a plan:
|
|
2264
|
+
|
|
2265
|
+
\`\`\`bash
|
|
2266
|
+
forge cair action --plan "A RN t=S#1 nn=<newName>"
|
|
2267
|
+
\`\`\`
|
|
2268
|
+
|
|
2269
|
+
Apply the returned plan path:
|
|
2270
|
+
|
|
2271
|
+
\`\`\`bash
|
|
2272
|
+
forge cair action "A APPLY plan=<P#|.forge/cair/plans/...json>"
|
|
2273
|
+
\`\`\`
|
|
2274
|
+
|
|
2275
|
+
Keep returned journal paths for rollback:
|
|
2276
|
+
|
|
2277
|
+
\`\`\`bash
|
|
2278
|
+
forge cair action "A ROLLBACK journal=.forge/cair/journal/<journal>.json"
|
|
2279
|
+
\`\`\`
|
|
2280
|
+
|
|
2281
|
+
## Semantic actions
|
|
2282
|
+
|
|
2283
|
+
\`\`\`txt
|
|
2284
|
+
A RN t=S#1 nn=<newName>
|
|
2285
|
+
A MV t=S#1 to=src/target.ts
|
|
2286
|
+
A SIG t=S#1 signature="export function x(input: string): boolean"
|
|
2287
|
+
A PARAM t=S#1 name=tenantId type=string default="defaultTenant"
|
|
2288
|
+
A CALLS t=S#1 appendArg="defaultTenant"
|
|
2289
|
+
A OI f=M#1
|
|
2290
|
+
A FMT f=M#1
|
|
2291
|
+
\`\`\`
|
|
2292
|
+
|
|
2293
|
+
For high-risk semantic actions, include expectations when available:
|
|
2294
|
+
|
|
2295
|
+
\`\`\`txt
|
|
2296
|
+
expect.file=src/path.ts
|
|
2297
|
+
expect.kind=command
|
|
2298
|
+
expect.hash=<sha256>
|
|
2299
|
+
\`\`\`
|
|
2300
|
+
|
|
2301
|
+
## Forge-native actions
|
|
2302
|
+
|
|
2303
|
+
Prefer Forge-native CAIR actions over hand-writing boilerplate:
|
|
2304
|
+
|
|
2305
|
+
\`\`\`txt
|
|
2306
|
+
A MC n=createTicket
|
|
2307
|
+
A MQ n=listTickets
|
|
2308
|
+
A MA n=chargeCustomer
|
|
2309
|
+
A MT n=tickets fields=title:text,status:text
|
|
2310
|
+
A AT t=S#1 kind=unit
|
|
2311
|
+
A WX t=S#1 file=src/index.ts
|
|
2312
|
+
\`\`\`
|
|
2313
|
+
|
|
2314
|
+
## Compact aliases
|
|
2315
|
+
|
|
2316
|
+
Queries:
|
|
2317
|
+
|
|
2318
|
+
\`\`\`txt
|
|
2319
|
+
Q ST = Q STATUS
|
|
2320
|
+
Q S = Q SYMBOL
|
|
2321
|
+
Q D = Q DEF
|
|
2322
|
+
Q R = Q REFS
|
|
2323
|
+
Q I = Q IMPACT
|
|
2324
|
+
Q M = Q MODULE
|
|
2325
|
+
Q T = Q TESTS
|
|
2326
|
+
Q API = Q DEP.API
|
|
2327
|
+
\`\`\`
|
|
2328
|
+
|
|
2329
|
+
Actions:
|
|
2330
|
+
|
|
2331
|
+
\`\`\`txt
|
|
2332
|
+
A RN = A RENAME.SYMBOL
|
|
2333
|
+
A MV = A MOVE.SYMBOL
|
|
2334
|
+
A OI = A ORGANIZE.IMPORTS
|
|
2335
|
+
A FMT = A FORMAT
|
|
2336
|
+
A MC = A MAKE.COMMAND
|
|
2337
|
+
A MQ = A MAKE.QUERY
|
|
2338
|
+
A MA = A MAKE.ACTION
|
|
2339
|
+
A MT = A MAKE.TABLE
|
|
2340
|
+
A AT = A ADD.TEST
|
|
2341
|
+
A WX = A WIRE.EXPORT
|
|
2342
|
+
A AP = A APPLY
|
|
2343
|
+
A RB = A ROLLBACK
|
|
2344
|
+
\`\`\`
|
|
2345
|
+
|
|
2346
|
+
## Verification
|
|
2347
|
+
|
|
2348
|
+
After CAIR edits, run the narrowest useful checks:
|
|
2349
|
+
|
|
2350
|
+
\`\`\`bash
|
|
2351
|
+
forge check --json
|
|
2352
|
+
forge verify --standard
|
|
2353
|
+
${finalVerify}
|
|
2354
|
+
\`\`\`
|
|
2355
|
+
|
|
2356
|
+
## Constraints
|
|
2357
|
+
|
|
2358
|
+
- Do not edit \`src/forge/_generated/**\` unless explicitly allowed.
|
|
2359
|
+
- Do not bypass \`--plan\` for semantic edits.
|
|
2360
|
+
- Do not use CAIR as blind text replacement when a semantic action exists.
|
|
2361
|
+
- Use TypeScript language service, ast-grep, ts-morph, or raw file reads only as implementation backends or fallbacks. CAIR is the agent-facing protocol.
|
|
2362
|
+
`));
|
|
1679
2363
|
}
|