@hunter-harness/workflow-harness 0.2.34 → 0.2.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/harness/bundles/general/claude-code/.harness-build.json +1 -1
- package/harness/bundles/general/claude-code/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/general/claude-code/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/general/claude-code/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
- 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/pitfalls.md +1 -1
- package/harness/bundles/general/claude-code/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/general/claude-code/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/general/claude-code/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/general/claude-code/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/general/claude-code/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +24 -12
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +121 -12
- package/harness/bundles/general/claude-code/scripts/harness_preflight.py +2 -2
- package/harness/bundles/general/claude-code/scripts/harness_profile.py +308 -23
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/general/codebuddy/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/general/codebuddy/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
- 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/pitfalls.md +1 -1
- package/harness/bundles/general/codebuddy/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/general/codebuddy/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/general/codebuddy/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/general/codebuddy/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/general/codebuddy/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +24 -12
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +121 -12
- package/harness/bundles/general/codebuddy/scripts/harness_preflight.py +2 -2
- package/harness/bundles/general/codebuddy/scripts/harness_profile.py +308 -23
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/general/codex/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/general/codex/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
- 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/pitfalls.md +1 -1
- package/harness/bundles/general/codex/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/general/codex/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/general/codex/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/general/codex/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/general/codex/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/general/codex/scripts/harness_archive.py +24 -12
- package/harness/bundles/general/codex/scripts/harness_ledger.py +121 -12
- package/harness/bundles/general/codex/scripts/harness_preflight.py +2 -2
- package/harness/bundles/general/codex/scripts/harness_profile.py +308 -23
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/general/cursor/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/general/cursor/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
- 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/pitfalls.md +1 -1
- package/harness/bundles/general/cursor/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/general/cursor/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/general/cursor/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/general/cursor/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/general/cursor/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/general/cursor/scripts/harness_archive.py +24 -12
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +121 -12
- package/harness/bundles/general/cursor/scripts/harness_preflight.py +2 -2
- package/harness/bundles/general/cursor/scripts/harness_profile.py +308 -23
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/java/claude-code/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/java/claude-code/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- 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/harness-test/pitfalls.md +1 -1
- package/harness/bundles/java/claude-code/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/java/claude-code/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/java/claude-code/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/java/claude-code/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/java/claude-code/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +24 -12
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +121 -12
- package/harness/bundles/java/claude-code/scripts/harness_preflight.py +2 -2
- package/harness/bundles/java/claude-code/scripts/harness_profile.py +308 -23
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/java/codebuddy/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/java/codebuddy/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- 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/harness-test/pitfalls.md +1 -1
- package/harness/bundles/java/codebuddy/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/java/codebuddy/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/java/codebuddy/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/java/codebuddy/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/java/codebuddy/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +24 -12
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +121 -12
- package/harness/bundles/java/codebuddy/scripts/harness_preflight.py +2 -2
- package/harness/bundles/java/codebuddy/scripts/harness_profile.py +308 -23
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/java/codex/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/java/codex/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- 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/harness-test/pitfalls.md +1 -1
- package/harness/bundles/java/codex/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/java/codex/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/java/codex/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/java/codex/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/java/codex/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/java/codex/scripts/harness_archive.py +24 -12
- package/harness/bundles/java/codex/scripts/harness_ledger.py +121 -12
- package/harness/bundles/java/codex/scripts/harness_preflight.py +2 -2
- package/harness/bundles/java/codex/scripts/harness_profile.py +308 -23
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/contracts/build-profile-v3.schema.json +147 -0
- package/harness/bundles/java/cursor/contracts/doctor-capability.schema.json +43 -0
- package/harness/bundles/java/cursor/contracts/external-platform-observation.schema.json +62 -0
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- 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/harness-test/pitfalls.md +1 -1
- package/harness/bundles/java/cursor/protocols/ci-layering-protocol.md +22 -0
- package/harness/bundles/java/cursor/protocols/external-platform-protocol.md +27 -0
- package/harness/bundles/java/cursor/protocols/memory-closeout-protocol.md +21 -0
- package/harness/bundles/java/cursor/protocols/registry-governance-protocol.md +31 -0
- package/harness/bundles/java/cursor/protocols/verification-graph-protocol.md +26 -0
- package/harness/bundles/java/cursor/scripts/harness_archive.py +24 -12
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +121 -12
- package/harness/bundles/java/cursor/scripts/harness_preflight.py +2 -2
- package/harness/bundles/java/cursor/scripts/harness_profile.py +308 -23
- package/harness/manifests/general/claude-code.json +58 -20
- package/harness/manifests/general/codebuddy.json +58 -20
- package/harness/manifests/general/codex.json +58 -20
- package/harness/manifests/general/cursor.json +58 -20
- package/harness/manifests/java/claude-code.json +60 -22
- package/harness/manifests/java/codebuddy.json +60 -22
- package/harness/manifests/java/codex.json +60 -22
- package/harness/manifests/java/cursor.json +60 -22
- package/hunter-workflow-family.json +17 -5
- package/package.json +1 -1
|
@@ -621,6 +621,7 @@ def evaluate_product_ci_gate(change_dir: Path) -> dict[str, Any]:
|
|
|
621
621
|
|
|
622
622
|
if assurance == "local-reproducible" and provider == "local-harness":
|
|
623
623
|
local_required = {
|
|
624
|
+
"subject.environmentHash": environment_hash,
|
|
624
625
|
"verification.commandSetHash": command_set_hash,
|
|
625
626
|
"verification.ledgerHash": ledger_hash,
|
|
626
627
|
"verification.toolchainHashes": verification.get("toolchainHashes"),
|
|
@@ -1047,6 +1048,14 @@ def certify_local_candidate(
|
|
|
1047
1048
|
f"ledger={recorded_tree_hash} current={current_tree_hash}"
|
|
1048
1049
|
)
|
|
1049
1050
|
product_tree_hash = current_tree_hash
|
|
1051
|
+
environment_hashes = sorted(
|
|
1052
|
+
{str(item["environmentHash"]) for item in selected}
|
|
1053
|
+
)
|
|
1054
|
+
subject_environment_hash = (
|
|
1055
|
+
environment_hashes[0]
|
|
1056
|
+
if len(environment_hashes) == 1
|
|
1057
|
+
else _candidate_value_hash(environment_hashes)
|
|
1058
|
+
)
|
|
1050
1059
|
|
|
1051
1060
|
receipt = {
|
|
1052
1061
|
"schemaVersion": 2,
|
|
@@ -1057,6 +1066,7 @@ def certify_local_candidate(
|
|
|
1057
1066
|
"subject": {
|
|
1058
1067
|
"productCommit": product_commit,
|
|
1059
1068
|
"productTreeHash": product_tree_hash,
|
|
1069
|
+
"environmentHash": subject_environment_hash,
|
|
1060
1070
|
},
|
|
1061
1071
|
"verification": {
|
|
1062
1072
|
"requiredValidations": required,
|
|
@@ -1068,9 +1078,7 @@ def certify_local_candidate(
|
|
|
1068
1078
|
"toolchainHashes": sorted(
|
|
1069
1079
|
{str(item["toolchainHash"]) for item in selected}
|
|
1070
1080
|
),
|
|
1071
|
-
"environmentHashes":
|
|
1072
|
-
{str(item["environmentHash"]) for item in selected}
|
|
1073
|
-
),
|
|
1081
|
+
"environmentHashes": environment_hashes,
|
|
1074
1082
|
"dependencyHashes": sorted(
|
|
1075
1083
|
{str(item["inputsHash"]) for item in selected}
|
|
1076
1084
|
),
|
|
@@ -1495,6 +1503,14 @@ def build_workflow_timing(
|
|
|
1495
1503
|
started = started_dt.isoformat() if started_dt else None
|
|
1496
1504
|
cutoff = cutoff_dt.isoformat() if cutoff_dt else cutoff_text
|
|
1497
1505
|
|
|
1506
|
+
def elapsed_ms(start: Any, end: Any) -> int:
|
|
1507
|
+
delta = end - start
|
|
1508
|
+
total_microseconds = (
|
|
1509
|
+
(delta.days * 86_400 + delta.seconds) * 1_000_000
|
|
1510
|
+
+ delta.microseconds
|
|
1511
|
+
)
|
|
1512
|
+
return max(0, total_microseconds // 1_000)
|
|
1513
|
+
|
|
1498
1514
|
def clipped_interval(
|
|
1499
1515
|
start_value: Any,
|
|
1500
1516
|
end_value: Any,
|
|
@@ -1527,7 +1543,7 @@ def build_workflow_timing(
|
|
|
1527
1543
|
return sum(
|
|
1528
1544
|
max(
|
|
1529
1545
|
0,
|
|
1530
|
-
|
|
1546
|
+
elapsed_ms(interval_start, interval_end),
|
|
1531
1547
|
)
|
|
1532
1548
|
for interval_start, interval_end in merged
|
|
1533
1549
|
)
|
|
@@ -1628,7 +1644,7 @@ def build_workflow_timing(
|
|
|
1628
1644
|
for segment_start, segment_end in zip(boundaries, boundaries[1:]):
|
|
1629
1645
|
milliseconds = max(
|
|
1630
1646
|
0,
|
|
1631
|
-
|
|
1647
|
+
elapsed_ms(segment_start, segment_end),
|
|
1632
1648
|
)
|
|
1633
1649
|
if covered(segment_start, segment_end, active_intervals):
|
|
1634
1650
|
categories["attributed"] += milliseconds
|
|
@@ -1640,7 +1656,7 @@ def build_workflow_timing(
|
|
|
1640
1656
|
categories["unattributed"] += milliseconds
|
|
1641
1657
|
|
|
1642
1658
|
workflow_wall = (
|
|
1643
|
-
|
|
1659
|
+
elapsed_ms(started_dt, cutoff_dt)
|
|
1644
1660
|
if started_dt is not None and cutoff_dt is not None
|
|
1645
1661
|
else 0
|
|
1646
1662
|
)
|
|
@@ -1660,9 +1676,7 @@ def build_workflow_timing(
|
|
|
1660
1676
|
"session": len(sessions) + 1,
|
|
1661
1677
|
"startedAt": session_start.isoformat(),
|
|
1662
1678
|
"endedAt": pause_start_dt.isoformat(),
|
|
1663
|
-
"wallClockMs":
|
|
1664
|
-
(pause_start_dt - session_start).total_seconds() * 1000
|
|
1665
|
-
),
|
|
1679
|
+
"wallClockMs": elapsed_ms(session_start, pause_start_dt),
|
|
1666
1680
|
"terminalStatus": "PAUSED",
|
|
1667
1681
|
}
|
|
1668
1682
|
)
|
|
@@ -1677,9 +1691,7 @@ def build_workflow_timing(
|
|
|
1677
1691
|
"session": len(sessions) + 1,
|
|
1678
1692
|
"startedAt": session_start.isoformat(),
|
|
1679
1693
|
"endedAt": cutoff_dt.isoformat(),
|
|
1680
|
-
"wallClockMs":
|
|
1681
|
-
(cutoff_dt - session_start).total_seconds() * 1000
|
|
1682
|
-
),
|
|
1694
|
+
"wallClockMs": elapsed_ms(session_start, cutoff_dt),
|
|
1683
1695
|
"terminalStatus": "CUTOFF",
|
|
1684
1696
|
}
|
|
1685
1697
|
)
|
|
@@ -82,6 +82,63 @@ REQUIRED_COVERAGE = {
|
|
|
82
82
|
_EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
|
83
83
|
|
|
84
84
|
|
|
85
|
+
def resolve_verification_target(
|
|
86
|
+
verification: str,
|
|
87
|
+
project_root: Path | None,
|
|
88
|
+
) -> dict[str, Any] | None:
|
|
89
|
+
"""Resolve a built-in or project-declared profile-v3 verification target."""
|
|
90
|
+
if not isinstance(verification, str) or not re.fullmatch(
|
|
91
|
+
r"[A-Za-z][A-Za-z0-9_-]{0,63}",
|
|
92
|
+
verification,
|
|
93
|
+
):
|
|
94
|
+
return None
|
|
95
|
+
if project_root is not None:
|
|
96
|
+
profile = harness_profile.load_profile(project_root)
|
|
97
|
+
graph = (
|
|
98
|
+
profile.get("verificationGraph")
|
|
99
|
+
if isinstance(profile, dict)
|
|
100
|
+
else None
|
|
101
|
+
)
|
|
102
|
+
targets = graph.get("targets") if isinstance(graph, dict) else None
|
|
103
|
+
target = targets.get(verification) if isinstance(targets, dict) else None
|
|
104
|
+
if isinstance(target, dict):
|
|
105
|
+
required = str(target.get("requiredCoverage") or "module")
|
|
106
|
+
if required not in COVERAGE_RANK:
|
|
107
|
+
return None
|
|
108
|
+
return {**target, "requiredCoverage": required}
|
|
109
|
+
if verification in VERIFICATIONS:
|
|
110
|
+
required_rank = REQUIRED_COVERAGE.get(verification, 1)
|
|
111
|
+
required = next(
|
|
112
|
+
(
|
|
113
|
+
name
|
|
114
|
+
for name, rank in COVERAGE_RANK.items()
|
|
115
|
+
if rank == required_rank
|
|
116
|
+
),
|
|
117
|
+
"module",
|
|
118
|
+
)
|
|
119
|
+
return {
|
|
120
|
+
"commandKey": verification,
|
|
121
|
+
"dependsOn": [],
|
|
122
|
+
"requiredCoverage": required,
|
|
123
|
+
"candidate": verification == "unitTestFull",
|
|
124
|
+
"requiredCapabilities": [],
|
|
125
|
+
}
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def verification_target_identity(
|
|
130
|
+
verification: str,
|
|
131
|
+
target: dict[str, Any],
|
|
132
|
+
) -> str:
|
|
133
|
+
payload = json.dumps(
|
|
134
|
+
{"verification": verification, "target": target},
|
|
135
|
+
ensure_ascii=False,
|
|
136
|
+
sort_keys=True,
|
|
137
|
+
separators=(",", ":"),
|
|
138
|
+
).encode("utf-8")
|
|
139
|
+
return "sha256:" + hashlib.sha256(payload).hexdigest()
|
|
140
|
+
|
|
141
|
+
|
|
85
142
|
def now_iso() -> str:
|
|
86
143
|
return dt.datetime.now().astimezone().isoformat(timespec="milliseconds")
|
|
87
144
|
|
|
@@ -1075,6 +1132,8 @@ def decide_can_reuse(
|
|
|
1075
1132
|
requested_profile_hash: str | None = None,
|
|
1076
1133
|
requested_environment_hash: str | None = None,
|
|
1077
1134
|
requested_db_schema_hash: str | None = None,
|
|
1135
|
+
requested_target_identity: str | None = None,
|
|
1136
|
+
required_coverage: str | None = None,
|
|
1078
1137
|
project_root: Path | str | None = None,
|
|
1079
1138
|
) -> dict[str, Any]:
|
|
1080
1139
|
ledger, ledger_path = load_ledger(change_dir)
|
|
@@ -1136,6 +1195,7 @@ def decide_can_reuse(
|
|
|
1136
1195
|
scope = entry.get("scope")
|
|
1137
1196
|
algorithm_version = entry.get("algorithmVersion")
|
|
1138
1197
|
coverage = entry.get("coverage")
|
|
1198
|
+
stored_target_identity = entry.get("targetIdentity")
|
|
1139
1199
|
|
|
1140
1200
|
if entry.get("reusable") is False or isinstance(entry.get("invalidation"), dict):
|
|
1141
1201
|
return {
|
|
@@ -1198,7 +1258,11 @@ def decide_can_reuse(
|
|
|
1198
1258
|
# Coverage lattice: recorded coverage rank must meet the verification's
|
|
1199
1259
|
# required rank. Stops incremental evidence satisfying a module/full gate
|
|
1200
1260
|
# (UT-015 / API-005).
|
|
1201
|
-
required =
|
|
1261
|
+
required = (
|
|
1262
|
+
COVERAGE_RANK.get(required_coverage, 1)
|
|
1263
|
+
if required_coverage is not None
|
|
1264
|
+
else REQUIRED_COVERAGE.get(verification, 1)
|
|
1265
|
+
)
|
|
1202
1266
|
if COVERAGE_RANK.get(str(coverage).strip(), -1) < required:
|
|
1203
1267
|
return {
|
|
1204
1268
|
"ok": True,
|
|
@@ -1211,6 +1275,31 @@ def decide_can_reuse(
|
|
|
1211
1275
|
"stored_coverage": coverage,
|
|
1212
1276
|
}
|
|
1213
1277
|
|
|
1278
|
+
if _nonempty_str(requested_target_identity):
|
|
1279
|
+
if not _nonempty_str(stored_target_identity):
|
|
1280
|
+
return {
|
|
1281
|
+
"ok": True,
|
|
1282
|
+
"reuse": False,
|
|
1283
|
+
"reason": "insufficient-evidence",
|
|
1284
|
+
"code": "MISSING_TARGET_IDENTITY",
|
|
1285
|
+
"verification": verification,
|
|
1286
|
+
"detail": "recorded evidence predates the current verification target identity",
|
|
1287
|
+
"ledger_path": str(ledger_path) if ledger_path else None,
|
|
1288
|
+
"requested_target_identity": requested_target_identity,
|
|
1289
|
+
}
|
|
1290
|
+
if str(stored_target_identity).strip() != str(requested_target_identity).strip():
|
|
1291
|
+
return {
|
|
1292
|
+
"ok": True,
|
|
1293
|
+
"reuse": False,
|
|
1294
|
+
"reason": "rerun",
|
|
1295
|
+
"code": "TARGET_IDENTITY_CHANGED",
|
|
1296
|
+
"verification": verification,
|
|
1297
|
+
"detail": "verification target definition changed",
|
|
1298
|
+
"ledger_path": str(ledger_path) if ledger_path else None,
|
|
1299
|
+
"stored_target_identity": stored_target_identity,
|
|
1300
|
+
"requested_target_identity": requested_target_identity,
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1214
1303
|
if requested_command is not None and str(requested_command).strip():
|
|
1215
1304
|
if str(command).strip() != str(requested_command).strip():
|
|
1216
1305
|
return {
|
|
@@ -1352,6 +1441,7 @@ def upsert_verification_graph_node(
|
|
|
1352
1441
|
environment_hash: str | None = None,
|
|
1353
1442
|
db_schema_hash: str | None = None,
|
|
1354
1443
|
diff_hash: str | None = None,
|
|
1444
|
+
target_identity: str | None = None,
|
|
1355
1445
|
) -> dict[str, Any]:
|
|
1356
1446
|
"""Persist a verification graph node keyed by canonical identity (H-9)."""
|
|
1357
1447
|
path = verification_graph_path(change_dir)
|
|
@@ -1376,6 +1466,7 @@ def upsert_verification_graph_node(
|
|
|
1376
1466
|
"environmentHash": environment_hash,
|
|
1377
1467
|
"dbSchemaHash": db_schema_hash,
|
|
1378
1468
|
"diffHash": diff_hash,
|
|
1469
|
+
"targetIdentity": target_identity,
|
|
1379
1470
|
}
|
|
1380
1471
|
node = {
|
|
1381
1472
|
"identity": identity,
|
|
@@ -1427,16 +1518,19 @@ def cmd_can_reuse(args: argparse.Namespace) -> int:
|
|
|
1427
1518
|
as_json = bool(args.json)
|
|
1428
1519
|
verbose = bool(getattr(args, "verbose", False))
|
|
1429
1520
|
verification = args.verification
|
|
1430
|
-
if verification not in VERIFICATIONS:
|
|
1431
|
-
return emit_error(
|
|
1432
|
-
f"unsupported verification: {verification}; expected one of {sorted(VERIFICATIONS)}",
|
|
1433
|
-
as_json=as_json,
|
|
1434
|
-
)
|
|
1435
1521
|
change_dir = resolve_path(args.change_dir)
|
|
1436
1522
|
try:
|
|
1437
1523
|
files, project_root = input_files_from_args(args)
|
|
1438
1524
|
except (OSError, ValueError) as exc:
|
|
1439
1525
|
return emit_error(f"can-reuse failed: {exc}", as_json=as_json)
|
|
1526
|
+
target = resolve_verification_target(verification, project_root)
|
|
1527
|
+
if target is None:
|
|
1528
|
+
return emit_error(
|
|
1529
|
+
"unsupported verification: "
|
|
1530
|
+
f"{verification}; declare it in build-profile.json "
|
|
1531
|
+
"verificationGraph.targets",
|
|
1532
|
+
as_json=as_json,
|
|
1533
|
+
)
|
|
1440
1534
|
profile_input = getattr(args, "profile_input", None)
|
|
1441
1535
|
project_raw = getattr(args, "project", None)
|
|
1442
1536
|
if profile_input:
|
|
@@ -1474,6 +1568,10 @@ def cmd_can_reuse(args: argparse.Namespace) -> int:
|
|
|
1474
1568
|
requested_profile_hash=getattr(args, "profile_hash", None),
|
|
1475
1569
|
requested_environment_hash=getattr(args, "environment_hash", None),
|
|
1476
1570
|
requested_db_schema_hash=getattr(args, "db_schema_hash", None),
|
|
1571
|
+
requested_target_identity=verification_target_identity(
|
|
1572
|
+
verification, target
|
|
1573
|
+
),
|
|
1574
|
+
required_coverage=str(target["requiredCoverage"]),
|
|
1477
1575
|
project_root=project_root,
|
|
1478
1576
|
)
|
|
1479
1577
|
except (OSError, ValueError, json.JSONDecodeError) as exc:
|
|
@@ -1492,11 +1590,6 @@ def cmd_record(args: argparse.Namespace) -> int:
|
|
|
1492
1590
|
verbose = bool(getattr(args, "verbose", False))
|
|
1493
1591
|
change_dir = resolve_path(args.change_dir)
|
|
1494
1592
|
verification = args.verification
|
|
1495
|
-
if verification not in VERIFICATIONS:
|
|
1496
|
-
return emit_error(
|
|
1497
|
-
f"unsupported verification: {verification}; expected one of {sorted(VERIFICATIONS)}",
|
|
1498
|
-
as_json=as_json,
|
|
1499
|
-
)
|
|
1500
1593
|
contract_v2 = _contract_is_v2(change_dir)
|
|
1501
1594
|
if not contract_v2 and any(
|
|
1502
1595
|
_nonempty_str(getattr(args, field, None))
|
|
@@ -1510,6 +1603,14 @@ def cmd_record(args: argparse.Namespace) -> int:
|
|
|
1510
1603
|
files, project_root = input_files_from_args(args)
|
|
1511
1604
|
except (OSError, ValueError) as exc:
|
|
1512
1605
|
return emit_error(f"record failed: {exc}", as_json=as_json)
|
|
1606
|
+
target = resolve_verification_target(verification, project_root)
|
|
1607
|
+
if target is None:
|
|
1608
|
+
return emit_error(
|
|
1609
|
+
"unsupported verification: "
|
|
1610
|
+
f"{verification}; declare it in build-profile.json "
|
|
1611
|
+
"verificationGraph.targets",
|
|
1612
|
+
as_json=as_json,
|
|
1613
|
+
)
|
|
1513
1614
|
profile_input = getattr(args, "profile_input", None)
|
|
1514
1615
|
project_raw = getattr(args, "project", None)
|
|
1515
1616
|
if profile_input:
|
|
@@ -1610,6 +1711,9 @@ def cmd_record(args: argparse.Namespace) -> int:
|
|
|
1610
1711
|
# toolchain/profile/environment hashes. v1 entries missing these are
|
|
1611
1712
|
# conservatively invalidated by can-reuse (COM-002).
|
|
1612
1713
|
entry["algorithmVersion"] = LEDGER_VERSION
|
|
1714
|
+
entry["targetIdentity"] = verification_target_identity(
|
|
1715
|
+
verification, target
|
|
1716
|
+
)
|
|
1613
1717
|
coverage = getattr(args, "coverage", None)
|
|
1614
1718
|
if not (_nonempty_str(coverage) and str(coverage).strip() in COVERAGE_RANK):
|
|
1615
1719
|
coverage = derive_coverage(verification, args.scope)
|
|
@@ -1757,6 +1861,11 @@ def cmd_record(args: argparse.Namespace) -> int:
|
|
|
1757
1861
|
if _nonempty_str(ledger.get("diffHash"))
|
|
1758
1862
|
else None
|
|
1759
1863
|
),
|
|
1864
|
+
target_identity=(
|
|
1865
|
+
str(entry.get("targetIdentity")).strip()
|
|
1866
|
+
if _nonempty_str(entry.get("targetIdentity"))
|
|
1867
|
+
else None
|
|
1868
|
+
),
|
|
1760
1869
|
)
|
|
1761
1870
|
except (OSError, ValueError, TypeError):
|
|
1762
1871
|
# Graph is advisory persistence; ledger write already succeeded.
|
|
@@ -1832,7 +1941,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1832
1941
|
p_reuse.add_argument(
|
|
1833
1942
|
"--verification",
|
|
1834
1943
|
required=True,
|
|
1835
|
-
|
|
1944
|
+
help="built-in or build-profile v3 verificationGraph target",
|
|
1836
1945
|
)
|
|
1837
1946
|
p_reuse.add_argument(
|
|
1838
1947
|
"--files",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Harness preflight: build-profile detect/check + quirk recording + agent precheck.
|
|
3
3
|
|
|
4
|
-
变更簇 4:detect/check 委托 ``harness_profile``(
|
|
4
|
+
变更簇 4:detect/check 委托 ``harness_profile``(Build Profile v3 公共内核),不再保留
|
|
5
5
|
v1 重复探测逻辑与 ``buildCommands`` 扁平字符串。record-quirk 适配 v2 ``commands``
|
|
6
6
|
结构:``fix-command`` 写 ``source=user`` override(spec §3.1 显式保留),跨 detect
|
|
7
7
|
保留;``skip-not-block`` 仍写 ``knownPreexistingErrors``。check-agents 与 pitfalls
|
|
@@ -51,7 +51,7 @@ def emit_json(payload: dict[str, Any], *, ok: bool = True) -> int:
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
# ---------------------------------------------------------------------------
|
|
54
|
-
# detect / check — 委托 harness_profile(
|
|
54
|
+
# detect / check — 委托 harness_profile(Build Profile v3 公共内核)
|
|
55
55
|
# ---------------------------------------------------------------------------
|
|
56
56
|
|
|
57
57
|
def cmd_detect(project: Path) -> dict[str, Any]:
|