@hunter-harness/workflow-harness 0.2.25 → 0.2.27
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-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 +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 +9 -4
- package/harness/bundles/general/claude-code/harness-sync/reference.md +40 -3
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +96 -12
- package/harness/bundles/general/claude-code/scripts/harness_change.py +8 -3
- package/harness/bundles/general/claude-code/scripts/harness_events.py +14 -0
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +39 -1
- package/harness/bundles/general/claude-code/scripts/harness_integration.py +31 -6
- 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-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 +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 +9 -4
- package/harness/bundles/general/codebuddy/harness-sync/reference.md +40 -3
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +96 -12
- package/harness/bundles/general/codebuddy/scripts/harness_change.py +8 -3
- package/harness/bundles/general/codebuddy/scripts/harness_events.py +14 -0
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +39 -1
- package/harness/bundles/general/codebuddy/scripts/harness_integration.py +31 -6
- 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-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 +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 +9 -4
- package/harness/bundles/general/codex/harness-sync/reference.md +40 -3
- package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codex/scripts/harness_archive.py +96 -12
- package/harness/bundles/general/codex/scripts/harness_change.py +8 -3
- package/harness/bundles/general/codex/scripts/harness_events.py +14 -0
- package/harness/bundles/general/codex/scripts/harness_gate.py +39 -1
- package/harness/bundles/general/codex/scripts/harness_integration.py +31 -6
- 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-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 +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 +9 -4
- package/harness/bundles/general/cursor/harness-sync/reference.md +40 -3
- package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/cursor/scripts/harness_archive.py +96 -12
- package/harness/bundles/general/cursor/scripts/harness_change.py +8 -3
- package/harness/bundles/general/cursor/scripts/harness_events.py +14 -0
- package/harness/bundles/general/cursor/scripts/harness_gate.py +39 -1
- package/harness/bundles/general/cursor/scripts/harness_integration.py +31 -6
- 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-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-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 +9 -4
- package/harness/bundles/java/claude-code/harness-sync/reference.md +40 -3
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +96 -12
- package/harness/bundles/java/claude-code/scripts/harness_change.py +8 -3
- package/harness/bundles/java/claude-code/scripts/harness_events.py +14 -0
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +39 -1
- package/harness/bundles/java/claude-code/scripts/harness_integration.py +31 -6
- 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-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-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 +9 -4
- package/harness/bundles/java/codebuddy/harness-sync/reference.md +40 -3
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +96 -12
- package/harness/bundles/java/codebuddy/scripts/harness_change.py +8 -3
- package/harness/bundles/java/codebuddy/scripts/harness_events.py +14 -0
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +39 -1
- package/harness/bundles/java/codebuddy/scripts/harness_integration.py +31 -6
- 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-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-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 +9 -4
- package/harness/bundles/java/codex/harness-sync/reference.md +40 -3
- package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codex/scripts/harness_archive.py +96 -12
- package/harness/bundles/java/codex/scripts/harness_change.py +8 -3
- package/harness/bundles/java/codex/scripts/harness_events.py +14 -0
- package/harness/bundles/java/codex/scripts/harness_gate.py +39 -1
- package/harness/bundles/java/codex/scripts/harness_integration.py +31 -6
- 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-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-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 +9 -4
- package/harness/bundles/java/cursor/harness-sync/reference.md +40 -3
- package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/cursor/scripts/harness_archive.py +96 -12
- package/harness/bundles/java/cursor/scripts/harness_change.py +8 -3
- package/harness/bundles/java/cursor/scripts/harness_events.py +14 -0
- package/harness/bundles/java/cursor/scripts/harness_gate.py +39 -1
- package/harness/bundles/java/cursor/scripts/harness_integration.py +31 -6
- package/harness/manifests/general/claude-code.json +18 -18
- package/harness/manifests/general/codebuddy.json +18 -18
- package/harness/manifests/general/codex.json +18 -18
- package/harness/manifests/general/cursor.json +18 -18
- package/harness/manifests/java/claude-code.json +20 -20
- package/harness/manifests/java/codebuddy.json +20 -20
- package/harness/manifests/java/codex.json +20 -20
- package/harness/manifests/java/cursor.json +20 -20
- package/hunter-workflow-family.json +2 -2
- package/package.json +1 -1
|
@@ -1047,13 +1047,30 @@ def build_workflow_timing(
|
|
|
1047
1047
|
started = str(stamps[0]) if stamps else None
|
|
1048
1048
|
cutoff = report_cutoff_at or (str(stamps[-1]) if stamps else None)
|
|
1049
1049
|
stage_active = 0
|
|
1050
|
-
|
|
1050
|
+
stage_intervals: list[tuple[Any, Any]] = []
|
|
1051
1051
|
unclosed = 0
|
|
1052
1052
|
for _phase, phase_events in he.group_events_by_phase(events):
|
|
1053
1053
|
timing = he.canonical_phase_timing(phase_events, cutoff_ts=cutoff)
|
|
1054
1054
|
stage_active += int(timing.get("activeExecutionMs") or 0)
|
|
1055
|
-
stage_wall += int(timing.get("wallClockSpanMs") or 0)
|
|
1056
1055
|
unclosed += int(timing.get("unclosedAttemptCount") or 0)
|
|
1056
|
+
phase_stamps = [
|
|
1057
|
+
he.parse_timestamp(event.get("timestamp"))
|
|
1058
|
+
for event in phase_events
|
|
1059
|
+
if event.get("timestamp")
|
|
1060
|
+
]
|
|
1061
|
+
phase_stamps = [stamp for stamp in phase_stamps if stamp is not None]
|
|
1062
|
+
if phase_stamps:
|
|
1063
|
+
stage_intervals.append((min(phase_stamps), max(phase_stamps)))
|
|
1064
|
+
merged_intervals: list[list[Any]] = []
|
|
1065
|
+
for interval_start, interval_end in sorted(stage_intervals):
|
|
1066
|
+
if not merged_intervals or interval_start > merged_intervals[-1][1]:
|
|
1067
|
+
merged_intervals.append([interval_start, interval_end])
|
|
1068
|
+
else:
|
|
1069
|
+
merged_intervals[-1][1] = max(merged_intervals[-1][1], interval_end)
|
|
1070
|
+
stage_wall = sum(
|
|
1071
|
+
max(0, int((interval_end - interval_start).total_seconds() * 1000))
|
|
1072
|
+
for interval_start, interval_end in merged_intervals
|
|
1073
|
+
)
|
|
1057
1074
|
workflow_wall = he.duration_ms_between(started, cutoff) if started and cutoff else 0
|
|
1058
1075
|
external = 0
|
|
1059
1076
|
for event in events:
|
|
@@ -1817,14 +1834,26 @@ def _ledger_api_tests(
|
|
|
1817
1834
|
counted = False
|
|
1818
1835
|
|
|
1819
1836
|
metrics = api.get("metrics")
|
|
1820
|
-
|
|
1821
|
-
|
|
1837
|
+
normalized_metrics = (
|
|
1838
|
+
{str(key).lower(): value for key, value in metrics.items()}
|
|
1839
|
+
if isinstance(metrics, dict)
|
|
1840
|
+
else {}
|
|
1841
|
+
)
|
|
1842
|
+
if any(
|
|
1843
|
+
k in normalized_metrics
|
|
1844
|
+
for k in ("total", "passed", "pass", "failed", "fail", "blocked")
|
|
1822
1845
|
):
|
|
1823
|
-
passed = int(
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1846
|
+
passed = int(
|
|
1847
|
+
normalized_metrics.get("passed", normalized_metrics.get("pass", 0)) or 0
|
|
1848
|
+
)
|
|
1849
|
+
failed = int(
|
|
1850
|
+
normalized_metrics.get("failed", normalized_metrics.get("fail", 0)) or 0
|
|
1851
|
+
)
|
|
1852
|
+
blocked = int(normalized_metrics.get("blocked", 0) or 0)
|
|
1853
|
+
total = int(
|
|
1854
|
+
normalized_metrics.get("total", passed + failed + blocked) or 0
|
|
1855
|
+
)
|
|
1856
|
+
pass_rate = normalized_metrics.get("passrate")
|
|
1828
1857
|
source = "committed"
|
|
1829
1858
|
counted = total > 0 or passed > 0 or failed > 0 or blocked > 0
|
|
1830
1859
|
|
|
@@ -2191,8 +2220,12 @@ def _artifacts_from_events(
|
|
|
2191
2220
|
raw_path = str(e.get("path") or "")
|
|
2192
2221
|
archived_path = raw_path
|
|
2193
2222
|
if change_dir is not None and raw_path:
|
|
2223
|
+
normalized = raw_path.replace("\\", "/")
|
|
2224
|
+
same_change_prefix = f".harness/changes/{change_dir.name}/"
|
|
2225
|
+
if normalized.startswith(same_change_prefix):
|
|
2226
|
+
archived_path = normalized[len(same_change_prefix):]
|
|
2194
2227
|
product_copy = change_dir / "artifacts" / "product" / raw_path
|
|
2195
|
-
if not (change_dir / raw_path).is_file() and product_copy.is_file():
|
|
2228
|
+
if archived_path == raw_path and not (change_dir / raw_path).is_file() and product_copy.is_file():
|
|
2196
2229
|
archived_path = product_copy.relative_to(change_dir).as_posix()
|
|
2197
2230
|
out.append(
|
|
2198
2231
|
{
|
|
@@ -2618,6 +2651,37 @@ def _review_summary(
|
|
|
2618
2651
|
merged = dict(base)
|
|
2619
2652
|
merged.update(existing["reviewSummary"])
|
|
2620
2653
|
return merged
|
|
2654
|
+
reports = find_review_reports(change_dir)
|
|
2655
|
+
if reports:
|
|
2656
|
+
labels: set[tuple[str, str]] = set()
|
|
2657
|
+
pattern = re.compile(
|
|
2658
|
+
r"(?im)^\s{0,3}(?:#{1,6}\s*)?(?:[-*]\s*)?(?:\*\*)?"
|
|
2659
|
+
r"(RED|YELLOW)[-_\s]?(\d+)\b"
|
|
2660
|
+
)
|
|
2661
|
+
for report in reports:
|
|
2662
|
+
try:
|
|
2663
|
+
text = report.read_text(encoding="utf-8-sig")
|
|
2664
|
+
except OSError:
|
|
2665
|
+
continue
|
|
2666
|
+
labels.update(
|
|
2667
|
+
(match.group(1).upper(), match.group(2))
|
|
2668
|
+
for match in pattern.finditer(text)
|
|
2669
|
+
)
|
|
2670
|
+
red = sum(1 for severity, _ in labels if severity == "RED")
|
|
2671
|
+
yellow = sum(1 for severity, _ in labels if severity == "YELLOW")
|
|
2672
|
+
base.update(
|
|
2673
|
+
{
|
|
2674
|
+
"status": "ADVISORY_UNSTRUCTURED",
|
|
2675
|
+
"red": red,
|
|
2676
|
+
"yellow": yellow,
|
|
2677
|
+
"redConfirmed": red,
|
|
2678
|
+
"summary": (
|
|
2679
|
+
"structured review findings missing; counts inferred from "
|
|
2680
|
+
f"{len(reports)} markdown report(s)"
|
|
2681
|
+
),
|
|
2682
|
+
}
|
|
2683
|
+
)
|
|
2684
|
+
return base
|
|
2621
2685
|
if not review_evidence_present(change_dir, events):
|
|
2622
2686
|
base["status"] = "ADVISORY_NOT_RUN"
|
|
2623
2687
|
return base
|
|
@@ -4317,9 +4381,9 @@ def cmd_finalize(
|
|
|
4317
4381
|
if resolved_state_dir.resolve() != original_change_dir.resolve()
|
|
4318
4382
|
else None
|
|
4319
4383
|
)
|
|
4320
|
-
operation_id = f"
|
|
4384
|
+
operation_id = f"a-{uuid.uuid4().hex[:12]}"
|
|
4321
4385
|
operation_root = project_root / ".harness" / "archive-operations"
|
|
4322
|
-
operation_temp_dir = operation_root / "staging" / operation_id /
|
|
4386
|
+
operation_temp_dir = operation_root / "staging" / operation_id / "c"
|
|
4323
4387
|
operation_record = operation_root / f"{operation_id}.json"
|
|
4324
4388
|
|
|
4325
4389
|
def _restore_finalize_failure() -> None:
|
|
@@ -4378,12 +4442,32 @@ def cmd_finalize(
|
|
|
4378
4442
|
if not exact_byte["ok"]:
|
|
4379
4443
|
warnings.append(str(exact_byte["remediation"]))
|
|
4380
4444
|
|
|
4445
|
+
payload["steps"]["service_stop_before_staging"] = run_service_stop(
|
|
4446
|
+
original_change_dir
|
|
4447
|
+
)
|
|
4448
|
+
transient_names = {
|
|
4449
|
+
"node_modules",
|
|
4450
|
+
".venv",
|
|
4451
|
+
"venv",
|
|
4452
|
+
"__pycache__",
|
|
4453
|
+
".cache",
|
|
4454
|
+
"integration-temp",
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
def _ignore_archive_transients(_directory: str, names: list[str]) -> set[str]:
|
|
4458
|
+
return {
|
|
4459
|
+
name
|
|
4460
|
+
for name in names
|
|
4461
|
+
if name in transient_names or name.endswith(".lock")
|
|
4462
|
+
}
|
|
4463
|
+
|
|
4381
4464
|
try:
|
|
4382
4465
|
operation_temp_dir.parent.mkdir(parents=True, exist_ok=True)
|
|
4383
4466
|
shutil.copytree(
|
|
4384
4467
|
original_change_dir,
|
|
4385
4468
|
operation_temp_dir,
|
|
4386
4469
|
copy_function=shutil.copy2,
|
|
4470
|
+
ignore=_ignore_archive_transients,
|
|
4387
4471
|
)
|
|
4388
4472
|
write_json(
|
|
4389
4473
|
operation_record,
|
|
@@ -232,8 +232,13 @@ def read_concurrency_mode(project_root: Path) -> str:
|
|
|
232
232
|
``isolated-multi-active`` (allows multiple active Changes but all
|
|
233
233
|
Change-scoped commands require ``--change``).
|
|
234
234
|
"""
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
configs = [
|
|
236
|
+
project_root / ".harness" / "config" / "harness.json",
|
|
237
|
+
project_root / ".harness" / "config.json",
|
|
238
|
+
]
|
|
239
|
+
for cfg in configs:
|
|
240
|
+
if not cfg.is_file():
|
|
241
|
+
continue
|
|
237
242
|
try:
|
|
238
243
|
data = json.loads(cfg.read_text(encoding="utf-8"))
|
|
239
244
|
if isinstance(data, dict):
|
|
@@ -244,7 +249,7 @@ def read_concurrency_mode(project_root: Path) -> str:
|
|
|
244
249
|
}:
|
|
245
250
|
return mode
|
|
246
251
|
except (OSError, json.JSONDecodeError):
|
|
247
|
-
|
|
252
|
+
continue
|
|
248
253
|
return "single-active"
|
|
249
254
|
|
|
250
255
|
|
|
@@ -883,6 +883,15 @@ def split_phase_attempts(phase_events: list[dict[str, Any]]) -> list[dict[str, A
|
|
|
883
883
|
attempts: list[dict[str, Any]] = []
|
|
884
884
|
current: dict[str, Any] | None = None
|
|
885
885
|
next_attempt = 1
|
|
886
|
+
pre_start_metadata_types = {
|
|
887
|
+
"correction",
|
|
888
|
+
"decision",
|
|
889
|
+
"environment.wait",
|
|
890
|
+
"env.wait",
|
|
891
|
+
"external.wait",
|
|
892
|
+
"issue",
|
|
893
|
+
"ci.wait",
|
|
894
|
+
}
|
|
886
895
|
for event in phase_events:
|
|
887
896
|
if event.get("type") == "phase.start":
|
|
888
897
|
if current is not None:
|
|
@@ -900,6 +909,11 @@ def split_phase_attempts(phase_events: list[dict[str, Any]]) -> list[dict[str, A
|
|
|
900
909
|
if prior_type == "phase.end":
|
|
901
910
|
attempts[-1]["warnings"].append("event recorded after phase.end")
|
|
902
911
|
continue
|
|
912
|
+
if event.get("type") in pre_start_metadata_types:
|
|
913
|
+
# Decisions and diagnostics may be emitted while selecting or
|
|
914
|
+
# recovering a phase. They describe workflow context, not an
|
|
915
|
+
# execution attempt, so they must not manufacture an orphan.
|
|
916
|
+
continue
|
|
903
917
|
raw_attempt = event.get("attempt")
|
|
904
918
|
attempt = raw_attempt if isinstance(raw_attempt, int) and raw_attempt > 0 else next_attempt
|
|
905
919
|
next_attempt = max(next_attempt, attempt + 1)
|
|
@@ -1140,6 +1140,7 @@ def append_phase_event(
|
|
|
1140
1140
|
executor_tool: str | None = None,
|
|
1141
1141
|
executor_agent: str | None = None,
|
|
1142
1142
|
executor_model: str | None = None,
|
|
1143
|
+
code: str | None = None,
|
|
1143
1144
|
) -> dict[str, Any]:
|
|
1144
1145
|
events_file = he.events_path(change_dir)
|
|
1145
1146
|
existing = he.load_events(events_file)
|
|
@@ -1154,7 +1155,7 @@ def append_phase_event(
|
|
|
1154
1155
|
name=None,
|
|
1155
1156
|
path=None,
|
|
1156
1157
|
kind=None,
|
|
1157
|
-
code=
|
|
1158
|
+
code=code,
|
|
1158
1159
|
severity=None,
|
|
1159
1160
|
message=None,
|
|
1160
1161
|
decision=None,
|
|
@@ -1192,6 +1193,34 @@ def append_phase_event(
|
|
|
1192
1193
|
}
|
|
1193
1194
|
|
|
1194
1195
|
|
|
1196
|
+
def record_blocked_attempt(
|
|
1197
|
+
change_dir: Path,
|
|
1198
|
+
*,
|
|
1199
|
+
phase: str,
|
|
1200
|
+
code: str,
|
|
1201
|
+
message: str,
|
|
1202
|
+
run_id: str | None = None,
|
|
1203
|
+
) -> dict[str, Any]:
|
|
1204
|
+
"""Persist a rejected begin as a complete, zero-work attempt."""
|
|
1205
|
+
blocked_run_id = run_id or "blocked-" + uuid.uuid4().hex[:12]
|
|
1206
|
+
append_phase_event(
|
|
1207
|
+
change_dir,
|
|
1208
|
+
phase=phase,
|
|
1209
|
+
type_="phase.start",
|
|
1210
|
+
note=f"begin rejected: {code}",
|
|
1211
|
+
run_id=blocked_run_id,
|
|
1212
|
+
)
|
|
1213
|
+
return append_phase_event(
|
|
1214
|
+
change_dir,
|
|
1215
|
+
phase=phase,
|
|
1216
|
+
type_="phase.end",
|
|
1217
|
+
status="BLOCKED",
|
|
1218
|
+
note=message,
|
|
1219
|
+
run_id=blocked_run_id,
|
|
1220
|
+
code=code,
|
|
1221
|
+
)
|
|
1222
|
+
|
|
1223
|
+
|
|
1195
1224
|
def _phase_event_exists(change_dir: Path, phase: str, type_: str, run_id: str) -> bool:
|
|
1196
1225
|
return any(
|
|
1197
1226
|
event.get("phase") == phase
|
|
@@ -1279,6 +1308,15 @@ def cmd_begin(args: argparse.Namespace) -> int:
|
|
|
1279
1308
|
change_dir = Path(resolved["changeDir"])
|
|
1280
1309
|
concurrency_block = hc.check_concurrency_block(project, resolved["changeId"])
|
|
1281
1310
|
if concurrency_block is not None:
|
|
1311
|
+
record_blocked_attempt(
|
|
1312
|
+
change_dir,
|
|
1313
|
+
phase=args.phase,
|
|
1314
|
+
code=str(concurrency_block.get("code", "CONCURRENCY_BLOCKED")),
|
|
1315
|
+
message=str(
|
|
1316
|
+
concurrency_block.get("message", "concurrency mode blocked begin")
|
|
1317
|
+
),
|
|
1318
|
+
run_id=args.run_id or os.environ.get("HUNTER_HARNESS_RUN_ID"),
|
|
1319
|
+
)
|
|
1282
1320
|
return emit_error(
|
|
1283
1321
|
str(concurrency_block.get("code", "CONCURRENCY_BLOCKED")),
|
|
1284
1322
|
str(concurrency_block.get("message", "concurrency mode blocked begin")),
|
|
@@ -243,6 +243,26 @@ def _sanitize(value: str) -> str:
|
|
|
243
243
|
return re.sub(r"[^A-Za-z0-9._-]+", "-", value).strip("-") or "txn"
|
|
244
244
|
|
|
245
245
|
|
|
246
|
+
def _compact_transaction_id(change_id: str, run_id: str, *, limit: int = 48) -> str:
|
|
247
|
+
readable = f"{_sanitize(change_id)}-{_sanitize(run_id)}"
|
|
248
|
+
if len(readable) <= limit:
|
|
249
|
+
return readable
|
|
250
|
+
digest = hashlib.sha256(readable.encode("utf-8")).hexdigest()[:12]
|
|
251
|
+
prefix = _sanitize(change_id)[: max(8, limit - len(digest) - 1)]
|
|
252
|
+
return f"{prefix}-{digest}"
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def default_temp_root(project_root: Path) -> Path:
|
|
256
|
+
"""Use a deliberately short Windows worktree root to protect MAX_PATH."""
|
|
257
|
+
configured = os.environ.get("HUNTER_HARNESS_INTEGRATION_ROOT")
|
|
258
|
+
if configured:
|
|
259
|
+
return Path(configured).expanduser().resolve()
|
|
260
|
+
resolved = Path(project_root).resolve()
|
|
261
|
+
if os.name == "nt" and resolved.drive:
|
|
262
|
+
return Path(resolved.drive + os.sep) / "hh-int"
|
|
263
|
+
return resolved / ".harness" / "runtime" / "i"
|
|
264
|
+
|
|
265
|
+
|
|
246
266
|
def journal_dir(project_root: Path, transaction_id: str) -> Path:
|
|
247
267
|
return (
|
|
248
268
|
Path(project_root)
|
|
@@ -419,7 +439,7 @@ class IntegrationTransaction:
|
|
|
419
439
|
self.feature_branch = feature_branch
|
|
420
440
|
self.temp_root = Path(temp_root).resolve()
|
|
421
441
|
self.runner = runner or GitRunner()
|
|
422
|
-
self.transaction_id =
|
|
442
|
+
self.transaction_id = _compact_transaction_id(change_id, run_id)
|
|
423
443
|
self.temp_branch = f"harness/integration/{self.transaction_id}"
|
|
424
444
|
|
|
425
445
|
# ------------------------------------------------------------- journal
|
|
@@ -1592,13 +1612,18 @@ class IntegrationTransaction:
|
|
|
1592
1612
|
|
|
1593
1613
|
|
|
1594
1614
|
def _txn_from_args(args: argparse.Namespace) -> IntegrationTransaction:
|
|
1615
|
+
project_root = Path.cwd()
|
|
1595
1616
|
return IntegrationTransaction(
|
|
1596
|
-
project_root=
|
|
1617
|
+
project_root=project_root,
|
|
1597
1618
|
change_id=args.change,
|
|
1598
1619
|
run_id=args.run_id,
|
|
1599
1620
|
target_branch=args.target_branch,
|
|
1600
1621
|
feature_branch=args.feature_branch,
|
|
1601
|
-
temp_root=
|
|
1622
|
+
temp_root=(
|
|
1623
|
+
Path(args.temp_root)
|
|
1624
|
+
if getattr(args, "temp_root", None)
|
|
1625
|
+
else default_temp_root(project_root)
|
|
1626
|
+
),
|
|
1602
1627
|
)
|
|
1603
1628
|
|
|
1604
1629
|
|
|
@@ -1693,7 +1718,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1693
1718
|
p.add_argument("--run-id", required=True)
|
|
1694
1719
|
p.add_argument("--target-branch", default="main")
|
|
1695
1720
|
p.add_argument("--feature-branch", required=True)
|
|
1696
|
-
p.add_argument("--temp-root"
|
|
1721
|
+
p.add_argument("--temp-root")
|
|
1697
1722
|
p.set_defaults(func=func)
|
|
1698
1723
|
|
|
1699
1724
|
add("preflight", cmd_preflight)
|
|
@@ -1710,7 +1735,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1710
1735
|
p_journal.add_argument("--run-id", required=True)
|
|
1711
1736
|
p_journal.add_argument("--target-branch", default="main")
|
|
1712
1737
|
p_journal.add_argument("--feature-branch", required=True)
|
|
1713
|
-
p_journal.add_argument("--temp-root"
|
|
1738
|
+
p_journal.add_argument("--temp-root")
|
|
1714
1739
|
p_journal.add_argument(
|
|
1715
1740
|
"--verbose",
|
|
1716
1741
|
action="store_true",
|
|
@@ -1723,7 +1748,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1723
1748
|
p_verify.add_argument("--run-id", required=True)
|
|
1724
1749
|
p_verify.add_argument("--target-branch", default="main")
|
|
1725
1750
|
p_verify.add_argument("--feature-branch", required=True)
|
|
1726
|
-
p_verify.add_argument("--temp-root"
|
|
1751
|
+
p_verify.add_argument("--temp-root")
|
|
1727
1752
|
p_verify.add_argument("--command", action="append")
|
|
1728
1753
|
p_verify.add_argument(
|
|
1729
1754
|
"--timeout-seconds",
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"schema_version": 2,
|
|
3
3
|
"profile": "general",
|
|
4
4
|
"adapter": "claude-code",
|
|
5
|
-
"bundle_version": "0.2.
|
|
5
|
+
"bundle_version": "0.2.19",
|
|
6
6
|
"generator": "harness_deploy.py",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
9
9
|
"path": ".harness-build.json",
|
|
10
|
-
"sha256": "
|
|
10
|
+
"sha256": "9da5ac3cdc99fda652e0292657d77ff89590629cc95fea21c336d4782cd46eb2"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"path": "agents/harness-evaluator.md",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"path": "harness-archive/SKILL.md",
|
|
50
|
-
"sha256": "
|
|
50
|
+
"sha256": "535bd2ca8715fe6030b0d6280f260c637d0a70c00111ab3a5cf7bab7b2a4cfd5"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"path": "harness-archive/templates/render-summary.mjs",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
"path": "harness-codebase-map/SKILL.md",
|
|
70
|
-
"sha256": "
|
|
70
|
+
"sha256": "fb04db711353439594a5fb2acf5004e118cdff0c109f341bb2fb8976102f4cb9"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"path": "harness-codebase-map/templates/ARCHITECTURE.md",
|
|
@@ -131,11 +131,11 @@
|
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
"path": "harness-knowledge-ingest/SKILL.md",
|
|
134
|
-
"sha256": "
|
|
134
|
+
"sha256": "13310e20440e24bbfefed24342a6941935147d7f27219ead08d489cbf631fcb3"
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
137
|
"path": "harness-knowledge-query/SKILL.md",
|
|
138
|
-
"sha256": "
|
|
138
|
+
"sha256": "24db27e5577aeb98bde14d0c4e465b9b5635ff6bce2d12cb6a1bf0d331c08400"
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
"path": "harness-plan/checklist.md",
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
153
|
"path": "harness-plan/SKILL.md",
|
|
154
|
-
"sha256": "
|
|
154
|
+
"sha256": "bd8f3e11ada1156d01843e3316c76f8c41743bd0d60237dff9040681571339cb"
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
157
|
"path": "harness-review/checklist.md",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
169
|
"path": "harness-review/SKILL.md",
|
|
170
|
-
"sha256": "
|
|
170
|
+
"sha256": "4bf9ad4c922d0c02769aa378270cc40d161077d9d5954bc26ccafe70a0da8bfe"
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
"path": "harness-run/checklist.md",
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
"path": "harness-run/SKILL.md",
|
|
186
|
-
"sha256": "
|
|
186
|
+
"sha256": "d58739a0b8761e220a2d0887f2bae7eb8345ede23f078560a0acfde22a2f9718"
|
|
187
187
|
},
|
|
188
188
|
{
|
|
189
189
|
"path": "harness-submit/checklist.md",
|
|
@@ -195,15 +195,15 @@
|
|
|
195
195
|
},
|
|
196
196
|
{
|
|
197
197
|
"path": "harness-submit/SKILL.md",
|
|
198
|
-
"sha256": "
|
|
198
|
+
"sha256": "bb4d5a48576dacf199a29332828958a0bda56fd99b5348d9d7ef393e6de68b4e"
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
"path": "harness-sync/reference.md",
|
|
202
|
-
"sha256": "
|
|
202
|
+
"sha256": "24ab6641392f42aaf659a030f9cae910a303e2194675be8aab1bd2672ae49f8b"
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
205
|
"path": "harness-sync/SKILL.md",
|
|
206
|
-
"sha256": "
|
|
206
|
+
"sha256": "1392f31271625b56227487996aa6b596ca8aa2b4ba2b4dea478c0cda34bb3742"
|
|
207
207
|
},
|
|
208
208
|
{
|
|
209
209
|
"path": "harness-test/checklist.md",
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
229
|
"path": "harness-test/SKILL.md",
|
|
230
|
-
"sha256": "
|
|
230
|
+
"sha256": "17d8472e69d30f64d3e8623599234ce5a30a1b16b0312025ef7988b7a7a2de0c"
|
|
231
231
|
},
|
|
232
232
|
{
|
|
233
233
|
"path": "protocols/archive-report-protocol.md",
|
|
@@ -275,11 +275,11 @@
|
|
|
275
275
|
},
|
|
276
276
|
{
|
|
277
277
|
"path": "scripts/harness_archive.py",
|
|
278
|
-
"sha256": "
|
|
278
|
+
"sha256": "40c9cc17e3b42a92e4aa4ff7fb503cfb10e408c45d1b7cbb825001032a1e55a7"
|
|
279
279
|
},
|
|
280
280
|
{
|
|
281
281
|
"path": "scripts/harness_change.py",
|
|
282
|
-
"sha256": "
|
|
282
|
+
"sha256": "72d1030fdc77b26076b24553ef017a95eb095db16fc2e1b7aff837d76f9aae44"
|
|
283
283
|
},
|
|
284
284
|
{
|
|
285
285
|
"path": "scripts/harness_check_gate.py",
|
|
@@ -295,15 +295,15 @@
|
|
|
295
295
|
},
|
|
296
296
|
{
|
|
297
297
|
"path": "scripts/harness_events.py",
|
|
298
|
-
"sha256": "
|
|
298
|
+
"sha256": "5733a66e8512adcbdc7b9f00ef3cc63f43f865ba0cdb14687a16c133d678aa43"
|
|
299
299
|
},
|
|
300
300
|
{
|
|
301
301
|
"path": "scripts/harness_gate.py",
|
|
302
|
-
"sha256": "
|
|
302
|
+
"sha256": "abf0717cb8cf1f13b804458017483a981a64ebf812028353543b146be261b6ae"
|
|
303
303
|
},
|
|
304
304
|
{
|
|
305
305
|
"path": "scripts/harness_integration.py",
|
|
306
|
-
"sha256": "
|
|
306
|
+
"sha256": "e1c17bc19a0bdcb1cb6f3cfc0074c579ca2becc45712e7bce08b188b6b206184"
|
|
307
307
|
},
|
|
308
308
|
{
|
|
309
309
|
"path": "scripts/harness_ledger.py",
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"schema_version": 2,
|
|
3
3
|
"profile": "general",
|
|
4
4
|
"adapter": "codebuddy",
|
|
5
|
-
"bundle_version": "0.2.
|
|
5
|
+
"bundle_version": "0.2.19",
|
|
6
6
|
"generator": "harness_deploy.py",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
9
9
|
"path": ".harness-build.json",
|
|
10
|
-
"sha256": "
|
|
10
|
+
"sha256": "9d4b1dfb2aa7fa7c54b9c4b358ca9aa0331bc607bb49c5d7c06cb86ac130e11f"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"path": "agents/harness-evaluator.md",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"path": "harness-archive/SKILL.md",
|
|
50
|
-
"sha256": "
|
|
50
|
+
"sha256": "d670393d229d89551bc6d0dad18398fe66ac4dd89df90625355e1c2422e65bd4"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"path": "harness-archive/templates/render-summary.mjs",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
"path": "harness-codebase-map/SKILL.md",
|
|
70
|
-
"sha256": "
|
|
70
|
+
"sha256": "2d97af6dc0d2e2c404dcc5ee6d36c178f934caa0bdf1e8c6cdf355a7ad4c8ea0"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"path": "harness-codebase-map/templates/ARCHITECTURE.md",
|
|
@@ -131,11 +131,11 @@
|
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
"path": "harness-knowledge-ingest/SKILL.md",
|
|
134
|
-
"sha256": "
|
|
134
|
+
"sha256": "a8ebaf2f912ba6bcc9848110b41e6ceb6c3795dffcbdcb7fc9b5100b90223448"
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
137
|
"path": "harness-knowledge-query/SKILL.md",
|
|
138
|
-
"sha256": "
|
|
138
|
+
"sha256": "056bb8680ce112c7467916534205aebcdbc75262cf2e06200920d34bfbd15206"
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
"path": "harness-plan/checklist.md",
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
153
|
"path": "harness-plan/SKILL.md",
|
|
154
|
-
"sha256": "
|
|
154
|
+
"sha256": "0c9a084b1ff1c334fde922419a25b42aa327e38679707996073716f7d4051109"
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
157
|
"path": "harness-review/checklist.md",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
},
|
|
168
168
|
{
|
|
169
169
|
"path": "harness-review/SKILL.md",
|
|
170
|
-
"sha256": "
|
|
170
|
+
"sha256": "c067e963cc5c1de2deb6560b42aa90e59316afa0c9e832827c6e71533814ef99"
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
"path": "harness-run/checklist.md",
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
"path": "harness-run/SKILL.md",
|
|
186
|
-
"sha256": "
|
|
186
|
+
"sha256": "6a9ac90d6abb6ce3714b4c02db8c9714a09223bb5807e74b96f98b57ba476fd6"
|
|
187
187
|
},
|
|
188
188
|
{
|
|
189
189
|
"path": "harness-submit/checklist.md",
|
|
@@ -195,15 +195,15 @@
|
|
|
195
195
|
},
|
|
196
196
|
{
|
|
197
197
|
"path": "harness-submit/SKILL.md",
|
|
198
|
-
"sha256": "
|
|
198
|
+
"sha256": "75f2ba39db36b0cec51e8d41deb6f3bfad1f8efff09c2aface91d41d224036cb"
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
"path": "harness-sync/reference.md",
|
|
202
|
-
"sha256": "
|
|
202
|
+
"sha256": "24ab6641392f42aaf659a030f9cae910a303e2194675be8aab1bd2672ae49f8b"
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
205
|
"path": "harness-sync/SKILL.md",
|
|
206
|
-
"sha256": "
|
|
206
|
+
"sha256": "0919d763b16747d637d091400f8a511885f8a2162bed85926b8a90e32423b4e7"
|
|
207
207
|
},
|
|
208
208
|
{
|
|
209
209
|
"path": "harness-test/checklist.md",
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
229
|
"path": "harness-test/SKILL.md",
|
|
230
|
-
"sha256": "
|
|
230
|
+
"sha256": "3f742afb5343d7254a005c1b643f7678ca2b46a1f5da149016729850f40fe15e"
|
|
231
231
|
},
|
|
232
232
|
{
|
|
233
233
|
"path": "protocols/archive-report-protocol.md",
|
|
@@ -275,11 +275,11 @@
|
|
|
275
275
|
},
|
|
276
276
|
{
|
|
277
277
|
"path": "scripts/harness_archive.py",
|
|
278
|
-
"sha256": "
|
|
278
|
+
"sha256": "40c9cc17e3b42a92e4aa4ff7fb503cfb10e408c45d1b7cbb825001032a1e55a7"
|
|
279
279
|
},
|
|
280
280
|
{
|
|
281
281
|
"path": "scripts/harness_change.py",
|
|
282
|
-
"sha256": "
|
|
282
|
+
"sha256": "72d1030fdc77b26076b24553ef017a95eb095db16fc2e1b7aff837d76f9aae44"
|
|
283
283
|
},
|
|
284
284
|
{
|
|
285
285
|
"path": "scripts/harness_check_gate.py",
|
|
@@ -295,15 +295,15 @@
|
|
|
295
295
|
},
|
|
296
296
|
{
|
|
297
297
|
"path": "scripts/harness_events.py",
|
|
298
|
-
"sha256": "
|
|
298
|
+
"sha256": "5733a66e8512adcbdc7b9f00ef3cc63f43f865ba0cdb14687a16c133d678aa43"
|
|
299
299
|
},
|
|
300
300
|
{
|
|
301
301
|
"path": "scripts/harness_gate.py",
|
|
302
|
-
"sha256": "
|
|
302
|
+
"sha256": "abf0717cb8cf1f13b804458017483a981a64ebf812028353543b146be261b6ae"
|
|
303
303
|
},
|
|
304
304
|
{
|
|
305
305
|
"path": "scripts/harness_integration.py",
|
|
306
|
-
"sha256": "
|
|
306
|
+
"sha256": "e1c17bc19a0bdcb1cb6f3cfc0074c579ca2becc45712e7bce08b188b6b206184"
|
|
307
307
|
},
|
|
308
308
|
{
|
|
309
309
|
"path": "scripts/harness_ledger.py",
|