forgeos 0.1.0-alpha.0
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 +1 -0
- package/AGENTS.md +277 -0
- package/CHANGELOG.md +8 -0
- package/CONTRIBUTING.md +58 -0
- package/README.md +377 -0
- package/bin/forge-bun.mjs +110 -0
- package/bin/forge.mjs +19 -0
- package/package.json +96 -0
- package/packages/eslint-plugin-forge/index.ts +15 -0
- package/packages/eslint-plugin-forge/package.json +10 -0
- package/packages/eslint-plugin-forge/src/check-source.ts +95 -0
- package/packages/eslint-plugin-forge/src/load-artifacts.ts +24 -0
- package/packages/eslint-plugin-forge/src/rule-no-forge-guard-violation.ts +93 -0
- package/src/forge/_generated/actionSubscriptions.json +2 -0
- package/src/forge/_generated/actionSubscriptions.ts +10 -0
- package/src/forge/_generated/agentAdapterManifest.json +2 -0
- package/src/forge/_generated/agentAdapterManifest.ts +73 -0
- package/src/forge/_generated/agentContract.json +2 -0
- package/src/forge/_generated/agentContract.ts +912 -0
- package/src/forge/_generated/agentQuickstart.md +32 -0
- package/src/forge/_generated/aiContext.ts +59 -0
- package/src/forge/_generated/aiModels.json +2 -0
- package/src/forge/_generated/aiModels.ts +35 -0
- package/src/forge/_generated/aiProviders.json +2 -0
- package/src/forge/_generated/aiProviders.ts +23 -0
- package/src/forge/_generated/aiRegistry.json +2 -0
- package/src/forge/_generated/aiRegistry.ts +29 -0
- package/src/forge/_generated/api.json +2 -0
- package/src/forge/_generated/api.ts +8 -0
- package/src/forge/_generated/appGraph.json +2 -0
- package/src/forge/_generated/appGraph.ts +14511 -0
- package/src/forge/_generated/appMap.md +35 -0
- package/src/forge/_generated/artifactManifest.json +2 -0
- package/src/forge/_generated/artifactManifest.ts +7 -0
- package/src/forge/_generated/authClaims.json +2 -0
- package/src/forge/_generated/authClaims.ts +13 -0
- package/src/forge/_generated/authConfig.json +2 -0
- package/src/forge/_generated/authConfig.ts +17 -0
- package/src/forge/_generated/authContext.ts +23 -0
- package/src/forge/_generated/authRegistry.json +2 -0
- package/src/forge/_generated/authRegistry.ts +25 -0
- package/src/forge/_generated/buildInfo.json +2 -0
- package/src/forge/_generated/buildInfo.ts +9 -0
- package/src/forge/_generated/capabilityMap.json +2 -0
- package/src/forge/_generated/capabilityMap.md +15 -0
- package/src/forge/_generated/capabilityMap.ts +17 -0
- package/src/forge/_generated/client.ts +282 -0
- package/src/forge/_generated/clientApi.ts +9 -0
- package/src/forge/_generated/clientManifest.json +2 -0
- package/src/forge/_generated/clientManifest.ts +39 -0
- package/src/forge/_generated/clientTypes.ts +78 -0
- package/src/forge/_generated/configRegistry.json +2 -0
- package/src/forge/_generated/configRegistry.ts +4 -0
- package/src/forge/_generated/dataGraph.json +2 -0
- package/src/forge/_generated/dataGraph.ts +8 -0
- package/src/forge/_generated/db.json +2 -0
- package/src/forge/_generated/db.ts +2 -0
- package/src/forge/_generated/dbSecurityManifest.json +2 -0
- package/src/forge/_generated/dbSecurityManifest.ts +15 -0
- package/src/forge/_generated/dbSessionContext.json +2 -0
- package/src/forge/_generated/dbSessionContext.ts +39 -0
- package/src/forge/_generated/deployManifest.json +2 -0
- package/src/forge/_generated/deployManifest.ts +14 -0
- package/src/forge/_generated/devManifest.json +2 -0
- package/src/forge/_generated/devManifest.ts +47 -0
- package/src/forge/_generated/envSchema.json +2 -0
- package/src/forge/_generated/envSchema.ts +59 -0
- package/src/forge/_generated/frontendGraph.json +2 -0
- package/src/forge/_generated/frontendGraph.ts +27 -0
- package/src/forge/_generated/importGuards.json +2 -0
- package/src/forge/_generated/importGuards.ts +652 -0
- package/src/forge/_generated/index.ts +67 -0
- package/src/forge/_generated/liveProductionManifest.json +2 -0
- package/src/forge/_generated/liveProductionManifest.ts +23 -0
- package/src/forge/_generated/liveProtocol.json +2 -0
- package/src/forge/_generated/liveProtocol.ts +21 -0
- package/src/forge/_generated/liveQueryRegistry.json +2 -0
- package/src/forge/_generated/liveQueryRegistry.ts +9 -0
- package/src/forge/_generated/liveTransportConfig.json +2 -0
- package/src/forge/_generated/liveTransportConfig.ts +19 -0
- package/src/forge/_generated/makeRegistry.json +2 -0
- package/src/forge/_generated/makeRegistry.ts +163 -0
- package/src/forge/_generated/makeTemplates.json +2 -0
- package/src/forge/_generated/makeTemplates.ts +61 -0
- package/src/forge/_generated/mockMap.json +2 -0
- package/src/forge/_generated/mockMap.ts +7 -0
- package/src/forge/_generated/operationPlaybooks.md +145 -0
- package/src/forge/_generated/packageGraph.json +2 -0
- package/src/forge/_generated/packageGraph.ts +168569 -0
- package/src/forge/_generated/packageUpgradeRegistry.json +2 -0
- package/src/forge/_generated/packageUpgradeRegistry.ts +15 -0
- package/src/forge/_generated/permissionMatrix.json +2 -0
- package/src/forge/_generated/permissionMatrix.ts +7 -0
- package/src/forge/_generated/policyRegistry.json +2 -0
- package/src/forge/_generated/policyRegistry.ts +11 -0
- package/src/forge/_generated/queryRegistry.json +2 -0
- package/src/forge/_generated/queryRegistry.ts +9 -0
- package/src/forge/_generated/react.d.ts +22 -0
- package/src/forge/_generated/react.ts +29 -0
- package/src/forge/_generated/reactManifest.json +2 -0
- package/src/forge/_generated/reactManifest.ts +19 -0
- package/src/forge/_generated/releaseManifest.json +2 -0
- package/src/forge/_generated/releaseManifest.ts +25 -0
- package/src/forge/_generated/rlsPolicies.json +2 -0
- package/src/forge/_generated/rlsPolicies.sql +34 -0
- package/src/forge/_generated/rlsPolicies.ts +6 -0
- package/src/forge/_generated/runtimeGraph.json +2 -0
- package/src/forge/_generated/runtimeGraph.ts +8 -0
- package/src/forge/_generated/runtimeMatrix.json +2 -0
- package/src/forge/_generated/runtimeMatrix.ts +229125 -0
- package/src/forge/_generated/runtimeRegistry.ts +2 -0
- package/src/forge/_generated/runtimeRules.md +79 -0
- package/src/forge/_generated/secretRegistry.json +2 -0
- package/src/forge/_generated/secretRegistry.ts +50 -0
- package/src/forge/_generated/secretsContext.ts +11 -0
- package/src/forge/_generated/serverApi.ts +10 -0
- package/src/forge/_generated/sourceMapManifest.json +2 -0
- package/src/forge/_generated/sourceMapManifest.ts +7 -0
- package/src/forge/_generated/sqlPlan.json +2 -0
- package/src/forge/_generated/sqlPlan.ts +88 -0
- package/src/forge/_generated/subscriptionManifest.json +2 -0
- package/src/forge/_generated/subscriptionManifest.ts +7 -0
- package/src/forge/_generated/symbolicationManifest.json +2 -0
- package/src/forge/_generated/symbolicationManifest.ts +17 -0
- package/src/forge/_generated/telemetryRegistry.json +2 -0
- package/src/forge/_generated/telemetryRegistry.ts +9 -0
- package/src/forge/_generated/telemetrySinks.json +2 -0
- package/src/forge/_generated/telemetrySinks.ts +11 -0
- package/src/forge/_generated/tenantScope.json +2 -0
- package/src/forge/_generated/tenantScope.ts +8 -0
- package/src/forge/_generated/testGraph.json +2 -0
- package/src/forge/_generated/testGraph.ts +3054 -0
- package/src/forge/_generated/testPlanRegistry.json +2 -0
- package/src/forge/_generated/testPlanRegistry.ts +33 -0
- package/src/forge/_generated/uiRoutes.json +2 -0
- package/src/forge/_generated/uiRoutes.ts +16 -0
- package/src/forge/_generated/uiScenarios.json +2 -0
- package/src/forge/_generated/uiScenarios.ts +30 -0
- package/src/forge/_generated/uiTestManifest.json +2 -0
- package/src/forge/_generated/uiTestManifest.ts +27 -0
- package/src/forge/_generated/workflowRegistry.json +2 -0
- package/src/forge/_generated/workflowRegistry.ts +9 -0
- package/src/forge/_generated/workflowSubscriptions.json +2 -0
- package/src/forge/_generated/workflowSubscriptions.ts +10 -0
- package/src/forge/agent-adapters/index.ts +1002 -0
- package/src/forge/agent-adapters/types.ts +135 -0
- package/src/forge/cli/agent-contract.ts +50 -0
- package/src/forge/cli/ai.ts +148 -0
- package/src/forge/cli/auth.ts +198 -0
- package/src/forge/cli/build.ts +105 -0
- package/src/forge/cli/bun-exec.ts +4 -0
- package/src/forge/cli/commands.ts +1130 -0
- package/src/forge/cli/db.ts +316 -0
- package/src/forge/cli/deps.ts +277 -0
- package/src/forge/cli/dev.ts +529 -0
- package/src/forge/cli/doctor.ts +209 -0
- package/src/forge/cli/feature.ts +485 -0
- package/src/forge/cli/index.ts +25 -0
- package/src/forge/cli/lint-forge.ts +119 -0
- package/src/forge/cli/live.ts +179 -0
- package/src/forge/cli/main.ts +92 -0
- package/src/forge/cli/make.ts +133 -0
- package/src/forge/cli/new.ts +505 -0
- package/src/forge/cli/outbox.ts +297 -0
- package/src/forge/cli/output.ts +114 -0
- package/src/forge/cli/parse.ts +2211 -0
- package/src/forge/cli/policy.ts +204 -0
- package/src/forge/cli/query.ts +91 -0
- package/src/forge/cli/refactor.ts +221 -0
- package/src/forge/cli/release.ts +285 -0
- package/src/forge/cli/rls.ts +322 -0
- package/src/forge/cli/run.ts +76 -0
- package/src/forge/cli/secrets.ts +274 -0
- package/src/forge/cli/self-host.ts +468 -0
- package/src/forge/cli/serve.ts +93 -0
- package/src/forge/cli/telemetry.ts +219 -0
- package/src/forge/cli/verify.ts +587 -0
- package/src/forge/cli/version.ts +1 -0
- package/src/forge/cli/windows.ts +413 -0
- package/src/forge/cli/worker.ts +87 -0
- package/src/forge/cli/workflow.ts +424 -0
- package/src/forge/compiler/action-subscriptions/build.ts +116 -0
- package/src/forge/compiler/action-subscriptions/constants.ts +2 -0
- package/src/forge/compiler/action-subscriptions/index.ts +6 -0
- package/src/forge/compiler/action-subscriptions/parse.ts +6 -0
- package/src/forge/compiler/agent-contract/build.ts +1651 -0
- package/src/forge/compiler/agent-contract/types.ts +326 -0
- package/src/forge/compiler/ai-registry/build.ts +165 -0
- package/src/forge/compiler/ai-registry/constants.ts +2 -0
- package/src/forge/compiler/ai-registry/parse.ts +56 -0
- package/src/forge/compiler/api-surface/build.ts +107 -0
- package/src/forge/compiler/app-graph/build.ts +121 -0
- package/src/forge/compiler/app-graph/classify.ts +10 -0
- package/src/forge/compiler/app-graph/dup-symbol.ts +29 -0
- package/src/forge/compiler/app-graph/extract.ts +124 -0
- package/src/forge/compiler/app-graph/forge-apis.ts +29 -0
- package/src/forge/compiler/app-graph/index.ts +15 -0
- package/src/forge/compiler/app-graph/module-graph.ts +320 -0
- package/src/forge/compiler/app-graph/parser.ts +119 -0
- package/src/forge/compiler/app-graph/symbols.ts +48 -0
- package/src/forge/compiler/app-graph/tsconfig-hash.ts +62 -0
- package/src/forge/compiler/app-graph/types.ts +43 -0
- package/src/forge/compiler/app-graph/versions.ts +14 -0
- package/src/forge/compiler/cache/index.ts +17 -0
- package/src/forge/compiler/cache/key.ts +46 -0
- package/src/forge/compiler/cache/scheduler.ts +72 -0
- package/src/forge/compiler/cache/store.ts +78 -0
- package/src/forge/compiler/classifier/capabilities.ts +78 -0
- package/src/forge/compiler/classifier/classify.ts +113 -0
- package/src/forge/compiler/classifier/contexts.ts +188 -0
- package/src/forge/compiler/classifier/index.ts +18 -0
- package/src/forge/compiler/classifier/runtime-matrix.ts +45 -0
- package/src/forge/compiler/classifier/secrets.ts +41 -0
- package/src/forge/compiler/classifier/signals.ts +129 -0
- package/src/forge/compiler/client-sdk/build-manifest.ts +151 -0
- package/src/forge/compiler/client-sdk/render-client.ts +432 -0
- package/src/forge/compiler/data-graph/build.ts +131 -0
- package/src/forge/compiler/data-graph/constants.ts +5 -0
- package/src/forge/compiler/data-graph/index.ts +6 -0
- package/src/forge/compiler/data-graph/parse.ts +176 -0
- package/src/forge/compiler/data-graph/rls/build.ts +222 -0
- package/src/forge/compiler/data-graph/rls/types.ts +62 -0
- package/src/forge/compiler/data-graph/sql/ddl.ts +390 -0
- package/src/forge/compiler/data-graph/sql/naming.ts +10 -0
- package/src/forge/compiler/data-graph/sql/serialize.ts +85 -0
- package/src/forge/compiler/data-graph/sql/types.ts +37 -0
- package/src/forge/compiler/dev-manifest/build.ts +170 -0
- package/src/forge/compiler/dev-manifest/constants.ts +5 -0
- package/src/forge/compiler/diagnostics/codes.ts +611 -0
- package/src/forge/compiler/diagnostics/create.ts +245 -0
- package/src/forge/compiler/diagnostics/index.ts +55 -0
- package/src/forge/compiler/emitter/artifact-kind.ts +14 -0
- package/src/forge/compiler/emitter/barrel.ts +44 -0
- package/src/forge/compiler/emitter/constants.ts +7 -0
- package/src/forge/compiler/emitter/emit.ts +237 -0
- package/src/forge/compiler/emitter/index.ts +24 -0
- package/src/forge/compiler/emitter/lock.ts +62 -0
- package/src/forge/compiler/emitter/render.ts +73 -0
- package/src/forge/compiler/emitter/write.ts +35 -0
- package/src/forge/compiler/frontend-graph/build.ts +495 -0
- package/src/forge/compiler/fs/index.ts +23 -0
- package/src/forge/compiler/fs/memory.ts +233 -0
- package/src/forge/compiler/fs/node.ts +139 -0
- package/src/forge/compiler/fs/profile.ts +108 -0
- package/src/forge/compiler/fs/types.ts +52 -0
- package/src/forge/compiler/guards/artifacts.ts +96 -0
- package/src/forge/compiler/guards/check-ai-usage.ts +98 -0
- package/src/forge/compiler/guards/check-import-guards.ts +106 -0
- package/src/forge/compiler/guards/check-process-env.ts +98 -0
- package/src/forge/compiler/guards/check-query-usage.ts +76 -0
- package/src/forge/compiler/guards/index.ts +11 -0
- package/src/forge/compiler/guards/propagate-contexts.ts +57 -0
- package/src/forge/compiler/index.ts +17 -0
- package/src/forge/compiler/integration/add.ts +496 -0
- package/src/forge/compiler/integration/index.ts +17 -0
- package/src/forge/compiler/integration/plan.ts +283 -0
- package/src/forge/compiler/integration/render.ts +189 -0
- package/src/forge/compiler/integration/snapshot.ts +52 -0
- package/src/forge/compiler/integration/templates/ai.ts +131 -0
- package/src/forge/compiler/integration/templates/index.ts +8 -0
- package/src/forge/compiler/integration/templates/posthog.ts +145 -0
- package/src/forge/compiler/integration/templates/render.ts +113 -0
- package/src/forge/compiler/integration/templates/sentry.ts +151 -0
- package/src/forge/compiler/integration/templates/stripe.ts +109 -0
- package/src/forge/compiler/integration/templates/types.ts +14 -0
- package/src/forge/compiler/integration/templates/zod.ts +55 -0
- package/src/forge/compiler/live-production/types.ts +122 -0
- package/src/forge/compiler/live-query-registry/build.ts +150 -0
- package/src/forge/compiler/live-query-registry/constants.ts +2 -0
- package/src/forge/compiler/make-registry/build.ts +179 -0
- package/src/forge/compiler/orchestrator/discover.ts +214 -0
- package/src/forge/compiler/orchestrator/fast-check.ts +117 -0
- package/src/forge/compiler/orchestrator/generate-lock.ts +138 -0
- package/src/forge/compiler/orchestrator/guards.ts +5 -0
- package/src/forge/compiler/orchestrator/index.ts +27 -0
- package/src/forge/compiler/orchestrator/manifest-hashes.ts +21 -0
- package/src/forge/compiler/orchestrator/manifest.ts +92 -0
- package/src/forge/compiler/orchestrator/orphans.ts +51 -0
- package/src/forge/compiler/orchestrator/plan.ts +876 -0
- package/src/forge/compiler/orchestrator/profile.ts +36 -0
- package/src/forge/compiler/orchestrator/run.ts +277 -0
- package/src/forge/compiler/orchestrator/serialize.ts +886 -0
- package/src/forge/compiler/orchestrator/session.ts +96 -0
- package/src/forge/compiler/orchestrator/types.ts +31 -0
- package/src/forge/compiler/orchestrator/verify.ts +38 -0
- package/src/forge/compiler/orchestrator/workspace-index.ts +154 -0
- package/src/forge/compiler/package-graph/capabilities-stub.ts +33 -0
- package/src/forge/compiler/package-graph/checksum.ts +97 -0
- package/src/forge/compiler/package-graph/compiler.ts +392 -0
- package/src/forge/compiler/package-graph/constants.ts +4 -0
- package/src/forge/compiler/package-graph/dts-extractor.ts +142 -0
- package/src/forge/compiler/package-graph/exports-discovery.ts +84 -0
- package/src/forge/compiler/package-graph/extract-dts.ts +32 -0
- package/src/forge/compiler/package-graph/index.ts +33 -0
- package/src/forge/compiler/package-graph/jsdoc.ts +62 -0
- package/src/forge/compiler/package-graph/read-file.ts +21 -0
- package/src/forge/compiler/package-graph/resolve.ts +127 -0
- package/src/forge/compiler/package-manager/adapter.ts +237 -0
- package/src/forge/compiler/package-manager/bun-executable.ts +92 -0
- package/src/forge/compiler/package-manager/commands.ts +47 -0
- package/src/forge/compiler/package-manager/detect.ts +79 -0
- package/src/forge/compiler/package-manager/executor.ts +117 -0
- package/src/forge/compiler/package-manager/index.ts +22 -0
- package/src/forge/compiler/package-manager/parse-spec.ts +16 -0
- package/src/forge/compiler/package-manager/version.ts +27 -0
- package/src/forge/compiler/package-upgrades/apply.ts +195 -0
- package/src/forge/compiler/package-upgrades/comparator.ts +181 -0
- package/src/forge/compiler/package-upgrades/impact.ts +139 -0
- package/src/forge/compiler/package-upgrades/markdown.ts +97 -0
- package/src/forge/compiler/package-upgrades/planner.ts +532 -0
- package/src/forge/compiler/package-upgrades/risk.ts +208 -0
- package/src/forge/compiler/package-upgrades/types.ts +174 -0
- package/src/forge/compiler/policy-registry/build.ts +266 -0
- package/src/forge/compiler/policy-registry/constants.ts +2 -0
- package/src/forge/compiler/policy-registry/parse.ts +81 -0
- package/src/forge/compiler/primitives/compare.ts +26 -0
- package/src/forge/compiler/primitives/hash.ts +40 -0
- package/src/forge/compiler/primitives/header.ts +45 -0
- package/src/forge/compiler/primitives/index.ts +45 -0
- package/src/forge/compiler/primitives/paths.ts +24 -0
- package/src/forge/compiler/primitives/result.ts +164 -0
- package/src/forge/compiler/primitives/serialize.ts +66 -0
- package/src/forge/compiler/primitives/sort.ts +87 -0
- package/src/forge/compiler/query-registry/build.ts +114 -0
- package/src/forge/compiler/query-registry/constants.ts +2 -0
- package/src/forge/compiler/recipes/definitions.ts +289 -0
- package/src/forge/compiler/recipes/helpers.ts +37 -0
- package/src/forge/compiler/recipes/index.ts +21 -0
- package/src/forge/compiler/recipes/registry.ts +102 -0
- package/src/forge/compiler/release/build.ts +100 -0
- package/src/forge/compiler/release/types.ts +119 -0
- package/src/forge/compiler/runtime-graph/build.ts +137 -0
- package/src/forge/compiler/runtime-graph/constants.ts +5 -0
- package/src/forge/compiler/runtime-graph/index.ts +5 -0
- package/src/forge/compiler/sandbox/artifact-sanitize.ts +26 -0
- package/src/forge/compiler/sandbox/backends/child.ts +123 -0
- package/src/forge/compiler/sandbox/backends/docker.ts +173 -0
- package/src/forge/compiler/sandbox/index.ts +51 -0
- package/src/forge/compiler/sandbox/inspect.ts +143 -0
- package/src/forge/compiler/sandbox/inspector-entry.ts +115 -0
- package/src/forge/compiler/sandbox/limits.ts +31 -0
- package/src/forge/compiler/sandbox/scrub-env.ts +60 -0
- package/src/forge/compiler/sandbox/secret-scan.ts +54 -0
- package/src/forge/compiler/sandbox/serialize.ts +106 -0
- package/src/forge/compiler/sandbox/types.ts +7 -0
- package/src/forge/compiler/secret-registry/build.ts +123 -0
- package/src/forge/compiler/telemetry-registry/build.ts +89 -0
- package/src/forge/compiler/telemetry-registry/constants.ts +2 -0
- package/src/forge/compiler/telemetry-registry/parse.ts +13 -0
- package/src/forge/compiler/test-graph/build.ts +277 -0
- package/src/forge/compiler/types/action-subscriptions.ts +19 -0
- package/src/forge/compiler/types/ai-registry.ts +33 -0
- package/src/forge/compiler/types/app-graph.ts +80 -0
- package/src/forge/compiler/types/capability.ts +29 -0
- package/src/forge/compiler/types/classification.ts +9 -0
- package/src/forge/compiler/types/cli.ts +159 -0
- package/src/forge/compiler/types/data-graph.ts +24 -0
- package/src/forge/compiler/types/dev-manifest.ts +41 -0
- package/src/forge/compiler/types/diagnostic.ts +12 -0
- package/src/forge/compiler/types/emit.ts +25 -0
- package/src/forge/compiler/types/frontend-graph.ts +81 -0
- package/src/forge/compiler/types/import-guards.ts +19 -0
- package/src/forge/compiler/types/index.ts +98 -0
- package/src/forge/compiler/types/integration.ts +25 -0
- package/src/forge/compiler/types/json.ts +3 -0
- package/src/forge/compiler/types/live-query-registry.ts +32 -0
- package/src/forge/compiler/types/lock.ts +37 -0
- package/src/forge/compiler/types/package-graph.ts +84 -0
- package/src/forge/compiler/types/policy-registry.ts +69 -0
- package/src/forge/compiler/types/query-registry.ts +18 -0
- package/src/forge/compiler/types/runtime-graph.ts +30 -0
- package/src/forge/compiler/types/runtime-matrix.ts +16 -0
- package/src/forge/compiler/types/runtime.ts +30 -0
- package/src/forge/compiler/types/sandbox.ts +24 -0
- package/src/forge/compiler/types/secret-registry.ts +38 -0
- package/src/forge/compiler/types/telemetry-registry.ts +26 -0
- package/src/forge/compiler/types/test-graph.ts +45 -0
- package/src/forge/compiler/types/workflow-registry.ts +42 -0
- package/src/forge/compiler/workflow-registry/build.ts +180 -0
- package/src/forge/compiler/workflow-registry/constants.ts +2 -0
- package/src/forge/compiler/workflow-registry/index.ts +5 -0
- package/src/forge/compiler/workflow-registry/parse.ts +19 -0
- package/src/forge/dev/server.ts +1379 -0
- package/src/forge/dev/types.ts +49 -0
- package/src/forge/dev/watch.ts +109 -0
- package/src/forge/dev-console/cycle.ts +652 -0
- package/src/forge/dev-console/types.ts +99 -0
- package/src/forge/feature/compiler.ts +656 -0
- package/src/forge/feature/examples.ts +125 -0
- package/src/forge/feature/types.ts +177 -0
- package/src/forge/impact/index.ts +1160 -0
- package/src/forge/impact/types.ts +151 -0
- package/src/forge/intent/index.ts +490 -0
- package/src/forge/intent/types.ts +73 -0
- package/src/forge/make/fields.ts +146 -0
- package/src/forge/make/index.ts +1101 -0
- package/src/forge/make/naming.ts +42 -0
- package/src/forge/make/templates.ts +525 -0
- package/src/forge/make/types.ts +151 -0
- package/src/forge/platform/module.ts +20 -0
- package/src/forge/policy.ts +1 -0
- package/src/forge/react/index.ts +418 -0
- package/src/forge/refactor/index.ts +1936 -0
- package/src/forge/refactor/text-utils.ts +34 -0
- package/src/forge/refactor/types.ts +191 -0
- package/src/forge/refactor/workspace-fs.ts +171 -0
- package/src/forge/repair/index.ts +656 -0
- package/src/forge/repair/rules/index.ts +476 -0
- package/src/forge/repair/types.ts +175 -0
- package/src/forge/review/index.ts +992 -0
- package/src/forge/review/types.ts +196 -0
- package/src/forge/runtime/ai/check.ts +86 -0
- package/src/forge/runtime/ai/context.ts +394 -0
- package/src/forge/runtime/ai/cost-estimator.ts +41 -0
- package/src/forge/runtime/ai/mock.ts +49 -0
- package/src/forge/runtime/ai/providers.ts +78 -0
- package/src/forge/runtime/ai/state.ts +17 -0
- package/src/forge/runtime/ai/types.ts +67 -0
- package/src/forge/runtime/auth/authenticate.ts +58 -0
- package/src/forge/runtime/auth/claims.ts +119 -0
- package/src/forge/runtime/auth/config.ts +148 -0
- package/src/forge/runtime/auth/errors.ts +45 -0
- package/src/forge/runtime/auth/evaluate.ts +126 -0
- package/src/forge/runtime/auth/resolve.ts +74 -0
- package/src/forge/runtime/auth/types.ts +87 -0
- package/src/forge/runtime/auth/verifier.ts +138 -0
- package/src/forge/runtime/context/create-context.ts +204 -0
- package/src/forge/runtime/context/create-query-context.ts +34 -0
- package/src/forge/runtime/db/adapter.ts +31 -0
- package/src/forge/runtime/db/factory.ts +83 -0
- package/src/forge/runtime/db/generated-client.ts +294 -0
- package/src/forge/runtime/db/memory-adapter.ts +706 -0
- package/src/forge/runtime/db/migrate.ts +132 -0
- package/src/forge/runtime/db/outbox.ts +54 -0
- package/src/forge/runtime/db/pglite-adapter.ts +51 -0
- package/src/forge/runtime/db/postgres-adapter.ts +112 -0
- package/src/forge/runtime/db/read-only-client.ts +97 -0
- package/src/forge/runtime/db/session-context.ts +62 -0
- package/src/forge/runtime/executor.ts +446 -0
- package/src/forge/runtime/live/dependency-tracker.ts +57 -0
- package/src/forge/runtime/live/invalidation-log.ts +189 -0
- package/src/forge/runtime/live/live-query-runner.ts +267 -0
- package/src/forge/runtime/live/registry.ts +28 -0
- package/src/forge/runtime/live/sse.ts +75 -0
- package/src/forge/runtime/live/subscription-manager.ts +443 -0
- package/src/forge/runtime/live/types.ts +143 -0
- package/src/forge/runtime/outbox/claim.ts +153 -0
- package/src/forge/runtime/outbox/process.ts +298 -0
- package/src/forge/runtime/outbox/retry.ts +8 -0
- package/src/forge/runtime/outbox/subscriptions.ts +33 -0
- package/src/forge/runtime/outbox/types.ts +69 -0
- package/src/forge/runtime/policy/check.ts +157 -0
- package/src/forge/runtime/policy/load.ts +55 -0
- package/src/forge/runtime/query/registry.ts +19 -0
- package/src/forge/runtime/query/run-query.ts +347 -0
- package/src/forge/runtime/release/runtime.ts +322 -0
- package/src/forge/runtime/release/symbolicate.ts +175 -0
- package/src/forge/runtime/runner/command-transaction.ts +193 -0
- package/src/forge/runtime/runner/run-entry.ts +226 -0
- package/src/forge/runtime/secrets/check.ts +78 -0
- package/src/forge/runtime/secrets/create-context.ts +138 -0
- package/src/forge/runtime/secrets/env-loader.ts +94 -0
- package/src/forge/runtime/secrets/runtime-bundle.ts +47 -0
- package/src/forge/runtime/secrets/types.ts +31 -0
- package/src/forge/runtime/telemetry/buffer.ts +87 -0
- package/src/forge/runtime/telemetry/context.ts +192 -0
- package/src/forge/runtime/telemetry/correlation.ts +13 -0
- package/src/forge/runtime/telemetry/flush.ts +190 -0
- package/src/forge/runtime/telemetry/process.ts +20 -0
- package/src/forge/runtime/telemetry/scrubber.ts +115 -0
- package/src/forge/runtime/telemetry/sinks/local-jsonl.ts +39 -0
- package/src/forge/runtime/telemetry/sinks/posthog.ts +64 -0
- package/src/forge/runtime/telemetry/sinks/sentry.ts +60 -0
- package/src/forge/runtime/telemetry/spans.ts +58 -0
- package/src/forge/runtime/telemetry/types.ts +64 -0
- package/src/forge/runtime/workflows/cancel.ts +26 -0
- package/src/forge/runtime/workflows/create-run.ts +98 -0
- package/src/forge/runtime/workflows/process-run.ts +182 -0
- package/src/forge/runtime/workflows/process-step.ts +190 -0
- package/src/forge/runtime/workflows/process.ts +260 -0
- package/src/forge/runtime/workflows/registry.ts +51 -0
- package/src/forge/runtime/workflows/resolve-step.ts +46 -0
- package/src/forge/runtime/workflows/retry-run.ts +44 -0
- package/src/forge/runtime/workflows/retry.ts +8 -0
- package/src/forge/runtime/workflows/sanitize.ts +19 -0
- package/src/forge/runtime/workflows/start-from-outbox.ts +71 -0
- package/src/forge/runtime/workflows/types.ts +77 -0
- package/src/forge/server.ts +96 -0
- package/src/forge/ui/index.ts +770 -0
- package/src/forge/ui/types.ts +191 -0
- package/templates/b2b-support-web/.env.example +22 -0
- package/templates/b2b-support-web/.vscode/settings.json +14 -0
- package/templates/b2b-support-web/AGENTS.md +108 -0
- package/templates/b2b-support-web/README.md +48 -0
- package/templates/b2b-support-web/forge.config.ts +3 -0
- package/templates/b2b-support-web/package.json +34 -0
- package/templates/b2b-support-web/src/actions/captureTicketCreated.ts +14 -0
- package/templates/b2b-support-web/src/commands/closeTicket.ts +20 -0
- package/templates/b2b-support-web/src/commands/createTicket.ts +47 -0
- package/templates/b2b-support-web/src/commands/manageBilling.ts +9 -0
- package/templates/b2b-support-web/src/forge/schema.ts +35 -0
- package/templates/b2b-support-web/src/policies.ts +9 -0
- package/templates/b2b-support-web/src/queries/getTicket.ts +6 -0
- package/templates/b2b-support-web/src/queries/listTickets.ts +6 -0
- package/templates/b2b-support-web/src/queries/liveTickets.ts +9 -0
- package/templates/b2b-support-web/src/workflows/triageTicketWorkflow.ts +64 -0
- package/templates/b2b-support-web/tsconfig.json +14 -0
- package/templates/b2b-support-web/web/app/globals.css +77 -0
- package/templates/b2b-support-web/web/app/layout.tsx +13 -0
- package/templates/b2b-support-web/web/app/page.tsx +13 -0
- package/templates/b2b-support-web/web/app/providers.tsx +21 -0
- package/templates/b2b-support-web/web/app/tickets/page.tsx +21 -0
- package/templates/b2b-support-web/web/components/CreateTicketForm.tsx +43 -0
- package/templates/b2b-support-web/web/components/PolicyDeniedDemo.tsx +31 -0
- package/templates/b2b-support-web/web/components/TicketList.tsx +52 -0
- package/templates/b2b-support-web/web/components/TraceDetails.tsx +18 -0
- package/templates/b2b-support-web/web/components/TriageStatus.tsx +13 -0
- package/templates/b2b-support-web/web/lib/forge.ts +13 -0
- package/templates/b2b-support-web/web/next-env.d.ts +5 -0
- package/templates/b2b-support-web/web/next.config.ts +8 -0
- package/templates/b2b-support-web/web/package.json +21 -0
- package/templates/b2b-support-web/web/tsconfig.json +30 -0
- package/templates/minimal-web/.vscode/settings.json +14 -0
- package/templates/minimal-web/README.md +21 -0
- package/templates/minimal-web/forge.config.ts +3 -0
- package/templates/minimal-web/package.json +32 -0
- package/templates/minimal-web/src/actions/logNoteCreated.ts +11 -0
- package/templates/minimal-web/src/commands/createNote.ts +26 -0
- package/templates/minimal-web/src/forge/schema.ts +12 -0
- package/templates/minimal-web/src/policies.ts +6 -0
- package/templates/minimal-web/src/queries/listNotes.ts +8 -0
- package/templates/minimal-web/src/queries/liveNotes.ts +8 -0
- package/templates/minimal-web/tsconfig.json +15 -0
- package/templates/minimal-web/web/index.html +12 -0
- package/templates/minimal-web/web/package.json +21 -0
- package/templates/minimal-web/web/src/App.tsx +89 -0
- package/templates/minimal-web/web/src/lib/forge.ts +13 -0
- package/templates/minimal-web/web/src/main.tsx +13 -0
- package/templates/minimal-web/web/src/styles.css +156 -0
- package/templates/minimal-web/web/tsconfig.json +18 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import type { Diagnostic, DiagnosticSeverity } from "../types/diagnostic.ts";
|
|
2
|
+
import type { DiagnosticCode } from "./codes.ts";
|
|
3
|
+
|
|
4
|
+
export interface DiagnosticInput {
|
|
5
|
+
severity: DiagnosticSeverity;
|
|
6
|
+
code: DiagnosticCode | string;
|
|
7
|
+
message: string;
|
|
8
|
+
file?: string;
|
|
9
|
+
span?: { start: number; end: number };
|
|
10
|
+
fixHint?: string;
|
|
11
|
+
suggestedCommands?: string[];
|
|
12
|
+
docs?: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface DiagnosticGuidance {
|
|
16
|
+
fixHint: string;
|
|
17
|
+
suggestedCommands?: string[];
|
|
18
|
+
docs?: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function defaultGuidanceForCode(code: string): DiagnosticGuidance | null {
|
|
22
|
+
if (code === "FORGE_DRIFT") {
|
|
23
|
+
return {
|
|
24
|
+
fixHint: "Regenerate Forge artifacts and re-run the drift check.",
|
|
25
|
+
suggestedCommands: ["forge generate", "forge generate --check"],
|
|
26
|
+
docs: ["AGENTS.md"],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (code === "FORGE_IMPACT_GENERATED_DRIFT") {
|
|
30
|
+
return {
|
|
31
|
+
fixHint: "Generated artifacts are stale. Run forge generate, then re-run the impact or verify command.",
|
|
32
|
+
suggestedCommands: ["forge generate", "forge generate --check", "forge verify --changed --json"],
|
|
33
|
+
docs: ["AGENTS.md", "src/forge/_generated/agentContract.json"],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (code === "FORGE_GENERATE_LOCKED") {
|
|
37
|
+
return {
|
|
38
|
+
fixHint: "Wait for the active forge generate command to finish. If no Forge process is running, delete .forge/locks/generate.lock and retry.",
|
|
39
|
+
suggestedCommands: ["forge generate", "forge generate --check", "forge dev --once --json"],
|
|
40
|
+
docs: ["AGENTS.md"],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (code === "FORGE_GUARD_VIOLATION" || code === "FORGE_RUNTIME_GUARD_BLOCKED") {
|
|
44
|
+
return {
|
|
45
|
+
fixHint: "Move forbidden side effects into an action/workflow, or replace the package with an allowed adapter for this runtime.",
|
|
46
|
+
suggestedCommands: ["forge repair diagnose --diagnostic FORGE_GUARD_VIOLATION --json", "forge refactor extract-action <command> --package <package> --dry-run --json"],
|
|
47
|
+
docs: ["src/forge/_generated/runtimeRules.md", "AGENTS.md"],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (code === "FORGE_SECRET_DIRECT_PROCESS_ENV") {
|
|
51
|
+
return {
|
|
52
|
+
fixHint: "Use ctx.secrets or ctx.config instead of reading process.env directly from app runtime code.",
|
|
53
|
+
suggestedCommands: ["forge repair diagnose --diagnostic FORGE_SECRET_DIRECT_PROCESS_ENV --json", "forge refactor replace-process-env <ENV_NAME> --dry-run --json"],
|
|
54
|
+
docs: ["src/forge/_generated/runtimeRules.md"],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (code === "FORGE_AI_FORBIDDEN_CONTEXT") {
|
|
58
|
+
return {
|
|
59
|
+
fixHint: "Move AI calls to an action, workflow, endpoint, or server context.",
|
|
60
|
+
suggestedCommands: ["forge repair diagnose --diagnostic FORGE_AI_FORBIDDEN_CONTEXT --json", "forge inspect ai --json"],
|
|
61
|
+
docs: ["src/forge/_generated/runtimeRules.md"],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (code === "FORGE_QUERY_FORBIDDEN_WRITE" || code === "FORGE_QUERY_FORBIDDEN_SIDE_EFFECT") {
|
|
65
|
+
return {
|
|
66
|
+
fixHint: "Keep queries and liveQueries read-only; move writes and side effects to commands/actions.",
|
|
67
|
+
suggestedCommands: ["forge inspect queries --json", "forge repair diagnose --diagnostic " + code + " --json"],
|
|
68
|
+
docs: ["src/forge/_generated/runtimeRules.md"],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (code.startsWith("FORGE_RLS_")) {
|
|
72
|
+
return {
|
|
73
|
+
fixHint: "Inspect generated RLS SQL and validate tenant isolation before applying migrations.",
|
|
74
|
+
suggestedCommands: ["forge rls check --json", "forge rls print --json"],
|
|
75
|
+
docs: ["src/forge/_generated/agentContract.json"],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (code.startsWith("FORGE_UI_")) {
|
|
79
|
+
return {
|
|
80
|
+
fixHint: "Inspect the last UI run and use the UI report as repair input.",
|
|
81
|
+
suggestedCommands: ["forge ui report last --json", "forge repair diagnose --from-last-ui-run --json"],
|
|
82
|
+
docs: ["src/forge/_generated/uiTestManifest.json"],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (code === "FORGE_VERIFY_SCRIPT_TIMEOUT") {
|
|
86
|
+
return {
|
|
87
|
+
fixHint: "Run the timed-out script directly, or use impact-based verification to narrow the check before retrying the full gate.",
|
|
88
|
+
suggestedCommands: ["forge test plan --changed --json", "forge verify --changed", "forge dev --once --json"],
|
|
89
|
+
docs: ["AGENTS.md"],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (code === "FORGE_TEST_RUN_TIMEOUT") {
|
|
93
|
+
return {
|
|
94
|
+
fixHint: "Run the timed-out command directly, or increase the impact test timeout only after checking why it is slow.",
|
|
95
|
+
suggestedCommands: ["forge test plan --changed --json", "forge test run --changed --timeout-ms 120000 --json"],
|
|
96
|
+
docs: ["AGENTS.md", ".forge/test-runs/last.json"],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (code === "FORGE_TEST_COMMAND_RESOLUTION_FAILED") {
|
|
100
|
+
return {
|
|
101
|
+
fixHint: "Fix the local command resolution before retrying. On Windows, install Bun at ~/.bun/bin/bun.exe or set FORGE_BUN to an existing bun.exe.",
|
|
102
|
+
suggestedCommands: ["forge dev --once --json", "forge test plan --changed --json"],
|
|
103
|
+
docs: ["AGENTS.md"],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (code.startsWith("FORGE_FRONTEND_")) {
|
|
107
|
+
return {
|
|
108
|
+
fixHint: "Use the generated frontend bridge and inspect src/forge/_generated/frontendGraph.json before editing UI wiring.",
|
|
109
|
+
suggestedCommands: ["forge inspect frontend --json", "forge make ui --framework vite --dry-run --json", "forge generate"],
|
|
110
|
+
docs: ["src/forge/_generated/frontendGraph.json", "AGENTS.md"],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (code.startsWith("FORGE_REFACTOR_")) {
|
|
114
|
+
return {
|
|
115
|
+
fixHint: "Review the refactor plan, lower the scope if diagnostics are unsafe, and re-run in dry-run mode before applying.",
|
|
116
|
+
suggestedCommands: ["forge refactor <operation> --dry-run --json", "forge impact --changed --json"],
|
|
117
|
+
docs: ["AGENTS.md"],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (code.startsWith("FORGE_REPAIR_")) {
|
|
121
|
+
return {
|
|
122
|
+
fixHint: "Open the repair plan and apply only high-confidence repairs.",
|
|
123
|
+
suggestedCommands: ["forge repair plan --json", "forge repair apply <repairId> --dry-run --json"],
|
|
124
|
+
docs: ["AGENTS.md"],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function createDiagnostic(input: DiagnosticInput): Diagnostic {
|
|
131
|
+
const guidance = defaultGuidanceForCode(input.code);
|
|
132
|
+
return {
|
|
133
|
+
severity: input.severity,
|
|
134
|
+
code: input.code,
|
|
135
|
+
message: input.message,
|
|
136
|
+
...(input.file !== undefined ? { file: input.file } : {}),
|
|
137
|
+
...(input.span !== undefined ? { span: input.span } : {}),
|
|
138
|
+
...(input.fixHint ?? guidance?.fixHint ? { fixHint: input.fixHint ?? guidance?.fixHint } : {}),
|
|
139
|
+
...(input.suggestedCommands ?? guidance?.suggestedCommands
|
|
140
|
+
? { suggestedCommands: input.suggestedCommands ?? guidance?.suggestedCommands }
|
|
141
|
+
: {}),
|
|
142
|
+
...(input.docs ?? guidance?.docs ? { docs: input.docs ?? guidance?.docs } : {}),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function forgeDupSymbol(
|
|
147
|
+
qualifiedName: string,
|
|
148
|
+
file: string,
|
|
149
|
+
): Diagnostic {
|
|
150
|
+
return createDiagnostic({
|
|
151
|
+
severity: "warning",
|
|
152
|
+
code: "FORGE_DUP_SYMBOL",
|
|
153
|
+
message: `duplicate symbol id for '${qualifiedName}'`,
|
|
154
|
+
file,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function forgeDrift(file: string): Diagnostic {
|
|
159
|
+
return createDiagnostic({
|
|
160
|
+
severity: "warning",
|
|
161
|
+
code: "FORGE_DRIFT",
|
|
162
|
+
message: `generated file drift detected: ${file}`,
|
|
163
|
+
file,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function forgePkgNoTypes(
|
|
168
|
+
packageName: string,
|
|
169
|
+
subpath: string,
|
|
170
|
+
): Diagnostic {
|
|
171
|
+
return createDiagnostic({
|
|
172
|
+
severity: "warning",
|
|
173
|
+
code: "FORGE_PKG_NO_TYPES",
|
|
174
|
+
message: `no types found for '${packageName}' subpath '${subpath}'`,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function forgeGuardViolation(
|
|
179
|
+
packageName: string,
|
|
180
|
+
context: string,
|
|
181
|
+
rationale: string,
|
|
182
|
+
file: string,
|
|
183
|
+
span: { start: number; end: number },
|
|
184
|
+
): Diagnostic {
|
|
185
|
+
return createDiagnostic({
|
|
186
|
+
severity: "error",
|
|
187
|
+
code: "FORGE_GUARD_VIOLATION",
|
|
188
|
+
message: `'${packageName}' is not allowed in '${context}' context: ${rationale}`,
|
|
189
|
+
file,
|
|
190
|
+
span,
|
|
191
|
+
fixHint:
|
|
192
|
+
context === "command" || context === "query" || context === "liveQuery"
|
|
193
|
+
? `Move '${packageName}' usage out of the ${context} path into an action/workflow, then emit an event from the ${context}.`
|
|
194
|
+
: `Move '${packageName}' usage to a runtime context that allows it, or add a package recipe exception intentionally.`,
|
|
195
|
+
suggestedCommands:
|
|
196
|
+
context === "command"
|
|
197
|
+
? [`forge refactor extract-action <command> --package ${packageName} --dry-run --json`, "forge repair diagnose --diagnostic FORGE_GUARD_VIOLATION --json"]
|
|
198
|
+
: ["forge inspect runtime-matrix --json", "forge repair diagnose --diagnostic FORGE_GUARD_VIOLATION --json"],
|
|
199
|
+
docs: ["src/forge/_generated/runtimeRules.md", "AGENTS.md"],
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function forgeSandboxLimit(packageName: string): Diagnostic {
|
|
204
|
+
return createDiagnostic({
|
|
205
|
+
severity: "warning",
|
|
206
|
+
code: "FORGE_SANDBOX_LIMIT",
|
|
207
|
+
message: `sandbox limit exceeded while inspecting '${packageName}'; falling back to static analysis`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function forgeSandboxAbnormal(packageName: string, detail?: string): Diagnostic {
|
|
212
|
+
const suffix = detail ? ` (${detail})` : "";
|
|
213
|
+
return createDiagnostic({
|
|
214
|
+
severity: "warning",
|
|
215
|
+
code: "FORGE_SANDBOX_ABNORMAL",
|
|
216
|
+
message: `runtime inspection process exited abnormally for '${packageName}'; falling back to static-only package analysis${suffix}`,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function forgeSecretLeak(): Diagnostic {
|
|
221
|
+
return createDiagnostic({
|
|
222
|
+
severity: "error",
|
|
223
|
+
code: "FORGE_SECRET_LEAK",
|
|
224
|
+
message:
|
|
225
|
+
"secret leak detected in sandbox inspection result; withholding runtime data",
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function forgeOrphanedGeneratedFile(file: string): Diagnostic {
|
|
230
|
+
return createDiagnostic({
|
|
231
|
+
severity: "error",
|
|
232
|
+
code: "FORGE_ORPHANED_GENERATED_FILE",
|
|
233
|
+
message: `orphaned generated file: ${file}`,
|
|
234
|
+
file,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function forgeWriteError(file: string): Diagnostic {
|
|
239
|
+
return createDiagnostic({
|
|
240
|
+
severity: "error",
|
|
241
|
+
code: "FORGE_WRITE_ERROR",
|
|
242
|
+
message: `failed to write generated file: ${file}`,
|
|
243
|
+
file,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export {
|
|
2
|
+
FORGE_DUP_SYMBOL,
|
|
3
|
+
FORGE_DRIFT,
|
|
4
|
+
FORGE_PKG_NO_TYPES,
|
|
5
|
+
FORGE_GUARD_VIOLATION,
|
|
6
|
+
FORGE_SANDBOX_LIMIT,
|
|
7
|
+
FORGE_SECRET_LEAK,
|
|
8
|
+
FORGE_ORPHANED_GENERATED_FILE,
|
|
9
|
+
FORGE_SANDBOX_ABNORMAL,
|
|
10
|
+
FORGE_DUP_RUNTIME_ENTRY,
|
|
11
|
+
FORGE_RUNTIME_UNRESOLVABLE,
|
|
12
|
+
FORGE_RUNTIME_NOT_FOUND,
|
|
13
|
+
FORGE_RUNTIME_GUARD_BLOCKED,
|
|
14
|
+
FORGE_DEV_SERVER_ERROR,
|
|
15
|
+
FORGE_DEV_WATCH_FAILED,
|
|
16
|
+
FORGE_DEV_INVOKE_FAILED,
|
|
17
|
+
FORGE_DB_CONNECT_FAILED,
|
|
18
|
+
FORGE_DB_MIGRATION_FAILED,
|
|
19
|
+
FORGE_DB_UNSUPPORTED_FIELD_TYPE,
|
|
20
|
+
FORGE_DB_INVALID_SQL_PLAN,
|
|
21
|
+
FORGE_DB_TRANSACTION_FAILED,
|
|
22
|
+
FORGE_DB_OUTBOX_WRITE_FAILED,
|
|
23
|
+
FORGE_DB_ADAPTER_UNAVAILABLE,
|
|
24
|
+
FORGE_AI_FORBIDDEN_CONTEXT,
|
|
25
|
+
FORGE_AI_PROVIDER_UNKNOWN,
|
|
26
|
+
FORGE_AI_MODEL_MISSING,
|
|
27
|
+
FORGE_AI_SECRET_MISSING,
|
|
28
|
+
FORGE_AI_DYNAMIC_PROVIDER,
|
|
29
|
+
FORGE_AI_GENERATION_FAILED,
|
|
30
|
+
FORGE_AI_USAGE_UNAVAILABLE,
|
|
31
|
+
FORGE_LIVEQUERY_WRITE_FORBIDDEN,
|
|
32
|
+
FORGE_LIVEQUERY_EMIT_FORBIDDEN,
|
|
33
|
+
FORGE_LIVEQUERY_SECRET_FORBIDDEN,
|
|
34
|
+
FORGE_LIVEQUERY_AI_FORBIDDEN,
|
|
35
|
+
FORGE_LIVEQUERY_INTEGRATION_FORBIDDEN,
|
|
36
|
+
FORGE_LIVEQUERY_POLICY_DENIED,
|
|
37
|
+
FORGE_LIVEQUERY_UNKNOWN,
|
|
38
|
+
FORGE_LIVEQUERY_SUBSCRIPTION_FAILED,
|
|
39
|
+
FORGE_LIVEQUERY_RERUN_FAILED,
|
|
40
|
+
DIAGNOSTIC_CODES,
|
|
41
|
+
} from "./codes.ts";
|
|
42
|
+
export type { DiagnosticCode } from "./codes.ts";
|
|
43
|
+
export {
|
|
44
|
+
createDiagnostic,
|
|
45
|
+
forgeDupSymbol,
|
|
46
|
+
forgeDrift,
|
|
47
|
+
forgePkgNoTypes,
|
|
48
|
+
forgeGuardViolation,
|
|
49
|
+
forgeSandboxLimit,
|
|
50
|
+
forgeSandboxAbnormal,
|
|
51
|
+
forgeSecretLeak,
|
|
52
|
+
forgeOrphanedGeneratedFile,
|
|
53
|
+
forgeWriteError,
|
|
54
|
+
} from "./create.ts";
|
|
55
|
+
export type { DiagnosticInput } from "./create.ts";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ArtifactKind = "json" | "typescript" | "markdown" | "text";
|
|
2
|
+
|
|
3
|
+
export function detectArtifactKind(path: string): ArtifactKind {
|
|
4
|
+
if (path.endsWith(".json")) {
|
|
5
|
+
return "json";
|
|
6
|
+
}
|
|
7
|
+
if (path.endsWith(".ts") || path.endsWith(".tsx")) {
|
|
8
|
+
return "typescript";
|
|
9
|
+
}
|
|
10
|
+
if (path.endsWith(".md")) {
|
|
11
|
+
return "markdown";
|
|
12
|
+
}
|
|
13
|
+
return "text";
|
|
14
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { comparePaths, normalizeNewlines, normalizePath } from "../primitives/index.ts";
|
|
2
|
+
import { BARREL_INDEX_PATH, GENERATED_DIR } from "./constants.ts";
|
|
3
|
+
|
|
4
|
+
function toBarrelExportPath(filePath: string): string {
|
|
5
|
+
const normalized = normalizePath(filePath);
|
|
6
|
+
const generatedPrefix = `${GENERATED_DIR}/`;
|
|
7
|
+
|
|
8
|
+
if (!normalized.startsWith(generatedPrefix)) {
|
|
9
|
+
throw new Error(`barrel export path must live under ${GENERATED_DIR}: ${filePath}`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const relative = normalized.slice(generatedPrefix.length);
|
|
13
|
+
const withoutExtension = relative.replace(/\.tsx?$/, "");
|
|
14
|
+
return `./${withoutExtension}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Build barrel index.ts body (sorted re-exports, no header).
|
|
19
|
+
*/
|
|
20
|
+
export function buildBarrelIndexBody(exportFilePaths: string[]): string {
|
|
21
|
+
const candidates = exportFilePaths
|
|
22
|
+
.map(normalizePath)
|
|
23
|
+
.filter(
|
|
24
|
+
(path) =>
|
|
25
|
+
path.startsWith(`${GENERATED_DIR}/`) &&
|
|
26
|
+
(path.endsWith(".ts") || path.endsWith(".tsx")) &&
|
|
27
|
+
!path.endsWith(".d.ts") &&
|
|
28
|
+
path !== BARREL_INDEX_PATH,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const unique = [...new Set(candidates)];
|
|
32
|
+
unique.sort(comparePaths);
|
|
33
|
+
|
|
34
|
+
const lines = unique.map((path) => {
|
|
35
|
+
const exportPath = toBarrelExportPath(path);
|
|
36
|
+
return `export * from "${exportPath}";`;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (lines.length === 0) {
|
|
40
|
+
return normalizeNewlines("// Forge generated barrel\n");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return normalizeNewlines(lines.join("\n"));
|
|
44
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GENERATOR_VERSION } from "../package-graph/constants.ts";
|
|
2
|
+
|
|
3
|
+
export const FORGE_LOCK_SCHEMA_VERSION = "1.0.0";
|
|
4
|
+
export const GENERATED_DIR = "src/forge/_generated";
|
|
5
|
+
export const FORGE_LOCK_PATH = "forge.lock";
|
|
6
|
+
export const BARREL_INDEX_PATH = `${GENERATED_DIR}/index.ts`;
|
|
7
|
+
export { GENERATOR_VERSION };
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import type { Diagnostic } from "../types/diagnostic.ts";
|
|
3
|
+
import type { EmitFile, EmitMode, EmitPlan } from "../types/emit.ts";
|
|
4
|
+
import { runWithConcurrency } from "../cache/scheduler.ts";
|
|
5
|
+
import { nodeFileSystem } from "../fs/index.ts";
|
|
6
|
+
import type { FileSystem } from "../fs/index.ts";
|
|
7
|
+
import {
|
|
8
|
+
forgeDrift,
|
|
9
|
+
forgeOrphanedGeneratedFile,
|
|
10
|
+
forgeWriteError,
|
|
11
|
+
} from "../diagnostics/create.ts";
|
|
12
|
+
import {
|
|
13
|
+
hashStable,
|
|
14
|
+
normalizePath,
|
|
15
|
+
stableSortByPath,
|
|
16
|
+
stableSortEmitFiles,
|
|
17
|
+
stripDeterministicHeader,
|
|
18
|
+
} from "../primitives/index.ts";
|
|
19
|
+
import { buildBarrelIndexBody } from "./barrel.ts";
|
|
20
|
+
import {
|
|
21
|
+
BARREL_INDEX_PATH,
|
|
22
|
+
FORGE_LOCK_PATH,
|
|
23
|
+
GENERATED_DIR,
|
|
24
|
+
} from "./constants.ts";
|
|
25
|
+
import { serializeForgeLock } from "./lock.ts";
|
|
26
|
+
import { render, renderBody, type RenderContext } from "./render.ts";
|
|
27
|
+
import {
|
|
28
|
+
readTextFileIfExists,
|
|
29
|
+
removeFileIfExists,
|
|
30
|
+
writeFileAtomic,
|
|
31
|
+
} from "./write.ts";
|
|
32
|
+
|
|
33
|
+
export interface EmitOptions {
|
|
34
|
+
workspaceRoot: string;
|
|
35
|
+
mode: EmitMode;
|
|
36
|
+
fs?: FileSystem;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface EmitResult {
|
|
40
|
+
changed: string[];
|
|
41
|
+
unchanged: string[];
|
|
42
|
+
removed: string[];
|
|
43
|
+
wouldChange: string[];
|
|
44
|
+
warnings: Diagnostic[];
|
|
45
|
+
errors: Diagnostic[];
|
|
46
|
+
exitCode: 0 | 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function resolveWorkspacePath(workspaceRoot: string, relativePath: string): string {
|
|
50
|
+
return join(workspaceRoot, normalizePath(relativePath));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function bodiesDiffer(rendered: string, onDisk: string | null): boolean {
|
|
54
|
+
const renderedBody = stripDeterministicHeader(rendered);
|
|
55
|
+
if (onDisk === null) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
const diskBody = stripDeterministicHeader(onDisk);
|
|
59
|
+
return renderedBody !== diskBody;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function buildRenderContext(plan: EmitPlan): RenderContext {
|
|
63
|
+
return {
|
|
64
|
+
generatorVersion: plan.lock.generatorVersion,
|
|
65
|
+
inputHash: plan.lock.inputHash,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function upsertBarrelFile(files: EmitFile[], exportPaths: string[]): EmitFile[] {
|
|
70
|
+
const body = buildBarrelIndexBody(exportPaths);
|
|
71
|
+
const barrel: EmitFile = {
|
|
72
|
+
path: BARREL_INDEX_PATH,
|
|
73
|
+
content: body,
|
|
74
|
+
contentHash: hashStable(body),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const withoutBarrel = files.filter((file) => file.path !== BARREL_INDEX_PATH);
|
|
78
|
+
return stableSortEmitFiles([...withoutBarrel, barrel]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function preparePlannedFiles(plan: EmitPlan): EmitFile[] {
|
|
82
|
+
const exportPaths = plan.files.map((file) => file.path);
|
|
83
|
+
return upsertBarrelFile(plan.files, exportPaths);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function classifyFile(
|
|
87
|
+
file: EmitFile,
|
|
88
|
+
context: RenderContext,
|
|
89
|
+
workspaceRoot: string,
|
|
90
|
+
fs: FileSystem = nodeFileSystem,
|
|
91
|
+
): Promise<"changed" | "unchanged"> {
|
|
92
|
+
const rendered = render(file, context);
|
|
93
|
+
const absolutePath = resolveWorkspacePath(workspaceRoot, file.path);
|
|
94
|
+
const onDisk = await readTextFileIfExists(absolutePath, fs);
|
|
95
|
+
return bodiesDiffer(rendered, onDisk) ? "changed" : "unchanged";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function emit(plan: EmitPlan, options: EmitOptions): Promise<EmitResult> {
|
|
99
|
+
const { workspaceRoot, mode } = options;
|
|
100
|
+
const fs = options.fs ?? nodeFileSystem;
|
|
101
|
+
const context = buildRenderContext(plan);
|
|
102
|
+
const plannedFiles = preparePlannedFiles(plan);
|
|
103
|
+
const sortedOrphans = stableSortByPath([...plan.orphanedFiles]);
|
|
104
|
+
|
|
105
|
+
const changed: string[] = [];
|
|
106
|
+
const unchanged: string[] = [];
|
|
107
|
+
const wouldChange: string[] = [];
|
|
108
|
+
const removed: string[] = [];
|
|
109
|
+
const warnings: Diagnostic[] = [];
|
|
110
|
+
const errors: Diagnostic[] = [];
|
|
111
|
+
|
|
112
|
+
const classifications = await runWithConcurrency(
|
|
113
|
+
plannedFiles,
|
|
114
|
+
8,
|
|
115
|
+
async (file) => {
|
|
116
|
+
const rendered = render(file, context);
|
|
117
|
+
const absolutePath = resolveWorkspacePath(workspaceRoot, file.path);
|
|
118
|
+
const onDisk = await readTextFileIfExists(absolutePath, fs);
|
|
119
|
+
return {
|
|
120
|
+
file,
|
|
121
|
+
rendered,
|
|
122
|
+
differs: bodiesDiffer(rendered, onDisk),
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
for (const { file, rendered, differs } of classifications) {
|
|
128
|
+
if (differs) {
|
|
129
|
+
changed.push(file.path);
|
|
130
|
+
wouldChange.push(file.path);
|
|
131
|
+
|
|
132
|
+
if (mode === "check" || mode === "dry-run") {
|
|
133
|
+
warnings.push(forgeDrift(file.path));
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const absolutePath = resolveWorkspacePath(workspaceRoot, file.path);
|
|
139
|
+
await writeFileAtomic(absolutePath, rendered, fs);
|
|
140
|
+
} catch {
|
|
141
|
+
errors.push(forgeWriteError(file.path));
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
unchanged.push(file.path);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
for (const orphan of sortedOrphans) {
|
|
149
|
+
const normalizedOrphan = normalizePath(orphan);
|
|
150
|
+
if (!normalizedOrphan.startsWith(`${GENERATED_DIR}/`)) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const absoluteOrphan = resolveWorkspacePath(workspaceRoot, normalizedOrphan);
|
|
155
|
+
|
|
156
|
+
if (mode === "check") {
|
|
157
|
+
errors.push(forgeOrphanedGeneratedFile(normalizedOrphan));
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (mode === "dry-run") {
|
|
162
|
+
wouldChange.push(normalizedOrphan);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const removedOrphan = await removeFileIfExists(absoluteOrphan, fs);
|
|
167
|
+
if (removedOrphan) {
|
|
168
|
+
removed.push(normalizedOrphan);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const lockDiffers = await lockWouldChange(plan, workspaceRoot, fs);
|
|
173
|
+
|
|
174
|
+
if (lockDiffers) {
|
|
175
|
+
wouldChange.push(FORGE_LOCK_PATH);
|
|
176
|
+
if (mode === "check" || mode === "dry-run") {
|
|
177
|
+
warnings.push(forgeDrift(FORGE_LOCK_PATH));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (mode === "write" && errors.length === 0) {
|
|
182
|
+
const lockContent = serializeForgeLock(plan.lock);
|
|
183
|
+
const lockAbsolutePath = resolveWorkspacePath(workspaceRoot, FORGE_LOCK_PATH);
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
if (lockDiffers) {
|
|
187
|
+
await writeFileAtomic(lockAbsolutePath, lockContent, fs);
|
|
188
|
+
changed.push(FORGE_LOCK_PATH);
|
|
189
|
+
} else {
|
|
190
|
+
unchanged.push(FORGE_LOCK_PATH);
|
|
191
|
+
}
|
|
192
|
+
} catch {
|
|
193
|
+
errors.push(forgeWriteError(FORGE_LOCK_PATH));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const driftFailure =
|
|
198
|
+
mode === "check" &&
|
|
199
|
+
(changed.length > 0 || sortedOrphans.length > 0 || lockDiffers);
|
|
200
|
+
const exitCode: 0 | 1 =
|
|
201
|
+
errors.length > 0 || driftFailure ? 1 : 0;
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
changed,
|
|
205
|
+
unchanged,
|
|
206
|
+
removed,
|
|
207
|
+
wouldChange,
|
|
208
|
+
warnings,
|
|
209
|
+
errors,
|
|
210
|
+
exitCode,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function lockWouldChange(
|
|
215
|
+
plan: EmitPlan,
|
|
216
|
+
workspaceRoot: string,
|
|
217
|
+
fs: FileSystem = nodeFileSystem,
|
|
218
|
+
): Promise<boolean> {
|
|
219
|
+
const lockContent = serializeForgeLock(plan.lock);
|
|
220
|
+
const lockAbsolutePath = resolveWorkspacePath(workspaceRoot, FORGE_LOCK_PATH);
|
|
221
|
+
const onDisk = await readTextFileIfExists(lockAbsolutePath, fs);
|
|
222
|
+
return onDisk !== lockContent;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Exposed for tests: classify a single file without writing.
|
|
227
|
+
*/
|
|
228
|
+
export async function classifyPlannedFile(
|
|
229
|
+
file: EmitFile,
|
|
230
|
+
context: RenderContext,
|
|
231
|
+
workspaceRoot: string,
|
|
232
|
+
fs: FileSystem = nodeFileSystem,
|
|
233
|
+
): Promise<"changed" | "unchanged"> {
|
|
234
|
+
return classifyFile(file, context, workspaceRoot, fs);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export { render, renderBody, serializeForgeLock, buildBarrelIndexBody };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export {
|
|
2
|
+
FORGE_LOCK_SCHEMA_VERSION,
|
|
3
|
+
GENERATED_DIR,
|
|
4
|
+
FORGE_LOCK_PATH,
|
|
5
|
+
BARREL_INDEX_PATH,
|
|
6
|
+
GENERATOR_VERSION,
|
|
7
|
+
} from "./constants.ts";
|
|
8
|
+
export { detectArtifactKind } from "./artifact-kind.ts";
|
|
9
|
+
export type { ArtifactKind } from "./artifact-kind.ts";
|
|
10
|
+
export { render, renderBody } from "./render.ts";
|
|
11
|
+
export type { RenderContext } from "./render.ts";
|
|
12
|
+
export { serializeForgeLock } from "./lock.ts";
|
|
13
|
+
export { buildBarrelIndexBody } from "./barrel.ts";
|
|
14
|
+
export {
|
|
15
|
+
readTextFileIfExists,
|
|
16
|
+
writeFileAtomic,
|
|
17
|
+
removeFileIfExists,
|
|
18
|
+
} from "./write.ts";
|
|
19
|
+
export {
|
|
20
|
+
emit,
|
|
21
|
+
classifyPlannedFile,
|
|
22
|
+
type EmitOptions,
|
|
23
|
+
type EmitResult,
|
|
24
|
+
} from "./emit.ts";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ForgeLock, ForgeLockEntry } from "../types/lock.ts";
|
|
2
|
+
import type { SecretRequirement } from "../types/capability.ts";
|
|
3
|
+
import {
|
|
4
|
+
compareBytes,
|
|
5
|
+
serializeCanonical,
|
|
6
|
+
stableSortByPath,
|
|
7
|
+
stableSortStrings,
|
|
8
|
+
} from "../primitives/index.ts";
|
|
9
|
+
|
|
10
|
+
function compareLockEntries(a: ForgeLockEntry, b: ForgeLockEntry): number {
|
|
11
|
+
return compareBytes(a.name, b.name);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function compareSecrets(a: SecretRequirement, b: SecretRequirement): number {
|
|
15
|
+
return compareBytes(a.envVar, b.envVar);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function stableSortLockEntries(entries: ForgeLockEntry[]): ForgeLockEntry[] {
|
|
19
|
+
return [...entries].sort(compareLockEntries);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function stableSortSecrets(secrets: SecretRequirement[]): SecretRequirement[] {
|
|
23
|
+
return [...secrets].sort(compareSecrets);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function canonicalizeLockEntry(entry: ForgeLockEntry): ForgeLockEntry {
|
|
27
|
+
return {
|
|
28
|
+
name: entry.name,
|
|
29
|
+
version: entry.version,
|
|
30
|
+
...(entry.recipeVersion !== undefined
|
|
31
|
+
? { recipeVersion: entry.recipeVersion }
|
|
32
|
+
: {}),
|
|
33
|
+
runtimeContexts: stableSortStrings([...entry.runtimeContexts]) as ForgeLockEntry["runtimeContexts"],
|
|
34
|
+
capabilities: {
|
|
35
|
+
...entry.capabilities,
|
|
36
|
+
secrets: stableSortSecrets([...entry.capabilities.secrets]),
|
|
37
|
+
},
|
|
38
|
+
secrets: stableSortSecrets([...entry.secrets]),
|
|
39
|
+
generatedFiles: stableSortByPath([...entry.generatedFiles]),
|
|
40
|
+
contentChecksum: entry.contentChecksum,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Deterministic forge.lock serialization (no deterministic header).
|
|
46
|
+
*/
|
|
47
|
+
export function serializeForgeLock(lock: ForgeLock): string {
|
|
48
|
+
const canonical: ForgeLock = {
|
|
49
|
+
schemaVersion: lock.schemaVersion,
|
|
50
|
+
generatorVersion: lock.generatorVersion,
|
|
51
|
+
analyzerVersion: lock.analyzerVersion,
|
|
52
|
+
inputHash: lock.inputHash,
|
|
53
|
+
lockfileHash: lock.lockfileHash,
|
|
54
|
+
packageManager: lock.packageManager,
|
|
55
|
+
...(lock.recipeVersion !== undefined
|
|
56
|
+
? { recipeVersion: lock.recipeVersion }
|
|
57
|
+
: {}),
|
|
58
|
+
packages: stableSortLockEntries(lock.packages).map(canonicalizeLockEntry),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return serializeCanonical(canonical);
|
|
62
|
+
}
|