@hunter-harness/workflow-harness 0.2.59 → 0.2.61
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/README.md +14 -16
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +43 -46
- package/harness/bundles/general/claude-code/harness-archive/checklist.md +10 -10
- package/harness/bundles/general/claude-code/harness-archive/reference.md +29 -22
- package/harness/bundles/general/claude-code/harness-archive/templates/summary-data-template.json +1 -7
- 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 +4 -4
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +2 -2
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +5 -3
- package/harness/bundles/general/claude-code/harness-run/checklist.md +10 -9
- package/harness/bundles/general/claude-code/harness-run/protocols.md +2 -0
- package/harness/bundles/general/claude-code/harness-run/reference.md +19 -16
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +2 -2
- package/harness/bundles/general/claude-code/harness-test/checklist.md +2 -2
- package/harness/bundles/general/claude-code/harness-test/pitfalls.md +3 -3
- package/harness/bundles/general/claude-code/harness-test/reference.md +2 -2
- package/harness/bundles/general/claude-code/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/general/claude-code/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/general/claude-code/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/general/claude-code/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/general/claude-code/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/general/claude-code/scripts/harness_context.py +8 -2
- package/harness/bundles/general/claude-code/scripts/harness_events.py +5 -0
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +79 -2
- package/harness/bundles/general/claude-code/scripts/harness_profile.py +7 -0
- package/harness/bundles/general/claude-code/scripts/harness_state.py +22 -3
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/README.md +14 -16
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +43 -46
- package/harness/bundles/general/codebuddy/harness-archive/checklist.md +10 -10
- package/harness/bundles/general/codebuddy/harness-archive/reference.md +29 -22
- package/harness/bundles/general/codebuddy/harness-archive/templates/summary-data-template.json +1 -7
- 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 +4 -4
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +2 -2
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +5 -3
- package/harness/bundles/general/codebuddy/harness-run/checklist.md +10 -9
- package/harness/bundles/general/codebuddy/harness-run/protocols.md +2 -0
- package/harness/bundles/general/codebuddy/harness-run/reference.md +19 -16
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +2 -2
- package/harness/bundles/general/codebuddy/harness-test/checklist.md +2 -2
- package/harness/bundles/general/codebuddy/harness-test/pitfalls.md +3 -3
- package/harness/bundles/general/codebuddy/harness-test/reference.md +2 -2
- package/harness/bundles/general/codebuddy/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/general/codebuddy/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/general/codebuddy/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/general/codebuddy/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/general/codebuddy/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/general/codebuddy/scripts/harness_context.py +8 -2
- package/harness/bundles/general/codebuddy/scripts/harness_events.py +5 -0
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +79 -2
- package/harness/bundles/general/codebuddy/scripts/harness_profile.py +7 -0
- package/harness/bundles/general/codebuddy/scripts/harness_state.py +22 -3
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/README.md +14 -16
- package/harness/bundles/general/codex/harness-archive/SKILL.md +43 -46
- package/harness/bundles/general/codex/harness-archive/checklist.md +10 -10
- package/harness/bundles/general/codex/harness-archive/reference.md +29 -22
- package/harness/bundles/general/codex/harness-archive/templates/summary-data-template.json +1 -7
- 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 +4 -4
- package/harness/bundles/general/codex/harness-review/SKILL.md +2 -2
- package/harness/bundles/general/codex/harness-run/SKILL.md +5 -3
- package/harness/bundles/general/codex/harness-run/checklist.md +10 -9
- package/harness/bundles/general/codex/harness-run/protocols.md +2 -0
- package/harness/bundles/general/codex/harness-run/reference.md +19 -16
- package/harness/bundles/general/codex/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-test/SKILL.md +2 -2
- package/harness/bundles/general/codex/harness-test/checklist.md +2 -2
- package/harness/bundles/general/codex/harness-test/pitfalls.md +3 -3
- package/harness/bundles/general/codex/harness-test/reference.md +2 -2
- package/harness/bundles/general/codex/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/general/codex/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/general/codex/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/general/codex/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/general/codex/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/general/codex/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/general/codex/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/general/codex/scripts/harness_context.py +8 -2
- package/harness/bundles/general/codex/scripts/harness_events.py +5 -0
- package/harness/bundles/general/codex/scripts/harness_ledger.py +79 -2
- package/harness/bundles/general/codex/scripts/harness_profile.py +7 -0
- package/harness/bundles/general/codex/scripts/harness_state.py +22 -3
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/README.md +14 -16
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +43 -46
- package/harness/bundles/general/cursor/harness-archive/checklist.md +10 -10
- package/harness/bundles/general/cursor/harness-archive/reference.md +29 -22
- package/harness/bundles/general/cursor/harness-archive/templates/summary-data-template.json +1 -7
- 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 +4 -4
- package/harness/bundles/general/cursor/harness-review/SKILL.md +2 -2
- package/harness/bundles/general/cursor/harness-run/SKILL.md +5 -3
- package/harness/bundles/general/cursor/harness-run/checklist.md +10 -9
- package/harness/bundles/general/cursor/harness-run/protocols.md +2 -0
- package/harness/bundles/general/cursor/harness-run/reference.md +19 -16
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-test/SKILL.md +2 -2
- package/harness/bundles/general/cursor/harness-test/checklist.md +2 -2
- package/harness/bundles/general/cursor/harness-test/pitfalls.md +3 -3
- package/harness/bundles/general/cursor/harness-test/reference.md +2 -2
- package/harness/bundles/general/cursor/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/general/cursor/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/general/cursor/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/general/cursor/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/general/cursor/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/general/cursor/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/general/cursor/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/general/cursor/scripts/harness_context.py +8 -2
- package/harness/bundles/general/cursor/scripts/harness_events.py +5 -0
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +79 -2
- package/harness/bundles/general/cursor/scripts/harness_profile.py +7 -0
- package/harness/bundles/general/cursor/scripts/harness_state.py +22 -3
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/README.md +14 -16
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +2 -2
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +43 -46
- package/harness/bundles/java/claude-code/harness-archive/checklist.md +10 -10
- package/harness/bundles/java/claude-code/harness-archive/reference.md +29 -22
- package/harness/bundles/java/claude-code/harness-archive/templates/summary-data-template.json +1 -7
- 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 +2 -2
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +4 -4
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +2 -2
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +5 -3
- package/harness/bundles/java/claude-code/harness-run/protocols.md +2 -0
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +2 -2
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +2 -2
- package/harness/bundles/java/claude-code/harness-test/checklist.md +2 -2
- package/harness/bundles/java/claude-code/harness-test/pitfalls.md +3 -3
- package/harness/bundles/java/claude-code/harness-test/reference.md +2 -2
- package/harness/bundles/java/claude-code/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/java/claude-code/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/java/claude-code/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/java/claude-code/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/java/claude-code/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/java/claude-code/scripts/harness_context.py +8 -2
- package/harness/bundles/java/claude-code/scripts/harness_events.py +5 -0
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +79 -2
- package/harness/bundles/java/claude-code/scripts/harness_profile.py +7 -0
- package/harness/bundles/java/claude-code/scripts/harness_state.py +22 -3
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/README.md +14 -16
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +2 -2
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +43 -46
- package/harness/bundles/java/codebuddy/harness-archive/checklist.md +10 -10
- package/harness/bundles/java/codebuddy/harness-archive/reference.md +29 -22
- package/harness/bundles/java/codebuddy/harness-archive/templates/summary-data-template.json +1 -7
- 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 +2 -2
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +4 -4
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +2 -2
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +5 -3
- package/harness/bundles/java/codebuddy/harness-run/protocols.md +2 -0
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +2 -2
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +2 -2
- package/harness/bundles/java/codebuddy/harness-test/checklist.md +2 -2
- package/harness/bundles/java/codebuddy/harness-test/pitfalls.md +3 -3
- package/harness/bundles/java/codebuddy/harness-test/reference.md +2 -2
- package/harness/bundles/java/codebuddy/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/java/codebuddy/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/java/codebuddy/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/java/codebuddy/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/java/codebuddy/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/java/codebuddy/scripts/harness_context.py +8 -2
- package/harness/bundles/java/codebuddy/scripts/harness_events.py +5 -0
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +79 -2
- package/harness/bundles/java/codebuddy/scripts/harness_profile.py +7 -0
- package/harness/bundles/java/codebuddy/scripts/harness_state.py +22 -3
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/README.md +14 -16
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +2 -2
- package/harness/bundles/java/codex/harness-archive/SKILL.md +43 -46
- package/harness/bundles/java/codex/harness-archive/checklist.md +10 -10
- package/harness/bundles/java/codex/harness-archive/reference.md +29 -22
- package/harness/bundles/java/codex/harness-archive/templates/summary-data-template.json +1 -7
- 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 +2 -2
- package/harness/bundles/java/codex/harness-plan/SKILL.md +4 -4
- package/harness/bundles/java/codex/harness-review/SKILL.md +2 -2
- package/harness/bundles/java/codex/harness-run/SKILL.md +5 -3
- package/harness/bundles/java/codex/harness-run/protocols.md +2 -0
- package/harness/bundles/java/codex/harness-submit/SKILL.md +2 -2
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +2 -2
- package/harness/bundles/java/codex/harness-test/checklist.md +2 -2
- package/harness/bundles/java/codex/harness-test/pitfalls.md +3 -3
- package/harness/bundles/java/codex/harness-test/reference.md +2 -2
- package/harness/bundles/java/codex/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/java/codex/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/java/codex/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/java/codex/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/java/codex/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/java/codex/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/java/codex/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/java/codex/scripts/harness_context.py +8 -2
- package/harness/bundles/java/codex/scripts/harness_events.py +5 -0
- package/harness/bundles/java/codex/scripts/harness_ledger.py +79 -2
- package/harness/bundles/java/codex/scripts/harness_profile.py +7 -0
- package/harness/bundles/java/codex/scripts/harness_state.py +22 -3
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/README.md +14 -16
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +2 -2
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +43 -46
- package/harness/bundles/java/cursor/harness-archive/checklist.md +10 -10
- package/harness/bundles/java/cursor/harness-archive/reference.md +29 -22
- package/harness/bundles/java/cursor/harness-archive/templates/summary-data-template.json +1 -7
- 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 +2 -2
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +4 -4
- package/harness/bundles/java/cursor/harness-review/SKILL.md +2 -2
- package/harness/bundles/java/cursor/harness-run/SKILL.md +5 -3
- package/harness/bundles/java/cursor/harness-run/protocols.md +2 -0
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +2 -2
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +2 -2
- package/harness/bundles/java/cursor/harness-test/checklist.md +2 -2
- package/harness/bundles/java/cursor/harness-test/pitfalls.md +3 -3
- package/harness/bundles/java/cursor/harness-test/reference.md +2 -2
- package/harness/bundles/java/cursor/protocols/archive-report-protocol.md +18 -25
- package/harness/bundles/java/cursor/protocols/evidence-based-reporting-protocol.md +5 -5
- package/harness/bundles/java/cursor/protocols/ledger-protocol.md +7 -7
- package/harness/bundles/java/cursor/protocols/report-pipeline-protocol.md +10 -9
- package/harness/bundles/java/cursor/protocols/sensitive-info-protocol.md +3 -3
- package/harness/bundles/java/cursor/protocols/state-layout-protocol.md +5 -6
- package/harness/bundles/java/cursor/scripts/harness_archive.py +1043 -1108
- package/harness/bundles/java/cursor/scripts/harness_context.py +8 -2
- package/harness/bundles/java/cursor/scripts/harness_events.py +5 -0
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +79 -2
- package/harness/bundles/java/cursor/scripts/harness_profile.py +7 -0
- package/harness/bundles/java/cursor/scripts/harness_state.py +22 -3
- package/harness/manifests/general/claude-code.json +35 -39
- package/harness/manifests/general/codebuddy.json +35 -39
- package/harness/manifests/general/codex.json +35 -39
- package/harness/manifests/general/cursor.json +35 -39
- package/harness/manifests/java/claude-code.json +35 -39
- package/harness/manifests/java/codebuddy.json +35 -39
- package/harness/manifests/java/codex.json +35 -39
- package/harness/manifests/java/cursor.json +35 -39
- package/hunter-workflow-family.json +5 -5
- package/package.json +1 -1
- package/harness/bundles/general/claude-code/harness-archive/templates/render-summary.mjs +0 -299
- package/harness/bundles/general/codebuddy/harness-archive/templates/render-summary.mjs +0 -299
- package/harness/bundles/general/codex/harness-archive/templates/render-summary.mjs +0 -299
- package/harness/bundles/general/cursor/harness-archive/templates/render-summary.mjs +0 -299
- package/harness/bundles/java/claude-code/harness-archive/templates/render-summary.mjs +0 -299
- package/harness/bundles/java/codebuddy/harness-archive/templates/render-summary.mjs +0 -299
- package/harness/bundles/java/codex/harness-archive/templates/render-summary.mjs +0 -299
- package/harness/bundles/java/cursor/harness-archive/templates/render-summary.mjs +0 -299
|
@@ -810,10 +810,15 @@ def close_transition(
|
|
|
810
810
|
artifact_entries: list[dict[str, Any]] = []
|
|
811
811
|
for raw in artifacts or []:
|
|
812
812
|
requested = Path(raw)
|
|
813
|
+
artifact_bases: list[Path] = []
|
|
814
|
+
for base in (project, contract_root, state_root):
|
|
815
|
+
resolved_base = base.resolve()
|
|
816
|
+
if resolved_base not in artifact_bases:
|
|
817
|
+
artifact_bases.append(resolved_base)
|
|
813
818
|
candidates = (
|
|
814
819
|
[requested]
|
|
815
820
|
if requested.is_absolute()
|
|
816
|
-
else [
|
|
821
|
+
else [base / requested for base in artifact_bases]
|
|
817
822
|
)
|
|
818
823
|
valid: list[Path] = []
|
|
819
824
|
for candidate in candidates:
|
|
@@ -838,10 +843,11 @@ def close_transition(
|
|
|
838
843
|
"ok": False,
|
|
839
844
|
"code": "TRANSITION_ARTIFACT_INVALID",
|
|
840
845
|
"path": raw,
|
|
841
|
-
"acceptedBases": [str(
|
|
846
|
+
"acceptedBases": [str(base) for base in artifact_bases],
|
|
842
847
|
"examples": [
|
|
843
848
|
str(contract_root / "meta" / "plan-finalization.json"),
|
|
844
849
|
f".harness/changes/{change}/meta/plan-finalization.json",
|
|
850
|
+
f".harness/state/changes/{change}/evidence/verification-ledger.json",
|
|
845
851
|
"meta/plan-finalization.json",
|
|
846
852
|
],
|
|
847
853
|
}
|
|
@@ -1077,6 +1077,11 @@ def split_phase_attempts(phase_events: list[dict[str, Any]]) -> list[dict[str, A
|
|
|
1077
1077
|
"external.wait",
|
|
1078
1078
|
"issue",
|
|
1079
1079
|
"ci.wait",
|
|
1080
|
+
# Preparation is intentionally outside the formal phase lifecycle.
|
|
1081
|
+
# A blocked preflight must remain visible in the raw timeline without
|
|
1082
|
+
# manufacturing an attempt or inflating the phase duration/count.
|
|
1083
|
+
"phase.prepare.start",
|
|
1084
|
+
"phase.prepare.end",
|
|
1080
1085
|
}
|
|
1081
1086
|
for event in phase_events:
|
|
1082
1087
|
if event.get("type") == "phase.start":
|
|
@@ -1053,6 +1053,40 @@ def ledger_evidence_identity(ledger: dict[str, Any]) -> str:
|
|
|
1053
1053
|
return "sha256:" + hashlib.sha256(canonical).hexdigest()
|
|
1054
1054
|
|
|
1055
1055
|
|
|
1056
|
+
def _immutable_change_base(
|
|
1057
|
+
change_dir: Path,
|
|
1058
|
+
project_root: Path,
|
|
1059
|
+
) -> str:
|
|
1060
|
+
roots = [change_dir]
|
|
1061
|
+
try:
|
|
1062
|
+
state_root = harness_paths.resolve_state_dir_for_contract(
|
|
1063
|
+
change_dir,
|
|
1064
|
+
project_root,
|
|
1065
|
+
)
|
|
1066
|
+
if state_root.resolve() != change_dir.resolve():
|
|
1067
|
+
roots.insert(0, state_root)
|
|
1068
|
+
except (OSError, ValueError):
|
|
1069
|
+
pass
|
|
1070
|
+
for root in roots:
|
|
1071
|
+
for relative in (
|
|
1072
|
+
Path("meta") / "state-snapshot.json",
|
|
1073
|
+
Path("state-snapshot.json"),
|
|
1074
|
+
):
|
|
1075
|
+
path = root / relative
|
|
1076
|
+
if not path.is_file():
|
|
1077
|
+
continue
|
|
1078
|
+
try:
|
|
1079
|
+
payload = json.loads(path.read_text(encoding="utf-8-sig"))
|
|
1080
|
+
except (OSError, json.JSONDecodeError, TypeError):
|
|
1081
|
+
continue
|
|
1082
|
+
if not isinstance(payload, dict):
|
|
1083
|
+
continue
|
|
1084
|
+
value = str(payload.get("changeBase") or "").strip()
|
|
1085
|
+
if value:
|
|
1086
|
+
return value
|
|
1087
|
+
return ""
|
|
1088
|
+
|
|
1089
|
+
|
|
1056
1090
|
def migrate_ledger_for_write(
|
|
1057
1091
|
change_dir: Path,
|
|
1058
1092
|
ledger: dict[str, Any],
|
|
@@ -1089,6 +1123,15 @@ def migrate_ledger_for_write(
|
|
|
1089
1123
|
if not _nonempty_str(resolved_base):
|
|
1090
1124
|
resolved_base = ledger.get("baseCommit")
|
|
1091
1125
|
if not _nonempty_str(resolved_base):
|
|
1126
|
+
resolved_base = _immutable_change_base(change_dir, repo_root)
|
|
1127
|
+
if not _nonempty_str(resolved_base):
|
|
1128
|
+
if record_migration:
|
|
1129
|
+
raise LedgerMigrationError(
|
|
1130
|
+
"immutable change base is missing; recapture the Plan boundary "
|
|
1131
|
+
"or pass an explicit --base-commit instead of using write-time HEAD"
|
|
1132
|
+
)
|
|
1133
|
+
# A genuinely new ledger establishes its identity at the first write.
|
|
1134
|
+
# Existing ledgers are handled above and may never take this fallback.
|
|
1092
1135
|
resolved_base = current_head
|
|
1093
1136
|
resolved_diff = diff_hash
|
|
1094
1137
|
if not _nonempty_str(resolved_diff):
|
|
@@ -2795,9 +2838,43 @@ def cmd_diff_hash(args: argparse.Namespace) -> int:
|
|
|
2795
2838
|
repo_raw = getattr(args, "repo", None)
|
|
2796
2839
|
repo = Path(repo_raw).expanduser().resolve() if repo_raw else Path.cwd().resolve()
|
|
2797
2840
|
base = getattr(args, "base", None)
|
|
2798
|
-
|
|
2841
|
+
change_dir_raw = getattr(args, "change_dir", None)
|
|
2799
2842
|
try:
|
|
2800
|
-
|
|
2843
|
+
change_dir = resolve_path(change_dir_raw) if change_dir_raw else None
|
|
2844
|
+
if change_dir is not None and _contract_is_v2(change_dir):
|
|
2845
|
+
resolved_base = str(base or "").strip()
|
|
2846
|
+
if not resolved_base:
|
|
2847
|
+
existing, _ = load_ledger(change_dir)
|
|
2848
|
+
if isinstance(existing, dict):
|
|
2849
|
+
resolved_base = str(existing.get("baseCommit") or "").strip()
|
|
2850
|
+
if not resolved_base:
|
|
2851
|
+
resolved_base = _immutable_change_base(change_dir, repo)
|
|
2852
|
+
if not resolved_base:
|
|
2853
|
+
raise ValueError(
|
|
2854
|
+
"immutable change base is missing; capture the Plan boundary "
|
|
2855
|
+
"or pass --base"
|
|
2856
|
+
)
|
|
2857
|
+
detail = compute_ownership_diff(
|
|
2858
|
+
repo,
|
|
2859
|
+
base=resolved_base,
|
|
2860
|
+
change_dir=change_dir,
|
|
2861
|
+
)
|
|
2862
|
+
payload = {
|
|
2863
|
+
"ok": True,
|
|
2864
|
+
"action": "diff-hash",
|
|
2865
|
+
"identityScope": "change-ownership",
|
|
2866
|
+
"algorithmVersion": "ownership-content-changeset-1",
|
|
2867
|
+
"base": resolved_base,
|
|
2868
|
+
"head": _git_text(repo, "rev-parse", "--verify", "HEAD"),
|
|
2869
|
+
**detail,
|
|
2870
|
+
}
|
|
2871
|
+
emit_json(payload, as_json=as_json)
|
|
2872
|
+
return 0
|
|
2873
|
+
diff_hash, meta = compute_diff_hash(
|
|
2874
|
+
repo,
|
|
2875
|
+
base=base,
|
|
2876
|
+
change_dir=str(change_dir) if change_dir is not None else None,
|
|
2877
|
+
)
|
|
2801
2878
|
except (OSError, RuntimeError, ValueError) as exc:
|
|
2802
2879
|
return emit_error(str(exc), as_json=as_json)
|
|
2803
2880
|
payload = {"ok": True, "action": "diff-hash", "diffHash": diff_hash}
|
|
@@ -838,13 +838,20 @@ def _node_commands(project: Path) -> dict[str, Any]:
|
|
|
838
838
|
"src/**/*.tsx",
|
|
839
839
|
"test/**/*.ts",
|
|
840
840
|
"test/**/*.tsx",
|
|
841
|
+
"tests/**/*.ts",
|
|
842
|
+
"tests/**/*.tsx",
|
|
841
843
|
"packages/*/src/**/*.ts",
|
|
842
844
|
"packages/*/src/**/*.tsx",
|
|
843
845
|
"packages/*/test/**/*.ts",
|
|
844
846
|
"packages/*/test/**/*.tsx",
|
|
847
|
+
"packages/*/tests/**/*.ts",
|
|
848
|
+
"packages/*/tests/**/*.tsx",
|
|
845
849
|
"apps/*/src/**/*.ts",
|
|
846
850
|
"apps/*/src/**/*.tsx",
|
|
847
851
|
"apps/*/test/**/*.ts",
|
|
852
|
+
"apps/*/test/**/*.tsx",
|
|
853
|
+
"apps/*/tests/**/*.ts",
|
|
854
|
+
"apps/*/tests/**/*.tsx",
|
|
848
855
|
]
|
|
849
856
|
# harness dogfood: canonical Python + .mjs sources feed npm run check (vitest
|
|
850
857
|
# imports harness-test/scripts; smoke:pack runs sync-harness.mjs).
|
|
@@ -119,6 +119,10 @@ def capture_snapshot(
|
|
|
119
119
|
"schemaVersion": SNAPSHOT_SCHEMA_VERSION,
|
|
120
120
|
"generatedAt": now_iso(),
|
|
121
121
|
"changeName": change_name,
|
|
122
|
+
# The first captured Git boundary is the immutable identity of the
|
|
123
|
+
# change. Later phases may advance HEAD, but must never silently move
|
|
124
|
+
# the base and collapse the archive range.
|
|
125
|
+
"changeBase": base or "",
|
|
122
126
|
"project": {"root": str(project.resolve())},
|
|
123
127
|
"worktree": {"root": str(Path(worktree_root).resolve())},
|
|
124
128
|
"git": {"base": base or "", "head": head or ""},
|
|
@@ -250,10 +254,25 @@ def capture_current_state(
|
|
|
250
254
|
base: str = "",
|
|
251
255
|
head: str = "HEAD",
|
|
252
256
|
) -> tuple[dict[str, Any], list[str]]:
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
files = discover_segment_files(project, change_dir, base=resolved_base, head=resolved_head)
|
|
257
|
+
git_head = _git(project, "rev-parse", head)
|
|
258
|
+
resolved_head = git_head or head
|
|
256
259
|
previous = load_snapshot(change_dir)
|
|
260
|
+
previous_git = previous.get("git") if isinstance(previous, dict) else None
|
|
261
|
+
previous_base = (
|
|
262
|
+
str(previous.get("changeBase") or "").strip()
|
|
263
|
+
if isinstance(previous, dict)
|
|
264
|
+
else ""
|
|
265
|
+
)
|
|
266
|
+
if not previous_base and isinstance(previous_git, dict):
|
|
267
|
+
previous_base = str(
|
|
268
|
+
previous_git.get("base") or previous_git.get("baseCommit") or ""
|
|
269
|
+
).strip()
|
|
270
|
+
requested_base = _git(project, "rev-parse", base) if base else ""
|
|
271
|
+
# First capture establishes the boundary. A later --base value is an
|
|
272
|
+
# observation hint only; changing the boundary requires the explicit
|
|
273
|
+
# archive range-adoption receipt.
|
|
274
|
+
resolved_base = previous_base or requested_base or git_head
|
|
275
|
+
files = discover_segment_files(project, change_dir, base=resolved_base, head=resolved_head)
|
|
257
276
|
fresh = capture_snapshot(
|
|
258
277
|
change_dir,
|
|
259
278
|
change_name=change_name,
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
|
|
24
24
|
## 共用规则文件(强制约束)
|
|
25
25
|
|
|
26
|
-
跨 skill 共用的强制约束规则全部集中在 `protocols/` 下(8 个 protocol;其中 report pipeline
|
|
26
|
+
跨 skill 共用的强制约束规则全部集中在 `protocols/` 下(8 个 protocol;其中 report pipeline 用于结构化事件,以及 summary-data 的生成与校验),各 skill 通过相对路径引用:
|
|
27
27
|
|
|
28
28
|
| 文件 | 作用 |
|
|
29
29
|
|------|------|
|
|
30
30
|
| `protocols/powershell-protocol.md` | Shell 执行安全策略:Windows/中文路径下禁止普通 Bash,所有 git/构建命令必须通过 `powershell.exe -Command "..."` 执行;命令被拒绝时不得回退普通 Bash;所有"成功"必须有明确证据(构建成功 / git 输出 / 文件存在 / exit code 0) |
|
|
31
|
-
| `protocols/sensitive-info-protocol.md` | 敏感信息脱敏:token、密码、Authorization header、Cookie、API key、access/secret key 不得明文出现在 execution-log、报告、commit message、
|
|
31
|
+
| `protocols/sensitive-info-protocol.md` | 敏感信息脱敏:token、密码、Authorization header、Cookie、API key、access/secret key 不得明文出现在 execution-log、报告、commit message、summary-data 中;引用时统一替换为 `<TOKEN_REDACTED>` / `<PASSWORD_REDACTED>` / `<SECRET_REDACTED>` |
|
|
32
32
|
| `protocols/evidence-based-reporting-protocol.md` | 证据化报告:所有 skill 输出必须区分 ✅ 真实成功 / 🟡 静态验证或用户跳过 / ❌ 失败或被拒绝;禁止把"静态验证"写成"测试通过",禁止把"命令被拒绝"写成"成功" |
|
|
33
33
|
| `protocols/ledger-protocol.md` | 验证账本:每个变更目录维护 `verification-ledger.json`,记录 compile/unitTest/apiTest 的结果+证据+diffHash+作用范围;后续阶段先读 ledger 判定是否可复用,避免跨阶段重复编译/测试;post-test 变更按 7 类分类,决定是否重跑 |
|
|
34
34
|
| `protocols/state-layout-protocol.md` | 状态目录分层:`.harness/changes/<cn>/` 下按 `meta/`、`logs/`、`evidence/`、`reports/`、`scripts/`、`backups/` 子目录分层写入;读取时先读新路径再兼容旧路径 |
|
|
35
35
|
| `protocols/submit-protocol.md` | 固定提交交互:提交方式与 commit message 确认使用固定选项模板,禁止 AI footer |
|
|
36
|
-
| `protocols/archive-report-protocol.md` | 归档报告:`summary-data.json
|
|
37
|
-
| `protocols/report-pipeline-protocol.md` | 报告流水线:`events.ndjson` + `harness_archive.py
|
|
36
|
+
| `protocols/archive-report-protocol.md` | 归档报告:`summary-data.json`、manifest/checksum 与真实性规则 |
|
|
37
|
+
| `protocols/report-pipeline-protocol.md` | 报告流水线:`events.ndjson` + `harness_archive.py execute/replay` + 数据一致性校验 |
|
|
38
38
|
|
|
39
39
|
每个 skill 的 SKILL.md 关键规则章节都通过相对路径引用这些 protocol(`../protocols/powershell-protocol.md` 等)。
|
|
40
40
|
|
|
@@ -85,8 +85,7 @@
|
|
|
85
85
|
│ │ ├── test/
|
|
86
86
|
│ │ ├── review/
|
|
87
87
|
│ │ └── final/
|
|
88
|
-
│ │
|
|
89
|
-
│ │ └── final-summary.html # 最终报告(代码量+产出清单+测试/审查摘要)
|
|
88
|
+
│ │ └── summary-data.json # 平台展示使用的最终报告数据
|
|
90
89
|
│ ├── events.ndjson # 结构化事件层(新流程推荐;历史 archive 可缺失)
|
|
91
90
|
│ └── backups/
|
|
92
91
|
├── <change-name>/ # 当前未归档变更(最多 1 个,不提交)
|
|
@@ -160,9 +159,9 @@
|
|
|
160
159
|
- **Bash 拒绝、PowerShell 重试、降级、跳过、用户确认都必须记录**
|
|
161
160
|
- 日志状态统一使用 `✅OK / 🟡WARN(原因) / ❌FAIL(原因)`
|
|
162
161
|
- harness-archive 归档时从日志汇总:时间线、总用时、Skill 调用统计
|
|
163
|
-
- `harness_archive.py
|
|
162
|
+
- `harness_archive.py execute/replay` 优先从 `events.ndjson` 汇总命令、验证、artifact、问题和决策;旧 archive 缺少 events 时才回放 execution-log/ledger/manifest
|
|
164
163
|
- sync 默认不关联具体变更目录,仅在已有变更目录时追加日志和 events
|
|
165
|
-
- archive
|
|
164
|
+
- archive 是例外:`execute` 负责一次准备记录和一次正式 `phase.start` / `phase.end`,调用者不得重复追加阶段边界,也不得串行运行 `auto-gate`、`status`、`finalize`
|
|
166
165
|
|
|
167
166
|
## Skill 目录结构
|
|
168
167
|
|
|
@@ -211,8 +210,7 @@ harness-skills/
|
|
|
211
210
|
├── checklist.md # 归档前后检查项
|
|
212
211
|
├── reference.md # 归档操作 + 占位符真实性规则
|
|
213
212
|
└── templates/
|
|
214
|
-
|
|
215
|
-
└── render-summary.mjs # final-summary UTF-8 固定渲染脚本
|
|
213
|
+
└── summary-data-template.json # 最终报告数据结构
|
|
216
214
|
```
|
|
217
215
|
|
|
218
216
|
## Skill 列表
|
|
@@ -280,11 +278,11 @@ harness-skills/
|
|
|
280
278
|
| **submit hash 记录** | pre-pull local hash + final pushed hash 双标注(主目录);worktree 模式 submit 段只本地 commit,合并段产生 `mergeFinalHash`,archive 以 `mergeFinalHash` 为准(无则回退 final pushed hash) |
|
|
281
279
|
| **archive 阶段 1** | 归档前确认实际计划阶段的证据与结局;有 Git 时核对最终提交身份,无 Git、无 upstream 或跳过 submit 时使用内容清单身份。发布候选资格与本地封存分开判断;阶段边界由 finalize 单进程维护,调用者不额外 append |
|
|
282
280
|
| **archive 文件移动** | 只用 PowerShell 或 Read+Write+验证,**禁止 Bash mv/cp/rm**;移动失败时不删除原目录 |
|
|
283
|
-
| **archive
|
|
281
|
+
| **archive 最终报告** | 必须运行 `harness_archive.py execute`,由内部 finalize 生成权威 `summary-data.json` 并完成 validate。平台直接读取该 JSON;本地不生成重复的 HTML 报告。无测试或无 review 时必须标记 `NOT_RUN` / `ADVISORY_NOT_RUN`,禁止伪造 100% 通过率。状态演进须真实展示(✅OK / 🟡WARN / 🔁REUSED / 🔁RETESTED / 📝ADVISORY / 🧹NON_BEHAVIORAL_CLEANUP) |
|
|
284
282
|
|
|
285
283
|
### 敏感信息脱敏
|
|
286
284
|
|
|
287
|
-
- token / Authorization / Cookie / Redis 密码 / 数据库密码 / API key / access&secret key 不得明文出现在 execution-log、报告、commit message、
|
|
285
|
+
- token / Authorization / Cookie / Redis 密码 / 数据库密码 / API key / access&secret key 不得明文出现在 execution-log、报告、commit message、summary-data 中
|
|
288
286
|
- 引用敏感值时统一使用占位符:`<TOKEN_REDACTED>` / `<PASSWORD_REDACTED>` / `<SECRET_REDACTED>` / `<API_KEY_REDACTED>` / `<AUTH_HEADER_REDACTED>` / `<COOKIE_REDACTED>`
|
|
289
287
|
- 命令示例使用占位符,不复述真实值
|
|
290
288
|
- 测试中临时使用的 token 在持久化测试报告中必须替换为占位符
|
|
@@ -426,7 +424,7 @@ npx hunter-harness # 初始化阶段检查环境/CodeGraph/基础状态(非
|
|
|
426
424
|
/harness-test # 运行测试(30条避坑规则)
|
|
427
425
|
/harness-review # 代码审查
|
|
428
426
|
/harness-submit # 提交代码(worktree 模式含合并;/harness-merge 为别名)
|
|
429
|
-
/harness-archive # 归档产出(harness_archive.py
|
|
427
|
+
/harness-archive # 归档产出(harness_archive.py execute),释放工作区
|
|
430
428
|
```
|
|
431
429
|
|
|
432
430
|
## 避坑知识来源
|
|
@@ -455,8 +453,8 @@ npx hunter-harness # 初始化阶段检查环境/CodeGraph/基础状态(非
|
|
|
455
453
|
- `protocols/sensitive-info-protocol.md`:敏感信息脱敏(token/密码/密钥占位符化,已取代原 `harness-plan/sensitive-info.md`,各 skill 引用此版本)。
|
|
456
454
|
- `protocols/evidence-based-reporting-protocol.md`:证据化报告(✅/🟡/❌ 三态,已取代原 `harness-plan/evidence-based-reporting.md`,各 skill 引用此版本)。
|
|
457
455
|
- `protocols/submit-protocol.md`:固定提交交互、中文 commit 文件、禁止 AI footer。
|
|
458
|
-
- `protocols/archive-report-protocol.md`:summary-data
|
|
459
|
-
- `protocols/report-pipeline-protocol.md`:events.ndjson + `harness_archive.py
|
|
456
|
+
- `protocols/archive-report-protocol.md`:summary-data、manifest/checksum 与平台归档展示合同。
|
|
457
|
+
- `protocols/report-pipeline-protocol.md`:events.ndjson + `harness_archive.py execute/replay` + summary-data 一致性校验。
|
|
460
458
|
- `protocols/state-layout-protocol.md`:`.harness/changes/<cn>/` 子目录分层(meta/logs/evidence/reports/scripts/backups),读取先新后旧。
|
|
461
459
|
|
|
462
460
|
各 skill 的 `SKILL.md` 只保留阶段目标和硬门禁,细节优先引用这些协议,避免在多个 skill 中复制并产生冲突。
|
|
@@ -477,4 +475,4 @@ backups/ 未提交但用于验证的测试文件等备份
|
|
|
477
475
|
|
|
478
476
|
读取时先读新路径,再兼容旧路径。详见 `protocols/state-layout-protocol.md`。
|
|
479
477
|
|
|
480
|
-
Archive
|
|
478
|
+
Archive 常规入口为 `harness_archive.py execute`,内部 finalize 生成 `summary-data.json`。Hunter Platform 直接读取该文件,避免本地重复渲染和两份报告数据不一致。
|
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(awk *)
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=c4b98f515e0ec1ae; overlay=java; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-apidoc — 前端接口文档(Java overlay)
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -43,7 +43,7 @@ disallowed-tools:
|
|
|
43
43
|
6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
|
|
44
44
|
7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
|
|
45
45
|
8. **禁止读取 `docs/superpowers/` 作为正式输入** — 旧草稿仅人工线索
|
|
46
|
-
9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --base <baseCommit
|
|
46
|
+
9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --json`。首次 Plan 捕获时,脚本把当时的 Git HEAD 写入不可变 `changeBase`;后续阶段只刷新 `git.head` 与各段指纹,不得用当前 HEAD 覆盖 `changeBase`。只有迁移旧 change 且已能证明真实计划起点时,才在首次补录时传 `--base <baseCommit>`。`changedSegments=[]` 时复用已有 profile/rules/map/change/code 指纹,不再重复跑全量 `harness-sync` 或代码库扫描。`knowledge` 段仅为兼容空段,知识始终按需远端查询;快照不能替代源码读取和验证门禁。
|
|
47
47
|
|
|
48
48
|
状态目录分层:新路径优先,旧路径兼容 → [[../protocols/state-layout-protocol.md|state-layout-protocol]]
|
|
49
49
|
> 片段:read-protocol
|
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(awk *)
|
|
22
22
|
- Bash(curl *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=c4b98f515e0ec1ae; overlay=java; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-archive — 变更归档
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -47,7 +47,7 @@ disallowed-tools:
|
|
|
47
47
|
- **产品候选验证**:
|
|
48
48
|
- 有远端 CI:保留 `product-candidate-ci.json` 兼容证据;归档会把有效的 legacy schema v1 证据迁移为 `remote-claimed` 的 schema v2 `product-candidate-verification.json`,不会冒充 `remote-attested`。
|
|
49
49
|
- `remote-attested` 必须同时带远端运行 URL 与 `verification.attestationDigest`;只有 URL、旧 JSON 哈希或 ledger 哈希只能达到 `remote-claimed`。
|
|
50
|
-
- 无 CI
|
|
50
|
+
- 无 CI:`execute` 在候选收据缺失时自动尝试本地认证,只复用身份一致且完整的 `unitTestFull` ledger 证据,并在产品内容未变化时把提交前验证安全重绑定到当前 HEAD;认证不会执行测试。只有需要单独诊断认证结果时才手工运行 `certify-local`。
|
|
51
51
|
- `release-candidate` 要求候选验证通过;正常本地完成或结束未完成变更使用 `--intent record-only`,固定 `releaseEligible=false`,但仍生成 ZIP 并上传平台。
|
|
52
52
|
|
|
53
53
|
## Inputs
|
|
@@ -64,62 +64,60 @@ disallowed-tools:
|
|
|
64
64
|
6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
|
|
65
65
|
7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
|
|
66
66
|
8. **禁止读取 `docs/superpowers/` 作为正式输入** — 旧草稿仅人工线索
|
|
67
|
-
9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --base <baseCommit
|
|
67
|
+
9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --json`。首次 Plan 捕获时,脚本把当时的 Git HEAD 写入不可变 `changeBase`;后续阶段只刷新 `git.head` 与各段指纹,不得用当前 HEAD 覆盖 `changeBase`。只有迁移旧 change 且已能证明真实计划起点时,才在首次补录时传 `--base <baseCommit>`。`changedSegments=[]` 时复用已有 profile/rules/map/change/code 指纹,不再重复跑全量 `harness-sync` 或代码库扫描。`knowledge` 段仅为兼容空段,知识始终按需远端查询;快照不能替代源码读取和验证门禁。
|
|
68
68
|
|
|
69
69
|
状态目录分层:新路径优先,旧路径兼容 → [[../protocols/state-layout-protocol.md|state-layout-protocol]]
|
|
70
70
|
> 片段:read-protocol
|
|
71
71
|
|
|
72
72
|
## Workflow
|
|
73
73
|
|
|
74
|
-
先用 `harness_change.py resolve [--change] --json` 解析 change;多个 active change 未显式选择时返回 `CHANGE_SELECTION_REQUIRED`,禁止按 Glob/mtime
|
|
74
|
+
先用 `harness_change.py resolve [--change] --json` 解析 change;多个 active change 未显式选择时返回 `CHANGE_SELECTION_REQUIRED`,禁止按 Glob/mtime 自动选择。常规路径只运行一次 `harness_archive.py execute`。该命令一次性完成状态采集、自动门禁和 finalize,并复用同一份预检结果。调用者不得再串行运行 `auto-gate`、`status` 和 `finalize`,避免重复扫描、重复事件和幽灵 change 目录。
|
|
75
75
|
|
|
76
76
|
### Phase 0:读取规则和上下文
|
|
77
77
|
|
|
78
78
|
1. 读取本文件。
|
|
79
|
-
2.
|
|
80
|
-
3.
|
|
81
|
-
|
|
82
|
-
- `../protocols/state-layout-protocol.md`
|
|
83
|
-
- `../protocols/powershell-protocol.md`
|
|
84
|
-
- `../protocols/sensitive-info-protocol.md`
|
|
85
|
-
- `../protocols/evidence-based-reporting-protocol.md`
|
|
86
|
-
- `../protocols/report-pipeline-protocol.md`
|
|
87
|
-
4. 用 `harness_change.py resolve [--change] --json` 解析 `$ARGUMENTS`;多个 active change 时让用户选择。
|
|
79
|
+
2. 用 `harness_change.py resolve [--change] --json` 解析 `$ARGUMENTS`;多个 active change 时让用户选择。
|
|
80
|
+
3. 按共享读取协议刷新一次状态快照。首次 Plan 已记录的 `changeBase` 必须保持不变,归档阶段不得把当前 HEAD 写回为基线。
|
|
81
|
+
4. 常规路径不预读全部参考资料。仅在 `execute` 返回阻断或需要解释结果时,读取 `reference.md` 和对应协议章节。
|
|
88
82
|
|
|
89
83
|
### Phase 1:确认归档对象(扫描未归档变更)
|
|
90
84
|
|
|
91
|
-
使用 resolver 返回的 active changes 展示变更概要;同时读取 `plannedPhases
|
|
85
|
+
使用 resolver 返回的 active changes 展示变更概要;同时读取 `plannedPhases`、已完成阶段和用户表达的生命周期结局。Git remote 与平台连接不是归档前置条件,不在这里额外探测。
|
|
92
86
|
|
|
93
|
-
- **Read `checklist.md`** — 归档前检查项
|
|
94
87
|
- 发现多个未归档变更 → 让用户选择或终止
|
|
95
88
|
|
|
96
|
-
### Phase 2
|
|
89
|
+
### Phase 2:确定归档结局
|
|
97
90
|
|
|
98
|
-
|
|
91
|
+
根据用户当前指令确定一次归档结局:
|
|
99
92
|
|
|
100
|
-
-
|
|
101
|
-
-
|
|
93
|
+
- 明确要求发布候选:`--intent release-candidate --closure completed`。
|
|
94
|
+
- 正常完成但不要求发布:`--intent record-only --closure completed`。
|
|
95
|
+
- 主动停止或被其他方案替代:`--intent record-only --closure abandoned|superseded --closure-reason "<中文原因>"`。
|
|
102
96
|
|
|
103
|
-
|
|
97
|
+
信息已经明确时,不重复询问。信息不足且会改变结局时,才用中文提供「正常完成」「发布候选」「主动废弃」「被其他方案替代」「取消」。无 upstream 不阻止保存。
|
|
104
98
|
|
|
105
99
|
### Phase 3:执行归档
|
|
106
100
|
|
|
107
|
-
1.
|
|
108
|
-
2.
|
|
109
|
-
3.
|
|
101
|
+
1. 不要为归档预先补跑测试或手工修 ledger。候选收据缺失时,`execute` 会先尝试复用身份一致的全量 ledger 完成本地认证;无法认证时保留结构化原因,`record-only` 仍按事实归档,`release-candidate` 则由发布门禁决定是否阻断。
|
|
102
|
+
2. 运行一次 `harness_archive.py execute --change-dir "<executionRoot>" --archive-root ".harness/archive" --intent <...> --closure <...> [--closure-reason "..."] --json`。`execute` 只采集一次状态,并把准备耗时、正式归档耗时和唯一阶段轮次写入事件。调用者不得在它前后再运行 `auto-gate`、`status`、`finalize` 或手工追加 archive 阶段边界。
|
|
103
|
+
3. `meta/archive-meta.md` 与 `reports/final/summary-data.json` 均由脚本生成。禁止手写、补字段或手工修改 ledger 以绕过门禁。
|
|
104
|
+
4. `execute` 失败时,先按 `reasonCode` 处理,不要盲目重跑:
|
|
105
|
+
- `ARCHIVE_BASE_EQUALS_FEATURE_TIP`:正常完成不允许空范围归档。仅可选择受控认领既有提交范围、改为未完成封存,或取消。
|
|
106
|
+
- 受控认领既有范围:先展示 base、tip 和产品文件清单;获得用户明确确认后运行 `adopt-existing-range --base <base> --tip <tip> --reason "<中文原因>" --confirm-existing-range --json`,再重跑一次 `execute`。禁止直接编辑 snapshot 或 ledger。
|
|
107
|
+
- `abandoned` / `superseded`:允许没有产品增量,但必须保存中文原因,并固定 `releaseEligible=false`。
|
|
108
|
+
- 其他阻断:读取 `reference.md` 中对应错误的恢复说明;原变更目录必须保留。
|
|
109
|
+
|
|
110
|
+
**本地不执行知识 ingest**;服务端在 ZIP 持久保存并解包后 ingest。失败时保留原目录、ZIP 和回执。
|
|
110
111
|
- **归档包上传**:始终先生成一个确定性 ZIP;有远程凭据时再调用 `npx hunter-harness archive upload`。ZIP 仅包含 `summary-data.json`、`spec/**/*.md`、`plans/**/*.md`、`archive-meta.md`、`change-context.json` 和稳定 manifest;明确排除 logs、review/test 报告、HTML、缓存、备份、凭据和临时文件。
|
|
111
112
|
- **失败可恢复**:无论远端凭据是否齐全,都先生成 ZIP 与 `<change-key>.upload.json`;上传或服务端 ingest 失败不破坏本地归档。待上传 ZIP 与逐 change 回执保留在 `.harness/state/local/archive-packages/`,可枚举独立重试。只有 CLI 核验 package hash 且服务端同时返回 `archive_status=durable`、`knowledge_status=ready` 后,才清理对应 ZIP 与回执;`indexing` 记为 pending,不记为失败。
|
|
112
113
|
- **监控终态(C3)**:auto-upload 之后自动 `events-sync`,用归档前 change 路径派生的 `run_id` + 原 `change_key` 上报;失败只记 warning。
|
|
113
114
|
|
|
114
|
-
- **Read `reference.md`** —
|
|
115
|
-
- **Read `templates/summary-data-template.json`** — summary
|
|
116
|
-
- **Read `templates/render-summary.mjs`** — final-summary 渲染脚本(finalize 内嵌调用)
|
|
115
|
+
- **Read `reference.md`** — 仅在阻断恢复或需要解释输出字段时读取
|
|
116
|
+
- **Read `templates/summary-data-template.json`** — 仅在排查 summary 校验失败时读取
|
|
117
117
|
|
|
118
118
|
### Phase 4:验证与提示
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
- **Read `checklist.md`** — 归档后验证项
|
|
120
|
+
以 `execute` 返回的 manifest、ZIP、上传回执和 `finalStatus` 为权威结果。只有返回字段缺失或不一致时,才读取 `checklist.md` 做人工诊断。不要为了重复确认成功结果再次扫描整个目录。
|
|
123
121
|
|
|
124
122
|
## P0 执行可信度规则
|
|
125
123
|
|
|
@@ -143,15 +141,15 @@ disallowed-tools:
|
|
|
143
141
|
|
|
144
142
|
### 二、归档前确认或自动门禁
|
|
145
143
|
|
|
146
|
-
`
|
|
144
|
+
`execute` 内部运行自动门禁。实际计划最后阶段已终态、边界快照存在且 `status.archivable=true` 时直接执行;未满足时返回阻断且不移动原目录。用户取消后不得重跑。
|
|
147
145
|
|
|
148
146
|
### 三、文件移动只用内置工具或 PowerShell
|
|
149
147
|
|
|
150
148
|
移动用 Read+Write+验证 或 PowerShell;**禁止 Bash mv/cp/rm**。移动失败时不删除原目录,报错退出让用户手动处理。
|
|
151
149
|
|
|
152
|
-
###
|
|
150
|
+
### 四、数据化归档门禁
|
|
153
151
|
|
|
154
|
-
必须通过 `harness_archive.py finalize` 生成权威 `reports/final/summary-data.json` 并完成 validate
|
|
152
|
+
必须通过 `harness_archive.py finalize` 生成权威 `reports/final/summary-data.json` 并完成 validate。平台监控直接读取该数据;本地不再生成重复的 HTML 报告。统计数字只能来自 summary-data、events、ledger 或 manifest。详见 `../protocols/report-pipeline-protocol.md`、`../protocols/archive-report-protocol.md`、`reference.md`。
|
|
155
153
|
|
|
156
154
|
### 五、manifest/checksum 必须存在
|
|
157
155
|
|
|
@@ -166,13 +164,15 @@ disallowed-tools:
|
|
|
166
164
|
|
|
167
165
|
### 七、verification-ledger 汇总状态
|
|
168
166
|
|
|
169
|
-
归档前读 `evidence/verification-ledger.json`,提取各阶段 status、postTestClassification、复用关系,供
|
|
167
|
+
归档前读 `evidence/verification-ledger.json`,提取各阶段 status、postTestClassification、复用关系,供 summary-data 真实记录状态演进。若 ledger 有 `postTestClassification`,summary-data 必须记录该分类及对应的复用/重测决策。
|
|
168
|
+
|
|
169
|
+
门禁策略未声明 `database` 能力,且 `requiredValidations` / `requiredValidationsByPhase` 也未要求 `dbCompatibility` 时,数据库兼容性投影固定为 `NOT_APPLICABLE`,原因来自能力配置。不得要求纯前端、文档或无数据库项目伪造数据库证据。
|
|
170
170
|
|
|
171
|
-
### 八、
|
|
171
|
+
### 八、summary-data 不得伪造且必须记录状态演进
|
|
172
172
|
|
|
173
173
|
无测试报告 → 显示"未运行测试 / 静态验证",不得 100% 通过率;无 review → "📝ADVISORY:未运行 review"。状态用 ✅OK / 🟡WARN / 🔁REUSED / 🔁RETESTED / 📝ADVISORY / 🧹NON_BEHAVIORAL_CLEANUP,复用前一阶段结果显示 🔁REUSED,**不得伪装成重新执行,不得无脑全绿**。
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
`summary-data.json` 是最终报告的唯一权威数据源,必须产出并通过 validate/adequacy。平台按该文件展示归档结果,本地不维护第二份展示文件。
|
|
176
176
|
|
|
177
177
|
### 九、CONDITIONAL_OK 最终状态
|
|
178
178
|
|
|
@@ -180,15 +180,15 @@ API 测试 `USER_SKIPPED` 或 DB 兼容 `BLOCKED_BY_DBA` 时,最终状态必
|
|
|
180
180
|
|
|
181
181
|
### 十、未提交测试文件归档
|
|
182
182
|
|
|
183
|
-
未提交但用于验证的测试文件必须归档到 `backups/uncommitted-tests
|
|
183
|
+
未提交但用于验证的测试文件必须归档到 `backups/uncommitted-tests/`,并在 summary-data 中记录。
|
|
184
184
|
|
|
185
185
|
### 十一、归档事件单一所有权
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
`execute` 在一次性预检通过后负责且仅负责一次正式 `phase.start` / `phase.end`。准备阶段单独使用 `phase.prepare.start/end`,不计为归档重跑。调用者不得重复追加阶段边界。归档后 events.ndjson 与自动渲染的 execution-log.md 一起位于 archive。
|
|
188
188
|
|
|
189
189
|
### 十二、Shell 安全 / 敏感信息 / 证据化报告
|
|
190
190
|
|
|
191
|
-
git 命令通过 `powershell.exe -Command "..."` 执行;archive-meta.md 和
|
|
191
|
+
git 命令通过 `powershell.exe -Command "..."` 执行;archive-meta.md 和 summary-data.json 不得含明文 token、密码或密钥;归档报告必须区分 ✅真实成功 / 🟡跳过·静态验证 / ❌失败。
|
|
192
192
|
|
|
193
193
|
### 十三、归档完整性与发布资格分离
|
|
194
194
|
|
|
@@ -196,27 +196,24 @@ git 命令通过 `powershell.exe -Command "..."` 执行;archive-meta.md 和 fi
|
|
|
196
196
|
|
|
197
197
|
## Output Format
|
|
198
198
|
|
|
199
|
-
> 归档元数据格式见 `reference.md` 的 archive-meta
|
|
199
|
+
> 归档元数据格式见 `reference.md` 的 archive-meta 模板;最终报告使用 `templates/summary-data-template.json` 定义的数据结构。
|
|
200
200
|
|
|
201
201
|
产出文件:
|
|
202
202
|
|
|
203
203
|
- `.harness/archive/YYYY-MM-DD-<change-name>/meta/archive-meta.md` — 归档元数据
|
|
204
204
|
- `.harness/archive/YYYY-MM-DD-<change-name>/events.ndjson` — 结构化事件层(新流程推荐;旧 archive 可缺失)
|
|
205
205
|
- `.harness/archive/YYYY-MM-DD-<change-name>/reports/final/summary-data.json` — 最终报告数据源
|
|
206
|
-
- `.harness/archive/YYYY-MM-DD-<change-name>/reports/final/final-summary.html` — 可选展示投影,由 `render-summary.mjs` 渲染(Node 失败时 Python fallback);渲染失败降级 warning,`--no-html` 可跳过
|
|
207
206
|
- `.harness/archive/YYYY-MM-DD-<change-name>/evidence/archive-manifest-before.json` / `archive-manifest-after.json` — 归档前后 manifest/checksum
|
|
208
207
|
|
|
209
208
|
## 渐进披露
|
|
210
209
|
|
|
211
|
-
- **Read `checklist.md`** 仅在
|
|
212
|
-
- **Read `reference.md`**
|
|
213
|
-
- **Read `
|
|
214
|
-
- **Read `templates/summary-data-template.json`** 仅在 Phase 3 生成 `summary-data.json` 时 — 含最终报告数据结构
|
|
215
|
-
- **Read `templates/render-summary.mjs`** 仅在 Phase 3 渲染 `final-summary.html` 时 — 固定 HTML 渲染脚本
|
|
210
|
+
- **Read `checklist.md`** 仅在 `execute` 返回结果缺失或 manifest 不一致时
|
|
211
|
+
- **Read `reference.md`** 仅在阻断恢复、受控范围认领或解释最终状态时
|
|
212
|
+
- **Read `templates/summary-data-template.json`** 仅在 summary 校验失败时
|
|
216
213
|
|
|
217
214
|
## 交互白名单
|
|
218
215
|
|
|
219
|
-
|
|
216
|
+
仅当生命周期结局不明确,或需要受控认领既有提交范围时,允许阻断式确认。拒绝后终止,不执行任何移动。
|
|
220
217
|
|
|
221
218
|
## 执行日志
|
|
222
219
|
|
|
@@ -8,11 +8,10 @@ description: harness-archive 的归档前检查项和归档后验证项。仅在
|
|
|
8
8
|
|
|
9
9
|
归档遵循 `../protocols/archive-report-protocol.md`,门禁要点见 SKILL.md `## 关键规则` 四/五/九:
|
|
10
10
|
|
|
11
|
-
-
|
|
11
|
+
- 生成并校验 `reports/final/summary-data.json`;平台直接使用该文件展示结果。
|
|
12
12
|
- 归档前生成 `evidence/archive-manifest-before.json`,移动后生成 `archive-manifest-after.json`。
|
|
13
|
-
-
|
|
13
|
+
- 归档统计只能来自 summary-data 或 manifest。
|
|
14
14
|
- before/after checksum 不一致时,不得删除原目录。
|
|
15
|
-
- 默认渲染器 `templates/render-summary.mjs`(finalize 内嵌调用)。
|
|
16
15
|
- 需要跨工作区恢复时传 `--durable-root <独立存储>`;成功必须为 `ARCHIVED_DURABLE`,并验证 content-addressed object 与 durable receipt 可读回。
|
|
17
16
|
- `restore-durable` 只恢复到不存在的目标;目标已存在或对象 digest 不符时 fail closed,禁止覆盖。
|
|
18
17
|
- 未配置 durable root 时显式记录 `ARCHIVED_LOCAL_ONLY` 风险,不得把同工作区 move 宣称为独立备份。
|
|
@@ -33,9 +32,9 @@ description: harness-archive 的归档前检查项和归档后验证项。仅在
|
|
|
33
32
|
|
|
34
33
|
## 归档前检查(Phase 1)
|
|
35
34
|
|
|
36
|
-
> ⚠️
|
|
35
|
+
> ⚠️ **单一所有权**:`execute` 负责一次准备记录和一次正式 `phase.start` / `phase.end`。归档前检查不得自行追加 archive 阶段边界。
|
|
37
36
|
|
|
38
|
-
- [ ] 未在调用
|
|
37
|
+
- [ ] 未在调用 `execute` 前手工追加 archive 阶段边界,也未串行调用 `auto-gate`、`status`、`finalize`
|
|
39
38
|
- [ ] 只有一个未归档变更目录(多个时终止或让用户选择)
|
|
40
39
|
- [ ] 已确认 `closure`:正常完成 / 主动废弃 / 被其他方案替代;后两者有中文 `closure-reason`
|
|
41
40
|
- [ ] 正常完成按 `plannedPhases` 核对;提前结束只要求可识别变更与安全封存的最小材料
|
|
@@ -46,13 +45,16 @@ description: harness-archive 的归档前检查项和归档后验证项。仅在
|
|
|
46
45
|
- [ ] Git 项目记录 dirty/HEAD/upstream;无 upstream 或仅本地 commit 允许归档,但 `releaseEligible=false`
|
|
47
46
|
- [ ] 非 Git 项目生成确定性内容清单与产品树散列,并记录 `sourceControl=none`
|
|
48
47
|
- [ ] 最终产品身份来自 Submit 收据或当前内容;提交前候选只允许在验证输入未变化时由 `certify-local` 自动重绑定
|
|
48
|
+
- [ ] `changeBase` 来自首次 Plan 快照,后续阶段未用当前 HEAD 覆盖;正常完成时 base 与产品 tip 不得相同
|
|
49
|
+
- [ ] 如使用既有提交范围,`meta/archive-range-adoption.json` 由 `adopt-existing-range --confirm-existing-range` 生成,未手工修改 ledger 或 snapshot
|
|
50
|
+
- [ ] 主动废弃或被替代允许没有产品增量,但必须有中文原因,且不得声明为发布候选
|
|
49
51
|
- [ ] **test/review 报告状态确认**:
|
|
50
52
|
- ✅ `.harness/changes/<change-name>/tests/test-report-*.md` 存在 → 归档正常
|
|
51
|
-
- 🟡 不存在 → 必须在 archive-meta.md 和
|
|
53
|
+
- 🟡 不存在 → 必须在 archive-meta.md 和 summary-data.json 中标记「跳过测试」或「未运行测试」,不得伪造通过率
|
|
52
54
|
- ✅ `.harness/changes/<change-name>/reports/review/review-report-*.md` 存在(旧路径 `reviews/review-report-*.md` 兼容回退)→ 作为 📝ADVISORY 归档材料
|
|
53
55
|
- 📝 `.harness/changes/<change-name>/reports/review/fixback-*.md` 存在 → 随 review 报告一并归档;默认 advisory,除非 `strict-review-gate=true`
|
|
54
56
|
- 🟡 不存在但 `logs/execution-log.md` 有 harness-review 小节 → **review 已运行但未落盘**(harness-review `context:fork` 交接缝常见,见 `agent/case-candidates/2026-06-30-harness-review-forked-not-persisting-report.md`):从 execution-log/会话补落盘到 `reports/review/review-report-YYYYMMDD-HHmm.md` 再归档,**不得误标"未运行 review"**(实际跑过)
|
|
55
|
-
- 🟡 不存在且 execution-log 无 review 小节 → 在 archive-meta.md 和
|
|
57
|
+
- 🟡 不存在且 execution-log 无 review 小节 → 在 archive-meta.md 和 summary-data.json 中标记「📝ADVISORY:未运行 review」
|
|
56
58
|
|
|
57
59
|
## 归档后验证(Phase 4)
|
|
58
60
|
|
|
@@ -61,11 +63,9 @@ description: harness-archive 的归档前检查项和归档后验证项。仅在
|
|
|
61
63
|
- [ ] before/after manifest 校验通过(排除 `logs/execution-log.md`——归档追加结束记录预期 sha256 变化;其他 moved 文件 sha256 必须一致,missing/mismatch=0)
|
|
62
64
|
- [ ] archive-meta.md 由 finalize 自动生成且字段完整;调用者未手写或补改
|
|
63
65
|
- [ ] summary-data.json 已生成,且为合法 JSON
|
|
64
|
-
- [ ]
|
|
65
|
-
- [ ] **final-summary.html 真实性检查**:
|
|
66
|
+
- [ ] **summary-data.json 真实性检查**:
|
|
66
67
|
- 无测试报告时,`summary-data.json.verification.unitTests.status` / `summary-data.json.verification.apiTests.status` 必须标记为 `NOT_RUN`、`USER_SKIPPED`、`BLOCKED` 或 `STATIC_ONLY`,不得显示 100%
|
|
67
68
|
- 无 review 报告时,`summary-data.json.reviewSummary.status` 必须标记为 `ADVISORY_NOT_RUN`,不得显示 100%
|
|
68
69
|
- 跳过、复用、人工确认的部分必须明确标记,不伪装成 ✅
|
|
69
|
-
- final-summary.html 中不得残留 `{{...}}` 占位符
|
|
70
70
|
- [ ] 原目录 `.harness/changes/<change-name>/` 已删除(仅在前面所有验证通过后)
|
|
71
71
|
- [ ] .harness/ 下无残留未归档变更目录
|