@hunter-harness/workflow-harness 0.4.11 → 0.4.13

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.
Files changed (192) hide show
  1. package/harness/bundles/general/claude-code/.harness-build.json +1 -1
  2. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
  3. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
  4. package/harness/bundles/general/claude-code/harness-execute/SKILL.md +1 -1
  5. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  6. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  7. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-pull/SKILL.md +1 -1
  9. package/harness/bundles/general/claude-code/harness-push/SKILL.md +1 -1
  10. package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +2 -2
  12. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/scripts/harness_archive.py +18 -11
  14. package/harness/bundles/general/claude-code/scripts/harness_gate.py +69 -1
  15. package/harness/bundles/general/claude-code/scripts/harness_knowledge_candidates.py +58 -12
  16. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +27 -3
  17. package/harness/bundles/general/claude-code/scripts/harness_review.py +16 -2
  18. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  19. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  20. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  21. package/harness/bundles/general/codebuddy/harness-execute/SKILL.md +1 -1
  22. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  23. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  24. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
  25. package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +1 -1
  26. package/harness/bundles/general/codebuddy/harness-push/SKILL.md +1 -1
  27. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
  28. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +2 -2
  29. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  30. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +18 -11
  31. package/harness/bundles/general/codebuddy/scripts/harness_gate.py +69 -1
  32. package/harness/bundles/general/codebuddy/scripts/harness_knowledge_candidates.py +58 -12
  33. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +27 -3
  34. package/harness/bundles/general/codebuddy/scripts/harness_review.py +16 -2
  35. package/harness/bundles/general/codex/.harness-build.json +1 -1
  36. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  37. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  38. package/harness/bundles/general/codex/harness-execute/SKILL.md +1 -1
  39. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  40. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  41. package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
  42. package/harness/bundles/general/codex/harness-pull/SKILL.md +1 -1
  43. package/harness/bundles/general/codex/harness-push/SKILL.md +1 -1
  44. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  45. package/harness/bundles/general/codex/harness-submit/SKILL.md +2 -2
  46. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  47. package/harness/bundles/general/codex/scripts/harness_archive.py +18 -11
  48. package/harness/bundles/general/codex/scripts/harness_gate.py +69 -1
  49. package/harness/bundles/general/codex/scripts/harness_knowledge_candidates.py +58 -12
  50. package/harness/bundles/general/codex/scripts/harness_ledger.py +27 -3
  51. package/harness/bundles/general/codex/scripts/harness_review.py +16 -2
  52. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  53. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  54. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  55. package/harness/bundles/general/cursor/harness-execute/SKILL.md +1 -1
  56. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  57. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  58. package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
  59. package/harness/bundles/general/cursor/harness-pull/SKILL.md +1 -1
  60. package/harness/bundles/general/cursor/harness-push/SKILL.md +1 -1
  61. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  62. package/harness/bundles/general/cursor/harness-submit/SKILL.md +2 -2
  63. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  64. package/harness/bundles/general/cursor/scripts/harness_archive.py +18 -11
  65. package/harness/bundles/general/cursor/scripts/harness_gate.py +69 -1
  66. package/harness/bundles/general/cursor/scripts/harness_knowledge_candidates.py +58 -12
  67. package/harness/bundles/general/cursor/scripts/harness_ledger.py +27 -3
  68. package/harness/bundles/general/cursor/scripts/harness_review.py +16 -2
  69. package/harness/bundles/general/pi/.harness-build.json +1 -1
  70. package/harness/bundles/general/pi/harness-archive/SKILL.md +1 -1
  71. package/harness/bundles/general/pi/harness-codebase-map/SKILL.md +1 -1
  72. package/harness/bundles/general/pi/harness-execute/SKILL.md +1 -1
  73. package/harness/bundles/general/pi/harness-knowledge-ingest/SKILL.md +1 -1
  74. package/harness/bundles/general/pi/harness-knowledge-query/SKILL.md +1 -1
  75. package/harness/bundles/general/pi/harness-plan/SKILL.md +1 -1
  76. package/harness/bundles/general/pi/harness-pull/SKILL.md +1 -1
  77. package/harness/bundles/general/pi/harness-push/SKILL.md +1 -1
  78. package/harness/bundles/general/pi/harness-review/SKILL.md +1 -1
  79. package/harness/bundles/general/pi/harness-submit/SKILL.md +2 -2
  80. package/harness/bundles/general/pi/harness-sync/SKILL.md +1 -1
  81. package/harness/bundles/general/pi/scripts/harness_archive.py +18 -11
  82. package/harness/bundles/general/pi/scripts/harness_gate.py +69 -1
  83. package/harness/bundles/general/pi/scripts/harness_knowledge_candidates.py +58 -12
  84. package/harness/bundles/general/pi/scripts/harness_ledger.py +27 -3
  85. package/harness/bundles/general/pi/scripts/harness_review.py +16 -2
  86. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  87. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  88. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  89. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  90. package/harness/bundles/java/claude-code/harness-execute/SKILL.md +1 -1
  91. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  92. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  93. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  94. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
  95. package/harness/bundles/java/claude-code/harness-pull/SKILL.md +1 -1
  96. package/harness/bundles/java/claude-code/harness-push/SKILL.md +1 -1
  97. package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
  98. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +2 -2
  99. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  100. package/harness/bundles/java/claude-code/scripts/harness_archive.py +18 -11
  101. package/harness/bundles/java/claude-code/scripts/harness_gate.py +69 -1
  102. package/harness/bundles/java/claude-code/scripts/harness_knowledge_candidates.py +58 -12
  103. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +27 -3
  104. package/harness/bundles/java/claude-code/scripts/harness_review.py +16 -2
  105. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  106. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  107. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  108. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  109. package/harness/bundles/java/codebuddy/harness-execute/SKILL.md +1 -1
  110. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  111. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  112. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  113. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
  114. package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +1 -1
  115. package/harness/bundles/java/codebuddy/harness-push/SKILL.md +1 -1
  116. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
  117. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +2 -2
  118. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  119. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +18 -11
  120. package/harness/bundles/java/codebuddy/scripts/harness_gate.py +69 -1
  121. package/harness/bundles/java/codebuddy/scripts/harness_knowledge_candidates.py +58 -12
  122. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +27 -3
  123. package/harness/bundles/java/codebuddy/scripts/harness_review.py +16 -2
  124. package/harness/bundles/java/codex/.harness-build.json +1 -1
  125. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  126. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  127. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  128. package/harness/bundles/java/codex/harness-execute/SKILL.md +1 -1
  129. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  130. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  131. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  132. package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
  133. package/harness/bundles/java/codex/harness-pull/SKILL.md +1 -1
  134. package/harness/bundles/java/codex/harness-push/SKILL.md +1 -1
  135. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  136. package/harness/bundles/java/codex/harness-submit/SKILL.md +2 -2
  137. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  138. package/harness/bundles/java/codex/scripts/harness_archive.py +18 -11
  139. package/harness/bundles/java/codex/scripts/harness_gate.py +69 -1
  140. package/harness/bundles/java/codex/scripts/harness_knowledge_candidates.py +58 -12
  141. package/harness/bundles/java/codex/scripts/harness_ledger.py +27 -3
  142. package/harness/bundles/java/codex/scripts/harness_review.py +16 -2
  143. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  144. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  145. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  146. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  147. package/harness/bundles/java/cursor/harness-execute/SKILL.md +1 -1
  148. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  149. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  150. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  151. package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
  152. package/harness/bundles/java/cursor/harness-pull/SKILL.md +1 -1
  153. package/harness/bundles/java/cursor/harness-push/SKILL.md +1 -1
  154. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  155. package/harness/bundles/java/cursor/harness-submit/SKILL.md +2 -2
  156. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  157. package/harness/bundles/java/cursor/scripts/harness_archive.py +18 -11
  158. package/harness/bundles/java/cursor/scripts/harness_gate.py +69 -1
  159. package/harness/bundles/java/cursor/scripts/harness_knowledge_candidates.py +58 -12
  160. package/harness/bundles/java/cursor/scripts/harness_ledger.py +27 -3
  161. package/harness/bundles/java/cursor/scripts/harness_review.py +16 -2
  162. package/harness/bundles/java/pi/.harness-build.json +1 -1
  163. package/harness/bundles/java/pi/harness-apidoc/SKILL.md +1 -1
  164. package/harness/bundles/java/pi/harness-archive/SKILL.md +1 -1
  165. package/harness/bundles/java/pi/harness-codebase-map/SKILL.md +1 -1
  166. package/harness/bundles/java/pi/harness-execute/SKILL.md +1 -1
  167. package/harness/bundles/java/pi/harness-knowledge-ingest/SKILL.md +1 -1
  168. package/harness/bundles/java/pi/harness-knowledge-query/SKILL.md +1 -1
  169. package/harness/bundles/java/pi/harness-package/SKILL.md +1 -1
  170. package/harness/bundles/java/pi/harness-plan/SKILL.md +1 -1
  171. package/harness/bundles/java/pi/harness-pull/SKILL.md +1 -1
  172. package/harness/bundles/java/pi/harness-push/SKILL.md +1 -1
  173. package/harness/bundles/java/pi/harness-review/SKILL.md +1 -1
  174. package/harness/bundles/java/pi/harness-submit/SKILL.md +2 -2
  175. package/harness/bundles/java/pi/harness-sync/SKILL.md +1 -1
  176. package/harness/bundles/java/pi/scripts/harness_archive.py +18 -11
  177. package/harness/bundles/java/pi/scripts/harness_gate.py +69 -1
  178. package/harness/bundles/java/pi/scripts/harness_knowledge_candidates.py +58 -12
  179. package/harness/bundles/java/pi/scripts/harness_ledger.py +27 -3
  180. package/harness/bundles/java/pi/scripts/harness_review.py +16 -2
  181. package/harness/manifests/general/claude-code.json +17 -17
  182. package/harness/manifests/general/codebuddy.json +17 -17
  183. package/harness/manifests/general/codex.json +17 -17
  184. package/harness/manifests/general/cursor.json +17 -17
  185. package/harness/manifests/general/pi.json +17 -17
  186. package/harness/manifests/java/claude-code.json +19 -19
  187. package/harness/manifests/java/codebuddy.json +19 -19
  188. package/harness/manifests/java/codex.json +19 -19
  189. package/harness/manifests/java/cursor.json +19 -19
  190. package/harness/manifests/java/pi.json +19 -19
  191. package/hunter-workflow-family.json +2 -2
  192. package/package.json +1 -1
