@hunter-harness/workflow-harness 0.2.54 → 0.2.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/harness/bundles/general/claude-code/.harness-build.json +1 -1
- package/harness/bundles/general/claude-code/README.md +3 -3
- package/harness/bundles/general/claude-code/contracts/workflow-policy.json +1 -1
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +21 -33
- package/harness/bundles/general/claude-code/harness-archive/checklist.md +6 -10
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +7 -3
- package/harness/bundles/general/claude-code/harness-plan/checklist.md +2 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +8 -4
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +9 -7
- package/harness/bundles/general/claude-code/harness-run/checklist.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/reference.md +3 -3
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +6 -6
- package/harness/bundles/general/claude-code/harness-submit/checklist.md +1 -1
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +8 -6
- package/harness/bundles/general/claude-code/harness-test/checklist.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/reference.md +2 -2
- package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +322 -74
- package/harness/bundles/general/claude-code/scripts/harness_context.py +236 -63
- package/harness/bundles/general/claude-code/scripts/harness_events.py +86 -5
- package/harness/bundles/general/claude-code/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/general/claude-code/scripts/harness_fixback.py +189 -1
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +353 -3
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +195 -11
- package/harness/bundles/general/claude-code/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +37 -44
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/README.md +3 -3
- package/harness/bundles/general/codebuddy/contracts/workflow-policy.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +21 -33
- package/harness/bundles/general/codebuddy/harness-archive/checklist.md +6 -10
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +7 -3
- package/harness/bundles/general/codebuddy/harness-plan/checklist.md +2 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +8 -4
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +9 -7
- package/harness/bundles/general/codebuddy/harness-run/checklist.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/reference.md +3 -3
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +6 -6
- package/harness/bundles/general/codebuddy/harness-submit/checklist.md +1 -1
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +8 -6
- package/harness/bundles/general/codebuddy/harness-test/checklist.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/reference.md +2 -2
- package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +322 -74
- package/harness/bundles/general/codebuddy/scripts/harness_context.py +236 -63
- package/harness/bundles/general/codebuddy/scripts/harness_events.py +86 -5
- package/harness/bundles/general/codebuddy/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/general/codebuddy/scripts/harness_fixback.py +189 -1
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +353 -3
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +195 -11
- package/harness/bundles/general/codebuddy/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +37 -44
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/README.md +3 -3
- package/harness/bundles/general/codex/contracts/workflow-policy.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +21 -33
- package/harness/bundles/general/codex/harness-archive/checklist.md +6 -10
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +7 -3
- package/harness/bundles/general/codex/harness-plan/checklist.md +2 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +4 -4
- package/harness/bundles/general/codex/harness-run/SKILL.md +9 -7
- package/harness/bundles/general/codex/harness-run/checklist.md +1 -1
- package/harness/bundles/general/codex/harness-run/reference.md +3 -3
- package/harness/bundles/general/codex/harness-submit/SKILL.md +6 -6
- package/harness/bundles/general/codex/harness-submit/checklist.md +1 -1
- package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-test/SKILL.md +8 -6
- package/harness/bundles/general/codex/harness-test/checklist.md +1 -1
- package/harness/bundles/general/codex/harness-test/reference.md +2 -2
- package/harness/bundles/general/codex/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/general/codex/scripts/harness_archive.py +322 -74
- package/harness/bundles/general/codex/scripts/harness_context.py +236 -63
- package/harness/bundles/general/codex/scripts/harness_events.py +86 -5
- package/harness/bundles/general/codex/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/general/codex/scripts/harness_fixback.py +189 -1
- package/harness/bundles/general/codex/scripts/harness_gate.py +353 -3
- package/harness/bundles/general/codex/scripts/harness_ledger.py +195 -11
- package/harness/bundles/general/codex/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/general/codex/scripts/harness_test_guard.py +37 -44
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/README.md +3 -3
- package/harness/bundles/general/cursor/contracts/workflow-policy.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +21 -33
- package/harness/bundles/general/cursor/harness-archive/checklist.md +6 -10
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +7 -3
- package/harness/bundles/general/cursor/harness-plan/checklist.md +2 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +4 -4
- package/harness/bundles/general/cursor/harness-run/SKILL.md +9 -7
- package/harness/bundles/general/cursor/harness-run/checklist.md +1 -1
- package/harness/bundles/general/cursor/harness-run/reference.md +3 -3
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +6 -6
- package/harness/bundles/general/cursor/harness-submit/checklist.md +1 -1
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-test/SKILL.md +8 -6
- package/harness/bundles/general/cursor/harness-test/checklist.md +1 -1
- package/harness/bundles/general/cursor/harness-test/reference.md +2 -2
- package/harness/bundles/general/cursor/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/general/cursor/scripts/harness_archive.py +322 -74
- package/harness/bundles/general/cursor/scripts/harness_context.py +236 -63
- package/harness/bundles/general/cursor/scripts/harness_events.py +86 -5
- package/harness/bundles/general/cursor/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/general/cursor/scripts/harness_fixback.py +189 -1
- package/harness/bundles/general/cursor/scripts/harness_gate.py +353 -3
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +195 -11
- package/harness/bundles/general/cursor/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/general/cursor/scripts/harness_test_guard.py +37 -44
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/README.md +3 -3
- package/harness/bundles/java/claude-code/contracts/workflow-policy.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 +21 -33
- package/harness/bundles/java/claude-code/harness-archive/checklist.md +6 -10
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/checklist.md +1 -1
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +7 -3
- package/harness/bundles/java/claude-code/harness-plan/checklist.md +2 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +8 -4
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +9 -7
- package/harness/bundles/java/claude-code/harness-run/checklist.md +1 -1
- package/harness/bundles/java/claude-code/harness-run/reference.md +2 -2
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +6 -6
- package/harness/bundles/java/claude-code/harness-submit/checklist.md +1 -1
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +8 -6
- package/harness/bundles/java/claude-code/harness-test/checklist.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/reference.md +1 -1
- package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +322 -74
- package/harness/bundles/java/claude-code/scripts/harness_context.py +236 -63
- package/harness/bundles/java/claude-code/scripts/harness_events.py +86 -5
- package/harness/bundles/java/claude-code/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/java/claude-code/scripts/harness_fixback.py +189 -1
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +353 -3
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +195 -11
- package/harness/bundles/java/claude-code/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +37 -44
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/README.md +3 -3
- package/harness/bundles/java/codebuddy/contracts/workflow-policy.json +1 -1
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +21 -33
- package/harness/bundles/java/codebuddy/harness-archive/checklist.md +6 -10
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/checklist.md +1 -1
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +7 -3
- package/harness/bundles/java/codebuddy/harness-plan/checklist.md +2 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +8 -4
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +9 -7
- package/harness/bundles/java/codebuddy/harness-run/checklist.md +1 -1
- package/harness/bundles/java/codebuddy/harness-run/reference.md +2 -2
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +6 -6
- package/harness/bundles/java/codebuddy/harness-submit/checklist.md +1 -1
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +8 -6
- package/harness/bundles/java/codebuddy/harness-test/checklist.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/reference.md +1 -1
- package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +322 -74
- package/harness/bundles/java/codebuddy/scripts/harness_context.py +236 -63
- package/harness/bundles/java/codebuddy/scripts/harness_events.py +86 -5
- package/harness/bundles/java/codebuddy/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/java/codebuddy/scripts/harness_fixback.py +189 -1
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +353 -3
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +195 -11
- package/harness/bundles/java/codebuddy/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +37 -44
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/README.md +3 -3
- package/harness/bundles/java/codex/contracts/workflow-policy.json +1 -1
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-archive/SKILL.md +21 -33
- package/harness/bundles/java/codex/harness-archive/checklist.md +6 -10
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/checklist.md +1 -1
- package/harness/bundles/java/codex/harness-plan/SKILL.md +7 -3
- package/harness/bundles/java/codex/harness-plan/checklist.md +2 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +4 -4
- package/harness/bundles/java/codex/harness-run/SKILL.md +9 -7
- package/harness/bundles/java/codex/harness-run/checklist.md +1 -1
- package/harness/bundles/java/codex/harness-run/reference.md +2 -2
- package/harness/bundles/java/codex/harness-submit/SKILL.md +6 -6
- package/harness/bundles/java/codex/harness-submit/checklist.md +1 -1
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +8 -6
- package/harness/bundles/java/codex/harness-test/checklist.md +1 -1
- package/harness/bundles/java/codex/harness-test/reference.md +1 -1
- package/harness/bundles/java/codex/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/java/codex/scripts/harness_archive.py +322 -74
- package/harness/bundles/java/codex/scripts/harness_context.py +236 -63
- package/harness/bundles/java/codex/scripts/harness_events.py +86 -5
- package/harness/bundles/java/codex/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/java/codex/scripts/harness_fixback.py +189 -1
- package/harness/bundles/java/codex/scripts/harness_gate.py +353 -3
- package/harness/bundles/java/codex/scripts/harness_ledger.py +195 -11
- package/harness/bundles/java/codex/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/java/codex/scripts/harness_test_guard.py +37 -44
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/README.md +3 -3
- package/harness/bundles/java/cursor/contracts/workflow-policy.json +1 -1
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +21 -33
- package/harness/bundles/java/cursor/harness-archive/checklist.md +6 -10
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/checklist.md +1 -1
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +7 -3
- package/harness/bundles/java/cursor/harness-plan/checklist.md +2 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +4 -4
- package/harness/bundles/java/cursor/harness-run/SKILL.md +9 -7
- package/harness/bundles/java/cursor/harness-run/checklist.md +1 -1
- package/harness/bundles/java/cursor/harness-run/reference.md +2 -2
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +6 -6
- package/harness/bundles/java/cursor/harness-submit/checklist.md +1 -1
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +8 -6
- package/harness/bundles/java/cursor/harness-test/checklist.md +1 -1
- package/harness/bundles/java/cursor/harness-test/reference.md +1 -1
- package/harness/bundles/java/cursor/protocols/ledger-protocol.md +3 -3
- package/harness/bundles/java/cursor/scripts/harness_archive.py +322 -74
- package/harness/bundles/java/cursor/scripts/harness_context.py +236 -63
- package/harness/bundles/java/cursor/scripts/harness_events.py +86 -5
- package/harness/bundles/java/cursor/scripts/harness_events_sync.py +201 -17
- package/harness/bundles/java/cursor/scripts/harness_fixback.py +189 -1
- package/harness/bundles/java/cursor/scripts/harness_gate.py +353 -3
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +195 -11
- package/harness/bundles/java/cursor/scripts/harness_plan_finalize.py +82 -0
- package/harness/bundles/java/cursor/scripts/harness_test_guard.py +37 -44
- package/harness/manifests/general/claude-code.json +32 -32
- package/harness/manifests/general/codebuddy.json +32 -32
- package/harness/manifests/general/codex.json +32 -32
- package/harness/manifests/general/cursor.json +32 -32
- package/harness/manifests/java/claude-code.json +35 -35
- package/harness/manifests/java/codebuddy.json +35 -35
- package/harness/manifests/java/codex.json +35 -35
- package/harness/manifests/java/cursor.json +35 -35
- package/hunter-workflow-family.json +5 -4
- package/package.json +1 -1
|
@@ -30,6 +30,7 @@ if str(SCRIPTS_DIR) not in sys.path:
|
|
|
30
30
|
sys.path.insert(0, str(SCRIPTS_DIR))
|
|
31
31
|
|
|
32
32
|
import harness_change as hc # noqa: E402
|
|
33
|
+
import harness_context as hctx # noqa: E402
|
|
33
34
|
import harness_events as he # noqa: E402
|
|
34
35
|
import harness_events_sync as hes # noqa: E402
|
|
35
36
|
import harness_ledger as hl # noqa: E402
|
|
@@ -692,11 +693,12 @@ def validate_ledger_for_phase_close(
|
|
|
692
693
|
try:
|
|
693
694
|
current_repository = hp.repository_identity(root)
|
|
694
695
|
current_ownership = hl.ownership_hash(contract)
|
|
695
|
-
|
|
696
|
+
current_diff_detail = hl.compute_ownership_diff(
|
|
696
697
|
root,
|
|
697
698
|
base=str(ledger["baseCommit"]),
|
|
698
699
|
change_dir=change_dir,
|
|
699
|
-
)
|
|
700
|
+
)
|
|
701
|
+
current_diff = current_diff_detail["diffHash"]
|
|
700
702
|
current_head = _git_text(root, "rev-parse", "--verify", "HEAD")
|
|
701
703
|
except (OSError, ValueError, RuntimeError) as exc:
|
|
702
704
|
return {
|
|
@@ -726,6 +728,18 @@ def validate_ledger_for_phase_close(
|
|
|
726
728
|
"storedHead": ledger.get("currentHead"),
|
|
727
729
|
"currentHead": current_head,
|
|
728
730
|
"ledgerPath": str(ledger_path) if ledger_path else None,
|
|
731
|
+
"pathSummary": {
|
|
732
|
+
"ownedFiles": list(current_diff_detail.get("files") or [])[:20],
|
|
733
|
+
"foreignPaths": list(current_diff_detail.get("foreignPaths") or [])[:20],
|
|
734
|
+
"ownedFileCount": current_diff_detail.get("ownedFileCount", 0),
|
|
735
|
+
"excludedRuntimeCount": current_diff_detail.get(
|
|
736
|
+
"excludedRuntimeCount", 0
|
|
737
|
+
),
|
|
738
|
+
},
|
|
739
|
+
"recoveryAction": (
|
|
740
|
+
"先确认新增、删除或越界路径是否属于当前变更;更新所有权后,"
|
|
741
|
+
"只重新执行受影响的验证,再原样重试 close。"
|
|
742
|
+
),
|
|
729
743
|
}
|
|
730
744
|
|
|
731
745
|
problems: list[dict[str, Any]] = []
|
|
@@ -1602,6 +1616,18 @@ def append_phase_event(
|
|
|
1602
1616
|
auto_sealed: list[dict[str, Any]] = []
|
|
1603
1617
|
with he.event_file_lock(lock_path):
|
|
1604
1618
|
existing = he.load_events(events_file)
|
|
1619
|
+
phase_attempts = he.split_phase_attempts(
|
|
1620
|
+
[event for event in existing if event.get("phase") == phase]
|
|
1621
|
+
)
|
|
1622
|
+
latest_attempt = max(
|
|
1623
|
+
(
|
|
1624
|
+
int(item.get("attempt"))
|
|
1625
|
+
for item in phase_attempts
|
|
1626
|
+
if isinstance(item.get("attempt"), int)
|
|
1627
|
+
),
|
|
1628
|
+
default=0,
|
|
1629
|
+
)
|
|
1630
|
+
event_attempt = latest_attempt + 1 if type_ == "phase.start" else latest_attempt or 1
|
|
1605
1631
|
args = argparse.Namespace(
|
|
1606
1632
|
phase=phase,
|
|
1607
1633
|
type=type_,
|
|
@@ -1619,12 +1645,18 @@ def append_phase_event(
|
|
|
1619
1645
|
decision=None,
|
|
1620
1646
|
reason=None,
|
|
1621
1647
|
run_id=run_id,
|
|
1622
|
-
attempt=
|
|
1648
|
+
attempt=event_attempt,
|
|
1623
1649
|
executor_tool=executor_tool,
|
|
1624
1650
|
executor_agent=executor_agent,
|
|
1625
1651
|
executor_model=executor_model,
|
|
1626
1652
|
handoff_from_tool=None,
|
|
1627
1653
|
handoff_reason=None,
|
|
1654
|
+
execution_mode=None,
|
|
1655
|
+
decision_reason_code=None,
|
|
1656
|
+
fallback_reason_code=None,
|
|
1657
|
+
trigger=("fixback" if "fixback" in note.lower() else None),
|
|
1658
|
+
from_phase=("review" if phase == "run" and "fixback" in note.lower() else None),
|
|
1659
|
+
result_status=None,
|
|
1628
1660
|
)
|
|
1629
1661
|
event = he.build_event(args, existing)
|
|
1630
1662
|
if identity:
|
|
@@ -1655,6 +1687,7 @@ def append_phase_event(
|
|
|
1655
1687
|
content = he.render_execution_log(events)
|
|
1656
1688
|
log_path = he.write_execution_log(change_dir, content)
|
|
1657
1689
|
rendered = True
|
|
1690
|
+
he.nudge_remote_sync(change_dir)
|
|
1658
1691
|
return {
|
|
1659
1692
|
"ok": True,
|
|
1660
1693
|
"eventId": event.get("id"),
|
|
@@ -1693,6 +1726,98 @@ def record_blocked_attempt(
|
|
|
1693
1726
|
)
|
|
1694
1727
|
|
|
1695
1728
|
|
|
1729
|
+
def record_gate_blocked(
|
|
1730
|
+
change_dir: Path,
|
|
1731
|
+
*,
|
|
1732
|
+
phase: str,
|
|
1733
|
+
code: str,
|
|
1734
|
+
message: str,
|
|
1735
|
+
run_id: str | None = None,
|
|
1736
|
+
) -> dict[str, Any]:
|
|
1737
|
+
"""Persist a recoverable gate rejection without manufacturing a phase run."""
|
|
1738
|
+
return append_phase_event(
|
|
1739
|
+
change_dir,
|
|
1740
|
+
phase=phase,
|
|
1741
|
+
type_="gate.blocked",
|
|
1742
|
+
status="BLOCKED",
|
|
1743
|
+
note=message,
|
|
1744
|
+
run_id=run_id or "blocked-" + uuid.uuid4().hex[:12],
|
|
1745
|
+
code=code,
|
|
1746
|
+
)
|
|
1747
|
+
|
|
1748
|
+
|
|
1749
|
+
def record_gate_recovered(
|
|
1750
|
+
change_dir: Path,
|
|
1751
|
+
*,
|
|
1752
|
+
phase: str,
|
|
1753
|
+
run_id: str,
|
|
1754
|
+
) -> dict[str, Any]:
|
|
1755
|
+
"""Close the latest unresolved gate.blocked record for this phase."""
|
|
1756
|
+
blocked: dict[str, Any] | None = None
|
|
1757
|
+
for event in reversed(he.load_events(he.events_path(change_dir))):
|
|
1758
|
+
if event.get("phase") != phase:
|
|
1759
|
+
continue
|
|
1760
|
+
if event.get("type") == "gate.recovered":
|
|
1761
|
+
break
|
|
1762
|
+
if event.get("type") == "gate.blocked":
|
|
1763
|
+
blocked = event
|
|
1764
|
+
break
|
|
1765
|
+
if blocked is None:
|
|
1766
|
+
return {"ok": True, "skipped": True, "reason": "no-unresolved-block"}
|
|
1767
|
+
return append_phase_event(
|
|
1768
|
+
change_dir,
|
|
1769
|
+
phase=phase,
|
|
1770
|
+
type_="gate.recovered",
|
|
1771
|
+
status="OK",
|
|
1772
|
+
note="阶段交接已恢复,门禁现已成功启动。",
|
|
1773
|
+
run_id=run_id,
|
|
1774
|
+
code=str(blocked.get("code") or "GATE_BLOCKED"),
|
|
1775
|
+
)
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
def validate_context_for_gate_begin(
|
|
1779
|
+
project: Path,
|
|
1780
|
+
change_id: str,
|
|
1781
|
+
phase: str,
|
|
1782
|
+
) -> dict[str, Any]:
|
|
1783
|
+
"""Require a completed Context handoff whenever modern Context state exists."""
|
|
1784
|
+
view = hctx.context_view(project, change_id)
|
|
1785
|
+
if not isinstance(view, dict) or not view.get("ok"):
|
|
1786
|
+
return {"ok": True, "code": "CONTEXT_LEGACY_COMPATIBLE"}
|
|
1787
|
+
current = view.get("current")
|
|
1788
|
+
transitions = view.get("transitions")
|
|
1789
|
+
begins = (view.get("attemptHistory") or {}).get("begins")
|
|
1790
|
+
if not isinstance(current, dict):
|
|
1791
|
+
return {"ok": True, "code": "CONTEXT_LEGACY_COMPATIBLE"}
|
|
1792
|
+
current_phase = str(current.get("phase") or view.get("currentPhase") or "")
|
|
1793
|
+
if current_phase != phase:
|
|
1794
|
+
return {
|
|
1795
|
+
"ok": False,
|
|
1796
|
+
"code": "CONTEXT_HANDOFF_REQUIRED",
|
|
1797
|
+
"message": "阶段交接尚未完成,门禁未启动;请先完成上下文交接。",
|
|
1798
|
+
"expectedPhase": current_phase or None,
|
|
1799
|
+
"requestedPhase": phase,
|
|
1800
|
+
}
|
|
1801
|
+
if isinstance(transitions, list) and transitions:
|
|
1802
|
+
latest = transitions[-1] if isinstance(transitions[-1], dict) else {}
|
|
1803
|
+
receipt_hash = latest.get("receiptHash")
|
|
1804
|
+
begin_items = begins if isinstance(begins, list) else []
|
|
1805
|
+
acknowledged = any(
|
|
1806
|
+
isinstance(item, dict)
|
|
1807
|
+
and item.get("phase") == phase
|
|
1808
|
+
and item.get("receiptHash") == receipt_hash
|
|
1809
|
+
for item in begin_items
|
|
1810
|
+
)
|
|
1811
|
+
if latest.get("toPhase") != phase or not acknowledged:
|
|
1812
|
+
return {
|
|
1813
|
+
"ok": False,
|
|
1814
|
+
"code": "CONTEXT_BEGIN_REQUIRED",
|
|
1815
|
+
"message": "阶段交接收据尚未确认,门禁未启动;请先执行上下文 begin。",
|
|
1816
|
+
"requestedPhase": phase,
|
|
1817
|
+
}
|
|
1818
|
+
return {"ok": True, "code": "CONTEXT_READY"}
|
|
1819
|
+
|
|
1820
|
+
|
|
1696
1821
|
def _phase_event_exists(change_dir: Path, phase: str, type_: str, run_id: str) -> bool:
|
|
1697
1822
|
return any(
|
|
1698
1823
|
event.get("phase") == phase
|
|
@@ -1702,6 +1827,80 @@ def _phase_event_exists(change_dir: Path, phase: str, type_: str, run_id: str) -
|
|
|
1702
1827
|
)
|
|
1703
1828
|
|
|
1704
1829
|
|
|
1830
|
+
def _latest_phase_end(
|
|
1831
|
+
change_dir: Path,
|
|
1832
|
+
phase: str,
|
|
1833
|
+
run_id: str | None = None,
|
|
1834
|
+
) -> dict[str, Any] | None:
|
|
1835
|
+
for event in reversed(he.load_events(he.events_path(change_dir))):
|
|
1836
|
+
if event.get("phase") != phase or event.get("type") != "phase.end":
|
|
1837
|
+
continue
|
|
1838
|
+
if run_id and event.get("run_id") != run_id:
|
|
1839
|
+
continue
|
|
1840
|
+
return event
|
|
1841
|
+
return None
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
def _terminal_matches_context_session(
|
|
1845
|
+
project: Path,
|
|
1846
|
+
change_id: str,
|
|
1847
|
+
phase: str,
|
|
1848
|
+
terminal: dict[str, Any],
|
|
1849
|
+
) -> bool:
|
|
1850
|
+
view = hctx.context_view(project, change_id)
|
|
1851
|
+
current = view.get("current") if isinstance(view, dict) else None
|
|
1852
|
+
if not isinstance(current, dict) or current.get("phase") != phase:
|
|
1853
|
+
return False
|
|
1854
|
+
prepared_at = he.parse_timestamp(current.get("preparedAt"))
|
|
1855
|
+
terminal_at = he.parse_timestamp(
|
|
1856
|
+
terminal.get("timestamp") or terminal.get("occurred_at")
|
|
1857
|
+
)
|
|
1858
|
+
return (
|
|
1859
|
+
prepared_at is not None
|
|
1860
|
+
and terminal_at is not None
|
|
1861
|
+
and terminal_at >= prepared_at
|
|
1862
|
+
)
|
|
1863
|
+
|
|
1864
|
+
|
|
1865
|
+
def _close_context_handoff(
|
|
1866
|
+
project: Path,
|
|
1867
|
+
change_id: str,
|
|
1868
|
+
args: argparse.Namespace,
|
|
1869
|
+
*,
|
|
1870
|
+
status: str,
|
|
1871
|
+
) -> dict[str, Any] | None:
|
|
1872
|
+
to_phase = getattr(args, "to_phase", None)
|
|
1873
|
+
if not to_phase:
|
|
1874
|
+
return None
|
|
1875
|
+
try:
|
|
1876
|
+
return hctx.close_transition(
|
|
1877
|
+
project,
|
|
1878
|
+
change_id,
|
|
1879
|
+
from_phase=args.phase,
|
|
1880
|
+
to_phase=str(to_phase),
|
|
1881
|
+
executor=getattr(args, "executor", None),
|
|
1882
|
+
artifacts=list(getattr(args, "artifact", None) or []),
|
|
1883
|
+
status=status,
|
|
1884
|
+
)
|
|
1885
|
+
except Exception as exc: # noqa: BLE001 — phase close remains locally durable
|
|
1886
|
+
return {
|
|
1887
|
+
"ok": False,
|
|
1888
|
+
"code": "CONTEXT_HANDOFF_FAILED",
|
|
1889
|
+
"message": str(exc),
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
|
|
1893
|
+
def _sync_after_phase_close(project: Path, change_dir: Path) -> dict[str, Any]:
|
|
1894
|
+
try:
|
|
1895
|
+
return hes.auto_events_sync(project, change_dir)
|
|
1896
|
+
except Exception as exc: # noqa: BLE001 — remote sync is recoverable
|
|
1897
|
+
return {
|
|
1898
|
+
"ok": False,
|
|
1899
|
+
"code": "PLATFORM_EVENTS_SYNC_WARN",
|
|
1900
|
+
"warning": f"events-sync hook failed: {exc}",
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
|
|
1705
1904
|
def _validate_scenario_coverage(change_dir: Path) -> dict[str, Any]:
|
|
1706
1905
|
"""C9: validate all ledger-required scenarios are covered by ledger entries.
|
|
1707
1906
|
|
|
@@ -1971,6 +2170,32 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
1971
2170
|
extra={k: v for k, v in resolved.items() if k not in {"ok", "message"}},
|
|
1972
2171
|
)
|
|
1973
2172
|
change_dir = Path(resolved["changeDir"])
|
|
2173
|
+
context_check = validate_context_for_gate_begin(
|
|
2174
|
+
project, str(resolved["changeId"]), args.phase
|
|
2175
|
+
)
|
|
2176
|
+
if not context_check.get("ok"):
|
|
2177
|
+
code = str(context_check.get("code") or "CONTEXT_HANDOFF_REQUIRED")
|
|
2178
|
+
message = str(
|
|
2179
|
+
context_check.get("message")
|
|
2180
|
+
or "阶段交接尚未完成,门禁未启动。"
|
|
2181
|
+
)
|
|
2182
|
+
record_gate_blocked(
|
|
2183
|
+
change_dir,
|
|
2184
|
+
phase=args.phase,
|
|
2185
|
+
code=code,
|
|
2186
|
+
message=message,
|
|
2187
|
+
run_id=args.run_id or os.environ.get("HUNTER_HARNESS_RUN_ID"),
|
|
2188
|
+
)
|
|
2189
|
+
return emit_error(
|
|
2190
|
+
code,
|
|
2191
|
+
message,
|
|
2192
|
+
as_json=as_json,
|
|
2193
|
+
extra={
|
|
2194
|
+
key: value
|
|
2195
|
+
for key, value in context_check.items()
|
|
2196
|
+
if key not in {"ok", "code", "message"}
|
|
2197
|
+
},
|
|
2198
|
+
)
|
|
1974
2199
|
severity_mode = gate_severity_mode(project, change_dir)
|
|
1975
2200
|
gate_warnings: list[dict[str, Any]] = []
|
|
1976
2201
|
plan_verification: dict[str, Any] | None = None
|
|
@@ -2142,6 +2367,16 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
2142
2367
|
message="test guard begin failed (downgraded to WARN)",
|
|
2143
2368
|
))
|
|
2144
2369
|
else:
|
|
2370
|
+
record_gate_blocked(
|
|
2371
|
+
change_dir,
|
|
2372
|
+
phase=args.phase,
|
|
2373
|
+
code=str(
|
|
2374
|
+
guard_result.get("code")
|
|
2375
|
+
or "TEST_GUARD_BEGIN_FAILED"
|
|
2376
|
+
),
|
|
2377
|
+
message="测试保护快照建立失败,已停止阶段启动。",
|
|
2378
|
+
run_id=run_id,
|
|
2379
|
+
)
|
|
2145
2380
|
hc.release_lease(
|
|
2146
2381
|
project,
|
|
2147
2382
|
change_id=resolved["changeId"],
|
|
@@ -2158,6 +2393,11 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
2158
2393
|
current_head = _git_text(execution_root, "rev-parse", "--verify", "HEAD")
|
|
2159
2394
|
ledger, _ = hl.load_ledger(change_dir)
|
|
2160
2395
|
base_commit = ledger.get("baseCommit") if isinstance(ledger, dict) else None
|
|
2396
|
+
try:
|
|
2397
|
+
begin_contract = hp.load_change_contract(change_dir)
|
|
2398
|
+
begin_ownership_hash = hl.ownership_hash(begin_contract)
|
|
2399
|
+
except (OSError, ValueError, json.JSONDecodeError):
|
|
2400
|
+
begin_ownership_hash = None
|
|
2161
2401
|
capsule = {
|
|
2162
2402
|
"schemaVersion": 1,
|
|
2163
2403
|
"changeId": resolved["changeId"],
|
|
@@ -2170,6 +2410,7 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
2170
2410
|
"repositoryId": hp.repository_identity(execution_root),
|
|
2171
2411
|
"baseCommit": base_commit or current_head,
|
|
2172
2412
|
"currentHead": current_head,
|
|
2413
|
+
"ownershipHash": begin_ownership_hash,
|
|
2173
2414
|
"createdAt": he.now_iso(),
|
|
2174
2415
|
"projectionReceipt": projection,
|
|
2175
2416
|
}
|
|
@@ -2187,6 +2428,11 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
2187
2428
|
executor_agent=args.executor_agent or os.environ.get("HUNTER_HARNESS_AGENT"),
|
|
2188
2429
|
executor_model=args.executor_model or os.environ.get("HUNTER_HARNESS_MODEL"),
|
|
2189
2430
|
)
|
|
2431
|
+
recovery_result = record_gate_recovered(
|
|
2432
|
+
change_dir,
|
|
2433
|
+
phase=args.phase,
|
|
2434
|
+
run_id=run_id,
|
|
2435
|
+
)
|
|
2190
2436
|
except BaseException:
|
|
2191
2437
|
hc.release_lease(
|
|
2192
2438
|
project, change_id=resolved["changeId"], phase=args.phase, run_id=run_id
|
|
@@ -2206,6 +2452,7 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
2206
2452
|
"lease": claim.get("lease"),
|
|
2207
2453
|
"identity": identity,
|
|
2208
2454
|
"event": event_result,
|
|
2455
|
+
"gateRecovery": recovery_result,
|
|
2209
2456
|
"testGuard": guard_result,
|
|
2210
2457
|
"policySchemaVersion": policy.get("schemaVersion"),
|
|
2211
2458
|
"planVerification": plan_verification,
|
|
@@ -2266,6 +2513,48 @@ def cmd_close(args: argparse.Namespace) -> int:
|
|
|
2266
2513
|
explicit_run_id = args.run_id or os.environ.get("HUNTER_HARNESS_RUN_ID")
|
|
2267
2514
|
current_lease = hc.inspect_lease(project, resolved["changeId"])
|
|
2268
2515
|
if current_lease is None:
|
|
2516
|
+
terminal = _latest_phase_end(change_dir, args.phase, explicit_run_id)
|
|
2517
|
+
if (
|
|
2518
|
+
getattr(args, "to_phase", None)
|
|
2519
|
+
and terminal is not None
|
|
2520
|
+
and _terminal_matches_context_session(
|
|
2521
|
+
project, str(resolved["changeId"]), args.phase, terminal
|
|
2522
|
+
)
|
|
2523
|
+
):
|
|
2524
|
+
terminal_status = str(terminal.get("status") or args.status)
|
|
2525
|
+
handoff = _close_context_handoff(
|
|
2526
|
+
project,
|
|
2527
|
+
str(resolved["changeId"]),
|
|
2528
|
+
args,
|
|
2529
|
+
status=terminal_status,
|
|
2530
|
+
)
|
|
2531
|
+
monitor = _sync_after_phase_close(project, change_dir)
|
|
2532
|
+
if not isinstance(handoff, dict) or not handoff.get("ok"):
|
|
2533
|
+
return emit_error(
|
|
2534
|
+
"PHASE_HANDOFF_PENDING",
|
|
2535
|
+
"phase gate is closed, but context handoff still needs attention",
|
|
2536
|
+
as_json=as_json,
|
|
2537
|
+
extra={
|
|
2538
|
+
"localCloseComplete": True,
|
|
2539
|
+
"retryable": True,
|
|
2540
|
+
"contextHandoff": handoff,
|
|
2541
|
+
"platformMonitor": monitor,
|
|
2542
|
+
},
|
|
2543
|
+
)
|
|
2544
|
+
emit(
|
|
2545
|
+
{
|
|
2546
|
+
"ok": True,
|
|
2547
|
+
"code": "PHASE_CLOSE_RESUMED",
|
|
2548
|
+
"phase": args.phase,
|
|
2549
|
+
"status": terminal_status,
|
|
2550
|
+
"changeId": resolved["changeId"],
|
|
2551
|
+
"localCloseComplete": True,
|
|
2552
|
+
"contextHandoff": handoff,
|
|
2553
|
+
"platformMonitor": monitor,
|
|
2554
|
+
},
|
|
2555
|
+
as_json=as_json,
|
|
2556
|
+
)
|
|
2557
|
+
return 0
|
|
2269
2558
|
return emit_error("LEASE_ABSENT", "no active lease for phase close", as_json=as_json)
|
|
2270
2559
|
run_id = explicit_run_id or str(current_lease.get("runId") or "")
|
|
2271
2560
|
if str(current_lease.get("runId")) != run_id or str(current_lease.get("phase")) != args.phase:
|
|
@@ -2432,6 +2721,16 @@ def cmd_close(args: argparse.Namespace) -> int:
|
|
|
2432
2721
|
status="LEDGER_VALIDATION_FAILED",
|
|
2433
2722
|
error=ledger_result,
|
|
2434
2723
|
)
|
|
2724
|
+
record_gate_blocked(
|
|
2725
|
+
change_dir,
|
|
2726
|
+
phase=args.phase,
|
|
2727
|
+
code=str(ledger_result.get("code") or "LEDGER_INVALID"),
|
|
2728
|
+
message=(
|
|
2729
|
+
"验证记录与当前变更身份不一致,已保留现场;"
|
|
2730
|
+
"请按返回的路径摘要重新验证受影响范围。"
|
|
2731
|
+
),
|
|
2732
|
+
run_id=run_id,
|
|
2733
|
+
)
|
|
2435
2734
|
return emit_error(
|
|
2436
2735
|
str(ledger_result.get("code", "LEDGER_INVALID")),
|
|
2437
2736
|
str(ledger_result.get("message", "ledger validation failed")),
|
|
@@ -2520,6 +2819,16 @@ def cmd_close(args: argparse.Namespace) -> int:
|
|
|
2520
2819
|
"updatedAt": he.now_iso(),
|
|
2521
2820
|
})
|
|
2522
2821
|
write_phase_capsule(change_dir, args.phase, run_id, capsule)
|
|
2822
|
+
record_gate_blocked(
|
|
2823
|
+
change_dir,
|
|
2824
|
+
phase=args.phase,
|
|
2825
|
+
code=str(
|
|
2826
|
+
guard_result.get("code")
|
|
2827
|
+
or "TEST_GUARD_CLOSE_FAILED"
|
|
2828
|
+
),
|
|
2829
|
+
message="测试保护关门失败,已保留现场并等待同一命令恢复。",
|
|
2830
|
+
run_id=run_id,
|
|
2831
|
+
)
|
|
2523
2832
|
return emit_error(
|
|
2524
2833
|
str(guard_result.get("code", "TEST_GUARD_CLOSE_FAILED")),
|
|
2525
2834
|
"test guard close failed",
|
|
@@ -2597,6 +2906,41 @@ def cmd_close(args: argparse.Namespace) -> int:
|
|
|
2597
2906
|
capsule["closeStatus"] = close_status
|
|
2598
2907
|
write_phase_capsule(change_dir, args.phase, run_id, capsule)
|
|
2599
2908
|
|
|
2909
|
+
context_handoff = _close_context_handoff(
|
|
2910
|
+
project,
|
|
2911
|
+
str(resolved["changeId"]),
|
|
2912
|
+
args,
|
|
2913
|
+
status=close_status,
|
|
2914
|
+
)
|
|
2915
|
+
platform_monitor = _sync_after_phase_close(project, change_dir)
|
|
2916
|
+
if isinstance(context_handoff, dict) and not context_handoff.get("ok"):
|
|
2917
|
+
record_gate_blocked(
|
|
2918
|
+
change_dir,
|
|
2919
|
+
phase=args.phase,
|
|
2920
|
+
code=str(context_handoff.get("code") or "PHASE_HANDOFF_PENDING"),
|
|
2921
|
+
message="阶段本地关门已完成,但上下文交接尚待恢复。",
|
|
2922
|
+
run_id=run_id,
|
|
2923
|
+
)
|
|
2924
|
+
return emit_error(
|
|
2925
|
+
"PHASE_HANDOFF_PENDING",
|
|
2926
|
+
"phase gate closed locally, but context handoff failed; retry the same close command",
|
|
2927
|
+
as_json=as_json,
|
|
2928
|
+
extra={
|
|
2929
|
+
"localCloseComplete": True,
|
|
2930
|
+
"retryable": True,
|
|
2931
|
+
"phase": args.phase,
|
|
2932
|
+
"status": close_status,
|
|
2933
|
+
"changeId": resolved["changeId"],
|
|
2934
|
+
"contextHandoff": context_handoff,
|
|
2935
|
+
"platformMonitor": platform_monitor,
|
|
2936
|
+
},
|
|
2937
|
+
)
|
|
2938
|
+
|
|
2939
|
+
recovery_result = record_gate_recovered(
|
|
2940
|
+
change_dir,
|
|
2941
|
+
phase=args.phase,
|
|
2942
|
+
run_id=run_id,
|
|
2943
|
+
)
|
|
2600
2944
|
payload = {
|
|
2601
2945
|
"ok": True,
|
|
2602
2946
|
"code": close_code,
|
|
@@ -2612,6 +2956,9 @@ def cmd_close(args: argparse.Namespace) -> int:
|
|
|
2612
2956
|
"lease": release,
|
|
2613
2957
|
"gateSeverityMode": severity_mode,
|
|
2614
2958
|
"gateWarnings": gate_warnings,
|
|
2959
|
+
"contextHandoff": context_handoff,
|
|
2960
|
+
"platformMonitor": platform_monitor,
|
|
2961
|
+
"gateRecovery": recovery_result,
|
|
2615
2962
|
}
|
|
2616
2963
|
emit(payload, as_json=as_json)
|
|
2617
2964
|
return 0
|
|
@@ -2806,6 +3153,9 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
2806
3153
|
p_close.add_argument("--run-id", default=None)
|
|
2807
3154
|
p_close.add_argument("--task", type=int, default=None)
|
|
2808
3155
|
p_close.add_argument("--note", default="")
|
|
3156
|
+
p_close.add_argument("--to-phase", default=None)
|
|
3157
|
+
p_close.add_argument("--executor", default=None)
|
|
3158
|
+
p_close.add_argument("--artifact", action="append", default=[])
|
|
2809
3159
|
p_close.set_defaults(func=cmd_close)
|
|
2810
3160
|
|
|
2811
3161
|
p_classify = sub.add_parser("classify", parents=[shared])
|