@hunter-harness/workflow-harness 0.2.35 → 0.2.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/harness/bundles/general/claude-code/.harness-build.json +1 -1
  2. package/harness/bundles/general/claude-code/contracts/build-profile-v3.schema.json +147 -0
  3. package/harness/bundles/general/claude-code/contracts/doctor-capability.schema.json +43 -0
  4. package/harness/bundles/general/claude-code/contracts/external-platform-observation.schema.json +62 -0
  5. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
  6. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
  7. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  9. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  10. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
  12. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
  14. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  15. package/harness/bundles/general/claude-code/harness-sync/reference.md +2 -2
  16. package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
  17. package/harness/bundles/general/claude-code/harness-test/pitfalls.md +1 -1
  18. package/harness/bundles/general/claude-code/protocols/ci-layering-protocol.md +22 -0
  19. package/harness/bundles/general/claude-code/protocols/external-platform-protocol.md +27 -0
  20. package/harness/bundles/general/claude-code/protocols/memory-closeout-protocol.md +21 -0
  21. package/harness/bundles/general/claude-code/protocols/registry-governance-protocol.md +31 -0
  22. package/harness/bundles/general/claude-code/protocols/verification-graph-protocol.md +26 -0
  23. package/harness/bundles/general/claude-code/scripts/harness_archive.py +13 -9
  24. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +121 -12
  25. package/harness/bundles/general/claude-code/scripts/harness_preflight.py +2 -2
  26. package/harness/bundles/general/claude-code/scripts/harness_profile.py +308 -23
  27. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  28. package/harness/bundles/general/codebuddy/contracts/build-profile-v3.schema.json +147 -0
  29. package/harness/bundles/general/codebuddy/contracts/doctor-capability.schema.json +43 -0
  30. package/harness/bundles/general/codebuddy/contracts/external-platform-observation.schema.json +62 -0
  31. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  32. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  33. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  34. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  35. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  36. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
  37. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
  38. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  39. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
  40. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  41. package/harness/bundles/general/codebuddy/harness-sync/reference.md +2 -2
  42. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
  43. package/harness/bundles/general/codebuddy/harness-test/pitfalls.md +1 -1
  44. package/harness/bundles/general/codebuddy/protocols/ci-layering-protocol.md +22 -0
  45. package/harness/bundles/general/codebuddy/protocols/external-platform-protocol.md +27 -0
  46. package/harness/bundles/general/codebuddy/protocols/memory-closeout-protocol.md +21 -0
  47. package/harness/bundles/general/codebuddy/protocols/registry-governance-protocol.md +31 -0
  48. package/harness/bundles/general/codebuddy/protocols/verification-graph-protocol.md +26 -0
  49. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +13 -9
  50. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +121 -12
  51. package/harness/bundles/general/codebuddy/scripts/harness_preflight.py +2 -2
  52. package/harness/bundles/general/codebuddy/scripts/harness_profile.py +308 -23
  53. package/harness/bundles/general/codex/.harness-build.json +1 -1
  54. package/harness/bundles/general/codex/contracts/build-profile-v3.schema.json +147 -0
  55. package/harness/bundles/general/codex/contracts/doctor-capability.schema.json +43 -0
  56. package/harness/bundles/general/codex/contracts/external-platform-observation.schema.json +62 -0
  57. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  58. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  59. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  60. package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  61. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  62. package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
  63. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  64. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  65. package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
  66. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  67. package/harness/bundles/general/codex/harness-sync/reference.md +2 -2
  68. package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
  69. package/harness/bundles/general/codex/harness-test/pitfalls.md +1 -1
  70. package/harness/bundles/general/codex/protocols/ci-layering-protocol.md +22 -0
  71. package/harness/bundles/general/codex/protocols/external-platform-protocol.md +27 -0
  72. package/harness/bundles/general/codex/protocols/memory-closeout-protocol.md +21 -0
  73. package/harness/bundles/general/codex/protocols/registry-governance-protocol.md +31 -0
  74. package/harness/bundles/general/codex/protocols/verification-graph-protocol.md +26 -0
  75. package/harness/bundles/general/codex/scripts/harness_archive.py +13 -9
  76. package/harness/bundles/general/codex/scripts/harness_ledger.py +121 -12
  77. package/harness/bundles/general/codex/scripts/harness_preflight.py +2 -2
  78. package/harness/bundles/general/codex/scripts/harness_profile.py +308 -23
  79. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  80. package/harness/bundles/general/cursor/contracts/build-profile-v3.schema.json +147 -0
  81. package/harness/bundles/general/cursor/contracts/doctor-capability.schema.json +43 -0
  82. package/harness/bundles/general/cursor/contracts/external-platform-observation.schema.json +62 -0
  83. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  84. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  85. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  86. package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  87. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  88. package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
  89. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  90. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  91. package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
  92. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  93. package/harness/bundles/general/cursor/harness-sync/reference.md +2 -2
  94. package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
  95. package/harness/bundles/general/cursor/harness-test/pitfalls.md +1 -1
  96. package/harness/bundles/general/cursor/protocols/ci-layering-protocol.md +22 -0
  97. package/harness/bundles/general/cursor/protocols/external-platform-protocol.md +27 -0
  98. package/harness/bundles/general/cursor/protocols/memory-closeout-protocol.md +21 -0
  99. package/harness/bundles/general/cursor/protocols/registry-governance-protocol.md +31 -0
  100. package/harness/bundles/general/cursor/protocols/verification-graph-protocol.md +26 -0
  101. package/harness/bundles/general/cursor/scripts/harness_archive.py +13 -9
  102. package/harness/bundles/general/cursor/scripts/harness_ledger.py +121 -12
  103. package/harness/bundles/general/cursor/scripts/harness_preflight.py +2 -2
  104. package/harness/bundles/general/cursor/scripts/harness_profile.py +308 -23
  105. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  106. package/harness/bundles/java/claude-code/contracts/build-profile-v3.schema.json +147 -0
  107. package/harness/bundles/java/claude-code/contracts/doctor-capability.schema.json +43 -0
  108. package/harness/bundles/java/claude-code/contracts/external-platform-observation.schema.json +62 -0
  109. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  110. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  111. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  112. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  113. package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  114. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  115. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  116. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
  117. package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
  118. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  119. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
  120. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  121. package/harness/bundles/java/claude-code/harness-sync/reference.md +2 -2
  122. package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
  123. package/harness/bundles/java/claude-code/harness-test/pitfalls.md +1 -1
  124. package/harness/bundles/java/claude-code/protocols/ci-layering-protocol.md +22 -0
  125. package/harness/bundles/java/claude-code/protocols/external-platform-protocol.md +27 -0
  126. package/harness/bundles/java/claude-code/protocols/memory-closeout-protocol.md +21 -0
  127. package/harness/bundles/java/claude-code/protocols/registry-governance-protocol.md +31 -0
  128. package/harness/bundles/java/claude-code/protocols/verification-graph-protocol.md +26 -0
  129. package/harness/bundles/java/claude-code/scripts/harness_archive.py +13 -9
  130. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +121 -12
  131. package/harness/bundles/java/claude-code/scripts/harness_preflight.py +2 -2
  132. package/harness/bundles/java/claude-code/scripts/harness_profile.py +308 -23
  133. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  134. package/harness/bundles/java/codebuddy/contracts/build-profile-v3.schema.json +147 -0
  135. package/harness/bundles/java/codebuddy/contracts/doctor-capability.schema.json +43 -0
  136. package/harness/bundles/java/codebuddy/contracts/external-platform-observation.schema.json +62 -0
  137. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  138. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  139. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  140. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  141. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  142. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  143. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  144. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
  145. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
  146. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  147. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
  148. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  149. package/harness/bundles/java/codebuddy/harness-sync/reference.md +2 -2
  150. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
  151. package/harness/bundles/java/codebuddy/harness-test/pitfalls.md +1 -1
  152. package/harness/bundles/java/codebuddy/protocols/ci-layering-protocol.md +22 -0
  153. package/harness/bundles/java/codebuddy/protocols/external-platform-protocol.md +27 -0
  154. package/harness/bundles/java/codebuddy/protocols/memory-closeout-protocol.md +21 -0
  155. package/harness/bundles/java/codebuddy/protocols/registry-governance-protocol.md +31 -0
  156. package/harness/bundles/java/codebuddy/protocols/verification-graph-protocol.md +26 -0
  157. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +13 -9
  158. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +121 -12
  159. package/harness/bundles/java/codebuddy/scripts/harness_preflight.py +2 -2
  160. package/harness/bundles/java/codebuddy/scripts/harness_profile.py +308 -23
  161. package/harness/bundles/java/codex/.harness-build.json +1 -1
  162. package/harness/bundles/java/codex/contracts/build-profile-v3.schema.json +147 -0
  163. package/harness/bundles/java/codex/contracts/doctor-capability.schema.json +43 -0
  164. package/harness/bundles/java/codex/contracts/external-platform-observation.schema.json +62 -0
  165. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  166. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  167. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  168. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  169. package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  170. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  171. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  172. package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
  173. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  174. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  175. package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
  176. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  177. package/harness/bundles/java/codex/harness-sync/reference.md +2 -2
  178. package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
  179. package/harness/bundles/java/codex/harness-test/pitfalls.md +1 -1
  180. package/harness/bundles/java/codex/protocols/ci-layering-protocol.md +22 -0
  181. package/harness/bundles/java/codex/protocols/external-platform-protocol.md +27 -0
  182. package/harness/bundles/java/codex/protocols/memory-closeout-protocol.md +21 -0
  183. package/harness/bundles/java/codex/protocols/registry-governance-protocol.md +31 -0
  184. package/harness/bundles/java/codex/protocols/verification-graph-protocol.md +26 -0
  185. package/harness/bundles/java/codex/scripts/harness_archive.py +13 -9
  186. package/harness/bundles/java/codex/scripts/harness_ledger.py +121 -12
  187. package/harness/bundles/java/codex/scripts/harness_preflight.py +2 -2
  188. package/harness/bundles/java/codex/scripts/harness_profile.py +308 -23
  189. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  190. package/harness/bundles/java/cursor/contracts/build-profile-v3.schema.json +147 -0
  191. package/harness/bundles/java/cursor/contracts/doctor-capability.schema.json +43 -0
  192. package/harness/bundles/java/cursor/contracts/external-platform-observation.schema.json +62 -0
  193. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  194. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  195. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  196. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  197. package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +24 -1
  198. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  199. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  200. package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
  201. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  202. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  203. package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
  204. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  205. package/harness/bundles/java/cursor/harness-sync/reference.md +2 -2
  206. package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
  207. package/harness/bundles/java/cursor/harness-test/pitfalls.md +1 -1
  208. package/harness/bundles/java/cursor/protocols/ci-layering-protocol.md +22 -0
  209. package/harness/bundles/java/cursor/protocols/external-platform-protocol.md +27 -0
  210. package/harness/bundles/java/cursor/protocols/memory-closeout-protocol.md +21 -0
  211. package/harness/bundles/java/cursor/protocols/registry-governance-protocol.md +31 -0
  212. package/harness/bundles/java/cursor/protocols/verification-graph-protocol.md +26 -0
  213. package/harness/bundles/java/cursor/scripts/harness_archive.py +13 -9
  214. package/harness/bundles/java/cursor/scripts/harness_ledger.py +121 -12
  215. package/harness/bundles/java/cursor/scripts/harness_preflight.py +2 -2
  216. package/harness/bundles/java/cursor/scripts/harness_profile.py +308 -23
  217. package/harness/manifests/general/claude-code.json +58 -20
  218. package/harness/manifests/general/codebuddy.json +58 -20
  219. package/harness/manifests/general/codex.json +58 -20
  220. package/harness/manifests/general/cursor.json +58 -20
  221. package/harness/manifests/java/claude-code.json +60 -22
  222. package/harness/manifests/java/codebuddy.json +60 -22
  223. package/harness/manifests/java/codex.json +60 -22
  224. package/harness/manifests/java/cursor.json +60 -22
  225. package/hunter-workflow-family.json +17 -5
  226. package/package.json +1 -1
