@empire-builder-kit/nx 1.0.0-beta.9 → 1.0.0-rc.2
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/NOTICE +6 -0
- package/README.md +113 -3
- package/executors.json +30 -0
- package/package.json +84 -6
- package/src/api-contract/baseline-update.d.ts +82 -0
- package/src/api-contract/baseline-update.js +225 -0
- package/src/api-contract/baseline-update.js.map +1 -0
- package/src/api-contract/compatibility.d.ts +30 -0
- package/src/api-contract/compatibility.js +643 -0
- package/src/api-contract/compatibility.js.map +1 -0
- package/src/api-contract/contract-graph.d.ts +35 -0
- package/src/api-contract/contract-graph.js +141 -0
- package/src/api-contract/contract-graph.js.map +1 -0
- package/src/api-contract/evidence.d.ts +23 -0
- package/src/api-contract/evidence.js +87 -0
- package/src/api-contract/evidence.js.map +1 -0
- package/src/api-contract/index.d.ts +6 -0
- package/src/api-contract/index.js +10 -0
- package/src/api-contract/index.js.map +1 -0
- package/src/api-contract/model.d.ts +144 -0
- package/src/api-contract/model.fixtures.d.ts +2 -0
- package/src/api-contract/model.fixtures.js +81 -0
- package/src/api-contract/model.fixtures.js.map +1 -0
- package/src/api-contract/model.js +993 -0
- package/src/api-contract/model.js.map +1 -0
- package/src/api-contract/rollout.d.ts +32 -0
- package/src/api-contract/rollout.js +88 -0
- package/src/api-contract/rollout.js.map +1 -0
- package/src/authorization/compatibility.d.ts +62 -0
- package/src/authorization/compatibility.js +175 -0
- package/src/authorization/compatibility.js.map +1 -0
- package/src/authorization/index.d.ts +1 -0
- package/src/authorization/index.js +5 -0
- package/src/authorization/index.js.map +1 -0
- package/src/blueprints/execution.d.ts +25 -1
- package/src/blueprints/execution.js +246 -83
- package/src/blueprints/execution.js.map +1 -1
- package/src/blueprints/external-sandbox.d.ts +53 -0
- package/src/blueprints/external-sandbox.js +1182 -0
- package/src/blueprints/external-sandbox.js.map +1 -0
- package/src/blueprints/manifest.d.ts +42 -2
- package/src/blueprints/manifest.js +82 -27
- package/src/blueprints/manifest.js.map +1 -1
- package/src/blueprints/resolver.d.ts +14 -5
- package/src/blueprints/resolver.js +228 -68
- package/src/blueprints/resolver.js.map +1 -1
- package/src/cli/agent-command.d.ts +30 -0
- package/src/cli/agent-command.js +204 -0
- package/src/cli/agent-command.js.map +1 -0
- package/src/cli/agent-runtime.d.ts +25 -0
- package/src/cli/agent-runtime.js +488 -0
- package/src/cli/agent-runtime.js.map +1 -0
- package/src/cli/blueprint-authority.d.ts +9 -0
- package/src/cli/blueprint-authority.js +43 -0
- package/src/cli/blueprint-authority.js.map +1 -0
- package/src/cli/blueprint-command.d.ts +24 -0
- package/src/cli/blueprint-command.js +63 -0
- package/src/cli/blueprint-command.js.map +1 -0
- package/src/cli/bootstrap.d.ts +31 -0
- package/src/cli/bootstrap.js +165 -0
- package/src/cli/bootstrap.js.map +1 -0
- package/src/cli/dev-command.d.ts +92 -0
- package/src/cli/dev-command.js +561 -0
- package/src/cli/dev-command.js.map +1 -0
- package/src/cli/main.d.ts +131 -0
- package/src/cli/main.js +1199 -0
- package/src/cli/main.js.map +1 -0
- package/src/cli/output.d.ts +19 -0
- package/src/cli/output.js +51 -0
- package/src/cli/output.js.map +1 -0
- package/src/cli/personal-secret-runtime.d.ts +81 -0
- package/src/cli/personal-secret-runtime.js +567 -0
- package/src/cli/personal-secret-runtime.js.map +1 -0
- package/src/cli/secret-terminal.d.ts +12 -0
- package/src/cli/secret-terminal.js +128 -0
- package/src/cli/secret-terminal.js.map +1 -0
- package/src/container-images.d.ts +1 -0
- package/src/container-images.js +5 -0
- package/src/container-images.js.map +1 -0
- package/src/data-lifecycle/index.d.ts +3 -0
- package/src/data-lifecycle/index.js +7 -0
- package/src/data-lifecycle/index.js.map +1 -0
- package/src/data-lifecycle/model.d.ts +172 -0
- package/src/data-lifecycle/model.fixtures.d.ts +2 -0
- package/src/data-lifecycle/model.fixtures.js +244 -0
- package/src/data-lifecycle/model.fixtures.js.map +1 -0
- package/src/data-lifecycle/model.js +95 -0
- package/src/data-lifecycle/model.js.map +1 -0
- package/src/data-lifecycle/sensitive-artifacts.d.ts +28 -0
- package/src/data-lifecycle/sensitive-artifacts.js +146 -0
- package/src/data-lifecycle/sensitive-artifacts.js.map +1 -0
- package/src/data-lifecycle/validation.d.ts +32 -0
- package/src/data-lifecycle/validation.js +837 -0
- package/src/data-lifecycle/validation.js.map +1 -0
- package/src/database-retirement/contract.d.ts +68 -0
- package/src/database-retirement/contract.js +166 -0
- package/src/database-retirement/contract.js.map +1 -0
- package/src/database-retirement/index.d.ts +1 -0
- package/src/database-retirement/index.js +5 -0
- package/src/database-retirement/index.js.map +1 -0
- package/src/deterministic-order.d.ts +2 -0
- package/src/deterministic-order.js +7 -0
- package/src/deterministic-order.js.map +1 -0
- package/src/developer-agent/context.d.ts +27 -0
- package/src/developer-agent/context.js +497 -0
- package/src/developer-agent/context.js.map +1 -0
- package/src/developer-agent/generator-planning.d.ts +34 -0
- package/src/developer-agent/generator-planning.js +645 -0
- package/src/developer-agent/generator-planning.js.map +1 -0
- package/src/developer-agent/generator-preview.d.ts +8 -0
- package/src/developer-agent/generator-preview.js +650 -0
- package/src/developer-agent/generator-preview.js.map +1 -0
- package/src/developer-agent/git-inspection.d.ts +108 -0
- package/src/developer-agent/git-inspection.js +815 -0
- package/src/developer-agent/git-inspection.js.map +1 -0
- package/src/developer-agent/handoff.d.ts +43 -0
- package/src/developer-agent/handoff.js +698 -0
- package/src/developer-agent/handoff.js.map +1 -0
- package/src/developer-agent/index.d.ts +10 -0
- package/src/developer-agent/index.js +14 -0
- package/src/developer-agent/index.js.map +1 -0
- package/src/developer-agent/model.d.ts +481 -0
- package/src/developer-agent/model.js +143 -0
- package/src/developer-agent/model.js.map +1 -0
- package/src/developer-agent/operation-registry.d.ts +45 -0
- package/src/developer-agent/operation-registry.js +1255 -0
- package/src/developer-agent/operation-registry.js.map +1 -0
- package/src/developer-agent/ordering.d.ts +9 -0
- package/src/developer-agent/ordering.js +15 -0
- package/src/developer-agent/ordering.js.map +1 -0
- package/src/developer-agent/planning.d.ts +18 -0
- package/src/developer-agent/planning.js +447 -0
- package/src/developer-agent/planning.js.map +1 -0
- package/src/developer-agent/preview-changes.d.ts +26 -0
- package/src/developer-agent/preview-changes.js +203 -0
- package/src/developer-agent/preview-changes.js.map +1 -0
- package/src/developer-agent/preview-source.d.ts +2 -0
- package/src/developer-agent/preview-source.js +16 -0
- package/src/developer-agent/preview-source.js.map +1 -0
- package/src/developer-agent/validation.d.ts +18 -0
- package/src/developer-agent/validation.js +2617 -0
- package/src/developer-agent/validation.js.map +1 -0
- package/src/developer-agent/workspace-inspection.d.ts +20 -0
- package/src/developer-agent/workspace-inspection.js +1134 -0
- package/src/developer-agent/workspace-inspection.js.map +1 -0
- package/src/developer-agent/workspace-path.d.ts +6 -0
- package/src/developer-agent/workspace-path.js +22 -0
- package/src/developer-agent/workspace-path.js.map +1 -0
- package/src/executors/blueprint-trust/blueprint-trust.d.ts +29 -0
- package/src/executors/blueprint-trust/blueprint-trust.js +115 -0
- package/src/executors/blueprint-trust/blueprint-trust.js.map +1 -0
- package/src/executors/blueprint-trust/schema.json +27 -0
- package/src/executors/blueprint-verification/blueprint-verification.d.ts +13 -0
- package/src/executors/blueprint-verification/blueprint-verification.js +110 -0
- package/src/executors/blueprint-verification/blueprint-verification.js.map +1 -0
- package/src/executors/blueprint-verification/schema.json +44 -0
- package/src/executors/deployment-plan/deployment-plan.js +1 -0
- package/src/executors/deployment-plan/deployment-plan.js.map +1 -1
- package/src/executors/dev-doctor/dev-doctor.d.ts +19 -5
- package/src/executors/dev-doctor/dev-doctor.js +186 -32
- package/src/executors/dev-doctor/dev-doctor.js.map +1 -1
- package/src/executors/dev-doctor/schema.json +1 -6
- package/src/executors/dev-setup/dev-setup.d.ts +7 -1
- package/src/executors/dev-setup/dev-setup.js +14 -3
- package/src/executors/dev-setup/dev-setup.js.map +1 -1
- package/src/executors/developer-context/developer-context.d.ts +38 -0
- package/src/executors/developer-context/developer-context.js +78 -0
- package/src/executors/developer-context/developer-context.js.map +1 -0
- package/src/executors/developer-context/schema.json +87 -0
- package/src/executors/fleet/fleet.d.ts +12 -43
- package/src/executors/fleet/fleet.js +120 -500
- package/src/executors/fleet/fleet.js.map +1 -1
- package/src/executors/fleet/schema.json +64 -14
- package/src/executors/github-bootstrap/github-bootstrap.d.ts +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js.map +1 -1
- package/src/executors/github-bootstrap/schema.json +5 -0
- package/src/executors/infrastructure-plan/infrastructure-plan.d.ts +144 -0
- package/src/executors/infrastructure-plan/infrastructure-plan.js +3320 -0
- package/src/executors/infrastructure-plan/infrastructure-plan.js.map +1 -0
- package/src/executors/infrastructure-plan/schema.json +78 -0
- package/src/executors/secret-guardrails/schema.json +6 -0
- package/src/executors/secret-guardrails/secret-guardrails.d.ts +3 -0
- package/src/executors/secret-guardrails/secret-guardrails.js +44 -0
- package/src/executors/secret-guardrails/secret-guardrails.js.map +1 -0
- package/src/executors/secret-metadata/schema.json +31 -0
- package/src/executors/secret-metadata/secret-metadata.d.ts +32 -0
- package/src/executors/secret-metadata/secret-metadata.js +131 -0
- package/src/executors/secret-metadata/secret-metadata.js.map +1 -0
- package/src/executors/sst-lifecycle/logging-preflight.d.ts +17 -0
- package/src/executors/sst-lifecycle/logging-preflight.js +196 -0
- package/src/executors/sst-lifecycle/logging-preflight.js.map +1 -0
- package/src/executors/sst-lifecycle/run-sst-command.d.ts +23 -3
- package/src/executors/sst-lifecycle/run-sst-command.js +113 -10
- package/src/executors/sst-lifecycle/run-sst-command.js.map +1 -1
- package/src/executors/sst-lifecycle/schema.json +9 -5
- package/src/executors/sst-lifecycle/secret-preflight.d.ts +25 -0
- package/src/executors/sst-lifecycle/secret-preflight.js +119 -0
- package/src/executors/sst-lifecycle/secret-preflight.js.map +1 -0
- package/src/foundation/discovery.d.ts +17 -1
- package/src/foundation/discovery.js +16 -1
- package/src/foundation/discovery.js.map +1 -1
- package/src/foundation/index.d.ts +3 -0
- package/src/foundation/index.js +3 -0
- package/src/foundation/index.js.map +1 -1
- package/src/foundation/local-database-contract.d.ts +1 -0
- package/src/foundation/local-database-contract.js +3 -0
- package/src/foundation/local-database-contract.js.map +1 -1
- package/src/foundation/logging-preflight.d.ts +30 -0
- package/src/foundation/logging-preflight.js +138 -0
- package/src/foundation/logging-preflight.js.map +1 -0
- package/src/foundation/logging.d.ts +70 -0
- package/src/foundation/logging.js +133 -0
- package/src/foundation/logging.js.map +1 -0
- package/src/foundation/preflight.d.ts +9 -0
- package/src/foundation/preflight.js +58 -2
- package/src/foundation/preflight.js.map +1 -1
- package/src/foundation/provision-database-bindings.d.ts +9 -1
- package/src/foundation/provision-database-bindings.js +25 -5
- package/src/foundation/provision-database-bindings.js.map +1 -1
- package/src/foundation/provision-logical-database.d.ts +10 -2
- package/src/foundation/provision-logical-database.js +68 -113
- package/src/foundation/provision-logical-database.js.map +1 -1
- package/src/foundation/router-origin-proof.d.ts +2 -0
- package/src/foundation/router-origin-proof.js +25 -0
- package/src/foundation/router-origin-proof.js.map +1 -0
- package/src/foundation/stages.d.ts +1 -0
- package/src/foundation/stages.js +9 -1
- package/src/foundation/stages.js.map +1 -1
- package/src/frontend-security/index.d.ts +1 -0
- package/src/frontend-security/index.js +5 -0
- package/src/frontend-security/index.js.map +1 -0
- package/src/frontend-security/security-headers.d.ts +50 -0
- package/src/frontend-security/security-headers.js +418 -0
- package/src/frontend-security/security-headers.js.map +1 -0
- package/src/generators/feature-registry.d.ts +13 -0
- package/src/generators/feature-registry.js +73 -0
- package/src/generators/feature-registry.js.map +1 -0
- package/src/generators/function/function.d.ts +1 -1
- package/src/generators/function/function.js +51 -6
- package/src/generators/function/function.js.map +1 -1
- package/src/generators/function/schema.d.ts +1 -0
- package/src/generators/function/schema.json +6 -1
- package/src/generators/logging-registry.d.ts +13 -0
- package/src/generators/logging-registry.js +62 -0
- package/src/generators/logging-registry.js.map +1 -0
- package/src/generators/post-generation-install.d.ts +67 -0
- package/src/generators/post-generation-install.js +3308 -0
- package/src/generators/post-generation-install.js.map +1 -0
- package/src/generators/preset/generator.js +3 -0
- package/src/generators/preset/generator.js.map +1 -1
- package/src/generators/preset/tool-versions.d.ts +18 -0
- package/src/generators/preset/tool-versions.js +22 -0
- package/src/generators/preset/tool-versions.js.map +1 -0
- package/src/generators/preset/workspace-files-developer-agent.d.ts +14 -0
- package/src/generators/preset/workspace-files-developer-agent.js +511 -0
- package/src/generators/preset/workspace-files-developer-agent.js.map +1 -0
- package/src/generators/preset/workspace-files-foundation-workload-roles.d.ts +6 -0
- package/src/generators/preset/workspace-files-foundation-workload-roles.js +406 -0
- package/src/generators/preset/workspace-files-foundation-workload-roles.js.map +1 -0
- package/src/generators/preset/workspace-files-performance-cost.d.ts +66 -0
- package/src/generators/preset/workspace-files-performance-cost.js +866 -0
- package/src/generators/preset/workspace-files-performance-cost.js.map +1 -0
- package/src/generators/preset/workspace-files-performance-load.d.ts +73 -0
- package/src/generators/preset/workspace-files-performance-load.js +801 -0
- package/src/generators/preset/workspace-files-performance-load.js.map +1 -0
- package/src/generators/preset/workspace-files-workload-role-baseline.d.ts +9 -0
- package/src/generators/preset/workspace-files-workload-role-baseline.js +1102 -0
- package/src/generators/preset/workspace-files-workload-role-baseline.js.map +1 -0
- package/src/generators/preset/workspace-files.d.ts +14 -1
- package/src/generators/preset/workspace-files.js +8189 -245
- package/src/generators/preset/workspace-files.js.map +1 -1
- package/src/generators/repository-policy/repository-policy.js +3 -47
- package/src/generators/repository-policy/repository-policy.js.map +1 -1
- package/src/generators/slice/built-in-plan-api-contract-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-api-contract-files.js +2656 -0
- package/src/generators/slice/built-in-plan-api-contract-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-api-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-api-files.js +1186 -0
- package/src/generators/slice/built-in-plan-api-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-async-work-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-async-work-files.js +7903 -0
- package/src/generators/slice/built-in-plan-async-work-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-authorization-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-authorization-files.js +2314 -0
- package/src/generators/slice/built-in-plan-authorization-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +559 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-deletion-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-deletion-files.js +1101 -0
- package/src/generators/slice/built-in-plan-data-deletion-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js +249 -0
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-files.js +1530 -0
- package/src/generators/slice/built-in-plan-data-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-files.js +750 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js +828 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-retention-job-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-retention-job-files.js +2604 -0
- package/src/generators/slice/built-in-plan-data-retention-job-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js +144 -0
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-rights-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-rights-files.js +4628 -0
- package/src/generators/slice/built-in-plan-data-rights-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-database-lifecycle-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js +1901 -0
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js +485 -0
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-foundation-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-foundation-files.js +184 -0
- package/src/generators/slice/built-in-plan-foundation-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-frontend-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-frontend-files.js +2233 -0
- package/src/generators/slice/built-in-plan-frontend-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.js +3038 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.js +312 -0
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-metadata-files.d.ts +3 -0
- package/src/generators/slice/built-in-plan-metadata-files.js +219 -0
- package/src/generators/slice/built-in-plan-metadata-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-operations-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-operations-files.js +630 -0
- package/src/generators/slice/built-in-plan-operations-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-performance-files.d.ts +3 -0
- package/src/generators/slice/built-in-plan-performance-files.js +3293 -0
- package/src/generators/slice/built-in-plan-performance-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-project-files.d.ts +3 -0
- package/src/generators/slice/built-in-plan-project-files.js +979 -0
- package/src/generators/slice/built-in-plan-project-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-release-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-release-files.js +6387 -0
- package/src/generators/slice/built-in-plan-release-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-reliability-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-reliability-files.js +4499 -0
- package/src/generators/slice/built-in-plan-reliability-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-secret-runtime-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-secret-runtime-files.js +1004 -0
- package/src/generators/slice/built-in-plan-secret-runtime-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-shared.d.ts +53 -0
- package/src/generators/slice/built-in-plan-shared.js +113 -0
- package/src/generators/slice/built-in-plan-shared.js.map +1 -0
- package/src/generators/slice/built-in-plan-testing-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-testing-files.js +2356 -0
- package/src/generators/slice/built-in-plan-testing-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-verification-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-verification-files.js +358 -0
- package/src/generators/slice/built-in-plan-verification-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-web-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-web-files.js +430 -0
- package/src/generators/slice/built-in-plan-web-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-workload-role-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-workload-role-files.js +2356 -0
- package/src/generators/slice/built-in-plan-workload-role-files.js.map +1 -0
- package/src/generators/slice/built-in-plan.d.ts +8 -0
- package/src/generators/slice/built-in-plan.js +264 -0
- package/src/generators/slice/built-in-plan.js.map +1 -0
- package/src/generators/slice/schema.json +1 -1
- package/src/generators/slice/slice.d.ts +1 -22
- package/src/generators/slice/slice.js +185 -1510
- package/src/generators/slice/slice.js.map +1 -1
- package/src/generators/upgrade/schema.d.ts +2 -0
- package/src/generators/upgrade/schema.json +11 -1
- package/src/generators/upgrade/upgrade.d.ts +51 -1
- package/src/generators/upgrade/upgrade.js +820 -82
- package/src/generators/upgrade/upgrade.js.map +1 -1
- package/src/generators/workload/frozen-container.d.ts +8 -0
- package/src/generators/workload/frozen-container.js +36 -0
- package/src/generators/workload/frozen-container.js.map +1 -0
- package/src/generators/workload/performance-registration.d.ts +32 -0
- package/src/generators/workload/performance-registration.js +226 -0
- package/src/generators/workload/performance-registration.js.map +1 -0
- package/src/generators/workload/reliability-registration.d.ts +16 -0
- package/src/generators/workload/reliability-registration.js +150 -0
- package/src/generators/workload/reliability-registration.js.map +1 -0
- package/src/generators/workload/schema.d.ts +1 -0
- package/src/generators/workload/schema.json +6 -1
- package/src/generators/workload/service-performance-files.d.ts +4 -0
- package/src/generators/workload/service-performance-files.js +1846 -0
- package/src/generators/workload/service-performance-files.js.map +1 -0
- package/src/generators/workload/workload.d.ts +3 -2
- package/src/generators/workload/workload.js +1083 -18
- package/src/generators/workload/workload.js.map +1 -1
- package/src/git-policy/action-pins.d.ts +10 -0
- package/src/git-policy/action-pins.js +10 -0
- package/src/git-policy/action-pins.js.map +1 -1
- package/src/git-policy/github-bootstrap.d.ts +14 -1
- package/src/git-policy/github-bootstrap.js +274 -46
- package/src/git-policy/github-bootstrap.js.map +1 -1
- package/src/index.d.ts +2 -0
- package/src/index.js +2 -0
- package/src/index.js.map +1 -1
- package/src/infrastructure-change/convergence.d.ts +13 -0
- package/src/infrastructure-change/convergence.js +85 -0
- package/src/infrastructure-change/convergence.js.map +1 -0
- package/src/infrastructure-change/drift.d.ts +13 -0
- package/src/infrastructure-change/drift.js +112 -0
- package/src/infrastructure-change/drift.js.map +1 -0
- package/src/infrastructure-change/index.d.ts +7 -0
- package/src/infrastructure-change/index.js +11 -0
- package/src/infrastructure-change/index.js.map +1 -0
- package/src/infrastructure-change/model.d.ts +253 -0
- package/src/infrastructure-change/model.js +28 -0
- package/src/infrastructure-change/model.js.map +1 -0
- package/src/infrastructure-change/normalize.d.ts +12 -0
- package/src/infrastructure-change/normalize.js +245 -0
- package/src/infrastructure-change/normalize.js.map +1 -0
- package/src/infrastructure-change/plan.d.ts +40 -0
- package/src/infrastructure-change/plan.js +361 -0
- package/src/infrastructure-change/plan.js.map +1 -0
- package/src/infrastructure-change/risk.d.ts +7 -0
- package/src/infrastructure-change/risk.js +269 -0
- package/src/infrastructure-change/risk.js.map +1 -0
- package/src/infrastructure-change/summary.d.ts +20 -0
- package/src/infrastructure-change/summary.js +130 -0
- package/src/infrastructure-change/summary.js.map +1 -0
- package/src/local-dev/context-discovery.d.ts +2 -0
- package/src/local-dev/context-discovery.js +59 -0
- package/src/local-dev/context-discovery.js.map +1 -0
- package/src/local-dev/contract-validation.d.ts +15 -0
- package/src/local-dev/contract-validation.js +84 -0
- package/src/local-dev/contract-validation.js.map +1 -0
- package/src/local-dev/contracts.d.ts +10 -1
- package/src/local-dev/contracts.js +57 -5
- package/src/local-dev/contracts.js.map +1 -1
- package/src/local-dev/control-contract.d.ts +67 -0
- package/src/local-dev/control-contract.js +180 -0
- package/src/local-dev/control-contract.js.map +1 -0
- package/src/local-dev/dev-command-core.d.ts +60 -0
- package/src/local-dev/dev-command-core.js +89 -0
- package/src/local-dev/dev-command-core.js.map +1 -0
- package/src/local-dev/effects.d.ts +16 -0
- package/src/local-dev/effects.js +63 -0
- package/src/local-dev/effects.js.map +1 -0
- package/src/local-dev/environment-inspector.d.ts +125 -0
- package/src/local-dev/environment-inspector.js +687 -0
- package/src/local-dev/environment-inspector.js.map +1 -0
- package/src/local-dev/environment-state.d.ts +113 -0
- package/src/local-dev/environment-state.js +463 -0
- package/src/local-dev/environment-state.js.map +1 -0
- package/src/local-dev/errors.d.ts +6 -0
- package/src/local-dev/errors.js +41 -0
- package/src/local-dev/errors.js.map +1 -0
- package/src/local-dev/fleet-client.d.ts +33 -0
- package/src/local-dev/fleet-client.js +156 -0
- package/src/local-dev/fleet-client.js.map +1 -0
- package/src/local-dev/fleet-configuration.d.ts +13 -0
- package/src/local-dev/fleet-configuration.js +71 -0
- package/src/local-dev/fleet-configuration.js.map +1 -0
- package/src/local-dev/fleet-inventory.d.ts +56 -0
- package/src/local-dev/fleet-inventory.js +469 -0
- package/src/local-dev/fleet-inventory.js.map +1 -0
- package/src/local-dev/fleet-ipc.d.ts +28 -0
- package/src/local-dev/fleet-ipc.js +267 -0
- package/src/local-dev/fleet-ipc.js.map +1 -0
- package/src/local-dev/fleet-launcher.d.ts +53 -0
- package/src/local-dev/fleet-launcher.js +379 -0
- package/src/local-dev/fleet-launcher.js.map +1 -0
- package/src/local-dev/fleet-lock.d.ts +41 -0
- package/src/local-dev/fleet-lock.js +135 -0
- package/src/local-dev/fleet-lock.js.map +1 -0
- package/src/local-dev/fleet-logs.d.ts +66 -0
- package/src/local-dev/fleet-logs.js +542 -0
- package/src/local-dev/fleet-logs.js.map +1 -0
- package/src/local-dev/fleet-process.d.ts +50 -0
- package/src/local-dev/fleet-process.js +289 -0
- package/src/local-dev/fleet-process.js.map +1 -0
- package/src/local-dev/fleet-runtime.d.ts +22 -0
- package/src/local-dev/fleet-runtime.js +368 -0
- package/src/local-dev/fleet-runtime.js.map +1 -0
- package/src/local-dev/fleet-session.d.ts +70 -0
- package/src/local-dev/fleet-session.js +301 -0
- package/src/local-dev/fleet-session.js.map +1 -0
- package/src/local-dev/fleet-slice-runner-daemon.d.ts +1 -0
- package/src/local-dev/fleet-slice-runner-daemon.js +21 -0
- package/src/local-dev/fleet-slice-runner-daemon.js.map +1 -0
- package/src/local-dev/fleet-startup.d.ts +22 -0
- package/src/local-dev/fleet-startup.js +114 -0
- package/src/local-dev/fleet-startup.js.map +1 -0
- package/src/local-dev/fleet-state.d.ts +62 -0
- package/src/local-dev/fleet-state.js +297 -0
- package/src/local-dev/fleet-state.js.map +1 -0
- package/src/local-dev/fleet-supervisor-daemon.d.ts +1 -0
- package/src/local-dev/fleet-supervisor-daemon.js +41 -0
- package/src/local-dev/fleet-supervisor-daemon.js.map +1 -0
- package/src/local-dev/fleet-supervisor.d.ts +52 -0
- package/src/local-dev/fleet-supervisor.js +384 -0
- package/src/local-dev/fleet-supervisor.js.map +1 -0
- package/src/local-dev/gateway.js +1 -1
- package/src/local-dev/gateway.js.map +1 -1
- package/src/local-dev/identity.js +4 -6
- package/src/local-dev/identity.js.map +1 -1
- package/src/local-dev/index.d.ts +1 -0
- package/src/local-dev/index.js +1 -0
- package/src/local-dev/index.js.map +1 -1
- package/src/local-dev/local-context.d.ts +62 -0
- package/src/local-dev/local-context.js +299 -0
- package/src/local-dev/local-context.js.map +1 -0
- package/src/local-dev/nx-workspace.d.ts +45 -0
- package/src/local-dev/nx-workspace.js +228 -0
- package/src/local-dev/nx-workspace.js.map +1 -0
- package/src/local-dev/personal-secret-ledger.d.ts +75 -0
- package/src/local-dev/personal-secret-ledger.js +391 -0
- package/src/local-dev/personal-secret-ledger.js.map +1 -0
- package/src/local-dev/personal-stage.d.ts +18 -0
- package/src/local-dev/personal-stage.js +129 -0
- package/src/local-dev/personal-stage.js.map +1 -0
- package/src/local-dev/private-state.d.ts +17 -0
- package/src/local-dev/private-state.js +254 -0
- package/src/local-dev/private-state.js.map +1 -0
- package/src/local-dev/process-identity.d.ts +9 -0
- package/src/local-dev/process-identity.js +79 -0
- package/src/local-dev/process-identity.js.map +1 -0
- package/src/local-dev/runtime-paths.d.ts +17 -0
- package/src/local-dev/runtime-paths.js +33 -0
- package/src/local-dev/runtime-paths.js.map +1 -0
- package/src/local-dev/secret-slice-claim.d.ts +17 -0
- package/src/local-dev/secret-slice-claim.js +75 -0
- package/src/local-dev/secret-slice-claim.js.map +1 -0
- package/src/local-dev/slice-claim.d.ts +36 -0
- package/src/local-dev/slice-claim.js +199 -0
- package/src/local-dev/slice-claim.js.map +1 -0
- package/src/local-dev/slice-runner.d.ts +121 -0
- package/src/local-dev/slice-runner.js +715 -0
- package/src/local-dev/slice-runner.js.map +1 -0
- package/src/local-dev/tls.js +51 -17
- package/src/local-dev/tls.js.map +1 -1
- package/src/ownership/composition.d.ts +5 -2
- package/src/ownership/composition.js +26 -3
- package/src/ownership/composition.js.map +1 -1
- package/src/ownership/hash.d.ts +1 -1
- package/src/ownership/hash.js +3 -1
- package/src/ownership/hash.js.map +1 -1
- package/src/ownership/record.d.ts +32 -1
- package/src/ownership/record.js +139 -2
- package/src/ownership/record.js.map +1 -1
- package/src/performance/cost-collection.d.ts +225 -0
- package/src/performance/cost-collection.js +825 -0
- package/src/performance/cost-collection.js.map +1 -0
- package/src/performance/cost-controls.d.ts +131 -0
- package/src/performance/cost-controls.js +336 -0
- package/src/performance/cost-controls.js.map +1 -0
- package/src/performance/evidence.d.ts +140 -0
- package/src/performance/evidence.js +599 -0
- package/src/performance/evidence.js.map +1 -0
- package/src/performance/index.d.ts +10 -0
- package/src/performance/index.js +14 -0
- package/src/performance/index.js.map +1 -0
- package/src/performance/load-safety.d.ts +84 -0
- package/src/performance/load-safety.js +346 -0
- package/src/performance/load-safety.js.map +1 -0
- package/src/performance/model.d.ts +129 -0
- package/src/performance/model.js +452 -0
- package/src/performance/model.js.map +1 -0
- package/src/performance/pr-artifact-budget.d.ts +42 -0
- package/src/performance/pr-artifact-budget.js +151 -0
- package/src/performance/pr-artifact-budget.js.map +1 -0
- package/src/performance/runner.d.ts +75 -0
- package/src/performance/runner.js +227 -0
- package/src/performance/runner.js.map +1 -0
- package/src/performance/scenario-endpoint.d.ts +1 -0
- package/src/performance/scenario-endpoint.js +5 -0
- package/src/performance/scenario-endpoint.js.map +1 -0
- package/src/performance/scenario.d.ts +193 -0
- package/src/performance/scenario.js +736 -0
- package/src/performance/scenario.js.map +1 -0
- package/src/performance/test-fixtures.d.ts +7 -0
- package/src/performance/test-fixtures.js +169 -0
- package/src/performance/test-fixtures.js.map +1 -0
- package/src/performance/unit-cost.d.ts +105 -0
- package/src/performance/unit-cost.js +364 -0
- package/src/performance/unit-cost.js.map +1 -0
- package/src/release/index.d.ts +4 -0
- package/src/release/index.js +8 -0
- package/src/release/index.js.map +1 -0
- package/src/release/lifecycle.d.ts +132 -0
- package/src/release/lifecycle.js +411 -0
- package/src/release/lifecycle.js.map +1 -0
- package/src/release/manifest.d.ts +148 -0
- package/src/release/manifest.js +503 -0
- package/src/release/manifest.js.map +1 -0
- package/src/release/rollout.d.ts +170 -0
- package/src/release/rollout.js +578 -0
- package/src/release/rollout.js.map +1 -0
- package/src/release/source-authority.d.ts +19 -0
- package/src/release/source-authority.js +195 -0
- package/src/release/source-authority.js.map +1 -0
- package/src/repository-policy/deployment-plan.d.ts +2 -1
- package/src/repository-policy/deployment-plan.js +2 -0
- package/src/repository-policy/deployment-plan.js.map +1 -1
- package/src/repository-policy/policy.d.ts +1 -1
- package/src/repository-policy/policy.js +29 -25
- package/src/repository-policy/policy.js.map +1 -1
- package/src/schemas/aggregate-count-evidence-v1.json +135 -0
- package/src/schemas/api-contract-baseline-v1.json +674 -0
- package/src/schemas/api-contract-compatibility-report-v1.json +126 -0
- package/src/schemas/aws-billing-actual-evidence-v1.json +407 -0
- package/src/schemas/blueprint-v1.json +18 -1
- package/src/schemas/data-lifecycle-policy-v1.json +517 -0
- package/src/schemas/generated-ownership-v2.json +22 -0
- package/src/schemas/performance-policy-v1.json +335 -0
- package/src/schemas/repository-policy-v1.json +1 -0
- package/src/schemas/testing-evidence-quarantine-v1.json +168 -0
- package/src/schemas/testing-evidence-result-v1.json +319 -0
- package/src/secrets/adapters.d.ts +49 -0
- package/src/secrets/adapters.js +184 -0
- package/src/secrets/adapters.js.map +1 -0
- package/src/secrets/aws-control-plane.d.ts +20 -0
- package/src/secrets/aws-control-plane.js +255 -0
- package/src/secrets/aws-control-plane.js.map +1 -0
- package/src/secrets/declaration-verification.d.ts +11 -0
- package/src/secrets/declaration-verification.js +68 -0
- package/src/secrets/declaration-verification.js.map +1 -0
- package/src/secrets/guardrails.d.ts +26 -0
- package/src/secrets/guardrails.js +328 -0
- package/src/secrets/guardrails.js.map +1 -0
- package/src/secrets/index.d.ts +12 -0
- package/src/secrets/index.js +16 -0
- package/src/secrets/index.js.map +1 -0
- package/src/secrets/metadata.d.ts +48 -0
- package/src/secrets/metadata.js +171 -0
- package/src/secrets/metadata.js.map +1 -0
- package/src/secrets/model.d.ts +49 -0
- package/src/secrets/model.js +125 -0
- package/src/secrets/model.js.map +1 -0
- package/src/secrets/operator.d.ts +101 -0
- package/src/secrets/operator.js +229 -0
- package/src/secrets/operator.js.map +1 -0
- package/src/secrets/permissions.d.ts +34 -0
- package/src/secrets/permissions.js +86 -0
- package/src/secrets/permissions.js.map +1 -0
- package/src/secrets/personal-command.d.ts +83 -0
- package/src/secrets/personal-command.js +197 -0
- package/src/secrets/personal-command.js.map +1 -0
- package/src/secrets/personal-ledger.d.ts +21 -0
- package/src/secrets/personal-ledger.js +135 -0
- package/src/secrets/personal-ledger.js.map +1 -0
- package/src/secrets/registry.d.ts +9 -0
- package/src/secrets/registry.js +86 -0
- package/src/secrets/registry.js.map +1 -0
- package/src/secrets/verification.d.ts +18 -0
- package/src/secrets/verification.js +139 -0
- package/src/secrets/verification.js.map +1 -0
- package/src/secrets/workload-access.d.ts +46 -0
- package/src/secrets/workload-access.js +163 -0
- package/src/secrets/workload-access.js.map +1 -0
- package/src/supply-chain/action-pins.d.ts +26 -0
- package/src/supply-chain/action-pins.js +208 -0
- package/src/supply-chain/action-pins.js.map +1 -0
- package/src/supply-chain/blueprint-trust-git.d.ts +130 -0
- package/src/supply-chain/blueprint-trust-git.js +1581 -0
- package/src/supply-chain/blueprint-trust-git.js.map +1 -0
- package/src/supply-chain/blueprint-trust-process.d.ts +4 -0
- package/src/supply-chain/blueprint-trust-process.js +88 -0
- package/src/supply-chain/blueprint-trust-process.js.map +1 -0
- package/src/supply-chain/blueprint-trust.d.ts +354 -0
- package/src/supply-chain/blueprint-trust.js +1558 -0
- package/src/supply-chain/blueprint-trust.js.map +1 -0
- package/src/supply-chain/blueprint-verification-authority.d.ts +62 -0
- package/src/supply-chain/blueprint-verification-authority.js +588 -0
- package/src/supply-chain/blueprint-verification-authority.js.map +1 -0
- package/src/supply-chain/blueprint-verification-execution.d.ts +68 -0
- package/src/supply-chain/blueprint-verification-execution.js +624 -0
- package/src/supply-chain/blueprint-verification-execution.js.map +1 -0
- package/src/supply-chain/build-output.d.ts +35 -0
- package/src/supply-chain/build-output.js +398 -0
- package/src/supply-chain/build-output.js.map +1 -0
- package/src/supply-chain/common.d.ts +21 -0
- package/src/supply-chain/common.js +107 -0
- package/src/supply-chain/common.js.map +1 -0
- package/src/supply-chain/container-artifact-contract.d.ts +23 -0
- package/src/supply-chain/container-artifact-contract.js +208 -0
- package/src/supply-chain/container-artifact-contract.js.map +1 -0
- package/src/supply-chain/container-release.d.ts +119 -0
- package/src/supply-chain/container-release.js +496 -0
- package/src/supply-chain/container-release.js.map +1 -0
- package/src/supply-chain/ecr-applicability.d.ts +19 -0
- package/src/supply-chain/ecr-applicability.js +103 -0
- package/src/supply-chain/ecr-applicability.js.map +1 -0
- package/src/supply-chain/ecr-scanning.d.ts +83 -0
- package/src/supply-chain/ecr-scanning.js +321 -0
- package/src/supply-chain/ecr-scanning.js.map +1 -0
- package/src/supply-chain/ecs-deployed-image.d.ts +85 -0
- package/src/supply-chain/ecs-deployed-image.js +300 -0
- package/src/supply-chain/ecs-deployed-image.js.map +1 -0
- package/src/supply-chain/errors.d.ts +6 -0
- package/src/supply-chain/errors.js +15 -0
- package/src/supply-chain/errors.js.map +1 -0
- package/src/supply-chain/generated-blueprint-trust-command.d.ts +4 -0
- package/src/supply-chain/generated-blueprint-trust-command.js +1362 -0
- package/src/supply-chain/generated-blueprint-trust-command.js.map +1 -0
- package/src/supply-chain/generated-command.d.ts +1 -0
- package/src/supply-chain/generated-command.js +687 -0
- package/src/supply-chain/generated-command.js.map +1 -0
- package/src/supply-chain/generated-container-release-command.d.ts +16 -0
- package/src/supply-chain/generated-container-release-command.js +2087 -0
- package/src/supply-chain/generated-container-release-command.js.map +1 -0
- package/src/supply-chain/generated-ecr-collector-command.d.ts +21 -0
- package/src/supply-chain/generated-ecr-collector-command.js +1338 -0
- package/src/supply-chain/generated-ecr-collector-command.js.map +1 -0
- package/src/supply-chain/generated-files.d.ts +13 -0
- package/src/supply-chain/generated-files.js +401 -0
- package/src/supply-chain/generated-files.js.map +1 -0
- package/src/supply-chain/generated-scanner-command.d.ts +1 -0
- package/src/supply-chain/generated-scanner-command.js +718 -0
- package/src/supply-chain/generated-scanner-command.js.map +1 -0
- package/src/supply-chain/index.d.ts +28 -0
- package/src/supply-chain/index.js +35 -0
- package/src/supply-chain/index.js.map +1 -0
- package/src/supply-chain/inventory.d.ts +79 -0
- package/src/supply-chain/inventory.js +717 -0
- package/src/supply-chain/inventory.js.map +1 -0
- package/src/supply-chain/license-expression.d.ts +7 -0
- package/src/supply-chain/license-expression.js +128 -0
- package/src/supply-chain/license-expression.js.map +1 -0
- package/src/supply-chain/pnpm-toolchain-authority.d.ts +31 -0
- package/src/supply-chain/pnpm-toolchain-authority.js +316 -0
- package/src/supply-chain/pnpm-toolchain-authority.js.map +1 -0
- package/src/supply-chain/policy.d.ts +105 -0
- package/src/supply-chain/policy.js +301 -0
- package/src/supply-chain/policy.js.map +1 -0
- package/src/supply-chain/publication.d.ts +48 -0
- package/src/supply-chain/publication.js +85 -0
- package/src/supply-chain/publication.js.map +1 -0
- package/src/supply-chain/sbom.d.ts +228 -0
- package/src/supply-chain/sbom.js +826 -0
- package/src/supply-chain/sbom.js.map +1 -0
- package/src/supply-chain/scanner.d.ts +77 -0
- package/src/supply-chain/scanner.js +502 -0
- package/src/supply-chain/scanner.js.map +1 -0
- package/src/supply-chain/vendored-source.d.ts +95 -0
- package/src/supply-chain/vendored-source.js +315 -0
- package/src/supply-chain/vendored-source.js.map +1 -0
- package/src/testing-evidence/fixture-scope.d.ts +52 -0
- package/src/testing-evidence/fixture-scope.js +140 -0
- package/src/testing-evidence/fixture-scope.js.map +1 -0
- package/src/testing-evidence/index.d.ts +5 -0
- package/src/testing-evidence/index.js +9 -0
- package/src/testing-evidence/index.js.map +1 -0
- package/src/testing-evidence/quarantine.d.ts +48 -0
- package/src/testing-evidence/quarantine.js +253 -0
- package/src/testing-evidence/quarantine.js.map +1 -0
- package/src/testing-evidence/result.d.ts +108 -0
- package/src/testing-evidence/result.js +571 -0
- package/src/testing-evidence/result.js.map +1 -0
- package/src/testing-evidence/runner-adapter.d.ts +51 -0
- package/src/testing-evidence/runner-adapter.js +288 -0
- package/src/testing-evidence/runner-adapter.js.map +1 -0
- package/src/testing-evidence/sensitive-artifacts.d.ts +13 -0
- package/src/testing-evidence/sensitive-artifacts.js +93 -0
- package/src/testing-evidence/sensitive-artifacts.js.map +1 -0
- package/src/work-markers/work-markers.js +4 -3
- package/src/work-markers/work-markers.js.map +1 -1
- package/src/workload-roles/account-baseline.d.ts +132 -0
- package/src/workload-roles/account-baseline.js +743 -0
- package/src/workload-roles/account-baseline.js.map +1 -0
- package/src/workload-roles/authority.d.ts +38 -0
- package/src/workload-roles/authority.js +156 -0
- package/src/workload-roles/authority.js.map +1 -0
- package/src/workload-roles/aws-adapter.d.ts +99 -0
- package/src/workload-roles/aws-adapter.js +416 -0
- package/src/workload-roles/aws-adapter.js.map +1 -0
- package/src/workload-roles/aws-internal-handler.d.ts +27 -0
- package/src/workload-roles/aws-internal-handler.js +58 -0
- package/src/workload-roles/aws-internal-handler.js.map +1 -0
- package/src/workload-roles/aws-s3-state.d.ts +52 -0
- package/src/workload-roles/aws-s3-state.js +164 -0
- package/src/workload-roles/aws-s3-state.js.map +1 -0
- package/src/workload-roles/aws-sdk-control-plane.d.ts +12 -0
- package/src/workload-roles/aws-sdk-control-plane.js +291 -0
- package/src/workload-roles/aws-sdk-control-plane.js.map +1 -0
- package/src/workload-roles/boundary.d.ts +33 -0
- package/src/workload-roles/boundary.js +130 -0
- package/src/workload-roles/boundary.js.map +1 -0
- package/src/workload-roles/convergence.d.ts +66 -0
- package/src/workload-roles/convergence.js +186 -0
- package/src/workload-roles/convergence.js.map +1 -0
- package/src/workload-roles/effective-policy.d.ts +51 -0
- package/src/workload-roles/effective-policy.js +183 -0
- package/src/workload-roles/effective-policy.js.map +1 -0
- package/src/workload-roles/handler.d.ts +43 -0
- package/src/workload-roles/handler.js +130 -0
- package/src/workload-roles/handler.js.map +1 -0
- package/src/workload-roles/history.d.ts +47 -0
- package/src/workload-roles/history.js +324 -0
- package/src/workload-roles/history.js.map +1 -0
- package/src/workload-roles/index.d.ts +17 -0
- package/src/workload-roles/index.js +21 -0
- package/src/workload-roles/index.js.map +1 -0
- package/src/workload-roles/injection.d.ts +119 -0
- package/src/workload-roles/injection.js +495 -0
- package/src/workload-roles/injection.js.map +1 -0
- package/src/workload-roles/manifest.d.ts +54 -0
- package/src/workload-roles/manifest.js +343 -0
- package/src/workload-roles/manifest.js.map +1 -0
- package/src/workload-roles/provisioner.d.ts +70 -0
- package/src/workload-roles/provisioner.js +231 -0
- package/src/workload-roles/provisioner.js.map +1 -0
- package/src/workload-roles/registration.d.ts +101 -0
- package/src/workload-roles/registration.js +457 -0
- package/src/workload-roles/registration.js.map +1 -0
- package/src/workload-roles/stage-boundary.d.ts +31 -0
- package/src/workload-roles/stage-boundary.js +208 -0
- package/src/workload-roles/stage-boundary.js.map +1 -0
- package/src/workload-roles/standard-slice.d.ts +54 -0
- package/src/workload-roles/standard-slice.js +252 -0
- package/src/workload-roles/standard-slice.js.map +1 -0
- package/migrations/standard-pre-v1-to-v1.md +0 -11
- package/src/foundation/aurora-logical-database.d.ts +0 -76
- package/src/foundation/aurora-logical-database.js +0 -419
- package/src/foundation/aurora-logical-database.js.map +0 -1
|
@@ -0,0 +1,2617 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeveloperAgentContractValidationError = void 0;
|
|
4
|
+
exports.validateDeveloperAgentContext = validateDeveloperAgentContext;
|
|
5
|
+
exports.validateDeveloperAgentGeneratorPreview = validateDeveloperAgentGeneratorPreview;
|
|
6
|
+
exports.validateDeveloperAgentGeneratorPreviewReceipt = validateDeveloperAgentGeneratorPreviewReceipt;
|
|
7
|
+
exports.validateDeveloperAgentPlan = validateDeveloperAgentPlan;
|
|
8
|
+
exports.validateDeveloperAgentResult = validateDeveloperAgentResult;
|
|
9
|
+
exports.validateDeveloperAgentHandoff = validateDeveloperAgentHandoff;
|
|
10
|
+
exports.serializeDeveloperAgentContext = serializeDeveloperAgentContext;
|
|
11
|
+
exports.serializeDeveloperAgentGeneratorPreview = serializeDeveloperAgentGeneratorPreview;
|
|
12
|
+
exports.serializeDeveloperAgentGeneratorPreviewReceipt = serializeDeveloperAgentGeneratorPreviewReceipt;
|
|
13
|
+
exports.serializeDeveloperAgentPlan = serializeDeveloperAgentPlan;
|
|
14
|
+
exports.serializeDeveloperAgentResult = serializeDeveloperAgentResult;
|
|
15
|
+
exports.serializeDeveloperAgentHandoff = serializeDeveloperAgentHandoff;
|
|
16
|
+
const node_crypto_1 = require("node:crypto");
|
|
17
|
+
const node_util_1 = require("node:util");
|
|
18
|
+
const canonical_json_1 = require("@empire-builder-kit/runtime/canonical-json");
|
|
19
|
+
const safe_reference_1 = require("@empire-builder-kit/runtime/safe-reference");
|
|
20
|
+
const index_js_1 = require("../testing-evidence/index.js");
|
|
21
|
+
const validation_js_1 = require("../validation.js");
|
|
22
|
+
const model_js_1 = require("./model.js");
|
|
23
|
+
const ordering_js_1 = require("./ordering.js");
|
|
24
|
+
const workspace_path_js_1 = require("./workspace-path.js");
|
|
25
|
+
const MAX_COLLECTION_ITEMS = 256;
|
|
26
|
+
const MAX_AFFECTED_FILE_REFERENCES = 128;
|
|
27
|
+
const MAX_CONCURRENT_PATHS = 2_048;
|
|
28
|
+
const MAX_GENERATED_SURFACES = 512;
|
|
29
|
+
const MAX_RESULTS = 16;
|
|
30
|
+
const MAX_COMMAND_ARGUMENTS = 64;
|
|
31
|
+
const MAX_IDENTIFIER_LENGTH = (0, safe_reference_1.safeReferenceMaximumLength)('supply-chain');
|
|
32
|
+
const MAX_PATH_LENGTH = 1024;
|
|
33
|
+
const MAX_SUMMARY_LENGTH = 1024;
|
|
34
|
+
const MAX_INPUT_VALUE_LENGTH = 512;
|
|
35
|
+
const COMMIT_PATTERN = /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/;
|
|
36
|
+
const SHA256_DIGEST_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
37
|
+
const GENERATOR_PREVIEW_CHANGE_SET = new Set(['create', 'delete', 'update']);
|
|
38
|
+
const IDENTIFIER_PATTERN = new RegExp((0, safe_reference_1.safeReferencePatternSource)('supply-chain'));
|
|
39
|
+
const FIELD_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9._-]*$/;
|
|
40
|
+
const WORKSPACE_RELATIVE_PATH_PATTERN = /^(?![\\/])(?![A-Za-z]:[\\/])(?!.*(?:^|[\\/])\.\.(?:[\\/]|$)).+$/;
|
|
41
|
+
const GENERATOR_PREVIEW_REFERENCE_PATTERN = /^\.ebk\/agent\/previews\/[a-z][a-z0-9-]{0,62}\.json$/;
|
|
42
|
+
const GENERATOR_SLUG_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
43
|
+
const AUTHORITY_SET = new Set(model_js_1.DEVELOPER_AGENT_AUTHORITY_CLASSES);
|
|
44
|
+
const CANONICAL_STAGE_SET = new Set(model_js_1.DEVELOPER_AGENT_CANONICAL_STAGES);
|
|
45
|
+
const FAILURE_SET = new Set(model_js_1.DEVELOPER_AGENT_FAILURE_CLASSIFICATIONS);
|
|
46
|
+
const RESULT_OUTCOME_SET = new Set(model_js_1.DEVELOPER_AGENT_RESULT_OUTCOMES);
|
|
47
|
+
const HANDOFF_STATE_SET = new Set(model_js_1.DEVELOPER_AGENT_HANDOFF_STATES);
|
|
48
|
+
const PRIVACY_CLASS_SET = new Set(model_js_1.DEVELOPER_AGENT_ARTIFACT_PRIVACY_CLASSES);
|
|
49
|
+
const CLEANUP_RECOVERY_SET = new Set(model_js_1.DEVELOPER_AGENT_CLEANUP_RECOVERY_OUTCOMES);
|
|
50
|
+
const OWNERSHIP_MODE_SET = new Set(model_js_1.DEVELOPER_AGENT_OWNERSHIP_MODES);
|
|
51
|
+
const CONTRACT_CLASS_SET = new Set(model_js_1.DEVELOPER_AGENT_CONTRACT_CLASSES);
|
|
52
|
+
const RISK_CLASS_SET = new Set(model_js_1.DEVELOPER_AGENT_RISK_CLASSES);
|
|
53
|
+
const OPERATION_OWNER_SET = new Set(model_js_1.DEVELOPER_AGENT_OPERATION_OWNERS);
|
|
54
|
+
const POLICY_LIFECYCLE_ACTION_SET = new Set(model_js_1.DEVELOPER_AGENT_POLICY_LIFECYCLE_ACTIONS);
|
|
55
|
+
const STABLE_GENERATOR_SET = new Set(model_js_1.DEVELOPER_AGENT_STABLE_GENERATORS);
|
|
56
|
+
const GENERATOR_MODE_SET = new Set(model_js_1.DEVELOPER_AGENT_GENERATOR_MODES);
|
|
57
|
+
const PRODUCTION_PROFILE_SET = new Set(['cost-optimized', 'standard']);
|
|
58
|
+
const BLOCKING_FAILURES = new Set([
|
|
59
|
+
'unsupported-operation',
|
|
60
|
+
'invalid-input',
|
|
61
|
+
'dirty-worktree',
|
|
62
|
+
'stale-base',
|
|
63
|
+
'ownership-conflict',
|
|
64
|
+
'generated-drift',
|
|
65
|
+
'policy-conflict',
|
|
66
|
+
'marker-blocked',
|
|
67
|
+
'authority-required',
|
|
68
|
+
'prerequisite-missing',
|
|
69
|
+
]);
|
|
70
|
+
const FAILED_FAILURES = new Set([
|
|
71
|
+
'verification-failed',
|
|
72
|
+
'cleanup-incomplete',
|
|
73
|
+
'tool-internal-error',
|
|
74
|
+
]);
|
|
75
|
+
class DeveloperAgentContractValidationError extends Error {
|
|
76
|
+
issues;
|
|
77
|
+
constructor(label, issues) {
|
|
78
|
+
super(`${label} is invalid: ${issues
|
|
79
|
+
.slice(0, 3)
|
|
80
|
+
.map(({ message, path }) => `${path} ${message}`)
|
|
81
|
+
.join('; ')}`);
|
|
82
|
+
this.name = 'DeveloperAgentContractValidationError';
|
|
83
|
+
this.issues = issues;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.DeveloperAgentContractValidationError = DeveloperAgentContractValidationError;
|
|
87
|
+
function addIssue(issues, path, message) {
|
|
88
|
+
issues.push({ message, path });
|
|
89
|
+
}
|
|
90
|
+
function has(value, property) {
|
|
91
|
+
return Object.prototype.hasOwnProperty.call(value, property);
|
|
92
|
+
}
|
|
93
|
+
function requireRecord(value, path, required, optional, issues) {
|
|
94
|
+
if (!(0, validation_js_1.isRecord)(value)) {
|
|
95
|
+
addIssue(issues, path, 'must be an object');
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const allowed = new Set([...required, ...optional]);
|
|
99
|
+
for (const property of Object.keys(value)) {
|
|
100
|
+
if (!allowed.has(property)) {
|
|
101
|
+
addIssue(issues, `${path}.*`, 'is not an allowlisted property');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const property of required) {
|
|
105
|
+
if (!has(value, property)) {
|
|
106
|
+
addIssue(issues, `${path}.${property}`, 'is required');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
function requireSafeString(value, path, issues, options = {}) {
|
|
112
|
+
if (typeof value !== 'string' ||
|
|
113
|
+
value.length === 0 ||
|
|
114
|
+
value !== value.trim()) {
|
|
115
|
+
addIssue(issues, path, 'must be a non-empty trimmed string');
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (value.length > (options.maximumLength ?? MAX_IDENTIFIER_LENGTH)) {
|
|
119
|
+
addIssue(issues, path, `must contain at most ${options.maximumLength ?? MAX_IDENTIFIER_LENGTH} characters`);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
for (const character of value) {
|
|
123
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
124
|
+
if (codePoint <= 31 ||
|
|
125
|
+
(codePoint >= 127 && codePoint <= 159) ||
|
|
126
|
+
codePoint === 0x2028 ||
|
|
127
|
+
codePoint === 0x2029) {
|
|
128
|
+
addIssue(issues, path, 'must not contain unsafe control characters');
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (options.pattern && !options.pattern.test(value)) {
|
|
133
|
+
addIssue(issues, path, 'has an unsupported format');
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
const inspection = (0, index_js_1.inspectTestingEvidenceText)(value);
|
|
137
|
+
if (!inspection.safe) {
|
|
138
|
+
addIssue(issues, path, 'must not contain protected data');
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
function requireBoolean(value, path, issues) {
|
|
144
|
+
if (typeof value !== 'boolean') {
|
|
145
|
+
addIssue(issues, path, 'must be a boolean');
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
function requireInteger(value, path, issues, minimum = 0, maximum = Number.MAX_SAFE_INTEGER) {
|
|
151
|
+
if (typeof value !== 'number' ||
|
|
152
|
+
!Number.isSafeInteger(value) ||
|
|
153
|
+
value < minimum ||
|
|
154
|
+
value > maximum) {
|
|
155
|
+
addIssue(issues, path, `must be an integer from ${minimum} through ${maximum}`);
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
function requireEnum(value, path, allowed, issues) {
|
|
161
|
+
if (typeof value !== 'string' || !allowed.has(value)) {
|
|
162
|
+
addIssue(issues, path, `must equal one of ${[...allowed].join(', ')}`);
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
function requireArray(value, path, issues, maximumItems = MAX_COLLECTION_ITEMS) {
|
|
168
|
+
if (!Array.isArray(value)) {
|
|
169
|
+
addIssue(issues, path, 'must be an array');
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
if (value.length > maximumItems) {
|
|
173
|
+
addIssue(issues, path, `must contain at most ${maximumItems} items`);
|
|
174
|
+
}
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
function validateStringArray(value, path, issues, options = {}) {
|
|
178
|
+
const entries = requireArray(value, path, issues, options.maximumItems ?? MAX_COLLECTION_ITEMS);
|
|
179
|
+
if (!entries)
|
|
180
|
+
return false;
|
|
181
|
+
const seen = new Set();
|
|
182
|
+
entries.forEach((entry, index) => {
|
|
183
|
+
if (requireSafeString(entry, `${path}[${index}]`, issues, {
|
|
184
|
+
maximumLength: options.maximumLength,
|
|
185
|
+
pattern: options.pattern,
|
|
186
|
+
}) &&
|
|
187
|
+
options.unique !== false) {
|
|
188
|
+
if (seen.has(entry)) {
|
|
189
|
+
addIssue(issues, `${path}[${index}]`, 'must not duplicate another item');
|
|
190
|
+
}
|
|
191
|
+
seen.add(entry);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
return entries.every((entry) => typeof entry === 'string');
|
|
195
|
+
}
|
|
196
|
+
function validateVersionRecord(value, path, issues) {
|
|
197
|
+
const record = requireRecord(value, path, ['name', 'version'], [], issues);
|
|
198
|
+
if (!record)
|
|
199
|
+
return false;
|
|
200
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
201
|
+
pattern: IDENTIFIER_PATTERN,
|
|
202
|
+
});
|
|
203
|
+
requireSafeString(record.version, `${path}.version`, issues);
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
function validateVersionRecords(value, path, issues) {
|
|
207
|
+
const entries = requireArray(value, path, issues);
|
|
208
|
+
if (!entries)
|
|
209
|
+
return false;
|
|
210
|
+
const names = new Set();
|
|
211
|
+
entries.forEach((entry, index) => {
|
|
212
|
+
if (validateVersionRecord(entry, `${path}[${index}]`, issues)) {
|
|
213
|
+
const name = entry.name;
|
|
214
|
+
if (names.has(name)) {
|
|
215
|
+
addIssue(issues, `${path}[${index}].name`, 'must be unique');
|
|
216
|
+
}
|
|
217
|
+
names.add(name);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
function validateCandidateProvenance(value, path, issues) {
|
|
223
|
+
const record = requireRecord(value, path, ['reference'], ['digest'], issues);
|
|
224
|
+
if (!record)
|
|
225
|
+
return false;
|
|
226
|
+
requireSafeString(record.reference, `${path}.reference`, issues, {
|
|
227
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
228
|
+
});
|
|
229
|
+
if (has(record, 'digest')) {
|
|
230
|
+
requireSafeString(record.digest, `${path}.digest`, issues, {
|
|
231
|
+
maximumLength: 71,
|
|
232
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
function validateCommand(value, path, issues) {
|
|
238
|
+
const record = requireRecord(value, path, ['args', 'executable'], ['cwd'], issues);
|
|
239
|
+
if (!record)
|
|
240
|
+
return false;
|
|
241
|
+
requireSafeString(record.executable, `${path}.executable`, issues, {
|
|
242
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
243
|
+
});
|
|
244
|
+
validateStringArray(record.args, `${path}.args`, issues, {
|
|
245
|
+
maximumItems: MAX_COMMAND_ARGUMENTS,
|
|
246
|
+
maximumLength: MAX_INPUT_VALUE_LENGTH,
|
|
247
|
+
unique: false,
|
|
248
|
+
});
|
|
249
|
+
if (has(record, 'cwd')) {
|
|
250
|
+
requireSafeString(record.cwd, `${path}.cwd`, issues, {
|
|
251
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
function validateNextSafeAction(value, path, issues) {
|
|
257
|
+
const record = requireRecord(value, path, ['approvalRequired', 'authority', 'description'], ['command', 'operationId', 'owner'], issues);
|
|
258
|
+
if (!record)
|
|
259
|
+
return false;
|
|
260
|
+
requireBoolean(record.approvalRequired, `${path}.approvalRequired`, issues);
|
|
261
|
+
requireEnum(record.authority, `${path}.authority`, AUTHORITY_SET, issues);
|
|
262
|
+
requireSafeString(record.description, `${path}.description`, issues, {
|
|
263
|
+
maximumLength: MAX_SUMMARY_LENGTH,
|
|
264
|
+
});
|
|
265
|
+
if (has(record, 'command')) {
|
|
266
|
+
validateCommand(record.command, `${path}.command`, issues);
|
|
267
|
+
}
|
|
268
|
+
if (has(record, 'operationId')) {
|
|
269
|
+
requireSafeString(record.operationId, `${path}.operationId`, issues, {
|
|
270
|
+
maximumLength: MAX_IDENTIFIER_LENGTH,
|
|
271
|
+
pattern: IDENTIFIER_PATTERN,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
if (has(record, 'owner')) {
|
|
275
|
+
requireEnum(record.owner, `${path}.owner`, OPERATION_OWNER_SET, issues);
|
|
276
|
+
}
|
|
277
|
+
if (has(record, 'operationId') !== has(record, 'owner')) {
|
|
278
|
+
addIssue(issues, path, 'operationId and owner must be retained together');
|
|
279
|
+
}
|
|
280
|
+
if ((record.authority === 'protected-mutate' ||
|
|
281
|
+
record.authority === 'destructive') &&
|
|
282
|
+
record.approvalRequired !== true) {
|
|
283
|
+
addIssue(issues, `${path}.approvalRequired`, 'must be true for protected or destructive action');
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
function validateCleanupRecovery(value, path, issues) {
|
|
288
|
+
const record = requireRecord(value, path, ['outcome'], ['owner', 'sanitizedSummary'], issues);
|
|
289
|
+
if (!record)
|
|
290
|
+
return false;
|
|
291
|
+
requireEnum(record.outcome, `${path}.outcome`, CLEANUP_RECOVERY_SET, issues);
|
|
292
|
+
if (has(record, 'owner')) {
|
|
293
|
+
requireSafeString(record.owner, `${path}.owner`, issues);
|
|
294
|
+
}
|
|
295
|
+
if (has(record, 'sanitizedSummary')) {
|
|
296
|
+
requireSafeString(record.sanitizedSummary, `${path}.sanitizedSummary`, issues, { maximumLength: MAX_SUMMARY_LENGTH });
|
|
297
|
+
}
|
|
298
|
+
if (record.outcome === 'incomplete' && !has(record, 'sanitizedSummary')) {
|
|
299
|
+
addIssue(issues, path, 'must include a sanitized summary when incomplete');
|
|
300
|
+
}
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
function validateArtifact(value, path, issues) {
|
|
304
|
+
const record = requireRecord(value, path, ['digest', 'evidenceClass', 'name', 'privacyClass', 'reference'], [], issues);
|
|
305
|
+
if (!record)
|
|
306
|
+
return false;
|
|
307
|
+
requireSafeString(record.digest, `${path}.digest`, issues, {
|
|
308
|
+
maximumLength: 71,
|
|
309
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
310
|
+
});
|
|
311
|
+
requireSafeString(record.evidenceClass, `${path}.evidenceClass`, issues, {
|
|
312
|
+
maximumLength: MAX_IDENTIFIER_LENGTH,
|
|
313
|
+
pattern: IDENTIFIER_PATTERN,
|
|
314
|
+
});
|
|
315
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
316
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
317
|
+
});
|
|
318
|
+
validateCanonicalWorkspacePath(record.reference, `${path}.reference`, issues);
|
|
319
|
+
requireEnum(record.privacyClass, `${path}.privacyClass`, PRIVACY_CLASS_SET, issues);
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
function validateArtifacts(value, path, issues) {
|
|
323
|
+
const entries = requireArray(value, path, issues);
|
|
324
|
+
if (!entries)
|
|
325
|
+
return false;
|
|
326
|
+
const names = new Set();
|
|
327
|
+
entries.forEach((entry, index) => {
|
|
328
|
+
if (validateArtifact(entry, `${path}[${index}]`, issues)) {
|
|
329
|
+
const name = entry.name;
|
|
330
|
+
if (names.has(name)) {
|
|
331
|
+
addIssue(issues, `${path}[${index}].name`, 'must be unique');
|
|
332
|
+
}
|
|
333
|
+
names.add(name);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
function validateContractReference(value, path, issues) {
|
|
339
|
+
const record = requireRecord(value, path, ['class', 'reference'], [], issues);
|
|
340
|
+
if (!record)
|
|
341
|
+
return false;
|
|
342
|
+
requireEnum(record.class, `${path}.class`, CONTRACT_CLASS_SET, issues);
|
|
343
|
+
requireSafeString(record.reference, `${path}.reference`, issues, {
|
|
344
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
345
|
+
});
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
function validateContractReferences(value, path, issues) {
|
|
349
|
+
const entries = requireArray(value, path, issues);
|
|
350
|
+
if (!entries)
|
|
351
|
+
return false;
|
|
352
|
+
const identities = new Set();
|
|
353
|
+
entries.forEach((entry, index) => {
|
|
354
|
+
if (validateContractReference(entry, `${path}[${index}]`, issues)) {
|
|
355
|
+
const contract = entry;
|
|
356
|
+
const identity = `${contract.class}:${contract.reference}`;
|
|
357
|
+
if (identities.has(identity)) {
|
|
358
|
+
addIssue(issues, `${path}[${index}]`, 'must be unique');
|
|
359
|
+
}
|
|
360
|
+
identities.add(identity);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
function validateWorkspaceContext(value, path, issues) {
|
|
366
|
+
const record = requireRecord(value, path, [
|
|
367
|
+
'blueprintVersions',
|
|
368
|
+
'frameworkVersion',
|
|
369
|
+
'identity',
|
|
370
|
+
'ownershipVersions',
|
|
371
|
+
'ownershipAgreement',
|
|
372
|
+
'repositoryRoot',
|
|
373
|
+
], ['candidateProvenance'], issues);
|
|
374
|
+
if (!record)
|
|
375
|
+
return false;
|
|
376
|
+
validateVersionRecords(record.blueprintVersions, `${path}.blueprintVersions`, issues);
|
|
377
|
+
requireSafeString(record.frameworkVersion, `${path}.frameworkVersion`, issues);
|
|
378
|
+
requireSafeString(record.identity, `${path}.identity`, issues, {
|
|
379
|
+
pattern: IDENTIFIER_PATTERN,
|
|
380
|
+
});
|
|
381
|
+
validateOwnershipVersionStates(record.ownershipVersions, `${path}.ownershipVersions`, issues);
|
|
382
|
+
requireEnum(record.ownershipAgreement, `${path}.ownershipAgreement`, new Set(['agrees', 'conflict', 'unavailable']), issues);
|
|
383
|
+
requireSafeString(record.repositoryRoot, `${path}.repositoryRoot`, issues, {
|
|
384
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
385
|
+
});
|
|
386
|
+
if (has(record, 'candidateProvenance')) {
|
|
387
|
+
validateCandidateProvenance(record.candidateProvenance, `${path}.candidateProvenance`, issues);
|
|
388
|
+
}
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
function validateOwnershipVersionState(value, path, issues) {
|
|
392
|
+
const record = requireRecord(value, path, ['kind', 'target'], [
|
|
393
|
+
'blueprintName',
|
|
394
|
+
'installedBlueprintVersion',
|
|
395
|
+
'installedFrameworkVersion',
|
|
396
|
+
'recordedBlueprintVersion',
|
|
397
|
+
'recordedFrameworkVersion',
|
|
398
|
+
], issues);
|
|
399
|
+
if (!record)
|
|
400
|
+
return false;
|
|
401
|
+
requireEnum(record.kind, `${path}.kind`, new Set(['foundation', 'slice', 'workspace']), issues);
|
|
402
|
+
requireSafeString(record.target, `${path}.target`, issues, {
|
|
403
|
+
pattern: IDENTIFIER_PATTERN,
|
|
404
|
+
});
|
|
405
|
+
for (const field of [
|
|
406
|
+
'blueprintName',
|
|
407
|
+
'installedBlueprintVersion',
|
|
408
|
+
'installedFrameworkVersion',
|
|
409
|
+
'recordedBlueprintVersion',
|
|
410
|
+
'recordedFrameworkVersion',
|
|
411
|
+
]) {
|
|
412
|
+
if (has(record, field)) {
|
|
413
|
+
requireSafeString(record[field], `${path}.${field}`, issues);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const kind = record.kind;
|
|
417
|
+
if ((kind === 'workspace' || kind === 'foundation') &&
|
|
418
|
+
record.target !== kind) {
|
|
419
|
+
addIssue(issues, `${path}.target`, `must equal ${kind}`);
|
|
420
|
+
}
|
|
421
|
+
if (kind === 'slice') {
|
|
422
|
+
for (const field of ['blueprintName', 'recordedBlueprintVersion']) {
|
|
423
|
+
if (!has(record, field)) {
|
|
424
|
+
addIssue(issues, `${path}.${field}`, 'is required for a Slice');
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
if (!has(record, 'recordedFrameworkVersion')) {
|
|
430
|
+
addIssue(issues, `${path}.recordedFrameworkVersion`, `is required for ${String(kind)} ownership`);
|
|
431
|
+
}
|
|
432
|
+
for (const field of [
|
|
433
|
+
'blueprintName',
|
|
434
|
+
'installedBlueprintVersion',
|
|
435
|
+
'recordedBlueprintVersion',
|
|
436
|
+
]) {
|
|
437
|
+
if (has(record, field)) {
|
|
438
|
+
addIssue(issues, `${path}.${field}`, 'is accepted only for Slice ownership');
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
function validateOwnershipVersionStates(value, path, issues) {
|
|
445
|
+
const entries = requireArray(value, path, issues, MAX_COLLECTION_ITEMS);
|
|
446
|
+
if (!entries)
|
|
447
|
+
return false;
|
|
448
|
+
const targets = new Set();
|
|
449
|
+
let previousTarget;
|
|
450
|
+
entries.forEach((entry, index) => {
|
|
451
|
+
if (validateOwnershipVersionState(entry, `${path}[${index}]`, issues)) {
|
|
452
|
+
if (targets.has(entry.target)) {
|
|
453
|
+
addIssue(issues, `${path}[${index}].target`, 'must be unique');
|
|
454
|
+
}
|
|
455
|
+
if (previousTarget !== undefined &&
|
|
456
|
+
(0, ordering_js_1.compareDeveloperAgentStrings)(previousTarget, entry.target) >= 0) {
|
|
457
|
+
addIssue(issues, `${path}[${index}].target`, 'must be in ascending canonical order');
|
|
458
|
+
}
|
|
459
|
+
targets.add(entry.target);
|
|
460
|
+
previousTarget = entry.target;
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
function validateGitContext(value, path, issues) {
|
|
466
|
+
const record = requireRecord(value, path, [
|
|
467
|
+
'ahead',
|
|
468
|
+
'behind',
|
|
469
|
+
'commit',
|
|
470
|
+
'concurrentChangeInspectionComplete',
|
|
471
|
+
'concurrentChanges',
|
|
472
|
+
'defaultBaseCommit',
|
|
473
|
+
'defaultBaseRef',
|
|
474
|
+
'dirty',
|
|
475
|
+
'worktreeRoot',
|
|
476
|
+
], ['baseCommit', 'branch', 'headCommit', 'upstream'], issues);
|
|
477
|
+
if (!record)
|
|
478
|
+
return false;
|
|
479
|
+
requireInteger(record.ahead, `${path}.ahead`, issues, 0, 1_000_000);
|
|
480
|
+
requireInteger(record.behind, `${path}.behind`, issues, 0, 1_000_000);
|
|
481
|
+
requireSafeString(record.commit, `${path}.commit`, issues, {
|
|
482
|
+
maximumLength: 64,
|
|
483
|
+
pattern: COMMIT_PATTERN,
|
|
484
|
+
});
|
|
485
|
+
requireBoolean(record.concurrentChangeInspectionComplete, `${path}.concurrentChangeInspectionComplete`, issues);
|
|
486
|
+
const concurrentChanges = requireArray(record.concurrentChanges, `${path}.concurrentChanges`, issues, MAX_CONCURRENT_PATHS);
|
|
487
|
+
const concurrentPaths = new Set();
|
|
488
|
+
let previousConcurrentPath;
|
|
489
|
+
concurrentChanges?.forEach((entry, index) => {
|
|
490
|
+
const entryPath = `${path}.concurrentChanges[${index}]`;
|
|
491
|
+
const concurrent = requireRecord(entry, entryPath, ['committed', 'dirty', 'path', 'worktreeCount'], [], issues);
|
|
492
|
+
if (!concurrent)
|
|
493
|
+
return;
|
|
494
|
+
const committedValid = requireBoolean(concurrent.committed, `${entryPath}.committed`, issues);
|
|
495
|
+
const dirtyValid = requireBoolean(concurrent.dirty, `${entryPath}.dirty`, issues);
|
|
496
|
+
if (committedValid &&
|
|
497
|
+
dirtyValid &&
|
|
498
|
+
concurrent.committed === false &&
|
|
499
|
+
concurrent.dirty === false) {
|
|
500
|
+
addIssue(issues, entryPath, 'must identify a dirty or committed concurrent change');
|
|
501
|
+
}
|
|
502
|
+
if (validateCanonicalWorkspacePath(concurrent.path, `${entryPath}.path`, issues)) {
|
|
503
|
+
const change = concurrent;
|
|
504
|
+
const collisionKey = change.path
|
|
505
|
+
.normalize('NFC')
|
|
506
|
+
.toLocaleLowerCase('en-US');
|
|
507
|
+
if (concurrentPaths.has(collisionKey)) {
|
|
508
|
+
addIssue(issues, `${entryPath}.path`, 'must not duplicate or case-alias another concurrent path');
|
|
509
|
+
}
|
|
510
|
+
if (previousConcurrentPath !== undefined &&
|
|
511
|
+
previousConcurrentPath >= collisionKey) {
|
|
512
|
+
addIssue(issues, `${entryPath}.path`, 'must be in ascending canonical order');
|
|
513
|
+
}
|
|
514
|
+
concurrentPaths.add(collisionKey);
|
|
515
|
+
previousConcurrentPath = collisionKey;
|
|
516
|
+
}
|
|
517
|
+
requireInteger(concurrent.worktreeCount, `${entryPath}.worktreeCount`, issues, 1, 64);
|
|
518
|
+
});
|
|
519
|
+
requireSafeString(record.defaultBaseCommit, `${path}.defaultBaseCommit`, issues, {
|
|
520
|
+
maximumLength: 64,
|
|
521
|
+
pattern: COMMIT_PATTERN,
|
|
522
|
+
});
|
|
523
|
+
requireSafeString(record.defaultBaseRef, `${path}.defaultBaseRef`, issues, {
|
|
524
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
525
|
+
});
|
|
526
|
+
requireBoolean(record.dirty, `${path}.dirty`, issues);
|
|
527
|
+
requireSafeString(record.worktreeRoot, `${path}.worktreeRoot`, issues, {
|
|
528
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
529
|
+
});
|
|
530
|
+
for (const property of ['baseCommit', 'headCommit']) {
|
|
531
|
+
if (has(record, property)) {
|
|
532
|
+
requireSafeString(record[property], `${path}.${property}`, issues, {
|
|
533
|
+
maximumLength: 64,
|
|
534
|
+
pattern: COMMIT_PATTERN,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
for (const property of ['branch', 'upstream']) {
|
|
539
|
+
if (has(record, property)) {
|
|
540
|
+
requireSafeString(record[property], `${path}.${property}`, issues, {
|
|
541
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
function validatePolicyField(value, path, issues) {
|
|
548
|
+
const record = requireRecord(value, path, ['name', 'value'], [], issues);
|
|
549
|
+
if (!record)
|
|
550
|
+
return false;
|
|
551
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
552
|
+
pattern: FIELD_NAME_PATTERN,
|
|
553
|
+
});
|
|
554
|
+
requireSafeString(record.value, `${path}.value`, issues, {
|
|
555
|
+
maximumLength: MAX_INPUT_VALUE_LENGTH,
|
|
556
|
+
});
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
function validateEffectivePolicyDecision(value, path, issues) {
|
|
560
|
+
const record = requireRecord(value, path, ['action', 'allowed', 'projects', 'reasons', 'stage'], ['effectiveProductionProfile'], issues);
|
|
561
|
+
if (!record)
|
|
562
|
+
return false;
|
|
563
|
+
requireEnum(record.action, `${path}.action`, POLICY_LIFECYCLE_ACTION_SET, issues);
|
|
564
|
+
requireBoolean(record.allowed, `${path}.allowed`, issues);
|
|
565
|
+
validateStringArray(record.projects, `${path}.projects`, issues, {
|
|
566
|
+
pattern: IDENTIFIER_PATTERN,
|
|
567
|
+
});
|
|
568
|
+
validateStringArray(record.reasons, `${path}.reasons`, issues, {
|
|
569
|
+
maximumLength: MAX_SUMMARY_LENGTH,
|
|
570
|
+
});
|
|
571
|
+
requireEnum(record.stage, `${path}.stage`, CANONICAL_STAGE_SET, issues);
|
|
572
|
+
if (has(record, 'effectiveProductionProfile')) {
|
|
573
|
+
requireEnum(record.effectiveProductionProfile, `${path}.effectiveProductionProfile`, PRODUCTION_PROFILE_SET, issues);
|
|
574
|
+
}
|
|
575
|
+
if (record.allowed === true &&
|
|
576
|
+
Array.isArray(record.reasons) &&
|
|
577
|
+
record.reasons.length > 0) {
|
|
578
|
+
addIssue(issues, `${path}.reasons`, 'must be empty when allowed is true');
|
|
579
|
+
}
|
|
580
|
+
if (record.allowed === false &&
|
|
581
|
+
Array.isArray(record.reasons) &&
|
|
582
|
+
record.reasons.length === 0) {
|
|
583
|
+
addIssue(issues, `${path}.reasons`, 'must explain a denied decision');
|
|
584
|
+
}
|
|
585
|
+
return true;
|
|
586
|
+
}
|
|
587
|
+
function validatePolicyContext(value, path, issues) {
|
|
588
|
+
const record = requireRecord(value, path, [
|
|
589
|
+
'canonicalStage',
|
|
590
|
+
'effectiveDecisions',
|
|
591
|
+
'effectivePolicyDigest',
|
|
592
|
+
'effectivePolicyReferences',
|
|
593
|
+
'repositoryPolicyFields',
|
|
594
|
+
], [], issues);
|
|
595
|
+
if (!record)
|
|
596
|
+
return false;
|
|
597
|
+
requireEnum(record.canonicalStage, `${path}.canonicalStage`, CANONICAL_STAGE_SET, issues);
|
|
598
|
+
const decisions = requireArray(record.effectiveDecisions, `${path}.effectiveDecisions`, issues);
|
|
599
|
+
const decisionKeys = new Set();
|
|
600
|
+
decisions?.forEach((entry, index) => {
|
|
601
|
+
if (validateEffectivePolicyDecision(entry, `${path}.effectiveDecisions[${index}]`, issues)) {
|
|
602
|
+
const decision = entry;
|
|
603
|
+
const key = `${decision.stage}:${decision.action}:${decision.projects.join(',')}`;
|
|
604
|
+
if (decisionKeys.has(key)) {
|
|
605
|
+
addIssue(issues, `${path}.effectiveDecisions[${index}]`, 'must not duplicate another stage/action decision');
|
|
606
|
+
}
|
|
607
|
+
decisionKeys.add(key);
|
|
608
|
+
if (decision.stage !== record.canonicalStage) {
|
|
609
|
+
addIssue(issues, `${path}.effectiveDecisions[${index}].stage`, 'must equal the canonical stage');
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
requireSafeString(record.effectivePolicyDigest, `${path}.effectivePolicyDigest`, issues, {
|
|
614
|
+
maximumLength: 71,
|
|
615
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
616
|
+
});
|
|
617
|
+
validateStringArray(record.effectivePolicyReferences, `${path}.effectivePolicyReferences`, issues, { maximumLength: MAX_PATH_LENGTH });
|
|
618
|
+
const fields = requireArray(record.repositoryPolicyFields, `${path}.repositoryPolicyFields`, issues);
|
|
619
|
+
if (fields) {
|
|
620
|
+
const names = new Set();
|
|
621
|
+
fields.forEach((entry, index) => {
|
|
622
|
+
if (validatePolicyField(entry, `${path}.repositoryPolicyFields[${index}]`, issues)) {
|
|
623
|
+
const name = entry.name;
|
|
624
|
+
if (names.has(name)) {
|
|
625
|
+
addIssue(issues, `${path}.repositoryPolicyFields[${index}].name`, 'must be unique');
|
|
626
|
+
}
|
|
627
|
+
names.add(name);
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
return true;
|
|
632
|
+
}
|
|
633
|
+
function validateProjectContext(value, path, issues) {
|
|
634
|
+
const record = requireRecord(value, path, ['dependencies', 'name', 'root', 'tags', 'targets'], [], issues);
|
|
635
|
+
if (!record)
|
|
636
|
+
return false;
|
|
637
|
+
validateStringArray(record.dependencies, `${path}.dependencies`, issues, {
|
|
638
|
+
pattern: IDENTIFIER_PATTERN,
|
|
639
|
+
});
|
|
640
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
641
|
+
pattern: IDENTIFIER_PATTERN,
|
|
642
|
+
});
|
|
643
|
+
requireSafeString(record.root, `${path}.root`, issues, {
|
|
644
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
645
|
+
});
|
|
646
|
+
validateStringArray(record.tags, `${path}.tags`, issues, {
|
|
647
|
+
pattern: IDENTIFIER_PATTERN,
|
|
648
|
+
});
|
|
649
|
+
validateStringArray(record.targets, `${path}.targets`, issues, {
|
|
650
|
+
pattern: IDENTIFIER_PATTERN,
|
|
651
|
+
});
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
function validateProjectContexts(value, path, issues) {
|
|
655
|
+
const entries = requireArray(value, path, issues);
|
|
656
|
+
if (!entries)
|
|
657
|
+
return false;
|
|
658
|
+
const names = new Set();
|
|
659
|
+
entries.forEach((entry, index) => {
|
|
660
|
+
if (validateProjectContext(entry, `${path}[${index}]`, issues)) {
|
|
661
|
+
const name = entry.name;
|
|
662
|
+
if (names.has(name)) {
|
|
663
|
+
addIssue(issues, `${path}[${index}].name`, 'must be unique');
|
|
664
|
+
}
|
|
665
|
+
names.add(name);
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
670
|
+
function validateSelectionContext(value, path, issues) {
|
|
671
|
+
const record = requireRecord(value, path, ['contracts', 'foundationCapabilities', 'projectInventory'], ['feature', 'files', 'slice'], issues);
|
|
672
|
+
if (!record)
|
|
673
|
+
return false;
|
|
674
|
+
validateContractReferences(record.contracts, `${path}.contracts`, issues);
|
|
675
|
+
validateStringArray(record.foundationCapabilities, `${path}.foundationCapabilities`, issues, { pattern: IDENTIFIER_PATTERN });
|
|
676
|
+
requireEnum(record.projectInventory, `${path}.projectInventory`, new Set(['bounded', 'full']), issues);
|
|
677
|
+
for (const property of ['feature', 'slice']) {
|
|
678
|
+
if (has(record, property)) {
|
|
679
|
+
requireSafeString(record[property], `${path}.${property}`, issues, {
|
|
680
|
+
pattern: IDENTIFIER_PATTERN,
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
if (has(record, 'files')) {
|
|
685
|
+
const files = requireArray(record.files, `${path}.files`, issues);
|
|
686
|
+
const paths = new Set();
|
|
687
|
+
files?.forEach((entry, index) => {
|
|
688
|
+
if (validateSelectedFileContext(entry, `${path}.files[${index}]`, issues)) {
|
|
689
|
+
const selected = entry;
|
|
690
|
+
if (paths.has(selected.path)) {
|
|
691
|
+
addIssue(issues, `${path}.files[${index}].path`, 'must not duplicate another selected file');
|
|
692
|
+
}
|
|
693
|
+
paths.add(selected.path);
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
return true;
|
|
698
|
+
}
|
|
699
|
+
function validateSelectedFileContext(value, path, issues) {
|
|
700
|
+
const record = requireRecord(value, path, ['ownershipMode', 'path', 'project'], [], issues);
|
|
701
|
+
if (!record)
|
|
702
|
+
return false;
|
|
703
|
+
requireEnum(record.ownershipMode, `${path}.ownershipMode`, OWNERSHIP_MODE_SET, issues);
|
|
704
|
+
validateCanonicalWorkspacePath(record.path, `${path}.path`, issues);
|
|
705
|
+
requireSafeString(record.project, `${path}.project`, issues, {
|
|
706
|
+
pattern: IDENTIFIER_PATTERN,
|
|
707
|
+
});
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
function validateCanonicalWorkspacePath(value, path, issues) {
|
|
711
|
+
const valid = requireSafeString(value, path, issues, {
|
|
712
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
713
|
+
pattern: WORKSPACE_RELATIVE_PATH_PATTERN,
|
|
714
|
+
});
|
|
715
|
+
if (valid && !(0, workspace_path_js_1.isCanonicalDeveloperAgentWorkspacePath)(value)) {
|
|
716
|
+
addIssue(issues, path, 'must be a canonical relative path');
|
|
717
|
+
}
|
|
718
|
+
return valid;
|
|
719
|
+
}
|
|
720
|
+
function validateAffectedContext(value, path, issues) {
|
|
721
|
+
const record = requireRecord(value, path, [
|
|
722
|
+
'baseCommit',
|
|
723
|
+
'fileCount',
|
|
724
|
+
'files',
|
|
725
|
+
'filesDigest',
|
|
726
|
+
'filesTruncated',
|
|
727
|
+
'headCommit',
|
|
728
|
+
'projects',
|
|
729
|
+
'targets',
|
|
730
|
+
], [], issues);
|
|
731
|
+
if (!record)
|
|
732
|
+
return false;
|
|
733
|
+
for (const property of ['baseCommit', 'headCommit']) {
|
|
734
|
+
requireSafeString(record[property], `${path}.${property}`, issues, {
|
|
735
|
+
maximumLength: 64,
|
|
736
|
+
pattern: COMMIT_PATTERN,
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
const fileCountValid = requireInteger(record.fileCount, `${path}.fileCount`, issues, 0, MAX_CONCURRENT_PATHS);
|
|
740
|
+
const files = requireArray(record.files, `${path}.files`, issues, MAX_AFFECTED_FILE_REFERENCES);
|
|
741
|
+
const fileKeys = new Set();
|
|
742
|
+
let previousFileKey;
|
|
743
|
+
files?.forEach((entry, index) => {
|
|
744
|
+
if (validateCanonicalWorkspacePath(entry, `${path}.files[${index}]`, issues)) {
|
|
745
|
+
const file = entry;
|
|
746
|
+
const key = file.normalize('NFC').toLocaleLowerCase('en-US');
|
|
747
|
+
if (fileKeys.has(key)) {
|
|
748
|
+
addIssue(issues, `${path}.files[${index}]`, 'must not duplicate or case-alias another affected path');
|
|
749
|
+
}
|
|
750
|
+
if (previousFileKey !== undefined && previousFileKey >= key) {
|
|
751
|
+
addIssue(issues, `${path}.files[${index}]`, 'must be in ascending canonical order');
|
|
752
|
+
}
|
|
753
|
+
fileKeys.add(key);
|
|
754
|
+
previousFileKey = key;
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
requireSafeString(record.filesDigest, `${path}.filesDigest`, issues, {
|
|
758
|
+
maximumLength: 71,
|
|
759
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
760
|
+
});
|
|
761
|
+
const truncatedValid = requireBoolean(record.filesTruncated, `${path}.filesTruncated`, issues);
|
|
762
|
+
if (fileCountValid && truncatedValid && files) {
|
|
763
|
+
const fileCount = record.fileCount;
|
|
764
|
+
if ((record.filesTruncated === false && fileCount !== files.length) ||
|
|
765
|
+
(record.filesTruncated === true &&
|
|
766
|
+
(files.length !== MAX_AFFECTED_FILE_REFERENCES ||
|
|
767
|
+
fileCount <= files.length))) {
|
|
768
|
+
addIssue(issues, path, 'must retain an exact file count and an honest bounded-file truncation state');
|
|
769
|
+
}
|
|
770
|
+
if (record.filesTruncated === false &&
|
|
771
|
+
files.every((entry) => typeof entry === 'string') &&
|
|
772
|
+
record.filesDigest !==
|
|
773
|
+
`sha256:${(0, node_crypto_1.createHash)('sha256')
|
|
774
|
+
.update(JSON.stringify(files), 'utf8')
|
|
775
|
+
.digest('hex')}`) {
|
|
776
|
+
addIssue(issues, `${path}.filesDigest`, 'must bind the complete retained affected-path set');
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
validateStringArray(record.projects, `${path}.projects`, issues, {
|
|
780
|
+
pattern: IDENTIFIER_PATTERN,
|
|
781
|
+
});
|
|
782
|
+
validateStringArray(record.targets, `${path}.targets`, issues, {
|
|
783
|
+
pattern: IDENTIFIER_PATTERN,
|
|
784
|
+
});
|
|
785
|
+
return true;
|
|
786
|
+
}
|
|
787
|
+
function validateMarkerContext(value, path, issues) {
|
|
788
|
+
const record = requireRecord(value, path, ['blocking', 'path', 'reference', 'sanitizedSummary'], [], issues);
|
|
789
|
+
if (!record)
|
|
790
|
+
return false;
|
|
791
|
+
requireBoolean(record.blocking, `${path}.blocking`, issues);
|
|
792
|
+
validateCanonicalWorkspacePath(record.path, `${path}.path`, issues);
|
|
793
|
+
requireSafeString(record.reference, `${path}.reference`, issues);
|
|
794
|
+
requireSafeString(record.sanitizedSummary, `${path}.sanitizedSummary`, issues, { maximumLength: MAX_SUMMARY_LENGTH });
|
|
795
|
+
return true;
|
|
796
|
+
}
|
|
797
|
+
function validateReportContext(value, path, issues) {
|
|
798
|
+
const record = requireRecord(value, path, ['name', 'outcome'], ['reference'], issues);
|
|
799
|
+
if (!record)
|
|
800
|
+
return false;
|
|
801
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
802
|
+
pattern: IDENTIFIER_PATTERN,
|
|
803
|
+
});
|
|
804
|
+
requireEnum(record.outcome, `${path}.outcome`, new Set(['passed', 'failed', 'blocked', 'unavailable']), issues);
|
|
805
|
+
if (has(record, 'reference')) {
|
|
806
|
+
requireSafeString(record.reference, `${path}.reference`, issues, {
|
|
807
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
return true;
|
|
811
|
+
}
|
|
812
|
+
function validateWarning(value, path, issues) {
|
|
813
|
+
const record = requireRecord(value, path, ['classification', 'sanitizedSummary'], ['upgradeVersionDrift'], issues);
|
|
814
|
+
if (!record)
|
|
815
|
+
return false;
|
|
816
|
+
requireEnum(record.classification, `${path}.classification`, FAILURE_SET, issues);
|
|
817
|
+
requireSafeString(record.sanitizedSummary, `${path}.sanitizedSummary`, issues, { maximumLength: MAX_SUMMARY_LENGTH });
|
|
818
|
+
if (has(record, 'upgradeVersionDrift')) {
|
|
819
|
+
const drift = requireRecord(record.upgradeVersionDrift, `${path}.upgradeVersionDrift`, ['kind', 'target'], [], issues);
|
|
820
|
+
if (drift) {
|
|
821
|
+
requireEnum(drift.kind, `${path}.upgradeVersionDrift.kind`, new Set(['foundation', 'slice', 'workspace']), issues);
|
|
822
|
+
requireSafeString(drift.target, `${path}.upgradeVersionDrift.target`, issues, { pattern: IDENTIFIER_PATTERN });
|
|
823
|
+
}
|
|
824
|
+
if (record.classification !== 'ownership-conflict') {
|
|
825
|
+
addIssue(issues, `${path}.upgradeVersionDrift`, 'is accepted only for ownership-conflict warnings');
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
return true;
|
|
829
|
+
}
|
|
830
|
+
function validateWarnings(value, path, issues) {
|
|
831
|
+
const entries = requireArray(value, path, issues);
|
|
832
|
+
if (!entries)
|
|
833
|
+
return false;
|
|
834
|
+
entries.forEach((entry, index) => validateWarning(entry, `${path}[${index}]`, issues));
|
|
835
|
+
return true;
|
|
836
|
+
}
|
|
837
|
+
function validateGeneratorOperation(value, path, issues) {
|
|
838
|
+
const record = requireRecord(value, path, ['generator', 'mode'], [], issues);
|
|
839
|
+
if (!record)
|
|
840
|
+
return false;
|
|
841
|
+
requireEnum(record.generator, `${path}.generator`, STABLE_GENERATOR_SET, issues);
|
|
842
|
+
requireEnum(record.mode, `${path}.mode`, GENERATOR_MODE_SET, issues);
|
|
843
|
+
return true;
|
|
844
|
+
}
|
|
845
|
+
function validateGeneratorInput(value, path, issues) {
|
|
846
|
+
if (!(0, validation_js_1.isRecord)(value) || typeof value.generator !== 'string') {
|
|
847
|
+
addIssue(issues, path, 'must be one closed typed stable-generator input');
|
|
848
|
+
return false;
|
|
849
|
+
}
|
|
850
|
+
const slug = (entry, entryPath) => requireSafeString(entry, entryPath, issues, {
|
|
851
|
+
maximumLength: 63,
|
|
852
|
+
pattern: GENERATOR_SLUG_PATTERN,
|
|
853
|
+
});
|
|
854
|
+
if (value.generator === 'slice') {
|
|
855
|
+
const record = requireRecord(value, path, ['generator', 'name'], [], issues);
|
|
856
|
+
if (record)
|
|
857
|
+
slug(record.name, `${path}.name`);
|
|
858
|
+
return record !== undefined;
|
|
859
|
+
}
|
|
860
|
+
if (value.generator === 'function' ||
|
|
861
|
+
value.generator === 'service' ||
|
|
862
|
+
value.generator === 'job') {
|
|
863
|
+
const record = requireRecord(value, path, ['feature', 'generator', 'name', 'slice'], [], issues);
|
|
864
|
+
if (record) {
|
|
865
|
+
slug(record.feature, `${path}.feature`);
|
|
866
|
+
slug(record.name, `${path}.name`);
|
|
867
|
+
slug(record.slice, `${path}.slice`);
|
|
868
|
+
}
|
|
869
|
+
return record !== undefined;
|
|
870
|
+
}
|
|
871
|
+
if (value.generator === 'upgrade') {
|
|
872
|
+
const record = requireRecord(value, path, ['generator', 'name'], ['preview'], issues);
|
|
873
|
+
if (!record)
|
|
874
|
+
return false;
|
|
875
|
+
slug(record.name, `${path}.name`);
|
|
876
|
+
if (has(record, 'preview')) {
|
|
877
|
+
const preview = requireRecord(record.preview, `${path}.preview`, ['digest', 'reference'], [], issues);
|
|
878
|
+
if (preview) {
|
|
879
|
+
requireSafeString(preview.digest, `${path}.preview.digest`, issues, {
|
|
880
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
881
|
+
});
|
|
882
|
+
requireSafeString(preview.reference, `${path}.preview.reference`, issues, {
|
|
883
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
884
|
+
pattern: GENERATOR_PREVIEW_REFERENCE_PATTERN,
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return true;
|
|
889
|
+
}
|
|
890
|
+
addIssue(issues, `${path}.generator`, 'must identify a stable typed generator');
|
|
891
|
+
return false;
|
|
892
|
+
}
|
|
893
|
+
function validateSupportedOperation(value, path, issues) {
|
|
894
|
+
const record = requireRecord(value, path, [
|
|
895
|
+
'applicableStages',
|
|
896
|
+
'approvalRequired',
|
|
897
|
+
'authority',
|
|
898
|
+
'contracts',
|
|
899
|
+
'documentationPaths',
|
|
900
|
+
'evidenceClasses',
|
|
901
|
+
'id',
|
|
902
|
+
'owner',
|
|
903
|
+
'projects',
|
|
904
|
+
'requiredVerification',
|
|
905
|
+
], ['command', 'generator', 'policyLifecycleAction'], issues);
|
|
906
|
+
if (!record)
|
|
907
|
+
return false;
|
|
908
|
+
const applicableStages = requireArray(record.applicableStages, `${path}.applicableStages`, issues);
|
|
909
|
+
const stages = new Set();
|
|
910
|
+
applicableStages?.forEach((stage, index) => {
|
|
911
|
+
if (requireEnum(stage, `${path}.applicableStages[${index}]`, CANONICAL_STAGE_SET, issues)) {
|
|
912
|
+
if (stages.has(stage)) {
|
|
913
|
+
addIssue(issues, `${path}.applicableStages[${index}]`, 'must not duplicate another stage');
|
|
914
|
+
}
|
|
915
|
+
stages.add(stage);
|
|
916
|
+
}
|
|
917
|
+
});
|
|
918
|
+
if (applicableStages?.length === 0) {
|
|
919
|
+
addIssue(issues, `${path}.applicableStages`, 'must declare at least one canonical stage');
|
|
920
|
+
}
|
|
921
|
+
requireBoolean(record.approvalRequired, `${path}.approvalRequired`, issues);
|
|
922
|
+
requireEnum(record.authority, `${path}.authority`, AUTHORITY_SET, issues);
|
|
923
|
+
if (has(record, 'command')) {
|
|
924
|
+
validateCommand(record.command, `${path}.command`, issues);
|
|
925
|
+
}
|
|
926
|
+
if (has(record, 'generator')) {
|
|
927
|
+
validateGeneratorOperation(record.generator, `${path}.generator`, issues);
|
|
928
|
+
}
|
|
929
|
+
validateContractReferences(record.contracts, `${path}.contracts`, issues);
|
|
930
|
+
validateStringArray(record.documentationPaths, `${path}.documentationPaths`, issues, { maximumLength: MAX_PATH_LENGTH });
|
|
931
|
+
validateStringArray(record.evidenceClasses, `${path}.evidenceClasses`, issues);
|
|
932
|
+
requireSafeString(record.id, `${path}.id`, issues, {
|
|
933
|
+
pattern: IDENTIFIER_PATTERN,
|
|
934
|
+
});
|
|
935
|
+
requireEnum(record.owner, `${path}.owner`, OPERATION_OWNER_SET, issues);
|
|
936
|
+
if (has(record, 'policyLifecycleAction')) {
|
|
937
|
+
requireEnum(record.policyLifecycleAction, `${path}.policyLifecycleAction`, POLICY_LIFECYCLE_ACTION_SET, issues);
|
|
938
|
+
}
|
|
939
|
+
validateStringArray(record.projects, `${path}.projects`, issues, {
|
|
940
|
+
pattern: IDENTIFIER_PATTERN,
|
|
941
|
+
});
|
|
942
|
+
validateStringArray(record.requiredVerification, `${path}.requiredVerification`, issues);
|
|
943
|
+
if ((record.authority === 'protected-mutate' ||
|
|
944
|
+
record.authority === 'destructive') &&
|
|
945
|
+
record.approvalRequired !== true) {
|
|
946
|
+
addIssue(issues, `${path}.approvalRequired`, 'must be true for protected or destructive operation');
|
|
947
|
+
}
|
|
948
|
+
if ((record.authority === 'protected-mutate' ||
|
|
949
|
+
record.authority === 'destructive') &&
|
|
950
|
+
has(record, 'command')) {
|
|
951
|
+
addIssue(issues, `${path}.command`, 'must be absent because protected or destructive authority is not local argv');
|
|
952
|
+
}
|
|
953
|
+
if (record.authority !== 'protected-mutate' &&
|
|
954
|
+
record.authority !== 'destructive' &&
|
|
955
|
+
record.owner !== 'source-edit' &&
|
|
956
|
+
record.owner !== 'nx-generator' &&
|
|
957
|
+
!has(record, 'command')) {
|
|
958
|
+
addIssue(issues, `${path}.command`, 'is required for a locally invocable operation');
|
|
959
|
+
}
|
|
960
|
+
const generator = (0, validation_js_1.isRecord)(record.generator) ? record.generator : undefined;
|
|
961
|
+
if (record.owner === 'nx-generator') {
|
|
962
|
+
if (!generator) {
|
|
963
|
+
addIssue(issues, `${path}.generator`, 'is required for a typed Nx generator template');
|
|
964
|
+
}
|
|
965
|
+
else {
|
|
966
|
+
if (typeof generator.generator === 'string' &&
|
|
967
|
+
typeof generator.mode === 'string' &&
|
|
968
|
+
record.id !== `generator:${generator.generator}:${generator.mode}`) {
|
|
969
|
+
addIssue(issues, `${path}.id`, 'must exactly identify the typed generator and mode');
|
|
970
|
+
}
|
|
971
|
+
if ((generator.mode === 'preview' || generator.mode === 'apply') &&
|
|
972
|
+
record.authority !== 'local-source') {
|
|
973
|
+
addIssue(issues, `${path}.authority`, 'must be local-source because generator preview and apply execute the owning generator against a workspace tree');
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (has(record, 'command')) {
|
|
977
|
+
addIssue(issues, `${path}.command`, 'must be absent until typed generator inputs are bound by planning');
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
else if (generator) {
|
|
981
|
+
addIssue(issues, `${path}.generator`, 'is valid only for an nx-generator owner');
|
|
982
|
+
}
|
|
983
|
+
if (record.authority === 'development-mutate' &&
|
|
984
|
+
(stages.size !== 1 || !stages.has('development'))) {
|
|
985
|
+
addIssue(issues, `${path}.applicableStages`, 'must equal development for development mutation');
|
|
986
|
+
}
|
|
987
|
+
if (record.policyLifecycleAction === 'dev' &&
|
|
988
|
+
(stages.size !== 1 || !stages.has('development'))) {
|
|
989
|
+
addIssue(issues, `${path}.applicableStages`, 'must equal development for repository-policy dev actions');
|
|
990
|
+
}
|
|
991
|
+
if ((record.authority === 'protected-mutate' ||
|
|
992
|
+
record.authority === 'destructive') &&
|
|
993
|
+
['deploy', 'migrate', 'refresh', 'remove'].includes(String(record.policyLifecycleAction)) &&
|
|
994
|
+
stages.has('development')) {
|
|
995
|
+
addIssue(issues, `${path}.applicableStages`, 'must route protected lifecycle mutation through staging or production');
|
|
996
|
+
}
|
|
997
|
+
return true;
|
|
998
|
+
}
|
|
999
|
+
function validateSerializedBound(value, path, maximumBytes, issues) {
|
|
1000
|
+
try {
|
|
1001
|
+
const serialized = (0, canonical_json_1.canonicalJson)(value);
|
|
1002
|
+
if (Buffer.byteLength(serialized, 'utf8') > maximumBytes) {
|
|
1003
|
+
addIssue(issues, path, `must serialize to at most ${maximumBytes} bytes`);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
catch {
|
|
1007
|
+
addIssue(issues, path, 'must be canonically JSON serializable');
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
function validateDeveloperAgentContext(value) {
|
|
1011
|
+
const issues = [];
|
|
1012
|
+
validateSerializedBound(value, '$', model_js_1.DEVELOPER_AGENT_CONTEXT_MAX_BYTES, issues);
|
|
1013
|
+
const record = requireRecord(value, '$', [
|
|
1014
|
+
'authenticatedTargets',
|
|
1015
|
+
'documentationPaths',
|
|
1016
|
+
'evidenceClasses',
|
|
1017
|
+
'git',
|
|
1018
|
+
'kind',
|
|
1019
|
+
'markers',
|
|
1020
|
+
'nonPlannableTargets',
|
|
1021
|
+
'policy',
|
|
1022
|
+
'projectNames',
|
|
1023
|
+
'projects',
|
|
1024
|
+
'reports',
|
|
1025
|
+
'requiredVerification',
|
|
1026
|
+
'schemaVersion',
|
|
1027
|
+
'selection',
|
|
1028
|
+
'supportedOperations',
|
|
1029
|
+
'warnings',
|
|
1030
|
+
'workspace',
|
|
1031
|
+
], ['affected'], issues);
|
|
1032
|
+
if (!record)
|
|
1033
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1034
|
+
if (record.kind !== model_js_1.DEVELOPER_AGENT_CONTEXT_KIND) {
|
|
1035
|
+
addIssue(issues, '$.kind', `must equal ${model_js_1.DEVELOPER_AGENT_CONTEXT_KIND}`);
|
|
1036
|
+
}
|
|
1037
|
+
if (record.schemaVersion !== model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION) {
|
|
1038
|
+
addIssue(issues, '$.schemaVersion', `must equal ${model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION}`);
|
|
1039
|
+
}
|
|
1040
|
+
validateStringArray(record.authenticatedTargets, '$.authenticatedTargets', issues, { pattern: IDENTIFIER_PATTERN });
|
|
1041
|
+
validateStringArray(record.documentationPaths, '$.documentationPaths', issues, {
|
|
1042
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1043
|
+
});
|
|
1044
|
+
validateStringArray(record.evidenceClasses, '$.evidenceClasses', issues);
|
|
1045
|
+
validateGitContext(record.git, '$.git', issues);
|
|
1046
|
+
const markers = requireArray(record.markers, '$.markers', issues);
|
|
1047
|
+
markers?.forEach((entry, index) => validateMarkerContext(entry, `$.markers[${index}]`, issues));
|
|
1048
|
+
const nonPlannableTargets = requireArray(record.nonPlannableTargets, '$.nonPlannableTargets', issues);
|
|
1049
|
+
const nonPlannableNames = new Set();
|
|
1050
|
+
nonPlannableTargets?.forEach((entry, index) => {
|
|
1051
|
+
const path = `$.nonPlannableTargets[${index}]`;
|
|
1052
|
+
const target = requireRecord(entry, path, ['rationale', 'target'], [], issues);
|
|
1053
|
+
if (!target)
|
|
1054
|
+
return;
|
|
1055
|
+
requireSafeString(target.rationale, `${path}.rationale`, issues, {
|
|
1056
|
+
maximumLength: MAX_SUMMARY_LENGTH,
|
|
1057
|
+
});
|
|
1058
|
+
if (requireSafeString(target.target, `${path}.target`, issues, {
|
|
1059
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1060
|
+
})) {
|
|
1061
|
+
const name = target.target;
|
|
1062
|
+
if (nonPlannableNames.has(name)) {
|
|
1063
|
+
addIssue(issues, `${path}.target`, 'must be unique');
|
|
1064
|
+
}
|
|
1065
|
+
nonPlannableNames.add(name);
|
|
1066
|
+
}
|
|
1067
|
+
});
|
|
1068
|
+
if (Array.isArray(record.authenticatedTargets)) {
|
|
1069
|
+
for (const target of record.authenticatedTargets) {
|
|
1070
|
+
if (typeof target === 'string' && nonPlannableNames.has(target)) {
|
|
1071
|
+
addIssue(issues, '$.nonPlannableTargets', `${target} cannot be both authenticated and non-plannable`);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
validatePolicyContext(record.policy, '$.policy', issues);
|
|
1076
|
+
const projectNamesValid = validateStringArray(record.projectNames, '$.projectNames', issues, {
|
|
1077
|
+
maximumItems: model_js_1.DEVELOPER_AGENT_MAX_PROJECT_NAMES,
|
|
1078
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1079
|
+
});
|
|
1080
|
+
const projectNames = projectNamesValid
|
|
1081
|
+
? record.projectNames
|
|
1082
|
+
: undefined;
|
|
1083
|
+
if (projectNames) {
|
|
1084
|
+
if (projectNames.length === 0) {
|
|
1085
|
+
addIssue(issues, '$.projectNames', 'must contain the Nx workspace project');
|
|
1086
|
+
}
|
|
1087
|
+
for (let index = 1; index < projectNames.length; index += 1) {
|
|
1088
|
+
if ((0, ordering_js_1.compareDeveloperAgentStrings)(projectNames[index - 1], projectNames[index]) >= 0) {
|
|
1089
|
+
addIssue(issues, `$.projectNames[${index}]`, 'must be in ascending canonical order');
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
const projectsValid = validateProjectContexts(record.projects, '$.projects', issues);
|
|
1094
|
+
const projects = projectsValid
|
|
1095
|
+
? record.projects
|
|
1096
|
+
: undefined;
|
|
1097
|
+
const reports = requireArray(record.reports, '$.reports', issues);
|
|
1098
|
+
reports?.forEach((entry, index) => validateReportContext(entry, `$.reports[${index}]`, issues));
|
|
1099
|
+
validateStringArray(record.requiredVerification, '$.requiredVerification', issues);
|
|
1100
|
+
validateSelectionContext(record.selection, '$.selection', issues);
|
|
1101
|
+
const operations = requireArray(record.supportedOperations, '$.supportedOperations', issues);
|
|
1102
|
+
const operationIds = new Set();
|
|
1103
|
+
operations?.forEach((entry, index) => {
|
|
1104
|
+
if (validateSupportedOperation(entry, `$.supportedOperations[${index}]`, issues)) {
|
|
1105
|
+
const id = entry.id;
|
|
1106
|
+
if (operationIds.has(id)) {
|
|
1107
|
+
addIssue(issues, `$.supportedOperations[${index}].id`, 'must be unique');
|
|
1108
|
+
}
|
|
1109
|
+
operationIds.add(id);
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
validateWarnings(record.warnings, '$.warnings', issues);
|
|
1113
|
+
validateWorkspaceContext(record.workspace, '$.workspace', issues);
|
|
1114
|
+
if (projectNames) {
|
|
1115
|
+
const inventory = new Set(projectNames);
|
|
1116
|
+
if (projects) {
|
|
1117
|
+
for (const [index, project] of projects.entries()) {
|
|
1118
|
+
if (!inventory.has(project.name)) {
|
|
1119
|
+
addIssue(issues, `$.projects[${index}].name`, 'must be included in the full Nx project-name inventory');
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
if ((0, validation_js_1.isRecord)(record.workspace) &&
|
|
1124
|
+
typeof record.workspace.identity === 'string' &&
|
|
1125
|
+
!inventory.has(record.workspace.identity)) {
|
|
1126
|
+
addIssue(issues, '$.workspace.identity', 'must be included in the full Nx project-name inventory');
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
if (has(record, 'affected')) {
|
|
1130
|
+
validateAffectedContext(record.affected, '$.affected', issues);
|
|
1131
|
+
}
|
|
1132
|
+
if ((0, validation_js_1.isRecord)(record.git) && Array.isArray(record.warnings)) {
|
|
1133
|
+
const classifications = new Set(record.warnings.filter(validation_js_1.isRecord).map((warning) => warning.classification));
|
|
1134
|
+
if (record.git.dirty === true && !classifications.has('dirty-worktree')) {
|
|
1135
|
+
addIssue(issues, '$.warnings', 'must report dirty-worktree when Git context is dirty');
|
|
1136
|
+
}
|
|
1137
|
+
if ((0, validation_js_1.isRecord)(record.workspace) &&
|
|
1138
|
+
record.workspace.ownershipAgreement === 'conflict' &&
|
|
1139
|
+
!classifications.has('ownership-conflict')) {
|
|
1140
|
+
addIssue(issues, '$.warnings', 'must report ownership-conflict when records disagree');
|
|
1141
|
+
}
|
|
1142
|
+
if ((0, validation_js_1.isRecord)(record.workspace) &&
|
|
1143
|
+
Array.isArray(record.workspace.ownershipVersions)) {
|
|
1144
|
+
for (const [index, entry] of record.warnings.entries()) {
|
|
1145
|
+
if (!(0, validation_js_1.isRecord)(entry) || !(0, validation_js_1.isRecord)(entry.upgradeVersionDrift)) {
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
const drift = entry.upgradeVersionDrift;
|
|
1149
|
+
const state = record.workspace.ownershipVersions.find((candidate) => (0, validation_js_1.isRecord)(candidate) &&
|
|
1150
|
+
candidate.kind === drift.kind &&
|
|
1151
|
+
candidate.target === drift.target);
|
|
1152
|
+
const frameworkDrift = (0, validation_js_1.isRecord)(state) &&
|
|
1153
|
+
typeof state.installedFrameworkVersion === 'string' &&
|
|
1154
|
+
typeof state.recordedFrameworkVersion === 'string' &&
|
|
1155
|
+
state.installedFrameworkVersion !== state.recordedFrameworkVersion;
|
|
1156
|
+
const blueprintDrift = (0, validation_js_1.isRecord)(state) &&
|
|
1157
|
+
typeof state.installedBlueprintVersion === 'string' &&
|
|
1158
|
+
typeof state.recordedBlueprintVersion === 'string' &&
|
|
1159
|
+
state.installedBlueprintVersion !== state.recordedBlueprintVersion;
|
|
1160
|
+
if (!frameworkDrift && !blueprintDrift) {
|
|
1161
|
+
addIssue(issues, `$.warnings[${index}].upgradeVersionDrift`, 'must identify one exact inspected installed/recorded version mismatch');
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
if (has(record, 'affected') &&
|
|
1167
|
+
(0, validation_js_1.isRecord)(record.affected) &&
|
|
1168
|
+
(0, validation_js_1.isRecord)(record.git)) {
|
|
1169
|
+
if (typeof record.git.baseCommit === 'string' &&
|
|
1170
|
+
record.affected.baseCommit !== record.git.baseCommit) {
|
|
1171
|
+
addIssue(issues, '$.affected.baseCommit', 'must agree with Git baseCommit');
|
|
1172
|
+
}
|
|
1173
|
+
if (typeof record.git.headCommit === 'string' &&
|
|
1174
|
+
record.affected.headCommit !== record.git.headCommit) {
|
|
1175
|
+
addIssue(issues, '$.affected.headCommit', 'must agree with Git headCommit');
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1179
|
+
}
|
|
1180
|
+
function validateGeneratedSurface(value, path, issues) {
|
|
1181
|
+
const record = requireRecord(value, path, ['ownershipMode', 'path'], [], issues);
|
|
1182
|
+
if (!record)
|
|
1183
|
+
return false;
|
|
1184
|
+
requireEnum(record.ownershipMode, `${path}.ownershipMode`, OWNERSHIP_MODE_SET, issues);
|
|
1185
|
+
requireSafeString(record.path, `${path}.path`, issues, {
|
|
1186
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1187
|
+
});
|
|
1188
|
+
return true;
|
|
1189
|
+
}
|
|
1190
|
+
function validateGeneratorPreviewChange(value, path, issues) {
|
|
1191
|
+
const record = requireRecord(value, path, ['change', 'ownershipMode', 'path'], ['contentDigest', 'mode'], issues);
|
|
1192
|
+
if (!record)
|
|
1193
|
+
return false;
|
|
1194
|
+
requireEnum(record.change, `${path}.change`, GENERATOR_PREVIEW_CHANGE_SET, issues);
|
|
1195
|
+
requireEnum(record.ownershipMode, `${path}.ownershipMode`, OWNERSHIP_MODE_SET, issues);
|
|
1196
|
+
requireSafeString(record.path, `${path}.path`, issues, {
|
|
1197
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1198
|
+
});
|
|
1199
|
+
if (record.change === 'delete') {
|
|
1200
|
+
if (has(record, 'contentDigest')) {
|
|
1201
|
+
addIssue(issues, `${path}.contentDigest`, 'must be absent for a deleted file');
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
else {
|
|
1205
|
+
requireSafeString(record.contentDigest, `${path}.contentDigest`, issues, {
|
|
1206
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
if (has(record, 'mode')) {
|
|
1210
|
+
requireSafeString(record.mode, `${path}.mode`, issues, {
|
|
1211
|
+
pattern: /^[0-7]{3,4}$/,
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
return true;
|
|
1215
|
+
}
|
|
1216
|
+
function validateGeneratorPreviewSource(value, path, issues) {
|
|
1217
|
+
const record = requireRecord(value, path, [
|
|
1218
|
+
'blueprintVersions',
|
|
1219
|
+
'commit',
|
|
1220
|
+
'frameworkVersion',
|
|
1221
|
+
'ownershipVersions',
|
|
1222
|
+
'workspace',
|
|
1223
|
+
], ['candidateProvenance'], issues);
|
|
1224
|
+
if (!record)
|
|
1225
|
+
return false;
|
|
1226
|
+
validateVersionRecords(record.blueprintVersions, `${path}.blueprintVersions`, issues);
|
|
1227
|
+
if (has(record, 'candidateProvenance')) {
|
|
1228
|
+
validateCandidateProvenance(record.candidateProvenance, `${path}.candidateProvenance`, issues);
|
|
1229
|
+
}
|
|
1230
|
+
requireSafeString(record.commit, `${path}.commit`, issues, {
|
|
1231
|
+
maximumLength: 64,
|
|
1232
|
+
pattern: COMMIT_PATTERN,
|
|
1233
|
+
});
|
|
1234
|
+
requireSafeString(record.frameworkVersion, `${path}.frameworkVersion`, issues);
|
|
1235
|
+
validateOwnershipVersionStates(record.ownershipVersions, `${path}.ownershipVersions`, issues);
|
|
1236
|
+
requireSafeString(record.workspace, `${path}.workspace`, issues, {
|
|
1237
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1238
|
+
});
|
|
1239
|
+
return true;
|
|
1240
|
+
}
|
|
1241
|
+
function validateDeveloperAgentGeneratorPreview(value) {
|
|
1242
|
+
const issues = [];
|
|
1243
|
+
validateSerializedBound(value, '$', model_js_1.DEVELOPER_AGENT_GENERATOR_PREVIEW_MAX_BYTES, issues);
|
|
1244
|
+
const record = requireRecord(value, '$', [
|
|
1245
|
+
'changes',
|
|
1246
|
+
'generatedSurfaces',
|
|
1247
|
+
'generator',
|
|
1248
|
+
'input',
|
|
1249
|
+
'kind',
|
|
1250
|
+
'operationId',
|
|
1251
|
+
'schemaVersion',
|
|
1252
|
+
'source',
|
|
1253
|
+
], [], issues);
|
|
1254
|
+
if (!record)
|
|
1255
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1256
|
+
if (record.kind !== model_js_1.DEVELOPER_AGENT_GENERATOR_PREVIEW_KIND) {
|
|
1257
|
+
addIssue(issues, '$.kind', `must equal ${model_js_1.DEVELOPER_AGENT_GENERATOR_PREVIEW_KIND}`);
|
|
1258
|
+
}
|
|
1259
|
+
if (record.schemaVersion !== model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION) {
|
|
1260
|
+
addIssue(issues, '$.schemaVersion', `must equal ${model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION}`);
|
|
1261
|
+
}
|
|
1262
|
+
if (record.generator !== 'upgrade') {
|
|
1263
|
+
addIssue(issues, '$.generator', 'must equal upgrade');
|
|
1264
|
+
}
|
|
1265
|
+
if (record.operationId !== 'generator:upgrade:preview') {
|
|
1266
|
+
addIssue(issues, '$.operationId', 'must equal generator:upgrade:preview');
|
|
1267
|
+
}
|
|
1268
|
+
const input = requireRecord(record.input, '$.input', ['generator', 'name'], [], issues);
|
|
1269
|
+
if (input) {
|
|
1270
|
+
if (input.generator !== 'upgrade') {
|
|
1271
|
+
addIssue(issues, '$.input.generator', 'must equal upgrade');
|
|
1272
|
+
}
|
|
1273
|
+
requireSafeString(input.name, '$.input.name', issues, {
|
|
1274
|
+
maximumLength: 63,
|
|
1275
|
+
pattern: /^[a-z0-9][a-z0-9-]*$/,
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
validateGeneratorPreviewSource(record.source, '$.source', issues);
|
|
1279
|
+
const changes = requireArray(record.changes, '$.changes', issues, MAX_GENERATED_SURFACES);
|
|
1280
|
+
const changePaths = new Set();
|
|
1281
|
+
let previousChangePath;
|
|
1282
|
+
changes?.forEach((entry, index) => {
|
|
1283
|
+
if (validateGeneratorPreviewChange(entry, `$.changes[${index}]`, issues)) {
|
|
1284
|
+
validateCanonicalWorkspacePath(entry.path, `$.changes[${index}].path`, issues);
|
|
1285
|
+
if (changePaths.has(entry.path)) {
|
|
1286
|
+
addIssue(issues, `$.changes[${index}].path`, 'must be unique');
|
|
1287
|
+
}
|
|
1288
|
+
if (previousChangePath !== undefined &&
|
|
1289
|
+
(0, ordering_js_1.compareDeveloperAgentStrings)(previousChangePath, entry.path) >= 0) {
|
|
1290
|
+
addIssue(issues, `$.changes[${index}].path`, 'must be in ascending canonical order');
|
|
1291
|
+
}
|
|
1292
|
+
changePaths.add(entry.path);
|
|
1293
|
+
previousChangePath = entry.path;
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
const surfaces = requireArray(record.generatedSurfaces, '$.generatedSurfaces', issues, MAX_GENERATED_SURFACES);
|
|
1297
|
+
const paths = new Set();
|
|
1298
|
+
let previousPath;
|
|
1299
|
+
surfaces?.forEach((entry, index) => {
|
|
1300
|
+
if (validateGeneratedSurface(entry, `$.generatedSurfaces[${index}]`, issues)) {
|
|
1301
|
+
validateCanonicalWorkspacePath(entry.path, `$.generatedSurfaces[${index}].path`, issues);
|
|
1302
|
+
if (paths.has(entry.path)) {
|
|
1303
|
+
addIssue(issues, `$.generatedSurfaces[${index}].path`, 'must be unique');
|
|
1304
|
+
}
|
|
1305
|
+
if (previousPath !== undefined &&
|
|
1306
|
+
(0, ordering_js_1.compareDeveloperAgentStrings)(previousPath, entry.path) >= 0) {
|
|
1307
|
+
addIssue(issues, `$.generatedSurfaces[${index}].path`, 'must be in ascending canonical order');
|
|
1308
|
+
}
|
|
1309
|
+
paths.add(entry.path);
|
|
1310
|
+
previousPath = entry.path;
|
|
1311
|
+
}
|
|
1312
|
+
});
|
|
1313
|
+
if (changes &&
|
|
1314
|
+
surfaces &&
|
|
1315
|
+
changes.every(validation_js_1.isRecord) &&
|
|
1316
|
+
surfaces.every(validation_js_1.isRecord) &&
|
|
1317
|
+
!(0, node_util_1.isDeepStrictEqual)(surfaces, changes.map(({ ownershipMode, path }) => ({ ownershipMode, path })))) {
|
|
1318
|
+
addIssue(issues, '$.generatedSurfaces', 'must exactly project the preview change paths and ownership modes');
|
|
1319
|
+
}
|
|
1320
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1321
|
+
}
|
|
1322
|
+
function validateDeveloperAgentGeneratorPreviewReceipt(value) {
|
|
1323
|
+
const issues = [];
|
|
1324
|
+
validateSerializedBound(value, '$', model_js_1.DEVELOPER_AGENT_GENERATOR_PREVIEW_RECEIPT_MAX_BYTES, issues);
|
|
1325
|
+
const record = requireRecord(value, '$', ['digest', 'kind', 'preview', 'reference', 'schemaVersion'], [], issues);
|
|
1326
|
+
if (!record)
|
|
1327
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1328
|
+
if (record.kind !== model_js_1.DEVELOPER_AGENT_GENERATOR_PREVIEW_RECEIPT_KIND) {
|
|
1329
|
+
addIssue(issues, '$.kind', `must equal ${model_js_1.DEVELOPER_AGENT_GENERATOR_PREVIEW_RECEIPT_KIND}`);
|
|
1330
|
+
}
|
|
1331
|
+
if (record.schemaVersion !== model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION) {
|
|
1332
|
+
addIssue(issues, '$.schemaVersion', `must equal ${model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION}`);
|
|
1333
|
+
}
|
|
1334
|
+
requireSafeString(record.digest, '$.digest', issues, {
|
|
1335
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
1336
|
+
});
|
|
1337
|
+
requireSafeString(record.reference, '$.reference', issues, {
|
|
1338
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1339
|
+
pattern: GENERATOR_PREVIEW_REFERENCE_PATTERN,
|
|
1340
|
+
});
|
|
1341
|
+
const previewValidation = validateDeveloperAgentGeneratorPreview(record.preview);
|
|
1342
|
+
if (!previewValidation.valid) {
|
|
1343
|
+
for (const issue of previewValidation.issues) {
|
|
1344
|
+
addIssue(issues, `$.preview${issue.path === '$' ? '' : issue.path.slice(1)}`, issue.message);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
else if (record.digest !==
|
|
1348
|
+
`sha256:${(0, node_crypto_1.createHash)('sha256')
|
|
1349
|
+
.update((0, canonical_json_1.canonicalJson)(previewValidation.value), 'utf8')
|
|
1350
|
+
.digest('hex')}`) {
|
|
1351
|
+
addIssue(issues, '$.digest', 'must bind the canonical preview bytes exactly');
|
|
1352
|
+
}
|
|
1353
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1354
|
+
}
|
|
1355
|
+
function validateInvocation(value, path, issues) {
|
|
1356
|
+
const record = requireRecord(value, path, ['command', 'owner'], [], issues);
|
|
1357
|
+
if (!record)
|
|
1358
|
+
return false;
|
|
1359
|
+
validateCommand(record.command, `${path}.command`, issues);
|
|
1360
|
+
requireEnum(record.owner, `${path}.owner`, OPERATION_OWNER_SET, issues);
|
|
1361
|
+
return true;
|
|
1362
|
+
}
|
|
1363
|
+
function validateApprovalPoint(value, path, issues) {
|
|
1364
|
+
const record = requireRecord(value, path, ['authority', 'description'], [], issues);
|
|
1365
|
+
if (!record)
|
|
1366
|
+
return false;
|
|
1367
|
+
requireEnum(record.authority, `${path}.authority`, AUTHORITY_SET, issues);
|
|
1368
|
+
requireSafeString(record.description, `${path}.description`, issues, {
|
|
1369
|
+
maximumLength: MAX_SUMMARY_LENGTH,
|
|
1370
|
+
});
|
|
1371
|
+
return true;
|
|
1372
|
+
}
|
|
1373
|
+
function validateRisk(value, path, issues) {
|
|
1374
|
+
const record = requireRecord(value, path, ['class', 'sanitizedSummary'], [], issues);
|
|
1375
|
+
if (!record)
|
|
1376
|
+
return false;
|
|
1377
|
+
requireEnum(record.class, `${path}.class`, RISK_CLASS_SET, issues);
|
|
1378
|
+
requireSafeString(record.sanitizedSummary, `${path}.sanitizedSummary`, issues, { maximumLength: MAX_SUMMARY_LENGTH });
|
|
1379
|
+
return true;
|
|
1380
|
+
}
|
|
1381
|
+
function validateDeveloperAgentPlan(value) {
|
|
1382
|
+
const issues = [];
|
|
1383
|
+
validateSerializedBound(value, '$', model_js_1.DEVELOPER_AGENT_PLAN_MAX_BYTES, issues);
|
|
1384
|
+
const record = requireRecord(value, '$', [
|
|
1385
|
+
'acceptanceCriteriaReference',
|
|
1386
|
+
'affectedContracts',
|
|
1387
|
+
'approvalPoints',
|
|
1388
|
+
'assumptions',
|
|
1389
|
+
'authority',
|
|
1390
|
+
'blockers',
|
|
1391
|
+
'cleanup',
|
|
1392
|
+
'evidenceClasses',
|
|
1393
|
+
'generatedSurfaces',
|
|
1394
|
+
'invocations',
|
|
1395
|
+
'kind',
|
|
1396
|
+
'nextSafeAction',
|
|
1397
|
+
'operation',
|
|
1398
|
+
'recovery',
|
|
1399
|
+
'requestedOutcome',
|
|
1400
|
+
'risks',
|
|
1401
|
+
'schemaVersion',
|
|
1402
|
+
'selectedFiles',
|
|
1403
|
+
'selectedProjects',
|
|
1404
|
+
'verification',
|
|
1405
|
+
], [], issues);
|
|
1406
|
+
if (!record)
|
|
1407
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1408
|
+
if (record.kind !== model_js_1.DEVELOPER_AGENT_PLAN_KIND) {
|
|
1409
|
+
addIssue(issues, '$.kind', `must equal ${model_js_1.DEVELOPER_AGENT_PLAN_KIND}`);
|
|
1410
|
+
}
|
|
1411
|
+
if (record.schemaVersion !== model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION) {
|
|
1412
|
+
addIssue(issues, '$.schemaVersion', `must equal ${model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION}`);
|
|
1413
|
+
}
|
|
1414
|
+
requireSafeString(record.acceptanceCriteriaReference, '$.acceptanceCriteriaReference', issues, { maximumLength: MAX_PATH_LENGTH });
|
|
1415
|
+
validateContractReferences(record.affectedContracts, '$.affectedContracts', issues);
|
|
1416
|
+
const approvalPoints = requireArray(record.approvalPoints, '$.approvalPoints', issues);
|
|
1417
|
+
approvalPoints?.forEach((entry, index) => validateApprovalPoint(entry, `$.approvalPoints[${index}]`, issues));
|
|
1418
|
+
validateStringArray(record.assumptions, '$.assumptions', issues, {
|
|
1419
|
+
maximumLength: MAX_SUMMARY_LENGTH,
|
|
1420
|
+
});
|
|
1421
|
+
requireEnum(record.authority, '$.authority', AUTHORITY_SET, issues);
|
|
1422
|
+
validateWarnings(record.blockers, '$.blockers', issues);
|
|
1423
|
+
validateCleanupRecovery(record.cleanup, '$.cleanup', issues);
|
|
1424
|
+
validateStringArray(record.evidenceClasses, '$.evidenceClasses', issues);
|
|
1425
|
+
const surfaces = requireArray(record.generatedSurfaces, '$.generatedSurfaces', issues, MAX_GENERATED_SURFACES);
|
|
1426
|
+
surfaces?.forEach((entry, index) => validateGeneratedSurface(entry, `$.generatedSurfaces[${index}]`, issues));
|
|
1427
|
+
const invocations = requireArray(record.invocations, '$.invocations', issues);
|
|
1428
|
+
invocations?.forEach((entry, index) => validateInvocation(entry, `$.invocations[${index}]`, issues));
|
|
1429
|
+
validateNextSafeAction(record.nextSafeAction, '$.nextSafeAction', issues);
|
|
1430
|
+
validateHandoffOperation(record.operation, '$.operation', issues);
|
|
1431
|
+
validateCleanupRecovery(record.recovery, '$.recovery', issues);
|
|
1432
|
+
requireSafeString(record.requestedOutcome, '$.requestedOutcome', issues, {
|
|
1433
|
+
maximumLength: MAX_SUMMARY_LENGTH,
|
|
1434
|
+
});
|
|
1435
|
+
const risks = requireArray(record.risks, '$.risks', issues);
|
|
1436
|
+
risks?.forEach((entry, index) => validateRisk(entry, `$.risks[${index}]`, issues));
|
|
1437
|
+
validateStringArray(record.selectedFiles, '$.selectedFiles', issues, {
|
|
1438
|
+
maximumItems: MAX_GENERATED_SURFACES,
|
|
1439
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1440
|
+
});
|
|
1441
|
+
if (Array.isArray(record.selectedFiles)) {
|
|
1442
|
+
record.selectedFiles.forEach((entry, index) => validateCanonicalWorkspacePath(entry, `$.selectedFiles[${index}]`, issues));
|
|
1443
|
+
}
|
|
1444
|
+
validateStringArray(record.selectedProjects, '$.selectedProjects', issues, {
|
|
1445
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1446
|
+
});
|
|
1447
|
+
validateStringArray(record.verification, '$.verification', issues);
|
|
1448
|
+
if ((0, validation_js_1.isRecord)(record.operation) && (0, validation_js_1.isRecord)(record.operation.scope)) {
|
|
1449
|
+
if (record.operation.authority !== record.authority) {
|
|
1450
|
+
addIssue(issues, '$.operation.authority', 'must equal the effective plan authority');
|
|
1451
|
+
}
|
|
1452
|
+
const sameStringSet = (left, right) => Array.isArray(left) &&
|
|
1453
|
+
Array.isArray(right) &&
|
|
1454
|
+
left.length === right.length &&
|
|
1455
|
+
[...left]
|
|
1456
|
+
.sort()
|
|
1457
|
+
.every((entry, index) => entry === [...right].sort()[index]);
|
|
1458
|
+
const contractIdentity = (value) => (0, validation_js_1.isRecord)(value)
|
|
1459
|
+
? `${String(value.class)}\u0000${String(value.reference)}`
|
|
1460
|
+
: '';
|
|
1461
|
+
if (!sameStringSet(record.operation.scope.projects, record.selectedProjects)) {
|
|
1462
|
+
addIssue(issues, '$.operation.scope.projects', 'must equal the effective selected project scope');
|
|
1463
|
+
}
|
|
1464
|
+
if (!sameStringSet(Array.isArray(record.operation.scope.contracts)
|
|
1465
|
+
? record.operation.scope.contracts.map(contractIdentity)
|
|
1466
|
+
: undefined, Array.isArray(record.affectedContracts)
|
|
1467
|
+
? record.affectedContracts.map(contractIdentity)
|
|
1468
|
+
: undefined)) {
|
|
1469
|
+
addIssue(issues, '$.operation.scope.contracts', 'must equal the effective affected contract scope');
|
|
1470
|
+
}
|
|
1471
|
+
if (!sameStringSet(record.operation.scope.evidenceClasses, record.evidenceClasses)) {
|
|
1472
|
+
addIssue(issues, '$.operation.scope.evidenceClasses', 'must equal the effective evidence scope');
|
|
1473
|
+
}
|
|
1474
|
+
const planVerification = Array.isArray(record.verification)
|
|
1475
|
+
? record.verification
|
|
1476
|
+
: [];
|
|
1477
|
+
if (Array.isArray(record.operation.scope.requiredVerification) &&
|
|
1478
|
+
record.operation.scope.requiredVerification.some((entry) => !planVerification.includes(entry))) {
|
|
1479
|
+
addIssue(issues, '$.operation.scope.requiredVerification', 'must be included in the complete plan verification set');
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
if ((0, validation_js_1.isRecord)(record.operation) &&
|
|
1483
|
+
(0, validation_js_1.isRecord)(record.nextSafeAction) &&
|
|
1484
|
+
Array.isArray(record.invocations) &&
|
|
1485
|
+
Array.isArray(record.blockers)) {
|
|
1486
|
+
const blocked = record.blockers.length > 0;
|
|
1487
|
+
const protectedOrDestructive = record.operation.authority === 'protected-mutate' ||
|
|
1488
|
+
record.operation.authority === 'destructive';
|
|
1489
|
+
const sourceEdit = record.operation.owner === 'source-edit';
|
|
1490
|
+
if (blocked) {
|
|
1491
|
+
if (record.nextSafeAction.authority !== 'read-only' ||
|
|
1492
|
+
has(record.nextSafeAction, 'command') ||
|
|
1493
|
+
has(record.nextSafeAction, 'operationId') ||
|
|
1494
|
+
has(record.nextSafeAction, 'owner')) {
|
|
1495
|
+
addIssue(issues, '$.nextSafeAction', 'a blocked plan must retain only a non-actionable read-only remediation');
|
|
1496
|
+
}
|
|
1497
|
+
if (record.invocations.length !== 0) {
|
|
1498
|
+
addIssue(issues, '$.invocations', 'a blocked plan must not retain an invocation');
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
else {
|
|
1502
|
+
if (record.nextSafeAction.authority !== record.operation.authority) {
|
|
1503
|
+
addIssue(issues, '$.nextSafeAction.authority', 'must equal the effective operation authority');
|
|
1504
|
+
}
|
|
1505
|
+
if (record.nextSafeAction.operationId !== record.operation.id) {
|
|
1506
|
+
addIssue(issues, '$.nextSafeAction.operationId', 'must equal the effective operation id');
|
|
1507
|
+
}
|
|
1508
|
+
if (record.nextSafeAction.owner !== record.operation.owner) {
|
|
1509
|
+
addIssue(issues, '$.nextSafeAction.owner', 'must equal the effective operation owner');
|
|
1510
|
+
}
|
|
1511
|
+
if (protectedOrDestructive || sourceEdit) {
|
|
1512
|
+
if (record.invocations.length !== 0) {
|
|
1513
|
+
addIssue(issues, '$.invocations', 'this authority boundary must not retain a local invocation');
|
|
1514
|
+
}
|
|
1515
|
+
if (has(record.nextSafeAction, 'command')) {
|
|
1516
|
+
addIssue(issues, '$.nextSafeAction.command', 'this authority boundary must not retain executable argv');
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
else {
|
|
1520
|
+
if (record.invocations.length !== 1) {
|
|
1521
|
+
addIssue(issues, '$.invocations', 'an executable local plan must retain exactly one owning-tool invocation');
|
|
1522
|
+
}
|
|
1523
|
+
else {
|
|
1524
|
+
const invocation = record.invocations[0];
|
|
1525
|
+
if (!(0, validation_js_1.isRecord)(invocation) ||
|
|
1526
|
+
invocation.owner !== record.operation.owner) {
|
|
1527
|
+
addIssue(issues, '$.invocations[0].owner', 'must equal the effective operation owner');
|
|
1528
|
+
}
|
|
1529
|
+
if (!(0, validation_js_1.isRecord)(invocation) ||
|
|
1530
|
+
!has(record.nextSafeAction, 'command') ||
|
|
1531
|
+
!(0, node_util_1.isDeepStrictEqual)(record.nextSafeAction.command, invocation.command)) {
|
|
1532
|
+
addIssue(issues, '$.nextSafeAction.command', 'must equal the sole owning-tool invocation command');
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
if (Array.isArray(record.generatedSurfaces) &&
|
|
1539
|
+
Array.isArray(record.selectedFiles)) {
|
|
1540
|
+
const surfacePaths = record.generatedSurfaces.map((surface) => (0, validation_js_1.isRecord)(surface) && typeof surface.path === 'string'
|
|
1541
|
+
? surface.path
|
|
1542
|
+
: undefined);
|
|
1543
|
+
if (surfacePaths.length !== record.selectedFiles.length ||
|
|
1544
|
+
surfacePaths.some((surfacePath, index) => surfacePath !== record.selectedFiles[index])) {
|
|
1545
|
+
addIssue(issues, '$.generatedSurfaces', 'must be derived in order from selectedFiles');
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
if ((record.authority === 'protected-mutate' ||
|
|
1549
|
+
record.authority === 'destructive') &&
|
|
1550
|
+
Array.isArray(record.approvalPoints) &&
|
|
1551
|
+
record.approvalPoints.length === 0) {
|
|
1552
|
+
addIssue(issues, '$.approvalPoints', 'must identify an approval point for protected or destructive work');
|
|
1553
|
+
}
|
|
1554
|
+
if ((record.authority === 'protected-mutate' ||
|
|
1555
|
+
record.authority === 'destructive') &&
|
|
1556
|
+
Array.isArray(record.invocations) &&
|
|
1557
|
+
record.invocations.length > 0) {
|
|
1558
|
+
addIssue(issues, '$.invocations', 'must not materialize local argv for protected or destructive work');
|
|
1559
|
+
}
|
|
1560
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1561
|
+
}
|
|
1562
|
+
function validateSourceIdentity(value, path, issues) {
|
|
1563
|
+
const record = requireRecord(value, path, ['commit', 'worktree'], [], issues);
|
|
1564
|
+
if (!record)
|
|
1565
|
+
return false;
|
|
1566
|
+
requireSafeString(record.commit, `${path}.commit`, issues, {
|
|
1567
|
+
maximumLength: 64,
|
|
1568
|
+
pattern: COMMIT_PATTERN,
|
|
1569
|
+
});
|
|
1570
|
+
requireSafeString(record.worktree, `${path}.worktree`, issues, {
|
|
1571
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1572
|
+
});
|
|
1573
|
+
return true;
|
|
1574
|
+
}
|
|
1575
|
+
function validateToolIdentity(value, path, issues) {
|
|
1576
|
+
const record = requireRecord(value, path, ['contractVersion', 'name', 'version'], [], issues);
|
|
1577
|
+
if (!record)
|
|
1578
|
+
return false;
|
|
1579
|
+
if (record.contractVersion !== model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION) {
|
|
1580
|
+
addIssue(issues, `${path}.contractVersion`, `must equal ${model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION}`);
|
|
1581
|
+
}
|
|
1582
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
1583
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1584
|
+
});
|
|
1585
|
+
requireSafeString(record.version, `${path}.version`, issues);
|
|
1586
|
+
return true;
|
|
1587
|
+
}
|
|
1588
|
+
function validateNormalizedInput(value, path, issues) {
|
|
1589
|
+
const record = requireRecord(value, path, ['name', 'value'], [], issues);
|
|
1590
|
+
if (!record)
|
|
1591
|
+
return false;
|
|
1592
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
1593
|
+
pattern: FIELD_NAME_PATTERN,
|
|
1594
|
+
});
|
|
1595
|
+
requireSafeString(record.value, `${path}.value`, issues, {
|
|
1596
|
+
maximumLength: MAX_INPUT_VALUE_LENGTH,
|
|
1597
|
+
});
|
|
1598
|
+
return true;
|
|
1599
|
+
}
|
|
1600
|
+
function validateOperationIdentity(value, path, issues) {
|
|
1601
|
+
const record = requireRecord(value, path, ['name', 'normalizedInputs'], [], issues);
|
|
1602
|
+
if (!record)
|
|
1603
|
+
return false;
|
|
1604
|
+
requireSafeString(record.name, `${path}.name`, issues, {
|
|
1605
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1606
|
+
});
|
|
1607
|
+
const entries = requireArray(record.normalizedInputs, `${path}.normalizedInputs`, issues);
|
|
1608
|
+
const names = new Set();
|
|
1609
|
+
entries?.forEach((entry, index) => {
|
|
1610
|
+
if (validateNormalizedInput(entry, `${path}.normalizedInputs[${index}]`, issues)) {
|
|
1611
|
+
const name = entry.name;
|
|
1612
|
+
if (names.has(name)) {
|
|
1613
|
+
addIssue(issues, `${path}.normalizedInputs[${index}].name`, 'must be unique');
|
|
1614
|
+
}
|
|
1615
|
+
names.add(name);
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
return true;
|
|
1619
|
+
}
|
|
1620
|
+
function validateAffectedResult(value, path, issues) {
|
|
1621
|
+
const record = requireRecord(value, path, ['contracts', 'projects'], [], issues);
|
|
1622
|
+
if (!record)
|
|
1623
|
+
return false;
|
|
1624
|
+
validateContractReferences(record.contracts, `${path}.contracts`, issues);
|
|
1625
|
+
validateStringArray(record.projects, `${path}.projects`, issues, {
|
|
1626
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1627
|
+
});
|
|
1628
|
+
return true;
|
|
1629
|
+
}
|
|
1630
|
+
function validateChangeSet(value, path, issues) {
|
|
1631
|
+
const record = requireRecord(value, path, ['externalResources', 'files'], [], issues);
|
|
1632
|
+
if (!record)
|
|
1633
|
+
return false;
|
|
1634
|
+
validateStringArray(record.externalResources, `${path}.externalResources`, issues, { maximumLength: MAX_PATH_LENGTH });
|
|
1635
|
+
validateStringArray(record.files, `${path}.files`, issues, {
|
|
1636
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1637
|
+
});
|
|
1638
|
+
if (Array.isArray(record.files)) {
|
|
1639
|
+
record.files.forEach((entry, index) => validateCanonicalWorkspacePath(entry, `${path}.files[${index}]`, issues));
|
|
1640
|
+
}
|
|
1641
|
+
return true;
|
|
1642
|
+
}
|
|
1643
|
+
function validateVerificationSummary(value, path, issues) {
|
|
1644
|
+
const record = requireRecord(value, path, ['executed', 'omitted'], [], issues);
|
|
1645
|
+
if (!record)
|
|
1646
|
+
return false;
|
|
1647
|
+
validateStringArray(record.executed, `${path}.executed`, issues);
|
|
1648
|
+
validateStringArray(record.omitted, `${path}.omitted`, issues);
|
|
1649
|
+
if (Array.isArray(record.executed) && Array.isArray(record.omitted)) {
|
|
1650
|
+
const executed = new Set(record.executed);
|
|
1651
|
+
record.omitted.forEach((entry, index) => {
|
|
1652
|
+
if (executed.has(entry)) {
|
|
1653
|
+
addIssue(issues, `${path}.omitted[${index}]`, 'must not also be recorded as executed');
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
1656
|
+
}
|
|
1657
|
+
return true;
|
|
1658
|
+
}
|
|
1659
|
+
function validateTestingEvidenceComposition(value, path, issues) {
|
|
1660
|
+
const record = requireRecord(value, path, ['digest', 'reference', 'result', 'schemaVersion'], [], issues);
|
|
1661
|
+
if (!record)
|
|
1662
|
+
return false;
|
|
1663
|
+
requireSafeString(record.digest, `${path}.digest`, issues, {
|
|
1664
|
+
maximumLength: 71,
|
|
1665
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
1666
|
+
});
|
|
1667
|
+
validateCanonicalWorkspacePath(record.reference, `${path}.reference`, issues);
|
|
1668
|
+
if (record.schemaVersion !== index_js_1.TESTING_EVIDENCE_RESULT_SCHEMA_VERSION) {
|
|
1669
|
+
addIssue(issues, `${path}.schemaVersion`, `must equal consumed Testing/Evidence revision ${index_js_1.TESTING_EVIDENCE_RESULT_SCHEMA_VERSION}`);
|
|
1670
|
+
}
|
|
1671
|
+
const result = (0, index_js_1.validateTestingEvidenceResult)(record.result);
|
|
1672
|
+
if (!result.valid) {
|
|
1673
|
+
result.issues.forEach((issue) => addIssue(issues, `${path}.result${issue.path === 'result' ? '' : issue.path.replace(/^result/, '')}`, issue.message));
|
|
1674
|
+
}
|
|
1675
|
+
return true;
|
|
1676
|
+
}
|
|
1677
|
+
function validateUnresolvedState(value, path, issues) {
|
|
1678
|
+
const record = requireRecord(value, path, ['approvalNeeds', 'assumptions', 'conflicts', 'markers'], [], issues);
|
|
1679
|
+
if (!record)
|
|
1680
|
+
return false;
|
|
1681
|
+
for (const property of [
|
|
1682
|
+
'approvalNeeds',
|
|
1683
|
+
'assumptions',
|
|
1684
|
+
'conflicts',
|
|
1685
|
+
'markers',
|
|
1686
|
+
]) {
|
|
1687
|
+
validateStringArray(record[property], `${path}.${property}`, issues, {
|
|
1688
|
+
maximumLength: MAX_SUMMARY_LENGTH,
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1691
|
+
return true;
|
|
1692
|
+
}
|
|
1693
|
+
function validateResultCoherence(record, path, issues) {
|
|
1694
|
+
const outcome = record.outcome;
|
|
1695
|
+
const classification = record.failureClassification;
|
|
1696
|
+
const changes = (0, validation_js_1.isRecord)(record.changes) ? record.changes : undefined;
|
|
1697
|
+
const cleanup = (0, validation_js_1.isRecord)(record.cleanup) ? record.cleanup : undefined;
|
|
1698
|
+
const recovery = (0, validation_js_1.isRecord)(record.recovery) ? record.recovery : undefined;
|
|
1699
|
+
const verification = (0, validation_js_1.isRecord)(record.verification)
|
|
1700
|
+
? record.verification
|
|
1701
|
+
: undefined;
|
|
1702
|
+
if (outcome === 'succeeded' && classification !== undefined) {
|
|
1703
|
+
addIssue(issues, `${path}.failureClassification`, 'must be omitted for a succeeded result');
|
|
1704
|
+
}
|
|
1705
|
+
if ((outcome === 'blocked' || outcome === 'failed') &&
|
|
1706
|
+
classification === undefined) {
|
|
1707
|
+
addIssue(issues, `${path}.failureClassification`, `is required for a ${outcome} result`);
|
|
1708
|
+
}
|
|
1709
|
+
if (typeof classification === 'string' &&
|
|
1710
|
+
BLOCKING_FAILURES.has(classification) &&
|
|
1711
|
+
outcome !== 'blocked') {
|
|
1712
|
+
addIssue(issues, `${path}.outcome`, `must be blocked for ${classification}`);
|
|
1713
|
+
}
|
|
1714
|
+
if (typeof classification === 'string' &&
|
|
1715
|
+
FAILED_FAILURES.has(classification) &&
|
|
1716
|
+
outcome !== 'failed') {
|
|
1717
|
+
addIssue(issues, `${path}.outcome`, `must be failed for ${classification}`);
|
|
1718
|
+
}
|
|
1719
|
+
if (classification === 'external-proof-pending' && outcome !== 'incomplete') {
|
|
1720
|
+
addIssue(issues, `${path}.outcome`, 'must be incomplete while external proof is pending');
|
|
1721
|
+
}
|
|
1722
|
+
if (classification === 'external-proof-pending' &&
|
|
1723
|
+
(!verification ||
|
|
1724
|
+
!Array.isArray(verification.omitted) ||
|
|
1725
|
+
verification.omitted.length === 0)) {
|
|
1726
|
+
addIssue(issues, `${path}.verification.omitted`, 'must identify the pending external proof');
|
|
1727
|
+
}
|
|
1728
|
+
if (classification === 'cleanup-incomplete' &&
|
|
1729
|
+
cleanup?.outcome !== 'incomplete' &&
|
|
1730
|
+
recovery?.outcome !== 'incomplete') {
|
|
1731
|
+
addIssue(issues, `${path}.cleanup`, 'or recovery must be incomplete for cleanup-incomplete');
|
|
1732
|
+
}
|
|
1733
|
+
if (outcome === 'succeeded' &&
|
|
1734
|
+
(cleanup?.outcome === 'incomplete' || recovery?.outcome === 'incomplete')) {
|
|
1735
|
+
addIssue(issues, `${path}.outcome`, 'cannot succeed with incomplete cleanup or recovery');
|
|
1736
|
+
}
|
|
1737
|
+
if (outcome === 'blocked' &&
|
|
1738
|
+
changes &&
|
|
1739
|
+
((Array.isArray(changes.files) && changes.files.length > 0) ||
|
|
1740
|
+
(Array.isArray(changes.externalResources) &&
|
|
1741
|
+
changes.externalResources.length > 0))) {
|
|
1742
|
+
addIssue(issues, `${path}.changes`, 'must be empty when blocked before mutation');
|
|
1743
|
+
}
|
|
1744
|
+
if (outcome === 'incomplete' &&
|
|
1745
|
+
classification === undefined &&
|
|
1746
|
+
changes &&
|
|
1747
|
+
((Array.isArray(changes.files) && changes.files.length > 0) ||
|
|
1748
|
+
(Array.isArray(changes.externalResources) &&
|
|
1749
|
+
changes.externalResources.length > 0))) {
|
|
1750
|
+
addIssue(issues, `${path}.failureClassification`, 'is required when incomplete work changed state');
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
function validateDeveloperAgentResult(value) {
|
|
1754
|
+
const issues = [];
|
|
1755
|
+
validateSerializedBound(value, '$', model_js_1.DEVELOPER_AGENT_RESULT_MAX_BYTES, issues);
|
|
1756
|
+
const record = requireRecord(value, '$', [
|
|
1757
|
+
'affected',
|
|
1758
|
+
'artifacts',
|
|
1759
|
+
'changes',
|
|
1760
|
+
'cleanup',
|
|
1761
|
+
'kind',
|
|
1762
|
+
'nextSafeAction',
|
|
1763
|
+
'operation',
|
|
1764
|
+
'outcome',
|
|
1765
|
+
'recovery',
|
|
1766
|
+
'schemaVersion',
|
|
1767
|
+
'source',
|
|
1768
|
+
'tool',
|
|
1769
|
+
'unresolved',
|
|
1770
|
+
'verification',
|
|
1771
|
+
], ['failureClassification', 'testingEvidence'], issues);
|
|
1772
|
+
if (!record)
|
|
1773
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1774
|
+
if (record.kind !== model_js_1.DEVELOPER_AGENT_RESULT_KIND) {
|
|
1775
|
+
addIssue(issues, '$.kind', `must equal ${model_js_1.DEVELOPER_AGENT_RESULT_KIND}`);
|
|
1776
|
+
}
|
|
1777
|
+
if (record.schemaVersion !== model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION) {
|
|
1778
|
+
addIssue(issues, '$.schemaVersion', `must equal ${model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION}`);
|
|
1779
|
+
}
|
|
1780
|
+
validateAffectedResult(record.affected, '$.affected', issues);
|
|
1781
|
+
validateArtifacts(record.artifacts, '$.artifacts', issues);
|
|
1782
|
+
validateChangeSet(record.changes, '$.changes', issues);
|
|
1783
|
+
validateCleanupRecovery(record.cleanup, '$.cleanup', issues);
|
|
1784
|
+
if (has(record, 'failureClassification')) {
|
|
1785
|
+
requireEnum(record.failureClassification, '$.failureClassification', FAILURE_SET, issues);
|
|
1786
|
+
}
|
|
1787
|
+
validateNextSafeAction(record.nextSafeAction, '$.nextSafeAction', issues);
|
|
1788
|
+
validateOperationIdentity(record.operation, '$.operation', issues);
|
|
1789
|
+
requireEnum(record.outcome, '$.outcome', RESULT_OUTCOME_SET, issues);
|
|
1790
|
+
validateCleanupRecovery(record.recovery, '$.recovery', issues);
|
|
1791
|
+
validateSourceIdentity(record.source, '$.source', issues);
|
|
1792
|
+
if (has(record, 'testingEvidence')) {
|
|
1793
|
+
validateTestingEvidenceComposition(record.testingEvidence, '$.testingEvidence', issues);
|
|
1794
|
+
}
|
|
1795
|
+
validateToolIdentity(record.tool, '$.tool', issues);
|
|
1796
|
+
validateUnresolvedState(record.unresolved, '$.unresolved', issues);
|
|
1797
|
+
validateVerificationSummary(record.verification, '$.verification', issues);
|
|
1798
|
+
validateResultCoherence(record, '$', issues);
|
|
1799
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
1800
|
+
}
|
|
1801
|
+
function validateHandoffWork(value, path, issues) {
|
|
1802
|
+
const record = requireRecord(value, path, ['acceptanceCriteriaRevision', 'reference'], [], issues);
|
|
1803
|
+
if (!record)
|
|
1804
|
+
return false;
|
|
1805
|
+
requireSafeString(record.acceptanceCriteriaRevision, `${path}.acceptanceCriteriaRevision`, issues, { maximumLength: MAX_PATH_LENGTH });
|
|
1806
|
+
requireSafeString(record.reference, `${path}.reference`, issues, {
|
|
1807
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1808
|
+
});
|
|
1809
|
+
return true;
|
|
1810
|
+
}
|
|
1811
|
+
function validateHandoffRepository(value, path, issues) {
|
|
1812
|
+
const record = requireRecord(value, path, ['baseCommit', 'baseRef', 'branch', 'headCommit', 'identity', 'worktree'], [], issues);
|
|
1813
|
+
if (!record)
|
|
1814
|
+
return false;
|
|
1815
|
+
for (const property of ['baseCommit', 'headCommit']) {
|
|
1816
|
+
requireSafeString(record[property], `${path}.${property}`, issues, {
|
|
1817
|
+
maximumLength: 64,
|
|
1818
|
+
pattern: COMMIT_PATTERN,
|
|
1819
|
+
});
|
|
1820
|
+
}
|
|
1821
|
+
requireSafeString(record.baseRef, `${path}.baseRef`, issues, {
|
|
1822
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1823
|
+
});
|
|
1824
|
+
requireSafeString(record.branch, `${path}.branch`, issues, {
|
|
1825
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1826
|
+
});
|
|
1827
|
+
requireSafeString(record.identity, `${path}.identity`, issues, {
|
|
1828
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1829
|
+
});
|
|
1830
|
+
requireSafeString(record.worktree, `${path}.worktree`, issues, {
|
|
1831
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1832
|
+
});
|
|
1833
|
+
return true;
|
|
1834
|
+
}
|
|
1835
|
+
function validateHandoffVersions(value, path, issues) {
|
|
1836
|
+
const record = requireRecord(value, path, [
|
|
1837
|
+
'blueprintVersions',
|
|
1838
|
+
'canonicalStage',
|
|
1839
|
+
'effectivePolicyDigest',
|
|
1840
|
+
'frameworkVersion',
|
|
1841
|
+
'policyReferences',
|
|
1842
|
+
], ['candidateEvidenceReference'], issues);
|
|
1843
|
+
if (!record)
|
|
1844
|
+
return false;
|
|
1845
|
+
validateVersionRecords(record.blueprintVersions, `${path}.blueprintVersions`, issues);
|
|
1846
|
+
requireEnum(record.canonicalStage, `${path}.canonicalStage`, CANONICAL_STAGE_SET, issues);
|
|
1847
|
+
requireSafeString(record.effectivePolicyDigest, `${path}.effectivePolicyDigest`, issues, {
|
|
1848
|
+
maximumLength: 71,
|
|
1849
|
+
pattern: SHA256_DIGEST_PATTERN,
|
|
1850
|
+
});
|
|
1851
|
+
requireSafeString(record.frameworkVersion, `${path}.frameworkVersion`, issues);
|
|
1852
|
+
validateStringArray(record.policyReferences, `${path}.policyReferences`, issues, { maximumLength: MAX_PATH_LENGTH });
|
|
1853
|
+
if (has(record, 'candidateEvidenceReference')) {
|
|
1854
|
+
validateCandidateProvenance(record.candidateEvidenceReference, `${path}.candidateEvidenceReference`, issues);
|
|
1855
|
+
if (!(0, validation_js_1.isRecord)(record.candidateEvidenceReference) ||
|
|
1856
|
+
typeof record.candidateEvidenceReference.digest !== 'string') {
|
|
1857
|
+
addIssue(issues, `${path}.candidateEvidenceReference.digest`, 'is required for a resumable candidate reference');
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
return true;
|
|
1861
|
+
}
|
|
1862
|
+
function validateHandoffSelection(value, path, issues) {
|
|
1863
|
+
const record = requireRecord(value, path, ['affectedTargets', 'projects'], ['feature', 'slice'], issues);
|
|
1864
|
+
if (!record)
|
|
1865
|
+
return false;
|
|
1866
|
+
validateStringArray(record.affectedTargets, `${path}.affectedTargets`, issues, { pattern: IDENTIFIER_PATTERN });
|
|
1867
|
+
validateStringArray(record.projects, `${path}.projects`, issues, {
|
|
1868
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1869
|
+
});
|
|
1870
|
+
if (has(record, 'slice')) {
|
|
1871
|
+
requireSafeString(record.slice, `${path}.slice`, issues, {
|
|
1872
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
if (has(record, 'feature')) {
|
|
1876
|
+
requireSafeString(record.feature, `${path}.feature`, issues, {
|
|
1877
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1878
|
+
});
|
|
1879
|
+
if (!has(record, 'slice')) {
|
|
1880
|
+
addIssue(issues, `${path}.feature`, 'requires a selected Slice');
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
if (typeof record.slice === 'string' &&
|
|
1884
|
+
Array.isArray(record.projects) &&
|
|
1885
|
+
!record.projects.includes(record.slice)) {
|
|
1886
|
+
addIssue(issues, `${path}.slice`, 'must be included in the selected projects');
|
|
1887
|
+
}
|
|
1888
|
+
return true;
|
|
1889
|
+
}
|
|
1890
|
+
function validateHandoffOperation(value, path, issues) {
|
|
1891
|
+
const record = requireRecord(value, path, ['authority', 'id', 'owner', 'scope'], ['generatorInput'], issues);
|
|
1892
|
+
if (!record)
|
|
1893
|
+
return false;
|
|
1894
|
+
requireEnum(record.authority, `${path}.authority`, AUTHORITY_SET, issues);
|
|
1895
|
+
requireSafeString(record.id, `${path}.id`, issues, {
|
|
1896
|
+
maximumLength: MAX_IDENTIFIER_LENGTH,
|
|
1897
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1898
|
+
});
|
|
1899
|
+
requireEnum(record.owner, `${path}.owner`, OPERATION_OWNER_SET, issues);
|
|
1900
|
+
if (record.owner === 'nx-generator') {
|
|
1901
|
+
if (!has(record, 'generatorInput')) {
|
|
1902
|
+
addIssue(issues, `${path}.generatorInput`, 'is required to rebind a completed typed generator scope');
|
|
1903
|
+
}
|
|
1904
|
+
else if (validateGeneratorInput(record.generatorInput, `${path}.generatorInput`, issues) &&
|
|
1905
|
+
(0, validation_js_1.isRecord)(record.generatorInput) &&
|
|
1906
|
+
typeof record.generatorInput.generator === 'string' &&
|
|
1907
|
+
typeof record.id === 'string') {
|
|
1908
|
+
const previewId = `generator:${record.generatorInput.generator}:preview`;
|
|
1909
|
+
const applyId = `generator:${record.generatorInput.generator}:apply`;
|
|
1910
|
+
if (record.id !== previewId && record.id !== applyId) {
|
|
1911
|
+
addIssue(issues, `${path}.generatorInput.generator`, 'must exactly match the retained generator operation id');
|
|
1912
|
+
}
|
|
1913
|
+
if (record.generatorInput.generator === 'upgrade') {
|
|
1914
|
+
const hasPreview = has(record.generatorInput, 'preview');
|
|
1915
|
+
if (record.id === previewId && hasPreview) {
|
|
1916
|
+
addIssue(issues, `${path}.generatorInput.preview`, 'must be absent for a completed Upgrade preview operation');
|
|
1917
|
+
}
|
|
1918
|
+
if (record.id === applyId && !hasPreview) {
|
|
1919
|
+
addIssue(issues, `${path}.generatorInput.preview`, 'is required to bind a completed Upgrade apply operation');
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
else if (has(record, 'generatorInput')) {
|
|
1925
|
+
addIssue(issues, `${path}.generatorInput`, 'is valid only for a typed Nx generator operation');
|
|
1926
|
+
}
|
|
1927
|
+
const scope = requireRecord(record.scope, `${path}.scope`, ['contracts', 'evidenceClasses', 'projects', 'requiredVerification'], [], issues);
|
|
1928
|
+
if (scope) {
|
|
1929
|
+
validateContractReferences(scope.contracts, `${path}.scope.contracts`, issues);
|
|
1930
|
+
validateStringArray(scope.evidenceClasses, `${path}.scope.evidenceClasses`, issues);
|
|
1931
|
+
validateStringArray(scope.projects, `${path}.scope.projects`, issues, {
|
|
1932
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1933
|
+
});
|
|
1934
|
+
validateStringArray(scope.requiredVerification, `${path}.scope.requiredVerification`, issues);
|
|
1935
|
+
}
|
|
1936
|
+
return true;
|
|
1937
|
+
}
|
|
1938
|
+
function validateHandoffMarkerSnapshot(value, path, issues) {
|
|
1939
|
+
const record = requireRecord(value, path, ['blocking', 'reference'], [], issues);
|
|
1940
|
+
if (!record)
|
|
1941
|
+
return false;
|
|
1942
|
+
requireBoolean(record.blocking, `${path}.blocking`, issues);
|
|
1943
|
+
requireSafeString(record.reference, `${path}.reference`, issues, {
|
|
1944
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1945
|
+
});
|
|
1946
|
+
return true;
|
|
1947
|
+
}
|
|
1948
|
+
function validateExternalState(value, path, issues) {
|
|
1949
|
+
const record = requireRecord(value, path, ['cleanupOperationId', 'cleanupOwner', 'reference'], [], issues);
|
|
1950
|
+
if (!record)
|
|
1951
|
+
return false;
|
|
1952
|
+
requireSafeString(record.cleanupOperationId, `${path}.cleanupOperationId`, issues, {
|
|
1953
|
+
maximumLength: MAX_IDENTIFIER_LENGTH,
|
|
1954
|
+
pattern: IDENTIFIER_PATTERN,
|
|
1955
|
+
});
|
|
1956
|
+
requireEnum(record.cleanupOwner, `${path}.cleanupOwner`, OPERATION_OWNER_SET, issues);
|
|
1957
|
+
requireSafeString(record.reference, `${path}.reference`, issues, {
|
|
1958
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
1959
|
+
});
|
|
1960
|
+
return true;
|
|
1961
|
+
}
|
|
1962
|
+
function nestedResultIssues(value, path, issues) {
|
|
1963
|
+
const result = validateDeveloperAgentResult(value);
|
|
1964
|
+
if (result.valid)
|
|
1965
|
+
return true;
|
|
1966
|
+
result.issues.forEach((issue) => {
|
|
1967
|
+
addIssue(issues, issue.path === '$' ? path : `${path}${issue.path.replace(/^\$/, '')}`, issue.message);
|
|
1968
|
+
});
|
|
1969
|
+
return false;
|
|
1970
|
+
}
|
|
1971
|
+
function validateHandoffCoherence(record, issues) {
|
|
1972
|
+
const state = record.state;
|
|
1973
|
+
const results = Array.isArray(record.results)
|
|
1974
|
+
? record.results.filter(validation_js_1.isRecord)
|
|
1975
|
+
: [];
|
|
1976
|
+
const changedFiles = Array.isArray(record.changedFiles)
|
|
1977
|
+
? record.changedFiles
|
|
1978
|
+
: [];
|
|
1979
|
+
const changedContracts = Array.isArray(record.changedContracts)
|
|
1980
|
+
? record.changedContracts
|
|
1981
|
+
: [];
|
|
1982
|
+
const externalState = Array.isArray(record.externalState)
|
|
1983
|
+
? record.externalState
|
|
1984
|
+
: [];
|
|
1985
|
+
const pending = Array.isArray(record.requiredVerificationPending)
|
|
1986
|
+
? record.requiredVerificationPending
|
|
1987
|
+
: [];
|
|
1988
|
+
const requiredVerification = Array.isArray(record.requiredVerification)
|
|
1989
|
+
? record.requiredVerification
|
|
1990
|
+
: [];
|
|
1991
|
+
const requiredEvidence = Array.isArray(record.requiredEvidence)
|
|
1992
|
+
? record.requiredEvidence
|
|
1993
|
+
: [];
|
|
1994
|
+
const requiredEvidencePending = Array.isArray(record.requiredEvidencePending)
|
|
1995
|
+
? record.requiredEvidencePending
|
|
1996
|
+
: [];
|
|
1997
|
+
const markerSnapshot = Array.isArray(record.markerSnapshot)
|
|
1998
|
+
? record.markerSnapshot.filter(validation_js_1.isRecord)
|
|
1999
|
+
: [];
|
|
2000
|
+
const operations = Array.isArray(record.operations)
|
|
2001
|
+
? record.operations.filter(validation_js_1.isRecord)
|
|
2002
|
+
: [];
|
|
2003
|
+
const cleanup = (0, validation_js_1.isRecord)(record.cleanup) ? record.cleanup : undefined;
|
|
2004
|
+
const recovery = (0, validation_js_1.isRecord)(record.recovery) ? record.recovery : undefined;
|
|
2005
|
+
const unresolved = (0, validation_js_1.isRecord)(record.unresolved)
|
|
2006
|
+
? record.unresolved
|
|
2007
|
+
: undefined;
|
|
2008
|
+
const repository = (0, validation_js_1.isRecord)(record.repository)
|
|
2009
|
+
? record.repository
|
|
2010
|
+
: undefined;
|
|
2011
|
+
const selection = (0, validation_js_1.isRecord)(record.selection) ? record.selection : undefined;
|
|
2012
|
+
const nextSafeAction = (0, validation_js_1.isRecord)(record.nextSafeAction)
|
|
2013
|
+
? record.nextSafeAction
|
|
2014
|
+
: undefined;
|
|
2015
|
+
if (nextSafeAction && has(nextSafeAction, 'command')) {
|
|
2016
|
+
addIssue(issues, '$.nextSafeAction.command', 'handoffs retain an operation identity, never executable argv');
|
|
2017
|
+
}
|
|
2018
|
+
if (nextSafeAction &&
|
|
2019
|
+
(nextSafeAction.owner === 'nx-generator' ||
|
|
2020
|
+
(typeof nextSafeAction.operationId === 'string' &&
|
|
2021
|
+
nextSafeAction.operationId.startsWith('generator:')))) {
|
|
2022
|
+
addIssue(issues, '$.nextSafeAction', 'typed generator operations are not resumable because handoffs retain neither typed inputs nor preview references');
|
|
2023
|
+
}
|
|
2024
|
+
results.forEach((result, index) => {
|
|
2025
|
+
const resultNextSafeAction = (0, validation_js_1.isRecord)(result.nextSafeAction)
|
|
2026
|
+
? result.nextSafeAction
|
|
2027
|
+
: undefined;
|
|
2028
|
+
if (resultNextSafeAction && has(resultNextSafeAction, 'command')) {
|
|
2029
|
+
addIssue(issues, `$.results[${index}].nextSafeAction.command`, 'handoffs retain nested operation identity, never executable argv');
|
|
2030
|
+
}
|
|
2031
|
+
if (resultNextSafeAction &&
|
|
2032
|
+
(resultNextSafeAction.owner === 'nx-generator' ||
|
|
2033
|
+
(typeof resultNextSafeAction.operationId === 'string' &&
|
|
2034
|
+
resultNextSafeAction.operationId.startsWith('generator:')))) {
|
|
2035
|
+
addIssue(issues, `$.results[${index}].nextSafeAction`, 'typed generator operations are not resumable from a retained result');
|
|
2036
|
+
}
|
|
2037
|
+
const operation = (0, validation_js_1.isRecord)(result.operation) ? result.operation : undefined;
|
|
2038
|
+
if (Array.isArray(operation?.normalizedInputs) &&
|
|
2039
|
+
operation.normalizedInputs.length > 0) {
|
|
2040
|
+
addIssue(issues, `$.results[${index}].operation.normalizedInputs`, 'handoffs must not retain normalized operation inputs');
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
2043
|
+
if (nextSafeAction &&
|
|
2044
|
+
nextSafeAction.authority !== 'read-only' &&
|
|
2045
|
+
(!has(nextSafeAction, 'operationId') || !has(nextSafeAction, 'owner'))) {
|
|
2046
|
+
addIssue(issues, '$.nextSafeAction', 'an actionable handoff step requires a rebound operationId and owner');
|
|
2047
|
+
}
|
|
2048
|
+
const sortedUniqueStrings = (values) => [
|
|
2049
|
+
...new Set(values.filter((value) => typeof value === 'string')),
|
|
2050
|
+
].sort();
|
|
2051
|
+
const sameStrings = (left, right) => {
|
|
2052
|
+
const normalizedLeft = sortedUniqueStrings(left);
|
|
2053
|
+
const normalizedRight = sortedUniqueStrings(right);
|
|
2054
|
+
return (normalizedLeft.length === normalizedRight.length &&
|
|
2055
|
+
normalizedLeft.every((value, index) => value === normalizedRight[index]));
|
|
2056
|
+
};
|
|
2057
|
+
const contractKey = (value) => (0, validation_js_1.isRecord)(value) &&
|
|
2058
|
+
typeof value.class === 'string' &&
|
|
2059
|
+
typeof value.reference === 'string'
|
|
2060
|
+
? `${value.class}\u0000${value.reference}`
|
|
2061
|
+
: undefined;
|
|
2062
|
+
const selectedProjects = Array.isArray(selection?.projects)
|
|
2063
|
+
? selection.projects.filter((value) => typeof value === 'string')
|
|
2064
|
+
: [];
|
|
2065
|
+
const retainedScopeProjects = sortedUniqueStrings(operations.flatMap((operation) => {
|
|
2066
|
+
const scope = (0, validation_js_1.isRecord)(operation.scope) ? operation.scope : undefined;
|
|
2067
|
+
return Array.isArray(scope?.projects) ? scope.projects : [];
|
|
2068
|
+
}));
|
|
2069
|
+
if (operations.length > 0 &&
|
|
2070
|
+
!sameStrings(retainedScopeProjects, selectedProjects)) {
|
|
2071
|
+
addIssue(issues, '$.selection.projects', 'must equal the exact performed-operation project-scope union');
|
|
2072
|
+
}
|
|
2073
|
+
const retainedScopeEvidence = sortedUniqueStrings(operations.flatMap((operation) => {
|
|
2074
|
+
const scope = (0, validation_js_1.isRecord)(operation.scope) ? operation.scope : undefined;
|
|
2075
|
+
return Array.isArray(scope?.evidenceClasses) ? scope.evidenceClasses : [];
|
|
2076
|
+
}));
|
|
2077
|
+
if (state !== 'proposal-or-research-only' &&
|
|
2078
|
+
!sameStrings(retainedScopeEvidence, requiredEvidence)) {
|
|
2079
|
+
addIssue(issues, '$.requiredEvidence', 'must equal the exact performed-operation evidence-scope union');
|
|
2080
|
+
}
|
|
2081
|
+
results.forEach((result, index) => {
|
|
2082
|
+
const resultOperation = (0, validation_js_1.isRecord)(result.operation)
|
|
2083
|
+
? result.operation
|
|
2084
|
+
: undefined;
|
|
2085
|
+
const retained = operations.find((operation) => operation.id === resultOperation?.name);
|
|
2086
|
+
const scope = (0, validation_js_1.isRecord)(retained?.scope) ? retained.scope : undefined;
|
|
2087
|
+
if (!scope)
|
|
2088
|
+
return;
|
|
2089
|
+
if (result.outcome === 'blocked')
|
|
2090
|
+
return;
|
|
2091
|
+
const affected = (0, validation_js_1.isRecord)(result.affected) ? result.affected : undefined;
|
|
2092
|
+
const affectedProjects = Array.isArray(affected?.projects)
|
|
2093
|
+
? affected.projects
|
|
2094
|
+
: [];
|
|
2095
|
+
const affectedContracts = Array.isArray(affected?.contracts)
|
|
2096
|
+
? affected.contracts
|
|
2097
|
+
.map(contractKey)
|
|
2098
|
+
.filter((value) => value !== undefined)
|
|
2099
|
+
: [];
|
|
2100
|
+
const scopeContracts = Array.isArray(scope.contracts)
|
|
2101
|
+
? scope.contracts
|
|
2102
|
+
.map(contractKey)
|
|
2103
|
+
.filter((value) => value !== undefined)
|
|
2104
|
+
: [];
|
|
2105
|
+
if (!Array.isArray(scope.projects) ||
|
|
2106
|
+
!sameStrings(affectedProjects, scope.projects)) {
|
|
2107
|
+
addIssue(issues, `$.results[${index}].affected.projects`, 'must equal the exact retained effective-operation project scope');
|
|
2108
|
+
}
|
|
2109
|
+
if (!sameStrings(affectedContracts, scopeContracts)) {
|
|
2110
|
+
addIssue(issues, `$.results[${index}].affected.contracts`, 'must equal the exact retained effective-operation contract scope');
|
|
2111
|
+
}
|
|
2112
|
+
const verification = (0, validation_js_1.isRecord)(result.verification)
|
|
2113
|
+
? result.verification
|
|
2114
|
+
: undefined;
|
|
2115
|
+
const resultVerification = [
|
|
2116
|
+
...(Array.isArray(verification?.executed) ? verification.executed : []),
|
|
2117
|
+
...(Array.isArray(verification?.omitted) ? verification.omitted : []),
|
|
2118
|
+
];
|
|
2119
|
+
if (!Array.isArray(scope.requiredVerification) ||
|
|
2120
|
+
!sameStrings(resultVerification, scope.requiredVerification)) {
|
|
2121
|
+
addIssue(issues, `$.results[${index}].verification`, 'must equal the exact retained effective-operation verification scope');
|
|
2122
|
+
}
|
|
2123
|
+
});
|
|
2124
|
+
const executedVerification = sortedUniqueStrings(results.flatMap((result) => {
|
|
2125
|
+
const verification = (0, validation_js_1.isRecord)(result.verification)
|
|
2126
|
+
? result.verification
|
|
2127
|
+
: undefined;
|
|
2128
|
+
return Array.isArray(verification?.executed) ? verification.executed : [];
|
|
2129
|
+
}));
|
|
2130
|
+
const omittedVerification = sortedUniqueStrings(results.flatMap((result) => {
|
|
2131
|
+
const verification = (0, validation_js_1.isRecord)(result.verification)
|
|
2132
|
+
? result.verification
|
|
2133
|
+
: undefined;
|
|
2134
|
+
return Array.isArray(verification?.omitted) ? verification.omitted : [];
|
|
2135
|
+
}));
|
|
2136
|
+
if (!sameStrings(requiredVerification, [...executedVerification, ...pending])) {
|
|
2137
|
+
addIssue(issues, '$.requiredVerification', 'must equal the exact executed-or-pending verification union');
|
|
2138
|
+
}
|
|
2139
|
+
if (!sameStrings(omittedVerification, pending)) {
|
|
2140
|
+
addIssue(issues, '$.requiredVerificationPending', 'must equal the exact omitted verification union');
|
|
2141
|
+
}
|
|
2142
|
+
const artifacts = results.flatMap((result) => Array.isArray(result.artifacts) ? result.artifacts.filter(validation_js_1.isRecord) : []);
|
|
2143
|
+
const satisfiedEvidence = sortedUniqueStrings(artifacts.map((artifact) => artifact.evidenceClass));
|
|
2144
|
+
if (!sameStrings(requiredEvidence, [
|
|
2145
|
+
...satisfiedEvidence,
|
|
2146
|
+
...requiredEvidencePending,
|
|
2147
|
+
])) {
|
|
2148
|
+
addIssue(issues, '$.requiredEvidence', 'must equal the exact referenced-or-pending evidence union');
|
|
2149
|
+
}
|
|
2150
|
+
const protectedEvidenceClasses = new Set([
|
|
2151
|
+
'protected-promotion-proof',
|
|
2152
|
+
'recovery-proof',
|
|
2153
|
+
]);
|
|
2154
|
+
const externalEvidencePending = requiredEvidencePending.some((value) => typeof value === 'string' && protectedEvidenceClasses.has(value));
|
|
2155
|
+
if (record.externalProofPending !== externalEvidencePending) {
|
|
2156
|
+
addIssue(issues, '$.externalProofPending', 'must reflect whether required evidence remains pending');
|
|
2157
|
+
}
|
|
2158
|
+
for (const evidenceClass of protectedEvidenceClasses) {
|
|
2159
|
+
if (satisfiedEvidence.includes(evidenceClass) &&
|
|
2160
|
+
artifacts.some((artifact) => artifact.evidenceClass === evidenceClass)) {
|
|
2161
|
+
addIssue(issues, '$.results', `${evidenceClass} cannot be marked satisfied until a semantic validator binds repository head, workspace, stage, policy, and candidate identity`);
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
const retainedOperationIds = operations.map((operation) => operation.id);
|
|
2165
|
+
const resultOperationIds = results.flatMap((result) => {
|
|
2166
|
+
const operation = (0, validation_js_1.isRecord)(result.operation) ? result.operation : undefined;
|
|
2167
|
+
return typeof operation?.name === 'string' ? [operation.name] : [];
|
|
2168
|
+
});
|
|
2169
|
+
if (!sameStrings(retainedOperationIds, resultOperationIds)) {
|
|
2170
|
+
addIssue(issues, '$.operations', 'must identify exactly the operations represented by retained results');
|
|
2171
|
+
}
|
|
2172
|
+
results.forEach((result, index) => {
|
|
2173
|
+
const affected = (0, validation_js_1.isRecord)(result.affected) ? result.affected : undefined;
|
|
2174
|
+
const affectedProjects = Array.isArray(affected?.projects)
|
|
2175
|
+
? affected.projects.filter((value) => typeof value === 'string')
|
|
2176
|
+
: [];
|
|
2177
|
+
if (affectedProjects.some((project) => !selectedProjects.includes(project))) {
|
|
2178
|
+
addIssue(issues, `$.results[${index}].affected.projects`, 'must remain within the exact retained project selection');
|
|
2179
|
+
}
|
|
2180
|
+
});
|
|
2181
|
+
const resultFiles = [
|
|
2182
|
+
...new Set(results.flatMap((result) => {
|
|
2183
|
+
const changes = (0, validation_js_1.isRecord)(result.changes) ? result.changes : undefined;
|
|
2184
|
+
return Array.isArray(changes?.files)
|
|
2185
|
+
? changes.files.filter((value) => typeof value === 'string')
|
|
2186
|
+
: [];
|
|
2187
|
+
})),
|
|
2188
|
+
].sort();
|
|
2189
|
+
const retainedFiles = changedFiles
|
|
2190
|
+
.filter((value) => typeof value === 'string')
|
|
2191
|
+
.sort();
|
|
2192
|
+
if (resultFiles.length !== retainedFiles.length ||
|
|
2193
|
+
resultFiles.some((value, index) => value !== retainedFiles[index])) {
|
|
2194
|
+
addIssue(issues, '$.changedFiles', 'must equal the unique file-change union of retained results');
|
|
2195
|
+
}
|
|
2196
|
+
const resultContracts = [
|
|
2197
|
+
...new Set(results.flatMap((result) => {
|
|
2198
|
+
const affected = (0, validation_js_1.isRecord)(result.affected)
|
|
2199
|
+
? result.affected
|
|
2200
|
+
: undefined;
|
|
2201
|
+
return Array.isArray(affected?.contracts)
|
|
2202
|
+
? affected.contracts
|
|
2203
|
+
.map(contractKey)
|
|
2204
|
+
.filter((value) => value !== undefined)
|
|
2205
|
+
: [];
|
|
2206
|
+
})),
|
|
2207
|
+
].sort();
|
|
2208
|
+
const retainedContracts = changedContracts
|
|
2209
|
+
.map(contractKey)
|
|
2210
|
+
.filter((value) => value !== undefined)
|
|
2211
|
+
.sort();
|
|
2212
|
+
if (resultContracts.length !== retainedContracts.length ||
|
|
2213
|
+
resultContracts.some((value, index) => value !== retainedContracts[index])) {
|
|
2214
|
+
addIssue(issues, '$.changedContracts', 'must equal the unique contract-change union of retained results');
|
|
2215
|
+
}
|
|
2216
|
+
const resultExternalResources = sortedUniqueStrings(results.flatMap((result) => {
|
|
2217
|
+
const changes = (0, validation_js_1.isRecord)(result.changes) ? result.changes : undefined;
|
|
2218
|
+
return Array.isArray(changes?.externalResources)
|
|
2219
|
+
? changes.externalResources
|
|
2220
|
+
: [];
|
|
2221
|
+
}));
|
|
2222
|
+
const retainedExternalResources = externalState.flatMap((entry) => (0, validation_js_1.isRecord)(entry) && typeof entry.reference === 'string'
|
|
2223
|
+
? [entry.reference]
|
|
2224
|
+
: []);
|
|
2225
|
+
if (!sameStrings(resultExternalResources, retainedExternalResources)) {
|
|
2226
|
+
addIssue(issues, '$.externalState', 'must bind every nested external resource to one cleanup owner');
|
|
2227
|
+
}
|
|
2228
|
+
if (externalState.length > 0 &&
|
|
2229
|
+
!externalState.some((entry) => (0, validation_js_1.isRecord)(entry) &&
|
|
2230
|
+
entry.cleanupOperationId === nextSafeAction?.operationId &&
|
|
2231
|
+
entry.cleanupOwner === nextSafeAction?.owner)) {
|
|
2232
|
+
addIssue(issues, '$.nextSafeAction', 'must exactly bind one retained external-state cleanup operation and owner');
|
|
2233
|
+
}
|
|
2234
|
+
if (unresolved) {
|
|
2235
|
+
for (const property of [
|
|
2236
|
+
'approvalNeeds',
|
|
2237
|
+
'assumptions',
|
|
2238
|
+
'conflicts',
|
|
2239
|
+
'markers',
|
|
2240
|
+
]) {
|
|
2241
|
+
const nested = results.flatMap((result) => {
|
|
2242
|
+
const resultUnresolved = (0, validation_js_1.isRecord)(result.unresolved)
|
|
2243
|
+
? result.unresolved
|
|
2244
|
+
: undefined;
|
|
2245
|
+
return Array.isArray(resultUnresolved?.[property])
|
|
2246
|
+
? resultUnresolved[property]
|
|
2247
|
+
: [];
|
|
2248
|
+
});
|
|
2249
|
+
const retained = Array.isArray(unresolved[property])
|
|
2250
|
+
? unresolved[property]
|
|
2251
|
+
: [];
|
|
2252
|
+
if (!sameStrings(nested, retained)) {
|
|
2253
|
+
addIssue(issues, `$.unresolved.${property}`, 'must equal the exact nested unresolved-state union');
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
if (repository) {
|
|
2258
|
+
results.forEach((result, index) => {
|
|
2259
|
+
const source = (0, validation_js_1.isRecord)(result.source) ? result.source : undefined;
|
|
2260
|
+
if (source?.commit !== repository.headCommit ||
|
|
2261
|
+
source?.worktree !== repository.worktree) {
|
|
2262
|
+
addIssue(issues, `$.results[${index}].source`, 'must match the retained repository head commit and worktree');
|
|
2263
|
+
}
|
|
2264
|
+
const testingEvidence = (0, validation_js_1.isRecord)(result.testingEvidence)
|
|
2265
|
+
? result.testingEvidence
|
|
2266
|
+
: undefined;
|
|
2267
|
+
const testingResult = (0, validation_js_1.isRecord)(testingEvidence?.result)
|
|
2268
|
+
? testingEvidence.result
|
|
2269
|
+
: undefined;
|
|
2270
|
+
const testingSource = (0, validation_js_1.isRecord)(testingResult?.source)
|
|
2271
|
+
? testingResult.source
|
|
2272
|
+
: undefined;
|
|
2273
|
+
if (testingSource && testingSource.commit !== repository.headCommit) {
|
|
2274
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.source.commit`, 'must match the retained repository head commit');
|
|
2275
|
+
}
|
|
2276
|
+
if (testingResult && testingResult.workspace !== repository.identity) {
|
|
2277
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.workspace`, 'must match the retained repository identity');
|
|
2278
|
+
}
|
|
2279
|
+
const versions = (0, validation_js_1.isRecord)(record.versions) ? record.versions : undefined;
|
|
2280
|
+
const affected = (0, validation_js_1.isRecord)(result.affected) ? result.affected : undefined;
|
|
2281
|
+
const affectedProjects = Array.isArray(affected?.projects)
|
|
2282
|
+
? affected.projects.filter((value) => typeof value === 'string')
|
|
2283
|
+
: [];
|
|
2284
|
+
if (testingSource &&
|
|
2285
|
+
typeof versions?.frameworkVersion === 'string' &&
|
|
2286
|
+
testingSource.frameworkCandidate !==
|
|
2287
|
+
`@empire-builder-kit/nx@${versions.frameworkVersion}`) {
|
|
2288
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.source.frameworkCandidate`, 'must match the retained framework candidate');
|
|
2289
|
+
}
|
|
2290
|
+
if (testingSource &&
|
|
2291
|
+
Array.isArray(testingSource.blueprintCandidates) &&
|
|
2292
|
+
Array.isArray(versions?.blueprintVersions)) {
|
|
2293
|
+
const affectedProjectSet = new Set(affectedProjects);
|
|
2294
|
+
const expectedBlueprints = versions.blueprintVersions.flatMap((entry) => {
|
|
2295
|
+
if (!(0, validation_js_1.isRecord)(entry) ||
|
|
2296
|
+
typeof entry.name !== 'string' ||
|
|
2297
|
+
typeof entry.version !== 'string') {
|
|
2298
|
+
return [];
|
|
2299
|
+
}
|
|
2300
|
+
const separator = entry.name.indexOf(':@');
|
|
2301
|
+
const project = separator === -1 ? undefined : entry.name.slice(0, separator);
|
|
2302
|
+
if (project && !affectedProjectSet.has(project))
|
|
2303
|
+
return [];
|
|
2304
|
+
const packageName = separator === -1 ? entry.name : entry.name.slice(separator + 1);
|
|
2305
|
+
return [`${packageName}@${entry.version}`];
|
|
2306
|
+
});
|
|
2307
|
+
if (!sameStrings(testingSource.blueprintCandidates, expectedBlueprints)) {
|
|
2308
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.source.blueprintCandidates`, 'must match the retained Blueprint candidates for affected projects');
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
const testingOperation = (0, validation_js_1.isRecord)(testingResult?.operation)
|
|
2312
|
+
? testingResult.operation
|
|
2313
|
+
: undefined;
|
|
2314
|
+
const testingEnvironment = (0, validation_js_1.isRecord)(testingResult?.environment)
|
|
2315
|
+
? testingResult.environment
|
|
2316
|
+
: undefined;
|
|
2317
|
+
const testingCleanup = (0, validation_js_1.isRecord)(testingResult?.cleanup)
|
|
2318
|
+
? testingResult.cleanup
|
|
2319
|
+
: undefined;
|
|
2320
|
+
if (testingResult && testingResult.outcome !== 'passed') {
|
|
2321
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.outcome`, 'must be passed before Testing/Evidence can satisfy a handoff');
|
|
2322
|
+
}
|
|
2323
|
+
if (testingCleanup &&
|
|
2324
|
+
testingCleanup.outcome !== 'passed' &&
|
|
2325
|
+
testingCleanup.outcome !== 'not-required') {
|
|
2326
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.cleanup.outcome`, 'must be passed or not-required');
|
|
2327
|
+
}
|
|
2328
|
+
if (typeof testingOperation?.project === 'string' &&
|
|
2329
|
+
(!affectedProjects.includes(testingOperation.project) ||
|
|
2330
|
+
(Array.isArray(selection?.projects) &&
|
|
2331
|
+
!selection.projects.includes(testingOperation.project)))) {
|
|
2332
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.operation.project`, 'must identify an affected project in the retained selection');
|
|
2333
|
+
}
|
|
2334
|
+
if (testingResult &&
|
|
2335
|
+
(typeof selection?.slice === 'string'
|
|
2336
|
+
? testingResult.slice !== selection.slice
|
|
2337
|
+
: has(testingResult, 'slice'))) {
|
|
2338
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.slice`, 'must exactly match the retained Slice selection');
|
|
2339
|
+
}
|
|
2340
|
+
if (typeof versions?.canonicalStage === 'string' &&
|
|
2341
|
+
((testingEnvironment?.deployed === true &&
|
|
2342
|
+
testingEnvironment.stage !== versions.canonicalStage) ||
|
|
2343
|
+
(typeof testingEnvironment?.stage === 'string' &&
|
|
2344
|
+
testingEnvironment.stage !== versions.canonicalStage))) {
|
|
2345
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.environment.stage`, 'must be present for deployed proof and exactly match the retained canonical stage');
|
|
2346
|
+
}
|
|
2347
|
+
if (typeof testingOperation?.target === 'string' &&
|
|
2348
|
+
!requiredVerification.some((value) => typeof value === 'string' &&
|
|
2349
|
+
(value === testingOperation.target ||
|
|
2350
|
+
value.endsWith(`:${testingOperation.target}`)))) {
|
|
2351
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.operation.target`, 'must be accounted for by retained required verification');
|
|
2352
|
+
}
|
|
2353
|
+
if (typeof testingOperation?.proofLayer === 'string' &&
|
|
2354
|
+
!requiredEvidence.includes(testingOperation.proofLayer)) {
|
|
2355
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.operation.proofLayer`, 'must be accounted for by retained required evidence');
|
|
2356
|
+
}
|
|
2357
|
+
if (testingEvidence && testingResult) {
|
|
2358
|
+
const outerArtifacts = Array.isArray(result.artifacts)
|
|
2359
|
+
? result.artifacts.filter(validation_js_1.isRecord)
|
|
2360
|
+
: [];
|
|
2361
|
+
if (!outerArtifacts.some((artifact) => artifact.reference === testingEvidence.reference &&
|
|
2362
|
+
artifact.digest === testingEvidence.digest &&
|
|
2363
|
+
artifact.evidenceClass === testingOperation?.proofLayer)) {
|
|
2364
|
+
addIssue(issues, `$.results[${index}].testingEvidence`, 'must have an exact outer artifact reference, digest, and evidence-class identity');
|
|
2365
|
+
}
|
|
2366
|
+
const nestedArtifacts = Array.isArray(testingResult.artifacts)
|
|
2367
|
+
? testingResult.artifacts.filter(validation_js_1.isRecord)
|
|
2368
|
+
: [];
|
|
2369
|
+
nestedArtifacts.forEach((artifact, artifactIndex) => {
|
|
2370
|
+
if (!outerArtifacts.some((outer) => outer.name === artifact.name &&
|
|
2371
|
+
outer.digest === artifact.digest)) {
|
|
2372
|
+
addIssue(issues, `$.results[${index}].testingEvidence.result.artifacts[${artifactIndex}]`, 'must match an exact outer artifact name and digest');
|
|
2373
|
+
}
|
|
2374
|
+
});
|
|
2375
|
+
}
|
|
2376
|
+
});
|
|
2377
|
+
}
|
|
2378
|
+
if (resultExternalResources.length > 0 &&
|
|
2379
|
+
cleanup?.outcome === 'not-required') {
|
|
2380
|
+
addIssue(issues, '$.cleanup.outcome', 'cannot be not-required when external state was created');
|
|
2381
|
+
}
|
|
2382
|
+
if (state === 'implemented-and-verified') {
|
|
2383
|
+
if (markerSnapshot.some((marker) => marker.blocking === true)) {
|
|
2384
|
+
addIssue(issues, '$.markerSnapshot', 'cannot retain a blocking repository marker when verified');
|
|
2385
|
+
}
|
|
2386
|
+
if (results.length === 0 ||
|
|
2387
|
+
results.some((result) => result.outcome !== 'succeeded')) {
|
|
2388
|
+
addIssue(issues, '$.results', 'must contain only succeeded results when implemented and verified');
|
|
2389
|
+
}
|
|
2390
|
+
if (results.some((result) => !(0, validation_js_1.isRecord)(result.testingEvidence))) {
|
|
2391
|
+
addIssue(issues, '$.results', 'implemented work must retain ingested Testing/Evidence results');
|
|
2392
|
+
}
|
|
2393
|
+
if (results.some((result) => !(0, validation_js_1.isRecord)(result.verification) ||
|
|
2394
|
+
!Array.isArray(result.verification.executed) ||
|
|
2395
|
+
result.verification.executed.length === 0)) {
|
|
2396
|
+
addIssue(issues, '$.results', 'must retain executed verification for implemented work');
|
|
2397
|
+
}
|
|
2398
|
+
if (pending.length > 0 || record.externalProofPending !== false) {
|
|
2399
|
+
addIssue(issues, '$.state', 'cannot claim verified completion while proof is pending');
|
|
2400
|
+
}
|
|
2401
|
+
if (cleanup?.outcome === 'incomplete' ||
|
|
2402
|
+
recovery?.outcome === 'incomplete' ||
|
|
2403
|
+
results.some((result) => (0, validation_js_1.isRecord)(result.cleanup) && result.cleanup.outcome === 'incomplete') ||
|
|
2404
|
+
results.some((result) => (0, validation_js_1.isRecord)(result.recovery) && result.recovery.outcome === 'incomplete') ||
|
|
2405
|
+
results.some((result) => (0, validation_js_1.isRecord)(result.verification) &&
|
|
2406
|
+
Array.isArray(result.verification.omitted) &&
|
|
2407
|
+
result.verification.omitted.length > 0)) {
|
|
2408
|
+
addIssue(issues, '$.state', 'cannot claim verified completion with omitted proof or incomplete cleanup/recovery');
|
|
2409
|
+
}
|
|
2410
|
+
if (unresolved &&
|
|
2411
|
+
['approvalNeeds', 'assumptions', 'conflicts', 'markers'].some((property) => Array.isArray(unresolved[property]) &&
|
|
2412
|
+
unresolved[property].length > 0)) {
|
|
2413
|
+
addIssue(issues, '$.unresolved', 'cannot retain unresolved approval, assumption, conflict, or marker state when verified');
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
if (state === 'implemented-external-proof-pending') {
|
|
2417
|
+
if (record.externalProofPending !== true ||
|
|
2418
|
+
requiredEvidencePending.length === 0) {
|
|
2419
|
+
addIssue(issues, '$.requiredEvidencePending', 'must identify required external evidence');
|
|
2420
|
+
}
|
|
2421
|
+
if (results.length === 0 ||
|
|
2422
|
+
!results.some((result) => result.outcome === 'incomplete' &&
|
|
2423
|
+
result.failureClassification === 'external-proof-pending')) {
|
|
2424
|
+
addIssue(issues, '$.results', 'must include an external-proof-pending incomplete result');
|
|
2425
|
+
}
|
|
2426
|
+
if (results.some((result) => !(0, validation_js_1.isRecord)(result.testingEvidence))) {
|
|
2427
|
+
addIssue(issues, '$.results', 'implemented work must retain ingested Testing/Evidence results');
|
|
2428
|
+
}
|
|
2429
|
+
if (results.some((result) => result.outcome !== 'succeeded' &&
|
|
2430
|
+
!(result.outcome === 'incomplete' &&
|
|
2431
|
+
result.failureClassification === 'external-proof-pending'))) {
|
|
2432
|
+
addIssue(issues, '$.results', 'may contain only succeeded or external-proof-pending results');
|
|
2433
|
+
}
|
|
2434
|
+
if (cleanup?.outcome === 'incomplete' ||
|
|
2435
|
+
recovery?.outcome === 'incomplete' ||
|
|
2436
|
+
results.some((result) => ((0, validation_js_1.isRecord)(result.cleanup) &&
|
|
2437
|
+
result.cleanup.outcome === 'incomplete') ||
|
|
2438
|
+
((0, validation_js_1.isRecord)(result.recovery) &&
|
|
2439
|
+
result.recovery.outcome === 'incomplete'))) {
|
|
2440
|
+
addIssue(issues, '$.state', 'external-proof-pending cannot hide incomplete cleanup or recovery');
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
if (state === 'blocked-before-mutation') {
|
|
2444
|
+
if (results.length === 0 ||
|
|
2445
|
+
results.some((result) => result.outcome !== 'blocked')) {
|
|
2446
|
+
addIssue(issues, '$.results', 'must contain only blocked results when blocked before mutation');
|
|
2447
|
+
}
|
|
2448
|
+
if (changedContracts.length > 0 ||
|
|
2449
|
+
changedFiles.length > 0 ||
|
|
2450
|
+
externalState.length > 0) {
|
|
2451
|
+
addIssue(issues, '$.state', 'blocked-before-mutation cannot report changed or external state');
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
if (state === 'failed-recovery-complete') {
|
|
2455
|
+
if (!results.some((result) => result.outcome === 'failed') ||
|
|
2456
|
+
recovery?.outcome !== 'complete' ||
|
|
2457
|
+
cleanup?.outcome === 'incomplete') {
|
|
2458
|
+
addIssue(issues, '$.state', 'requires a failed result, complete recovery, and no incomplete cleanup');
|
|
2459
|
+
}
|
|
2460
|
+
if (results.some((result) => ((0, validation_js_1.isRecord)(result.cleanup) &&
|
|
2461
|
+
result.cleanup.outcome === 'incomplete') ||
|
|
2462
|
+
((0, validation_js_1.isRecord)(result.recovery) &&
|
|
2463
|
+
result.recovery.outcome === 'incomplete'))) {
|
|
2464
|
+
addIssue(issues, '$.results', 'cannot retain incomplete nested cleanup or recovery');
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
if (state === 'failed-recovery-or-cleanup-required') {
|
|
2468
|
+
if (!results.some((result) => result.outcome === 'failed') ||
|
|
2469
|
+
(recovery?.outcome !== 'incomplete' && cleanup?.outcome !== 'incomplete')) {
|
|
2470
|
+
addIssue(issues, '$.state', 'requires a failed result and incomplete recovery or cleanup');
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
if (state === 'proposal-or-research-only') {
|
|
2474
|
+
if (changedContracts.length > 0 ||
|
|
2475
|
+
changedFiles.length > 0 ||
|
|
2476
|
+
externalState.length > 0 ||
|
|
2477
|
+
results.some((result) => Array.isArray(result.changes) ||
|
|
2478
|
+
((0, validation_js_1.isRecord)(result.changes) &&
|
|
2479
|
+
((Array.isArray(result.changes.files) &&
|
|
2480
|
+
result.changes.files.length > 0) ||
|
|
2481
|
+
(Array.isArray(result.changes.externalResources) &&
|
|
2482
|
+
result.changes.externalResources.length > 0))))) {
|
|
2483
|
+
addIssue(issues, '$.state', 'proposal or research handoff cannot report mutation');
|
|
2484
|
+
}
|
|
2485
|
+
if (results.some((result) => result.outcome !== 'incomplete' && result.outcome !== 'blocked')) {
|
|
2486
|
+
addIssue(issues, '$.results', 'proposal or research results must be incomplete or blocked');
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
function validateDeveloperAgentHandoff(value) {
|
|
2491
|
+
const issues = [];
|
|
2492
|
+
validateSerializedBound(value, '$', model_js_1.DEVELOPER_AGENT_HANDOFF_MAX_BYTES, issues);
|
|
2493
|
+
const record = requireRecord(value, '$', [
|
|
2494
|
+
'changedContracts',
|
|
2495
|
+
'changedFiles',
|
|
2496
|
+
'cleanup',
|
|
2497
|
+
'externalProofPending',
|
|
2498
|
+
'externalState',
|
|
2499
|
+
'kind',
|
|
2500
|
+
'markerSnapshot',
|
|
2501
|
+
'nextSafeAction',
|
|
2502
|
+
'operations',
|
|
2503
|
+
'recovery',
|
|
2504
|
+
'repository',
|
|
2505
|
+
'requiredEvidence',
|
|
2506
|
+
'requiredEvidencePending',
|
|
2507
|
+
'requiredVerification',
|
|
2508
|
+
'requiredVerificationPending',
|
|
2509
|
+
'results',
|
|
2510
|
+
'schemaVersion',
|
|
2511
|
+
'selection',
|
|
2512
|
+
'state',
|
|
2513
|
+
'unresolved',
|
|
2514
|
+
'versions',
|
|
2515
|
+
'work',
|
|
2516
|
+
], [], issues);
|
|
2517
|
+
if (!record)
|
|
2518
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
2519
|
+
if (record.kind !== model_js_1.DEVELOPER_AGENT_HANDOFF_KIND) {
|
|
2520
|
+
addIssue(issues, '$.kind', `must equal ${model_js_1.DEVELOPER_AGENT_HANDOFF_KIND}`);
|
|
2521
|
+
}
|
|
2522
|
+
if (record.schemaVersion !== model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION) {
|
|
2523
|
+
addIssue(issues, '$.schemaVersion', `must equal ${model_js_1.DEVELOPER_AGENT_CONTRACT_SCHEMA_VERSION}`);
|
|
2524
|
+
}
|
|
2525
|
+
validateContractReferences(record.changedContracts, '$.changedContracts', issues);
|
|
2526
|
+
validateStringArray(record.changedFiles, '$.changedFiles', issues, {
|
|
2527
|
+
maximumLength: MAX_PATH_LENGTH,
|
|
2528
|
+
pattern: WORKSPACE_RELATIVE_PATH_PATTERN,
|
|
2529
|
+
});
|
|
2530
|
+
if (Array.isArray(record.changedFiles)) {
|
|
2531
|
+
record.changedFiles.forEach((entry, index) => validateCanonicalWorkspacePath(entry, `$.changedFiles[${index}]`, issues));
|
|
2532
|
+
}
|
|
2533
|
+
validateCleanupRecovery(record.cleanup, '$.cleanup', issues);
|
|
2534
|
+
requireBoolean(record.externalProofPending, '$.externalProofPending', issues);
|
|
2535
|
+
const externalState = requireArray(record.externalState, '$.externalState', issues);
|
|
2536
|
+
const externalReferences = new Set();
|
|
2537
|
+
const externalCleanupOwners = new Set();
|
|
2538
|
+
externalState?.forEach((entry, index) => {
|
|
2539
|
+
if (validateExternalState(entry, `$.externalState[${index}]`, issues)) {
|
|
2540
|
+
const retained = entry;
|
|
2541
|
+
if (externalReferences.has(retained.reference)) {
|
|
2542
|
+
addIssue(issues, `$.externalState[${index}].reference`, 'must be unique');
|
|
2543
|
+
}
|
|
2544
|
+
externalReferences.add(retained.reference);
|
|
2545
|
+
const cleanupIdentity = `${retained.cleanupOwner}\u0000${retained.cleanupOperationId}`;
|
|
2546
|
+
if (externalCleanupOwners.has(cleanupIdentity)) {
|
|
2547
|
+
addIssue(issues, `$.externalState[${index}]`, 'must have a unique cleanup operation owner');
|
|
2548
|
+
}
|
|
2549
|
+
externalCleanupOwners.add(cleanupIdentity);
|
|
2550
|
+
}
|
|
2551
|
+
});
|
|
2552
|
+
const markerSnapshot = requireArray(record.markerSnapshot, '$.markerSnapshot', issues);
|
|
2553
|
+
const markerReferences = new Set();
|
|
2554
|
+
markerSnapshot?.forEach((entry, index) => {
|
|
2555
|
+
if (validateHandoffMarkerSnapshot(entry, `$.markerSnapshot[${index}]`, issues)) {
|
|
2556
|
+
const reference = entry
|
|
2557
|
+
.reference;
|
|
2558
|
+
if (markerReferences.has(reference)) {
|
|
2559
|
+
addIssue(issues, `$.markerSnapshot[${index}].reference`, 'must be unique');
|
|
2560
|
+
}
|
|
2561
|
+
markerReferences.add(reference);
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2564
|
+
validateNextSafeAction(record.nextSafeAction, '$.nextSafeAction', issues);
|
|
2565
|
+
const operations = requireArray(record.operations, '$.operations', issues);
|
|
2566
|
+
const operationIds = new Set();
|
|
2567
|
+
operations?.forEach((entry, index) => {
|
|
2568
|
+
if (validateHandoffOperation(entry, `$.operations[${index}]`, issues)) {
|
|
2569
|
+
const id = entry.id;
|
|
2570
|
+
if (operationIds.has(id)) {
|
|
2571
|
+
addIssue(issues, `$.operations[${index}].id`, 'must be unique');
|
|
2572
|
+
}
|
|
2573
|
+
operationIds.add(id);
|
|
2574
|
+
}
|
|
2575
|
+
});
|
|
2576
|
+
validateCleanupRecovery(record.recovery, '$.recovery', issues);
|
|
2577
|
+
validateHandoffRepository(record.repository, '$.repository', issues);
|
|
2578
|
+
validateStringArray(record.requiredEvidence, '$.requiredEvidence', issues);
|
|
2579
|
+
validateStringArray(record.requiredEvidencePending, '$.requiredEvidencePending', issues);
|
|
2580
|
+
validateStringArray(record.requiredVerification, '$.requiredVerification', issues);
|
|
2581
|
+
validateStringArray(record.requiredVerificationPending, '$.requiredVerificationPending', issues);
|
|
2582
|
+
validateHandoffSelection(record.selection, '$.selection', issues);
|
|
2583
|
+
const results = requireArray(record.results, '$.results', issues, MAX_RESULTS);
|
|
2584
|
+
results?.forEach((entry, index) => nestedResultIssues(entry, `$.results[${index}]`, issues));
|
|
2585
|
+
requireEnum(record.state, '$.state', HANDOFF_STATE_SET, issues);
|
|
2586
|
+
validateUnresolvedState(record.unresolved, '$.unresolved', issues);
|
|
2587
|
+
validateHandoffVersions(record.versions, '$.versions', issues);
|
|
2588
|
+
validateHandoffWork(record.work, '$.work', issues);
|
|
2589
|
+
validateHandoffCoherence(record, issues);
|
|
2590
|
+
return (0, validation_js_1.validationResult)(value, issues);
|
|
2591
|
+
}
|
|
2592
|
+
function serializeValidated(label, value, validate) {
|
|
2593
|
+
const result = validate(value);
|
|
2594
|
+
if (!result.valid) {
|
|
2595
|
+
throw new DeveloperAgentContractValidationError(label, result.issues);
|
|
2596
|
+
}
|
|
2597
|
+
return (0, canonical_json_1.canonicalJson)(result.value);
|
|
2598
|
+
}
|
|
2599
|
+
function serializeDeveloperAgentContext(value) {
|
|
2600
|
+
return serializeValidated('Developer-Agent context', value, validateDeveloperAgentContext);
|
|
2601
|
+
}
|
|
2602
|
+
function serializeDeveloperAgentGeneratorPreview(value) {
|
|
2603
|
+
return serializeValidated('Developer-Agent generator preview', value, validateDeveloperAgentGeneratorPreview);
|
|
2604
|
+
}
|
|
2605
|
+
function serializeDeveloperAgentGeneratorPreviewReceipt(value) {
|
|
2606
|
+
return serializeValidated('Developer-Agent generator preview receipt', value, validateDeveloperAgentGeneratorPreviewReceipt);
|
|
2607
|
+
}
|
|
2608
|
+
function serializeDeveloperAgentPlan(value) {
|
|
2609
|
+
return serializeValidated('Developer-Agent plan', value, validateDeveloperAgentPlan);
|
|
2610
|
+
}
|
|
2611
|
+
function serializeDeveloperAgentResult(value) {
|
|
2612
|
+
return serializeValidated('Developer-Agent result', value, validateDeveloperAgentResult);
|
|
2613
|
+
}
|
|
2614
|
+
function serializeDeveloperAgentHandoff(value) {
|
|
2615
|
+
return serializeValidated('Developer-Agent handoff', value, validateDeveloperAgentHandoff);
|
|
2616
|
+
}
|
|
2617
|
+
//# sourceMappingURL=validation.js.map
|