@hunter-harness/workflow-harness 0.2.21 → 0.2.23
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 +12 -3
- package/harness/bundles/general/claude-code/harness-archive/checklist.md +14 -0
- package/harness/bundles/general/claude-code/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/general/claude-code/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/general/claude-code/harness-plan/checklist.md +1 -0
- package/harness/bundles/general/claude-code/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/general/claude-code/harness-submit/checklist.md +7 -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/harness-test/checklist.md +6 -0
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +1168 -28
- package/harness/bundles/general/claude-code/scripts/harness_environment.py +459 -0
- package/harness/bundles/general/claude-code/scripts/harness_events.py +93 -14
- package/harness/bundles/general/claude-code/scripts/harness_integration.py +126 -14
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +30 -6
- package/harness/bundles/general/claude-code/scripts/harness_profile.py +33 -0
- package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +30 -8
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +12 -3
- package/harness/bundles/general/codebuddy/harness-archive/checklist.md +14 -0
- package/harness/bundles/general/codebuddy/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/general/codebuddy/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/general/codebuddy/harness-plan/checklist.md +1 -0
- package/harness/bundles/general/codebuddy/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/general/codebuddy/harness-submit/checklist.md +7 -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/harness-test/checklist.md +6 -0
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +1168 -28
- package/harness/bundles/general/codebuddy/scripts/harness_environment.py +459 -0
- package/harness/bundles/general/codebuddy/scripts/harness_events.py +93 -14
- package/harness/bundles/general/codebuddy/scripts/harness_integration.py +126 -14
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +30 -6
- package/harness/bundles/general/codebuddy/scripts/harness_profile.py +33 -0
- package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +30 -8
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +12 -3
- package/harness/bundles/general/codex/harness-archive/checklist.md +14 -0
- package/harness/bundles/general/codex/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/general/codex/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/general/codex/harness-plan/checklist.md +1 -0
- package/harness/bundles/general/codex/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/general/codex/harness-submit/checklist.md +7 -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/harness-test/checklist.md +6 -0
- package/harness/bundles/general/codex/scripts/harness_archive.py +1168 -28
- package/harness/bundles/general/codex/scripts/harness_environment.py +459 -0
- package/harness/bundles/general/codex/scripts/harness_events.py +93 -14
- package/harness/bundles/general/codex/scripts/harness_integration.py +126 -14
- package/harness/bundles/general/codex/scripts/harness_ledger.py +30 -6
- package/harness/bundles/general/codex/scripts/harness_profile.py +33 -0
- package/harness/bundles/general/codex/scripts/harness_test_guard.py +30 -8
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +12 -3
- package/harness/bundles/general/cursor/harness-archive/checklist.md +14 -0
- package/harness/bundles/general/cursor/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/general/cursor/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/general/cursor/harness-plan/checklist.md +1 -0
- package/harness/bundles/general/cursor/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/general/cursor/harness-submit/checklist.md +7 -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/harness-test/checklist.md +6 -0
- package/harness/bundles/general/cursor/scripts/harness_archive.py +1168 -28
- package/harness/bundles/general/cursor/scripts/harness_environment.py +459 -0
- package/harness/bundles/general/cursor/scripts/harness_events.py +93 -14
- package/harness/bundles/general/cursor/scripts/harness_integration.py +126 -14
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +30 -6
- package/harness/bundles/general/cursor/scripts/harness_profile.py +33 -0
- package/harness/bundles/general/cursor/scripts/harness_test_guard.py +30 -8
- 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 +12 -3
- package/harness/bundles/java/claude-code/harness-archive/checklist.md +14 -0
- package/harness/bundles/java/claude-code/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/java/claude-code/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/java/claude-code/harness-plan/checklist.md +1 -0
- package/harness/bundles/java/claude-code/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/java/claude-code/harness-submit/checklist.md +7 -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 +1168 -28
- package/harness/bundles/java/claude-code/scripts/harness_environment.py +459 -0
- package/harness/bundles/java/claude-code/scripts/harness_events.py +93 -14
- package/harness/bundles/java/claude-code/scripts/harness_integration.py +126 -14
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +30 -6
- package/harness/bundles/java/claude-code/scripts/harness_profile.py +33 -0
- package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +30 -8
- 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 +12 -3
- package/harness/bundles/java/codebuddy/harness-archive/checklist.md +14 -0
- package/harness/bundles/java/codebuddy/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/java/codebuddy/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/java/codebuddy/harness-plan/checklist.md +1 -0
- package/harness/bundles/java/codebuddy/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/java/codebuddy/harness-submit/checklist.md +7 -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 +1168 -28
- package/harness/bundles/java/codebuddy/scripts/harness_environment.py +459 -0
- package/harness/bundles/java/codebuddy/scripts/harness_events.py +93 -14
- package/harness/bundles/java/codebuddy/scripts/harness_integration.py +126 -14
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +30 -6
- package/harness/bundles/java/codebuddy/scripts/harness_profile.py +33 -0
- package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +30 -8
- 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 +12 -3
- package/harness/bundles/java/codex/harness-archive/checklist.md +14 -0
- package/harness/bundles/java/codex/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/java/codex/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/java/codex/harness-plan/checklist.md +1 -0
- package/harness/bundles/java/codex/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/java/codex/harness-submit/checklist.md +7 -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 +1168 -28
- package/harness/bundles/java/codex/scripts/harness_environment.py +459 -0
- package/harness/bundles/java/codex/scripts/harness_events.py +93 -14
- package/harness/bundles/java/codex/scripts/harness_integration.py +126 -14
- package/harness/bundles/java/codex/scripts/harness_ledger.py +30 -6
- package/harness/bundles/java/codex/scripts/harness_profile.py +33 -0
- package/harness/bundles/java/codex/scripts/harness_test_guard.py +30 -8
- 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 +12 -3
- package/harness/bundles/java/cursor/harness-archive/checklist.md +14 -0
- package/harness/bundles/java/cursor/harness-archive/templates/render-summary.mjs +24 -3
- package/harness/bundles/java/cursor/harness-archive/templates/summary-data-template.json +11 -0
- 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 +2 -1
- package/harness/bundles/java/cursor/harness-plan/checklist.md +1 -0
- package/harness/bundles/java/cursor/harness-plan/reference.md +17 -15
- 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 +3 -1
- package/harness/bundles/java/cursor/harness-submit/checklist.md +7 -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 +1168 -28
- package/harness/bundles/java/cursor/scripts/harness_environment.py +459 -0
- package/harness/bundles/java/cursor/scripts/harness_events.py +93 -14
- package/harness/bundles/java/cursor/scripts/harness_integration.py +126 -14
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +30 -6
- package/harness/bundles/java/cursor/scripts/harness_profile.py +33 -0
- package/harness/bundles/java/cursor/scripts/harness_test_guard.py +30 -8
- package/harness/manifests/general/claude-code.json +29 -25
- package/harness/manifests/general/codebuddy.json +29 -25
- package/harness/manifests/general/codex.json +29 -25
- package/harness/manifests/general/cursor.json +29 -25
- package/harness/manifests/java/claude-code.json +30 -26
- package/harness/manifests/java/codebuddy.json +30 -26
- package/harness/manifests/java/codex.json +30 -26
- package/harness/manifests/java/cursor.json +30 -26
- package/hunter-workflow-family.json +2 -2
- package/package.json +1 -1
|
@@ -43,6 +43,7 @@ if hasattr(sys.stderr, "reconfigure"):
|
|
|
43
43
|
sys.stderr.reconfigure(encoding="utf-8")
|
|
44
44
|
|
|
45
45
|
STEP_ORDER = ["preflight", "prepare", "merge", "verify", "push", "cleanup"]
|
|
46
|
+
DEFAULT_VERIFY_TIMEOUT_SECONDS = 1800
|
|
46
47
|
HEAVY_WORKTREE_ROOTS = (
|
|
47
48
|
"node_modules", ".venv", "venv", "build", "dist", "target", ".cache", "__pycache__"
|
|
48
49
|
)
|
|
@@ -56,6 +57,48 @@ def now_iso() -> str:
|
|
|
56
57
|
return dt.datetime.now().astimezone().isoformat(timespec="milliseconds")
|
|
57
58
|
|
|
58
59
|
|
|
60
|
+
def _split_verify_command(raw: str, *, platform: str = sys.platform) -> list[str]:
|
|
61
|
+
# Harness profile/CLI commands use one portable quoting contract. Keep
|
|
62
|
+
# POSIX tokenization on Windows too; executable normalization happens later.
|
|
63
|
+
return shlex.split(raw, posix=True)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _dedupe_verify_commands(
|
|
67
|
+
commands: Sequence[Sequence[str]],
|
|
68
|
+
) -> list[list[str]]:
|
|
69
|
+
"""Preserve order while preventing explicit/profile duplicate execution."""
|
|
70
|
+
result: list[list[str]] = []
|
|
71
|
+
seen: set[tuple[str, ...]] = set()
|
|
72
|
+
for command in commands:
|
|
73
|
+
normalized = tuple(str(item) for item in command)
|
|
74
|
+
if normalized in seen:
|
|
75
|
+
continue
|
|
76
|
+
seen.add(normalized)
|
|
77
|
+
result.append(list(normalized))
|
|
78
|
+
return result
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _normalize_verify_command(
|
|
82
|
+
command: Sequence[str],
|
|
83
|
+
*,
|
|
84
|
+
platform: str = sys.platform,
|
|
85
|
+
resolver: Callable[[str], str | None] = shutil.which,
|
|
86
|
+
) -> list[str]:
|
|
87
|
+
"""Resolve Windows package-manager wrappers without enabling shell mode."""
|
|
88
|
+
result = [str(item) for item in command]
|
|
89
|
+
if not result or not platform.lower().startswith("win"):
|
|
90
|
+
return result
|
|
91
|
+
executable = Path(result[0]).name.lower()
|
|
92
|
+
if Path(executable).suffix:
|
|
93
|
+
return result
|
|
94
|
+
if executable not in {"npm", "npx", "pnpm", "yarn", "corepack"}:
|
|
95
|
+
return result
|
|
96
|
+
resolved = resolver(executable + ".cmd") or resolver(executable)
|
|
97
|
+
if resolved:
|
|
98
|
+
result[0] = resolved
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
|
|
59
102
|
class IntegrationError(Exception):
|
|
60
103
|
code = "INTEGRATION_ERROR"
|
|
61
104
|
|
|
@@ -224,6 +267,11 @@ def load_journal(project_root: Path, transaction_id: str) -> dict[str, Any]:
|
|
|
224
267
|
def _pid_alive(pid: int) -> bool:
|
|
225
268
|
if pid <= 0:
|
|
226
269
|
return False
|
|
270
|
+
# On Windows, os.kill(pid, 0) can transiently report EINVAL for the
|
|
271
|
+
# current low-priority/background process. The current process is
|
|
272
|
+
# unambiguously alive, so avoid reclaiming its lock on that platform race.
|
|
273
|
+
if pid == os.getpid():
|
|
274
|
+
return True
|
|
227
275
|
try:
|
|
228
276
|
os.kill(pid, 0)
|
|
229
277
|
except ProcessLookupError:
|
|
@@ -878,7 +926,7 @@ class IntegrationTransaction:
|
|
|
878
926
|
commands: list[list[str]] = []
|
|
879
927
|
for index, item in enumerate(required):
|
|
880
928
|
if isinstance(item, str) and item.strip():
|
|
881
|
-
commands.append(
|
|
929
|
+
commands.append(_split_verify_command(item.strip()))
|
|
882
930
|
continue
|
|
883
931
|
if not isinstance(item, dict):
|
|
884
932
|
raise ValueError(f"requiredOnMerge[{index}] must be string or object")
|
|
@@ -886,18 +934,26 @@ class IntegrationTransaction:
|
|
|
886
934
|
if isinstance(raw, list) and raw and all(isinstance(x, str) and x for x in raw):
|
|
887
935
|
commands.append([str(x) for x in raw])
|
|
888
936
|
elif isinstance(raw, str) and raw.strip():
|
|
889
|
-
commands.append(
|
|
937
|
+
commands.append(_split_verify_command(raw.strip()))
|
|
890
938
|
else:
|
|
891
939
|
raise ValueError(f"requiredOnMerge[{index}].command missing")
|
|
892
940
|
return commands
|
|
893
941
|
|
|
894
|
-
def verify(
|
|
942
|
+
def verify(
|
|
943
|
+
self,
|
|
944
|
+
commands: Sequence[Sequence[str]] | None = None,
|
|
945
|
+
*,
|
|
946
|
+
timeout_seconds: float = DEFAULT_VERIFY_TIMEOUT_SECONDS,
|
|
947
|
+
) -> dict[str, Any]:
|
|
895
948
|
commands = list(commands or [])
|
|
896
949
|
# Wave-2 H-9: append profile mergeVerification.requiredOnMerge commands.
|
|
897
950
|
try:
|
|
898
951
|
commands.extend(self._required_on_merge_commands())
|
|
899
952
|
except Exception as exc: # noqa: BLE001 — surface as verify plan error
|
|
900
953
|
raise VerifyPlanMissingError(f"mergeVerification load failed: {exc}") from exc
|
|
954
|
+
commands = _dedupe_verify_commands(commands)
|
|
955
|
+
if timeout_seconds <= 0:
|
|
956
|
+
raise VerifyPlanMissingError("verification timeout must be greater than zero")
|
|
901
957
|
|
|
902
958
|
def action(journal: dict[str, Any]) -> None:
|
|
903
959
|
if not commands or any(
|
|
@@ -910,21 +966,67 @@ class IntegrationTransaction:
|
|
|
910
966
|
intg_root = Path(journal["integrationRoot"]).resolve()
|
|
911
967
|
results: list[dict[str, Any]] = []
|
|
912
968
|
for command in commands:
|
|
969
|
+
executable_command = _normalize_verify_command(command)
|
|
913
970
|
started = dt.datetime.now().astimezone()
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
971
|
+
try:
|
|
972
|
+
proc = subprocess.run(
|
|
973
|
+
executable_command,
|
|
974
|
+
cwd=str(intg_root),
|
|
975
|
+
capture_output=True,
|
|
976
|
+
text=True,
|
|
977
|
+
encoding="utf-8",
|
|
978
|
+
errors="replace",
|
|
979
|
+
check=False,
|
|
980
|
+
timeout=timeout_seconds,
|
|
981
|
+
)
|
|
982
|
+
except subprocess.TimeoutExpired:
|
|
983
|
+
finished = dt.datetime.now().astimezone()
|
|
984
|
+
results.append(
|
|
985
|
+
{
|
|
986
|
+
"command": list(command),
|
|
987
|
+
"resolvedCommand": executable_command,
|
|
988
|
+
"exitCode": None,
|
|
989
|
+
"timedOut": True,
|
|
990
|
+
"timeoutSeconds": timeout_seconds,
|
|
991
|
+
"startedAt": started.isoformat(timespec="milliseconds"),
|
|
992
|
+
"finishedAt": finished.isoformat(timespec="milliseconds"),
|
|
993
|
+
"durationMs": int(
|
|
994
|
+
(finished - started).total_seconds() * 1000
|
|
995
|
+
),
|
|
996
|
+
}
|
|
997
|
+
)
|
|
998
|
+
journal["verifyResults"] = results
|
|
999
|
+
self._save(journal)
|
|
1000
|
+
raise VerificationFailedError(
|
|
1001
|
+
f"command timed out after {timeout_seconds}s: {' '.join(command)}"
|
|
1002
|
+
)
|
|
1003
|
+
except FileNotFoundError as exc:
|
|
1004
|
+
finished = dt.datetime.now().astimezone()
|
|
1005
|
+
results.append(
|
|
1006
|
+
{
|
|
1007
|
+
"command": list(command),
|
|
1008
|
+
"resolvedCommand": executable_command,
|
|
1009
|
+
"exitCode": None,
|
|
1010
|
+
"error": str(exc),
|
|
1011
|
+
"startedAt": started.isoformat(timespec="milliseconds"),
|
|
1012
|
+
"finishedAt": finished.isoformat(timespec="milliseconds"),
|
|
1013
|
+
"durationMs": int(
|
|
1014
|
+
(finished - started).total_seconds() * 1000
|
|
1015
|
+
),
|
|
1016
|
+
}
|
|
1017
|
+
)
|
|
1018
|
+
journal["verifyResults"] = results
|
|
1019
|
+
self._save(journal)
|
|
1020
|
+
raise VerifyPlanMissingError(
|
|
1021
|
+
f"verification executable not found: {executable_command[0]}"
|
|
1022
|
+
) from exc
|
|
923
1023
|
finished = dt.datetime.now().astimezone()
|
|
924
1024
|
results.append(
|
|
925
1025
|
{
|
|
926
1026
|
"command": list(command),
|
|
1027
|
+
"resolvedCommand": executable_command,
|
|
927
1028
|
"exitCode": proc.returncode,
|
|
1029
|
+
"timedOut": False,
|
|
928
1030
|
"startedAt": started.isoformat(timespec="milliseconds"),
|
|
929
1031
|
"finishedAt": finished.isoformat(timespec="milliseconds"),
|
|
930
1032
|
"durationMs": int(
|
|
@@ -1449,11 +1551,16 @@ def _parse_verify_commands(values: Sequence[str] | None) -> list[list[str]]:
|
|
|
1449
1551
|
POSIX shlex semantics: single/double quotes group tokens, backslash
|
|
1450
1552
|
escapes the next character (quote Windows paths).
|
|
1451
1553
|
"""
|
|
1452
|
-
return [
|
|
1554
|
+
return [_split_verify_command(value) for value in (values or [])]
|
|
1453
1555
|
|
|
1454
1556
|
|
|
1455
1557
|
def cmd_verify(args: argparse.Namespace) -> int:
|
|
1456
|
-
return _emit(
|
|
1558
|
+
return _emit(
|
|
1559
|
+
_txn_from_args(args).verify(
|
|
1560
|
+
commands=_parse_verify_commands(args.command),
|
|
1561
|
+
timeout_seconds=float(args.timeout_seconds),
|
|
1562
|
+
)
|
|
1563
|
+
)
|
|
1457
1564
|
|
|
1458
1565
|
|
|
1459
1566
|
def cmd_push(args: argparse.Namespace) -> int:
|
|
@@ -1543,6 +1650,11 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1543
1650
|
p_verify.add_argument("--feature-branch", required=True)
|
|
1544
1651
|
p_verify.add_argument("--temp-root", required=True)
|
|
1545
1652
|
p_verify.add_argument("--command", action="append")
|
|
1653
|
+
p_verify.add_argument(
|
|
1654
|
+
"--timeout-seconds",
|
|
1655
|
+
type=float,
|
|
1656
|
+
default=DEFAULT_VERIFY_TIMEOUT_SECONDS,
|
|
1657
|
+
)
|
|
1546
1658
|
p_verify.set_defaults(func=cmd_verify)
|
|
1547
1659
|
|
|
1548
1660
|
return parser
|
|
@@ -219,14 +219,30 @@ def sha256_file(path: Path) -> str:
|
|
|
219
219
|
return digest.hexdigest()
|
|
220
220
|
|
|
221
221
|
|
|
222
|
-
def compute_inputs_hash(
|
|
222
|
+
def compute_inputs_hash(
|
|
223
|
+
file_paths: list[str], *, project_root: Path | str | None = None
|
|
224
|
+
) -> tuple[str, list[str]]:
|
|
223
225
|
"""Per-file content sha256 → sort digests → hash again (order-independent)."""
|
|
226
|
+
root = (
|
|
227
|
+
Path(project_root).expanduser().resolve()
|
|
228
|
+
if project_root is not None
|
|
229
|
+
else None
|
|
230
|
+
)
|
|
224
231
|
by_path: dict[str, str] = {}
|
|
225
232
|
for raw in file_paths:
|
|
226
233
|
path = resolve_path(raw)
|
|
227
234
|
if not path.is_file():
|
|
228
235
|
raise FileNotFoundError(f"file not found: {raw}")
|
|
229
|
-
|
|
236
|
+
if root is not None:
|
|
237
|
+
try:
|
|
238
|
+
logical_path = path.relative_to(root).as_posix()
|
|
239
|
+
except ValueError as exc:
|
|
240
|
+
raise ValueError(
|
|
241
|
+
f"INPUT_OUTSIDE_PROJECT: {path} is outside {root}"
|
|
242
|
+
) from exc
|
|
243
|
+
else:
|
|
244
|
+
logical_path = path.as_posix()
|
|
245
|
+
by_path[logical_path] = sha256_file(path)
|
|
230
246
|
|
|
231
247
|
# Stable file list for callers; bind every resolved path to its digest.
|
|
232
248
|
# Hashing only the content multiset let a path swap incorrectly reuse a
|
|
@@ -1056,6 +1072,7 @@ def decide_can_reuse(
|
|
|
1056
1072
|
requested_profile_hash: str | None = None,
|
|
1057
1073
|
requested_environment_hash: str | None = None,
|
|
1058
1074
|
requested_db_schema_hash: str | None = None,
|
|
1075
|
+
project_root: Path | str | None = None,
|
|
1059
1076
|
) -> dict[str, Any]:
|
|
1060
1077
|
ledger, ledger_path = load_ledger(change_dir)
|
|
1061
1078
|
if ledger is None:
|
|
@@ -1220,8 +1237,10 @@ def decide_can_reuse(
|
|
|
1220
1237
|
}
|
|
1221
1238
|
|
|
1222
1239
|
try:
|
|
1223
|
-
current_hash, current_files = compute_inputs_hash(
|
|
1224
|
-
|
|
1240
|
+
current_hash, current_files = compute_inputs_hash(
|
|
1241
|
+
files, project_root=project_root
|
|
1242
|
+
)
|
|
1243
|
+
except (FileNotFoundError, ValueError) as exc:
|
|
1225
1244
|
return {
|
|
1226
1245
|
"ok": True,
|
|
1227
1246
|
"reuse": False,
|
|
@@ -1351,7 +1370,9 @@ def cmd_hash(args: argparse.Namespace) -> int:
|
|
|
1351
1370
|
files, project_root = input_files_from_args(args)
|
|
1352
1371
|
if not files:
|
|
1353
1372
|
return emit_error("hash requires --files or --files-from", as_json=as_json)
|
|
1354
|
-
inputs_hash, inputs_files = compute_inputs_hash(
|
|
1373
|
+
inputs_hash, inputs_files = compute_inputs_hash(
|
|
1374
|
+
files, project_root=project_root
|
|
1375
|
+
)
|
|
1355
1376
|
except (OSError, FileNotFoundError) as exc:
|
|
1356
1377
|
return emit_error(str(exc), as_json=as_json)
|
|
1357
1378
|
|
|
@@ -1418,6 +1439,7 @@ def cmd_can_reuse(args: argparse.Namespace) -> int:
|
|
|
1418
1439
|
requested_profile_hash=getattr(args, "profile_hash", None),
|
|
1419
1440
|
requested_environment_hash=getattr(args, "environment_hash", None),
|
|
1420
1441
|
requested_db_schema_hash=getattr(args, "db_schema_hash", None),
|
|
1442
|
+
project_root=project_root,
|
|
1421
1443
|
)
|
|
1422
1444
|
except (OSError, ValueError, json.JSONDecodeError) as exc:
|
|
1423
1445
|
return emit_error(f"can-reuse failed: {exc}", as_json=as_json)
|
|
@@ -1470,7 +1492,9 @@ def cmd_record(args: argparse.Namespace) -> int:
|
|
|
1470
1492
|
|
|
1471
1493
|
try:
|
|
1472
1494
|
status = normalize_status(args.status)
|
|
1473
|
-
inputs_hash, inputs_files = compute_inputs_hash(
|
|
1495
|
+
inputs_hash, inputs_files = compute_inputs_hash(
|
|
1496
|
+
files, project_root=project_root
|
|
1497
|
+
)
|
|
1474
1498
|
ledger, _existing_path = load_ledger(change_dir)
|
|
1475
1499
|
if ledger is None:
|
|
1476
1500
|
ledger = {
|
|
@@ -66,6 +66,16 @@ DEFAULT_EXCLUDED_ROOTS: tuple[str, ...] = (
|
|
|
66
66
|
".cache",
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
+
|
|
70
|
+
def profile_defaults_fingerprint() -> str:
|
|
71
|
+
"""Fingerprint generated defaults so old profiles are refreshed safely."""
|
|
72
|
+
payload = {
|
|
73
|
+
"schemaVersion": SCHEMA_VERSION,
|
|
74
|
+
"excludedRoots": list(DEFAULT_EXCLUDED_ROOTS),
|
|
75
|
+
}
|
|
76
|
+
encoded = json.dumps(payload, ensure_ascii=False, sort_keys=True).encode("utf-8")
|
|
77
|
+
return f"sha256:{hashlib.sha256(encoded).hexdigest()}"
|
|
78
|
+
|
|
69
79
|
# 覆盖层级(spec §3.2):unitTest ⊂ unitTestFull;package 独立;submit 复用 unitTestFull。
|
|
70
80
|
VERIFICATION_KEYS: tuple[str, ...] = (
|
|
71
81
|
"compile",
|
|
@@ -330,6 +340,7 @@ def _node_commands(project: Path) -> dict[str, Any]:
|
|
|
330
340
|
def empty_profile_skeleton(excluded: tuple[str, ...] | list[str]) -> dict[str, Any]:
|
|
331
341
|
return {
|
|
332
342
|
"schemaVersion": SCHEMA_VERSION,
|
|
343
|
+
"defaultsFingerprint": profile_defaults_fingerprint(),
|
|
333
344
|
"detectedAt": "",
|
|
334
345
|
"projectType": "unknown",
|
|
335
346
|
"toolPaths": {"node": "", "mvn": ""},
|
|
@@ -596,6 +607,28 @@ def check(project: Path) -> dict[str, Any]:
|
|
|
596
607
|
issues: list[str] = []
|
|
597
608
|
stale = False
|
|
598
609
|
|
|
610
|
+
expected_defaults_fingerprint = profile_defaults_fingerprint()
|
|
611
|
+
if profile.get("defaultsFingerprint") != expected_defaults_fingerprint:
|
|
612
|
+
stale = True
|
|
613
|
+
issues.append(
|
|
614
|
+
"defaultsFingerprint is missing or outdated; run detect to refresh generated defaults"
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
excluded_roots = {
|
|
618
|
+
str(item).replace("\\", "/").strip("/")
|
|
619
|
+
for item in (profile.get("excludedRoots") or [])
|
|
620
|
+
if isinstance(item, str) and item.strip("/")
|
|
621
|
+
}
|
|
622
|
+
missing_excluded_roots = [
|
|
623
|
+
item for item in DEFAULT_EXCLUDED_ROOTS if item not in excluded_roots
|
|
624
|
+
]
|
|
625
|
+
if missing_excluded_roots:
|
|
626
|
+
stale = True
|
|
627
|
+
issues.append(
|
|
628
|
+
"excludedRoots missing generated defaults: "
|
|
629
|
+
+ ", ".join(missing_excluded_roots)
|
|
630
|
+
)
|
|
631
|
+
|
|
599
632
|
fp = profile.get("fingerprint") or {}
|
|
600
633
|
stored_pom = fp.get("pomHash") or "" if isinstance(fp, dict) else ""
|
|
601
634
|
current_pom = sha256_file(project / "pom.xml") if (project / "pom.xml").is_file() else ""
|
|
@@ -32,6 +32,24 @@ MODE = "force-track-touched"
|
|
|
32
32
|
MANIFEST_REL = Path("evidence") / "test-tracking.json"
|
|
33
33
|
SNAPSHOT_REL = Path("evidence") / "test-guard-snapshot.json"
|
|
34
34
|
PROFILE_REL = Path(".harness") / "config" / "build-profile.json"
|
|
35
|
+
MANDATORY_EXCLUDED_ROOTS = (
|
|
36
|
+
".git",
|
|
37
|
+
".harness",
|
|
38
|
+
".worktrees",
|
|
39
|
+
".claude/worktrees",
|
|
40
|
+
".codex/worktrees",
|
|
41
|
+
".cursor/worktrees",
|
|
42
|
+
".codebuddy/worktrees",
|
|
43
|
+
".codeium/worktrees",
|
|
44
|
+
"target",
|
|
45
|
+
"build",
|
|
46
|
+
"dist",
|
|
47
|
+
"node_modules",
|
|
48
|
+
".gradle",
|
|
49
|
+
"__pycache__",
|
|
50
|
+
".pytest_cache",
|
|
51
|
+
".cache",
|
|
52
|
+
)
|
|
35
53
|
REASONS = ("tdd-created", "stale-test-repair", "test-updated")
|
|
36
54
|
|
|
37
55
|
|
|
@@ -213,11 +231,14 @@ def _profile_config(project: Path) -> tuple[list[str], list[str]] | None:
|
|
|
213
231
|
if not isinstance(paths, list):
|
|
214
232
|
return [], []
|
|
215
233
|
excluded = profile.get("excludedRoots") if isinstance(profile, dict) else None
|
|
216
|
-
|
|
234
|
+
configured_roots = (
|
|
217
235
|
[item.replace("\\", "/").strip("/") for item in excluded if isinstance(item, str) and item]
|
|
218
236
|
if isinstance(excluded, list)
|
|
219
237
|
else []
|
|
220
238
|
)
|
|
239
|
+
excluded_roots = list(
|
|
240
|
+
dict.fromkeys([*configured_roots, *MANDATORY_EXCLUDED_ROOTS])
|
|
241
|
+
)
|
|
221
242
|
patterns = [
|
|
222
243
|
item.replace("\\", "/") for item in paths if isinstance(item, str) and item
|
|
223
244
|
]
|
|
@@ -254,11 +275,8 @@ def _allowed_test_path(project: Path, rel: str) -> bool:
|
|
|
254
275
|
if config is None:
|
|
255
276
|
return _standard_test_path(rel)
|
|
256
277
|
patterns, excluded_roots = config
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
excluded_parts = tuple(os.path.normcase(part) for part in excluded.split("/"))
|
|
260
|
-
if rel_parts[: len(excluded_parts)] == excluded_parts:
|
|
261
|
-
return False
|
|
278
|
+
if _path_is_excluded(rel, excluded_roots):
|
|
279
|
+
return False
|
|
262
280
|
return any(_matches_pattern(rel, pattern) for pattern in patterns)
|
|
263
281
|
|
|
264
282
|
|
|
@@ -820,8 +838,12 @@ def _path_is_excluded(rel: str, excluded_roots: list[str]) -> bool:
|
|
|
820
838
|
excluded_parts = tuple(
|
|
821
839
|
os.path.normcase(part) for part in excluded.split("/") if part
|
|
822
840
|
)
|
|
823
|
-
if
|
|
824
|
-
|
|
841
|
+
if not excluded_parts:
|
|
842
|
+
continue
|
|
843
|
+
width = len(excluded_parts)
|
|
844
|
+
for index in range(len(rel_parts) - width + 1):
|
|
845
|
+
if rel_parts[index : index + width] == excluded_parts:
|
|
846
|
+
return True
|
|
825
847
|
return False
|
|
826
848
|
|
|
827
849
|
|
|
@@ -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.17",
|
|
6
6
|
"generator": "harness_deploy.py",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
9
9
|
"path": ".harness-build.json",
|
|
10
|
-
"sha256": "
|
|
10
|
+
"sha256": "c98f26983913009f3f8c9775f935dcd0a9703c6981914cb9f7dadcfa4b20942b"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"path": "agents/harness-evaluator.md",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"path": "harness-archive/checklist.md",
|
|
38
|
-
"sha256": "
|
|
38
|
+
"sha256": "dedc3cb106e692015f31a98465342d0ea6367ff56f87602602ce7a2818a792a6"
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"path": "harness-archive/reference.md",
|
|
@@ -47,15 +47,15 @@
|
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"path": "harness-archive/SKILL.md",
|
|
50
|
-
"sha256": "
|
|
50
|
+
"sha256": "c338fe8ca50093810206d172dfb8105b487e57b1c6315b16e7ae2bdc1c142682"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"path": "harness-archive/templates/render-summary.mjs",
|
|
54
|
-
"sha256": "
|
|
54
|
+
"sha256": "7478a27f71b006b206443fee7ac8c2ee9722d21c78e6b2a82d3a1300de41d391"
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
"path": "harness-archive/templates/summary-data-template.json",
|
|
58
|
-
"sha256": "
|
|
58
|
+
"sha256": "b5cceb8f85cc99a689723863292119f3aeccacbb17aea7257632353b4e617ff7"
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
"path": "harness-codebase-map/checklist.md",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
69
|
"path": "harness-codebase-map/SKILL.md",
|
|
70
|
-
"sha256": "
|
|
70
|
+
"sha256": "5dee320bee18bad368c3a9118356723e0de93aeacef5e4d47a6186a8f45bc515"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"path": "harness-codebase-map/templates/ARCHITECTURE.md",
|
|
@@ -131,15 +131,15 @@
|
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
"path": "harness-knowledge-ingest/SKILL.md",
|
|
134
|
-
"sha256": "
|
|
134
|
+
"sha256": "218482cf4d500d509c96f1e69fc6e7949ce45d05baab57ddf59e17a4ffdafdc3"
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
137
|
"path": "harness-knowledge-query/SKILL.md",
|
|
138
|
-
"sha256": "
|
|
138
|
+
"sha256": "4a8f5831d1139d52b4993ee62a4a264b2c38a8b2754d800caf56c81d46d273e9"
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
"path": "harness-plan/checklist.md",
|
|
142
|
-
"sha256": "
|
|
142
|
+
"sha256": "60802b67d0184e76e745df483ca7244f399793a6eda6c2e5031b9cba865ce03b"
|
|
143
143
|
},
|
|
144
144
|
{
|
|
145
145
|
"path": "harness-plan/protocols.md",
|
|
@@ -147,11 +147,11 @@
|
|
|
147
147
|
},
|
|
148
148
|
{
|
|
149
149
|
"path": "harness-plan/reference.md",
|
|
150
|
-
"sha256": "
|
|
150
|
+
"sha256": "9a2a2a33ccaa6bd39fed4d8803b5a246a2c029a9e3266091754801a133272219"
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
153
|
"path": "harness-plan/SKILL.md",
|
|
154
|
-
"sha256": "
|
|
154
|
+
"sha256": "fc18843c9b35b4928884a81a50eed6a09bb186686183491ade062c6e8a46ea85"
|
|
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": "0f122b78e96a7157f5288ede262c86b396928b1fed665feeebd33b3cc134578d"
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
"path": "harness-run/checklist.md",
|
|
@@ -183,11 +183,11 @@
|
|
|
183
183
|
},
|
|
184
184
|
{
|
|
185
185
|
"path": "harness-run/SKILL.md",
|
|
186
|
-
"sha256": "
|
|
186
|
+
"sha256": "6b9aa2493184ceefae162cb5c6745a8a52af95c290f36b0c2a74dae707aafe55"
|
|
187
187
|
},
|
|
188
188
|
{
|
|
189
189
|
"path": "harness-submit/checklist.md",
|
|
190
|
-
"sha256": "
|
|
190
|
+
"sha256": "7a0773ff7b5247cb74e449d654217e5a7c55992c3a32cd1e0ea2b808b8f3e6ab"
|
|
191
191
|
},
|
|
192
192
|
{
|
|
193
193
|
"path": "harness-submit/reference.md",
|
|
@@ -195,7 +195,7 @@
|
|
|
195
195
|
},
|
|
196
196
|
{
|
|
197
197
|
"path": "harness-submit/SKILL.md",
|
|
198
|
-
"sha256": "
|
|
198
|
+
"sha256": "b01f6ccb9f40834337d1bf280648196b6acc852e3a6d97d1dc31db272f164431"
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
"path": "harness-sync/reference.md",
|
|
@@ -203,11 +203,11 @@
|
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
205
|
"path": "harness-sync/SKILL.md",
|
|
206
|
-
"sha256": "
|
|
206
|
+
"sha256": "a89114b48bc1e8adf6272ac280463a70ac6f2348d4f786e9db45ab2e520bbfa8"
|
|
207
207
|
},
|
|
208
208
|
{
|
|
209
209
|
"path": "harness-test/checklist.md",
|
|
210
|
-
"sha256": "
|
|
210
|
+
"sha256": "499bc792815fc364123452f81b00c4043211289538f6f7dd62d19355d60d2e9e"
|
|
211
211
|
},
|
|
212
212
|
{
|
|
213
213
|
"path": "harness-test/pitfalls-java.md",
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
229
|
"path": "harness-test/SKILL.md",
|
|
230
|
-
"sha256": "
|
|
230
|
+
"sha256": "a357df30dcf0b6814094e54b8792c084a534f9d6a89d13af94554cab1359d871"
|
|
231
231
|
},
|
|
232
232
|
{
|
|
233
233
|
"path": "protocols/archive-report-protocol.md",
|
|
@@ -275,7 +275,7 @@
|
|
|
275
275
|
},
|
|
276
276
|
{
|
|
277
277
|
"path": "scripts/harness_archive.py",
|
|
278
|
-
"sha256": "
|
|
278
|
+
"sha256": "6a2d2422ab8b49ca25e51cad6b77b982efe05d1314a66afc48e006b30c3cab83"
|
|
279
279
|
},
|
|
280
280
|
{
|
|
281
281
|
"path": "scripts/harness_change.py",
|
|
@@ -289,9 +289,13 @@
|
|
|
289
289
|
"path": "scripts/harness_deploy.py",
|
|
290
290
|
"sha256": "48a95b696cd4df411cc206b80b16b436018e7648bd2daa55f110ceee2e403271"
|
|
291
291
|
},
|
|
292
|
+
{
|
|
293
|
+
"path": "scripts/harness_environment.py",
|
|
294
|
+
"sha256": "4f6269ef2e21cf9fc327a101cfa2f2eabce840242a718c548bf496ea924d43e9"
|
|
295
|
+
},
|
|
292
296
|
{
|
|
293
297
|
"path": "scripts/harness_events.py",
|
|
294
|
-
"sha256": "
|
|
298
|
+
"sha256": "e6dae6ccb341b22178bd9ef7578df85154c6e9a1d19c86e3769dc7098e50a546"
|
|
295
299
|
},
|
|
296
300
|
{
|
|
297
301
|
"path": "scripts/harness_gate.py",
|
|
@@ -299,11 +303,11 @@
|
|
|
299
303
|
},
|
|
300
304
|
{
|
|
301
305
|
"path": "scripts/harness_integration.py",
|
|
302
|
-
"sha256": "
|
|
306
|
+
"sha256": "f0dbdf506c3d0fb098f4eedcce15beae525c0c32298b48f051cd3ff320948346"
|
|
303
307
|
},
|
|
304
308
|
{
|
|
305
309
|
"path": "scripts/harness_ledger.py",
|
|
306
|
-
"sha256": "
|
|
310
|
+
"sha256": "ee461af57b9fb5d0be94cadf4312c0358ad3672cd5a8466a81ae3e7673c90e82"
|
|
307
311
|
},
|
|
308
312
|
{
|
|
309
313
|
"path": "scripts/harness_migration_head.py",
|
|
@@ -327,7 +331,7 @@
|
|
|
327
331
|
},
|
|
328
332
|
{
|
|
329
333
|
"path": "scripts/harness_profile.py",
|
|
330
|
-
"sha256": "
|
|
334
|
+
"sha256": "d8f6a07455c27c9167df44b33eb20ef7c6c65530462cd4958794db1063d5ac04"
|
|
331
335
|
},
|
|
332
336
|
{
|
|
333
337
|
"path": "scripts/harness_review.py",
|
|
@@ -355,7 +359,7 @@
|
|
|
355
359
|
},
|
|
356
360
|
{
|
|
357
361
|
"path": "scripts/harness_test_guard.py",
|
|
358
|
-
"sha256": "
|
|
362
|
+
"sha256": "a5792ca55242770d504a4a1ed458746a73bbf5bfa023eb8bc4f7d1e895c80a96"
|
|
359
363
|
},
|
|
360
364
|
{
|
|
361
365
|
"path": "scripts/harness_workflow_policy.py",
|