@@ -82,6 +82,63 @@ REQUIRED_COVERAGE = {
82
82
  _EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
83
83
 
84
84
 
85
+ def resolve_verification_target(
86
+ verification: str,
87
+ project_root: Path | None,
88
+ ) -> dict[str, Any] | None:
89
+ """Resolve a built-in or project-declared profile-v3 verification target."""
90
+ if not isinstance(verification, str) or not re.fullmatch(
91
+ r"[A-Za-z][A-Za-z0-9_-]{0,63}",
92
+ verification,
93
+ ):
94
+ return None
95
+ if project_root is not None:
96
+ profile = harness_profile.load_profile(project_root)
97
+ graph = (
98
+ profile.get("verificationGraph")
99
+ if isinstance(profile, dict)
100
+ else None
101
+ )
102
+ targets = graph.get("targets") if isinstance(graph, dict) else None
103
+ target = targets.get(verification) if isinstance(targets, dict) else None
104
+ if isinstance(target, dict):
105
+ required = str(target.get("requiredCoverage") or "module")
106
+ if required not in COVERAGE_RANK:
107
+ return None
108
+ return {**target, "requiredCoverage": required}
109
+ if verification in VERIFICATIONS:
110
+ required_rank = REQUIRED_COVERAGE.get(verification, 1)
111
+ required = next(
112
+ (
113
+ name
114
+ for name, rank in COVERAGE_RANK.items()
115
+ if rank == required_rank
116
+ ),
117
+ "module",
118
+ )
119
+ return {
120
+ "commandKey": verification,
121
+ "dependsOn": [],
122
+ "requiredCoverage": required,
123
+ "candidate": verification == "unitTestFull",
124
+ "requiredCapabilities": [],
125
+ }
126
+ return None
127
+
128
+
129
+ def verification_target_identity(
130
+ verification: str,
131
+ target: dict[str, Any],
132
+ ) -> str:
133
+ payload = json.dumps(
134
+ {"verification": verification, "target": target},
135
+ ensure_ascii=False,
136
+ sort_keys=True,
137
+ separators=(",", ":"),
138
+ ).encode("utf-8")
139
+ return "sha256:" + hashlib.sha256(payload).hexdigest()
140
+
141
+
85
142
  def now_iso() -> str:
86
143
  return dt.datetime.now().astimezone().isoformat(timespec="milliseconds")
87
144
 
@@ -1075,6 +1132,8 @@ def decide_can_reuse(
1075
1132
  requested_profile_hash: str | None = None,
1076
1133
  requested_environment_hash: str | None = None,
1077
1134
  requested_db_schema_hash: str | None = None,
1135
+ requested_target_identity: str | None = None,
1136
+ required_coverage: str | None = None,
1078
1137
  project_root: Path | str | None = None,
1079
1138
  ) -> dict[str, Any]:
1080
1139
  ledger, ledger_path = load_ledger(change_dir)
@@ -1136,6 +1195,7 @@ def decide_can_reuse(
1136
1195
  scope = entry.get("scope")
1137
1196
  algorithm_version = entry.get("algorithmVersion")
1138
1197
  coverage = entry.get("coverage")
1198
+ stored_target_identity = entry.get("targetIdentity")
1139
1199
 
1140
1200
  if entry.get("reusable") is False or isinstance(entry.get("invalidation"), dict):
1141
1201
  return {
@@ -1198,7 +1258,11 @@ def decide_can_reuse(
1198
1258
  # Coverage lattice: recorded coverage rank must meet the verification's
1199
1259
  # required rank. Stops incremental evidence satisfying a module/full gate
1200
1260
  # (UT-015 / API-005).
1201
- required = REQUIRED_COVERAGE.get(verification, 1)
1261
+ required = (
1262
+ COVERAGE_RANK.get(required_coverage, 1)
1263
+ if required_coverage is not None
1264
+ else REQUIRED_COVERAGE.get(verification, 1)
1265
+ )
1202
1266
  if COVERAGE_RANK.get(str(coverage).strip(), -1) < required:
1203
1267
  return {
1204
1268
  "ok": True,
@@ -1211,6 +1275,31 @@ def decide_can_reuse(
1211
1275
  "stored_coverage": coverage,
1212
1276
  }
1213
1277
 
1278
+ if _nonempty_str(requested_target_identity):
1279
+ if not _nonempty_str(stored_target_identity):
1280
+ return {
1281
+ "ok": True,
1282
+ "reuse": False,
1283
+ "reason": "insufficient-evidence",
1284
+ "code": "MISSING_TARGET_IDENTITY",
1285
+ "verification": verification,
1286
+ "detail": "recorded evidence predates the current verification target identity",
1287
+ "ledger_path": str(ledger_path) if ledger_path else None,
1288
+ "requested_target_identity": requested_target_identity,
1289
+ }
1290
+ if str(stored_target_identity).strip() != str(requested_target_identity).strip():
1291
+ return {
1292
+ "ok": True,
1293
+ "reuse": False,
1294
+ "reason": "rerun",
1295
+ "code": "TARGET_IDENTITY_CHANGED",
1296
+ "verification": verification,
1297
+ "detail": "verification target definition changed",
1298
+ "ledger_path": str(ledger_path) if ledger_path else None,
1299
+ "stored_target_identity": stored_target_identity,
1300
+ "requested_target_identity": requested_target_identity,
1301
+ }
1302
+
1214
1303
  if requested_command is not None and str(requested_command).strip():
1215
1304
  if str(command).strip() != str(requested_command).strip():
1216
1305
  return {
@@ -1352,6 +1441,7 @@ def upsert_verification_graph_node(
1352
1441
  environment_hash: str | None = None,
1353
1442
  db_schema_hash: str | None = None,
1354
1443
  diff_hash: str | None = None,
1444
+ target_identity: str | None = None,
1355
1445
  ) -> dict[str, Any]:
1356
1446
  """Persist a verification graph node keyed by canonical identity (H-9)."""
1357
1447
  path = verification_graph_path(change_dir)
@@ -1376,6 +1466,7 @@ def upsert_verification_graph_node(
1376
1466
  "environmentHash": environment_hash,
1377
1467
  "dbSchemaHash": db_schema_hash,
1378
1468
  "diffHash": diff_hash,
1469
+ "targetIdentity": target_identity,
1379
1470
  }
1380
1471
  node = {
1381
1472
  "identity": identity,
@@ -1427,16 +1518,19 @@ def cmd_can_reuse(args: argparse.Namespace) -> int:
1427
1518
  as_json = bool(args.json)
1428
1519
  verbose = bool(getattr(args, "verbose", False))
1429
1520
  verification = args.verification
1430
- if verification not in VERIFICATIONS:
1431
- return emit_error(
1432
- f"unsupported verification: {verification}; expected one of {sorted(VERIFICATIONS)}",
1433
- as_json=as_json,
1434
- )
1435
1521
  change_dir = resolve_path(args.change_dir)
1436
1522
  try:
1437
1523
  files, project_root = input_files_from_args(args)
1438
1524
  except (OSError, ValueError) as exc:
1439
1525
  return emit_error(f"can-reuse failed: {exc}", as_json=as_json)
1526
+ target = resolve_verification_target(verification, project_root)
1527
+ if target is None:
1528
+ return emit_error(
1529
+ "unsupported verification: "
1530
+ f"{verification}; declare it in build-profile.json "
1531
+ "verificationGraph.targets",
1532
+ as_json=as_json,
1533
+ )
1440
1534
  profile_input = getattr(args, "profile_input", None)
1441
1535
  project_raw = getattr(args, "project", None)
1442
1536
  if profile_input:
@@ -1474,6 +1568,10 @@ def cmd_can_reuse(args: argparse.Namespace) -> int:
1474
1568
  requested_profile_hash=getattr(args, "profile_hash", None),
1475
1569
  requested_environment_hash=getattr(args, "environment_hash", None),
1476
1570
  requested_db_schema_hash=getattr(args, "db_schema_hash", None),
1571
+ requested_target_identity=verification_target_identity(
1572
+ verification, target
1573
+ ),
1574
+ required_coverage=str(target["requiredCoverage"]),
1477
1575
  project_root=project_root,
1478
1576
  )
1479
1577
  except (OSError, ValueError, json.JSONDecodeError) as exc:
@@ -1492,11 +1590,6 @@ def cmd_record(args: argparse.Namespace) -> int:
1492
1590
  verbose = bool(getattr(args, "verbose", False))
1493
1591
  change_dir = resolve_path(args.change_dir)
1494
1592
  verification = args.verification
1495
- if verification not in VERIFICATIONS:
1496
- return emit_error(
1497
- f"unsupported verification: {verification}; expected one of {sorted(VERIFICATIONS)}",
1498
- as_json=as_json,
1499
- )
1500
1593
  contract_v2 = _contract_is_v2(change_dir)
1501
1594
  if not contract_v2 and any(
1502
1595
  _nonempty_str(getattr(args, field, None))
@@ -1510,6 +1603,14 @@ def cmd_record(args: argparse.Namespace) -> int:
1510
1603
  files, project_root = input_files_from_args(args)
1511
1604
  except (OSError, ValueError) as exc:
1512
1605
  return emit_error(f"record failed: {exc}", as_json=as_json)
1606
+ target = resolve_verification_target(verification, project_root)
1607
+ if target is None:
1608
+ return emit_error(
1609
+ "unsupported verification: "
1610
+ f"{verification}; declare it in build-profile.json "
1611
+ "verificationGraph.targets",
1612
+ as_json=as_json,
1613
+ )
1513
1614
  profile_input = getattr(args, "profile_input", None)
1514
1615
  project_raw = getattr(args, "project", None)
1515
1616
  if profile_input:
@@ -1610,6 +1711,9 @@ def cmd_record(args: argparse.Namespace) -> int:
1610
1711
  # toolchain/profile/environment hashes. v1 entries missing these are
1611
1712
  # conservatively invalidated by can-reuse (COM-002).
1612
1713
  entry["algorithmVersion"] = LEDGER_VERSION
1714
+ entry["targetIdentity"] = verification_target_identity(
1715
+ verification, target
1716
+ )
1613
1717
  coverage = getattr(args, "coverage", None)
1614
1718
  if not (_nonempty_str(coverage) and str(coverage).strip() in COVERAGE_RANK):
1615
1719
  coverage = derive_coverage(verification, args.scope)
@@ -1757,6 +1861,11 @@ def cmd_record(args: argparse.Namespace) -> int:
1757
1861
  if _nonempty_str(ledger.get("diffHash"))
1758
1862
  else None
1759
1863
  ),
1864
+ target_identity=(
1865
+ str(entry.get("targetIdentity")).strip()
1866
+ if _nonempty_str(entry.get("targetIdentity"))
1867
+ else None
1868
+ ),
1760
1869
  )
1761
1870
  except (OSError, ValueError, TypeError):
1762
1871
  # Graph is advisory persistence; ledger write already succeeded.
@@ -1832,7 +1941,7 @@ def build_parser() -> argparse.ArgumentParser:
1832
1941
  p_reuse.add_argument(
1833
1942
  "--verification",
1834
1943
  required=True,
1835
- choices=sorted(VERIFICATIONS),
1944
+ help="built-in or build-profile v3 verificationGraph target",
1836
1945
  )
1837
1946
  p_reuse.add_argument(
1838
1947
  "--files",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  """Harness preflight: build-profile detect/check + quirk recording + agent precheck.
3
3
 
4
- 变更簇 4:detect/check 委托 ``harness_profile``(profile v2 公共内核),不再保留
4
+ 变更簇 4:detect/check 委托 ``harness_profile``(Build Profile v3 公共内核),不再保留
5
5
  v1 重复探测逻辑与 ``buildCommands`` 扁平字符串。record-quirk 适配 v2 ``commands``
6
6
  结构:``fix-command`` 写 ``source=user`` override(spec §3.1 显式保留),跨 detect
7
7
  保留;``skip-not-block`` 仍写 ``knownPreexistingErrors``。check-agents 与 pitfalls
@@ -51,7 +51,7 @@ def emit_json(payload: dict[str, Any], *, ok: bool = True) -> int:
51
51
 
52
52
 
53
53
  # ---------------------------------------------------------------------------
54
- # detect / check — 委托 harness_profile(profile v2 公共内核)
54
+ # detect / check — 委托 harness_profile(Build Profile v3 公共内核)
55
55
  # ---------------------------------------------------------------------------
56
56
 
57
57
  def cmd_detect(project: Path) -> dict[str, Any]: