@hunter-harness/workflow-harness 0.2.1 → 0.2.3
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/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-archive/reference.md +2 -8
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +2 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +5 -1
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/checklist.md +1 -1
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/claude-code/harness-submit/checklist.md +30 -6
- 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 +1 -1
- package/harness/bundles/general/claude-code/harness-test/pitfalls.md +16 -0
- package/harness/bundles/general/claude-code/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/general/claude-code/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/general/claude-code/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/general/claude-code/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/general/claude-code/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +31 -14
- package/harness/bundles/general/claude-code/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/general/claude-code/scripts/harness_deploy.py +179 -4
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +269 -3
- package/harness/bundles/general/claude-code/scripts/harness_preflight.py +72 -382
- package/harness/bundles/general/claude-code/scripts/harness_profile.py +742 -0
- package/harness/bundles/general/claude-code/scripts/harness_service.py +99 -2
- package/harness/bundles/general/claude-code/scripts/harness_state.py +179 -0
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/reference.md +2 -8
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +2 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +5 -1
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/checklist.md +1 -1
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/codebuddy/harness-submit/checklist.md +30 -6
- 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 +1 -1
- package/harness/bundles/general/codebuddy/harness-test/pitfalls.md +16 -0
- package/harness/bundles/general/codebuddy/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/general/codebuddy/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/general/codebuddy/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/general/codebuddy/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/general/codebuddy/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +31 -14
- package/harness/bundles/general/codebuddy/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/general/codebuddy/scripts/harness_deploy.py +179 -4
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +269 -3
- package/harness/bundles/general/codebuddy/scripts/harness_preflight.py +72 -382
- package/harness/bundles/general/codebuddy/scripts/harness_profile.py +742 -0
- package/harness/bundles/general/codebuddy/scripts/harness_service.py +99 -2
- package/harness/bundles/general/codebuddy/scripts/harness_state.py +179 -0
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-archive/reference.md +2 -8
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +2 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +5 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/checklist.md +1 -1
- package/harness/bundles/general/codex/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/codex/harness-submit/checklist.md +30 -6
- 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 +1 -1
- package/harness/bundles/general/codex/harness-test/pitfalls.md +16 -0
- package/harness/bundles/general/codex/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/general/codex/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/general/codex/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/general/codex/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/general/codex/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/general/codex/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/general/codex/scripts/harness_archive.py +31 -14
- package/harness/bundles/general/codex/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/general/codex/scripts/harness_deploy.py +179 -4
- package/harness/bundles/general/codex/scripts/harness_ledger.py +269 -3
- package/harness/bundles/general/codex/scripts/harness_preflight.py +72 -382
- package/harness/bundles/general/codex/scripts/harness_profile.py +742 -0
- package/harness/bundles/general/codex/scripts/harness_service.py +99 -2
- package/harness/bundles/general/codex/scripts/harness_state.py +179 -0
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-archive/reference.md +2 -8
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +2 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +5 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/checklist.md +1 -1
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +2 -2
- package/harness/bundles/general/cursor/harness-submit/checklist.md +30 -6
- 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 +1 -1
- package/harness/bundles/general/cursor/harness-test/pitfalls.md +16 -0
- package/harness/bundles/general/cursor/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/general/cursor/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/general/cursor/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/general/cursor/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/general/cursor/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/general/cursor/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/general/cursor/scripts/harness_archive.py +31 -14
- package/harness/bundles/general/cursor/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/general/cursor/scripts/harness_deploy.py +179 -4
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +269 -3
- package/harness/bundles/general/cursor/scripts/harness_preflight.py +72 -382
- package/harness/bundles/general/cursor/scripts/harness_profile.py +742 -0
- package/harness/bundles/general/cursor/scripts/harness_service.py +99 -2
- package/harness/bundles/general/cursor/scripts/harness_state.py +179 -0
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- 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-archive/reference.md +2 -8
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +2 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +5 -1
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/claude-code/harness-run/checklist.md +3 -1
- package/harness/bundles/java/claude-code/harness-run/reference.md +6 -0
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-submit/checklist.md +30 -6
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +5 -5
- package/harness/bundles/java/claude-code/harness-test/checklist.md +3 -1
- package/harness/bundles/java/claude-code/harness-test/pitfalls.md +16 -0
- package/harness/bundles/java/claude-code/harness-test/reference.md +2 -0
- package/harness/bundles/java/claude-code/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/java/claude-code/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/java/claude-code/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/java/claude-code/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/java/claude-code/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +31 -14
- package/harness/bundles/java/claude-code/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/java/claude-code/scripts/harness_deploy.py +179 -4
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +269 -3
- package/harness/bundles/java/claude-code/scripts/harness_preflight.py +72 -382
- package/harness/bundles/java/claude-code/scripts/harness_profile.py +742 -0
- package/harness/bundles/java/claude-code/scripts/harness_service.py +99 -2
- package/harness/bundles/java/claude-code/scripts/harness_state.py +179 -0
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- 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-archive/reference.md +2 -8
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +2 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +5 -1
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/codebuddy/harness-run/checklist.md +3 -1
- package/harness/bundles/java/codebuddy/harness-run/reference.md +6 -0
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-submit/checklist.md +30 -6
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +5 -5
- package/harness/bundles/java/codebuddy/harness-test/checklist.md +3 -1
- package/harness/bundles/java/codebuddy/harness-test/pitfalls.md +16 -0
- package/harness/bundles/java/codebuddy/harness-test/reference.md +2 -0
- package/harness/bundles/java/codebuddy/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/java/codebuddy/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/java/codebuddy/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/java/codebuddy/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/java/codebuddy/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +31 -14
- package/harness/bundles/java/codebuddy/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/java/codebuddy/scripts/harness_deploy.py +179 -4
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +269 -3
- package/harness/bundles/java/codebuddy/scripts/harness_preflight.py +72 -382
- package/harness/bundles/java/codebuddy/scripts/harness_profile.py +742 -0
- package/harness/bundles/java/codebuddy/scripts/harness_service.py +99 -2
- package/harness/bundles/java/codebuddy/scripts/harness_state.py +179 -0
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- 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-archive/reference.md +2 -8
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-plan/SKILL.md +2 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +5 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/codex/harness-run/checklist.md +3 -1
- package/harness/bundles/java/codex/harness-run/reference.md +6 -0
- package/harness/bundles/java/codex/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/codex/harness-submit/checklist.md +30 -6
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +5 -5
- package/harness/bundles/java/codex/harness-test/checklist.md +3 -1
- package/harness/bundles/java/codex/harness-test/pitfalls.md +16 -0
- package/harness/bundles/java/codex/harness-test/reference.md +2 -0
- package/harness/bundles/java/codex/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/java/codex/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/java/codex/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/java/codex/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/java/codex/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/java/codex/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/java/codex/scripts/harness_archive.py +31 -14
- package/harness/bundles/java/codex/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/java/codex/scripts/harness_deploy.py +179 -4
- package/harness/bundles/java/codex/scripts/harness_ledger.py +269 -3
- package/harness/bundles/java/codex/scripts/harness_preflight.py +72 -382
- package/harness/bundles/java/codex/scripts/harness_profile.py +742 -0
- package/harness/bundles/java/codex/scripts/harness_service.py +99 -2
- package/harness/bundles/java/codex/scripts/harness_state.py +179 -0
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- 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-archive/reference.md +2 -8
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +2 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +474 -122
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +2 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +5 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +4 -4
- package/harness/bundles/java/cursor/harness-run/checklist.md +3 -1
- package/harness/bundles/java/cursor/harness-run/reference.md +6 -0
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +3 -3
- package/harness/bundles/java/cursor/harness-submit/checklist.md +30 -6
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +5 -5
- package/harness/bundles/java/cursor/harness-test/checklist.md +3 -1
- package/harness/bundles/java/cursor/harness-test/pitfalls.md +16 -0
- package/harness/bundles/java/cursor/harness-test/reference.md +2 -0
- package/harness/bundles/java/cursor/harness-test/scripts/runtime-helpers.mjs +216 -0
- package/harness/bundles/java/cursor/protocols/archive-report-protocol.md +1 -1
- package/harness/bundles/java/cursor/protocols/ledger-protocol.md +55 -2
- package/harness/bundles/java/cursor/protocols/report-pipeline-protocol.md +1 -8
- package/harness/bundles/java/cursor/protocols/sensitive-info-protocol.md +13 -0
- package/harness/bundles/java/cursor/protocols/state-layout-protocol.md +24 -0
- package/harness/bundles/java/cursor/scripts/harness_archive.py +31 -14
- package/harness/bundles/java/cursor/scripts/harness_check_gate.py +111 -0
- package/harness/bundles/java/cursor/scripts/harness_deploy.py +179 -4
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +269 -3
- package/harness/bundles/java/cursor/scripts/harness_preflight.py +72 -382
- package/harness/bundles/java/cursor/scripts/harness_profile.py +742 -0
- package/harness/bundles/java/cursor/scripts/harness_service.py +99 -2
- package/harness/bundles/java/cursor/scripts/harness_state.py +179 -0
- package/harness/manifests/general/claude-code.json +44 -28
- package/harness/manifests/general/codebuddy.json +44 -28
- package/harness/manifests/general/codex.json +44 -28
- package/harness/manifests/general/cursor.json +44 -28
- package/harness/manifests/java/claude-code.json +48 -32
- package/harness/manifests/java/codebuddy.json +48 -32
- package/harness/manifests/java/codex.json +48 -32
- package/harness/manifests/java/cursor.json +48 -32
- package/hunter-workflow-family.json +2 -2
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ name: harness-knowledge-query
|
|
|
3
3
|
description: 根据新需求、设计任务、代码修改请求或问题排查,在规划和编码前查询 .harness/knowledge
|
|
4
4
|
历史上下文。适用场景:query knowledge、查找历史需求、根据归档理解需求、继续之前类似开发、生成需求上下文包。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
7
7
|
# harness-knowledge-query
|
|
8
8
|
|
|
9
9
|
根据用户的新需求或排查问题,从项目本地 `.harness/knowledge` 中检索历史需求、决策、实现、风险和测试证据,并生成 AI 可读的 context pack。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: harness-package
|
|
3
3
|
description: 增量模块打包:拉取最新→编译验证→mvn package→汇总 jar/war。使用场景:打包、package、发版准备
|
|
4
4
|
---
|
|
5
|
-
<!-- generated by harness_deploy.py; core=
|
|
5
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
6
6
|
# harness-package — 增量模块打包(Java overlay)
|
|
7
7
|
|
|
8
8
|
## Purpose
|
|
@@ -36,9 +36,9 @@ description: 增量模块打包:拉取最新→编译验证→mvn package→
|
|
|
36
36
|
|
|
37
37
|
## Workflow
|
|
38
38
|
|
|
39
|
-
1. 读 ledger + build-profile 的 `
|
|
39
|
+
1. 读 ledger + build-profile 的 `commands.package`(v2,按 profile key resolve)
|
|
40
40
|
2. 识别变更模块(git diff + pom 结构)
|
|
41
|
-
3.
|
|
41
|
+
3. **单次** Maven package lifecycle(spec §3.3 去重,不预先 compile/test):full test 可复用(`can-reuse unitTestFull=true`)→ 按 `commands.package` resolve 执行一次 skip-tests package;不可复用 → 按 `commands.package` resolve 执行一次含测试 package
|
|
42
42
|
4. 写打包报告 + append 事件
|
|
43
43
|
|
|
44
44
|
## P0 执行可信度规则
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: harness-plan
|
|
3
3
|
description: 将需求转化为设计文档+实施计划+完整测试场景表,必须在编码前完成。使用场景:需求分析、feature plan、技术方案设计、实现方案规划
|
|
4
4
|
---
|
|
5
|
-
<!-- generated by harness_deploy.py; core=
|
|
5
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
6
6
|
# harness-plan — 需求规划
|
|
7
7
|
|
|
8
8
|
## Purpose
|
|
@@ -81,6 +81,7 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
|
|
|
81
81
|
| 阶段 8 | spec/plan/detail/scenarios/worktree.json/logs/events 缺一不可 → ❌FAIL |
|
|
82
82
|
| Plan 结束 | **禁止**询问执行模式;只提示 `/harness-run` |
|
|
83
83
|
| 知识查询 | 0.5 失败不得假装已读历史 |
|
|
84
|
+
| state snapshot | 读取 `state-snapshot.json`(`harness_state.py` / state-layout-protocol §state-snapshot.json)了解 project/worktree root、HEAD/base、profile/rules/map/knowledge 指纹;失效由脚本刷新,**不得仅凭缓存跳过代码探索或验证门禁**(design §3.6) |
|
|
84
85
|
| 协议 | sensitive-info / evidence-based-reporting / state-layout |
|
|
85
86
|
|
|
86
87
|
产出物表、frontmatter、legacy 兼容、结束输出模板 → `reference.md`
|
|
@@ -3,7 +3,7 @@ name: harness-review
|
|
|
3
3
|
description: 6维度代码审查(架构/安全/规范/兼容/测试/性能),对照项目规则(见
|
|
4
4
|
.harness/context-index.json)和测试场景表,在隔离上下文运行。使用场景:代码审查、提交前检查、合并评审
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
7
7
|
# harness-review — 代码审查
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -125,6 +125,10 @@ review 结果默认只作参考,不阻塞 submit/archive;报告措辞遵循
|
|
|
125
125
|
|
|
126
126
|
git diff/log 命令通过 `powershell.exe -Command "..."` 执行;review-report 中如发现明文 token/密码/密钥,必须列入 RED 问题并在报告中以 `<TOKEN_REDACTED>` 等占位符引用;RED/YELLOW/OK 结论必须基于实际 diff 内容,不得凭印象判断。代码探索必须优先使用 CodeGraph MCP 工具(`mcp__codegraph__codegraph_explore`),不允许通过普通 Bash 调 codegraph 命令(已列入 `disallowed-tools`);MCP 不可用时降级为 Grep/Glob + Read,并在执行日志记录降级原因。遵循 `../protocols/powershell-protocol.md` / `sensitive-info-protocol.md` / `evidence-based-reporting-protocol.md`。
|
|
127
127
|
|
|
128
|
+
### 五、state snapshot 与源码重验
|
|
129
|
+
|
|
130
|
+
review 读取 `state-snapshot.json`(`harness_state.py` / state-layout-protocol §state-snapshot.json)的 code/diff 段确定审查范围;snapshot 失效或代码段变化时**必须重新读取实际变更源码**,不得仅凭缓存快照跳过源码审查(design §3.6)。
|
|
131
|
+
|
|
128
132
|
## 交互白名单
|
|
129
133
|
|
|
130
134
|
**无** AskUserQuestion(审查全自动)。委派失败 → 主会话审查 + `decision` 事件。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: harness-run
|
|
3
3
|
description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编译验证),逐变更簇实现计划中的任务。使用场景:开始编码、实现功能、写代码、TDD 编码
|
|
4
4
|
---
|
|
5
|
-
<!-- generated by harness_deploy.py; core=
|
|
5
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
6
6
|
# harness-run — 需求编码
|
|
7
7
|
|
|
8
8
|
## Purpose
|
|
@@ -64,9 +64,9 @@ description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编
|
|
|
64
64
|
|
|
65
65
|
### Java 构建验证(Maven)
|
|
66
66
|
|
|
67
|
-
- 所有 `mvn`/`git` 经 `powershell.exe -NoProfile -Command`;命令读 `.harness/config/build-profile.json` 的 `
|
|
68
|
-
- 增量编译:`
|
|
69
|
-
- 变更簇 TDD
|
|
67
|
+
- 所有 `mvn`/`git` 经 `powershell.exe -NoProfile -Command`;命令读 `.harness/config/build-profile.json` 的 `commands`(v2,按 profile key resolve;**禁止 hardcode 模块名/端口**)
|
|
68
|
+
- 增量编译:`commands.compile`(典型 `mvn compile -pl <module> -o -q`)
|
|
69
|
+
- 变更簇 TDD:多测试类合并一次按 `commands.unitTest` resolve(典型 `mvn test -pl <module> -Dtest=A,B,C -o`);每簇最多一次 RED + 一次 GREEN Maven
|
|
70
70
|
- **轻量 run**:默认只 compile;全量 `mvn test` 仅当改了 mapper/sql/权限/controller/公共模块或用户要求 full-run-validation
|
|
71
71
|
- **install -am**:仅 worktree 首建或上游模块文件变化时(见 ledger-protocol);非每次 run 强制
|
|
72
72
|
- worktree 中确认 `.mvn/maven.config` 等构建配置存在;缺失时从主目录复制
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
- [ ] **读取任务状态**:`.harness/changes/<change>/run-task-status.md`(如存在)— 恢复上次运行状态
|
|
31
31
|
- [ ] 确认 `项目规则(见 .harness/context-index.json)/` 规则已加载
|
|
32
32
|
- [ ] 检查构建配置完整性(worktree 中确认 `.mvn/maven.config`、`settings.xml` 等存在)
|
|
33
|
+
- [ ] 读取 `.mvn/maven.config`,确认命令没有重复或覆盖项目已有的 `-s` / `-o` / 仓库设置
|
|
34
|
+
- [ ] 离线依赖缺失时仅在项目规则允许联网的前提下执行至多一次非离线 `-nsu` 恢复;禁止离线/联网循环重试
|
|
33
35
|
- [ ] 依赖模块预安装(worktree 中检查上游模块是否已 `mvn install`)
|
|
34
36
|
- [ ] 代码探索优先用 `codegraph_explore`,仅在返回不完整时补充 Read
|
|
35
37
|
- [ ] append `phase.start`(`note` 含测试基础设施 CHECKING 直至探测完成)
|
|
@@ -45,7 +47,7 @@
|
|
|
45
47
|
- [ ] 探测 1:`src/test/java` 目录是否存在
|
|
46
48
|
- [ ] 探测 2:`pom.xml` 是否包含 `spring-boot-starter-test` / `junit` / `mockito` 依赖
|
|
47
49
|
- [ ] 探测 3:是否存在已有测试文件(`*Test.java` 或 `*Tests.java`)
|
|
48
|
-
- [ ] 探测 4
|
|
50
|
+
- [ ] 探测 4:目标模块测试基础设施是否可用(`mvn test-compile -pl <module> -o -q` 验证测试可编译,或测试枚举/秒级 smoke;**禁止完整模块测试**,spec §3.3)
|
|
49
51
|
- [ ] 四项证据收集完毕 → 写结论:✅ 测试基础设施可用 / 🟡 测试基础设施部分可用 / ❌ 测试基础设施不可用
|
|
50
52
|
- [ ] 如果 ❌ 不可用 → 记录 TDD 降级原因(必须引用具体证据,如"模块 X 无 src/test/java 目录")
|
|
51
53
|
|
|
@@ -97,6 +97,12 @@ powershell.exe -NoProfile -Command "Test-Path '.claude/worktrees/<change-name>/.
|
|
|
97
97
|
13. **依赖模块预安装**:如果在 worktree 中执行,检查上游依赖模块是否已 `mvn install` 到本地仓库。缺失时先执行 `powershell.exe -Command "mvn install -pl <upstream-modules> -am -DskipTests -nsu"`
|
|
98
98
|
14. **代码探索优先用 codegraph_explore**:一次调用可获取多个相关符号的源码,替代逐个 Read 文件。违反 `项目 codegraph 规则` 规则逐个 Read 会浪费 3-5 分钟。仅在 codegraph 返回结果不完整时补充 Read
|
|
99
99
|
|
|
100
|
+
### Maven 项目配置与重试预算
|
|
101
|
+
|
|
102
|
+
- 运行 Maven 前先读取项目已有的 `.mvn/maven.config`;其中的 `-s`、`-o`、镜像和仓库设置视为项目契约,不在命令行重复追加或覆盖。
|
|
103
|
+
- 若项目配置已启用离线模式,依赖缺失只允许一次有明确原因的恢复尝试:仅在项目规则允许联网时临时执行非离线的 `-nsu` 命令;随后继续遵循项目配置,不得在离线/联网命令之间循环试错。
|
|
104
|
+
- 同一失败命令不得无分析地重复执行。先按“配置/依赖缺失、编译、测试、业务断言”分类,再决定修复或停止;每个变更簇仍遵守一次 RED、一次 GREEN 的 Maven 预算。
|
|
105
|
+
|
|
100
106
|
### 步骤 0.1:执行模式(默认 Inline)
|
|
101
107
|
|
|
102
108
|
默认 **Inline Execution**;仅 `--subagent` 强制 Subagent-Driven。**不询问**任务数/模块数(P1-5)。
|
|
@@ -3,7 +3,7 @@ name: harness-submit
|
|
|
3
3
|
description: 最终提交封装:验证→中文 commit→提交/推送;worktree 模式含 --no-ff
|
|
4
4
|
合并回主分支。使用场景:提交代码、commit、push、合并分支、merge to main、完成开发
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
7
7
|
# harness-submit — 最终提交(含 worktree 合并)
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -55,7 +55,7 @@ description: 最终提交封装:验证→中文 commit→提交/推送;workt
|
|
|
55
55
|
|
|
56
56
|
0. **启动准备** — 确定变更名;读 ledger + 计算 diffHash + post-test 7 类分类;append `phase.start`
|
|
57
57
|
1. **合并最新代码** — 主目录:`stash` → `pull --rebase` → `stash pop`;**worktree:N/A**(远端同步在合并段主分支完成)
|
|
58
|
-
2. **最终验证** — ledger
|
|
58
|
+
2. **最终验证** — ledger 复用优先;**提交前最终门禁只调 `can-reuse`**(删除与 coverage 冲突的二次全量门禁):`harness_ledger.py can-reuse --verification unitTestFull --scope module --project . --profile-input unitTestFull --command <resolved commands.unitTestFull.command>`。`--command` **按 profile key resolve**:读 `build-profile.json` 的 `commands.unitTestFull.command`(v2),或 `harness_profile.py resolve --project . --key unitTestFull --json` 取 resolved command,**不复制示例模块名**(文档示例只展示 key)。`--profile-input unitTestFull` 从 `verificationInputs.unitTestFull`(v2 由 `commands.unitTestFull.inputs` 派生)展开依赖闭包,**禁止用仅含 staged 文件的 `--files` 快捷方式**冒充全量闭包。`reuse=true` → 不再执行二次全量测试;仅 `reuse=false` 时执行**同一 resolved verification**(profile `unitTestFull` 命令),成功后用同一文件集、command、`scope=module` 写回 ledger `unitTestFull` 项。增量 `unitTest` 永远不能冒充 `unitTestFull` 门禁。
|
|
59
59
|
3. **.gitignore + 暂存** ⚠️ — 检查 `.harness/` 在 `.gitignore`;**禁止 `git add -A`**
|
|
60
60
|
4. **提交方式** — 主目录:AskUserQuestion 三选项(commit+push / 仅本地 / 取消);**worktree:固定仅本地 commit**
|
|
61
61
|
5. **commit-message.txt** ⚠️ — 展示 staged、diff stat、完整中文 message;用户确认
|
|
@@ -80,7 +80,7 @@ M8. **ledger + 收尾** — 写入 `mergeFinalHash`;append `phase.end`;提
|
|
|
80
80
|
|
|
81
81
|
通用 `harness-submit` 的最终门禁已统一为 `unitTestFull`(见通用 SKILL.md 步骤 2 / checklist 步骤 2)。Java overlay **不重复定义门禁规则**,只补两点:
|
|
82
82
|
|
|
83
|
-
- **Maven 命令来源**:`--command` 取 `build-profile.json` 的 `
|
|
83
|
+
- **Maven 命令来源**:`--command` 按 profile key resolve 取 `build-profile.json` 的 `commands.unitTestFull.command`(或 `harness_profile.py resolve --key unitTestFull`),典型 `mvn test -pl <module> -o`。`mvn test` 不带 `-Dtest=` 即模块级全量 → 记 `scope=module` 可复用;带 `-Dtest=<类>` 是增量 `unitTest`,**不能**冒充 `unitTestFull`。
|
|
84
84
|
- **Java 依赖闭包**:`verificationInputs.unitTestFull` 必须覆盖完整编译+测试依赖闭包,建议 `["pom.xml", "<module>/pom.xml", "<module>/src/main/**", "<module>/src/test/**"]`,避免只哈希 staged 文件而漏掉 pom 依赖变化导致误复用。`harness_preflight.py detect` 对单模块项目写入根级默认 `["pom.xml", "src/main/**", "src/test/**"]`,多模块项目需手工改为 module 专属 glob。
|
|
85
85
|
- **可选 package 前置**:若团队发版前需 jar 验证,在 submit 后接 `/harness-package`(默认时序 submit → package → archive)
|
|
86
86
|
## P0 执行可信度规则
|
|
@@ -89,21 +89,21 @@ powershell.exe -NoProfile -Command "<项目测试命令>"
|
|
|
89
89
|
|
|
90
90
|
**重跑后必须把结果写回 ledger** 的 `compile`/`unitTest` 项,并更新 `diffHash`/`currentHead`。
|
|
91
91
|
|
|
92
|
-
**提交前最终门禁**(步骤 2 末尾,commit 前强制,`unitTestFull`
|
|
92
|
+
**提交前最终门禁**(步骤 2 末尾,commit 前强制,`unitTestFull` 模块级全量)——**只调 `can-reuse`,删除二次全量门禁**:
|
|
93
93
|
|
|
94
94
|
```powershell
|
|
95
95
|
python <skills-root>/scripts/harness_ledger.py can-reuse `
|
|
96
96
|
--change-dir ".harness/changes/<change-name>" `
|
|
97
97
|
--verification unitTestFull --scope module `
|
|
98
98
|
--project . --profile-input unitTestFull `
|
|
99
|
-
--command "<
|
|
99
|
+
--command "<resolved commands.unitTestFull.command>" --json
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
- `--profile
|
|
103
|
-
- `--
|
|
102
|
+
- `--command` **按 profile key resolve**:读 `build-profile.json` 的 `commands.unitTestFull.command`(v2),或 `python <skills-root>/scripts/harness_profile.py resolve --project . --key unitTestFull --json` 取 resolved command。**禁止原样复制示例模块名**(命令按 profile key resolve,文档示例只展示 key)。
|
|
103
|
+
- `--profile-input unitTestFull` 从 `build-profile.json` 的 `verificationInputs.unitTestFull`(v2 由 `commands.unitTestFull.inputs` 派生)展开**依赖闭包**文件集,**禁止用仅含 staged 业务文件的 `--files` 快捷方式**冒充全量闭包。
|
|
104
104
|
- 增量 `unitTest`(scope=测试类)永远不能冒充 `unitTestFull` 门禁;ledger 只有 `unitTest` 时返回 `insufficient-evidence`。
|
|
105
|
-
- `reuse=
|
|
106
|
-
- profile 缺 `verificationInputs.unitTestFull` / glob 无匹配 / 结果为空 → 返回 `insufficient-evidence`(exit 0),仍须执行全量测试但**不允许缓存复用**,直到 profile 正确配置。
|
|
105
|
+
- `reuse=true` → **不再执行二次全量测试**(删除与 coverage 冲突的二次门禁,spec §3.3);仅 `reuse=false`(can-reuse 明确失败)时执行**同一 resolved verification**(profile `unitTestFull` 命令,模块级全量单元测试),成功后用**同一文件集、command、`scope=module`** 写回 ledger 的 `unitTestFull` 项,再继续步骤 3。
|
|
106
|
+
- profile 缺 `commands.unitTestFull` / `verificationInputs.unitTestFull` / glob 无匹配 / 结果为空 → 返回 `insufficient-evidence`(exit 0),仍须执行全量测试但**不允许缓存复用**,直到 profile 正确配置。
|
|
107
107
|
|
|
108
108
|
**编译/测试成功必须有明确证据**:
|
|
109
109
|
- 构建命令输出必须包含构建成功证据(如 `BUILD SUCCESS` / `Finished` / exit code 0)
|
|
@@ -337,6 +337,21 @@ powershell.exe -Command "git -C '<项目路径>' pull --rebase"
|
|
|
337
337
|
|
|
338
338
|
pull 输出非 `Already up to date.` → 引入他人提交 → M4 必须重跑验证。
|
|
339
339
|
|
|
340
|
+
**CRLF 预检**(pull 后强制):旧 working copy 的 `.gitattributes eol=lf` 文件可能是 CRLF(.gitattributes 后加未重新检出),曾导致 `core_content_hash` 跨工作树不一致 → sync 产生 dirty → M5 失败重跑。检测并修复:
|
|
341
|
+
|
|
342
|
+
```powershell
|
|
343
|
+
# 1. renormalize 暴露 CRLF 漂移(仅规范化行尾,不改内容语义)
|
|
344
|
+
powershell.exe -Command "git -C '<项目路径>' add --renormalize ."
|
|
345
|
+
# 2. 若 git status --porcelain 非空 → working copy 存在 CRLF 漂移
|
|
346
|
+
powershell.exe -Command "git -C '<项目路径>' status --porcelain"
|
|
347
|
+
# 3. 有漂移 → 弃 staging + 强制 LF 重检(worktree 合并段 M2 在主仓库 main,应 clean,安全)
|
|
348
|
+
powershell.exe -Command "git -C '<项目路径>' reset -q; git -C '<项目路径>' checkout -- ."
|
|
349
|
+
# 4. 重新 renormalize 确认 clean(git status --porcelain 应空)
|
|
350
|
+
powershell.exe -Command "git -C '<项目路径>' add --renormalize .; git status --porcelain"
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
> cluster 1 的 `core_content_hash` 改用 git blob sha 后,CRLF 不再影响 core hash,但 working copy CRLF 仍可能影响 workflow-data 包内容 hash,预检仍有价值。
|
|
354
|
+
|
|
340
355
|
### 步骤 M3:合并 worktree 分支
|
|
341
356
|
|
|
342
357
|
```powershell
|
|
@@ -365,6 +380,15 @@ powershell.exe -Command "git -C '<项目路径>' diff --name-only --diff-filter=
|
|
|
365
380
|
|
|
366
381
|
重跑后写回 ledger 的 `compile`/`unitTest`,更新 `diffHash`/`currentHead`。
|
|
367
382
|
|
|
383
|
+
**写 check-ok marker**(npm run check exit 0 后强制):让 pre-push hook 跳过重复 check。三重校验(marker ts<10min + command + commit tree),任一不满足照跑。marker 写入时记录 `git write-tree`,因此验证后创建 commit 不会仅因 HEAD 前移而使缓存失效。
|
|
384
|
+
|
|
385
|
+
```powershell
|
|
386
|
+
# npm run check exit 0 后立即写 marker(M5 或 REUSED 后均可)
|
|
387
|
+
powershell.exe -Command "python harness/scripts/harness_check_gate.py --write"
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
> marker 写入 `.harness/check-ok.marker`(gitignored,本地)。push 时 pre-push hook 比较 `HEAD^{tree}` 与 marker 的 `treeHash`,再校验 ts<10min + command;commit tree 未变化即可跳过,任何内容变化都照跑(安全默认)。
|
|
391
|
+
|
|
368
392
|
### 步骤 M6:push 主分支
|
|
369
393
|
|
|
370
394
|
```powershell
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: harness-sync
|
|
3
3
|
description: 检查并更新项目AI元数据(CodeGraph索引、harness-codebase-map分析、CLAUDE.md、AGENTS.md、.harness/完整性),确保Claude对代码库的理解与最新代码一致。当用户说'同步/更新索引/刷新元数据/检查一致性'时使用
|
|
4
4
|
---
|
|
5
|
-
<!-- generated by harness_deploy.py; core=
|
|
5
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
6
6
|
# harness-sync — 元数据同步
|
|
7
7
|
|
|
8
8
|
## Purpose
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: harness-test
|
|
3
3
|
description: 测试执行:读取场景表,执行单元测试+API接口测试+数据兼容验证,输出测试报告。当用户说'跑测试/验证/跑用例/接口测试/单元测试'时使用
|
|
4
4
|
---
|
|
5
|
-
<!-- generated by harness_deploy.py; core=
|
|
5
|
+
<!-- generated by harness_deploy.py; core=959b22fdc1e7af33; overlay=java; agent=codebuddy; do not edit -->
|
|
6
6
|
# harness-test — 测试执行
|
|
7
7
|
|
|
8
8
|
## Purpose
|
|
@@ -78,9 +78,9 @@ description: 测试执行:读取场景表,执行单元测试+API接口测试
|
|
|
78
78
|
### Java 测试环境补充
|
|
79
79
|
|
|
80
80
|
- **preflight 0.1**:写入 `runtime/preflight.json` 的 `executorPath`/`mvnVersion` 等;Maven 可用性 `mvn -version` exit 0
|
|
81
|
-
- **编译门禁**:测试前按 `build-profile.json` 的 `
|
|
82
|
-
- **条件 install**:worktree 首建或上游模块变更时按 profile 执行 `
|
|
83
|
-
- **单元测试**:可复用 ledger unitTest 则跳过;否则 `
|
|
81
|
+
- **编译门禁**:测试前按 `build-profile.json` 的 `commands.compile`(v2,profile key resolve);输出须含 `BUILD SUCCESS` 或 exit 0 证据
|
|
82
|
+
- **条件 install**:worktree 首建或上游模块变更时按 profile 执行 `commands.install`(非每次强制 `-am`)
|
|
83
|
+
- **单元测试**:可复用 ledger unitTest 则跳过;否则 `commands.unitTest`(典型 `mvn test -pl <module>`);执行模块全量 `commands.unitTestFull` 成功 → 记 `unitTestFull`(scope=module,供 submit 复用)
|
|
84
84
|
- **服务启动**:`build-profile.json` 的 `serviceStartTemplate`(典型 `spring-boot:run` + profile);**禁止 hardcode 端口/模块路径**
|
|
85
85
|
- **服务指纹输入**(Task 3 §5.1):`serviceStart.inputFiles` 必须列出 module 源 glob(如 `["<module>/pom.xml", "<module>/src/main/**/*.java", "<module>/src/main/resources/**"]`);`harness_service.py ensure` 取 CLI `--files` ∪ `inputFiles` 计算 `moduleInputsHash`。**空输入被拒绝**,不得生成可复用空指纹。源码/command/profile/overlayPath 任一变化即 restart
|
|
86
86
|
- **runtime overlay**:`-Dspring.config.additional-location=file:<ascii-abs-path>/application-harness-test.yml`;禁止默认 Edit tracked `application*.yml`
|
|
@@ -111,7 +111,7 @@ description: 测试执行:读取场景表,执行单元测试+API接口测试
|
|
|
111
111
|
|
|
112
112
|
### 四、单元测试复用 + 写入 ledger
|
|
113
113
|
|
|
114
|
-
Phase 1 前先读 `.harness/changes/<change-name>/evidence/verification-ledger.json`:run 的 unitTest 满足(diffHash 一致 + module/profile 一致 + scope 一致或更严格 + run 后无行为性修改 + run
|
|
114
|
+
Phase 1 前先读 `.harness/changes/<change-name>/evidence/verification-ledger.json`:run 的 unitTest 满足(diffHash 一致 + module/profile 一致 + scope 一致或更严格 + run 后无行为性修改 + run 跑了全量测试)则复用,否则按 **profile key resolve** 执行测试命令(`python <skills-root>/scripts/harness_profile.py resolve --project . --key unitTest|unitTestFull --json`,**不复制示例 `-pl` 命令**)。Phase 1/2 完成后必须写回 ledger:执行增量测试类 → 记 `unitTest`(scope=incremental);执行 profile 模块全量命令 → 记 `unitTestFull`(scope=module,可供 submit 复用);接口测试 → 记 `apiTest`。详见 `checklist.md`「单元测试复用」、`../protocols/ledger-protocol.md`。
|
|
115
115
|
|
|
116
116
|
### 五、命令与请求超时治理
|
|
117
117
|
|
|
@@ -37,6 +37,8 @@ description: harness-test 的 Phase 0 环境准备 + Playwright 探测 + 关门
|
|
|
37
37
|
- [ ] 检查 PowerShell 基础命令:`powershell.exe -NoProfile -Command "$PSVersionTable.PSVersion"` 返回 exitCode=0
|
|
38
38
|
- [ ] 检查 Node 绝对路径:`powershell.exe -NoProfile -Command "& 'C:\nvm4w\nodejs\node.exe' --version"` 返回 exitCode=0
|
|
39
39
|
- [ ] 检查 Maven 可用性:`powershell.exe -NoProfile -Command "mvn -version"` 返回 exitCode=0
|
|
40
|
+
- [ ] 读取 `.mvn/maven.config`,Maven 命令不重复或覆盖已有 `-s` / `-o` / 仓库设置
|
|
41
|
+
- [ ] 离线依赖缺失时仅在项目规则允许联网时执行至多一次非离线 `-nsu` 恢复;失败后停止,禁止切换参数反复重试
|
|
40
42
|
- [ ] 检查安全分类器:上述任一命令是否返回"安全分类器暂时不可用" / Auto mode 拦截 → **不应出现**
|
|
41
43
|
- [ ] 将通过的 `nodeAbsolutePath` / `powershellVersion` / `mvnVersion` 写入 `.harness/changes/<change-name>/runtime/preflight.json`
|
|
42
44
|
- [ ] **任一情况触发硬停**:原文输出"❌ 命令执行模式不可用:PowerShell/Node runner 无法稳定执行...",**不得继续编译/启动服务/生成 runner,不得长时间等待,不得盲目降级到 Playwright MCP**
|
|
@@ -314,4 +316,4 @@ powershell.exe -Command "Copy-Item '<main-dir>/<module>/src/main/resources/appli
|
|
|
314
316
|
- 请求执行器必须在报告中明确记录(四种执行器,含降级原因)
|
|
315
317
|
- 请求耗时统计必须包含在报告中
|
|
316
318
|
- 服务由 AI 启动的情况,测试结束默认 Stop-Process;**即使测试失败也要进入 finally 清理**
|
|
317
|
-
- final-summary 的 apiTest 状态必须用 OK/PARTIAL/BLOCKED/NOT_RUN/FAIL(不得把 PARTIAL 写成 NOT_RUN)
|
|
319
|
+
- final-summary 的 apiTest 状态必须用 OK/PARTIAL/BLOCKED/NOT_RUN/FAIL(不得把 PARTIAL 写成 NOT_RUN)
|
|
@@ -258,3 +258,19 @@ $cred = $resp.data.accessToken
|
|
|
258
258
|
**正确做法**:用 `git diff --binary` 生成 patch 并计算 SHA-256,ledger 只认 `sha256:<hash>` 格式。diffHash 不一致时必须重跑相关测试。
|
|
259
259
|
|
|
260
260
|
> diffHash/ledger 复用规则遵循 `../protocols/ledger-protocol.md`;结果证据要求遵循 `../protocols/evidence-based-reporting-protocol.md`。
|
|
261
|
+
|
|
262
|
+
## BOM-safe JSON / identifier sanitizer / 凭据扫描 (runtime-helpers.mjs)
|
|
263
|
+
|
|
264
|
+
> 变更簇 5 (spec §3.4):Node runtime helper 集中处理 PS5.1 BOM、非法测试标识符、凭据边界三类返工。源码 `scripts/runtime-helpers.mjs`,测试 `scripts/tests/runtime-helpers.test.mjs`(`node --test`)。
|
|
265
|
+
|
|
266
|
+
| 函数 | 用途 | 规避的坑 |
|
|
267
|
+
|------|------|----------|
|
|
268
|
+
| `readJsonUtf8BomSafe(path)` | 读 credential-cache.json / api-test-results.json,容忍 U+FEFF BOM | PS5.1 `Out-File -Encoding utf8` 写入 BOM 导致 `JSON.parse` 失败 |
|
|
269
|
+
| `writeJsonUtf8NoBom(path, value)` | 原子写 (temp+rename),UTF-8 no BOM,LF,2-space 缩进 | 结果文件被 BOM/换行符污染破坏字节稳定;半写入文件被并发读到 |
|
|
270
|
+
| `sanitizeTestIdentifier({name, pattern, maxLength, prefix})` | change-name → 稳定标识(清洗非法字符 + 超长截断 + 原文名短 hash 防碰撞) | 中文/连字符/超长 change-name 生成非法 identifier 触发服务端 400 |
|
|
271
|
+
| `validateRunnerPayload(payload, {identifierPattern})` | Runner 生成前本地校验 payload schema/必填/identifier/重复 id,返回结构化错误码 | 测试脚本错误(缺字段/非法 id)直到请求服务后才暴露,返工成本高 |
|
|
272
|
+
| `findCredentialValues(text)` | 扫描 profile/Markdown/docs 中的凭据明文值(password/token/secret/Authorization/jdbc password),占位符 `<*_REDACTED>` 与 env 引用 `${ENV}`/`$ENV` 不报 | profile/规则文档误含明文凭据被发布 |
|
|
273
|
+
|
|
274
|
+
**Runner 生成前强制**(spec §3.4 point 3):生成 `api-test-runner.mjs` 前用 `validateRunnerPayload` 校验全部场景;`ok=false` → 修复脚本错误,**不得带错请求服务**。场景 id 用 `sanitizeTestIdentifier` 生成(profile v2 `identifier.pattern/maxLength/prefix` 已声明)。
|
|
275
|
+
|
|
276
|
+
**凭据边界**(spec §3.4 point 4):credential 配置只含 env key(如 `${TEST_TOKEN}`)、cache path、角色,不含值。发布前用 `findCredentialValues` 扫 profile/规则/Markdown,命中即 ❌FAIL。详见 `../protocols/sensitive-info-protocol.md` §6。
|
|
@@ -6,6 +6,8 @@ description: harness-test 的 API 测试执行细节、批量 runner、token 缓
|
|
|
6
6
|
|
|
7
7
|
## 命令执行模式 preflight(0.0y)
|
|
8
8
|
|
|
9
|
+
执行 Maven 前必须读取 `.mvn/maven.config`。项目已声明的 `-s`、`-o`、镜像和仓库设置不得被测试命令重复追加或覆盖。离线依赖缺失时,只有在项目规则允许联网的情况下,才可临时执行至多一次非离线 `-nsu` 恢复;失败后停止并报告缺失依赖,不得在多套 Maven 参数间反复试跑。
|
|
10
|
+
|
|
9
11
|
`/harness-test` 高度依赖 PowerShell 与 Node。在编译/启动服务/生成 runner **之前**
|
|
10
12
|
必须执行 4 项执行模式检查:
|
|
11
13
|
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// runtime-helpers.mjs — BOM-safe JSON I/O + test-identifier sanitizer + runner payload validation + credential scan.
|
|
3
|
+
// 变更簇 5 (spec §3.4): BOM-safe Runner, identifier sanitizer, 凭据边界.
|
|
4
|
+
//
|
|
5
|
+
// 设计目标:
|
|
6
|
+
// - readJsonUtf8BomSafe: 容忍 UTF-8 BOM (U+FEFF), credential-cache.json 等文件可能被 PS5.1 写入 BOM
|
|
7
|
+
// - writeJsonUtf8NoBom: 原子写 (temp+rename), UTF-8 no BOM, LF — 结果/报告文件字节稳定
|
|
8
|
+
// - sanitizeTestIdentifier: 按 pattern/maxLength/prefix 生成稳定标识; 超长截断 + 原文名短 hash 防碰撞
|
|
9
|
+
// - validateRunnerPayload: Runner 生成前本地校验 payload schema/必填/identifier, 测试脚本错误不得请求服务后才发现
|
|
10
|
+
// - findCredentialValues: 扫描 profile/Markdown/docs 中的凭据明文值 (sensitive-info-protocol §1)
|
|
11
|
+
//
|
|
12
|
+
// Node ≥18 ESM, stdlib only. 输出 JSON 内容确定性 (不含 Math.random); 仅临时文件名用 randomBytes.
|
|
13
|
+
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
import crypto from 'node:crypto';
|
|
17
|
+
|
|
18
|
+
export const BOM = 0xfeff;
|
|
19
|
+
export const DEFAULT_IDENTIFIER_PATTERN = '^[A-Za-z][A-Za-z0-9_-]*$';
|
|
20
|
+
export const DEFAULT_IDENTIFIER_MAX_LENGTH = 64;
|
|
21
|
+
const HASH_LEN = 8;
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// BOM-safe JSON I/O
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
/** Strip a single leading UTF-8 BOM (U+FEFF) from text. No-op if absent. */
|
|
28
|
+
export function stripBom(text) {
|
|
29
|
+
return text.codePointAt(0) === BOM ? text.slice(1) : text;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Read a JSON file, tolerating a leading UTF-8 BOM. Throws on invalid JSON. */
|
|
33
|
+
export function readJsonUtf8BomSafe(filePath) {
|
|
34
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
35
|
+
return JSON.parse(stripBom(raw));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Atomically write JSON as UTF-8 (no BOM), LF, 2-space indent, trailing newline.
|
|
39
|
+
* Writes to a temp file then renames — readers never see a half-written file. */
|
|
40
|
+
export function writeJsonUtf8NoBom(filePath, value) {
|
|
41
|
+
const json = JSON.stringify(value, null, 2) + '\n';
|
|
42
|
+
const dir = path.dirname(filePath);
|
|
43
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
44
|
+
const tmp = `${filePath}.${process.pid}.${crypto.randomBytes(6).toString('hex')}.tmp`;
|
|
45
|
+
fs.writeFileSync(tmp, json, 'utf8');
|
|
46
|
+
try {
|
|
47
|
+
fs.renameSync(tmp, filePath);
|
|
48
|
+
} catch (err) {
|
|
49
|
+
try {
|
|
50
|
+
fs.unlinkSync(tmp);
|
|
51
|
+
} catch {
|
|
52
|
+
/* best-effort cleanup */
|
|
53
|
+
}
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// sanitizeTestIdentifier
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Sanitize a change/test name into a stable identifier matching the default
|
|
64
|
+
* pattern `^[A-Za-z][A-Za-z0-9_-]*$`.
|
|
65
|
+
*
|
|
66
|
+
* - runs of chars outside [A-Za-z0-9_-] → '_'
|
|
67
|
+
* - prepend `prefix_` when prefix given; ensure leading letter (prepend 'T')
|
|
68
|
+
* - if over maxLength: truncate and append a short sha256 hash of the ORIGINAL
|
|
69
|
+
* name, so two near-identical long names that collide after truncation stay
|
|
70
|
+
* distinct (UT-023). Hash is deterministic — no Math.random.
|
|
71
|
+
*
|
|
72
|
+
* @returns {string} identifier matching the default pattern, length ≤ maxLength.
|
|
73
|
+
*/
|
|
74
|
+
export function sanitizeTestIdentifier({
|
|
75
|
+
name,
|
|
76
|
+
pattern = DEFAULT_IDENTIFIER_PATTERN,
|
|
77
|
+
maxLength = DEFAULT_IDENTIFIER_MAX_LENGTH,
|
|
78
|
+
prefix = '',
|
|
79
|
+
}) {
|
|
80
|
+
const raw = String(name ?? '');
|
|
81
|
+
let base = prefix ? `${prefix}_` : '';
|
|
82
|
+
base += raw.replace(/[^A-Za-z0-9_-]+/g, '_');
|
|
83
|
+
// leading letter (pattern ^[A-Za-z]); prepend 'T' if first char is _ or digit
|
|
84
|
+
if (!/^[A-Za-z]/.test(base)) base = `T${base}`;
|
|
85
|
+
if (base.length <= maxLength) return base;
|
|
86
|
+
const hash = crypto.createHash('sha256').update(raw, 'utf8').digest('hex').slice(0, HASH_LEN);
|
|
87
|
+
const reserve = HASH_LEN + 1; // '_' + hash
|
|
88
|
+
const cap = Math.max(1, maxLength - reserve);
|
|
89
|
+
let truncated = base.slice(0, cap).replace(/_+$/, '');
|
|
90
|
+
// if truncation removed the leading letter guarantee, restore it
|
|
91
|
+
if (!/^[A-Za-z]/.test(truncated)) truncated = `T${truncated}`;
|
|
92
|
+
return `${truncated}_${hash}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Compile a pattern safely; returns null if invalid. */
|
|
96
|
+
function safeRegex(pattern) {
|
|
97
|
+
try {
|
|
98
|
+
return new RegExp(`^(?:${pattern})$`);
|
|
99
|
+
} catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** True if id matches pattern. Invalid pattern → false. */
|
|
105
|
+
export function matchesPattern(id, pattern = DEFAULT_IDENTIFIER_PATTERN) {
|
|
106
|
+
const re = safeRegex(pattern);
|
|
107
|
+
return re ? re.test(String(id)) : false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
// validateRunnerPayload — Runner 生成前本地校验
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
const HTTP_METHODS = /^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)$/i;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Validate a runner payload (array of API test scenarios) BEFORE generating or
|
|
118
|
+
* executing the runner. Catches script/schema errors locally so they don't
|
|
119
|
+
* surface only after a service request (spec §3.4 point 3).
|
|
120
|
+
*
|
|
121
|
+
* Scenario required fields: id, method, url. id must match identifierPattern
|
|
122
|
+
* and be unique. method must be a known HTTP method.
|
|
123
|
+
*
|
|
124
|
+
* @returns {{ ok: boolean, errors: Array<{code: string, field: string, message: string}> }}
|
|
125
|
+
*/
|
|
126
|
+
export function validateRunnerPayload(payload, opts = {}) {
|
|
127
|
+
const errors = [];
|
|
128
|
+
const pattern = opts.identifierPattern || DEFAULT_IDENTIFIER_PATTERN;
|
|
129
|
+
const re = safeRegex(pattern);
|
|
130
|
+
|
|
131
|
+
if (!Array.isArray(payload)) {
|
|
132
|
+
return {
|
|
133
|
+
ok: false,
|
|
134
|
+
errors: [{ code: 'PAYLOAD_NOT_ARRAY', field: 'payload', message: 'payload must be an array of scenarios' }],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (payload.length === 0) {
|
|
138
|
+
errors.push({ code: 'PAYLOAD_EMPTY', field: 'payload', message: 'payload has no scenarios' });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const seenIds = new Set();
|
|
142
|
+
payload.forEach((scn, i) => {
|
|
143
|
+
const where = `scenarios[${i}]`;
|
|
144
|
+
if (!scn || typeof scn !== 'object' || Array.isArray(scn)) {
|
|
145
|
+
errors.push({ code: 'SCENARIO_NOT_OBJECT', field: where, message: 'scenario must be an object' });
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
for (const f of ['id', 'method', 'url']) {
|
|
149
|
+
if (scn[f] === undefined || scn[f] === null || scn[f] === '') {
|
|
150
|
+
errors.push({ code: 'MISSING_FIELD', field: `${where}.${f}`, message: `required field '${f}' missing or empty` });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (scn.id !== undefined && scn.id !== null && scn.id !== '') {
|
|
154
|
+
const idStr = String(scn.id);
|
|
155
|
+
if (re && !re.test(idStr)) {
|
|
156
|
+
errors.push({ code: 'INVALID_IDENTIFIER', field: `${where}.id`, message: `id '${idStr}' does not match pattern ${pattern}` });
|
|
157
|
+
}
|
|
158
|
+
if (seenIds.has(idStr)) {
|
|
159
|
+
errors.push({ code: 'DUPLICATE_ID', field: `${where}.id`, message: `duplicate id '${idStr}'` });
|
|
160
|
+
} else {
|
|
161
|
+
seenIds.add(idStr);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (scn.method !== undefined && scn.method !== null && scn.method !== '') {
|
|
165
|
+
if (!HTTP_METHODS.test(String(scn.method))) {
|
|
166
|
+
errors.push({ code: 'INVALID_METHOD', field: `${where}.method`, message: `unknown HTTP method '${scn.method}'` });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return { ok: errors.length === 0, errors };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
// findCredentialValues — 凭据明文扫描 (sensitive-info-protocol §1)
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
// 值占位符或 env 引用 (不会被当作凭据明文): <*_REDACTED> / ${ENV} / $ENV
|
|
179
|
+
// 前缀匹配 ${ENV (无需闭合 }) — value 正则在 } 处停止, 仍应识别为 env 引用。
|
|
180
|
+
const SAFE_VALUE = /<\w+_REDACTED>|\$\{[A-Z0-9_]+|\$[A-Z][A-Z0-9_]*\b/;
|
|
181
|
+
|
|
182
|
+
const CRED_PATTERNS = [
|
|
183
|
+
// password / passwd / pwd = 或 : 后跟值 (字段名可带 JSON/YAML 引号)
|
|
184
|
+
{ code: 'PASSWORD_VALUE', re: /"?password"?\s*[:=]\s*(['"]?)([^'"\s,;)}\n]+)\1/i, group: 2 },
|
|
185
|
+
// token / access_token / api_key / apikey / secret / accessKey / secretAccessKey
|
|
186
|
+
{ code: 'SECRET_VALUE', re: /(?:"?(?:access_token|apikey|api_key|secretAccessKey|accessKey|secret|token)"?)\s*[:=]\s*(['"]?)([^'"\s,;)}\n]+)\1/i, group: 2 },
|
|
187
|
+
// Authorization: Bearer <jwt-ish>
|
|
188
|
+
{ code: 'AUTH_HEADER', re: /Authorization\s*:\s*Bearer\s+([A-Za-z0-9_.-]{10,})/i, group: 1 },
|
|
189
|
+
// jdbc url with password=
|
|
190
|
+
{ code: 'DB_PASSWORD', re: /jdbc:[^\s?]*[?&]password=([^&\s]+)/i, group: 1 },
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Scan text for credential VALUES per sensitive-info-protocol §1.
|
|
195
|
+
* Placeholders (`<TOKEN_REDACTED>`) and env refs (`${DB_PASSWORD}` / `$DB_PASSWORD`)
|
|
196
|
+
* are NOT flagged — credential config may carry env keys, not values (spec §3.4 point 4).
|
|
197
|
+
*
|
|
198
|
+
* @returns {Array<{ line: number, code: string, snippet: string }>}
|
|
199
|
+
*/
|
|
200
|
+
export function findCredentialValues(text) {
|
|
201
|
+
const findings = [];
|
|
202
|
+
const lines = String(text ?? '').split(/\r?\n/);
|
|
203
|
+
lines.forEach((line, idx) => {
|
|
204
|
+
for (const { code, re, group } of CRED_PATTERNS) {
|
|
205
|
+
const m = line.match(re);
|
|
206
|
+
if (!m) continue;
|
|
207
|
+
const value = m[group] || '';
|
|
208
|
+
if (SAFE_VALUE.test(value)) continue; // placeholder / env ref — safe
|
|
209
|
+
// Redact the captured credential value in the snippet so reports/logs
|
|
210
|
+
// never leak it; field name + line number remain for locating the finding.
|
|
211
|
+
const snippet = (value ? line.replace(value, '<REDACTED>') : line).trim().slice(0, 80);
|
|
212
|
+
findings.push({ line: idx + 1, code, snippet });
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
return findings;
|
|
216
|
+
}
|
|
@@ -139,7 +139,7 @@ PowerShell HTML renderer 仅作 legacy fallback。该脚本以 UTF-8 with BOM
|
|
|
139
139
|
|
|
140
140
|
**Python fallback(`harness_archive.py` 内置)**:Node 不可用/超时/exit 非 0/未产出文件时,`harness_archive.py render_final_summary` 自动降级为内置 Python fallback(`render_fallback_html`),渲染含 changeName、finalStatus、`reportPipeline.commands`(command/exitCode)、`verification`(unitTests/apiTests/dbCompatibility)、changedFiles、archiveManifest、knownRisks、manualActions、maintenanceNotes 的确定性 HTML;USER_SKIPPED/BLOCKED_BY_DBA/失败状态可见,所有动态值 HTML 转义。返回结构统一为 `{ok, renderer: node|python-fallback|none, fallbackReason, out_path}`。Node 与 Python fallback **都失败**(`renderer=none, ok=false`)时,finalize 立即恢复原 change 目录并 exit 非 0,**绝不归档无 final-summary.html 的变更**。
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
`validate` 是 `harness_archive.py finalize` 的内嵌同进程步骤(不存在独立 `report validate` CLI);validate error 存在时,finalize 恢复原 changes 目录并 exit 非 0,绝不删除原 changes 目录。**缺 final-summary.html 恒为 validate error**(不再有"没有 HTML 但只 warning"的分支)。
|
|
143
143
|
|
|
144
144
|
## 归档与知识维护解耦(§8)
|
|
145
145
|
|
|
@@ -182,7 +182,7 @@ verification-ledger 把每次验证(compile / unit test / api test / package
|
|
|
182
182
|
```text
|
|
183
183
|
harness_ledger.py can-reuse --verification unitTestFull --scope module \
|
|
184
184
|
--project . --profile-input unitTestFull \
|
|
185
|
-
--command "<build-profile.json
|
|
185
|
+
--command "<resolved build-profile.json commands.unitTestFull.command>" --json
|
|
186
186
|
```
|
|
187
187
|
|
|
188
188
|
`build-profile.json` 新增 `verificationInputs.unitTestFull`(glob 列表,相对 project 展开,只保留 project 内文件、去重排序):
|
|
@@ -201,7 +201,17 @@ profile key 缺失 / glob 无匹配 / 结果为空 → `insufficient-evidence`
|
|
|
201
201
|
|
|
202
202
|
必须基于真实 diff 计算 SHA-256,且**必须是 commit-invariant 的**——覆盖本变更集相对 `baseCommit` 的全部内容变更(已提交 + 未提交 + 未跟踪),使 checkpoint commit 前后指纹一致,保证 run→test 复用链不断。
|
|
203
203
|
|
|
204
|
-
`<baseCommit>` 从 ledger 读取(harness-plan 阶段写入);缺失时用 `git merge-base HEAD <默认分支>`
|
|
204
|
+
`<baseCommit>` 从 ledger 读取(harness-plan 阶段写入);缺失时用 `git merge-base HEAD <默认分支>` 兜底。
|
|
205
|
+
|
|
206
|
+
**canonical 命令(cluster 2 起脚本化,推荐)**:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
harness_ledger.py diff-hash --repo <projectRoot> --base <baseCommit> --json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`diff-hash` 用 subprocess 直接捕获 Git bytes,基于**内容变更集**计算 SHA-256:working tree 相对 base 的所有变化文件 + 未跟踪文件,按 repo-relative path 排序、长度 framing(`path-len | path | exists | content-len | content`),独立于 shell/控制台编码/BOM/系统换行,且 **commit-invariant**(checkpoint commit 不改 working tree → 指纹不变,UT-011)。算法版本 `content-changeset-1`,输出 `diffHash`/`algorithmVersion`/`fileCount`/`base`/`head`。
|
|
213
|
+
|
|
214
|
+
> 旧 v1 PowerShell 拼接命令(下方)已废弃:依赖文本编码,且未跟踪文件提交后表示从 framed-content 切换为 diff-format 会破坏 commit-invariance。仅作历史参考。
|
|
205
215
|
|
|
206
216
|
```powershell
|
|
207
217
|
powershell.exe -NoProfile -Command "$base = '<baseCommit>'; $patch = '.harness/changes/<change>/runtime/current-diff.patch'; & { git diff $base HEAD --binary; git diff --binary; git ls-files --others --exclude-standard | ForEach-Object { Get-Content -Raw -LiteralPath $_ } } | Out-File -Encoding utf8 $patch; (Get-FileHash $patch -Algorithm SHA256).Hash"
|
|
@@ -268,3 +278,46 @@ ledger 的 `status` 与 final-summary 展示状态对应:
|
|
|
268
278
|
| postTestClassification=NON_BEHAVIORAL_CLEANUP | 小清理 | 🧹NON_BEHAVIORAL_CLEANUP |
|
|
269
279
|
|
|
270
280
|
**强制规则**:任何阶段若复用了前一阶段结果,final-summary 必须显示 `🔁REUSED`,**不得伪装成重新执行**。
|
|
281
|
+
|
|
282
|
+
## 九、Ledger v2(cluster 2)
|
|
283
|
+
|
|
284
|
+
`harness_ledger.py` v2 引入确定性 `diff-hash`(§五)、v2 entry 字段、coverage lattice、`package` verification 与结构化错误码。Skill 只调用 `record`/`can-reuse`/`diff-hash`,不再手工判断或解释自由文本。
|
|
285
|
+
|
|
286
|
+
### 9.1 v2 entry 字段
|
|
287
|
+
|
|
288
|
+
`record` 自动写入:
|
|
289
|
+
|
|
290
|
+
| 字段 | 含义 |
|
|
291
|
+
|------|------|
|
|
292
|
+
| `algorithmVersion` | 固定 `harness-ledger-2`;缺失即 v1 entry |
|
|
293
|
+
| `coverage` | 覆盖层级 `incremental`/`module`/`module-am`/`full`,由 verification+scope 派生或 `--coverage` 显式指定 |
|
|
294
|
+
| `toolchainHash`/`profileHash`/`environmentHash` | 可选;`record --toolchain-hash` 等写入,`can-reuse --toolchain-hash` 等比对(UT-017) |
|
|
295
|
+
|
|
296
|
+
### 9.2 coverage lattice
|
|
297
|
+
|
|
298
|
+
`COVERAGE_RANK = {incremental:0, module:1, module-am:2, full:3}`。各 verification 最低要求:`unitTest`=0、`unitTestFull`/`compile`/`apiTest`=1、`install`/`package`=2。entry.coverage rank < 要求 → `insufficient-evidence`(code `COVERAGE_INSUFFICIENT`),**禁止增量证据提升为全量门禁**(UT-015/API-005)。
|
|
299
|
+
|
|
300
|
+
### 9.3 package verification
|
|
301
|
+
|
|
302
|
+
`package` 加入 `VERIFICATIONS`。`record --verification package` 额外记录 `deployArtifact`/`sha256`/`testsExecuted`/`testsReusedFrom`。API-006/007 的 package 生命周期复用编排由 cluster 4 负责,cluster 2 仅提供 record/can-reuse 能力(UT-018)。
|
|
303
|
+
|
|
304
|
+
### 9.4 结构化错误码
|
|
305
|
+
|
|
306
|
+
`can-reuse` 每个非 reuse 结果携带 `code` 字段,Skill 据 `code` 决策,不解析 `detail` 自由文本:
|
|
307
|
+
|
|
308
|
+
| code | reason | 含义 |
|
|
309
|
+
|------|--------|------|
|
|
310
|
+
| `LEDGER_MISSING`/`VALIDATIONS_MISSING`/`VALIDATION_MISSING` | insufficient-evidence | ledger/条目缺失 |
|
|
311
|
+
| `MISSING_V2_FIELDS` | insufficient-evidence | v1 entry 缺 algorithmVersion/coverage,**一次性保守失效**(COM-002),重记录 v2 后可复用 |
|
|
312
|
+
| `MISSING_FIELDS` | insufficient-evidence | 缺 status/evidence/inputsHash/scope 等基础字段 |
|
|
313
|
+
| `COVERAGE_INSUFFICIENT` | insufficient-evidence | coverage rank 不足 |
|
|
314
|
+
| `SCOPE_INSUFFICIENT` | insufficient-evidence | unitTest scope 不覆盖请求 |
|
|
315
|
+
| `INPUT_FILE_MISSING` | insufficient-evidence | 当前文件集读取失败 |
|
|
316
|
+
| `COMMAND_CHANGED` | rerun | 命令变化 |
|
|
317
|
+
| `TOOLCHAIN_CHANGED`/`PROFILE_CHANGED`/`ENVIRONMENT_CHANGED` | rerun | 对应 hash 变化(UT-017) |
|
|
318
|
+
| `INPUTS_HASH_CHANGED` | rerun | inputsHash 变化 |
|
|
319
|
+
| `REUSED` | reuse | 复用 |
|
|
320
|
+
|
|
321
|
+
### 9.5 v1→v2 兼容
|
|
322
|
+
|
|
323
|
+
v1 ledger 可读;entry 缺 v2 字段时 `can-reuse` 返回 `MISSING_V2_FIELDS`(insufficient-evidence),**不静默升级证据**。重新 `record`(自动补 v2 字段)后恢复复用。diffHash 算法升级后旧 ledger 一次性失效,不危险复用。
|