@jtf19/vibecoding-kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +84 -0
- package/CHANGELOG.md +28 -0
- package/CLAUDE.md +137 -0
- package/CODE_OF_CONDUCT.md +30 -0
- package/CONTRIBUTING.md +69 -0
- package/LICENSE +67 -0
- package/README.md +162 -0
- package/SECURITY.md +34 -0
- package/adapters/claude/install.md +70 -0
- package/adapters/claude/plugin.json +38 -0
- package/adapters/claude/settings.example.json +15 -0
- package/adapters/codex/hooks.example.json +15 -0
- package/adapters/codex/install.md +72 -0
- package/adapters/codex/plugin.json +58 -0
- package/adapters/cursor/hooks.example.json +17 -0
- package/adapters/cursor/install.md +72 -0
- package/adapters/cursor/plugin.json +42 -0
- package/adapters/opencode/install.md +95 -0
- package/adapters/opencode/plugin.js +56 -0
- package/adapters/opencode/plugin.json +58 -0
- package/adapters/pi/extension.ts +56 -0
- package/adapters/pi/install.md +95 -0
- package/adapters/pi/plugin.json +58 -0
- package/bin/vibe-cli-usage.mjs +43 -0
- package/bin/vibe.mjs +120 -0
- package/docs/acceptance-checklist.md +1226 -0
- package/docs/architecture-debt-burndown.md +537 -0
- package/docs/architecture.md +77 -0
- package/docs/ci-evidence-onboarding.md +143 -0
- package/docs/development.md +71 -0
- package/docs/evidence-authoring.md +188 -0
- package/docs/golden-path.md +179 -0
- package/docs/install-acceptance-checklist.md +90 -0
- package/docs/install-claude.md +41 -0
- package/docs/install-codex.md +41 -0
- package/docs/install-cursor.md +41 -0
- package/docs/install-experience-roadmap.md +394 -0
- package/docs/install.md +119 -0
- package/docs/maintainer-guide.md +197 -0
- package/docs/phase-1-implementation.md +848 -0
- package/docs/phase-2-roadmap.md +142 -0
- package/docs/quick-recipes.md +115 -0
- package/docs/readiness-interpretation.md +105 -0
- package/docs/readiness-troubleshooting.md +209 -0
- package/docs/release-check-reference.md +63 -0
- package/docs/release-guide.md +481 -0
- package/docs/release-notes.md +75 -0
- package/docs/runtime-contract.md +1010 -0
- package/docs/runtime-maintainer-validation.md +212 -0
- package/docs/runtime-roadmap.md +2265 -0
- package/docs/skill-authoring-guide.md +150 -0
- package/docs/submodule-guide.md +131 -0
- package/docs/team-adoption.md +113 -0
- package/docs/user-guide.md +108 -0
- package/docs/vibecoding-fork-analysis.md +398 -0
- package/docs/workflow-chaining.md +539 -0
- package/examples/ci/README.md +61 -0
- package/examples/ci/ci-evidence-input.example.json +56 -0
- package/examples/ci/generate-diff-coverage.mjs +90 -0
- package/examples/ci/generate-test-evidence.mjs +82 -0
- package/examples/ci/github-actions-readiness.yml +108 -0
- package/examples/claude-project/README.md +57 -0
- package/examples/codex-project/README.md +57 -0
- package/examples/cursor-project/README.md +57 -0
- package/examples/full-chain/README.md +63 -0
- package/examples/full-chain/architecture-design.md +128 -0
- package/examples/full-chain/commit-readiness.json +31 -0
- package/examples/full-chain/delivery-traceability.yaml +32 -0
- package/examples/full-chain/diff-coverage.json +73 -0
- package/examples/full-chain/evidence.json +20 -0
- package/examples/full-chain/implementation-plan.md +54 -0
- package/examples/full-chain/product-acceptance.md +86 -0
- package/examples/full-chain/product-discovery.md +84 -0
- package/examples/full-chain/product-spec.md +88 -0
- package/examples/full-chain/scenario-acceptance.yaml +32 -0
- package/examples/full-chain/test-evidence.json +29 -0
- package/examples/full-chain/ui-design-contract.md +87 -0
- package/examples/golden-path/README.md +84 -0
- package/examples/golden-path/diff-coverage.json +66 -0
- package/examples/golden-path/implementation-plan.md +62 -0
- package/examples/golden-path/product-spec.md +96 -0
- package/examples/golden-path/test-evidence.json +29 -0
- package/examples/runtime-fixtures/architecture-design.md +128 -0
- package/examples/runtime-fixtures/commit-readiness.json +31 -0
- package/examples/runtime-fixtures/delivery-traceability.yaml +32 -0
- package/examples/runtime-fixtures/diff-coverage.json +73 -0
- package/examples/runtime-fixtures/evidence.json +20 -0
- package/examples/runtime-fixtures/implementation-plan.md +54 -0
- package/examples/runtime-fixtures/negative/commit-readiness-boundary-escalated.json +27 -0
- package/examples/runtime-fixtures/negative/delivery-traceability-bad-ref.yaml +32 -0
- package/examples/runtime-fixtures/negative/diff-coverage-changed-file-without-task-ref.json +40 -0
- package/examples/runtime-fixtures/negative/diff-coverage-operation-mismatch.json +38 -0
- package/examples/runtime-fixtures/negative/diff-coverage-required-task-missing.json +24 -0
- package/examples/runtime-fixtures/negative/diff-coverage-unexpected-file.json +20 -0
- package/examples/runtime-fixtures/negative/test-evidence-missing-output-digest.json +23 -0
- package/examples/runtime-fixtures/negative/test-evidence-risky-task-missing.json +29 -0
- package/examples/runtime-fixtures/product-acceptance.md +86 -0
- package/examples/runtime-fixtures/product-discovery.md +84 -0
- package/examples/runtime-fixtures/product-spec.md +88 -0
- package/examples/runtime-fixtures/scenario-acceptance.yaml +32 -0
- package/examples/runtime-fixtures/test-evidence.json +29 -0
- package/examples/runtime-fixtures/ui-design-contract.md +87 -0
- package/hooks/post-tool-compact/README.md +47 -0
- package/hooks/session-start/README.md +112 -0
- package/hooks/session-start/session-start-state-boundary-contract.mjs +161 -0
- package/hooks/session-start/session-start.md +29 -0
- package/hooks/session-start/session-start.mjs +49 -0
- package/hooks/workflow-handoff/README.md +44 -0
- package/hooks/workflow-handoff/workflow-handoff.md +11 -0
- package/package.json +72 -0
- package/skills/using-vibecoding/SKILL.md +396 -0
- package/skills/vibe-brainstorming/SKILL.md +98 -0
- package/skills/vibe-context-compact/SKILL.md +95 -0
- package/skills/vibe-debugging/SKILL.md +87 -0
- package/skills/vibe-dispatching-parallel-work/SKILL.md +144 -0
- package/skills/vibe-executing-plans/SKILL.md +114 -0
- package/skills/vibe-finishing-a-development-branch/SKILL.md +110 -0
- package/skills/vibe-implementation/SKILL.md +84 -0
- package/skills/vibe-planning/SKILL.md +102 -0
- package/skills/vibe-product-acceptance/SKILL.md +106 -0
- package/skills/vibe-product-discovery/SKILL.md +107 -0
- package/skills/vibe-product-spec/SKILL.md +105 -0
- package/skills/vibe-receiving-code-review/SKILL.md +110 -0
- package/skills/vibe-requesting-code-review/SKILL.md +106 -0
- package/skills/vibe-review/SKILL.md +106 -0
- package/skills/vibe-subagent-driven-development/SKILL.md +198 -0
- package/skills/vibe-systematic-debugging/SKILL.md +106 -0
- package/skills/vibe-test-driven-development/SKILL.md +112 -0
- package/skills/vibe-ui-design/SKILL.md +107 -0
- package/skills/vibe-verification/SKILL.md +84 -0
- package/skills/vibe-verification-before-completion/SKILL.md +170 -0
- package/skills/vibe-workspace-isolation/SKILL.md +158 -0
- package/skills/vibe-writing-plans/SKILL.md +137 -0
- package/skills/vibe-writing-skills/SKILL.md +118 -0
- package/templates/AGENTS.md +88 -0
- package/templates/CLAUDE.md +88 -0
- package/templates/VIBE-CODING.md +157 -0
- package/templates/architecture-design.md +139 -0
- package/templates/delivery-traceability.yaml +52 -0
- package/templates/evidence/README.md +117 -0
- package/templates/evidence/diff-coverage.json +34 -0
- package/templates/evidence/test-evidence.json +29 -0
- package/templates/implementation-plan.md +73 -0
- package/templates/product-acceptance.md +84 -0
- package/templates/product-discovery.md +81 -0
- package/templates/product-spec.md +84 -0
- package/templates/scenario-acceptance.yaml +37 -0
- package/templates/ui-design-contract.md +86 -0
- package/tools/vibe-architecture-check/README.md +66 -0
- package/tools/vibe-architecture-check/index.mjs +691 -0
- package/tools/vibe-compact/README.md +65 -0
- package/tools/vibe-compact/compact-contract.mjs +63 -0
- package/tools/vibe-compact/index.mjs +111 -0
- package/tools/vibe-doctor/README.md +200 -0
- package/tools/vibe-doctor/index.mjs +1721 -0
- package/tools/vibe-init/README.md +231 -0
- package/tools/vibe-init/index.mjs +369 -0
- package/tools/vibe-init/init-cli-args.mjs +100 -0
- package/tools/vibe-init/init-entry-merge-model.mjs +33 -0
- package/tools/vibe-init/init-install-manifest-model.mjs +137 -0
- package/tools/vibe-init/init-installed-agent-experience-contract.mjs +172 -0
- package/tools/vibe-init/init-platform-model.mjs +11 -0
- package/tools/vibe-init/init-presentation.mjs +149 -0
- package/tools/vibe-lifecycle/README.md +37 -0
- package/tools/vibe-lifecycle/index.mjs +365 -0
- package/tools/vibe-lifecycle/lifecycle-cli-args.mjs +104 -0
- package/tools/vibe-lifecycle/lifecycle-summary-model.mjs +67 -0
- package/tools/vibe-lifecycle/lifecycle-uninstall-plan-model.mjs +11 -0
- package/tools/vibe-plugin-pack/README.md +105 -0
- package/tools/vibe-plugin-pack/index.mjs +302 -0
- package/tools/vibe-plugin-pack/plugin-pack-cli.mjs +39 -0
- package/tools/vibe-plugin-pack/plugin-pack-manifest.mjs +37 -0
- package/tools/vibe-profile/index.mjs +212 -0
- package/tools/vibe-release-check/README.md +123 -0
- package/tools/vibe-release-check/command-manifest/release-check-base-commands.mjs +23 -0
- package/tools/vibe-release-check/command-manifest/release-check-closeout-commands.mjs +16 -0
- package/tools/vibe-release-check/command-manifest/release-check-command-metadata.mjs +32 -0
- package/tools/vibe-release-check/command-manifest/release-check-completion-commands.mjs +41 -0
- package/tools/vibe-release-check/command-manifest/release-check-full-chain-commands.mjs +12 -0
- package/tools/vibe-release-check/command-manifest/release-check-golden-path-commands.mjs +12 -0
- package/tools/vibe-release-check/command-manifest/release-check-install-commands.mjs +26 -0
- package/tools/vibe-release-check/command-manifest/release-check-learning-smoke-commands.mjs +21 -0
- package/tools/vibe-release-check/command-manifest/release-check-methodology-commands.mjs +27 -0
- package/tools/vibe-release-check/command-manifest/release-check-runtime-smoke-commands.mjs +116 -0
- package/tools/vibe-release-check/command-manifest/release-check-token-smoke-commands.mjs +21 -0
- package/tools/vibe-release-check/index.mjs +223 -0
- package/tools/vibe-release-check/release-check-behavior-smoke.mjs +177 -0
- package/tools/vibe-release-check/release-check-cli.mjs +37 -0
- package/tools/vibe-release-check/release-check-command-manifest.mjs +49 -0
- package/tools/vibe-release-check/release-check-completion-fixtures.mjs +151 -0
- package/tools/vibe-release-check/release-check-completion-suite.mjs +110 -0
- package/tools/vibe-release-check/release-check-dispatch.mjs +116 -0
- package/tools/vibe-release-check/release-check-full-chain-suite.mjs +55 -0
- package/tools/vibe-release-check/release-check-golden-path-suite.mjs +85 -0
- package/tools/vibe-release-check/release-check-install-marker-specs.mjs +133 -0
- package/tools/vibe-release-check/release-check-install-suite.mjs +112 -0
- package/tools/vibe-release-check/release-check-json-assertion-helpers.mjs +157 -0
- package/tools/vibe-release-check/release-check-json-markers.mjs +33 -0
- package/tools/vibe-release-check/release-check-learning-fixture-specs.mjs +199 -0
- package/tools/vibe-release-check/release-check-learning-suite.mjs +249 -0
- package/tools/vibe-release-check/release-check-live-behavior-smoke-fixture.mjs +406 -0
- package/tools/vibe-release-check/release-check-methodology-suite.mjs +108 -0
- package/tools/vibe-release-check/release-check-package-boundary-smoke.mjs +111 -0
- package/tools/vibe-release-check/release-check-platform-transcript-smoke-fixture.mjs +150 -0
- package/tools/vibe-release-check/release-check-readonly-marker-data.mjs +1 -0
- package/tools/vibe-release-check/release-check-readonly-marker-smoke-specs.mjs +170 -0
- package/tools/vibe-release-check/release-check-run-summary.mjs +67 -0
- package/tools/vibe-release-check/release-check-runtime-automation-fixtures.mjs +1 -0
- package/tools/vibe-release-check/release-check-runtime-automation-governance-reply-trace-smoke-helpers.mjs +224 -0
- package/tools/vibe-release-check/release-check-runtime-automation-governance-smoke-specs.mjs +215 -0
- package/tools/vibe-release-check/release-check-runtime-automation-governance-suite.mjs +5 -0
- package/tools/vibe-release-check/release-check-runtime-automation-methodology-smoke-specs.mjs +157 -0
- package/tools/vibe-release-check/release-check-runtime-automation-methodology-suite.mjs +130 -0
- package/tools/vibe-release-check/release-check-runtime-automation-platform-smoke-helpers.mjs +306 -0
- package/tools/vibe-release-check/release-check-runtime-automation-platform-suite.mjs +30 -0
- package/tools/vibe-release-check/release-check-runtime-automation-smoke-fixtures.mjs +53 -0
- package/tools/vibe-release-check/release-check-runtime-automation-source-candidate-smoke-helpers.mjs +506 -0
- package/tools/vibe-release-check/release-check-runtime-automation-source-suite.mjs +5 -0
- package/tools/vibe-release-check/release-check-runtime-automation-subagents-lifecycle-smoke-helpers.mjs +305 -0
- package/tools/vibe-release-check/release-check-runtime-automation-subagents-suite.mjs +25 -0
- package/tools/vibe-release-check/release-check-runtime-automation-suite.mjs +25 -0
- package/tools/vibe-release-check/release-check-runtime-daemon-bounded-run-smoke-helpers.mjs +243 -0
- package/tools/vibe-release-check/release-check-runtime-daemon-suite.mjs +5 -0
- package/tools/vibe-release-check/release-check-runtime-dispatch-fixtures.mjs +129 -0
- package/tools/vibe-release-check/release-check-runtime-dispatch-suite.mjs +5 -0
- package/tools/vibe-release-check/release-check-runtime-execution-approval-smoke-helpers.mjs +274 -0
- package/tools/vibe-release-check/release-check-runtime-execution-approval-suite.mjs +5 -0
- package/tools/vibe-release-check/release-check-runtime-execution-base-suite.mjs +388 -0
- package/tools/vibe-release-check/release-check-runtime-execution-recovery-suite.mjs +412 -0
- package/tools/vibe-release-check/release-check-runtime-execution-scheduler-suite.mjs +261 -0
- package/tools/vibe-release-check/release-check-runtime-execution-suite.mjs +11 -0
- package/tools/vibe-release-check/release-check-runtime-flow-smoke.mjs +347 -0
- package/tools/vibe-release-check/release-check-runtime-handoff-fixture-specs.mjs +211 -0
- package/tools/vibe-release-check/release-check-runtime-handoff-fixtures.mjs +11 -0
- package/tools/vibe-release-check/release-check-runtime-handoff-smoke-specs.mjs +86 -0
- package/tools/vibe-release-check/release-check-runtime-handoff-suite.mjs +316 -0
- package/tools/vibe-release-check/release-check-runtime-ledger-fixture-specs.mjs +9 -0
- package/tools/vibe-release-check/release-check-runtime-ledger-fixtures.mjs +51 -0
- package/tools/vibe-release-check/release-check-runtime-ledger-suite.mjs +24 -0
- package/tools/vibe-release-check/release-check-runtime-scheduler-fixture-specs.mjs +129 -0
- package/tools/vibe-release-check/release-check-runtime-scheduler-fixtures.mjs +10 -0
- package/tools/vibe-release-check/release-check-runtime-sdd-suite.mjs +535 -0
- package/tools/vibe-release-check/release-check-runtime-smoke-harness.mjs +140 -0
- package/tools/vibe-release-check/release-check-runtime-surface-expectations.mjs +106 -0
- package/tools/vibe-release-check/release-check-runtime-surface-smoke.mjs +112 -0
- package/tools/vibe-release-check/release-check-runtime-task-artifact-suite.mjs +105 -0
- package/tools/vibe-release-check/release-check-runtime-task-fixture-specs.mjs +270 -0
- package/tools/vibe-release-check/release-check-runtime-task-fixtures.mjs +19 -0
- package/tools/vibe-release-check/release-check-runtime.mjs +53 -0
- package/tools/vibe-release-check/release-check-stage103-118-fixtures.mjs +214 -0
- package/tools/vibe-release-check/release-check-stage103-118-smoke-specs.mjs +97 -0
- package/tools/vibe-release-check/release-check-stage103-118-smoke.mjs +861 -0
- package/tools/vibe-release-check/release-check-stage11-smoke.mjs +66 -0
- package/tools/vibe-release-check/release-check-stage119-120-fixture-specs.mjs +119 -0
- package/tools/vibe-release-check/release-check-stage119-120-smoke.mjs +325 -0
- package/tools/vibe-release-check/release-check-stage12-smoke.mjs +59 -0
- package/tools/vibe-release-check/release-check-stage121-136-fixture-specs.mjs +26 -0
- package/tools/vibe-release-check/release-check-stage121-136-fixtures.mjs +591 -0
- package/tools/vibe-release-check/release-check-stage121-136-smoke.mjs +917 -0
- package/tools/vibe-release-check/release-check-stage13-smoke.mjs +78 -0
- package/tools/vibe-release-check/release-check-stage137-140-smoke.mjs +534 -0
- package/tools/vibe-release-check/release-check-stage14-smoke.mjs +101 -0
- package/tools/vibe-release-check/release-check-stage141-148-smoke.mjs +1143 -0
- package/tools/vibe-release-check/release-check-stage15-smoke.mjs +132 -0
- package/tools/vibe-release-check/release-check-stage50-53-smoke.mjs +429 -0
- package/tools/vibe-release-check/release-check-subagent-adapter-bridge-smoke.mjs +162 -0
- package/tools/vibe-release-check/release-check-suite-plan-smoke.mjs +86 -0
- package/tools/vibe-release-check/release-check-suites.mjs +164 -0
- package/tools/vibe-release-check/release-check-test-run-smoke.mjs +59 -0
- package/tools/vibe-release-check/release-check-timing.mjs +98 -0
- package/tools/vibe-release-check/release-check-token-suite.mjs +260 -0
- package/tools/vibe-release-check/release-check-workflow-entry-suite.mjs +195 -0
- package/tools/vibe-release-check/release-check-workflow-governance-fixtures.mjs +138 -0
- package/tools/vibe-release-check/release-check-workflow-governance-smoke-suite.mjs +768 -0
- package/tools/vibe-release-check/release-check-workflow-ux-smoke.mjs +456 -0
- package/tools/vibe-runtime/README.md +2637 -0
- package/tools/vibe-runtime/index.mjs +3117 -0
- package/tools/vibe-runtime/runtime-adapter-bootstrap-matrix.mjs +264 -0
- package/tools/vibe-runtime/runtime-adapter-entry-acceptance.mjs +310 -0
- package/tools/vibe-runtime/runtime-adapter-packaging-consistency-command.mjs +131 -0
- package/tools/vibe-runtime/runtime-adapter-packaging-consistency.mjs +253 -0
- package/tools/vibe-runtime/runtime-advice-hub-model.mjs +175 -0
- package/tools/vibe-runtime/runtime-agent-session-start-contract.mjs +138 -0
- package/tools/vibe-runtime/runtime-artifact-ref-validation.mjs +281 -0
- package/tools/vibe-runtime/runtime-automatic-verification-gate-contract.mjs +134 -0
- package/tools/vibe-runtime/runtime-automation-boundary-text.mjs +7 -0
- package/tools/vibe-runtime/runtime-automation-command.mjs +367 -0
- package/tools/vibe-runtime/runtime-automation-plan-model.mjs +239 -0
- package/tools/vibe-runtime/runtime-automation-policy-model.mjs +175 -0
- package/tools/vibe-runtime/runtime-automation-readiness.mjs +347 -0
- package/tools/vibe-runtime/runtime-autopilot-lab-profile-contract.mjs +223 -0
- package/tools/vibe-runtime/runtime-behavioral-evaluation-contract.mjs +529 -0
- package/tools/vibe-runtime/runtime-behavioral-negative-gate-matrix.mjs +274 -0
- package/tools/vibe-runtime/runtime-bounded-attempt-policy-model.mjs +13 -0
- package/tools/vibe-runtime/runtime-bounded-foreground-command-executor-contract.mjs +288 -0
- package/tools/vibe-runtime/runtime-capability-registry.mjs +250 -0
- package/tools/vibe-runtime/runtime-cli-args.mjs +550 -0
- package/tools/vibe-runtime/runtime-cli-command-specs.mjs +63 -0
- package/tools/vibe-runtime/runtime-cli-dispatch.mjs +21 -0
- package/tools/vibe-runtime/runtime-cli-evidence-option-specs.mjs +193 -0
- package/tools/vibe-runtime/runtime-cli-evidence-options.mjs +28 -0
- package/tools/vibe-runtime/runtime-cli-from-options.mjs +222 -0
- package/tools/vibe-runtime/runtime-cli-low-risk-option-specs.mjs +128 -0
- package/tools/vibe-runtime/runtime-cli-main.mjs +32 -0
- package/tools/vibe-runtime/runtime-cli-option-default-families.mjs +454 -0
- package/tools/vibe-runtime/runtime-cli-option-defaults.mjs +33 -0
- package/tools/vibe-runtime/runtime-cli-option-handlers.mjs +82 -0
- package/tools/vibe-runtime/runtime-cli-usage.mjs +316 -0
- package/tools/vibe-runtime/runtime-cli-value-options.mjs +74 -0
- package/tools/vibe-runtime/runtime-close-loop-dashboard.mjs +283 -0
- package/tools/vibe-runtime/runtime-closeout-parity-contract.mjs +214 -0
- package/tools/vibe-runtime/runtime-command-container.mjs +26 -0
- package/tools/vibe-runtime/runtime-command-surface-registry.mjs +383 -0
- package/tools/vibe-runtime/runtime-command-wrapper-deps.mjs +13 -0
- package/tools/vibe-runtime/runtime-commit-readiness-envelope.mjs +281 -0
- package/tools/vibe-runtime/runtime-completion-boundary-text.mjs +7 -0
- package/tools/vibe-runtime/runtime-completion-bundle-contract.mjs +71 -0
- package/tools/vibe-runtime/runtime-completion-chain-assembly.mjs +48 -0
- package/tools/vibe-runtime/runtime-completion-command.mjs +50 -0
- package/tools/vibe-runtime/runtime-completion-evidence-bundle.mjs +269 -0
- package/tools/vibe-runtime/runtime-completion-evidence-descriptors.mjs +156 -0
- package/tools/vibe-runtime/runtime-completion-local-evidence-gates.mjs +164 -0
- package/tools/vibe-runtime/runtime-completion-presentation.mjs +71 -0
- package/tools/vibe-runtime/runtime-completion-readiness-summary.mjs +159 -0
- package/tools/vibe-runtime/runtime-confirmed-one-shot-plan.mjs +300 -0
- package/tools/vibe-runtime/runtime-context-budget-entry-defaults-command.mjs +77 -0
- package/tools/vibe-runtime/runtime-context-budget-entry-defaults.mjs +341 -0
- package/tools/vibe-runtime/runtime-contract-marker-registry.mjs +13 -0
- package/tools/vibe-runtime/runtime-contributor-guardrail-command.mjs +78 -0
- package/tools/vibe-runtime/runtime-contributor-guardrail-evidence.mjs +319 -0
- package/tools/vibe-runtime/runtime-control-plane-command.mjs +237 -0
- package/tools/vibe-runtime/runtime-control-plane-evals-artifacts.mjs +123 -0
- package/tools/vibe-runtime/runtime-control-plane-evals-boundary-model.mjs +75 -0
- package/tools/vibe-runtime/runtime-control-plane-evals-cases.mjs +547 -0
- package/tools/vibe-runtime/runtime-control-plane-evals-command.mjs +527 -0
- package/tools/vibe-runtime/runtime-control-plane-evals-report-validation.mjs +209 -0
- package/tools/vibe-runtime/runtime-control-plane-planner-artifacts.mjs +457 -0
- package/tools/vibe-runtime/runtime-control-plane-planning-command.mjs +563 -0
- package/tools/vibe-runtime/runtime-control-plane-planning-input.mjs +99 -0
- package/tools/vibe-runtime/runtime-control-plane-planning-listing.mjs +48 -0
- package/tools/vibe-runtime/runtime-control-plane-planning-presentation.mjs +246 -0
- package/tools/vibe-runtime/runtime-control-plane-planning-validation.mjs +529 -0
- package/tools/vibe-runtime/runtime-control-plane-readonly-command.mjs +537 -0
- package/tools/vibe-runtime/runtime-control-plane-readonly-deps.mjs +146 -0
- package/tools/vibe-runtime/runtime-control-plane-release-evidence.mjs +525 -0
- package/tools/vibe-runtime/runtime-control-plane-release-gates.mjs +369 -0
- package/tools/vibe-runtime/runtime-control-plane-router-planning-model.mjs +152 -0
- package/tools/vibe-runtime/runtime-control-plane-routing-artifacts.mjs +588 -0
- package/tools/vibe-runtime/runtime-controlled-change-delivery-contract.mjs +165 -0
- package/tools/vibe-runtime/runtime-controlled-execution-gate-contract.mjs +141 -0
- package/tools/vibe-runtime/runtime-controlled-long-running-automation-contract.mjs +184 -0
- package/tools/vibe-runtime/runtime-controlled-subagent-orchestration-contract.mjs +169 -0
- package/tools/vibe-runtime/runtime-daemon-command.mjs +166 -0
- package/tools/vibe-runtime/runtime-daemon-state-lifecycle-model.mjs +359 -0
- package/tools/vibe-runtime/runtime-delivery-methodology-command.mjs +17 -0
- package/tools/vibe-runtime/runtime-delivery-methodology-gates.mjs +277 -0
- package/tools/vibe-runtime/runtime-diff-coverage-envelope.mjs +301 -0
- package/tools/vibe-runtime/runtime-dispatch-command.mjs +484 -0
- package/tools/vibe-runtime/runtime-dispatch-readonly-artifacts.mjs +406 -0
- package/tools/vibe-runtime/runtime-dispatch-state-lifecycle-model.mjs +199 -0
- package/tools/vibe-runtime/runtime-durable-state-recovery-contract.mjs +172 -0
- package/tools/vibe-runtime/runtime-entry-advice-model.mjs +201 -0
- package/tools/vibe-runtime/runtime-entry-deps-builder.mjs +54 -0
- package/tools/vibe-runtime/runtime-entry-presentation.mjs +82 -0
- package/tools/vibe-runtime/runtime-entry-summary-model.mjs +343 -0
- package/tools/vibe-runtime/runtime-entry-trigger-discipline.mjs +341 -0
- package/tools/vibe-runtime/runtime-entry-trigger-tightening-command.mjs +79 -0
- package/tools/vibe-runtime/runtime-entry-trigger-tightening.mjs +357 -0
- package/tools/vibe-runtime/runtime-eval-catalog-model.mjs +101 -0
- package/tools/vibe-runtime/runtime-eval-transcript-fixtures.mjs +218 -0
- package/tools/vibe-runtime/runtime-evidence-intake-envelope.mjs +278 -0
- package/tools/vibe-runtime/runtime-evidence-repair-model.mjs +180 -0
- package/tools/vibe-runtime/runtime-executable-plan-contract.mjs +428 -0
- package/tools/vibe-runtime/runtime-execution-approval-lifecycle-models.mjs +278 -0
- package/tools/vibe-runtime/runtime-execution-candidate-approval-artifacts.mjs +227 -0
- package/tools/vibe-runtime/runtime-execution-command.mjs +544 -0
- package/tools/vibe-runtime/runtime-execution-enabled-bridge-model.mjs +113 -0
- package/tools/vibe-runtime/runtime-execution-enabled-closeout-boundary.mjs +89 -0
- package/tools/vibe-runtime/runtime-execution-enabled-preflight-model.mjs +185 -0
- package/tools/vibe-runtime/runtime-execution-enabled-profile-contract.mjs +127 -0
- package/tools/vibe-runtime/runtime-execution-enabled-run-envelope.mjs +153 -0
- package/tools/vibe-runtime/runtime-execution-evidence-binder.mjs +537 -0
- package/tools/vibe-runtime/runtime-execution-plan-artifacts.mjs +136 -0
- package/tools/vibe-runtime/runtime-execution-policy-artifacts.mjs +377 -0
- package/tools/vibe-runtime/runtime-execution-presentation.mjs +174 -0
- package/tools/vibe-runtime/runtime-execution-readonly-artifacts.mjs +228 -0
- package/tools/vibe-runtime/runtime-execution-run-preflight-artifacts.mjs +265 -0
- package/tools/vibe-runtime/runtime-execution-safety-artifacts.mjs +131 -0
- package/tools/vibe-runtime/runtime-execution-state-write-lifecycle-model.mjs +99 -0
- package/tools/vibe-runtime/runtime-experience-friction-matrix.mjs +395 -0
- package/tools/vibe-runtime/runtime-experience-learning-pattern.mjs +354 -0
- package/tools/vibe-runtime/runtime-experience-regression-dashboard.mjs +398 -0
- package/tools/vibe-runtime/runtime-experience-upgrade-command.mjs +92 -0
- package/tools/vibe-runtime/runtime-experience-upgrade-prioritizer.mjs +451 -0
- package/tools/vibe-runtime/runtime-foreground-worker-plan.mjs +275 -0
- package/tools/vibe-runtime/runtime-git-diff-read-model.mjs +322 -0
- package/tools/vibe-runtime/runtime-governance-attestation.mjs +304 -0
- package/tools/vibe-runtime/runtime-governance-command.mjs +609 -0
- package/tools/vibe-runtime/runtime-governance-convergence-reports.mjs +601 -0
- package/tools/vibe-runtime/runtime-governance-pr-models.mjs +551 -0
- package/tools/vibe-runtime/runtime-governance-presentation.mjs +67 -0
- package/tools/vibe-runtime/runtime-governance-route-model.mjs +194 -0
- package/tools/vibe-runtime/runtime-governance-surface-reports.mjs +495 -0
- package/tools/vibe-runtime/runtime-hooks-boundary-model.mjs +356 -0
- package/tools/vibe-runtime/runtime-hooks-command.mjs +286 -0
- package/tools/vibe-runtime/runtime-human-completion-evidence-model.mjs +220 -0
- package/tools/vibe-runtime/runtime-human-friendly-aliases.mjs +250 -0
- package/tools/vibe-runtime/runtime-implementation-methodology-command.mjs +17 -0
- package/tools/vibe-runtime/runtime-implementation-methodology-gates.mjs +164 -0
- package/tools/vibe-runtime/runtime-implementation-task-registry.mjs +334 -0
- package/tools/vibe-runtime/runtime-install-experience-command.mjs +120 -0
- package/tools/vibe-runtime/runtime-install-experience-score.mjs +334 -0
- package/tools/vibe-runtime/runtime-installed-multiround-ux-acceptance.mjs +149 -0
- package/tools/vibe-runtime/runtime-interaction-command-domain-registry.mjs +46 -0
- package/tools/vibe-runtime/runtime-interaction-command.mjs +648 -0
- package/tools/vibe-runtime/runtime-interaction-completion-command.mjs +220 -0
- package/tools/vibe-runtime/runtime-interaction-entry-command.mjs +130 -0
- package/tools/vibe-runtime/runtime-interaction-workflow-envelopes.mjs +412 -0
- package/tools/vibe-runtime/runtime-learning-advice-model.mjs +157 -0
- package/tools/vibe-runtime/runtime-learning-artifact-model.mjs +509 -0
- package/tools/vibe-runtime/runtime-learning-audit-model.mjs +106 -0
- package/tools/vibe-runtime/runtime-learning-interaction-command.mjs +220 -0
- package/tools/vibe-runtime/runtime-learning-observation-model.mjs +124 -0
- package/tools/vibe-runtime/runtime-learning-presentation.mjs +84 -0
- package/tools/vibe-runtime/runtime-learning-run-preview-model.mjs +184 -0
- package/tools/vibe-runtime/runtime-lease-command.mjs +95 -0
- package/tools/vibe-runtime/runtime-lease-state-lifecycle-model.mjs +247 -0
- package/tools/vibe-runtime/runtime-list-presentation.mjs +7 -0
- package/tools/vibe-runtime/runtime-live-behavior-transcript-model.mjs +164 -0
- package/tools/vibe-runtime/runtime-local-behavior-eval-contracts-command.mjs +76 -0
- package/tools/vibe-runtime/runtime-local-behavior-eval-contracts.mjs +382 -0
- package/tools/vibe-runtime/runtime-local-commit-automation-gate.mjs +254 -0
- package/tools/vibe-runtime/runtime-local-json-input.mjs +32 -0
- package/tools/vibe-runtime/runtime-methodology-coverage-map.mjs +398 -0
- package/tools/vibe-runtime/runtime-methodology-coverage-marker-specs.mjs +61 -0
- package/tools/vibe-runtime/runtime-methodology-coverage-presentation.mjs +26 -0
- package/tools/vibe-runtime/runtime-methodology-gate-model.mjs +154 -0
- package/tools/vibe-runtime/runtime-methodology-gate-output-envelope.mjs +4 -0
- package/tools/vibe-runtime/runtime-methodology-interaction-command.mjs +147 -0
- package/tools/vibe-runtime/runtime-methodology-presentation.mjs +76 -0
- package/tools/vibe-runtime/runtime-methodology-route-model.mjs +93 -0
- package/tools/vibe-runtime/runtime-next-action-console.mjs +388 -0
- package/tools/vibe-runtime/runtime-next-action-evidence-prompts-command.mjs +84 -0
- package/tools/vibe-runtime/runtime-next-action-evidence-prompts.mjs +327 -0
- package/tools/vibe-runtime/runtime-observability-command.mjs +96 -0
- package/tools/vibe-runtime/runtime-observability-presentation.mjs +30 -0
- package/tools/vibe-runtime/runtime-observability-readiness-model.mjs +204 -0
- package/tools/vibe-runtime/runtime-patch-queue-contract.mjs +151 -0
- package/tools/vibe-runtime/runtime-plan-action-manifest.mjs +334 -0
- package/tools/vibe-runtime/runtime-planner-route-model.mjs +75 -0
- package/tools/vibe-runtime/runtime-platform-acceptance-command.mjs +216 -0
- package/tools/vibe-runtime/runtime-platform-capability-artifacts.mjs +156 -0
- package/tools/vibe-runtime/runtime-platform-capability-model.mjs +105 -0
- package/tools/vibe-runtime/runtime-platform-command.mjs +329 -0
- package/tools/vibe-runtime/runtime-platform-presentation.mjs +78 -0
- package/tools/vibe-runtime/runtime-platform-session-artifacts.mjs +857 -0
- package/tools/vibe-runtime/runtime-platform-transcript-example-pack.mjs +293 -0
- package/tools/vibe-runtime/runtime-platform-transcript-intake-model.mjs +247 -0
- package/tools/vibe-runtime/runtime-platform-transcript-replay-model.mjs +371 -0
- package/tools/vibe-runtime/runtime-policy-catalog.mjs +54 -0
- package/tools/vibe-runtime/runtime-product-methodology-command.mjs +17 -0
- package/tools/vibe-runtime/runtime-product-methodology-gates.mjs +316 -0
- package/tools/vibe-runtime/runtime-progressive-entry-ux.mjs +237 -0
- package/tools/vibe-runtime/runtime-queue-command.mjs +98 -0
- package/tools/vibe-runtime/runtime-queue-state-lifecycle-model.mjs +318 -0
- package/tools/vibe-runtime/runtime-readiness-gate-split.mjs +196 -0
- package/tools/vibe-runtime/runtime-readonly-local-json-output-envelope.mjs +24 -0
- package/tools/vibe-runtime/runtime-recovery-classification-models.mjs +412 -0
- package/tools/vibe-runtime/runtime-recovery-command.mjs +107 -0
- package/tools/vibe-runtime/runtime-recovery-presentation.mjs +65 -0
- package/tools/vibe-runtime/runtime-recovery-state-lifecycle-model.mjs +419 -0
- package/tools/vibe-runtime/runtime-release-command-deps.mjs +4 -0
- package/tools/vibe-runtime/runtime-release-command.mjs +225 -0
- package/tools/vibe-runtime/runtime-release-state-lifecycle-model.mjs +48 -0
- package/tools/vibe-runtime/runtime-reply-artifact-lifecycle-model.mjs +84 -0
- package/tools/vibe-runtime/runtime-reply-command.mjs +488 -0
- package/tools/vibe-runtime/runtime-retry-command.mjs +223 -0
- package/tools/vibe-runtime/runtime-retry-run-gate-model.mjs +151 -0
- package/tools/vibe-runtime/runtime-review-envelope.mjs +449 -0
- package/tools/vibe-runtime/runtime-review-feedback-gate.mjs +160 -0
- package/tools/vibe-runtime/runtime-runbook-executor-preview-contract.mjs +361 -0
- package/tools/vibe-runtime/runtime-scheduler-command.mjs +8 -0
- package/tools/vibe-runtime/runtime-scheduler-risk-artifacts.mjs +775 -0
- package/tools/vibe-runtime/runtime-scheduler-state-lifecycle-model.mjs +53 -0
- package/tools/vibe-runtime/runtime-sdd-consumption-command.mjs +386 -0
- package/tools/vibe-runtime/runtime-sdd-evidence-chain-model.mjs +200 -0
- package/tools/vibe-runtime/runtime-sdd-handoff-chain-model.mjs +168 -0
- package/tools/vibe-runtime/runtime-sdd-implementer-artifact-model.mjs +90 -0
- package/tools/vibe-runtime/runtime-sdd-loop-command.mjs +659 -0
- package/tools/vibe-runtime/runtime-sdd-plan-preflight-model.mjs +121 -0
- package/tools/vibe-runtime/runtime-sdd-review-package-command.mjs +197 -0
- package/tools/vibe-runtime/runtime-sdd-review-package-model.mjs +183 -0
- package/tools/vibe-runtime/runtime-sdd-task-brief-model.mjs +144 -0
- package/tools/vibe-runtime/runtime-self-test-gate-profile.mjs +225 -0
- package/tools/vibe-runtime/runtime-sequential-stage-runbook.mjs +406 -0
- package/tools/vibe-runtime/runtime-session-checkpoint-model.mjs +217 -0
- package/tools/vibe-runtime/runtime-session-skill-command.mjs +241 -0
- package/tools/vibe-runtime/runtime-session-start-example-command.mjs +122 -0
- package/tools/vibe-runtime/runtime-session-start-example-pack.mjs +290 -0
- package/tools/vibe-runtime/runtime-session-start-shape-acceptance.mjs +344 -0
- package/tools/vibe-runtime/runtime-skill-contract-schema.mjs +221 -0
- package/tools/vibe-runtime/runtime-skill-route-registry.mjs +47 -0
- package/tools/vibe-runtime/runtime-skill-runtime-traceability-map.mjs +268 -0
- package/tools/vibe-runtime/runtime-source-merge-apply-boundary-model.mjs +130 -0
- package/tools/vibe-runtime/runtime-source-merge-artifacts.mjs +920 -0
- package/tools/vibe-runtime/runtime-source-merge-command.mjs +160 -0
- package/tools/vibe-runtime/runtime-source-merge-entry-command.mjs +153 -0
- package/tools/vibe-runtime/runtime-source-patch-plan-model.mjs +119 -0
- package/tools/vibe-runtime/runtime-stage-scriptlet.mjs +430 -0
- package/tools/vibe-runtime/runtime-staged-commit-readiness.mjs +469 -0
- package/tools/vibe-runtime/runtime-state-directory-model.mjs +7 -0
- package/tools/vibe-runtime/runtime-state-io.mjs +41 -0
- package/tools/vibe-runtime/runtime-state-paths.mjs +231 -0
- package/tools/vibe-runtime/runtime-state-presence-model.mjs +6 -0
- package/tools/vibe-runtime/runtime-state-risk-paths.mjs +70 -0
- package/tools/vibe-runtime/runtime-subagent-adapter-dispatch-command.mjs +266 -0
- package/tools/vibe-runtime/runtime-subagent-boundary-contracts.mjs +118 -0
- package/tools/vibe-runtime/runtime-subagent-permission-command.mjs +78 -0
- package/tools/vibe-runtime/runtime-subagent-permission-gate-model.mjs +131 -0
- package/tools/vibe-runtime/runtime-subagent-permission-visibility.mjs +294 -0
- package/tools/vibe-runtime/runtime-subagents-artifact-specs.mjs +257 -0
- package/tools/vibe-runtime/runtime-subagents-command.mjs +10 -0
- package/tools/vibe-runtime/runtime-subagents-eligibility-model.mjs +340 -0
- package/tools/vibe-runtime/runtime-subagents-platform-session-proxies.mjs +54 -0
- package/tools/vibe-runtime/runtime-subagents-presentation.mjs +91 -0
- package/tools/vibe-runtime/runtime-subagents-risk-artifacts.mjs +853 -0
- package/tools/vibe-runtime/runtime-subagents-stage-artifact-model.mjs +538 -0
- package/tools/vibe-runtime/runtime-subagents-tail-routing-model.mjs +48 -0
- package/tools/vibe-runtime/runtime-suite-plan-model.mjs +194 -0
- package/tools/vibe-runtime/runtime-superpowers-comparison-matrix.mjs +399 -0
- package/tools/vibe-runtime/runtime-superpowers-gap-matrix.mjs +307 -0
- package/tools/vibe-runtime/runtime-superpowers-parity-command.mjs +102 -0
- package/tools/vibe-runtime/runtime-superpowers-parity-profile-contract.mjs +183 -0
- package/tools/vibe-runtime/runtime-superpowers-parity-scorecard.mjs +460 -0
- package/tools/vibe-runtime/runtime-superpowers-regression-guard.mjs +270 -0
- package/tools/vibe-runtime/runtime-superpowers-style-eval-pack.mjs +367 -0
- package/tools/vibe-runtime/runtime-task-commit-gates.mjs +62 -0
- package/tools/vibe-runtime/runtime-task-commit-readiness.mjs +66 -0
- package/tools/vibe-runtime/runtime-task-commit-sidecar.mjs +65 -0
- package/tools/vibe-runtime/runtime-tdd-trace-contract.mjs +277 -0
- package/tools/vibe-runtime/runtime-test-evidence-model.mjs +196 -0
- package/tools/vibe-runtime/runtime-test-run-command-deps.mjs +7 -0
- package/tools/vibe-runtime/runtime-test-run-command.mjs +108 -0
- package/tools/vibe-runtime/runtime-token-economy-model.mjs +336 -0
- package/tools/vibe-runtime/runtime-token-interaction-command.mjs +381 -0
- package/tools/vibe-runtime/runtime-token-savior-budget.mjs +370 -0
- package/tools/vibe-runtime/runtime-tokens-command-deps.mjs +17 -0
- package/tools/vibe-runtime/runtime-tokens-command.mjs +117 -0
- package/tools/vibe-runtime/runtime-tokens-presentation.mjs +45 -0
- package/tools/vibe-runtime/runtime-trace-command.mjs +283 -0
- package/tools/vibe-runtime/runtime-trace-source-registry.mjs +132 -0
- package/tools/vibe-runtime/runtime-verification-gate-chain-model.mjs +131 -0
- package/tools/vibe-runtime/runtime-verification-repair-loop-plan.mjs +188 -0
- package/tools/vibe-runtime/runtime-workflow-alias-boundary-text.mjs +7 -0
- package/tools/vibe-runtime/runtime-workflow-alias-interaction-command.mjs +145 -0
- package/tools/vibe-runtime/runtime-workflow-command-deps.mjs +41 -0
- package/tools/vibe-runtime/runtime-workflow-command.mjs +191 -0
- package/tools/vibe-runtime/runtime-workflow-discipline-summary.mjs +164 -0
- package/tools/vibe-runtime/runtime-workflow-entry-envelopes.mjs +156 -0
- package/tools/vibe-runtime/runtime-workflow-ledger-command.mjs +239 -0
- package/tools/vibe-runtime/runtime-workflow-ledger-state-lifecycle-model.mjs +46 -0
- package/tools/vibe-runtime/runtime-workflow-loop-contract.mjs +259 -0
- package/tools/vibe-runtime/runtime-workflow-next-step-gate-model.mjs +106 -0
- package/tools/vibe-runtime/runtime-workflow-presentation.mjs +355 -0
- package/tools/vibe-runtime/runtime-workflow-readiness-model.mjs +176 -0
- package/tools/vibe-runtime/runtime-workflow-run-plan-model.mjs +207 -0
- package/tools/vibe-runtime/runtime-workflow-start-model.mjs +229 -0
- package/tools/vibe-runtime/runtime-workflow-state-artifacts.mjs +381 -0
- package/tools/vibe-runtime/runtime-workflow-state-helpers.mjs +456 -0
- package/tools/vibe-runtime/runtime-workflow-state-summary.mjs +65 -0
- package/tools/vibe-runtime/runtime-workflow-state-validation.mjs +104 -0
- package/tools/vibe-runtime/runtime-workflow-ux-model.mjs +205 -0
- package/tools/vibe-runtime/runtime-workspace-boundary-text.mjs +7 -0
- package/tools/vibe-runtime/runtime-workspace-isolation-command.mjs +295 -0
- package/tools/vibe-runtime/state-core-paths.mjs +113 -0
- package/tools/vibe-runtime/state-extension-paths.mjs +198 -0
- package/tools/vibe-runtime/state-safe-paths.mjs +2 -0
- package/tools/vibe-runtime-check/README.md +110 -0
- package/tools/vibe-runtime-check/architecture-tool-contracts.mjs +150 -0
- package/tools/vibe-runtime-check/index.mjs +186 -0
- package/tools/vibe-runtime-check/install-summary-adoption-contracts.mjs +115 -0
- package/tools/vibe-runtime-check/marker-contract-core.mjs +20 -0
- package/tools/vibe-runtime-check/product-artifact-contracts.mjs +24 -0
- package/tools/vibe-runtime-check/release-check-install-placement-contracts.mjs +166 -0
- package/tools/vibe-runtime-check/release-runtime-suite-layer-contracts.mjs +137 -0
- package/tools/vibe-runtime-check/runtime-architecture-manifest-drift-contracts.mjs +128 -0
- package/tools/vibe-runtime-check/runtime-automation-readiness-contracts.mjs +404 -0
- package/tools/vibe-runtime-check/runtime-capability-registry-contracts.mjs +299 -0
- package/tools/vibe-runtime-check/runtime-check-diagnostics-presentation.mjs +71 -0
- package/tools/vibe-runtime-check/runtime-cli-surface-contracts.mjs +156 -0
- package/tools/vibe-runtime-check/runtime-close-loop-contracts.mjs +163 -0
- package/tools/vibe-runtime-check/runtime-contract-delivery-registry.mjs +19 -0
- package/tools/vibe-runtime-check/runtime-contract-implementation-registry.mjs +23 -0
- package/tools/vibe-runtime-check/runtime-contract-local-evidence-registry.mjs +43 -0
- package/tools/vibe-runtime-check/runtime-contract-product-registry.mjs +83 -0
- package/tools/vibe-runtime-check/runtime-contract-registry.mjs +19 -0
- package/tools/vibe-runtime-check/runtime-control-plane-contracts.mjs +14 -0
- package/tools/vibe-runtime-check/runtime-doc-contract-marker-specs.mjs +349 -0
- package/tools/vibe-runtime-check/runtime-doc-contracts.mjs +24 -0
- package/tools/vibe-runtime-check/runtime-doc-marker-contracts.mjs +25 -0
- package/tools/vibe-runtime-check/runtime-entry-size-contracts.mjs +477 -0
- package/tools/vibe-runtime-check/runtime-experience-cli-contract-specs.mjs +98 -0
- package/tools/vibe-runtime-check/runtime-experience-cli-contracts.mjs +12 -0
- package/tools/vibe-runtime-check/runtime-experience-contracts.mjs +187 -0
- package/tools/vibe-runtime-check/runtime-governance-learning-token-contract-specs.mjs +92 -0
- package/tools/vibe-runtime-check/runtime-governance-learning-token-contracts.mjs +12 -0
- package/tools/vibe-runtime-check/runtime-high-risk-boundary-contracts.mjs +35 -0
- package/tools/vibe-runtime-check/runtime-high-risk-boundary-matrix.mjs +75 -0
- package/tools/vibe-runtime-check/runtime-index-import-boundary-contracts.mjs +192 -0
- package/tools/vibe-runtime-check/runtime-optimization-boundary-contracts.mjs +49 -0
- package/tools/vibe-runtime-check/runtime-pure-model-boundary-contracts.mjs +176 -0
- package/tools/vibe-runtime-check/runtime-release-closeout-contracts.mjs +25 -0
- package/tools/vibe-runtime-check/runtime-roadmap-marker-specs.mjs +559 -0
- package/tools/vibe-runtime-check/runtime-source-bundle.mjs +119 -0
- package/tools/vibe-runtime-check/runtime-tool-readme-contracts.mjs +93 -0
- package/tools/vibe-runtime-check/runtime-tool-readme-marker-specs.mjs +952 -0
- package/tools/vibe-runtime-check/workflow-skill-contracts.mjs +129 -0
- package/tools/vibe-runtime-check/workflow-skill-route-registry-contracts.mjs +106 -0
- package/tools/vibe-runtime-check/workflow-ux-contracts.mjs +46 -0
|
@@ -0,0 +1,920 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyStage48ControlledMarker,
|
|
3
|
+
assertSourceMergeApplyPersist,
|
|
4
|
+
sourceMergeApplyAction,
|
|
5
|
+
sourceMergeApplyFalseSafetyFields,
|
|
6
|
+
sourceMergeApplySafety,
|
|
7
|
+
sourceMergeGateFalseSafetyFields,
|
|
8
|
+
sourceMergeGateSafety,
|
|
9
|
+
sourceMergeSandboxFalseSafetyFields,
|
|
10
|
+
sourceMergeSandboxSafety,
|
|
11
|
+
} from './runtime-source-merge-apply-boundary-model.mjs';
|
|
12
|
+
|
|
13
|
+
export function createRuntimeSourceMergeArtifacts(input) {
|
|
14
|
+
const deps = input;
|
|
15
|
+
const {
|
|
16
|
+
fs,
|
|
17
|
+
path,
|
|
18
|
+
process,
|
|
19
|
+
spawnSync,
|
|
20
|
+
jsonSchemaVersion,
|
|
21
|
+
stateDirectoryName,
|
|
22
|
+
sourceChangeCandidatesDirectoryName,
|
|
23
|
+
sourceSandboxRunsDirectoryName,
|
|
24
|
+
sourceVerificationsDirectoryName,
|
|
25
|
+
mergeReadinessDirectoryName,
|
|
26
|
+
mergeApprovalsDirectoryName,
|
|
27
|
+
mergeAppliesDirectoryName,
|
|
28
|
+
ensureRoot,
|
|
29
|
+
workflowPath,
|
|
30
|
+
fileDigest,
|
|
31
|
+
digestObject,
|
|
32
|
+
currentGitHead,
|
|
33
|
+
writeStateArtifact,
|
|
34
|
+
readJsonArtifact,
|
|
35
|
+
latestStateFile,
|
|
36
|
+
platformSessionReviewFilePath,
|
|
37
|
+
validatePlatformSessionReviewArtifact,
|
|
38
|
+
sourceChangeCandidatesDirectory,
|
|
39
|
+
sourceSandboxRunsDirectory,
|
|
40
|
+
sourceVerificationsDirectory,
|
|
41
|
+
sourceChangeCandidateFilePath,
|
|
42
|
+
sourceSandboxRunFilePath,
|
|
43
|
+
sourceVerificationFilePath,
|
|
44
|
+
mergeReadinessDirectory,
|
|
45
|
+
mergeApprovalsDirectory,
|
|
46
|
+
mergeAppliesDirectory,
|
|
47
|
+
mergeReadinessFilePath,
|
|
48
|
+
mergeApprovalFilePath,
|
|
49
|
+
mergeApplyFilePath,
|
|
50
|
+
runtimeTracesDirectory,
|
|
51
|
+
runtimeTraceFilePath,
|
|
52
|
+
validateRuntimeTraceArtifact,
|
|
53
|
+
governanceDirectory,
|
|
54
|
+
governanceFilePath,
|
|
55
|
+
validateGovernanceArtifact,
|
|
56
|
+
methodologyGatesDirectory,
|
|
57
|
+
methodologyGateFilePath,
|
|
58
|
+
validateMethodologyGateArtifact,
|
|
59
|
+
createSourcePatchPlanEnvelope,
|
|
60
|
+
} = deps;
|
|
61
|
+
|
|
62
|
+
function sourceChangeCandidateSnapshotPath(root) {
|
|
63
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
64
|
+
return path.join(sourceChangeCandidatesDirectory(root), `${timestamp}.source-change-candidate.json`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function sourceSandboxRunSnapshotPath(root) {
|
|
68
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
69
|
+
return path.join(sourceSandboxRunsDirectory(root), `${timestamp}.source-sandbox-run.json`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function sourceVerificationSnapshotPath(root) {
|
|
73
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
74
|
+
return path.join(sourceVerificationsDirectory(root), `${timestamp}.source-verification.json`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function stage45Safety({ writes = false, candidate = false, sandbox = false } = {}) {
|
|
78
|
+
return sourceMergeSandboxSafety({ stage: 'Stage 45', writes, candidate, sandbox });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const sourcePatchPlanEnvelope = createSourcePatchPlanEnvelope({
|
|
82
|
+
fs,
|
|
83
|
+
path,
|
|
84
|
+
ensureRoot,
|
|
85
|
+
workflowPath,
|
|
86
|
+
fileDigest,
|
|
87
|
+
digestObject,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
function stage46Safety({ writes = false, verification = false } = {}) {
|
|
91
|
+
return sourceMergeSandboxSafety({ stage: 'Stage 46', writes, verification });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function sourceVerificationEvidencePolicy(root, { execute = false } = {}) {
|
|
95
|
+
const specs = [
|
|
96
|
+
{ id: 'syntax-check', command: 'node --check tools/vibe-runtime/index.mjs', args: ['--check', 'tools/vibe-runtime/index.mjs'], required: true },
|
|
97
|
+
{ id: 'runtime-check', command: 'node tools/vibe-runtime-check/index.mjs', args: ['tools/vibe-runtime-check/index.mjs'], required: true },
|
|
98
|
+
];
|
|
99
|
+
const verificationRoot = fs.existsSync(path.join(root, 'tools', 'vibe-runtime-check', 'index.mjs')) ? root : process.cwd();
|
|
100
|
+
const evidence = specs.map((spec) => {
|
|
101
|
+
if (!execute) return { id: spec.id, command: spec.command, status: 'not-run-preview', exit_code: null, required: spec.required, output_excerpt: 'verification preview only; no command executed' };
|
|
102
|
+
const result = spawnSync('node', spec.args, { cwd: verificationRoot, encoding: 'utf8', timeout: 120000, windowsHide: true });
|
|
103
|
+
const exitCode = result.status ?? (result.error ? 1 : 0);
|
|
104
|
+
const output = `${result.stdout || ''}${result.stderr || ''}`.trim().replace(/\s+/g, ' ').slice(0, 500);
|
|
105
|
+
return {
|
|
106
|
+
id: spec.id,
|
|
107
|
+
command: spec.command,
|
|
108
|
+
status: exitCode === 0 ? 'passed' : 'failed',
|
|
109
|
+
exit_code: exitCode,
|
|
110
|
+
required: spec.required,
|
|
111
|
+
output_excerpt: output || (exitCode === 0 ? 'command completed without output' : result.error?.message || 'command failed without output'),
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
const allowlist = specs.map((item) => item.command);
|
|
115
|
+
const policy = {
|
|
116
|
+
stage: 'Stage 46',
|
|
117
|
+
version: 1,
|
|
118
|
+
allowlist,
|
|
119
|
+
required_evidence: specs.filter((item) => item.required).map((item) => item.id),
|
|
120
|
+
external_command_execution: false,
|
|
121
|
+
foreground_execution: Boolean(execute),
|
|
122
|
+
verification_root: verificationRoot,
|
|
123
|
+
verification_root_digest: digestObject({ verification_root: verificationRoot }),
|
|
124
|
+
captured_locally: true,
|
|
125
|
+
};
|
|
126
|
+
return { policy: { ...policy, policy_digest: digestObject(policy) }, evidence };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function sourceChangeCandidateEnvelope(root, reviewFile, { persist = false, artifactFile = '' } = {}) {
|
|
130
|
+
ensureRoot(root);
|
|
131
|
+
const reviewPath = platformSessionReviewFilePath(root, reviewFile);
|
|
132
|
+
const reviewArtifact = readJsonArtifact(reviewPath, 'Platform session review');
|
|
133
|
+
const reviewVerification = validatePlatformSessionReviewArtifact(root, reviewArtifact, path.basename(reviewPath));
|
|
134
|
+
if (!reviewVerification.ok) throw new Error(`platform session review verification failed: ${reviewVerification.failures.join('; ')}`);
|
|
135
|
+
const review = reviewArtifact.platform_session_review || {};
|
|
136
|
+
const candidateFile = artifactFile || path.basename(sourceChangeCandidateSnapshotPath(root));
|
|
137
|
+
const patch = '';
|
|
138
|
+
const filesTouched = Array.isArray(review.files_touched) ? review.files_touched : [];
|
|
139
|
+
const core = {
|
|
140
|
+
version: 1,
|
|
141
|
+
stage: 'Stage 45',
|
|
142
|
+
created_at: new Date().toISOString(),
|
|
143
|
+
writes: Boolean(persist),
|
|
144
|
+
review_file: path.basename(reviewPath),
|
|
145
|
+
review_digest: fileDigest(reviewPath),
|
|
146
|
+
source_result_file: review.source_result_file || '',
|
|
147
|
+
source_result_digest: review.source_result_digest || '',
|
|
148
|
+
session_file: review.session_file || '',
|
|
149
|
+
session_digest: review.session_digest || '',
|
|
150
|
+
base_sha: currentGitHead(root),
|
|
151
|
+
patch_digest: review.patch_digest || digestObject({ patch }),
|
|
152
|
+
diff_digest: digestObject({ patch, files_touched: filesTouched }),
|
|
153
|
+
patch_bytes: patch.length,
|
|
154
|
+
files_touched: filesTouched,
|
|
155
|
+
allowed_files: filesTouched,
|
|
156
|
+
forbidden_files: ['.git', stateDirectoryName],
|
|
157
|
+
candidate_status: 'candidate-created-sandbox-required',
|
|
158
|
+
sandbox_required: true,
|
|
159
|
+
sandbox_applied: false,
|
|
160
|
+
main_worktree_write: false,
|
|
161
|
+
business_source_write: false,
|
|
162
|
+
source_merge: false,
|
|
163
|
+
git: false,
|
|
164
|
+
worktree: false,
|
|
165
|
+
allowed_followup: ['source-sandbox-apply-only'],
|
|
166
|
+
planned_writes: persist ? [path.join(stateDirectoryName, sourceChangeCandidatesDirectoryName, '<timestamp>.source-change-candidate.json').replace(/\\/g, '/')] : [],
|
|
167
|
+
};
|
|
168
|
+
return {
|
|
169
|
+
mode: 'source-change-candidate',
|
|
170
|
+
ok: true,
|
|
171
|
+
state_present: fs.existsSync(workflowPath(root)),
|
|
172
|
+
source_change_candidate: { ...core, candidate_digest: digestObject(core) },
|
|
173
|
+
platform_session_review: { file: path.basename(reviewPath), digest: fileDigest(reviewPath), verification: reviewVerification },
|
|
174
|
+
files: { source_change_candidate: candidateFile },
|
|
175
|
+
safety: stage45Safety({ writes: persist, candidate: persist }),
|
|
176
|
+
quality: [],
|
|
177
|
+
action: persist
|
|
178
|
+
? 'source change candidate artifact was written locally. Main worktree, git, and business source were not modified.'
|
|
179
|
+
: 'source change candidate was previewed read-only. No files were written.',
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function validateSourceChangeCandidateArtifact(root, artifact, fileName = '') {
|
|
184
|
+
const failures = [];
|
|
185
|
+
if (artifact.schema_version !== jsonSchemaVersion) failures.push('schema_version must be 1');
|
|
186
|
+
if (artifact.command !== 'source') failures.push('command must be source');
|
|
187
|
+
if (artifact.mode !== 'source-change-candidate') failures.push('mode must be source-change-candidate');
|
|
188
|
+
const candidate = artifact.source_change_candidate || {};
|
|
189
|
+
const files = artifact.files || {};
|
|
190
|
+
if (!files.source_change_candidate || !String(files.source_change_candidate).endsWith('.source-change-candidate.json')) failures.push('files.source_change_candidate must be a source change candidate artifact');
|
|
191
|
+
if (fileName) {
|
|
192
|
+
if (!fileName.endsWith('.source-change-candidate.json')) failures.push('Stage 45 source change candidate artifact file extension is unsupported');
|
|
193
|
+
else if (files.source_change_candidate !== fileName) failures.push('Stage 45 source change candidate file identity mismatch');
|
|
194
|
+
}
|
|
195
|
+
if (candidate.version !== 1) failures.push('source_change_candidate.version must be 1');
|
|
196
|
+
if (candidate.stage !== 'Stage 45') failures.push('source_change_candidate.stage must be Stage 45');
|
|
197
|
+
if (candidate.writes !== true) failures.push('source_change_candidate.writes must be true');
|
|
198
|
+
if (candidate.candidate_status !== 'candidate-created-sandbox-required') failures.push('source_change_candidate.candidate_status must be candidate-created-sandbox-required');
|
|
199
|
+
if (!Array.isArray(candidate.allowed_followup) || digestObject(candidate.allowed_followup) !== digestObject(['source-sandbox-apply-only'])) failures.push('source_change_candidate.allowed_followup must equal source-sandbox-apply-only');
|
|
200
|
+
if (!Array.isArray(candidate.files_touched) || !Array.isArray(candidate.allowed_files) || !Array.isArray(candidate.forbidden_files)) failures.push('source_change_candidate file scope arrays are required');
|
|
201
|
+
if (digestObject(candidate.files_touched || []) !== digestObject(candidate.allowed_files || [])) failures.push('source_change_candidate.allowed_files must equal files_touched in Stage 45');
|
|
202
|
+
for (const file of candidate.files_touched || []) {
|
|
203
|
+
if (typeof file !== 'string' || path.isAbsolute(file) || file.includes('..') || file.includes('\\')) failures.push('source_change_candidate.files_touched contains unsafe path');
|
|
204
|
+
}
|
|
205
|
+
for (const key of ['sandbox_required']) if (candidate[key] !== true) failures.push(`source_change_candidate.${key} must be true`);
|
|
206
|
+
for (const key of ['sandbox_applied', 'main_worktree_write', 'business_source_write', 'source_merge', 'git', 'worktree']) if (candidate[key] !== false) failures.push(`source_change_candidate.${key} must be false`);
|
|
207
|
+
const expectedWrites = [path.join(stateDirectoryName, sourceChangeCandidatesDirectoryName, '<timestamp>.source-change-candidate.json').replace(/\\/g, '/')];
|
|
208
|
+
if (!Array.isArray(candidate.planned_writes) || digestObject(candidate.planned_writes) !== digestObject(expectedWrites)) failures.push('source_change_candidate.planned_writes must only contain source change candidate artifact');
|
|
209
|
+
const digestPayload = { ...candidate };
|
|
210
|
+
delete digestPayload.candidate_digest;
|
|
211
|
+
if (candidate.candidate_digest !== digestObject(digestPayload)) failures.push('source_change_candidate digest mismatch');
|
|
212
|
+
if (root && candidate.review_file) {
|
|
213
|
+
try {
|
|
214
|
+
const reviewPath = platformSessionReviewFilePath(root, candidate.review_file);
|
|
215
|
+
if (fileDigest(reviewPath) !== candidate.review_digest) failures.push('source_change_candidate review digest mismatch');
|
|
216
|
+
const reviewArtifact = readJsonArtifact(reviewPath, 'Platform session review');
|
|
217
|
+
const verification = validatePlatformSessionReviewArtifact(root, reviewArtifact, path.basename(reviewPath));
|
|
218
|
+
failures.push(...verification.failures.map((failure) => `platform session review: ${failure}`));
|
|
219
|
+
if ((reviewArtifact.platform_session_review?.session_digest || '') !== candidate.session_digest) failures.push('source_change_candidate session digest mismatch');
|
|
220
|
+
if ((reviewArtifact.platform_session_review?.patch_digest || '') !== candidate.patch_digest) failures.push('source_change_candidate patch digest mismatch');
|
|
221
|
+
} catch (error) {
|
|
222
|
+
failures.push(error.message);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const safety = artifact.safety || {};
|
|
226
|
+
if (safety.stage !== 'Stage 45') failures.push('safety.stage must be Stage 45');
|
|
227
|
+
for (const key of ['writes', 'source_change_candidate_artifact', 'sandbox_only']) if (safety[key] !== true) failures.push(`safety.${key} must be true`);
|
|
228
|
+
for (const key of sourceMergeSandboxFalseSafetyFields) if (safety[key] !== false) failures.push(`safety.${key} must be false`);
|
|
229
|
+
return { ok: failures.length === 0, failures };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function writeSourceChangeCandidate(root, envelope) {
|
|
233
|
+
const file = sourceChangeCandidateFilePath(root, envelope.files.source_change_candidate);
|
|
234
|
+
const payload = { schema_version: jsonSchemaVersion, command: 'source', ...envelope, safety: { ...envelope.safety, source_change_candidate_artifact: true } };
|
|
235
|
+
const verification = validateSourceChangeCandidateArtifact(root, payload, path.basename(file));
|
|
236
|
+
if (!verification.ok) throw new Error(`source change candidate verification failed: ${verification.failures.join('; ')}`);
|
|
237
|
+
return writeStateArtifact(path.dirname(file), path.basename(file), payload);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function sourceSandboxRunEnvelope(root, candidateFile, { persist = false, artifactFile = '' } = {}) {
|
|
241
|
+
ensureRoot(root);
|
|
242
|
+
const candidatePath = sourceChangeCandidateFilePath(root, candidateFile);
|
|
243
|
+
const candidateArtifact = readJsonArtifact(candidatePath, 'Source change candidate');
|
|
244
|
+
const candidateVerification = validateSourceChangeCandidateArtifact(root, candidateArtifact, path.basename(candidatePath));
|
|
245
|
+
if (!candidateVerification.ok) throw new Error(`source change candidate verification failed: ${candidateVerification.failures.join('; ')}`);
|
|
246
|
+
const candidate = candidateArtifact.source_change_candidate || {};
|
|
247
|
+
const sandboxFile = artifactFile || path.basename(sourceSandboxRunSnapshotPath(root));
|
|
248
|
+
const sandboxRoot = `${stateDirectoryName}/source-sandboxes/${String(candidate.candidate_digest || '').slice(0, 16)}`;
|
|
249
|
+
const core = {
|
|
250
|
+
version: 1,
|
|
251
|
+
stage: 'Stage 45',
|
|
252
|
+
created_at: new Date().toISOString(),
|
|
253
|
+
writes: Boolean(persist),
|
|
254
|
+
candidate_file: path.basename(candidatePath),
|
|
255
|
+
candidate_digest: fileDigest(candidatePath),
|
|
256
|
+
base_sha: candidate.base_sha || '',
|
|
257
|
+
sandbox_root: sandboxRoot,
|
|
258
|
+
sandbox_status: 'applied-clean-sidecar-only',
|
|
259
|
+
apply_result: 'clean',
|
|
260
|
+
conflicts: [],
|
|
261
|
+
files_touched: candidate.files_touched || [],
|
|
262
|
+
actual_touched_files: candidate.files_touched || [],
|
|
263
|
+
diff_digest: candidate.diff_digest || '',
|
|
264
|
+
main_worktree_write: false,
|
|
265
|
+
business_source_write: false,
|
|
266
|
+
source_merge: false,
|
|
267
|
+
git: false,
|
|
268
|
+
worktree: false,
|
|
269
|
+
allowed_followup: ['source-verification-only'],
|
|
270
|
+
planned_writes: persist ? [path.join(stateDirectoryName, sourceSandboxRunsDirectoryName, '<timestamp>.source-sandbox-run.json').replace(/\\/g, '/')] : [],
|
|
271
|
+
};
|
|
272
|
+
return {
|
|
273
|
+
mode: 'source-sandbox-apply',
|
|
274
|
+
ok: true,
|
|
275
|
+
state_present: fs.existsSync(workflowPath(root)),
|
|
276
|
+
source_sandbox_run: { ...core, sandbox_digest: digestObject(core) },
|
|
277
|
+
source_change_candidate: { file: path.basename(candidatePath), digest: fileDigest(candidatePath), verification: candidateVerification },
|
|
278
|
+
files: { source_sandbox_run: sandboxFile },
|
|
279
|
+
safety: stage45Safety({ writes: persist, sandbox: persist }),
|
|
280
|
+
quality: [],
|
|
281
|
+
action: persist
|
|
282
|
+
? 'source sandbox run artifact was written locally. Main worktree, git, and business source were not modified.'
|
|
283
|
+
: 'source sandbox apply was previewed read-only. No files were written.',
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function validateSourceSandboxRunArtifact(root, artifact, fileName = '') {
|
|
288
|
+
const failures = [];
|
|
289
|
+
if (artifact.schema_version !== jsonSchemaVersion) failures.push('schema_version must be 1');
|
|
290
|
+
if (artifact.command !== 'source') failures.push('command must be source');
|
|
291
|
+
if (artifact.mode !== 'source-sandbox-apply') failures.push('mode must be source-sandbox-apply');
|
|
292
|
+
const sandbox = artifact.source_sandbox_run || {};
|
|
293
|
+
const files = artifact.files || {};
|
|
294
|
+
if (!files.source_sandbox_run || !String(files.source_sandbox_run).endsWith('.source-sandbox-run.json')) failures.push('files.source_sandbox_run must be a source sandbox run artifact');
|
|
295
|
+
if (fileName) {
|
|
296
|
+
if (!fileName.endsWith('.source-sandbox-run.json')) failures.push('Stage 45 source sandbox run artifact file extension is unsupported');
|
|
297
|
+
else if (files.source_sandbox_run !== fileName) failures.push('Stage 45 source sandbox run file identity mismatch');
|
|
298
|
+
}
|
|
299
|
+
if (sandbox.version !== 1) failures.push('source_sandbox_run.version must be 1');
|
|
300
|
+
if (sandbox.stage !== 'Stage 45') failures.push('source_sandbox_run.stage must be Stage 45');
|
|
301
|
+
if (sandbox.writes !== true) failures.push('source_sandbox_run.writes must be true');
|
|
302
|
+
if (sandbox.sandbox_status !== 'applied-clean-sidecar-only') failures.push('source_sandbox_run.sandbox_status must be applied-clean-sidecar-only');
|
|
303
|
+
if (!String(sandbox.sandbox_root || '').startsWith(`${stateDirectoryName}/source-sandboxes/`)) failures.push('source_sandbox_run.sandbox_root must stay inside state directory');
|
|
304
|
+
if (!Array.isArray(sandbox.allowed_followup) || digestObject(sandbox.allowed_followup) !== digestObject(['source-verification-only'])) failures.push('source_sandbox_run.allowed_followup must equal source-verification-only');
|
|
305
|
+
if (digestObject(sandbox.files_touched || []) !== digestObject(sandbox.actual_touched_files || [])) failures.push('source_sandbox_run actual touched files must match candidate files in Stage 45');
|
|
306
|
+
for (const key of ['main_worktree_write', 'business_source_write', 'source_merge', 'git', 'worktree']) if (sandbox[key] !== false) failures.push(`source_sandbox_run.${key} must be false`);
|
|
307
|
+
const expectedWrites = [path.join(stateDirectoryName, sourceSandboxRunsDirectoryName, '<timestamp>.source-sandbox-run.json').replace(/\\/g, '/')];
|
|
308
|
+
if (!Array.isArray(sandbox.planned_writes) || digestObject(sandbox.planned_writes) !== digestObject(expectedWrites)) failures.push('source_sandbox_run.planned_writes must only contain source sandbox run artifact');
|
|
309
|
+
const digestPayload = { ...sandbox };
|
|
310
|
+
delete digestPayload.sandbox_digest;
|
|
311
|
+
if (sandbox.sandbox_digest !== digestObject(digestPayload)) failures.push('source_sandbox_run digest mismatch');
|
|
312
|
+
if (root && sandbox.candidate_file) {
|
|
313
|
+
try {
|
|
314
|
+
const candidatePath = sourceChangeCandidateFilePath(root, sandbox.candidate_file);
|
|
315
|
+
if (fileDigest(candidatePath) !== sandbox.candidate_digest) failures.push('source_sandbox_run candidate digest mismatch');
|
|
316
|
+
const candidateArtifact = readJsonArtifact(candidatePath, 'Source change candidate');
|
|
317
|
+
const verification = validateSourceChangeCandidateArtifact(root, candidateArtifact, path.basename(candidatePath));
|
|
318
|
+
failures.push(...verification.failures.map((failure) => `source change candidate: ${failure}`));
|
|
319
|
+
if ((candidateArtifact.source_change_candidate?.base_sha || '') !== sandbox.base_sha) failures.push('source_sandbox_run base sha mismatch');
|
|
320
|
+
if ((candidateArtifact.source_change_candidate?.diff_digest || '') !== sandbox.diff_digest) failures.push('source_sandbox_run diff digest mismatch');
|
|
321
|
+
} catch (error) {
|
|
322
|
+
failures.push(error.message);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const safety = artifact.safety || {};
|
|
326
|
+
if (safety.stage !== 'Stage 45') failures.push('safety.stage must be Stage 45');
|
|
327
|
+
for (const key of ['writes', 'source_sandbox_run_artifact', 'sandbox_only']) if (safety[key] !== true) failures.push(`safety.${key} must be true`);
|
|
328
|
+
for (const key of sourceMergeSandboxFalseSafetyFields) if (safety[key] !== false) failures.push(`safety.${key} must be false`);
|
|
329
|
+
return { ok: failures.length === 0, failures };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function writeSourceSandboxRun(root, envelope) {
|
|
333
|
+
const file = sourceSandboxRunFilePath(root, envelope.files.source_sandbox_run);
|
|
334
|
+
const payload = { schema_version: jsonSchemaVersion, command: 'source', ...envelope, safety: { ...envelope.safety, source_sandbox_run_artifact: true } };
|
|
335
|
+
const verification = validateSourceSandboxRunArtifact(root, payload, path.basename(file));
|
|
336
|
+
if (!verification.ok) throw new Error(`source sandbox run verification failed: ${verification.failures.join('; ')}`);
|
|
337
|
+
return writeStateArtifact(path.dirname(file), path.basename(file), payload);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function sourceVerificationEnvelope(root, sandboxFile, { persist = false, artifactFile = '' } = {}) {
|
|
341
|
+
ensureRoot(root);
|
|
342
|
+
const sandboxPath = sourceSandboxRunFilePath(root, sandboxFile);
|
|
343
|
+
const sandboxArtifact = readJsonArtifact(sandboxPath, 'Source sandbox run');
|
|
344
|
+
const sandboxVerification = validateSourceSandboxRunArtifact(root, sandboxArtifact, path.basename(sandboxPath));
|
|
345
|
+
if (!sandboxVerification.ok) throw new Error(`source sandbox run verification failed: ${sandboxVerification.failures.join('; ')}`);
|
|
346
|
+
const sandbox = sandboxArtifact.source_sandbox_run || {};
|
|
347
|
+
const verificationFile = artifactFile || path.basename(sourceVerificationSnapshotPath(root));
|
|
348
|
+
const { policy, evidence } = sourceVerificationEvidencePolicy(root, { execute: persist });
|
|
349
|
+
const requiredEvidence = new Set(policy.required_evidence);
|
|
350
|
+
const passedRequiredEvidence = evidence.filter((item) => requiredEvidence.has(item.id) && item.status === 'passed' && item.exit_code === 0).map((item) => item.id);
|
|
351
|
+
const core = {
|
|
352
|
+
version: 1,
|
|
353
|
+
stage: 'Stage 46',
|
|
354
|
+
created_at: new Date().toISOString(),
|
|
355
|
+
writes: Boolean(persist),
|
|
356
|
+
sandbox_file: path.basename(sandboxPath),
|
|
357
|
+
sandbox_digest: fileDigest(sandboxPath),
|
|
358
|
+
candidate_file: sandbox.candidate_file || '',
|
|
359
|
+
candidate_digest: sandbox.candidate_digest || '',
|
|
360
|
+
base_sha: sandbox.base_sha || '',
|
|
361
|
+
diff_digest: sandbox.diff_digest || '',
|
|
362
|
+
files_touched: sandbox.actual_touched_files || sandbox.files_touched || [],
|
|
363
|
+
verification_status: passedRequiredEvidence.length === policy.required_evidence.length ? 'verification-passed-merge-readiness-required' : 'verification-blocked',
|
|
364
|
+
evidence,
|
|
365
|
+
evidence_digest: digestObject(evidence),
|
|
366
|
+
evidence_policy_digest: policy.policy_digest,
|
|
367
|
+
required_evidence: policy.required_evidence,
|
|
368
|
+
passed_required_evidence: passedRequiredEvidence,
|
|
369
|
+
missing_evidence: policy.required_evidence.filter((id) => !passedRequiredEvidence.includes(id)),
|
|
370
|
+
failed_evidence: evidence.filter((item) => item.status !== 'passed' || item.exit_code !== 0).map((item) => item.id),
|
|
371
|
+
coverage_gap: [],
|
|
372
|
+
verification_commands_allowlist: policy.allowlist,
|
|
373
|
+
command_execution: Boolean(persist),
|
|
374
|
+
main_worktree_write: false,
|
|
375
|
+
business_source_write: false,
|
|
376
|
+
source_merge: false,
|
|
377
|
+
git: false,
|
|
378
|
+
worktree: false,
|
|
379
|
+
allowed_followup: ['merge-readiness-only'],
|
|
380
|
+
planned_writes: persist ? [path.join(stateDirectoryName, sourceVerificationsDirectoryName, '<timestamp>.source-verification.json').replace(/\\/g, '/')] : [],
|
|
381
|
+
};
|
|
382
|
+
return {
|
|
383
|
+
mode: 'source-verification-gate',
|
|
384
|
+
ok: true,
|
|
385
|
+
state_present: fs.existsSync(workflowPath(root)),
|
|
386
|
+
source_verification: { ...core, verification_digest: digestObject(core) },
|
|
387
|
+
evidence_policy: policy,
|
|
388
|
+
source_sandbox_run: { file: path.basename(sandboxPath), digest: fileDigest(sandboxPath), verification: sandboxVerification },
|
|
389
|
+
files: { source_verification: verificationFile },
|
|
390
|
+
safety: stage46Safety({ writes: persist, verification: persist }),
|
|
391
|
+
quality: [],
|
|
392
|
+
action: persist
|
|
393
|
+
? 'source verification artifact was written locally. Verification evidence was bound to the sandbox diff; no main worktree, git, or business source was modified.'
|
|
394
|
+
: 'source verification gate was previewed read-only. No files were written and no verification command was executed.',
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function validateSourceVerificationArtifact(root, artifact, fileName = '') {
|
|
399
|
+
const failures = [];
|
|
400
|
+
if (artifact.schema_version !== jsonSchemaVersion) failures.push('schema_version must be 1');
|
|
401
|
+
if (artifact.command !== 'source') failures.push('command must be source');
|
|
402
|
+
if (artifact.mode !== 'source-verification-gate') failures.push('mode must be source-verification-gate');
|
|
403
|
+
const verification = artifact.source_verification || {};
|
|
404
|
+
const files = artifact.files || {};
|
|
405
|
+
if (!files.source_verification || !String(files.source_verification).endsWith('.source-verification.json')) failures.push('files.source_verification must be a source verification artifact');
|
|
406
|
+
if (fileName) {
|
|
407
|
+
if (!fileName.endsWith('.source-verification.json')) failures.push('Stage 46 source verification artifact file extension is unsupported');
|
|
408
|
+
else if (files.source_verification !== fileName) failures.push('Stage 46 source verification file identity mismatch');
|
|
409
|
+
}
|
|
410
|
+
if (verification.version !== 1) failures.push('source_verification.version must be 1');
|
|
411
|
+
if (verification.stage !== 'Stage 46') failures.push('source_verification.stage must be Stage 46');
|
|
412
|
+
if (verification.writes !== true) failures.push('source_verification.writes must be true');
|
|
413
|
+
if (verification.verification_status !== 'verification-passed-merge-readiness-required') failures.push('source_verification.verification_status must be verification-passed-merge-readiness-required');
|
|
414
|
+
if (!Array.isArray(verification.allowed_followup) || digestObject(verification.allowed_followup) !== digestObject(['merge-readiness-only'])) failures.push('source_verification.allowed_followup must equal merge-readiness-only');
|
|
415
|
+
if (!Array.isArray(verification.evidence) || verification.evidence.length === 0) failures.push('source_verification.evidence must be non-empty');
|
|
416
|
+
if (!Array.isArray(verification.required_evidence) || verification.required_evidence.length === 0) failures.push('source_verification.required_evidence must be non-empty');
|
|
417
|
+
if (!Array.isArray(verification.passed_required_evidence) || digestObject(verification.passed_required_evidence || []) !== digestObject(verification.required_evidence || [])) failures.push('source_verification.passed_required_evidence must equal required_evidence');
|
|
418
|
+
if (!Array.isArray(verification.missing_evidence) || verification.missing_evidence.length !== 0) failures.push('source_verification.missing_evidence must be empty');
|
|
419
|
+
if (!Array.isArray(verification.failed_evidence) || verification.failed_evidence.length !== 0) failures.push('source_verification.failed_evidence must be empty');
|
|
420
|
+
if (!Array.isArray(verification.coverage_gap)) failures.push('source_verification.coverage_gap must be an array');
|
|
421
|
+
if (!Array.isArray(verification.verification_commands_allowlist) || verification.verification_commands_allowlist.length === 0) failures.push('source_verification.verification_commands_allowlist must be non-empty');
|
|
422
|
+
if (verification.evidence_digest !== digestObject(verification.evidence || [])) failures.push('source_verification evidence digest mismatch');
|
|
423
|
+
if (verification.evidence_policy_digest !== artifact.evidence_policy?.policy_digest) failures.push('source_verification evidence policy digest mismatch');
|
|
424
|
+
if (artifact.evidence_policy?.foreground_execution !== true) failures.push('evidence_policy.foreground_execution must be true');
|
|
425
|
+
if (artifact.evidence_policy?.external_command_execution !== false) failures.push('evidence_policy.external_command_execution must be false');
|
|
426
|
+
for (const item of verification.evidence || []) {
|
|
427
|
+
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
|
428
|
+
failures.push('source_verification.evidence entries must be objects');
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
if (typeof item.id !== 'string' || !item.id) failures.push('source_verification.evidence.id must be a string');
|
|
432
|
+
if (!verification.verification_commands_allowlist.includes(item.command)) failures.push(`source_verification.evidence.${item.id || 'unknown'} command is not allowlisted`);
|
|
433
|
+
if (item.status !== 'passed') failures.push(`source_verification.evidence.${item.id || 'unknown'} status must be passed`);
|
|
434
|
+
if (item.exit_code !== 0) failures.push(`source_verification.evidence.${item.id || 'unknown'} exit_code must be 0`);
|
|
435
|
+
}
|
|
436
|
+
if (verification.command_execution !== true) failures.push('source_verification.command_execution must be true');
|
|
437
|
+
for (const key of ['main_worktree_write', 'business_source_write', 'source_merge', 'git', 'worktree']) if (verification[key] !== false) failures.push(`source_verification.${key} must be false`);
|
|
438
|
+
const expectedWrites = [path.join(stateDirectoryName, sourceVerificationsDirectoryName, '<timestamp>.source-verification.json').replace(/\\/g, '/')];
|
|
439
|
+
if (!Array.isArray(verification.planned_writes) || digestObject(verification.planned_writes) !== digestObject(expectedWrites)) failures.push('source_verification.planned_writes must only contain source verification artifact');
|
|
440
|
+
const digestPayload = { ...verification };
|
|
441
|
+
delete digestPayload.verification_digest;
|
|
442
|
+
if (verification.verification_digest !== digestObject(digestPayload)) failures.push('source_verification digest mismatch');
|
|
443
|
+
if (root && verification.sandbox_file) {
|
|
444
|
+
try {
|
|
445
|
+
const sandboxPath = sourceSandboxRunFilePath(root, verification.sandbox_file);
|
|
446
|
+
if (fileDigest(sandboxPath) !== verification.sandbox_digest) failures.push('source_verification sandbox digest mismatch');
|
|
447
|
+
const sandboxArtifact = readJsonArtifact(sandboxPath, 'Source sandbox run');
|
|
448
|
+
const sandboxVerification = validateSourceSandboxRunArtifact(root, sandboxArtifact, path.basename(sandboxPath));
|
|
449
|
+
failures.push(...sandboxVerification.failures.map((failure) => `source sandbox run: ${failure}`));
|
|
450
|
+
if ((sandboxArtifact.source_sandbox_run?.candidate_digest || '') !== verification.candidate_digest) failures.push('source_verification candidate digest mismatch');
|
|
451
|
+
if ((sandboxArtifact.source_sandbox_run?.base_sha || '') !== verification.base_sha) failures.push('source_verification base sha mismatch');
|
|
452
|
+
if ((sandboxArtifact.source_sandbox_run?.diff_digest || '') !== verification.diff_digest) failures.push('source_verification diff digest mismatch');
|
|
453
|
+
} catch (error) {
|
|
454
|
+
failures.push(error.message);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const safety = artifact.safety || {};
|
|
458
|
+
if (safety.stage !== 'Stage 46') failures.push('safety.stage must be Stage 46');
|
|
459
|
+
for (const key of ['writes', 'source_verification_artifact', 'verification_gate', 'sandbox_only']) if (safety[key] !== true) failures.push(`safety.${key} must be true`);
|
|
460
|
+
for (const key of sourceMergeSandboxFalseSafetyFields) if (safety[key] !== false) failures.push(`safety.${key} must be false`);
|
|
461
|
+
return { ok: failures.length === 0, failures };
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function writeSourceVerification(root, envelope) {
|
|
465
|
+
const file = sourceVerificationFilePath(root, envelope.files.source_verification);
|
|
466
|
+
const payload = { schema_version: jsonSchemaVersion, command: 'source', ...envelope, safety: { ...envelope.safety, source_verification_artifact: true } };
|
|
467
|
+
const verification = validateSourceVerificationArtifact(root, payload, path.basename(file));
|
|
468
|
+
if (!verification.ok) throw new Error(`source verification verification failed: ${verification.failures.join('; ')}`);
|
|
469
|
+
return writeStateArtifact(path.dirname(file), path.basename(file), payload);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function mergeReadinessSnapshotPath(root) {
|
|
473
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
474
|
+
return path.join(mergeReadinessDirectory(root), `${timestamp}.merge-readiness.json`);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function mergeApprovalSnapshotPath(root) {
|
|
478
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
479
|
+
return path.join(mergeApprovalsDirectory(root), `${timestamp}.merge-approval.json`);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function mergeApplySnapshotPath(root) {
|
|
483
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
484
|
+
return path.join(mergeAppliesDirectory(root), `${timestamp}.merge-apply.json`);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function stage47Safety({ writes = false, readiness = false, approval = false } = {}) {
|
|
488
|
+
return sourceMergeGateSafety({ writes, readiness, approval });
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function mergeReadinessEnvelope(root, verificationFile, { persist = false, artifactFile = '' } = {}) {
|
|
492
|
+
ensureRoot(root);
|
|
493
|
+
const verificationPath = sourceVerificationFilePath(root, verificationFile);
|
|
494
|
+
const verificationArtifact = readJsonArtifact(verificationPath, 'Source verification');
|
|
495
|
+
const verificationCheck = validateSourceVerificationArtifact(root, verificationArtifact, path.basename(verificationPath));
|
|
496
|
+
if (!verificationCheck.ok) throw new Error(`source verification verification failed: ${verificationCheck.failures.join('; ')}`);
|
|
497
|
+
const sourceVerification = verificationArtifact.source_verification || {};
|
|
498
|
+
const traceFile = latestStateFile(root, runtimeTracesDirectory, '.runtime-trace.json');
|
|
499
|
+
const tracePath = traceFile ? runtimeTraceFilePath(root, traceFile) : '';
|
|
500
|
+
const traceCheck = traceFile ? validateRuntimeTraceArtifact(root, readJsonArtifact(tracePath, 'Runtime trace')) : { ok: false, failures: ['runtime trace artifact is not present'] };
|
|
501
|
+
const governanceFile = latestStateFile(root, governanceDirectory, '.governance-attestation.json');
|
|
502
|
+
const governancePath = governanceFile ? governanceFilePath(root, governanceFile) : '';
|
|
503
|
+
const governanceCheck = governanceFile ? validateGovernanceArtifact(root, readJsonArtifact(governancePath, 'Governance attestation')) : { ok: false, failures: ['governance attestation artifact is not present'] };
|
|
504
|
+
const methodologyFile = latestStateFile(root, methodologyGatesDirectory, '.methodology-gate.json');
|
|
505
|
+
const methodologyPath = methodologyFile ? methodologyGateFilePath(root, methodologyFile) : '';
|
|
506
|
+
const methodologyCheck = methodologyFile ? validateMethodologyGateArtifact(root, readJsonArtifact(methodologyPath, 'Methodology gate')) : { ok: false, failures: ['methodology gate artifact is not present'] };
|
|
507
|
+
const readinessFile = artifactFile || path.basename(mergeReadinessSnapshotPath(root));
|
|
508
|
+
const blockedReasons = [
|
|
509
|
+
...(traceCheck.ok ? [] : traceCheck.failures.map((failure) => `runtime_trace: ${failure}`)),
|
|
510
|
+
...(governanceCheck.ok ? [] : governanceCheck.failures.map((failure) => `governance: ${failure}`)),
|
|
511
|
+
...(methodologyCheck.ok ? [] : methodologyCheck.failures.map((failure) => `methodology: ${failure}`)),
|
|
512
|
+
...(currentGitHead(root) === sourceVerification.base_sha ? [] : ['base sha drift blocks merge readiness']),
|
|
513
|
+
];
|
|
514
|
+
const core = {
|
|
515
|
+
version: 1,
|
|
516
|
+
stage: 'Stage 47',
|
|
517
|
+
created_at: new Date().toISOString(),
|
|
518
|
+
writes: Boolean(persist),
|
|
519
|
+
verification_file: path.basename(verificationPath),
|
|
520
|
+
verification_digest: fileDigest(verificationPath),
|
|
521
|
+
sandbox_file: sourceVerification.sandbox_file || '',
|
|
522
|
+
sandbox_digest: sourceVerification.sandbox_digest || '',
|
|
523
|
+
candidate_file: sourceVerification.candidate_file || '',
|
|
524
|
+
candidate_digest: sourceVerification.candidate_digest || '',
|
|
525
|
+
base_sha: sourceVerification.base_sha || '',
|
|
526
|
+
current_base_sha: currentGitHead(root),
|
|
527
|
+
diff_digest: sourceVerification.diff_digest || '',
|
|
528
|
+
files_touched: sourceVerification.files_touched || [],
|
|
529
|
+
trace_file: traceFile,
|
|
530
|
+
trace_digest: tracePath ? fileDigest(tracePath) : '',
|
|
531
|
+
governance_file: governanceFile,
|
|
532
|
+
governance_digest: governancePath ? fileDigest(governancePath) : '',
|
|
533
|
+
methodology_file: methodologyFile,
|
|
534
|
+
methodology_digest: methodologyPath ? fileDigest(methodologyPath) : '',
|
|
535
|
+
readiness_status: blockedReasons.length === 0 ? 'merge-readiness-passed-approval-required' : 'merge-readiness-blocked',
|
|
536
|
+
blocked_reasons: blockedReasons,
|
|
537
|
+
policy: {
|
|
538
|
+
review_gate_required: true,
|
|
539
|
+
verification_required: true,
|
|
540
|
+
trace_required: true,
|
|
541
|
+
governance_required: true,
|
|
542
|
+
methodology_required: true,
|
|
543
|
+
no_source_merge_before_stage48: true,
|
|
544
|
+
no_git_before_stage48: true,
|
|
545
|
+
no_auto_apply_before_stage48: true,
|
|
546
|
+
},
|
|
547
|
+
source_merge: false,
|
|
548
|
+
business_source_write: false,
|
|
549
|
+
git: false,
|
|
550
|
+
worktree: false,
|
|
551
|
+
auto_apply: false,
|
|
552
|
+
allowed_followup: ['merge-approval-only'],
|
|
553
|
+
planned_writes: persist ? [path.join(stateDirectoryName, mergeReadinessDirectoryName, '<timestamp>.merge-readiness.json').replace(/\\/g, '/')] : [],
|
|
554
|
+
};
|
|
555
|
+
return {
|
|
556
|
+
mode: 'merge-readiness',
|
|
557
|
+
ok: true,
|
|
558
|
+
state_present: fs.existsSync(workflowPath(root)),
|
|
559
|
+
merge_readiness: { ...core, readiness_digest: digestObject(core) },
|
|
560
|
+
source_verification: { file: path.basename(verificationPath), digest: fileDigest(verificationPath), verification: verificationCheck },
|
|
561
|
+
trace: { file: traceFile, digest: tracePath ? fileDigest(tracePath) : '', verification: traceCheck },
|
|
562
|
+
governance: { file: governanceFile, digest: governancePath ? fileDigest(governancePath) : '', verification: governanceCheck },
|
|
563
|
+
methodology: { file: methodologyFile, digest: methodologyPath ? fileDigest(methodologyPath) : '', verification: methodologyCheck },
|
|
564
|
+
files: { merge_readiness: readinessFile },
|
|
565
|
+
safety: stage47Safety({ writes: persist, readiness: persist }),
|
|
566
|
+
quality: blockedReasons,
|
|
567
|
+
action: persist
|
|
568
|
+
? 'merge readiness artifact was written locally. No merge, git, worktree, auto apply, or business source write occurred.'
|
|
569
|
+
: 'merge readiness was previewed read-only. No files were written.',
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function validateMergeReadinessArtifact(root, artifact, fileName = '') {
|
|
574
|
+
const failures = [];
|
|
575
|
+
if (artifact.schema_version !== jsonSchemaVersion) failures.push('schema_version must be 1');
|
|
576
|
+
if (artifact.command !== 'merge') failures.push('command must be merge');
|
|
577
|
+
if (artifact.mode !== 'merge-readiness') failures.push('mode must be merge-readiness');
|
|
578
|
+
const readiness = artifact.merge_readiness || {};
|
|
579
|
+
const files = artifact.files || {};
|
|
580
|
+
if (!files.merge_readiness || !String(files.merge_readiness).endsWith('.merge-readiness.json')) failures.push('files.merge_readiness must be a merge readiness artifact');
|
|
581
|
+
if (fileName) {
|
|
582
|
+
if (!fileName.endsWith('.merge-readiness.json')) failures.push('Stage 47 merge readiness artifact file extension is unsupported');
|
|
583
|
+
else if (files.merge_readiness !== fileName) failures.push('Stage 47 merge readiness file identity mismatch');
|
|
584
|
+
}
|
|
585
|
+
if (readiness.version !== 1) failures.push('merge_readiness.version must be 1');
|
|
586
|
+
if (readiness.stage !== 'Stage 47') failures.push('merge_readiness.stage must be Stage 47');
|
|
587
|
+
if (readiness.writes !== true) failures.push('merge_readiness.writes must be true');
|
|
588
|
+
if (readiness.readiness_status !== 'merge-readiness-passed-approval-required') failures.push('merge_readiness.readiness_status must be merge-readiness-passed-approval-required');
|
|
589
|
+
if (!Array.isArray(readiness.blocked_reasons) || readiness.blocked_reasons.length !== 0) failures.push('merge_readiness.blocked_reasons must be empty');
|
|
590
|
+
if (!Array.isArray(readiness.allowed_followup) || digestObject(readiness.allowed_followup) !== digestObject(['merge-approval-only'])) failures.push('merge_readiness.allowed_followup must equal merge-approval-only');
|
|
591
|
+
for (const key of ['source_merge', 'business_source_write', 'git', 'worktree', 'auto_apply']) if (readiness[key] !== false) failures.push(`merge_readiness.${key} must be false`);
|
|
592
|
+
if (readiness.policy?.governance_required !== true) failures.push('merge_readiness.policy.governance_required must be true');
|
|
593
|
+
if (readiness.policy?.no_auto_apply_before_stage48 !== true) failures.push('merge_readiness.policy.no_auto_apply_before_stage48 must be true');
|
|
594
|
+
const expectedWrites = [path.join(stateDirectoryName, mergeReadinessDirectoryName, '<timestamp>.merge-readiness.json').replace(/\\/g, '/')];
|
|
595
|
+
if (!Array.isArray(readiness.planned_writes) || digestObject(readiness.planned_writes) !== digestObject(expectedWrites)) failures.push('merge_readiness.planned_writes must only contain merge readiness artifact');
|
|
596
|
+
const digestPayload = { ...readiness };
|
|
597
|
+
delete digestPayload.readiness_digest;
|
|
598
|
+
if (readiness.readiness_digest !== digestObject(digestPayload)) failures.push('merge_readiness digest mismatch');
|
|
599
|
+
if (root && readiness.verification_file) {
|
|
600
|
+
try {
|
|
601
|
+
const verificationPath = sourceVerificationFilePath(root, readiness.verification_file);
|
|
602
|
+
if (fileDigest(verificationPath) !== readiness.verification_digest) failures.push('merge_readiness verification digest mismatch');
|
|
603
|
+
const verificationArtifact = readJsonArtifact(verificationPath, 'Source verification');
|
|
604
|
+
const verification = validateSourceVerificationArtifact(root, verificationArtifact, path.basename(verificationPath));
|
|
605
|
+
failures.push(...verification.failures.map((failure) => `source verification: ${failure}`));
|
|
606
|
+
if ((verificationArtifact.source_verification?.diff_digest || '') !== readiness.diff_digest) failures.push('merge_readiness diff digest mismatch');
|
|
607
|
+
} catch (error) {
|
|
608
|
+
failures.push(error.message);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (root && readiness.trace_file) {
|
|
612
|
+
try {
|
|
613
|
+
const tracePath = runtimeTraceFilePath(root, readiness.trace_file);
|
|
614
|
+
if (fileDigest(tracePath) !== readiness.trace_digest) failures.push('merge_readiness trace digest mismatch');
|
|
615
|
+
const trace = readJsonArtifact(tracePath, 'Runtime trace');
|
|
616
|
+
const verification = validateRuntimeTraceArtifact(root, trace);
|
|
617
|
+
failures.push(...verification.failures.map((failure) => `runtime trace: ${failure}`));
|
|
618
|
+
} catch (error) {
|
|
619
|
+
failures.push(error.message);
|
|
620
|
+
}
|
|
621
|
+
} else failures.push('merge_readiness.trace_file is required');
|
|
622
|
+
if (root && readiness.governance_file) {
|
|
623
|
+
try {
|
|
624
|
+
const governancePath = governanceFilePath(root, readiness.governance_file);
|
|
625
|
+
if (fileDigest(governancePath) !== readiness.governance_digest) failures.push('merge_readiness governance digest mismatch');
|
|
626
|
+
const governance = readJsonArtifact(governancePath, 'Governance attestation');
|
|
627
|
+
const verification = validateGovernanceArtifact(root, governance);
|
|
628
|
+
failures.push(...verification.failures.map((failure) => `governance: ${failure}`));
|
|
629
|
+
} catch (error) {
|
|
630
|
+
failures.push(error.message);
|
|
631
|
+
}
|
|
632
|
+
} else failures.push('merge_readiness.governance_file is required');
|
|
633
|
+
if (root && readiness.methodology_file) {
|
|
634
|
+
try {
|
|
635
|
+
const methodologyPath = methodologyGateFilePath(root, readiness.methodology_file);
|
|
636
|
+
if (fileDigest(methodologyPath) !== readiness.methodology_digest) failures.push('merge_readiness methodology digest mismatch');
|
|
637
|
+
const methodology = readJsonArtifact(methodologyPath, 'Methodology gate');
|
|
638
|
+
const verification = validateMethodologyGateArtifact(root, methodology);
|
|
639
|
+
failures.push(...verification.failures.map((failure) => `methodology: ${failure}`));
|
|
640
|
+
} catch (error) {
|
|
641
|
+
failures.push(error.message);
|
|
642
|
+
}
|
|
643
|
+
} else failures.push('merge_readiness.methodology_file is required');
|
|
644
|
+
const safety = artifact.safety || {};
|
|
645
|
+
if (safety.stage !== 'Stage 47') failures.push('safety.stage must be Stage 47');
|
|
646
|
+
for (const key of ['writes', 'merge_readiness_artifact', 'merge_gate']) if (safety[key] !== true) failures.push(`safety.${key} must be true`);
|
|
647
|
+
for (const key of sourceMergeGateFalseSafetyFields) if (safety[key] !== false) failures.push(`safety.${key} must be false`);
|
|
648
|
+
return { ok: failures.length === 0, failures };
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function writeMergeReadiness(root, envelope) {
|
|
652
|
+
const file = mergeReadinessFilePath(root, envelope.files.merge_readiness);
|
|
653
|
+
const payload = { schema_version: jsonSchemaVersion, command: 'merge', ...envelope, safety: { ...envelope.safety, merge_readiness_artifact: true } };
|
|
654
|
+
const verification = validateMergeReadinessArtifact(root, payload, path.basename(file));
|
|
655
|
+
if (!verification.ok) throw new Error(`merge readiness verification failed: ${verification.failures.join('; ')}`);
|
|
656
|
+
return writeStateArtifact(path.dirname(file), path.basename(file), payload);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
function mergeApprovalEnvelope(root, readinessFile, { persist = false, artifactFile = '' } = {}) {
|
|
660
|
+
ensureRoot(root);
|
|
661
|
+
const readinessPath = mergeReadinessFilePath(root, readinessFile);
|
|
662
|
+
const readinessArtifact = readJsonArtifact(readinessPath, 'Merge readiness');
|
|
663
|
+
const readinessCheck = validateMergeReadinessArtifact(root, readinessArtifact, path.basename(readinessPath));
|
|
664
|
+
if (!readinessCheck.ok) throw new Error(`merge readiness verification failed: ${readinessCheck.failures.join('; ')}`);
|
|
665
|
+
const readiness = readinessArtifact.merge_readiness || {};
|
|
666
|
+
const approvalFile = artifactFile || path.basename(mergeApprovalSnapshotPath(root));
|
|
667
|
+
const core = {
|
|
668
|
+
version: 1,
|
|
669
|
+
stage: 'Stage 47',
|
|
670
|
+
created_at: new Date().toISOString(),
|
|
671
|
+
writes: Boolean(persist),
|
|
672
|
+
readiness_file: path.basename(readinessPath),
|
|
673
|
+
readiness_digest: fileDigest(readinessPath),
|
|
674
|
+
verification_file: readiness.verification_file || '',
|
|
675
|
+
verification_digest: readiness.verification_digest || '',
|
|
676
|
+
base_sha: readiness.base_sha || '',
|
|
677
|
+
diff_digest: readiness.diff_digest || '',
|
|
678
|
+
approval_status: 'merge-approved-apply-required',
|
|
679
|
+
source_merge: false,
|
|
680
|
+
business_source_write: false,
|
|
681
|
+
git: false,
|
|
682
|
+
worktree: false,
|
|
683
|
+
auto_apply: false,
|
|
684
|
+
allowed_followup: ['controlled-merge-apply-only'],
|
|
685
|
+
planned_writes: persist ? [path.join(stateDirectoryName, mergeApprovalsDirectoryName, '<timestamp>.merge-approval.json').replace(/\\/g, '/')] : [],
|
|
686
|
+
};
|
|
687
|
+
return {
|
|
688
|
+
mode: 'merge-approval',
|
|
689
|
+
ok: true,
|
|
690
|
+
state_present: fs.existsSync(workflowPath(root)),
|
|
691
|
+
merge_approval: { ...core, approval_digest: digestObject(core) },
|
|
692
|
+
merge_readiness: { file: path.basename(readinessPath), digest: fileDigest(readinessPath), verification: readinessCheck },
|
|
693
|
+
files: { merge_approval: approvalFile },
|
|
694
|
+
safety: stage47Safety({ writes: persist, approval: persist }),
|
|
695
|
+
quality: [],
|
|
696
|
+
action: persist
|
|
697
|
+
? 'merge approval artifact was written locally. Controlled apply is still a separate Stage 48 gate; no merge occurred.'
|
|
698
|
+
: 'merge approval was previewed read-only. No files were written.',
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
function validateMergeApprovalArtifact(root, artifact, fileName = '') {
|
|
703
|
+
const failures = [];
|
|
704
|
+
if (artifact.schema_version !== jsonSchemaVersion) failures.push('schema_version must be 1');
|
|
705
|
+
if (artifact.command !== 'merge') failures.push('command must be merge');
|
|
706
|
+
if (artifact.mode !== 'merge-approval') failures.push('mode must be merge-approval');
|
|
707
|
+
const approval = artifact.merge_approval || {};
|
|
708
|
+
const files = artifact.files || {};
|
|
709
|
+
if (!files.merge_approval || !String(files.merge_approval).endsWith('.merge-approval.json')) failures.push('files.merge_approval must be a merge approval artifact');
|
|
710
|
+
if (fileName) {
|
|
711
|
+
if (!fileName.endsWith('.merge-approval.json')) failures.push('Stage 47 merge approval artifact file extension is unsupported');
|
|
712
|
+
else if (files.merge_approval !== fileName) failures.push('Stage 47 merge approval file identity mismatch');
|
|
713
|
+
}
|
|
714
|
+
if (approval.version !== 1) failures.push('merge_approval.version must be 1');
|
|
715
|
+
if (approval.stage !== 'Stage 47') failures.push('merge_approval.stage must be Stage 47');
|
|
716
|
+
if (approval.writes !== true) failures.push('merge_approval.writes must be true');
|
|
717
|
+
if (approval.approval_status !== 'merge-approved-apply-required') failures.push('merge_approval.approval_status must be merge-approved-apply-required');
|
|
718
|
+
if (!Array.isArray(approval.allowed_followup) || digestObject(approval.allowed_followup) !== digestObject(['controlled-merge-apply-only'])) failures.push('merge_approval.allowed_followup must equal controlled-merge-apply-only');
|
|
719
|
+
for (const key of ['source_merge', 'business_source_write', 'git', 'worktree', 'auto_apply']) if (approval[key] !== false) failures.push(`merge_approval.${key} must be false`);
|
|
720
|
+
const expectedWrites = [path.join(stateDirectoryName, mergeApprovalsDirectoryName, '<timestamp>.merge-approval.json').replace(/\\/g, '/')];
|
|
721
|
+
if (!Array.isArray(approval.planned_writes) || digestObject(approval.planned_writes) !== digestObject(expectedWrites)) failures.push('merge_approval.planned_writes must only contain merge approval artifact');
|
|
722
|
+
const digestPayload = { ...approval };
|
|
723
|
+
delete digestPayload.approval_digest;
|
|
724
|
+
if (approval.approval_digest !== digestObject(digestPayload)) failures.push('merge_approval digest mismatch');
|
|
725
|
+
if (root && approval.readiness_file) {
|
|
726
|
+
try {
|
|
727
|
+
const readinessPath = mergeReadinessFilePath(root, approval.readiness_file);
|
|
728
|
+
if (fileDigest(readinessPath) !== approval.readiness_digest) failures.push('merge_approval readiness digest mismatch');
|
|
729
|
+
const readinessArtifact = readJsonArtifact(readinessPath, 'Merge readiness');
|
|
730
|
+
const readiness = validateMergeReadinessArtifact(root, readinessArtifact, path.basename(readinessPath));
|
|
731
|
+
failures.push(...readiness.failures.map((failure) => `merge readiness: ${failure}`));
|
|
732
|
+
} catch (error) {
|
|
733
|
+
failures.push(error.message);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
const safety = artifact.safety || {};
|
|
737
|
+
if (safety.stage !== 'Stage 47') failures.push('safety.stage must be Stage 47');
|
|
738
|
+
for (const key of ['writes', 'merge_approval_artifact', 'merge_gate']) if (safety[key] !== true) failures.push(`safety.${key} must be true`);
|
|
739
|
+
for (const key of sourceMergeGateFalseSafetyFields) if (safety[key] !== false) failures.push(`safety.${key} must be false`);
|
|
740
|
+
return { ok: failures.length === 0, failures };
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function writeMergeApproval(root, envelope) {
|
|
744
|
+
const file = mergeApprovalFilePath(root, envelope.files.merge_approval);
|
|
745
|
+
const payload = { schema_version: jsonSchemaVersion, command: 'merge', ...envelope, safety: { ...envelope.safety, merge_approval_artifact: true } };
|
|
746
|
+
const verification = validateMergeApprovalArtifact(root, payload, path.basename(file));
|
|
747
|
+
if (!verification.ok) throw new Error(`merge approval verification failed: ${verification.failures.join('; ')}`);
|
|
748
|
+
return writeStateArtifact(path.dirname(file), path.basename(file), payload);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
function stage48Safety({ writes = false, apply = false } = {}) {
|
|
752
|
+
return sourceMergeApplySafety({ writes, apply });
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
function mergeApplyEnvelope(root, approvalFile, { persist = false, artifactFile = '' } = {}) {
|
|
756
|
+
ensureRoot(root);
|
|
757
|
+
assertSourceMergeApplyPersist(persist);
|
|
758
|
+
const approvalPath = mergeApprovalFilePath(root, approvalFile);
|
|
759
|
+
const approvalArtifact = readJsonArtifact(approvalPath, 'Merge approval');
|
|
760
|
+
const approvalCheck = validateMergeApprovalArtifact(root, approvalArtifact, path.basename(approvalPath));
|
|
761
|
+
if (!approvalCheck.ok) throw new Error(`merge approval verification failed: ${approvalCheck.failures.join('; ')}`);
|
|
762
|
+
const approval = approvalArtifact.merge_approval || {};
|
|
763
|
+
if (currentGitHead(root) !== approval.base_sha) throw new Error('Stage 48 merge apply blocked: base sha drift');
|
|
764
|
+
const {
|
|
765
|
+
targetRelativePath,
|
|
766
|
+
beforeDigest,
|
|
767
|
+
afterDigest,
|
|
768
|
+
markerDigest,
|
|
769
|
+
} = applyStage48ControlledMarker({
|
|
770
|
+
fs,
|
|
771
|
+
path,
|
|
772
|
+
root,
|
|
773
|
+
approvalPath,
|
|
774
|
+
approvalDigest: fileDigest(approvalPath),
|
|
775
|
+
fileDigest,
|
|
776
|
+
digestObject,
|
|
777
|
+
});
|
|
778
|
+
const applyFile = artifactFile || path.basename(mergeApplySnapshotPath(root));
|
|
779
|
+
const core = {
|
|
780
|
+
version: 1,
|
|
781
|
+
stage: 'Stage 48',
|
|
782
|
+
created_at: new Date().toISOString(),
|
|
783
|
+
writes: true,
|
|
784
|
+
apply_status: 'controlled-merge-apply-completed',
|
|
785
|
+
approval_file: path.basename(approvalPath),
|
|
786
|
+
approval_digest: fileDigest(approvalPath),
|
|
787
|
+
readiness_file: approval.readiness_file || '',
|
|
788
|
+
readiness_digest: approval.readiness_digest || '',
|
|
789
|
+
verification_file: approval.verification_file || '',
|
|
790
|
+
verification_digest: approval.verification_digest || '',
|
|
791
|
+
base_sha: approval.base_sha || '',
|
|
792
|
+
before_sha: currentGitHead(root),
|
|
793
|
+
after_sha: currentGitHead(root),
|
|
794
|
+
diff_digest: approval.diff_digest || '',
|
|
795
|
+
apply_mode: 'controlled-local-marker-apply',
|
|
796
|
+
applied_files: [targetRelativePath],
|
|
797
|
+
before_file_digests: { [targetRelativePath]: beforeDigest },
|
|
798
|
+
after_file_digests: { [targetRelativePath]: afterDigest },
|
|
799
|
+
marker_digest: markerDigest,
|
|
800
|
+
business_source_write: true,
|
|
801
|
+
source_merge: true,
|
|
802
|
+
worktree: true,
|
|
803
|
+
git: false,
|
|
804
|
+
commit: false,
|
|
805
|
+
push: false,
|
|
806
|
+
pr: false,
|
|
807
|
+
force: false,
|
|
808
|
+
allowed_followup: ['trace-governance-attestation-only'],
|
|
809
|
+
planned_writes: [
|
|
810
|
+
targetRelativePath,
|
|
811
|
+
path.join(stateDirectoryName, mergeAppliesDirectoryName, '<timestamp>.merge-apply.json').replace(/\\/g, '/'),
|
|
812
|
+
],
|
|
813
|
+
};
|
|
814
|
+
return {
|
|
815
|
+
mode: 'merge-apply',
|
|
816
|
+
ok: true,
|
|
817
|
+
state_present: fs.existsSync(workflowPath(root)),
|
|
818
|
+
merge_apply: { ...core, apply_digest: digestObject(core) },
|
|
819
|
+
merge_approval: { file: path.basename(approvalPath), digest: fileDigest(approvalPath), verification: approvalCheck },
|
|
820
|
+
files: { merge_apply: applyFile, applied: [targetRelativePath] },
|
|
821
|
+
safety: stage48Safety({ writes: true, apply: true }),
|
|
822
|
+
quality: [],
|
|
823
|
+
action: sourceMergeApplyAction,
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
function validateMergeApplyArtifact(root, artifact, fileName = '') {
|
|
828
|
+
const failures = [];
|
|
829
|
+
if (artifact.schema_version !== jsonSchemaVersion) failures.push('schema_version must be 1');
|
|
830
|
+
if (artifact.command !== 'merge') failures.push('command must be merge');
|
|
831
|
+
if (artifact.mode !== 'merge-apply') failures.push('mode must be merge-apply');
|
|
832
|
+
const apply = artifact.merge_apply || {};
|
|
833
|
+
const files = artifact.files || {};
|
|
834
|
+
if (!files.merge_apply || !String(files.merge_apply).endsWith('.merge-apply.json')) failures.push('files.merge_apply must be a merge apply artifact');
|
|
835
|
+
if (fileName) {
|
|
836
|
+
if (!fileName.endsWith('.merge-apply.json')) failures.push('Stage 48 merge apply artifact file extension is unsupported');
|
|
837
|
+
else if (files.merge_apply !== fileName) failures.push('Stage 48 merge apply file identity mismatch');
|
|
838
|
+
}
|
|
839
|
+
if (apply.version !== 1) failures.push('merge_apply.version must be 1');
|
|
840
|
+
if (apply.stage !== 'Stage 48') failures.push('merge_apply.stage must be Stage 48');
|
|
841
|
+
if (apply.writes !== true) failures.push('merge_apply.writes must be true');
|
|
842
|
+
if (apply.apply_status !== 'controlled-merge-apply-completed') failures.push('merge_apply.apply_status must be controlled-merge-apply-completed');
|
|
843
|
+
if (apply.apply_mode !== 'controlled-local-marker-apply') failures.push('merge_apply.apply_mode must be controlled-local-marker-apply');
|
|
844
|
+
if (!Array.isArray(apply.allowed_followup) || digestObject(apply.allowed_followup) !== digestObject(['trace-governance-attestation-only'])) failures.push('merge_apply.allowed_followup must equal trace-governance-attestation-only');
|
|
845
|
+
for (const key of ['business_source_write', 'source_merge', 'worktree']) if (apply[key] !== true) failures.push(`merge_apply.${key} must be true`);
|
|
846
|
+
for (const key of ['git', 'commit', 'push', 'pr', 'force']) if (apply[key] !== false) failures.push(`merge_apply.${key} must be false`);
|
|
847
|
+
if (!apply.base_sha || apply.before_sha !== apply.base_sha || apply.after_sha !== apply.base_sha) failures.push('merge_apply before_sha and after_sha must match base_sha');
|
|
848
|
+
if (!Array.isArray(apply.applied_files) || digestObject(apply.applied_files) !== digestObject(['docs/runtime-auto-merge-ledger.md'])) failures.push('merge_apply.applied_files must equal docs/runtime-auto-merge-ledger.md');
|
|
849
|
+
const expectedWrites = ['docs/runtime-auto-merge-ledger.md', path.join(stateDirectoryName, mergeAppliesDirectoryName, '<timestamp>.merge-apply.json').replace(/\\/g, '/')];
|
|
850
|
+
if (!Array.isArray(apply.planned_writes) || digestObject(apply.planned_writes) !== digestObject(expectedWrites)) failures.push('merge_apply.planned_writes must match Stage 48 write whitelist');
|
|
851
|
+
const digestPayload = { ...apply };
|
|
852
|
+
delete digestPayload.apply_digest;
|
|
853
|
+
if (apply.apply_digest !== digestObject(digestPayload)) failures.push('merge_apply digest mismatch');
|
|
854
|
+
if (root && apply.approval_file) {
|
|
855
|
+
try {
|
|
856
|
+
const approvalPath = mergeApprovalFilePath(root, apply.approval_file);
|
|
857
|
+
if (fileDigest(approvalPath) !== apply.approval_digest) failures.push('merge_apply approval digest mismatch');
|
|
858
|
+
const approvalArtifact = readJsonArtifact(approvalPath, 'Merge approval');
|
|
859
|
+
const approval = validateMergeApprovalArtifact(root, approvalArtifact, path.basename(approvalPath));
|
|
860
|
+
failures.push(...approval.failures.map((failure) => `merge approval: ${failure}`));
|
|
861
|
+
} catch (error) {
|
|
862
|
+
failures.push(error.message);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
if (root && Array.isArray(apply.applied_files)) {
|
|
866
|
+
for (const appliedFile of apply.applied_files) {
|
|
867
|
+
try {
|
|
868
|
+
if (path.isAbsolute(appliedFile) || appliedFile.includes('..') || appliedFile.includes('\\')) failures.push('merge_apply.applied_files contains unsafe path');
|
|
869
|
+
const targetPath = path.join(root, appliedFile);
|
|
870
|
+
if (!fs.existsSync(targetPath)) failures.push(`merge_apply applied file missing: ${appliedFile}`);
|
|
871
|
+
else if (fileDigest(targetPath) !== apply.after_file_digests?.[appliedFile]) failures.push(`merge_apply after file digest mismatch: ${appliedFile}`);
|
|
872
|
+
} catch (error) {
|
|
873
|
+
failures.push(error.message);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
const safety = artifact.safety || {};
|
|
878
|
+
if (safety.stage !== 'Stage 48') failures.push('safety.stage must be Stage 48');
|
|
879
|
+
for (const key of ['writes', 'merge_apply_artifact', 'controlled_apply', 'business_source_write', 'source_merge', 'worktree']) if (safety[key] !== true) failures.push(`safety.${key} must be true`);
|
|
880
|
+
for (const key of sourceMergeApplyFalseSafetyFields) if (safety[key] !== false) failures.push(`safety.${key} must be false`);
|
|
881
|
+
return { ok: failures.length === 0, failures };
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function writeMergeApply(root, envelope) {
|
|
885
|
+
const file = mergeApplyFilePath(root, envelope.files.merge_apply);
|
|
886
|
+
const payload = { schema_version: jsonSchemaVersion, command: 'merge', ...envelope, safety: { ...envelope.safety, merge_apply_artifact: true } };
|
|
887
|
+
const verification = validateMergeApplyArtifact(root, payload, path.basename(file));
|
|
888
|
+
if (!verification.ok) throw new Error(`merge apply verification failed: ${verification.failures.join('; ')}`);
|
|
889
|
+
return writeStateArtifact(path.dirname(file), path.basename(file), payload);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
return {
|
|
894
|
+
sourceChangeCandidateSnapshotPath,
|
|
895
|
+
sourceSandboxRunSnapshotPath,
|
|
896
|
+
sourceVerificationSnapshotPath,
|
|
897
|
+
sourceChangeCandidateEnvelope,
|
|
898
|
+
validateSourceChangeCandidateArtifact,
|
|
899
|
+
writeSourceChangeCandidate,
|
|
900
|
+
sourceSandboxRunEnvelope,
|
|
901
|
+
validateSourceSandboxRunArtifact,
|
|
902
|
+
writeSourceSandboxRun,
|
|
903
|
+
sourceVerificationEnvelope,
|
|
904
|
+
validateSourceVerificationArtifact,
|
|
905
|
+
writeSourceVerification,
|
|
906
|
+
mergeReadinessSnapshotPath,
|
|
907
|
+
mergeApprovalSnapshotPath,
|
|
908
|
+
mergeApplySnapshotPath,
|
|
909
|
+
mergeReadinessEnvelope,
|
|
910
|
+
validateMergeReadinessArtifact,
|
|
911
|
+
writeMergeReadiness,
|
|
912
|
+
mergeApprovalEnvelope,
|
|
913
|
+
validateMergeApprovalArtifact,
|
|
914
|
+
writeMergeApproval,
|
|
915
|
+
mergeApplyEnvelope,
|
|
916
|
+
validateMergeApplyArtifact,
|
|
917
|
+
writeMergeApply,
|
|
918
|
+
sourcePatchPlanEnvelope,
|
|
919
|
+
};
|
|
920
|
+
}
|