@hunter-harness/workflow-harness 0.2.9 → 0.2.11
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 +12 -2
- package/harness/bundles/general/claude-code/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/reference.md +2 -0
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +15 -10
- package/harness/bundles/general/claude-code/harness-submit/checklist.md +40 -76
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +17 -2
- package/harness/bundles/general/claude-code/harness-sync/reference.md +2 -2
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/reference.md +2 -0
- package/harness/bundles/general/claude-code/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/general/claude-code/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +803 -274
- package/harness/bundles/general/claude-code/scripts/harness_change.py +18 -0
- package/harness/bundles/general/claude-code/scripts/harness_deploy.py +1 -44
- package/harness/bundles/general/claude-code/scripts/harness_events.py +104 -6
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +25 -4
- package/harness/bundles/general/claude-code/scripts/harness_integration.py +878 -0
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +440 -10
- package/harness/bundles/general/claude-code/scripts/harness_paths.py +315 -0
- package/harness/bundles/general/claude-code/scripts/harness_profile.py +45 -0
- package/harness/bundles/general/claude-code/scripts/harness_review.py +326 -0
- package/harness/bundles/general/claude-code/scripts/harness_sync.py +407 -0
- package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +244 -49
- 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 +12 -2
- package/harness/bundles/general/codebuddy/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +3 -3
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/reference.md +2 -0
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +15 -10
- package/harness/bundles/general/codebuddy/harness-submit/checklist.md +40 -76
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +17 -2
- package/harness/bundles/general/codebuddy/harness-sync/reference.md +2 -2
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/reference.md +2 -0
- package/harness/bundles/general/codebuddy/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/general/codebuddy/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +803 -274
- package/harness/bundles/general/codebuddy/scripts/harness_change.py +18 -0
- package/harness/bundles/general/codebuddy/scripts/harness_deploy.py +1 -44
- package/harness/bundles/general/codebuddy/scripts/harness_events.py +104 -6
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +25 -4
- package/harness/bundles/general/codebuddy/scripts/harness_integration.py +878 -0
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +440 -10
- package/harness/bundles/general/codebuddy/scripts/harness_paths.py +315 -0
- package/harness/bundles/general/codebuddy/scripts/harness_profile.py +45 -0
- package/harness/bundles/general/codebuddy/scripts/harness_review.py +326 -0
- package/harness/bundles/general/codebuddy/scripts/harness_sync.py +407 -0
- package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +244 -49
- 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 +12 -2
- package/harness/bundles/general/codex/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/reference.md +2 -0
- package/harness/bundles/general/codex/harness-submit/SKILL.md +15 -10
- package/harness/bundles/general/codex/harness-submit/checklist.md +40 -76
- package/harness/bundles/general/codex/harness-sync/SKILL.md +17 -2
- package/harness/bundles/general/codex/harness-sync/reference.md +2 -2
- package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-test/reference.md +2 -0
- package/harness/bundles/general/codex/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/general/codex/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/general/codex/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/general/codex/scripts/harness_archive.py +803 -274
- package/harness/bundles/general/codex/scripts/harness_change.py +18 -0
- package/harness/bundles/general/codex/scripts/harness_deploy.py +1 -44
- package/harness/bundles/general/codex/scripts/harness_events.py +104 -6
- package/harness/bundles/general/codex/scripts/harness_gate.py +25 -4
- package/harness/bundles/general/codex/scripts/harness_integration.py +878 -0
- package/harness/bundles/general/codex/scripts/harness_ledger.py +440 -10
- package/harness/bundles/general/codex/scripts/harness_paths.py +315 -0
- package/harness/bundles/general/codex/scripts/harness_profile.py +45 -0
- package/harness/bundles/general/codex/scripts/harness_review.py +326 -0
- package/harness/bundles/general/codex/scripts/harness_sync.py +407 -0
- package/harness/bundles/general/codex/scripts/harness_test_guard.py +244 -49
- 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 +12 -2
- package/harness/bundles/general/cursor/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/reference.md +2 -0
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +15 -10
- package/harness/bundles/general/cursor/harness-submit/checklist.md +40 -76
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +17 -2
- package/harness/bundles/general/cursor/harness-sync/reference.md +2 -2
- package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-test/reference.md +2 -0
- package/harness/bundles/general/cursor/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/general/cursor/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/general/cursor/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/general/cursor/scripts/harness_archive.py +803 -274
- package/harness/bundles/general/cursor/scripts/harness_change.py +18 -0
- package/harness/bundles/general/cursor/scripts/harness_deploy.py +1 -44
- package/harness/bundles/general/cursor/scripts/harness_events.py +104 -6
- package/harness/bundles/general/cursor/scripts/harness_gate.py +25 -4
- package/harness/bundles/general/cursor/scripts/harness_integration.py +878 -0
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +440 -10
- package/harness/bundles/general/cursor/scripts/harness_paths.py +315 -0
- package/harness/bundles/general/cursor/scripts/harness_profile.py +45 -0
- package/harness/bundles/general/cursor/scripts/harness_review.py +326 -0
- package/harness/bundles/general/cursor/scripts/harness_sync.py +407 -0
- package/harness/bundles/general/cursor/scripts/harness_test_guard.py +244 -49
- 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 +12 -2
- package/harness/bundles/java/claude-code/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +15 -10
- package/harness/bundles/java/claude-code/harness-submit/checklist.md +40 -76
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +17 -2
- package/harness/bundles/java/claude-code/harness-sync/reference.md +2 -2
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/java/claude-code/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +803 -274
- package/harness/bundles/java/claude-code/scripts/harness_change.py +18 -0
- package/harness/bundles/java/claude-code/scripts/harness_deploy.py +1 -44
- package/harness/bundles/java/claude-code/scripts/harness_events.py +104 -6
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +25 -4
- package/harness/bundles/java/claude-code/scripts/harness_integration.py +878 -0
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +440 -10
- package/harness/bundles/java/claude-code/scripts/harness_paths.py +315 -0
- package/harness/bundles/java/claude-code/scripts/harness_profile.py +45 -0
- package/harness/bundles/java/claude-code/scripts/harness_review.py +326 -0
- package/harness/bundles/java/claude-code/scripts/harness_sync.py +407 -0
- package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +244 -49
- 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 +12 -2
- package/harness/bundles/java/codebuddy/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +3 -3
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +15 -10
- package/harness/bundles/java/codebuddy/harness-submit/checklist.md +40 -76
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +17 -2
- package/harness/bundles/java/codebuddy/harness-sync/reference.md +2 -2
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/java/codebuddy/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +803 -274
- package/harness/bundles/java/codebuddy/scripts/harness_change.py +18 -0
- package/harness/bundles/java/codebuddy/scripts/harness_deploy.py +1 -44
- package/harness/bundles/java/codebuddy/scripts/harness_events.py +104 -6
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +25 -4
- package/harness/bundles/java/codebuddy/scripts/harness_integration.py +878 -0
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +440 -10
- package/harness/bundles/java/codebuddy/scripts/harness_paths.py +315 -0
- package/harness/bundles/java/codebuddy/scripts/harness_profile.py +45 -0
- package/harness/bundles/java/codebuddy/scripts/harness_review.py +326 -0
- package/harness/bundles/java/codebuddy/scripts/harness_sync.py +407 -0
- package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +244 -49
- 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 +12 -2
- package/harness/bundles/java/codex/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-submit/SKILL.md +15 -10
- package/harness/bundles/java/codex/harness-submit/checklist.md +40 -76
- package/harness/bundles/java/codex/harness-sync/SKILL.md +17 -2
- package/harness/bundles/java/codex/harness-sync/reference.md +2 -2
- package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codex/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/java/codex/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/java/codex/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/java/codex/scripts/harness_archive.py +803 -274
- package/harness/bundles/java/codex/scripts/harness_change.py +18 -0
- package/harness/bundles/java/codex/scripts/harness_deploy.py +1 -44
- package/harness/bundles/java/codex/scripts/harness_events.py +104 -6
- package/harness/bundles/java/codex/scripts/harness_gate.py +25 -4
- package/harness/bundles/java/codex/scripts/harness_integration.py +878 -0
- package/harness/bundles/java/codex/scripts/harness_ledger.py +440 -10
- package/harness/bundles/java/codex/scripts/harness_paths.py +315 -0
- package/harness/bundles/java/codex/scripts/harness_profile.py +45 -0
- package/harness/bundles/java/codex/scripts/harness_review.py +326 -0
- package/harness/bundles/java/codex/scripts/harness_sync.py +407 -0
- package/harness/bundles/java/codex/scripts/harness_test_guard.py +244 -49
- 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 +12 -2
- package/harness/bundles/java/cursor/harness-archive/templates/summary-data-template.json +6 -2
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +3 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/reference.md +7 -0
- package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +15 -10
- package/harness/bundles/java/cursor/harness-submit/checklist.md +40 -76
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +17 -2
- package/harness/bundles/java/cursor/harness-sync/reference.md +2 -2
- package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/cursor/protocols/archive-report-protocol.md +24 -4
- package/harness/bundles/java/cursor/protocols/ledger-protocol.md +36 -0
- package/harness/bundles/java/cursor/protocols/state-layout-protocol.md +15 -0
- package/harness/bundles/java/cursor/scripts/harness_archive.py +803 -274
- package/harness/bundles/java/cursor/scripts/harness_change.py +18 -0
- package/harness/bundles/java/cursor/scripts/harness_deploy.py +1 -44
- package/harness/bundles/java/cursor/scripts/harness_events.py +104 -6
- package/harness/bundles/java/cursor/scripts/harness_gate.py +25 -4
- package/harness/bundles/java/cursor/scripts/harness_integration.py +878 -0
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +440 -10
- package/harness/bundles/java/cursor/scripts/harness_paths.py +315 -0
- package/harness/bundles/java/cursor/scripts/harness_profile.py +45 -0
- package/harness/bundles/java/cursor/scripts/harness_review.py +326 -0
- package/harness/bundles/java/cursor/scripts/harness_sync.py +407 -0
- package/harness/bundles/java/cursor/scripts/harness_test_guard.py +244 -49
- package/harness/manifests/general/claude-code.json +47 -31
- package/harness/manifests/general/codebuddy.json +47 -31
- package/harness/manifests/general/codex.json +47 -31
- package/harness/manifests/general/cursor.json +47 -31
- package/harness/manifests/java/claude-code.json +47 -31
- package/harness/manifests/java/codebuddy.json +47 -31
- package/harness/manifests/java/codex.json +47 -31
- package/harness/manifests/java/cursor.json +47 -31
- package/hunter-workflow-family.json +2 -2
- package/package.json +1 -1
|
@@ -31,6 +31,8 @@ SCRIPTS_DIR = Path(__file__).resolve().parent
|
|
|
31
31
|
if str(SCRIPTS_DIR) not in sys.path:
|
|
32
32
|
sys.path.insert(0, str(SCRIPTS_DIR))
|
|
33
33
|
|
|
34
|
+
import harness_paths # noqa: E402
|
|
35
|
+
|
|
34
36
|
if hasattr(sys.stdout, "reconfigure"):
|
|
35
37
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
36
38
|
if hasattr(sys.stderr, "reconfigure"):
|
|
@@ -208,6 +210,20 @@ def change_dir_for_id(project_root: Path, change_id: str) -> Path | None:
|
|
|
208
210
|
return None
|
|
209
211
|
|
|
210
212
|
|
|
213
|
+
def _layout_fields(project_root: Path, change_id: str) -> dict[str, Any]:
|
|
214
|
+
"""Layout enrichment for resolve payloads; empty on any resolution issue."""
|
|
215
|
+
try:
|
|
216
|
+
layout = harness_paths.resolve_change_layout(project_root, change_id)
|
|
217
|
+
except (FileNotFoundError, ValueError, OSError):
|
|
218
|
+
return {}
|
|
219
|
+
return {
|
|
220
|
+
"contractRoot": layout["contractRoot"],
|
|
221
|
+
"stateRoot": layout["stateRoot"],
|
|
222
|
+
"layout": layout["layout"],
|
|
223
|
+
"repositoryId": layout["repositoryId"],
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
211
227
|
def resolve_change(
|
|
212
228
|
project_root: Path,
|
|
213
229
|
change_id: str | None,
|
|
@@ -229,6 +245,7 @@ def resolve_change(
|
|
|
229
245
|
"changeDir": str(resolved),
|
|
230
246
|
"projectRoot": str(project_root.resolve()),
|
|
231
247
|
"activeCount": len(active),
|
|
248
|
+
**_layout_fields(project_root, change_id),
|
|
232
249
|
}
|
|
233
250
|
if not active:
|
|
234
251
|
return {
|
|
@@ -247,6 +264,7 @@ def resolve_change(
|
|
|
247
264
|
"projectRoot": str(project_root.resolve()),
|
|
248
265
|
"activeCount": 1,
|
|
249
266
|
"autoSelected": True,
|
|
267
|
+
**_layout_fields(project_root, only["changeId"]),
|
|
250
268
|
}
|
|
251
269
|
return {
|
|
252
270
|
"ok": False,
|
|
@@ -719,40 +719,6 @@ def cmd_install(build_out: Path, project: Path, target: Path | None) -> dict[str
|
|
|
719
719
|
}
|
|
720
720
|
|
|
721
721
|
|
|
722
|
-
def cmd_diff(build_out: Path, project: Path, target: Path | None) -> dict[str, Any]:
|
|
723
|
-
build_out = build_out.resolve()
|
|
724
|
-
project = project.resolve()
|
|
725
|
-
installed = (target or project / ".claude" / "skills").resolve()
|
|
726
|
-
if not installed.is_dir():
|
|
727
|
-
return {
|
|
728
|
-
"ok": True,
|
|
729
|
-
"action": "diff",
|
|
730
|
-
"stale": True,
|
|
731
|
-
"missingInstall": True,
|
|
732
|
-
"outdated": [],
|
|
733
|
-
"missing": [],
|
|
734
|
-
"extra": [],
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
built = collect_files(build_out)
|
|
738
|
-
current = collect_files(installed)
|
|
739
|
-
outdated = [p for p, h in built.items() if p in current and current[p] != h]
|
|
740
|
-
missing = [p for p in built if p not in current]
|
|
741
|
-
# extra includes install-side managed manifests only as metadata, so they
|
|
742
|
-
# are excluded from the extra set; every other untracked file is a real
|
|
743
|
-
# extra and must mark the install stale (design §3.8 要点3).
|
|
744
|
-
extra = [p for p in current if p not in built and p not in INSTALL_METADATA]
|
|
745
|
-
return {
|
|
746
|
-
"ok": True,
|
|
747
|
-
"action": "diff",
|
|
748
|
-
"stale": bool(outdated or missing or extra),
|
|
749
|
-
"outdated": sorted(outdated),
|
|
750
|
-
"missing": sorted(missing),
|
|
751
|
-
"extra": sorted(extra),
|
|
752
|
-
"comparedAt": now_iso(),
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
|
|
756
722
|
def cmd_validate_manifest(
|
|
757
723
|
bundle_dir: Path, manifest_entries: list[dict[str, Any]]
|
|
758
724
|
) -> dict[str, Any]:
|
|
@@ -783,7 +749,7 @@ def cmd_validate_manifest(
|
|
|
783
749
|
|
|
784
750
|
|
|
785
751
|
def build_parser() -> argparse.ArgumentParser:
|
|
786
|
-
p = argparse.ArgumentParser(description="Harness skills deploy (build/install
|
|
752
|
+
p = argparse.ArgumentParser(description="Harness skills deploy (build/install)")
|
|
787
753
|
sub = p.add_subparsers(dest="command", required=True)
|
|
788
754
|
|
|
789
755
|
b = sub.add_parser("build", help="Synthesize core + overlay into output dir")
|
|
@@ -799,12 +765,6 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
799
765
|
i.add_argument("--target", type=Path)
|
|
800
766
|
i.add_argument("--json", action="store_true")
|
|
801
767
|
|
|
802
|
-
d = sub.add_parser("diff", help="Compare installed skills vs build output")
|
|
803
|
-
d.add_argument("--from", dest="from_dir", type=Path, required=True)
|
|
804
|
-
d.add_argument("--project", type=Path, required=True)
|
|
805
|
-
d.add_argument("--target", type=Path)
|
|
806
|
-
d.add_argument("--json", action="store_true")
|
|
807
|
-
|
|
808
768
|
v = sub.add_parser(
|
|
809
769
|
"validate-manifest", help="Validate bundle dir vs manifest (missing/extra/hash)"
|
|
810
770
|
)
|
|
@@ -823,9 +783,6 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
823
783
|
if args.command == "install":
|
|
824
784
|
result = cmd_install(args.from_dir, args.project, args.target)
|
|
825
785
|
return emit_json(result) if args.json else 0
|
|
826
|
-
if args.command == "diff":
|
|
827
|
-
result = cmd_diff(args.from_dir, args.project, args.target)
|
|
828
|
-
return emit_json(result) if args.json else 0
|
|
829
786
|
if args.command == "validate-manifest":
|
|
830
787
|
manifest_data = json.loads(args.manifest.read_text(encoding="utf-8"))
|
|
831
788
|
entries = (
|
|
@@ -23,6 +23,12 @@ import uuid
|
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Any
|
|
25
25
|
|
|
26
|
+
SCRIPTS_DIR = Path(__file__).resolve().parent
|
|
27
|
+
if str(SCRIPTS_DIR) not in sys.path:
|
|
28
|
+
sys.path.insert(0, str(SCRIPTS_DIR))
|
|
29
|
+
|
|
30
|
+
import harness_paths # noqa: E402
|
|
31
|
+
|
|
26
32
|
|
|
27
33
|
if hasattr(sys.stdout, "reconfigure"):
|
|
28
34
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
@@ -99,12 +105,16 @@ def resolve_change_dir(raw: str) -> Path:
|
|
|
99
105
|
return Path(raw).expanduser().resolve()
|
|
100
106
|
|
|
101
107
|
|
|
108
|
+
def _state_dir(change_dir: Path) -> Path:
|
|
109
|
+
return Path(harness_paths.resolve_state_dir_for_contract(change_dir))
|
|
110
|
+
|
|
111
|
+
|
|
102
112
|
def events_path(change_dir: Path) -> Path:
|
|
103
|
-
return change_dir / "events.ndjson"
|
|
113
|
+
return _state_dir(change_dir) / "events.ndjson"
|
|
104
114
|
|
|
105
115
|
|
|
106
116
|
def execution_log_path(change_dir: Path) -> Path:
|
|
107
|
-
return change_dir / "logs" / "execution-log.md"
|
|
117
|
+
return _state_dir(change_dir) / "logs" / "execution-log.md"
|
|
108
118
|
|
|
109
119
|
|
|
110
120
|
def archived_change_dir(change_dir: Path) -> Path | None:
|
|
@@ -179,6 +189,26 @@ def load_events(path: Path) -> list[dict[str, Any]]:
|
|
|
179
189
|
return events
|
|
180
190
|
|
|
181
191
|
|
|
192
|
+
def merge_event_files(paths: list[Path]) -> list[dict[str, Any]]:
|
|
193
|
+
"""Union events from multiple NDJSON files by event ID (UT-001/RET-05).
|
|
194
|
+
|
|
195
|
+
Each event ID appears exactly once; first-seen copy wins. Missing IDs are
|
|
196
|
+
kept keyed by (file index, line number) so unidentified events are never
|
|
197
|
+
silently dropped.
|
|
198
|
+
"""
|
|
199
|
+
merged: list[dict[str, Any]] = []
|
|
200
|
+
seen: set[str] = set()
|
|
201
|
+
for path in paths:
|
|
202
|
+
for event in load_events(Path(path)):
|
|
203
|
+
event_id = str(event.get("id") or "").strip()
|
|
204
|
+
if event_id:
|
|
205
|
+
if event_id in seen:
|
|
206
|
+
continue
|
|
207
|
+
seen.add(event_id)
|
|
208
|
+
merged.append(event)
|
|
209
|
+
return merged
|
|
210
|
+
|
|
211
|
+
|
|
182
212
|
def atomic_append_line(path: Path, line: str) -> None:
|
|
183
213
|
"""Write line to a temp file first, then append to the target (append-only)."""
|
|
184
214
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -433,9 +463,10 @@ def phase_duration_ms(phase_events: list[dict[str, Any]]) -> int | None:
|
|
|
433
463
|
elif etype == "phase.end":
|
|
434
464
|
end_ts = event.get("timestamp")
|
|
435
465
|
if start_ts and end_ts:
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
466
|
+
# Closed phases end at the matching phase.end. Late events appended
|
|
467
|
+
# after closure are reported separately (late_event_stats) and never
|
|
468
|
+
# extend the closed duration (RET-21).
|
|
469
|
+
return duration_ms_between(start_ts, end_ts)
|
|
439
470
|
# Fallback: first to last timestamp in the phase bucket.
|
|
440
471
|
stamps = [e.get("timestamp") for e in phase_events if e.get("timestamp")]
|
|
441
472
|
if len(stamps) >= 2:
|
|
@@ -443,6 +474,73 @@ def phase_duration_ms(phase_events: list[dict[str, Any]]) -> int | None:
|
|
|
443
474
|
return None
|
|
444
475
|
|
|
445
476
|
|
|
477
|
+
def late_event_stats(phase_events: list[dict[str, Any]]) -> dict[str, int]:
|
|
478
|
+
"""Count events recorded after the closing phase.end (RET-21)."""
|
|
479
|
+
end_ts = None
|
|
480
|
+
for event in phase_events:
|
|
481
|
+
if event.get("type") == "phase.end":
|
|
482
|
+
end_ts = event.get("timestamp")
|
|
483
|
+
if not end_ts:
|
|
484
|
+
return {"lateEventCount": 0, "lateEventSpanMs": 0}
|
|
485
|
+
late_stamps = []
|
|
486
|
+
seen_end = False
|
|
487
|
+
for event in phase_events:
|
|
488
|
+
if event.get("type") == "phase.end" and not seen_end:
|
|
489
|
+
seen_end = True
|
|
490
|
+
continue
|
|
491
|
+
if seen_end and event.get("timestamp"):
|
|
492
|
+
late_stamps.append(event["timestamp"])
|
|
493
|
+
if not late_stamps:
|
|
494
|
+
return {"lateEventCount": 0, "lateEventSpanMs": 0}
|
|
495
|
+
span = duration_ms_between(end_ts, late_stamps[-1]) or 0
|
|
496
|
+
return {"lateEventCount": len(late_stamps), "lateEventSpanMs": span}
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def attempt_invocations(phase_events: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
500
|
+
"""Per-attempt invocation view: attempt, status, durationMs (RET-22)."""
|
|
501
|
+
invocations: list[dict[str, Any]] = []
|
|
502
|
+
for attempt in split_phase_attempts(phase_events):
|
|
503
|
+
events_in = attempt.get("events") or []
|
|
504
|
+
start_ts = None
|
|
505
|
+
end_ts = None
|
|
506
|
+
status = None
|
|
507
|
+
for event in events_in:
|
|
508
|
+
if event.get("type") == "phase.start" and start_ts is None:
|
|
509
|
+
start_ts = event.get("timestamp")
|
|
510
|
+
elif event.get("type") == "phase.end":
|
|
511
|
+
end_ts = event.get("timestamp")
|
|
512
|
+
status = event.get("status", status)
|
|
513
|
+
duration = None
|
|
514
|
+
if start_ts and end_ts:
|
|
515
|
+
duration = duration_ms_between(start_ts, end_ts)
|
|
516
|
+
invocations.append(
|
|
517
|
+
{
|
|
518
|
+
"attempt": attempt.get("attempt"),
|
|
519
|
+
"status": status,
|
|
520
|
+
"durationMs": duration,
|
|
521
|
+
}
|
|
522
|
+
)
|
|
523
|
+
return invocations
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def canonical_phase_timing(phase_events: list[dict[str, Any]]) -> dict[str, Any]:
|
|
527
|
+
"""Single reducer for every duration view (RET-20).
|
|
528
|
+
|
|
529
|
+
activeExecutionMs: phase.start → matching phase.end (closed contract).
|
|
530
|
+
wallClockSpanMs: first → last timestamp in the bucket, late events included.
|
|
531
|
+
"""
|
|
532
|
+
stamps = [e.get("timestamp") for e in phase_events if e.get("timestamp")]
|
|
533
|
+
active = phase_duration_ms(phase_events)
|
|
534
|
+
late = late_event_stats(phase_events)
|
|
535
|
+
wall = duration_ms_between(stamps[0], stamps[-1]) if len(stamps) >= 2 else active
|
|
536
|
+
return {
|
|
537
|
+
"activeExecutionMs": active,
|
|
538
|
+
"wallClockSpanMs": wall,
|
|
539
|
+
"lateEventCount": late["lateEventCount"],
|
|
540
|
+
"lateEventSpanMs": late["lateEventSpanMs"],
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
|
|
446
544
|
def render_command_block(commands: list[dict[str, Any]]) -> list[str]:
|
|
447
545
|
if not commands:
|
|
448
546
|
return []
|
|
@@ -686,7 +784,7 @@ def cmd_append(args: argparse.Namespace) -> int:
|
|
|
686
784
|
as_json=as_json,
|
|
687
785
|
)
|
|
688
786
|
path = events_path(change_dir)
|
|
689
|
-
lock_path =
|
|
787
|
+
lock_path = path.with_name(path.name + ".lock")
|
|
690
788
|
|
|
691
789
|
# §6.1/§6.2: 普通 append = 加锁 -> 追加一行 -> fsync -> 解锁,不 load 历史、不渲染。
|
|
692
790
|
# new_event_id 用完整 uuid,无需扫描去重。锁覆盖 atomic_append_line 的
|
|
@@ -32,6 +32,7 @@ if str(SCRIPTS_DIR) not in sys.path:
|
|
|
32
32
|
import harness_change as hc # noqa: E402
|
|
33
33
|
import harness_events as he # noqa: E402
|
|
34
34
|
import harness_ledger as hl # noqa: E402
|
|
35
|
+
import harness_paths as hp # noqa: E402
|
|
35
36
|
import harness_workflow_policy as hwp # noqa: E402
|
|
36
37
|
import harness_test_guard as htg # noqa: E402
|
|
37
38
|
|
|
@@ -751,7 +752,7 @@ def append_phase_event(
|
|
|
751
752
|
if key not in event and value is not None:
|
|
752
753
|
event[key] = value
|
|
753
754
|
line = json.dumps(event, ensure_ascii=False, separators=(",", ":"))
|
|
754
|
-
lock_path =
|
|
755
|
+
lock_path = events_file.with_name(events_file.name + ".lock")
|
|
755
756
|
with he.event_file_lock(lock_path):
|
|
756
757
|
he.atomic_append_line(events_file, line)
|
|
757
758
|
rendered = False
|
|
@@ -1081,11 +1082,31 @@ def cmd_checkpoint(args: argparse.Namespace) -> int:
|
|
|
1081
1082
|
as_json=as_json,
|
|
1082
1083
|
)
|
|
1083
1084
|
required_report = str(item.get("requiredReport") or "")
|
|
1084
|
-
|
|
1085
|
-
if
|
|
1085
|
+
report_rel = Path(required_report)
|
|
1086
|
+
if (
|
|
1087
|
+
not required_report
|
|
1088
|
+
or report_rel.is_absolute()
|
|
1089
|
+
or ".." in report_rel.parts
|
|
1090
|
+
):
|
|
1091
|
+
return emit_error(
|
|
1092
|
+
"CHECKPOINT_REPORT_PATH_INVALID",
|
|
1093
|
+
f"required report path is invalid: {required_report or '<unset>'}",
|
|
1094
|
+
as_json=as_json,
|
|
1095
|
+
)
|
|
1096
|
+
state_dir = hp.resolve_state_dir_for_contract(change_dir, project)
|
|
1097
|
+
report_candidates = [state_dir / report_rel]
|
|
1098
|
+
if state_dir != change_dir:
|
|
1099
|
+
# Compatibility fallback for split-v1 changes created before dynamic
|
|
1100
|
+
# reports were routed to the state root.
|
|
1101
|
+
report_candidates.append(change_dir / report_rel)
|
|
1102
|
+
report_path = next(
|
|
1103
|
+
(candidate for candidate in report_candidates if candidate.is_file()),
|
|
1104
|
+
report_candidates[0],
|
|
1105
|
+
)
|
|
1106
|
+
if not report_path.is_file() or report_path.stat().st_size == 0:
|
|
1086
1107
|
return emit_error(
|
|
1087
1108
|
"CHECKPOINT_REPORT_MISSING",
|
|
1088
|
-
f"required report is missing: {required_report
|
|
1109
|
+
f"required report is missing: {required_report}",
|
|
1089
1110
|
as_json=as_json,
|
|
1090
1111
|
)
|
|
1091
1112
|
report_text = report_path.read_text(encoding="utf-8", errors="replace")
|