@hunter-harness/workflow-harness 0.2.38 → 0.2.39
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 +10 -7
- package/harness/bundles/general/claude-code/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/general/claude-code/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +446 -20
- package/harness/bundles/general/claude-code/scripts/harness_events.py +273 -21
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +56 -32
- package/harness/bundles/general/claude-code/scripts/harness_integration.py +197 -3
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +126 -2
- package/harness/bundles/general/claude-code/scripts/harness_report_model.py +28 -6
- package/harness/bundles/general/claude-code/scripts/harness_review.py +118 -17
- package/harness/bundles/general/claude-code/scripts/harness_service.py +219 -0
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +10 -7
- package/harness/bundles/general/codebuddy/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/general/codebuddy/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +446 -20
- package/harness/bundles/general/codebuddy/scripts/harness_events.py +273 -21
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +56 -32
- package/harness/bundles/general/codebuddy/scripts/harness_integration.py +197 -3
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +126 -2
- package/harness/bundles/general/codebuddy/scripts/harness_report_model.py +28 -6
- package/harness/bundles/general/codebuddy/scripts/harness_review.py +118 -17
- package/harness/bundles/general/codebuddy/scripts/harness_service.py +219 -0
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +10 -7
- package/harness/bundles/general/codex/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/general/codex/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/general/codex/scripts/harness_archive.py +446 -20
- package/harness/bundles/general/codex/scripts/harness_events.py +273 -21
- package/harness/bundles/general/codex/scripts/harness_gate.py +56 -32
- package/harness/bundles/general/codex/scripts/harness_integration.py +197 -3
- package/harness/bundles/general/codex/scripts/harness_ledger.py +126 -2
- package/harness/bundles/general/codex/scripts/harness_report_model.py +28 -6
- package/harness/bundles/general/codex/scripts/harness_review.py +118 -17
- package/harness/bundles/general/codex/scripts/harness_service.py +219 -0
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +10 -7
- package/harness/bundles/general/cursor/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/general/cursor/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/general/cursor/scripts/harness_archive.py +446 -20
- package/harness/bundles/general/cursor/scripts/harness_events.py +273 -21
- package/harness/bundles/general/cursor/scripts/harness_gate.py +56 -32
- package/harness/bundles/general/cursor/scripts/harness_integration.py +197 -3
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +126 -2
- package/harness/bundles/general/cursor/scripts/harness_report_model.py +28 -6
- package/harness/bundles/general/cursor/scripts/harness_review.py +118 -17
- package/harness/bundles/general/cursor/scripts/harness_service.py +219 -0
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +10 -7
- package/harness/bundles/java/claude-code/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/java/claude-code/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +446 -20
- package/harness/bundles/java/claude-code/scripts/harness_events.py +273 -21
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +56 -32
- package/harness/bundles/java/claude-code/scripts/harness_integration.py +197 -3
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +126 -2
- package/harness/bundles/java/claude-code/scripts/harness_report_model.py +28 -6
- package/harness/bundles/java/claude-code/scripts/harness_review.py +118 -17
- package/harness/bundles/java/claude-code/scripts/harness_service.py +219 -0
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +10 -7
- package/harness/bundles/java/codebuddy/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/java/codebuddy/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +446 -20
- package/harness/bundles/java/codebuddy/scripts/harness_events.py +273 -21
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +56 -32
- package/harness/bundles/java/codebuddy/scripts/harness_integration.py +197 -3
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +126 -2
- package/harness/bundles/java/codebuddy/scripts/harness_report_model.py +28 -6
- package/harness/bundles/java/codebuddy/scripts/harness_review.py +118 -17
- package/harness/bundles/java/codebuddy/scripts/harness_service.py +219 -0
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-archive/SKILL.md +10 -7
- package/harness/bundles/java/codex/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/java/codex/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/java/codex/scripts/harness_archive.py +446 -20
- package/harness/bundles/java/codex/scripts/harness_events.py +273 -21
- package/harness/bundles/java/codex/scripts/harness_gate.py +56 -32
- package/harness/bundles/java/codex/scripts/harness_integration.py +197 -3
- package/harness/bundles/java/codex/scripts/harness_ledger.py +126 -2
- package/harness/bundles/java/codex/scripts/harness_report_model.py +28 -6
- package/harness/bundles/java/codex/scripts/harness_review.py +118 -17
- package/harness/bundles/java/codex/scripts/harness_service.py +219 -0
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +10 -7
- package/harness/bundles/java/cursor/harness-archive/templates/render-summary.mjs +24 -4
- 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 +283 -28
- 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 +2 -2
- package/harness/bundles/java/cursor/harness-review/reference.md +20 -5
- 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-test/SKILL.md +1 -1
- package/harness/bundles/java/cursor/scripts/harness_archive.py +446 -20
- package/harness/bundles/java/cursor/scripts/harness_events.py +273 -21
- package/harness/bundles/java/cursor/scripts/harness_gate.py +56 -32
- package/harness/bundles/java/cursor/scripts/harness_integration.py +197 -3
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +126 -2
- package/harness/bundles/java/cursor/scripts/harness_report_model.py +28 -6
- package/harness/bundles/java/cursor/scripts/harness_review.py +118 -17
- package/harness/bundles/java/cursor/scripts/harness_service.py +219 -0
- package/harness/manifests/general/claude-code.json +24 -24
- package/harness/manifests/general/codebuddy.json +24 -24
- package/harness/manifests/general/codex.json +24 -24
- package/harness/manifests/general/cursor.json +24 -24
- package/harness/manifests/java/claude-code.json +26 -26
- package/harness/manifests/java/codebuddy.json +26 -26
- package/harness/manifests/java/codex.json +26 -26
- package/harness/manifests/java/cursor.json +26 -26
- package/hunter-workflow-family.json +4 -4
- package/package.json +1 -1
|
@@ -19,6 +19,7 @@ import hashlib
|
|
|
19
19
|
import json
|
|
20
20
|
import os
|
|
21
21
|
import re
|
|
22
|
+
import subprocess
|
|
22
23
|
import sys
|
|
23
24
|
import uuid
|
|
24
25
|
from pathlib import Path
|
|
@@ -351,43 +352,121 @@ def degradation_matrix(
|
|
|
351
352
|
return {"fallback": "advisory", "status": "ADVISORY"}
|
|
352
353
|
|
|
353
354
|
|
|
355
|
+
def _canonical_root(value: str | Path) -> str:
|
|
356
|
+
"""Canonicalize a root for an identity comparison across Windows worktrees."""
|
|
357
|
+
return os.path.normcase(str(Path(value).expanduser().resolve()))
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def codegraph_worktree_id(execution_root: Path) -> str | None:
|
|
361
|
+
"""Return a stable id for a linked worktree, or ``None`` for the main checkout."""
|
|
362
|
+
root = Path(execution_root).resolve()
|
|
363
|
+
try:
|
|
364
|
+
git_dir = subprocess.run(
|
|
365
|
+
["git", "rev-parse", "--git-dir"],
|
|
366
|
+
cwd=str(root),
|
|
367
|
+
capture_output=True,
|
|
368
|
+
text=True,
|
|
369
|
+
encoding="utf-8",
|
|
370
|
+
errors="replace",
|
|
371
|
+
check=False,
|
|
372
|
+
)
|
|
373
|
+
common_dir = subprocess.run(
|
|
374
|
+
["git", "rev-parse", "--git-common-dir"],
|
|
375
|
+
cwd=str(root),
|
|
376
|
+
capture_output=True,
|
|
377
|
+
text=True,
|
|
378
|
+
encoding="utf-8",
|
|
379
|
+
errors="replace",
|
|
380
|
+
check=False,
|
|
381
|
+
)
|
|
382
|
+
except OSError:
|
|
383
|
+
return None
|
|
384
|
+
if git_dir.returncode != 0 or common_dir.returncode != 0:
|
|
385
|
+
return None
|
|
386
|
+
git_dir_path = Path(git_dir.stdout.strip())
|
|
387
|
+
common_dir_path = Path(common_dir.stdout.strip())
|
|
388
|
+
if not git_dir_path.is_absolute():
|
|
389
|
+
git_dir_path = (root / git_dir_path).resolve()
|
|
390
|
+
if not common_dir_path.is_absolute():
|
|
391
|
+
common_dir_path = (root / common_dir_path).resolve()
|
|
392
|
+
if _canonical_root(git_dir_path) == _canonical_root(common_dir_path):
|
|
393
|
+
return None
|
|
394
|
+
return "sha256:" + hashlib.sha256(
|
|
395
|
+
_canonical_root(root).encode("utf-8")
|
|
396
|
+
).hexdigest()
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def codegraph_expected_identity(
|
|
400
|
+
execution_root: Path,
|
|
401
|
+
*,
|
|
402
|
+
expected_repository_id: str,
|
|
403
|
+
expected_head: str,
|
|
404
|
+
) -> dict[str, str | None]:
|
|
405
|
+
"""Build the identity contract supplied with every CodeGraph query."""
|
|
406
|
+
root = Path(execution_root).resolve()
|
|
407
|
+
return {
|
|
408
|
+
"rootPath": str(root),
|
|
409
|
+
"worktreeId": codegraph_worktree_id(root),
|
|
410
|
+
"repositoryId": expected_repository_id,
|
|
411
|
+
"head": expected_head,
|
|
412
|
+
"indexSnapshotAt": None,
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
|
|
354
416
|
def validate_codegraph_identity(
|
|
355
417
|
*,
|
|
356
418
|
response: dict[str, Any],
|
|
357
419
|
expected_repository_id: str,
|
|
358
420
|
expected_head: str,
|
|
421
|
+
expected_root: str | Path,
|
|
422
|
+
expected_worktree_id: str | None,
|
|
359
423
|
) -> dict[str, Any]:
|
|
360
|
-
"""
|
|
424
|
+
"""Validate CodeGraph evidence before Review adopts its source snippets.
|
|
361
425
|
|
|
362
|
-
|
|
426
|
+
A repository id is shared by the main checkout and linked worktrees, so it
|
|
427
|
+
cannot by itself prevent main-checkout evidence from being used for feature
|
|
428
|
+
worktree review. Root and worktree identity are therefore mandatory.
|
|
363
429
|
"""
|
|
364
430
|
repo_id = response.get("repositoryId")
|
|
365
|
-
indexed_head = response.get("indexedHead")
|
|
366
|
-
indexed_at = response.get("indexedAt")
|
|
431
|
+
indexed_head = response.get("head", response.get("indexedHead"))
|
|
432
|
+
indexed_at = response.get("indexSnapshotAt", response.get("indexedAt"))
|
|
433
|
+
root_path = response.get("rootPath", response.get("indexedRoot"))
|
|
434
|
+
worktree_id = response.get("worktreeId")
|
|
435
|
+
expected_root_path = _canonical_root(expected_root)
|
|
436
|
+
actual_root_path = (
|
|
437
|
+
_canonical_root(root_path) if isinstance(root_path, str) and root_path.strip() else None
|
|
438
|
+
)
|
|
439
|
+
actual = {
|
|
440
|
+
"rootPath": root_path,
|
|
441
|
+
"worktreeId": worktree_id,
|
|
442
|
+
"repositoryId": repo_id,
|
|
443
|
+
"head": indexed_head,
|
|
444
|
+
"indexSnapshotAt": indexed_at,
|
|
445
|
+
}
|
|
446
|
+
expected = {
|
|
447
|
+
"rootPath": str(Path(expected_root).resolve()),
|
|
448
|
+
"worktreeId": expected_worktree_id,
|
|
449
|
+
"repositoryId": expected_repository_id,
|
|
450
|
+
"head": expected_head,
|
|
451
|
+
"indexSnapshotAt": None,
|
|
452
|
+
}
|
|
367
453
|
if (
|
|
368
454
|
repo_id == expected_repository_id
|
|
369
455
|
and indexed_head == expected_head
|
|
456
|
+
and actual_root_path == expected_root_path
|
|
457
|
+
and worktree_id == expected_worktree_id
|
|
370
458
|
and indexed_at
|
|
371
459
|
):
|
|
372
460
|
return {
|
|
373
461
|
"ok": True,
|
|
374
462
|
"code": "IDENTITY_OK",
|
|
375
|
-
"
|
|
376
|
-
"indexedHead": indexed_head,
|
|
377
|
-
"indexedAt": indexed_at,
|
|
463
|
+
"evidence": actual,
|
|
378
464
|
}
|
|
379
465
|
return {
|
|
380
466
|
"ok": False,
|
|
381
|
-
"code": "
|
|
382
|
-
"expected":
|
|
383
|
-
|
|
384
|
-
"indexedHead": expected_head,
|
|
385
|
-
},
|
|
386
|
-
"actual": {
|
|
387
|
-
"repositoryId": repo_id,
|
|
388
|
-
"indexedHead": indexed_head,
|
|
389
|
-
"indexedAt": indexed_at,
|
|
390
|
-
},
|
|
467
|
+
"code": "IDENTITY_MISMATCH",
|
|
468
|
+
"expected": expected,
|
|
469
|
+
"actual": actual,
|
|
391
470
|
"fallback": "grep-glob-read",
|
|
392
471
|
}
|
|
393
472
|
|
|
@@ -399,6 +478,20 @@ def cmd_validate_findings(args: argparse.Namespace) -> int:
|
|
|
399
478
|
return _emit(payload, as_json=True)
|
|
400
479
|
|
|
401
480
|
|
|
481
|
+
def cmd_validate_codegraph_identity(args: argparse.Namespace) -> int:
|
|
482
|
+
response = _read_json(Path(args.input))
|
|
483
|
+
if not isinstance(response, dict):
|
|
484
|
+
raise ValueError("CodeGraph response must be an object")
|
|
485
|
+
payload = validate_codegraph_identity(
|
|
486
|
+
response=response,
|
|
487
|
+
expected_repository_id=args.repository_id,
|
|
488
|
+
expected_head=args.head,
|
|
489
|
+
expected_root=args.execution_root,
|
|
490
|
+
expected_worktree_id=args.worktree_id,
|
|
491
|
+
)
|
|
492
|
+
return _emit(payload, as_json=True)
|
|
493
|
+
|
|
494
|
+
|
|
402
495
|
def cmd_write_findings(args: argparse.Namespace) -> int:
|
|
403
496
|
doc = _read_json(Path(args.input))
|
|
404
497
|
return _emit(write_findings(Path(args.change_dir), doc), as_json=True)
|
|
@@ -421,6 +514,14 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
421
514
|
p_validate.add_argument("--input", required=True)
|
|
422
515
|
p_validate.set_defaults(func=cmd_validate_findings)
|
|
423
516
|
|
|
517
|
+
p_codegraph = sub.add_parser("validate-codegraph-identity")
|
|
518
|
+
p_codegraph.add_argument("--input", required=True)
|
|
519
|
+
p_codegraph.add_argument("--execution-root", required=True)
|
|
520
|
+
p_codegraph.add_argument("--repository-id", required=True)
|
|
521
|
+
p_codegraph.add_argument("--head", required=True)
|
|
522
|
+
p_codegraph.add_argument("--worktree-id")
|
|
523
|
+
p_codegraph.set_defaults(func=cmd_validate_codegraph_identity)
|
|
524
|
+
|
|
424
525
|
p_findings = sub.add_parser("write-findings")
|
|
425
526
|
p_findings.add_argument("--change-dir", required=True)
|
|
426
527
|
p_findings.add_argument("--input", required=True)
|
|
@@ -726,6 +726,173 @@ def write_session(change_dir: Path, session: dict[str, Any]) -> Path:
|
|
|
726
726
|
return path
|
|
727
727
|
|
|
728
728
|
|
|
729
|
+
def _same_path(left: Any, right: Path | None) -> bool:
|
|
730
|
+
if right is None or not isinstance(left, str) or not left.strip():
|
|
731
|
+
return False
|
|
732
|
+
try:
|
|
733
|
+
return Path(left).resolve() == right.resolve()
|
|
734
|
+
except OSError:
|
|
735
|
+
return False
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
def session_is_owned(
|
|
739
|
+
session: dict[str, Any],
|
|
740
|
+
*,
|
|
741
|
+
change_id: str | None = None,
|
|
742
|
+
execution_root: Path | None = None,
|
|
743
|
+
worktree_root: Path | None = None,
|
|
744
|
+
) -> bool:
|
|
745
|
+
"""Return true for an AI session owned by the supplied change/root filters.
|
|
746
|
+
|
|
747
|
+
``change_id`` is required when provided. Root filters match if the session's
|
|
748
|
+
``executionRoot`` or ``worktreeRoot`` equals any supplied root (OR).
|
|
749
|
+
"""
|
|
750
|
+
if session.get("startedBy") != "AI":
|
|
751
|
+
return False
|
|
752
|
+
if change_id is not None and session.get("changeId") != change_id:
|
|
753
|
+
return False
|
|
754
|
+
root_matches: list[bool] = []
|
|
755
|
+
if execution_root is not None:
|
|
756
|
+
root_matches.append(_same_path(session.get("executionRoot"), execution_root))
|
|
757
|
+
root_matches.append(_same_path(session.get("worktreeRoot"), execution_root))
|
|
758
|
+
if worktree_root is not None:
|
|
759
|
+
root_matches.append(_same_path(session.get("worktreeRoot"), worktree_root))
|
|
760
|
+
root_matches.append(_same_path(session.get("executionRoot"), worktree_root))
|
|
761
|
+
if root_matches and not any(root_matches):
|
|
762
|
+
return False
|
|
763
|
+
return True
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
def find_owned_sessions(
|
|
767
|
+
project_root: Path,
|
|
768
|
+
*,
|
|
769
|
+
change_id: str | None = None,
|
|
770
|
+
execution_root: Path | None = None,
|
|
771
|
+
worktree_root: Path | None = None,
|
|
772
|
+
) -> dict[str, list[dict[str, Any]]]:
|
|
773
|
+
"""Discover persisted sessions and classify them without stopping anything."""
|
|
774
|
+
project = resolve_path(project_root)
|
|
775
|
+
candidate_dirs: list[Path] = []
|
|
776
|
+
if change_id:
|
|
777
|
+
candidate_dirs.extend(
|
|
778
|
+
[
|
|
779
|
+
project / ".harness" / "changes" / change_id,
|
|
780
|
+
project / ".harness" / "state" / "changes" / change_id,
|
|
781
|
+
]
|
|
782
|
+
)
|
|
783
|
+
else:
|
|
784
|
+
for root in (
|
|
785
|
+
project / ".harness" / "changes",
|
|
786
|
+
project / ".harness" / "state" / "changes",
|
|
787
|
+
):
|
|
788
|
+
if root.is_dir():
|
|
789
|
+
candidate_dirs.extend(path for path in root.iterdir() if path.is_dir())
|
|
790
|
+
|
|
791
|
+
owned: list[dict[str, Any]] = []
|
|
792
|
+
reported: list[dict[str, Any]] = []
|
|
793
|
+
seen: set[Path] = set()
|
|
794
|
+
for change_dir in candidate_dirs:
|
|
795
|
+
path = session_path(change_dir)
|
|
796
|
+
try:
|
|
797
|
+
path = path.resolve()
|
|
798
|
+
except OSError:
|
|
799
|
+
continue
|
|
800
|
+
if path in seen or not path.is_file():
|
|
801
|
+
continue
|
|
802
|
+
seen.add(path)
|
|
803
|
+
try:
|
|
804
|
+
session = load_session(change_dir)
|
|
805
|
+
except SessionCorrupt as exc:
|
|
806
|
+
reported.append(
|
|
807
|
+
{
|
|
808
|
+
"sessionPath": str(path),
|
|
809
|
+
"reason": "session-corrupt",
|
|
810
|
+
"detail": str(exc),
|
|
811
|
+
}
|
|
812
|
+
)
|
|
813
|
+
continue
|
|
814
|
+
if session is None:
|
|
815
|
+
continue
|
|
816
|
+
item = {"changeDir": str(change_dir.resolve()), "session": session}
|
|
817
|
+
if session_is_owned(
|
|
818
|
+
session,
|
|
819
|
+
change_id=change_id,
|
|
820
|
+
execution_root=execution_root,
|
|
821
|
+
worktree_root=worktree_root,
|
|
822
|
+
):
|
|
823
|
+
owned.append(item)
|
|
824
|
+
else:
|
|
825
|
+
reported.append(
|
|
826
|
+
{
|
|
827
|
+
"sessionPath": str(path),
|
|
828
|
+
"reason": "not-owned",
|
|
829
|
+
"startedBy": session.get("startedBy"),
|
|
830
|
+
"pid": session.get("pid"),
|
|
831
|
+
"leasedPort": session.get("leasedPort"),
|
|
832
|
+
}
|
|
833
|
+
)
|
|
834
|
+
return {"owned": owned, "reported": reported}
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
def stop_owned_sessions(
|
|
838
|
+
project_root: Path,
|
|
839
|
+
*,
|
|
840
|
+
change_id: str | None = None,
|
|
841
|
+
execution_root: Path | None = None,
|
|
842
|
+
worktree_root: Path | None = None,
|
|
843
|
+
) -> dict[str, Any]:
|
|
844
|
+
"""Stop only discovered AI sessions whose persisted ownership still matches."""
|
|
845
|
+
discovered = find_owned_sessions(
|
|
846
|
+
project_root,
|
|
847
|
+
change_id=change_id,
|
|
848
|
+
execution_root=execution_root,
|
|
849
|
+
worktree_root=worktree_root,
|
|
850
|
+
)
|
|
851
|
+
stopped: list[dict[str, Any]] = []
|
|
852
|
+
blocked: list[dict[str, Any]] = []
|
|
853
|
+
ports_still_in_use: list[int] = []
|
|
854
|
+
for item in discovered["owned"]:
|
|
855
|
+
change_dir = Path(item["changeDir"])
|
|
856
|
+
session = item["session"]
|
|
857
|
+
if not session_is_owned(
|
|
858
|
+
session,
|
|
859
|
+
change_id=change_id,
|
|
860
|
+
execution_root=execution_root,
|
|
861
|
+
worktree_root=worktree_root,
|
|
862
|
+
):
|
|
863
|
+
blocked.append(
|
|
864
|
+
{"sessionPath": str(session_path(change_dir)), "reason": "ownership-changed"}
|
|
865
|
+
)
|
|
866
|
+
continue
|
|
867
|
+
result = stop_ai_session(change_dir, session, require_identity=True)
|
|
868
|
+
result["sessionPath"] = str(session_path(change_dir))
|
|
869
|
+
if result.get("action") == "needs-user-decision":
|
|
870
|
+
blocked.append(result)
|
|
871
|
+
continue
|
|
872
|
+
pid = session.get("pid")
|
|
873
|
+
if isinstance(pid, int) and is_pid_alive(pid):
|
|
874
|
+
blocked.append(
|
|
875
|
+
{
|
|
876
|
+
"sessionPath": str(session_path(change_dir)),
|
|
877
|
+
"reason": "owned-process-still-alive",
|
|
878
|
+
"pid": pid,
|
|
879
|
+
}
|
|
880
|
+
)
|
|
881
|
+
continue
|
|
882
|
+
stopped.append(result)
|
|
883
|
+
port = session.get("leasedPort")
|
|
884
|
+
if isinstance(port, int) and is_port_in_use(port):
|
|
885
|
+
ports_still_in_use.append(port)
|
|
886
|
+
return {
|
|
887
|
+
"ok": not blocked,
|
|
888
|
+
"ownedSessions": len(discovered["owned"]),
|
|
889
|
+
"stopped": stopped,
|
|
890
|
+
"blocked": blocked,
|
|
891
|
+
"reported": discovered["reported"],
|
|
892
|
+
"portsStillInUse": ports_still_in_use,
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
|
|
729
896
|
# ---------------------------------------------------------------------------
|
|
730
897
|
# Start / stop helpers
|
|
731
898
|
# ---------------------------------------------------------------------------
|
|
@@ -924,6 +1091,10 @@ def build_session(
|
|
|
924
1091
|
command: str,
|
|
925
1092
|
service_start: dict[str, Any],
|
|
926
1093
|
started_at: str | None = None,
|
|
1094
|
+
worktree_root: Path | None = None,
|
|
1095
|
+
execution_root: Path | None = None,
|
|
1096
|
+
change_id: str | None = None,
|
|
1097
|
+
attempt_id: str | None = None,
|
|
927
1098
|
) -> dict[str, Any]:
|
|
928
1099
|
profile_name = service_start.get("profile") or "local-dev"
|
|
929
1100
|
overlay = service_start.get("overlayPath") or ""
|
|
@@ -941,6 +1112,14 @@ def build_session(
|
|
|
941
1112
|
if isinstance(service_start.get("leasedPort"), int):
|
|
942
1113
|
session["leasedPort"] = service_start["leasedPort"]
|
|
943
1114
|
session["leaseOwner"] = service_start.get("leaseOwner")
|
|
1115
|
+
if worktree_root is not None:
|
|
1116
|
+
session["worktreeRoot"] = str(worktree_root.resolve())
|
|
1117
|
+
if execution_root is not None:
|
|
1118
|
+
session["executionRoot"] = str(execution_root.resolve())
|
|
1119
|
+
if change_id:
|
|
1120
|
+
session["changeId"] = change_id
|
|
1121
|
+
if attempt_id:
|
|
1122
|
+
session["attemptId"] = attempt_id
|
|
944
1123
|
return session
|
|
945
1124
|
|
|
946
1125
|
|
|
@@ -1031,6 +1210,15 @@ def cmd_ensure(args: argparse.Namespace) -> int:
|
|
|
1031
1210
|
# 持久 profile 只保存模板;runtime overlay/profile 注入到 session,不写回持久 profile。
|
|
1032
1211
|
# 含 worktree/change 陈旧持久值时拒绝(修复输入端陈旧 profile)。
|
|
1033
1212
|
change_name = getattr(args, "change_name", None) or change_dir.name
|
|
1213
|
+
worktree_root_raw = getattr(args, "worktree_root", None)
|
|
1214
|
+
execution_root_raw = getattr(args, "execution_root", None)
|
|
1215
|
+
attempt_id = str(getattr(args, "attempt_id", None) or "").strip() or None
|
|
1216
|
+
worktree_root = (
|
|
1217
|
+
resolve_path(worktree_root_raw) if worktree_root_raw else project
|
|
1218
|
+
)
|
|
1219
|
+
execution_root = (
|
|
1220
|
+
resolve_path(execution_root_raw) if execution_root_raw else None
|
|
1221
|
+
)
|
|
1034
1222
|
overlay = getattr(args, "overlay", None)
|
|
1035
1223
|
leased_port = getattr(args, "leased_port", None)
|
|
1036
1224
|
lease_owner = str(getattr(args, "lease_owner", None) or "").strip() or None
|
|
@@ -1135,6 +1323,10 @@ def cmd_ensure(args: argparse.Namespace) -> int:
|
|
|
1135
1323
|
as_json=as_json,
|
|
1136
1324
|
action="restarted",
|
|
1137
1325
|
previousPid=pid,
|
|
1326
|
+
worktree_root=worktree_root,
|
|
1327
|
+
execution_root=execution_root,
|
|
1328
|
+
change_id=change_name,
|
|
1329
|
+
attempt_id=attempt_id,
|
|
1138
1330
|
)
|
|
1139
1331
|
|
|
1140
1332
|
# pid dead → stale session; clear and fall through
|
|
@@ -1161,6 +1353,10 @@ def cmd_ensure(args: argparse.Namespace) -> int:
|
|
|
1161
1353
|
files=files,
|
|
1162
1354
|
as_json=as_json,
|
|
1163
1355
|
action="started",
|
|
1356
|
+
worktree_root=worktree_root,
|
|
1357
|
+
execution_root=execution_root,
|
|
1358
|
+
change_id=change_name,
|
|
1359
|
+
attempt_id=attempt_id,
|
|
1164
1360
|
)
|
|
1165
1361
|
|
|
1166
1362
|
|
|
@@ -1173,6 +1369,10 @@ def _start_and_record(
|
|
|
1173
1369
|
files: list[str],
|
|
1174
1370
|
as_json: bool,
|
|
1175
1371
|
action: str,
|
|
1372
|
+
worktree_root: Path | None = None,
|
|
1373
|
+
execution_root: Path | None = None,
|
|
1374
|
+
change_id: str | None = None,
|
|
1375
|
+
attempt_id: str | None = None,
|
|
1176
1376
|
**extra: Any,
|
|
1177
1377
|
) -> int:
|
|
1178
1378
|
if not files:
|
|
@@ -1224,6 +1424,10 @@ def _start_and_record(
|
|
|
1224
1424
|
command=command,
|
|
1225
1425
|
service_start=service_start,
|
|
1226
1426
|
started_at=started_at,
|
|
1427
|
+
worktree_root=worktree_root,
|
|
1428
|
+
execution_root=execution_root,
|
|
1429
|
+
change_id=change_id,
|
|
1430
|
+
attempt_id=attempt_id,
|
|
1227
1431
|
)
|
|
1228
1432
|
write_session(change_dir, session)
|
|
1229
1433
|
|
|
@@ -1423,6 +1627,21 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1423
1627
|
default=None,
|
|
1424
1628
|
help="run id that owns --leased-port",
|
|
1425
1629
|
)
|
|
1630
|
+
p_ensure.add_argument(
|
|
1631
|
+
"--worktree-root",
|
|
1632
|
+
default=None,
|
|
1633
|
+
help="worktree that owns the service (default: --project)",
|
|
1634
|
+
)
|
|
1635
|
+
p_ensure.add_argument(
|
|
1636
|
+
"--execution-root",
|
|
1637
|
+
default=None,
|
|
1638
|
+
help="ephemeral execution worktree that owns the service",
|
|
1639
|
+
)
|
|
1640
|
+
p_ensure.add_argument(
|
|
1641
|
+
"--attempt-id",
|
|
1642
|
+
default=None,
|
|
1643
|
+
help="phase or transaction attempt that started the service",
|
|
1644
|
+
)
|
|
1426
1645
|
p_ensure.add_argument("--json", action="store_true")
|
|
1427
1646
|
p_ensure.set_defaults(func=cmd_ensure)
|
|
1428
1647
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"schema_version": 2,
|
|
3
3
|
"profile": "general",
|
|
4
4
|
"adapter": "claude-code",
|
|
5
|
-
"bundle_version": "0.2.
|
|
5
|
+
"bundle_version": "0.2.29",
|
|
6
6
|
"requires": {
|
|
7
|
-
"minimumCliVersion": "0.2.
|
|
7
|
+
"minimumCliVersion": "0.2.41",
|
|
8
8
|
"capabilities": [
|
|
9
9
|
"sync@1",
|
|
10
10
|
"rules-sync@1",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"files": [
|
|
23
23
|
{
|
|
24
24
|
"path": ".harness-build.json",
|
|
25
|
-
"sha256": "
|
|
25
|
+
"sha256": "45df5a5dbfe9105752ef4fd05ab83c1811a4f9bf4d9b5b8b7a1d36481d2197ef"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"path": "agents/harness-evaluator.md",
|
|
@@ -74,11 +74,11 @@
|
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
"path": "harness-archive/SKILL.md",
|
|
77
|
-
"sha256": "
|
|
77
|
+
"sha256": "00382c82dc704e45dd8d19b20971bf5972e932ebf67f49e1ba4b37d568e2cdaa"
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"path": "harness-archive/templates/render-summary.mjs",
|
|
81
|
-
"sha256": "
|
|
81
|
+
"sha256": "6f5198906276a80859e1dc17793113c39dea8fb510c51678e0c1f91e40fddfa0"
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
"path": "harness-archive/templates/summary-data-template.json",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
96
|
"path": "harness-codebase-map/SKILL.md",
|
|
97
|
-
"sha256": "
|
|
97
|
+
"sha256": "c24223f26125039aad63e2596e9f2d4ade19d99ab1ccc52723ed9d315e3df079"
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"path": "harness-codebase-map/templates/ARCHITECTURE.md",
|
|
@@ -154,15 +154,15 @@
|
|
|
154
154
|
},
|
|
155
155
|
{
|
|
156
156
|
"path": "harness-knowledge-ingest/scripts/harness_knowledge.py",
|
|
157
|
-
"sha256": "
|
|
157
|
+
"sha256": "b451ad12a16758b69b6852e0a4348b3889795c05cbe691d49efdeb78a1abecea"
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
"path": "harness-knowledge-ingest/SKILL.md",
|
|
161
|
-
"sha256": "
|
|
161
|
+
"sha256": "26c49a665ddf68a01130e3b8b96285b392e52397c0931484ae89e9b0e329897a"
|
|
162
162
|
},
|
|
163
163
|
{
|
|
164
164
|
"path": "harness-knowledge-query/SKILL.md",
|
|
165
|
-
"sha256": "
|
|
165
|
+
"sha256": "4329b3378066d4e8566fd4890007825269b3ee06c684b636e90f30e1d3f70699"
|
|
166
166
|
},
|
|
167
167
|
{
|
|
168
168
|
"path": "harness-plan/checklist.md",
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
},
|
|
179
179
|
{
|
|
180
180
|
"path": "harness-plan/SKILL.md",
|
|
181
|
-
"sha256": "
|
|
181
|
+
"sha256": "c8b413024053717bd9822d000dfc3bffb602b4e66a71774bb311b09919fc74e2"
|
|
182
182
|
},
|
|
183
183
|
{
|
|
184
184
|
"path": "harness-review/checklist.md",
|
|
@@ -190,11 +190,11 @@
|
|
|
190
190
|
},
|
|
191
191
|
{
|
|
192
192
|
"path": "harness-review/reference.md",
|
|
193
|
-
"sha256": "
|
|
193
|
+
"sha256": "94bfb479910abbf393721887c4ce1b7d4259d170a1223c3315330d317ce77510"
|
|
194
194
|
},
|
|
195
195
|
{
|
|
196
196
|
"path": "harness-review/SKILL.md",
|
|
197
|
-
"sha256": "
|
|
197
|
+
"sha256": "1fa201e66482740662d82910d9958285d3589364be96cd69926fbb932a732c1c"
|
|
198
198
|
},
|
|
199
199
|
{
|
|
200
200
|
"path": "harness-run/checklist.md",
|
|
@@ -210,7 +210,7 @@
|
|
|
210
210
|
},
|
|
211
211
|
{
|
|
212
212
|
"path": "harness-run/SKILL.md",
|
|
213
|
-
"sha256": "
|
|
213
|
+
"sha256": "e886f41e4c4f4fc71ae19bb2804430faab5cafa22de070b517fe1ea43da7b316"
|
|
214
214
|
},
|
|
215
215
|
{
|
|
216
216
|
"path": "harness-submit/checklist.md",
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
},
|
|
223
223
|
{
|
|
224
224
|
"path": "harness-submit/SKILL.md",
|
|
225
|
-
"sha256": "
|
|
225
|
+
"sha256": "0473bf9a7ad86f9b14e9beb1b9fc2d19aa8ca720776b517de534bef040bb7c2e"
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
"path": "harness-sync/reference.md",
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
},
|
|
231
231
|
{
|
|
232
232
|
"path": "harness-sync/SKILL.md",
|
|
233
|
-
"sha256": "
|
|
233
|
+
"sha256": "45d990b184c82ff193cc1bb81b293c22971a203f2e20b888fc9fce4c0c45abe7"
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
236
|
"path": "harness-test/checklist.md",
|
|
@@ -254,7 +254,7 @@
|
|
|
254
254
|
},
|
|
255
255
|
{
|
|
256
256
|
"path": "harness-test/SKILL.md",
|
|
257
|
-
"sha256": "
|
|
257
|
+
"sha256": "fe595cdc91eb12e12d4881bf881cc8ad1d0c00577f1c219108508148e74f0886"
|
|
258
258
|
},
|
|
259
259
|
{
|
|
260
260
|
"path": "protocols/archive-report-protocol.md",
|
|
@@ -322,7 +322,7 @@
|
|
|
322
322
|
},
|
|
323
323
|
{
|
|
324
324
|
"path": "scripts/harness_archive.py",
|
|
325
|
-
"sha256": "
|
|
325
|
+
"sha256": "d9992c4f1a5e3c777ee4d6a8415b1a127dc28d2921110e4bd9fd2726827c0abb"
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
328
|
"path": "scripts/harness_change.py",
|
|
@@ -346,19 +346,19 @@
|
|
|
346
346
|
},
|
|
347
347
|
{
|
|
348
348
|
"path": "scripts/harness_events.py",
|
|
349
|
-
"sha256": "
|
|
349
|
+
"sha256": "0d4db19d71d5945837c255192f7c915af447f98e2ac66bf60e25b93f1613b391"
|
|
350
350
|
},
|
|
351
351
|
{
|
|
352
352
|
"path": "scripts/harness_gate.py",
|
|
353
|
-
"sha256": "
|
|
353
|
+
"sha256": "d6085f724ea59f0fcd47a190a7c45ce81c77a21e84fba185e47c6b21b84c054e"
|
|
354
354
|
},
|
|
355
355
|
{
|
|
356
356
|
"path": "scripts/harness_integration.py",
|
|
357
|
-
"sha256": "
|
|
357
|
+
"sha256": "19ff557794609d94af780f0055aa0a50d47cfd6775f97c163d542205d2ab0044"
|
|
358
358
|
},
|
|
359
359
|
{
|
|
360
360
|
"path": "scripts/harness_ledger.py",
|
|
361
|
-
"sha256": "
|
|
361
|
+
"sha256": "3b00ff15958a1cc650ee32f6a3d8807f4585b75c5bce33707fc9e48c9ec71235"
|
|
362
362
|
},
|
|
363
363
|
{
|
|
364
364
|
"path": "scripts/harness_migration_head.py",
|
|
@@ -390,7 +390,7 @@
|
|
|
390
390
|
},
|
|
391
391
|
{
|
|
392
392
|
"path": "scripts/harness_report_model.py",
|
|
393
|
-
"sha256": "
|
|
393
|
+
"sha256": "08b6df8f053ea3381ca24571056817e0756a06cef01edd1aaee6a7eb492426d6"
|
|
394
394
|
},
|
|
395
395
|
{
|
|
396
396
|
"path": "scripts/harness_retry.py",
|
|
@@ -398,7 +398,7 @@
|
|
|
398
398
|
},
|
|
399
399
|
{
|
|
400
400
|
"path": "scripts/harness_review.py",
|
|
401
|
-
"sha256": "
|
|
401
|
+
"sha256": "a493efd57d743f7414617ffa2e8cac59d6ddd102b0e45cab60795492bf442e20"
|
|
402
402
|
},
|
|
403
403
|
{
|
|
404
404
|
"path": "scripts/harness_runtime.py",
|
|
@@ -406,7 +406,7 @@
|
|
|
406
406
|
},
|
|
407
407
|
{
|
|
408
408
|
"path": "scripts/harness_service.py",
|
|
409
|
-
"sha256": "
|
|
409
|
+
"sha256": "a897ccb4ef397d1677e7d45ce55357b37f0083ea7e985685604c40a6da075d12"
|
|
410
410
|
},
|
|
411
411
|
{
|
|
412
412
|
"path": "scripts/harness_state.py",
|