@hunter-harness/workflow-harness 0.2.43 → 0.2.44
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/harness/bundles/general/claude-code/.harness-build.json +1 -1
- package/harness/bundles/general/claude-code/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/general/claude-code/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/general/claude-code/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/general/claude-code/contracts/run-session.schema.json +142 -0
- package/harness/bundles/general/claude-code/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/general/claude-code/contracts/service-session.schema.json +147 -0
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-submit/checklist.md +12 -0
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +267 -22
- package/harness/bundles/general/claude-code/scripts/harness_change.py +137 -2
- package/harness/bundles/general/claude-code/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/general/claude-code/scripts/harness_environment.py +55 -25
- package/harness/bundles/general/claude-code/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/general/claude-code/scripts/harness_integration.py +289 -52
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +5 -0
- package/harness/bundles/general/claude-code/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/general/claude-code/scripts/harness_process.py +1065 -0
- package/harness/bundles/general/claude-code/scripts/harness_profile.py +244 -4
- package/harness/bundles/general/claude-code/scripts/harness_runtime.py +543 -132
- package/harness/bundles/general/claude-code/scripts/harness_service.py +1469 -194
- package/harness/bundles/general/claude-code/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/general/claude-code/scripts/harness_verification.py +79 -0
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/general/codebuddy/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/general/codebuddy/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/general/codebuddy/contracts/run-session.schema.json +142 -0
- package/harness/bundles/general/codebuddy/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/general/codebuddy/contracts/service-session.schema.json +147 -0
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-submit/checklist.md +12 -0
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +267 -22
- package/harness/bundles/general/codebuddy/scripts/harness_change.py +137 -2
- package/harness/bundles/general/codebuddy/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/general/codebuddy/scripts/harness_environment.py +55 -25
- package/harness/bundles/general/codebuddy/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/general/codebuddy/scripts/harness_integration.py +289 -52
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +5 -0
- package/harness/bundles/general/codebuddy/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/general/codebuddy/scripts/harness_process.py +1065 -0
- package/harness/bundles/general/codebuddy/scripts/harness_profile.py +244 -4
- package/harness/bundles/general/codebuddy/scripts/harness_runtime.py +543 -132
- package/harness/bundles/general/codebuddy/scripts/harness_service.py +1469 -194
- package/harness/bundles/general/codebuddy/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/general/codebuddy/scripts/harness_verification.py +79 -0
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/general/codex/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/general/codex/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/general/codex/contracts/run-session.schema.json +142 -0
- package/harness/bundles/general/codex/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/general/codex/contracts/service-session.schema.json +147 -0
- package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-submit/checklist.md +12 -0
- package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codex/scripts/harness_archive.py +267 -22
- package/harness/bundles/general/codex/scripts/harness_change.py +137 -2
- package/harness/bundles/general/codex/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/general/codex/scripts/harness_environment.py +55 -25
- package/harness/bundles/general/codex/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/general/codex/scripts/harness_integration.py +289 -52
- package/harness/bundles/general/codex/scripts/harness_ledger.py +5 -0
- package/harness/bundles/general/codex/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/general/codex/scripts/harness_process.py +1065 -0
- package/harness/bundles/general/codex/scripts/harness_profile.py +244 -4
- package/harness/bundles/general/codex/scripts/harness_runtime.py +543 -132
- package/harness/bundles/general/codex/scripts/harness_service.py +1469 -194
- package/harness/bundles/general/codex/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/general/codex/scripts/harness_verification.py +79 -0
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/general/cursor/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/general/cursor/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/general/cursor/contracts/run-session.schema.json +142 -0
- package/harness/bundles/general/cursor/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/general/cursor/contracts/service-session.schema.json +147 -0
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-submit/checklist.md +12 -0
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/cursor/scripts/harness_archive.py +267 -22
- package/harness/bundles/general/cursor/scripts/harness_change.py +137 -2
- package/harness/bundles/general/cursor/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/general/cursor/scripts/harness_environment.py +55 -25
- package/harness/bundles/general/cursor/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/general/cursor/scripts/harness_integration.py +289 -52
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +5 -0
- package/harness/bundles/general/cursor/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/general/cursor/scripts/harness_process.py +1065 -0
- package/harness/bundles/general/cursor/scripts/harness_profile.py +244 -4
- package/harness/bundles/general/cursor/scripts/harness_runtime.py +543 -132
- package/harness/bundles/general/cursor/scripts/harness_service.py +1469 -194
- package/harness/bundles/general/cursor/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/general/cursor/scripts/harness_verification.py +79 -0
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/java/claude-code/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/java/claude-code/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/java/claude-code/contracts/run-session.schema.json +142 -0
- package/harness/bundles/java/claude-code/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/java/claude-code/contracts/service-session.schema.json +147 -0
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-submit/checklist.md +12 -0
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +267 -22
- package/harness/bundles/java/claude-code/scripts/harness_change.py +137 -2
- package/harness/bundles/java/claude-code/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/java/claude-code/scripts/harness_environment.py +55 -25
- package/harness/bundles/java/claude-code/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/java/claude-code/scripts/harness_integration.py +289 -52
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +5 -0
- package/harness/bundles/java/claude-code/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/java/claude-code/scripts/harness_process.py +1065 -0
- package/harness/bundles/java/claude-code/scripts/harness_profile.py +244 -4
- package/harness/bundles/java/claude-code/scripts/harness_runtime.py +543 -132
- package/harness/bundles/java/claude-code/scripts/harness_service.py +1469 -194
- package/harness/bundles/java/claude-code/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/java/claude-code/scripts/harness_verification.py +79 -0
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/java/codebuddy/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/java/codebuddy/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/java/codebuddy/contracts/run-session.schema.json +142 -0
- package/harness/bundles/java/codebuddy/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/java/codebuddy/contracts/service-session.schema.json +147 -0
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-submit/checklist.md +12 -0
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +267 -22
- package/harness/bundles/java/codebuddy/scripts/harness_change.py +137 -2
- package/harness/bundles/java/codebuddy/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/java/codebuddy/scripts/harness_environment.py +55 -25
- package/harness/bundles/java/codebuddy/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/java/codebuddy/scripts/harness_integration.py +289 -52
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +5 -0
- package/harness/bundles/java/codebuddy/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/java/codebuddy/scripts/harness_process.py +1065 -0
- package/harness/bundles/java/codebuddy/scripts/harness_profile.py +244 -4
- package/harness/bundles/java/codebuddy/scripts/harness_runtime.py +543 -132
- package/harness/bundles/java/codebuddy/scripts/harness_service.py +1469 -194
- package/harness/bundles/java/codebuddy/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/java/codebuddy/scripts/harness_verification.py +79 -0
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/java/codex/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/java/codex/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/java/codex/contracts/run-session.schema.json +142 -0
- package/harness/bundles/java/codex/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/java/codex/contracts/service-session.schema.json +147 -0
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-submit/checklist.md +12 -0
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codex/scripts/harness_archive.py +267 -22
- package/harness/bundles/java/codex/scripts/harness_change.py +137 -2
- package/harness/bundles/java/codex/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/java/codex/scripts/harness_environment.py +55 -25
- package/harness/bundles/java/codex/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/java/codex/scripts/harness_integration.py +289 -52
- package/harness/bundles/java/codex/scripts/harness_ledger.py +5 -0
- package/harness/bundles/java/codex/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/java/codex/scripts/harness_process.py +1065 -0
- package/harness/bundles/java/codex/scripts/harness_profile.py +244 -4
- package/harness/bundles/java/codex/scripts/harness_runtime.py +543 -132
- package/harness/bundles/java/codex/scripts/harness_service.py +1469 -194
- package/harness/bundles/java/codex/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/java/codex/scripts/harness_verification.py +79 -0
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/contracts/build-profile-v3.schema.json +100 -0
- package/harness/bundles/java/cursor/contracts/fixtures/managed-execution.json +341 -0
- package/harness/bundles/java/cursor/contracts/process-identity.schema.json +132 -0
- package/harness/bundles/java/cursor/contracts/run-session.schema.json +142 -0
- package/harness/bundles/java/cursor/contracts/service-retirement-receipt.schema.json +85 -0
- package/harness/bundles/java/cursor/contracts/service-session.schema.json +147 -0
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-submit/checklist.md +12 -0
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/cursor/scripts/harness_archive.py +267 -22
- package/harness/bundles/java/cursor/scripts/harness_change.py +137 -2
- package/harness/bundles/java/cursor/scripts/harness_efficiency.py +153 -0
- package/harness/bundles/java/cursor/scripts/harness_environment.py +55 -25
- package/harness/bundles/java/cursor/scripts/harness_execution_contracts.py +596 -0
- package/harness/bundles/java/cursor/scripts/harness_integration.py +289 -52
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +5 -0
- package/harness/bundles/java/cursor/scripts/harness_orchestration.py +344 -0
- package/harness/bundles/java/cursor/scripts/harness_process.py +1065 -0
- package/harness/bundles/java/cursor/scripts/harness_profile.py +244 -4
- package/harness/bundles/java/cursor/scripts/harness_runtime.py +543 -132
- package/harness/bundles/java/cursor/scripts/harness_service.py +1469 -194
- package/harness/bundles/java/cursor/scripts/harness_test_runner.py +107 -117
- package/harness/bundles/java/cursor/scripts/harness_verification.py +79 -0
- package/harness/manifests/general/claude-code.json +58 -26
- package/harness/manifests/general/codebuddy.json +58 -26
- package/harness/manifests/general/codex.json +58 -26
- package/harness/manifests/general/cursor.json +58 -26
- package/harness/manifests/java/claude-code.json +60 -28
- package/harness/manifests/java/codebuddy.json +60 -28
- package/harness/manifests/java/codex.json +60 -28
- package/harness/manifests/java/cursor.json +60 -28
- package/hunter-workflow-family.json +4 -4
- package/package.json +1 -1
|
@@ -77,6 +77,7 @@ import harness_paths as hp # noqa: E402
|
|
|
77
77
|
import harness_phase as hphase # noqa: E402
|
|
78
78
|
import harness_report_model as hrm # noqa: E402
|
|
79
79
|
import harness_review as hr # noqa: E402
|
|
80
|
+
import harness_runtime as hruntime # noqa: E402
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
# ---------------------------------------------------------------------------
|
|
@@ -1957,6 +1958,131 @@ def check_archive_exact_byte_policy(project_root: Path) -> dict[str, Any]:
|
|
|
1957
1958
|
}
|
|
1958
1959
|
|
|
1959
1960
|
|
|
1961
|
+
def validate_sensitive_evidence_publication_gate(
|
|
1962
|
+
change_dir: Path,
|
|
1963
|
+
*,
|
|
1964
|
+
copy_root: Path | None = None,
|
|
1965
|
+
require_receipt: bool = False,
|
|
1966
|
+
) -> dict[str, Any]:
|
|
1967
|
+
"""Fail closed before freeze/copy when plaintext evidence is unresolved.
|
|
1968
|
+
|
|
1969
|
+
The receipt is deliberately self-excluded from the tree digest. It may
|
|
1970
|
+
therefore bind the exact publishable bytes without creating a recursive
|
|
1971
|
+
digest. Private quarantine paths are evidence metadata only and must be
|
|
1972
|
+
outside both the project/copy roots.
|
|
1973
|
+
"""
|
|
1974
|
+
change_dir = change_dir.expanduser().resolve()
|
|
1975
|
+
copy_root = (copy_root or change_dir).expanduser().resolve()
|
|
1976
|
+
receipt_path = hruntime.sensitive_evidence_receipt_path(change_dir)
|
|
1977
|
+
candidates = hruntime.sensitive_evidence_candidates(change_dir)
|
|
1978
|
+
if candidates:
|
|
1979
|
+
return {
|
|
1980
|
+
"ok": False,
|
|
1981
|
+
"reasonCode": "SENSITIVE_EVIDENCE_UNQUARANTINED",
|
|
1982
|
+
"receiptPath": str(receipt_path),
|
|
1983
|
+
"unresolvedFailures": candidates,
|
|
1984
|
+
"nextAction": "Quarantine the original bytes before archive publication.",
|
|
1985
|
+
}
|
|
1986
|
+
if not receipt_path.is_file():
|
|
1987
|
+
if require_receipt:
|
|
1988
|
+
return {
|
|
1989
|
+
"ok": False,
|
|
1990
|
+
"reasonCode": "SECRET_SCAN_RECEIPT_MISSING",
|
|
1991
|
+
"receiptPath": str(receipt_path),
|
|
1992
|
+
"unresolvedFailures": [],
|
|
1993
|
+
}
|
|
1994
|
+
return {
|
|
1995
|
+
"ok": True,
|
|
1996
|
+
"reasonCode": "SECRET_SCAN_NOT_APPLICABLE",
|
|
1997
|
+
"receiptPath": str(receipt_path),
|
|
1998
|
+
"receiptRequired": False,
|
|
1999
|
+
"unresolvedFailures": [],
|
|
2000
|
+
}
|
|
2001
|
+
try:
|
|
2002
|
+
receipt = read_json(receipt_path)
|
|
2003
|
+
except (OSError, json.JSONDecodeError, TypeError) as exc:
|
|
2004
|
+
return {
|
|
2005
|
+
"ok": False,
|
|
2006
|
+
"reasonCode": "SECRET_SCAN_RECEIPT_INVALID",
|
|
2007
|
+
"receiptPath": str(receipt_path),
|
|
2008
|
+
"error": str(exc),
|
|
2009
|
+
}
|
|
2010
|
+
if not isinstance(receipt, dict):
|
|
2011
|
+
return {
|
|
2012
|
+
"ok": False,
|
|
2013
|
+
"reasonCode": "SECRET_SCAN_RECEIPT_INVALID",
|
|
2014
|
+
"receiptPath": str(receipt_path),
|
|
2015
|
+
"error": "receipt must be an object",
|
|
2016
|
+
}
|
|
2017
|
+
issues: list[dict[str, Any]] = []
|
|
2018
|
+
if receipt.get("schemaVersion") != 1:
|
|
2019
|
+
issues.append({"code": "SECRET_SCAN_SCHEMA_INVALID"})
|
|
2020
|
+
if receipt.get("rulesVersion") != hruntime.SECRET_SCAN_RULES_VERSION:
|
|
2021
|
+
issues.append({"code": "SECRET_SCAN_RULES_MISMATCH"})
|
|
2022
|
+
if receipt.get("changeId") != change_dir.name:
|
|
2023
|
+
issues.append({"code": "SECRET_SCAN_CHANGE_ID_MISMATCH"})
|
|
2024
|
+
if str(receipt.get("status") or "").upper() not in {"OK", "QUARANTINED"}:
|
|
2025
|
+
issues.append({"code": "SENSITIVE_EVIDENCE_QUARANTINE_FAILED"})
|
|
2026
|
+
unresolved = receipt.get("unresolvedFailures")
|
|
2027
|
+
if isinstance(unresolved, list) and unresolved:
|
|
2028
|
+
issues.append({"code": "SENSITIVE_EVIDENCE_QUARANTINE_FAILED", "count": len(unresolved)})
|
|
2029
|
+
elif unresolved not in (None, []):
|
|
2030
|
+
issues.append({"code": "SECRET_SCAN_UNRESOLVED_INVALID"})
|
|
2031
|
+
try:
|
|
2032
|
+
actual_digest = hruntime.publishable_tree_digest(change_dir)
|
|
2033
|
+
except OSError as exc:
|
|
2034
|
+
actual_digest = None
|
|
2035
|
+
issues.append({"code": "SECRET_SCAN_TREE_UNREADABLE", "error": str(exc)})
|
|
2036
|
+
if actual_digest is not None and receipt.get("publishableTreeDigest") != actual_digest:
|
|
2037
|
+
issues.append({
|
|
2038
|
+
"code": "SECRET_SCAN_TREE_DIGEST_MISMATCH",
|
|
2039
|
+
"expected": receipt.get("publishableTreeDigest"),
|
|
2040
|
+
"actual": actual_digest,
|
|
2041
|
+
})
|
|
2042
|
+
if receipt.get("publicationExcluded") is not True:
|
|
2043
|
+
issues.append({"code": "SECRET_SCAN_PUBLICATION_NOT_EXCLUDED"})
|
|
2044
|
+
project_root = find_project_root(change_dir)
|
|
2045
|
+
for entry in receipt.get("entries") or []:
|
|
2046
|
+
if not isinstance(entry, dict):
|
|
2047
|
+
issues.append({"code": "SECRET_SCAN_ENTRY_INVALID"})
|
|
2048
|
+
continue
|
|
2049
|
+
private_raw = entry.get("privatePath")
|
|
2050
|
+
if not isinstance(private_raw, str) or not private_raw.strip():
|
|
2051
|
+
issues.append({"code": "SECRET_SCAN_PRIVATE_PATH_MISSING"})
|
|
2052
|
+
continue
|
|
2053
|
+
private_path = Path(private_raw).expanduser().resolve()
|
|
2054
|
+
if (
|
|
2055
|
+
_path_is_within(private_path, copy_root)
|
|
2056
|
+
or _path_is_within(private_path, project_root)
|
|
2057
|
+
or _path_is_within(private_path, change_dir)
|
|
2058
|
+
):
|
|
2059
|
+
issues.append({
|
|
2060
|
+
"code": "SECRET_SCAN_PRIVATE_PATH_IN_COPY_ROOT",
|
|
2061
|
+
"privatePath": str(private_path),
|
|
2062
|
+
})
|
|
2063
|
+
if not private_path.is_file():
|
|
2064
|
+
issues.append({
|
|
2065
|
+
"code": "SECRET_SCAN_PRIVATE_PATH_MISSING",
|
|
2066
|
+
"privatePath": str(private_path),
|
|
2067
|
+
})
|
|
2068
|
+
source_raw = entry.get("sourcePath")
|
|
2069
|
+
if isinstance(source_raw, str) and source_raw.strip():
|
|
2070
|
+
source_path = (change_dir / source_raw).resolve()
|
|
2071
|
+
if _path_is_within(source_path, change_dir) and source_path.exists():
|
|
2072
|
+
issues.append({
|
|
2073
|
+
"code": "SENSITIVE_EVIDENCE_SOURCE_REMAINS",
|
|
2074
|
+
"sourcePath": source_raw,
|
|
2075
|
+
})
|
|
2076
|
+
return {
|
|
2077
|
+
"ok": not issues,
|
|
2078
|
+
"reasonCode": "SECRET_SCAN_GATE_SATISFIED" if not issues else "SECRET_SCAN_GATE_BLOCKED",
|
|
2079
|
+
"receiptPath": str(receipt_path),
|
|
2080
|
+
"receipt": receipt,
|
|
2081
|
+
"issues": issues,
|
|
2082
|
+
"treeDigest": actual_digest,
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
|
|
1960
2086
|
# ---------------------------------------------------------------------------
|
|
1961
2087
|
# status
|
|
1962
2088
|
# ---------------------------------------------------------------------------
|
|
@@ -2001,6 +2127,22 @@ def check_status(
|
|
|
2001
2127
|
}
|
|
2002
2128
|
)
|
|
2003
2129
|
|
|
2130
|
+
sensitive_gate = validate_sensitive_evidence_publication_gate(
|
|
2131
|
+
change_dir,
|
|
2132
|
+
copy_root=change_dir,
|
|
2133
|
+
require_receipt=False,
|
|
2134
|
+
)
|
|
2135
|
+
checks["sensitive_evidence_publication"] = sensitive_gate
|
|
2136
|
+
if not sensitive_gate.get("ok"):
|
|
2137
|
+
blockers.append({
|
|
2138
|
+
"code": str(sensitive_gate.get("reasonCode") or "SECRET_SCAN_GATE_BLOCKED"),
|
|
2139
|
+
"message": str(
|
|
2140
|
+
sensitive_gate.get("nextAction")
|
|
2141
|
+
or sensitive_gate.get("error")
|
|
2142
|
+
or "sensitive evidence publication gate failed"
|
|
2143
|
+
),
|
|
2144
|
+
})
|
|
2145
|
+
|
|
2004
2146
|
# --- H-4 formal-layer minimum set ---
|
|
2005
2147
|
plans_dir = change_dir / "plans"
|
|
2006
2148
|
plan_files = (
|
|
@@ -2246,6 +2388,14 @@ def check_status(
|
|
|
2246
2388
|
except Exception as exc: # noqa: BLE001 — preflight must not crash status
|
|
2247
2389
|
preflight = {"ok": False, "items": [], "blocking": [], "error": str(exc)}
|
|
2248
2390
|
checks["artifact_preflight"] = preflight
|
|
2391
|
+
if preflight.get("ok") is not True and not preflight.get("blocking"):
|
|
2392
|
+
blockers.append({
|
|
2393
|
+
"code": "artifact-preflight-invalid",
|
|
2394
|
+
"message": str(
|
|
2395
|
+
preflight.get("error")
|
|
2396
|
+
or "artifact event projection or preflight validation failed"
|
|
2397
|
+
),
|
|
2398
|
+
})
|
|
2249
2399
|
for item in preflight.get("blocking") or []:
|
|
2250
2400
|
blockers.append({
|
|
2251
2401
|
"code": "artifact-path-blocking",
|
|
@@ -6465,12 +6615,9 @@ def artifact_preflight(change_dir: Path) -> dict[str, Any]:
|
|
|
6465
6615
|
return {"ok": True, "items": [], "blocking": []}
|
|
6466
6616
|
change_id = change_dir.name
|
|
6467
6617
|
project_root = find_project_root(change_dir)
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
except json.JSONDecodeError:
|
|
6472
|
-
continue
|
|
6473
|
-
if not isinstance(event, dict) or event.get("type") != "artifact":
|
|
6618
|
+
events = he.apply_event_corrections(he.load_events(events_p))
|
|
6619
|
+
for event in events:
|
|
6620
|
+
if event.get("type") != "artifact":
|
|
6474
6621
|
continue
|
|
6475
6622
|
path = str(event.get("path") or "").strip()
|
|
6476
6623
|
kind = str(event.get("kind") or "").strip()
|
|
@@ -6657,9 +6804,19 @@ def evaluate_artifact_budget(change_dir: Path) -> dict[str, Any]:
|
|
|
6657
6804
|
except (OSError, ValueError, json.JSONDecodeError) as exc:
|
|
6658
6805
|
return {
|
|
6659
6806
|
"ok": False,
|
|
6660
|
-
"code": "
|
|
6807
|
+
"code": "ARTIFACT_PREFLIGHT_INVALID",
|
|
6661
6808
|
"message": str(exc),
|
|
6662
6809
|
}
|
|
6810
|
+
if preflight.get("ok") is not True:
|
|
6811
|
+
return {
|
|
6812
|
+
"ok": False,
|
|
6813
|
+
"code": "ARTIFACT_PREFLIGHT_INVALID",
|
|
6814
|
+
"message": str(
|
|
6815
|
+
preflight.get("error")
|
|
6816
|
+
or "artifact event projection or preflight validation failed"
|
|
6817
|
+
),
|
|
6818
|
+
"preflightBlocking": preflight.get("blocking") or [],
|
|
6819
|
+
}
|
|
6663
6820
|
excluded_parts = {
|
|
6664
6821
|
"node_modules",
|
|
6665
6822
|
".venv",
|
|
@@ -6697,7 +6854,7 @@ def evaluate_artifact_budget(change_dir: Path) -> dict[str, Any]:
|
|
|
6697
6854
|
oversized = [
|
|
6698
6855
|
item for item in entries if int(item["bytes"]) > max_file
|
|
6699
6856
|
]
|
|
6700
|
-
ok = total <= max_total and not oversized
|
|
6857
|
+
ok = total <= max_total and not oversized
|
|
6701
6858
|
return {
|
|
6702
6859
|
"ok": ok,
|
|
6703
6860
|
"code": (
|
|
@@ -6726,6 +6883,13 @@ def materialize_repository_artifacts(change_dir: Path) -> dict[str, Any]:
|
|
|
6726
6883
|
change_dir = change_dir.resolve()
|
|
6727
6884
|
project_root = find_project_root(change_dir)
|
|
6728
6885
|
preflight = artifact_preflight(change_dir)
|
|
6886
|
+
if preflight.get("ok") is not True:
|
|
6887
|
+
raise ValueError(
|
|
6888
|
+
str(
|
|
6889
|
+
preflight.get("error")
|
|
6890
|
+
or "artifact event projection or preflight validation failed"
|
|
6891
|
+
)
|
|
6892
|
+
)
|
|
6729
6893
|
copied: list[str] = []
|
|
6730
6894
|
objects: list[dict[str, Any]] = []
|
|
6731
6895
|
bytes_added = 0
|
|
@@ -7299,6 +7463,32 @@ def cmd_finalize(
|
|
|
7299
7463
|
payload["error"] = f"archive target already exists: {archive_dir}"
|
|
7300
7464
|
return 1, payload
|
|
7301
7465
|
|
|
7466
|
+
source_sensitive_gate = validate_sensitive_evidence_publication_gate(
|
|
7467
|
+
original_change_dir,
|
|
7468
|
+
copy_root=original_change_dir,
|
|
7469
|
+
require_receipt=False,
|
|
7470
|
+
)
|
|
7471
|
+
payload["steps"]["sensitive_evidence_source_gate"] = source_sensitive_gate
|
|
7472
|
+
if not source_sensitive_gate.get("ok"):
|
|
7473
|
+
payload["error"] = str(
|
|
7474
|
+
source_sensitive_gate.get("nextAction")
|
|
7475
|
+
or source_sensitive_gate.get("error")
|
|
7476
|
+
or "sensitive evidence publication gate failed"
|
|
7477
|
+
)
|
|
7478
|
+
payload["issues"] = [
|
|
7479
|
+
{
|
|
7480
|
+
"code": str(
|
|
7481
|
+
source_sensitive_gate.get("reasonCode")
|
|
7482
|
+
or "SECRET_SCAN_GATE_BLOCKED"
|
|
7483
|
+
),
|
|
7484
|
+
"severity": "error",
|
|
7485
|
+
"message": payload["error"],
|
|
7486
|
+
}
|
|
7487
|
+
]
|
|
7488
|
+
payload["original_preserved"] = original_change_dir.is_dir()
|
|
7489
|
+
payload["finalStatus"] = "FAIL"
|
|
7490
|
+
return 1, payload
|
|
7491
|
+
|
|
7302
7492
|
exact_byte = check_archive_exact_byte_policy(project_root)
|
|
7303
7493
|
payload["steps"]["archive_exact_byte"] = exact_byte
|
|
7304
7494
|
if not exact_byte["ok"]:
|
|
@@ -7307,7 +7497,13 @@ def cmd_finalize(
|
|
|
7307
7497
|
artifact_budget = evaluate_artifact_budget(original_change_dir)
|
|
7308
7498
|
payload["steps"]["artifact_budget"] = artifact_budget
|
|
7309
7499
|
if not artifact_budget.get("ok"):
|
|
7310
|
-
|
|
7500
|
+
if artifact_budget.get("code") == "ARTIFACT_PREFLIGHT_INVALID":
|
|
7501
|
+
payload["error"] = str(
|
|
7502
|
+
artifact_budget.get("message")
|
|
7503
|
+
or "artifact validation failed before staging"
|
|
7504
|
+
)
|
|
7505
|
+
else:
|
|
7506
|
+
payload["error"] = "artifact budget exceeded before staging"
|
|
7311
7507
|
payload["issues"] = [
|
|
7312
7508
|
{
|
|
7313
7509
|
"code": str(
|
|
@@ -7380,6 +7576,38 @@ def cmd_finalize(
|
|
|
7380
7576
|
work_dir = operation_temp_dir
|
|
7381
7577
|
before_manifest: dict[str, Any] | None = None
|
|
7382
7578
|
|
|
7579
|
+
# A source tree without sensitive evidence still receives a digest-bound
|
|
7580
|
+
# receipt in the isolated staging tree. This keeps legacy archives
|
|
7581
|
+
# compatible while making every published archive auditable.
|
|
7582
|
+
try:
|
|
7583
|
+
staged_receipt = hruntime.sensitive_evidence_receipt_path(work_dir)
|
|
7584
|
+
if not staged_receipt.is_file():
|
|
7585
|
+
hruntime.ensure_sensitive_evidence_scan_receipt(work_dir)
|
|
7586
|
+
staged_sensitive_gate = validate_sensitive_evidence_publication_gate(
|
|
7587
|
+
work_dir,
|
|
7588
|
+
copy_root=work_dir,
|
|
7589
|
+
require_receipt=True,
|
|
7590
|
+
)
|
|
7591
|
+
payload["steps"]["sensitive_evidence_publication"] = staged_sensitive_gate
|
|
7592
|
+
if not staged_sensitive_gate.get("ok"):
|
|
7593
|
+
payload["error"] = "sensitive evidence publication gate failed before freeze"
|
|
7594
|
+
payload["issues"] = [
|
|
7595
|
+
{
|
|
7596
|
+
"code": str(
|
|
7597
|
+
staged_sensitive_gate.get("reasonCode")
|
|
7598
|
+
or "SECRET_SCAN_GATE_BLOCKED"
|
|
7599
|
+
),
|
|
7600
|
+
"severity": "error",
|
|
7601
|
+
"message": payload["error"],
|
|
7602
|
+
}
|
|
7603
|
+
]
|
|
7604
|
+
_restore_finalize_failure()
|
|
7605
|
+
return 1, payload
|
|
7606
|
+
except (OSError, ValueError, json.JSONDecodeError) as exc:
|
|
7607
|
+
payload["error"] = f"sensitive evidence publication gate failed: {exc}"
|
|
7608
|
+
_restore_finalize_failure()
|
|
7609
|
+
return 1, payload
|
|
7610
|
+
|
|
7383
7611
|
if split_state_dir is not None and split_state_dir.is_dir():
|
|
7384
7612
|
_merge_runtime_state(split_state_dir, work_dir)
|
|
7385
7613
|
payload["steps"]["split_state_merge"] = {
|
|
@@ -7478,19 +7706,36 @@ def cmd_finalize(
|
|
|
7478
7706
|
"blockingCount": len(preflight.get("blocking") or []),
|
|
7479
7707
|
"itemsCount": len(preflight.get("items") or []),
|
|
7480
7708
|
}
|
|
7481
|
-
if preflight.get("
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7709
|
+
if preflight.get("ok") is not True:
|
|
7710
|
+
blocking_paths = preflight.get("blocking") or []
|
|
7711
|
+
if blocking_paths:
|
|
7712
|
+
payload["error"] = (
|
|
7713
|
+
f"artifact preflight blocking: "
|
|
7714
|
+
f"{len(blocking_paths)} path(s) cannot be archived"
|
|
7715
|
+
)
|
|
7716
|
+
payload["issues"] = [
|
|
7717
|
+
{
|
|
7718
|
+
"code": "ARTIFACT_PATH_BLOCKING",
|
|
7719
|
+
"severity": "error",
|
|
7720
|
+
"message": f"{item.get('path', '')}: {item.get('reason', 'blocking')}",
|
|
7721
|
+
}
|
|
7722
|
+
for item in blocking_paths
|
|
7723
|
+
]
|
|
7724
|
+
else:
|
|
7725
|
+
payload["error"] = (
|
|
7726
|
+
"artifact preflight invalid: "
|
|
7727
|
+
+ str(
|
|
7728
|
+
preflight.get("error")
|
|
7729
|
+
or "artifact event projection or preflight validation failed"
|
|
7730
|
+
)
|
|
7731
|
+
)
|
|
7732
|
+
payload["issues"] = [
|
|
7733
|
+
{
|
|
7734
|
+
"code": "ARTIFACT_PREFLIGHT_INVALID",
|
|
7735
|
+
"severity": "error",
|
|
7736
|
+
"message": payload["error"],
|
|
7737
|
+
}
|
|
7738
|
+
]
|
|
7494
7739
|
_restore_finalize_failure()
|
|
7495
7740
|
payload["warnings"] = warnings
|
|
7496
7741
|
payload["ok"] = False
|