@@ -30,6 +30,8 @@ from __future__ import annotations
30
30
 
31
31
  import hashlib
32
32
  import json
33
+ import re
34
+ import sys
33
35
  from typing import Any
34
36
 
35
37
  SCHEMA_VERSION = 1
@@ -44,6 +46,44 @@ _DISPOSITION_ENTRY_TYPES = {
44
46
  "DEFERRED": "risk",
45
47
  }
46
48
  _SEVERITY_CONFIDENCE = {"RED": 0.95, "YELLOW": 0.85}
49
+
50
+
51
+ def _valid_source_path(path: Any) -> str | None:
52
+ """source_ref 的结构校验(与服务端 ARCHIVE_CANDIDATE_SOURCE_UNBOUND 同规则)。
53
+
54
+ 合法形态:`relative/path/to/file.ext`(调用方再附 `#L<line>`)。
55
+ 拒绝:目录引用(尾部斜杠)、空路径段、`.`/`..` 段、绝对路径、盘符、
56
+ 反斜杠。返回规范化路径;不合法返回 None——调用方必须跳过该候选,
57
+ 不得生成「目录 + 行号」的伪来源(2026-08-31 demo-datasource 实测:
58
+ `quality/#L1` 一条不合法 ref 挡掉整份 42 条候选的包)。
59
+ """
60
+ if not isinstance(path, str):
61
+ return None
62
+ raw = path.strip()
63
+ if not raw:
64
+ return None
65
+ if "\\" in raw: # 反斜杠路径不合法(服务端拒绝,不做静默转换)
66
+ return None
67
+ if raw.startswith("/") or re.match(r"^[A-Za-z]:", raw):
68
+ return None
69
+ if raw.endswith("/"): # 目录引用——尾部斜杠形成空路径段
70
+ return None
71
+ segments = raw.split("/")
72
+ if any(segment in ("", ".", "..") for segment in segments):
73
+ return None
74
+ return raw
75
+
76
+
77
+ def _bound_source_refs(path: Any, line: Any, archive_id: str) -> list[str] | None:
78
+ """构造可绑定文件来源;path 缺失时回退 archive 级来源,非法时返回 None。"""
79
+ if not path or not isinstance(path, str) or not path.strip():
80
+ return [f"archive:{archive_id}"]
81
+ valid = _valid_source_path(path)
82
+ if valid is None:
83
+ return None
84
+ if isinstance(line, int) and line > 0:
85
+ return [f"{valid}#L{line}"]
86
+ return [valid]
47
87
  _KNOWN_RISK_CONFIDENCE = 0.85
48
88
 
49
89
  # decisions[](来自 change 的 evidence/decisions.json,经 summary.decisions 传入)
@@ -141,12 +181,16 @@ def _finding_candidate(
141
181
  disposition,
142
182
  )
143
183
  source_ref = f"archive:{archive_id}#{finding_id}" if finding_id else f"archive:{archive_id}"
144
- if path and location != path:
145
- source_refs = [f"{path}#L{line}"]
146
- elif path:
147
- source_refs = [path]
148
- else:
149
- source_refs = [f"archive:{archive_id}"]
184
+ source_refs = _bound_source_refs(path, line, archive_id)
185
+ if source_refs is None:
186
+ # 目录/非法路径——跳过整条候选,不生成伪来源(服务端会拒绝整包);
187
+ # 跳过必须可见,否则「少了一条候选」无从追溯
188
+ print(
189
+ "[harness-knowledge-candidates] 跳过候选:source_refs 非法"
190
+ f"(path={path!r},finding={finding_id or title!r})",
191
+ file=sys.stderr,
192
+ )
193
+ return None
150
194
 
151
195
  return {
152
196
  "schema_version": SCHEMA_VERSION,
@@ -266,12 +310,14 @@ def _decision_candidate(
266
310
  segments[-2] if len(segments) >= 2 else "",
267
311
  entry_type,
268
312
  )
269
- if path and location != path:
270
- source_refs = [f"{path}#L{line}"]
271
- elif path:
272
- source_refs = [path]
273
- else:
274
- source_refs = [f"archive:{archive_id}"]
313
+ source_refs = _bound_source_refs(path, line, archive_id)
314
+ if source_refs is None:
315
+ print(
316
+ "[harness-knowledge-candidates] 跳过候选:source_refs 非法"
317
+ f"(path={path!r})",
318
+ file=sys.stderr,
319
+ )
320
+ return None
275
321
 
276
322
  return {
277
323
  "schema_version": SCHEMA_VERSION,
@@ -2565,6 +2565,20 @@ def cmd_can_reuse(args: argparse.Namespace) -> int:
2565
2565
  return 0
2566
2566
 
2567
2567
 
2568
+ def _profile_input_missing_warning(
2569
+ verification: str, target: Any, profile_input: str | None
2570
+ ) -> str | None:
2571
+ """S-4:profile 声明了 target 却没带 --profile-input 时提前预警。"""
2572
+ if profile_input or not isinstance(target, dict):
2573
+ return None
2574
+ return (
2575
+ "PROFILE_INPUT_MISSING: 未传 --profile-input,本条记录缺少 profile 推导的"
2576
+ " scope/coverage/inputsHash 身份字段,can-reuse 将无法复用。建议重跑:"
2577
+ f"record --verification {verification} --profile-input <key> --project . "
2578
+ "(key 见 build-profile.json verificationInputs)"
2579
+ )
2580
+
2581
+
2568
2582
  def cmd_record(args: argparse.Namespace) -> int:
2569
2583
  as_json = bool(args.json)
2570
2584
  verbose = bool(getattr(args, "verbose", False))
@@ -2612,6 +2626,11 @@ def cmd_record(args: argparse.Namespace) -> int:
2612
2626
  "verificationGraph.targets",
2613
2627
  as_json=as_json,
2614
2628
  )
2629
+ # S-4:profile 声明了 target 却没带 --profile-input,条目缺身份字段,
2630
+ # can-reuse 事后才报 MISSING_FIELDS——只能重跑一遍(2026-08-31 实测)。
2631
+ profile_input_missing_warn = _profile_input_missing_warning(
2632
+ verification, target, profile_input
2633
+ )
2615
2634
  if profile_input:
2616
2635
  resolved_files, err = expand_profile_input_files(project_root, profile_input)
2617
2636
  if err:
@@ -3068,9 +3087,14 @@ def cmd_record(args: argparse.Namespace) -> int:
3068
3087
  zero_warn = _zero_tests_with_selector_warning(
3069
3088
  str(args.command), args.evidence, project_root
3070
3089
  )
3071
- if zero_warn is not None:
3072
- payload["warnings"] = [zero_warn]
3073
- print(f"[harness-ledger] WARNING {zero_warn}", file=sys.stderr)
3090
+ record_warnings = [
3091
+ warning for warning in (zero_warn, profile_input_missing_warn)
3092
+ if warning is not None
3093
+ ]
3094
+ if record_warnings:
3095
+ payload["warnings"] = record_warnings
3096
+ for warning in record_warnings:
3097
+ print(f"[harness-ledger] WARNING {warning}", file=sys.stderr)
3074
3098
  emit_compact_or_verbose(
3075
3099
  payload, as_json=as_json, verbose=verbose,
3076
3100
  compact_fn=_compact_record_payload,
@@ -176,10 +176,24 @@ def write_findings(change_dir: Path, doc: dict[str, Any]) -> dict[str, Any]:
176
176
  "changeName": doc.get("changeName") or Path(change_dir).name,
177
177
  "findings": assigned,
178
178
  }
179
+ # 目录路径的 finding 下游产不出可绑定的知识候选(source_refs 会拒整包),
180
+ # 写入时提前可见——demo-datasource 的 quality/#L1 就是这么漏出去的
181
+ directory_paths = [
182
+ str(f.get("path"))
183
+ for f in assigned
184
+ if isinstance(f.get("path"), str) and f["path"].rstrip().endswith("/")
185
+ ]
179
186
  out = findings_path(change_dir)
180
187
  _write_json_atomic(out, payload)
181
- return {"ok": True, "code": "FINDINGS_WRITTEN", "path": str(out),
182
- "count": len(assigned)}
188
+ result = {"ok": True, "code": "FINDINGS_WRITTEN", "path": str(out),
189
+ "count": len(assigned)}
190
+ if directory_paths:
191
+ result["warnings"] = [
192
+ "以下 finding 的 path 是目录而非文件,知识候选生成时会整条跳过"
193
+ "(source_refs 无法绑定文件):" + "; ".join(directory_paths) +
194
+ "。请改为具体文件路径后重新写入"
195
+ ]
196
+ return result
183
197
 
184
198
 
185
199
  def _load_findings(change_dir: Path) -> dict[str, Any] | None:
@@ -25,7 +25,7 @@
25
25
  "files": [
26
26
  {
27
27
  "path": ".harness-build.json",
28
- "sha256": "8fe273f108d3bc5330ef415a805af2361e87e94f9e6c21141fcf5babca92ced2"
28
+ "sha256": "293b5f83b7410a48658bc712b82fc6362ecd943cad34dcdd589c4ef9e587a823"
29
29
  },
30
30
  {
31
31
  "path": "agents/harness-evaluator.md",
@@ -97,7 +97,7 @@
97
97
  },
98
98
  {
99
99
  "path": "harness-archive/SKILL.md",
100
- "sha256": "1d98f85c52d4f604e283d399a035e5dc7f5bbba555e807363eb2210ff7e6e63e"
100
+ "sha256": "3c4ec8004eb1292579b76596044089a1cbc3f9515878e2c5ac903b564503f9d5"
101
101
  },
102
102
  {
103
103
  "path": "harness-archive/templates/summary-data-template.json",
@@ -113,7 +113,7 @@
113
113
  },
114
114
  {
115
115
  "path": "harness-codebase-map/SKILL.md",
116
- "sha256": "ceca1eab8848ba6adf9d072ae960cf0094410a822bcee0759085dc5863e8574d"
116
+ "sha256": "23d695eb315cff7b699f58ad9ad5d696e4f8b8fd5bf7a1a68eb6fc31c0a0c11a"
117
117
  },
118
118
  {
119
119
  "path": "harness-codebase-map/templates/ARCHITECTURE.md",
@@ -169,7 +169,7 @@
169
169
  },
170
170
  {
171
171
  "path": "harness-execute/SKILL.md",
172
- "sha256": "ef39665e52bb15b4cc3ca6fd37ea3c30bcf2f2e0970d500dee93a7c4aebf579b"
172
+ "sha256": "a74401243a525d3648ab7c6b4d2bdd41b0d2a51a6cb85d66d935c3f8e6c7721d"
173
173
  },
174
174
  {
175
175
  "path": "harness-execute/testing-checklist.md",
@@ -189,11 +189,11 @@
189
189
  },
190
190
  {
191
191
  "path": "harness-knowledge-ingest/SKILL.md",
192
- "sha256": "c119f459a46f796a2ce06e1971671bc99badfb3ef4fd598e8fe6b9bda93bcdc6"
192
+ "sha256": "434c835b8f5031f4806521b8045cf1ebdacd463a71431a8b14ab41f1ec522882"
193
193
  },
194
194
  {
195
195
  "path": "harness-knowledge-query/SKILL.md",
196
- "sha256": "f02690a9b597dfd09bd8ee72e5bafb959ad4f058c02399f460e67c88ee18c667"
196
+ "sha256": "214ffba57778d6307fa53df03aeaa3e86e4caae57b241d5de483d4a1b1ffa433"
197
197
  },
198
198
  {
199
199
  "path": "harness-plan/checklist.md",
@@ -209,15 +209,15 @@
209
209
  },
210
210
  {
211
211
  "path": "harness-plan/SKILL.md",
212
- "sha256": "47920970196c5275db143fe186140420260b48a2d93a51d4c7694076e09cecc9"
212
+ "sha256": "7cbd8f5b1e3e758031a80851039780612f0501e35c076474a59e9fd74134d3c7"
213
213
  },
214
214
  {
215
215
  "path": "harness-pull/SKILL.md",
216
- "sha256": "761888d321d111e8f62be1cc15d065e9ecc998b44c26d9ec6d5d2d55b2136292"
216
+ "sha256": "4149c09c8333ad96848a8aca22faaf1a7cc3555454a6d51f4300cb7b4e143461"
217
217
  },
218
218
  {
219
219
  "path": "harness-push/SKILL.md",
220
- "sha256": "15f663db481e58c8192e965c96170508f3b772ac6d7cfdea009d3a457df8decf"
220
+ "sha256": "04dbb729377a0eb34cb34f71d201cc14b79825f65e85ba4b708e73a135a1bb46"
221
221
  },
222
222
  {
223
223
  "path": "harness-review/checklist.md",
@@ -233,7 +233,7 @@
233
233
  },
234
234
  {
235
235
  "path": "harness-review/SKILL.md",
236
- "sha256": "4325813de04a27156e8263a2e30944773c5083e8f66daa73fc61401ff31ab7d3"
236
+ "sha256": "5303f6363667bab35a8f57e9af7dda498a7e2de2a58e463cdf91c2d4988fac50"
237
237
  },
238
238
  {
239
239
  "path": "harness-submit/checklist.md",
@@ -245,7 +245,7 @@
245
245
  },
246
246
  {
247
247
  "path": "harness-submit/SKILL.md",
248
- "sha256": "0d0e9feb4f6f64ed7ad3b1501e4ec9c0609b6588a9f103b5a83ee4db130544fc"
248
+ "sha256": "4fd5d1618b9f87a9249bf0936593bf08f76d39d364aa9ac655b4d57910f44ca9"
249
249
  },
250
250
  {
251
251
  "path": "harness-sync/reference.md",
@@ -253,7 +253,7 @@
253
253
  },
254
254
  {
255
255
  "path": "harness-sync/SKILL.md",
256
- "sha256": "4a73db8f6b433da35cb544579c2711b3847d572d4430065ffc9d37e230f36d1f"
256
+ "sha256": "b83bbe68e2260d053e546edbd3db853cb6f8fae44ab7707520087e38f83ad55e"
257
257
  },
258
258
  {
259
259
  "path": "protocols/archive-report-protocol.md",
@@ -329,7 +329,7 @@
329
329
  },
330
330
  {
331
331
  "path": "scripts/harness_archive.py",
332
- "sha256": "a93bca73ec922a6e254a49240730ba2a60b94f5abc707c0aa5275bdd0f4071a4"
332
+ "sha256": "ae67346ff61dfc980d30a42ec85e038e23c577f8c9cf54ab8cf0a6d8c950e623"
333
333
  },
334
334
  {
335
335
  "path": "scripts/harness_change.py",
@@ -373,7 +373,7 @@
373
373
  },
374
374
  {
375
375
  "path": "scripts/harness_gate.py",
376
- "sha256": "79b22274239986f90260084020bf1be0a2e1c937688801f9094e9237d40ed94c"
376
+ "sha256": "8938d4dcc9bc52afdc445f31471ed458d5c49598185a230ccbfa0c690c2a2d67"
377
377
  },
378
378
  {
379
379
  "path": "scripts/harness_headless.py",
@@ -385,11 +385,11 @@
385
385
  },
386
386
  {
387
387
  "path": "scripts/harness_knowledge_candidates.py",
388
- "sha256": "6f17bbe80f47839bbafab73b9231cf078569a2b3275fc79c1275d039b15861fc"
388
+ "sha256": "6322e95f8eae9077b740fd8f0297c52885b0933366fde83ae68cb574eec6e7eb"
389
389
  },
390
390
  {
391
391
  "path": "scripts/harness_ledger.py",
392
- "sha256": "97e27a8d585f5af0034bb79caf71aff15231a779da2fc9f331cb2430359fb9dc"
392
+ "sha256": "56334c4da39825e88d382dcba68dd0dca5b45849c1a2214e006a14ccf7540149"
393
393
  },
394
394
  {
395
395
  "path": "scripts/harness_migration_head.py",
@@ -437,7 +437,7 @@
437
437
  },
438
438
  {
439
439
  "path": "scripts/harness_review.py",
440
- "sha256": "27084f6bd462e2ff61b175fa67fba713db1316d2cfa1498ee16413b1c135e247"
440
+ "sha256": "2d41b75fe8daf9b15e283a7c24b6222d7a664c4dd0afcbd08a9fd8d4d2d8e25e"
441
441
  },
442
442
  {
443
443
  "path": "scripts/harness_runtime.py",
@@ -25,7 +25,7 @@
25
25
  "files": [
26
26
  {
27
27
  "path": ".harness-build.json",
28
- "sha256": "a1c66c87620474534fe1f2e09158b019cfeae7a01da7300a5ccd0c5b25f93f7f"
28
+ "sha256": "e704abec9a250cb4c4bb6de4e52644d0c58a7d8615bd9ae590b3b32c8be620c6"
29
29
  },
30
30
  {
31
31
  "path": "agents/harness-evaluator.md",
@@ -97,7 +97,7 @@
97
97
  },
98
98
  {
99
99
  "path": "harness-archive/SKILL.md",
100
- "sha256": "aaedf64f8b0fd1d06b7bb0d589172e96cb5e2e16d1c34fcfaa6c28593ed77146"
100
+ "sha256": "cc345640bfbccbc59c4c06026822ded60e1bbf0701623f82972e10790823507c"
101
101
  },
102
102
  {
103
103
  "path": "harness-archive/templates/summary-data-template.json",
@@ -113,7 +113,7 @@
113
113
  },
114
114
  {
115
115
  "path": "harness-codebase-map/SKILL.md",
116
- "sha256": "a81d5183d7cb1c390c5db94d2aaf062732682237f0142a79a564a539a7aa5edf"
116
+ "sha256": "82307c586ceb08406399361a412621326588af49c1b1d663b0a64856c9ec6676"
117
117
  },
118
118
  {
119
119
  "path": "harness-codebase-map/templates/ARCHITECTURE.md",
@@ -169,7 +169,7 @@
169
169
  },
170
170
  {
171
171
  "path": "harness-execute/SKILL.md",
172
- "sha256": "7610df98f02dab16bc4b08334f7fc4e0db3c34d83c7824565522008b4612a013"
172
+ "sha256": "fea576dd732addc492e59b5e3b7ba65ece900fdb360285196b6f4034c00a206d"
173
173
  },
174
174
  {
175
175
  "path": "harness-execute/testing-checklist.md",
@@ -189,11 +189,11 @@
189
189
  },
190
190
  {
191
191
  "path": "harness-knowledge-ingest/SKILL.md",
192
- "sha256": "61127aace6221746fe5b2f34324b329214d3eff7ce2598c40e9bb369500aaa83"
192
+ "sha256": "5f232835326f4d978783081ed7c5b54c98b36f9f427a3f6d883e7278f84aca56"
193
193
  },
194
194
  {
195
195
  "path": "harness-knowledge-query/SKILL.md",
196
- "sha256": "971caf1f560c0b46f0ae7a3061c75ab7e481fc05cfd76c8453222bad0f0ed345"
196
+ "sha256": "63dd20e17fa8533141f6416b465a999f8e17fc9c0164526b77da86c31aabcb29"
197
197
  },
198
198
  {
199
199
  "path": "harness-plan/checklist.md",
@@ -209,15 +209,15 @@
209
209
  },
210
210
  {
211
211
  "path": "harness-plan/SKILL.md",
212
- "sha256": "fe4f2c2cd0706e9bdbdf8d8a152271407e7d12da5e2f20b58fb5671ead2d0ba7"
212
+ "sha256": "5d81df096a64d844e76dbdca3e5313611381102bf96f6b2d49d63090067d5993"
213
213
  },
214
214
  {
215
215
  "path": "harness-pull/SKILL.md",
216
- "sha256": "013c72aa81dd113738aa4312436f2fb5364a323f4f65445a854a3f31bdbc9f2a"
216
+ "sha256": "38675c953979348795d320abf1f5b2b5f8aca84826839fc11a224adfd6a89b36"
217
217
  },
218
218
  {
219
219
  "path": "harness-push/SKILL.md",
220
- "sha256": "3a4583e4200d99f085cc29ba63ecbab9dd2467ea302fd3f494c26994e82f98c2"
220
+ "sha256": "72e69e497f2cf044948c1e465cd323af6239a8837e82996c76528e092bd081b2"
221
221
  },
222
222
  {
223
223
  "path": "harness-review/checklist.md",
@@ -233,7 +233,7 @@
233
233
  },
234
234
  {
235
235
  "path": "harness-review/SKILL.md",
236
- "sha256": "d8b382fb54947aebf4d5b4c98b7a85678ca4d12e61849db22b297f2a523c8d48"
236
+ "sha256": "70fc4bc5139171bfa12c64f8c66357c7ff0dc5e1ba7a633bcb32edd9edf74266"
237
237
  },
238
238
  {
239
239
  "path": "harness-submit/checklist.md",
@@ -245,7 +245,7 @@
245
245
  },
246
246
  {
247
247
  "path": "harness-submit/SKILL.md",
248
- "sha256": "b0eaa4800e89c35e54d76f769490a0a95bf25a4296fede6d6e9d5031d13a1150"
248
+ "sha256": "7d59e73a26e20fea855a7eb6cac1f3979e6b4934b2cec45132fb83a86f40c7f2"
249
249
  },
250
250
  {
251
251
  "path": "harness-sync/reference.md",
@@ -253,7 +253,7 @@
253
253
  },
254
254
  {
255
255
  "path": "harness-sync/SKILL.md",
256
- "sha256": "1317bba6959dd7e87f30e19198beeaf2b9cabce13a8156fde82c27f9de3f6cfe"
256
+ "sha256": "faef8139bd3e28b179cb96ca3c9ec87b46ffc5cb0eb16efa1db4d86a4d83f168"
257
257
  },
258
258
  {
259
259
  "path": "protocols/archive-report-protocol.md",
@@ -329,7 +329,7 @@
329
329
  },
330
330
  {
331
331
  "path": "scripts/harness_archive.py",
332
- "sha256": "a93bca73ec922a6e254a49240730ba2a60b94f5abc707c0aa5275bdd0f4071a4"
332
+ "sha256": "ae67346ff61dfc980d30a42ec85e038e23c577f8c9cf54ab8cf0a6d8c950e623"
333
333
  },
334
334
  {
335
335
  "path": "scripts/harness_change.py",
@@ -373,7 +373,7 @@
373
373
  },
374
374
  {
375
375
  "path": "scripts/harness_gate.py",
376
- "sha256": "79b22274239986f90260084020bf1be0a2e1c937688801f9094e9237d40ed94c"
376
+ "sha256": "8938d4dcc9bc52afdc445f31471ed458d5c49598185a230ccbfa0c690c2a2d67"
377
377
  },
378
378
  {
379
379
  "path": "scripts/harness_headless.py",
@@ -385,11 +385,11 @@
385
385
  },
386
386
  {
387
387
  "path": "scripts/harness_knowledge_candidates.py",
388
- "sha256": "6f17bbe80f47839bbafab73b9231cf078569a2b3275fc79c1275d039b15861fc"
388
+ "sha256": "6322e95f8eae9077b740fd8f0297c52885b0933366fde83ae68cb574eec6e7eb"
389
389
  },
390
390
  {
391
391
  "path": "scripts/harness_ledger.py",
392
- "sha256": "97e27a8d585f5af0034bb79caf71aff15231a779da2fc9f331cb2430359fb9dc"
392
+ "sha256": "56334c4da39825e88d382dcba68dd0dca5b45849c1a2214e006a14ccf7540149"
393
393
  },
394
394
  {
395
395
  "path": "scripts/harness_migration_head.py",
@@ -437,7 +437,7 @@
437
437
  },
438
438
  {
439
439
  "path": "scripts/harness_review.py",
440
- "sha256": "27084f6bd462e2ff61b175fa67fba713db1316d2cfa1498ee16413b1c135e247"
440
+ "sha256": "2d41b75fe8daf9b15e283a7c24b6222d7a664c4dd0afcbd08a9fd8d4d2d8e25e"
441
441
  },
442
442
  {
443
443
  "path": "scripts/harness_runtime.py",
@@ -25,7 +25,7 @@
25
25
  "files": [
26
26
  {
27
27
  "path": ".harness-build.json",
28
- "sha256": "fa285a8b6d035b6c60435c3caf67fdf205f1b96bd634f5ef919bf2425bf693da"
28
+ "sha256": "c7fa408fbff2cd7ee1b5a2f0fc99653ca149d531b51f73b0849b880ba100063c"
29
29
  },
30
30
  {
31
31
  "path": "CONTEXT.md",
@@ -85,7 +85,7 @@
85
85
  },
86
86
  {
87
87
  "path": "harness-archive/SKILL.md",
88
- "sha256": "c50d98e3bcbf9b1119bc6e44fc0e223a737d40059dfcd30c8e0af257d238bb2d"
88
+ "sha256": "b58b2c939a924273589f63b563c31b16085c6267c58475546e3a8a988edbb94a"
89
89
  },
90
90
  {
91
91
  "path": "harness-archive/templates/summary-data-template.json",
@@ -101,7 +101,7 @@
101
101
  },
102
102
  {
103
103
  "path": "harness-codebase-map/SKILL.md",
104
- "sha256": "47fea32b1847aa9fa03aadc51f2868f004365f1d7d8e0833ac18d7afd6cf4d31"
104
+ "sha256": "cdc9643dec24a15c446c9b7d21634cb97ce38d4ff8ca2eae320746b0895f49fd"
105
105
  },
106
106
  {
107
107
  "path": "harness-codebase-map/templates/ARCHITECTURE.md",
@@ -157,7 +157,7 @@
157
157
  },
158
158
  {
159
159
  "path": "harness-execute/SKILL.md",
160
- "sha256": "5bd810b09fcb7337abc0dacd977ebf7002ee21c450cb92c30aaf0516adc93f1a"
160
+ "sha256": "dcdd807c97efb17da7a39364ab0acab37ddb960138d629a6ce98cad5dfee5a0d"
161
161
  },
162
162
  {
163
163
  "path": "harness-execute/testing-checklist.md",
@@ -177,11 +177,11 @@
177
177
  },
178
178
  {
179
179
  "path": "harness-knowledge-ingest/SKILL.md",
180
- "sha256": "e303dff1e1f7e3c55395a106d92204f9e8842822c9135fea1103e33b5b97097b"
180
+ "sha256": "54296710a55e79668109cb786badc9bdf9ea99de6ae9f4442e34aa1d974e7132"
181
181
  },
182
182
  {
183
183
  "path": "harness-knowledge-query/SKILL.md",
184
- "sha256": "a7b5db6d955d0536b8fee3164e751f6e8d6ace61192f2273a78f809cda808857"
184
+ "sha256": "b042110e544b84bfaa4fba11be8ef3daa0ac94af91d9fae4a0e4243c7e2f9508"
185
185
  },
186
186
  {
187
187
  "path": "harness-plan/checklist.md",
@@ -197,15 +197,15 @@
197
197
  },
198
198
  {
199
199
  "path": "harness-plan/SKILL.md",
200
- "sha256": "33a19ef668f79495c1f7c7e8729099a6c7c187bfa58433d2196cce5a15c7b109"
200
+ "sha256": "a8966fd02a2310ef9e9abb08e57fb38a0f732ad5fad30c7a4a816cabd48435f7"
201
201
  },
202
202
  {
203
203
  "path": "harness-pull/SKILL.md",
204
- "sha256": "9bdc70dcbe02c59b721b18a096f91b9560010d12f826563b9377041c15649b05"
204
+ "sha256": "a9268370f3f763ef6751c78e219fdc5bcb255044a4c6b56f130501ec3e52f73d"
205
205
  },
206
206
  {
207
207
  "path": "harness-push/SKILL.md",
208
- "sha256": "2e8054c96e4e8f4713b3e4ef45a0f3dffdec27776656aadd295819e6d30e4324"
208
+ "sha256": "419e5d38975334bab0be00546d7d6f72746281a3235e44ede2e6779bae70b522"
209
209
  },
210
210
  {
211
211
  "path": "harness-review/checklist.md",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  {
223
223
  "path": "harness-review/SKILL.md",
224
- "sha256": "5d9f140a47db42a03e8ed2acc86f04db6cbd5e2c122dae034e8cd8fbba1c5a65"
224
+ "sha256": "cebd17a3888190f0fb55ab6a0ce7a3222d9874b8addb1ba90c3009174747e5b9"
225
225
  },
226
226
  {
227
227
  "path": "harness-submit/checklist.md",
@@ -233,7 +233,7 @@
233
233
  },
234
234
  {
235
235
  "path": "harness-submit/SKILL.md",
236
- "sha256": "dc0d3f0e76a86c56052c8d32b126e6f8953b39f8b83b1623e50339c2c79d73a3"
236
+ "sha256": "3b20bb1b6544b47ca0371d8e4186ac41e2c39c437ffdb8cd2045446d25091728"
237
237
  },
238
238
  {
239
239
  "path": "harness-sync/reference.md",
@@ -241,7 +241,7 @@
241
241
  },
242
242
  {
243
243
  "path": "harness-sync/SKILL.md",
244
- "sha256": "7a85291eef014b59d68c55ea3d1d2afd7b7b08a1ab79590c9347195eda4542a7"
244
+ "sha256": "63a4277e0e4b81e8961d4972b100b4e35b53ae21ae9d047c14c7508e7afbad45"
245
245
  },
246
246
  {
247
247
  "path": "protocols/archive-report-protocol.md",
@@ -317,7 +317,7 @@
317
317
  },
318
318
  {
319
319
  "path": "scripts/harness_archive.py",
320
- "sha256": "a93bca73ec922a6e254a49240730ba2a60b94f5abc707c0aa5275bdd0f4071a4"
320
+ "sha256": "ae67346ff61dfc980d30a42ec85e038e23c577f8c9cf54ab8cf0a6d8c950e623"
321
321
  },
322
322
  {
323
323
  "path": "scripts/harness_change.py",
@@ -361,7 +361,7 @@
361
361
  },
362
362
  {
363
363
  "path": "scripts/harness_gate.py",
364
- "sha256": "79b22274239986f90260084020bf1be0a2e1c937688801f9094e9237d40ed94c"
364
+ "sha256": "8938d4dcc9bc52afdc445f31471ed458d5c49598185a230ccbfa0c690c2a2d67"
365
365
  },
366
366
  {
367
367
  "path": "scripts/harness_headless.py",
@@ -373,11 +373,11 @@
373
373
  },
374
374
  {
375
375
  "path": "scripts/harness_knowledge_candidates.py",
376
- "sha256": "6f17bbe80f47839bbafab73b9231cf078569a2b3275fc79c1275d039b15861fc"
376
+ "sha256": "6322e95f8eae9077b740fd8f0297c52885b0933366fde83ae68cb574eec6e7eb"
377
377
  },
378
378
  {
379
379
  "path": "scripts/harness_ledger.py",
380
- "sha256": "97e27a8d585f5af0034bb79caf71aff15231a779da2fc9f331cb2430359fb9dc"
380
+ "sha256": "56334c4da39825e88d382dcba68dd0dca5b45849c1a2214e006a14ccf7540149"
381
381
  },
382
382
  {
383
383
  "path": "scripts/harness_migration_head.py",
@@ -425,7 +425,7 @@
425
425
  },
426
426
  {
427
427
  "path": "scripts/harness_review.py",
428
- "sha256": "27084f6bd462e2ff61b175fa67fba713db1316d2cfa1498ee16413b1c135e247"
428
+ "sha256": "2d41b75fe8daf9b15e283a7c24b6222d7a664c4dd0afcbd08a9fd8d4d2d8e25e"
429
429
  },
430
430
  {
431
431
  "path": "scripts/harness_runtime.py",