@hunter-harness/workflow-harness 0.2.34 → 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 +24 -12
  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 +24 -12
  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 +24 -12
  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 +24 -12
  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 +24 -12
  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 +24 -12
  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 +24 -12
  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 +24 -12
  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
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://hunter-harness.local/contracts/doctor-capability.schema.json",
4
+ "title": "Hunter Harness Capability Probe",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "capability",
9
+ "status",
10
+ "reasonCode",
11
+ "observedAt",
12
+ "evidence"
13
+ ],
14
+ "properties": {
15
+ "capability": {
16
+ "type": "string",
17
+ "minLength": 1
18
+ },
19
+ "status": {
20
+ "enum": [
21
+ "AVAILABLE",
22
+ "UNAVAILABLE",
23
+ "DEGRADED",
24
+ "UNKNOWN"
25
+ ]
26
+ },
27
+ "reasonCode": {
28
+ "type": "string",
29
+ "minLength": 1
30
+ },
31
+ "observedAt": {
32
+ "type": "string",
33
+ "format": "date-time"
34
+ },
35
+ "evidence": {
36
+ "type": "array",
37
+ "items": {
38
+ "type": "string"
39
+ }
40
+ },
41
+ "details": {}
42
+ }
43
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://hunter-harness.local/contracts/external-platform-observation.schema.json",
4
+ "title": "Authoritative External Platform Observation",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "subjectIdentity",
9
+ "businessState",
10
+ "observationState",
11
+ "freshness",
12
+ "retryable",
13
+ "reasonCode",
14
+ "observedAt"
15
+ ],
16
+ "properties": {
17
+ "subjectIdentity": {
18
+ "type": "string",
19
+ "minLength": 1
20
+ },
21
+ "businessState": {
22
+ "enum": [
23
+ "PENDING",
24
+ "RUNNING",
25
+ "SUCCEEDED",
26
+ "FAILED",
27
+ "CANCELLED",
28
+ "UNKNOWN"
29
+ ]
30
+ },
31
+ "observationState": {
32
+ "enum": [
33
+ "PENDING",
34
+ "TERMINAL",
35
+ "UNKNOWN"
36
+ ]
37
+ },
38
+ "freshness": {
39
+ "enum": [
40
+ "FRESH",
41
+ "STALE",
42
+ "UNKNOWN"
43
+ ]
44
+ },
45
+ "retryable": {
46
+ "type": "boolean"
47
+ },
48
+ "reasonCode": {
49
+ "type": "string",
50
+ "minLength": 1
51
+ },
52
+ "observedAt": {
53
+ "type": "string",
54
+ "format": "date-time"
55
+ },
56
+ "idempotencyKey": {
57
+ "type": "string",
58
+ "minLength": 1
59
+ },
60
+ "payload": {}
61
+ }
62
+ }
@@ -3,7 +3,7 @@ name: harness-archive
3
3
  description: 归档所有变更产出(计划/测试报告/审查/SQL/API文档)到
4
4
  .harness/archive/,含归档元数据和可视化最终总结。使用场景:归档、完成归档、收尾、打包产出物
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
7
7
  # harness-archive — 变更归档
8
8
 
9
9
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-codebase-map
3
3
  description: 分析现有代码库并生成 .harness/codebase/map/
4
4
  下的结构化代码库地图。用于陌生项目理解、重大改造前梳理、harness-sync 提示 map 过期后的人工刷新。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
7
7
  # harness-codebase-map — 代码库地图
8
8
 
9
9
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-knowledge-ingest
3
3
  description: 从 .harness/archive 归档整理、同步和维护项目知识索引。适用场景:ingest knowledge、sync
4
4
  knowledge、rebuild knowledge index、promote knowledge、确认知识条目、检查知识库是否过期。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
7
7
  # harness-knowledge-ingest
8
8
 
9
9
  从 `.harness/archive/**/reports/final/summary-data.json` 抽取项目知识,生成并维护本地 `.harness/knowledge/` 索引。
@@ -1397,7 +1397,8 @@ def load_preserved_entries(knowledge: Path) -> list[dict[str, Any]]:
1397
1397
  entry
1398
1398
  for status in ["candidate", "stale", "superseded", "conflicted"]
1399
1399
  for entry in load_entries_from_dir(knowledge / "entries" / status)
1400
- if entry.get("lifecycle", {}).get("demotedAt")
1400
+ if status == "superseded"
1401
+ or entry.get("lifecycle", {}).get("demotedAt")
1401
1402
  or entry.get("lifecycle", {}).get("judgeAction")
1402
1403
  ]
1403
1404
  return active_entries + manually_decided_entries
@@ -1762,6 +1763,27 @@ def _preserve_confidence_timestamp(target: Path, entry: dict[str, Any]) -> None:
1762
1763
  entry["confidence"]["lastCalculatedAt"] = disk_conf.get("lastCalculatedAt")
1763
1764
 
1764
1765
 
1766
+ def remove_other_entry_status_files(
1767
+ knowledge: Path,
1768
+ entry: dict[str, Any],
1769
+ target: Path,
1770
+ ) -> None:
1771
+ entry_id = str(entry.get("id") or "")
1772
+ if not entry_id:
1773
+ return
1774
+ filename = entry_filename(entry)
1775
+ for status in ["candidate", "active", "stale", "superseded", "conflicted"]:
1776
+ existing_path = knowledge / "entries" / status / filename
1777
+ if existing_path == target or not existing_path.exists():
1778
+ continue
1779
+ try:
1780
+ existing = read_json(existing_path)
1781
+ except (OSError, json.JSONDecodeError):
1782
+ continue
1783
+ if isinstance(existing, dict) and str(existing.get("id") or "") == entry_id:
1784
+ existing_path.unlink()
1785
+
1786
+
1765
1787
  def persist_entry_updates(knowledge: Path, entries: list[dict[str, Any]]) -> int:
1766
1788
  written = 0
1767
1789
  for entry in entries:
@@ -1773,6 +1795,7 @@ def persist_entry_updates(knowledge: Path, entries: list[dict[str, Any]]) -> int
1773
1795
  _preserve_confidence_timestamp(path, entry)
1774
1796
  if write_json_if_changed(path, entry):
1775
1797
  written += 1
1798
+ remove_other_entry_status_files(knowledge, entry, path)
1776
1799
  return written
1777
1800
 
1778
1801
 
@@ -3,7 +3,7 @@ name: harness-knowledge-query
3
3
  description: 根据新需求、设计任务、代码修改请求或问题排查,在规划和编码前查询 .harness/knowledge
4
4
  历史上下文。适用场景:query knowledge、查找历史需求、根据归档理解需求、继续之前类似开发、生成需求上下文包。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
7
7
  # harness-knowledge-query
8
8
 
9
9
  并行 change 中查询必须传 `--change <change-id>`;成功后以该 change 的 `meta/knowledge-context.json` 为稳定指针。全局 `context-packs/latest.json` 仅向后兼容,不得用于判断多个 active change 的上下文归属。
@@ -2,7 +2,7 @@
2
2
  name: harness-plan
3
3
  description: 将需求转化为设计文档+实施计划+完整测试场景表,必须在编码前完成。使用场景:需求分析、feature plan、技术方案设计、实现方案规划
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
6
6
  # harness-plan — 需求规划
7
7
 
8
8
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-review
3
3
  description: 6维度代码审查(架构/安全/规范/兼容/测试/性能),对照项目规则(见
4
4
  .harness/context-index.json)和测试场景表,在隔离上下文运行。使用场景:代码审查、提交前检查、合并评审
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
7
7
  # harness-review — 代码审查
8
8
 
9
9
  ## Purpose
@@ -2,7 +2,7 @@
2
2
  name: harness-run
3
3
  description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编译验证),逐变更簇实现计划中的任务。使用场景:开始编码、实现功能、写代码、TDD 编码
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
6
6
  # harness-run — 需求编码
7
7
 
8
8
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-submit
3
3
  description: 最终提交封装:验证→中文 commit→提交/推送;worktree 模式含 --no-ff
4
4
  合并回主分支。使用场景:提交代码、commit、push、合并分支、merge to main、完成开发
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
7
7
  # harness-submit — 最终提交(含 worktree 合并)
8
8
 
9
9
  ## Purpose
@@ -4,7 +4,7 @@ description: Use when the user asks to synchronize, refresh, or validate Harness
4
4
  metadata, adapters, knowledge, rules, instruction entrypoints, config origins,
5
5
  or CodeGraph status.
6
6
  ---
7
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
7
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
8
8
  # harness-sync
9
9
 
10
10
  ## Purpose
@@ -77,7 +77,7 @@ npx hunter-harness sync --project <项目路径> --profile general --progress js
77
77
  | instruction graph | 入口、include 边、环、主题可达性 | 缺失引用或循环为 `FAIL` |
78
78
  | config origins | canonical/projection 路径与 hash | 漂移 `WARN`,不静默覆盖 |
79
79
  | changes | 五态分类及归档收据 | `INVALID`/`ORPHAN` 不自动删除 |
80
- | CodeGraph | 服务、索引提交、pending、watcher lag | 证据不足为 `UNKNOWN`;不自动全量 reindex |
80
+ | CodeGraph | 索引文件、守护进程管道、watcher 日志、pending、watcher lag | 输出 `CURRENT/PENDING/STALE/INDEX_PRESENT_UNVERIFIED/MISSING/UNKNOWN`;不自动全量 reindex |
81
81
 
82
82
  全局状态优先级:`BLOCKED` → `FAIL` → `WARN` → `OK`。任一 `UNKNOWN` 至少使全局结果为 `WARN`。
83
83
 
@@ -85,7 +85,7 @@ npx hunter-harness sync --project <项目路径> --profile general --progress js
85
85
 
86
86
  增量基线来自上次成功 sync receipt 的 `headCommit`。首次运行或 receipt 不可用时,仅收集当前 HEAD 和有界文件统计;禁止固定 `HEAD~5`。
87
87
 
88
- CodeGraph 最多执行受限状态探测/短退避复查。不可用或 watcher 尚未追平时报告 `UNKNOWN`/`WARN` 和明确后续动作。不要在 sync 内执行全量索引,不使用依赖 shell 连接符的跨平台命令。
88
+ CodeGraph 状态探测读取 `.codegraph/codegraph.db`、daemon receipt/log,尝试有界管道连接,并比较项目文件与最近索引观察时间。只有服务可达、watcher 已启用且 `pendingFileCount=0` 时为 `CURRENT`;此时才可将当前 HEAD 记录为推断的 `indexedCommit`。不可用、待同步或证据不足时分别报告 `STALE/PENDING/INDEX_PRESENT_UNVERIFIED/UNKNOWN` 与明确后续动作。不要在 sync 内执行全量索引,不使用依赖 shell 连接符的跨平台命令。
89
89
 
90
90
  ## 6. Instruction graph
91
91
 
@@ -2,7 +2,7 @@
2
2
  name: harness-test
3
3
  description: 测试执行:读取场景表,执行单元测试+API接口测试+数据兼容验证,输出测试报告。当用户说'跑测试/验证/跑用例/接口测试/单元测试'时使用
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=a74978a5fd5c6938; overlay=none; agent=codebuddy; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=53e62510d9d800ee; overlay=none; agent=codebuddy; do not edit -->
6
6
  # harness-test — 测试执行
7
7
 
8
8
  ## Purpose
@@ -271,6 +271,6 @@ $cred = $resp.data.accessToken
271
271
  | `validateRunnerPayload(payload, {identifierPattern})` | Runner 生成前本地校验 payload schema/必填/identifier/重复 id,返回结构化错误码 | 测试脚本错误(缺字段/非法 id)直到请求服务后才暴露,返工成本高 |
272
272
  | `findCredentialValues(text)` | 扫描 profile/Markdown/docs 中的凭据明文值(password/token/secret/Authorization/jdbc password),占位符 `<*_REDACTED>` 与 env 引用 `${ENV}`/`$ENV` 不报 | profile/规则文档误含明文凭据被发布 |
273
273
 
274
- **Runner 生成前强制**(spec §3.4 point 3):生成 `api-test-runner.mjs` 前用 `validateRunnerPayload` 校验全部场景;`ok=false` → 修复脚本错误,**不得带错请求服务**。场景 id 用 `sanitizeTestIdentifier` 生成(profile v2 `identifier.pattern/maxLength/prefix` 已声明)。
274
+ **Runner 生成前强制**(spec §3.4 point 3):生成 `api-test-runner.mjs` 前用 `validateRunnerPayload` 校验全部场景;`ok=false` → 修复脚本错误,**不得带错请求服务**。场景 id 用 `sanitizeTestIdentifier` 生成(Build Profile v3 `identifier.pattern/maxLength/prefix` 已声明)。
275
275
 
276
276
  **凭据边界**(spec §3.4 point 4):credential 配置只含 env key(如 `${TEST_TOKEN}`)、cache path、角色,不含值。发布前用 `findCredentialValues` 扫 profile/规则/Markdown,命中即 ❌FAIL。详见 `../protocols/sensitive-info-protocol.md` §6。
@@ -0,0 +1,22 @@
1
+ # CI 分层与构建产物复用协议
2
+
3
+ 所有项目将远端验证拆成四层,触发条件和产物身份必须彼此独立:
4
+
5
+ | 层 | 默认触发 | 工作内容 |
6
+ |---|---|---|
7
+ | `fast` | push / pull request | 影响选择后的格式、合同和单元门禁;分钟级反馈 |
8
+ | `candidate` | 冻结产品 identity 后手动触发 | 完整测试、真实栈、安全扫描、SBOM;每个 identity 最多一次 |
9
+ | `evidence-only` | 证据路径变化或候选证据续跑 | 校验 schema、hash、identity;禁止重新构建产品镜像 |
10
+ | `release` | 已通过候选的受控发布 | 校验既有 artifact/digest,附加发布标签并部署;禁止再次构建 |
11
+
12
+ ## 必需控制
13
+
14
+ - 同分支同层启用 concurrency cancellation,取消过时运行;
15
+ - `candidate` 构建的镜像和制品以提交、产品树和环境 identity 命名并记录 digest;
16
+ - 产品路径冻结后,候选通过前不得夹带证据提交;候选通过后只允许 evidence-only 路径变化;
17
+ - 未知路径或影响图无法证明边界时扩大验证,不能缩小;
18
+ - Linux、Docker、shell 权限等行为先在受控 Linux 环境运行 canary;
19
+ - 发布层只消费候选产物,不执行源码构建;
20
+ - runner minutes、缓存命中和关键路径耗时写入周期报告,以实际基线评价优化。
21
+
22
+ 项目可用自身 CI 语法实现该协议,但层名、身份和收据语义保持一致。
@@ -0,0 +1,27 @@
1
+ # 外部平台最终一致性协议
2
+
3
+ 用于 CI、镜像仓库、部署控制面、证据回传等异步外部系统。目标是让网络传输、远端业务状态和本地观察新鲜度彼此独立,避免把“请求成功”误判为“业务成功”。
4
+
5
+ ## 统一观察合同
6
+
7
+ 每次观察至少包含:
8
+
9
+ - `subjectIdentity`:不可变业务对象身份,如提交、镜像 digest、运行 ID 与环境身份的规范化组合;
10
+ - `businessState`:`PENDING/RUNNING/SUCCEEDED/FAILED/CANCELLED/UNKNOWN`;
11
+ - `observationState`:`PENDING/TERMINAL/UNKNOWN`;
12
+ - `freshness`:`FRESH/STALE/UNKNOWN`;
13
+ - `retryable`、`reasonCode`、`observedAt`;
14
+ - 写操作还应携带稳定 `idempotencyKey`。
15
+
16
+ JSON 合同见 `contracts/external-platform-observation.schema.json`。
17
+
18
+ ## 收敛规则
19
+
20
+ 1. 只有身份一致、`freshness=FRESH` 且观察到权威终态,才能宣称完成。
21
+ 2. `TERMINAL + SUCCEEDED` 才是成功;`FAILED/CANCELLED` 必须保留为业务失败,不能被 HTTP 2xx、回调成功或旧缓存覆盖。
22
+ 3. 仅重试 retryable 的传输失败、陈旧观察或非终态;鉴权、参数、身份不匹配与权威失败不得重试成成功。
23
+ 4. 重试必须同时受最大次数、总耗时和退避表约束;预算耗尽输出结构化失败收据。
24
+ 5. 每次轮询继续使用同一 `subjectIdentity`/`idempotencyKey`,身份漂移立即 fail closed。
25
+ 6. 回调只是触发再次观察的信号,最终结论仍以权威读取接口为准。
26
+
27
+ 通用执行内核为 `@hunter-harness/core` 的 `convergeAuthoritativeState`。
@@ -0,0 +1,21 @@
1
+ # 项目与全局记忆收尾协议
2
+
3
+ Workflow 的 canonical state 永远是项目 Git 中的配置/文档和 `.harness` 的本地收据;聊天记录与跨项目记忆只能辅助发现,不能代替 gate、identity 或完成状态。
4
+
5
+ ## 分层写入
6
+
7
+ - 项目事实、命令、发布清单和长期约束写入项目真源;
8
+ - 当前运行状态、尝试和证据写入 `.harness`;
9
+ - 只有可跨项目复用、已经验证且不含 secret 的经验才写入全局记忆。
10
+
11
+ ## Closeout 字段
12
+
13
+ 每条全局记忆至少记录来源项目、来源提交/收据、`agent_id`、写入时间、置信度、TTL 或复核条件。新结论替代旧结论时显式记录 `supersede` 关系,不直接覆盖而失去历史。
14
+
15
+ ## 禁止项
16
+
17
+ - 不写入凭据、token、生产数据或个人隐私;
18
+ - 不写入未经验证的临时诊断;
19
+ - 不把“上次成功”当成当前环境事实;
20
+ - 不因 closeout 失败改写已经产生的产品或发布结论;
21
+ - 只检查不落库时使用 dry-run,成功写入后提交本轮实际修改的记忆文件。
@@ -0,0 +1,31 @@
1
+ # 容器仓库容量与生命周期治理协议
2
+
3
+ 适用于 TCR、GHCR 及其他按标签或版本计数的容器仓库。平台适配器负责读取真实库存和执行受控删除;通用内核只做容量判断、保护集合闭包与 dry-run 计划。
4
+
5
+ ## 构建前容量预检
6
+
7
+ 每次候选构建前必须提供当前版本数、计划新增数、配额和告警比例。若计划后超过配额,返回 `REGISTRY_VERSION_QUOTA_FULL` 并在构建前阻断;达到告警水位返回 `REGISTRY_VERSION_QUOTA_WARNING`。
8
+
9
+ 禁止先构建镜像、再依赖推送失败发现容量不足。
10
+
11
+ ## 保护集合
12
+
13
+ 保护标签至少包含:
14
+
15
+ - 当前生产与上一生产;
16
+ - 冻结候选、回滚窗口内候选;
17
+ - release/evidence/TAT/smoke 收据引用的标签或 digest;
18
+ - 运维显式 pin。
19
+
20
+ 保护标签解析出的 digest 必须加入保护 digest。共享 digest 被任一保护标签引用时,所有指向该 digest 的标签都进入保护集合,不能仅凭另一个标签较旧就删除。
21
+
22
+ ## 清理计划与执行
23
+
24
+ 1. 先调用 `planRegistryCleanup` 生成 `dryRun=true` 的结构化计划;
25
+ 2. 候选按创建时间与标签稳定排序,仅删除达到目标水位所需的最小数量;
26
+ 3. 若保护版本数量已超过目标水位,返回 `PROTECTED_VERSIONS_EXCEED_TARGET`,不扩大删除范围;
27
+ 4. 平台适配器执行前重新读取库存并核对计划 identity;
28
+ 5. 执行后重新查询版本数、受保护 digest 和剩余容量,写入最终收据;
29
+ 6. 通用内核不直接持有平台凭据,也不执行删除 API。
30
+
31
+ 通用容量与计划内核由 `@hunter-harness/core` 的 `assessRegistryCapacity` 和 `planRegistryCleanup` 提供。
@@ -0,0 +1,26 @@
1
+ # 能力感知验证图协议
2
+
3
+ Build Profile v3 用 `verificationGraph` 取代账本内的固定验证目标清单。项目可以声明后端、前端、浏览器、数据库、性能或发布候选等任意目标,同时保留统一的依赖、覆盖度和证据复用语义。
4
+
5
+ ## 目标合同
6
+
7
+ 每个目标必须声明:
8
+
9
+ - `commandKey`:指向 `commands` 中的真实命令;
10
+ - `dependsOn`:需要先完成的验证目标;
11
+ - `requiredCoverage`:`incremental/module-am/module`;
12
+ - `candidate`:是否为发布候选门禁;
13
+ - `requiredCapabilities`:执行环境必须具备的能力。
14
+
15
+ `candidateTarget` 必须引用已声明目标。未知目标、未知依赖、循环依赖、命令缺失都 fail closed。
16
+
17
+ ## 选择与执行
18
+
19
+ 1. 从显式请求目标开始;未显式请求时使用 `candidateTarget`。
20
+ 2. 展开完整依赖闭包并按拓扑顺序执行。
21
+ 3. 缺失能力不得静默跳过:目标记录 `CAPABILITY_MISSING`,依赖它的目标记录 `DEPENDENCY_BLOCKED`。
22
+ 4. 未进入闭包的目标是 `omitted`,与“执行失败”或“因能力阻断”分开报告。
23
+ 5. 账本记录目标定义的规范化 identity;依赖、覆盖度或能力声明变化后,旧证据必须失效。
24
+ 6. 候选目标即使自身命令可运行,也必须等待所有依赖和能力满足。
25
+
26
+ JSON 合同见 `contracts/build-profile-v3.schema.json`;通用选择器为 `@hunter-harness/core` 的 `selectVerificationTargets`。
@@ -621,6 +621,7 @@ def evaluate_product_ci_gate(change_dir: Path) -> dict[str, Any]:
621
621
 
622
622
  if assurance == "local-reproducible" and provider == "local-harness":
623
623
  local_required = {
624
+ "subject.environmentHash": environment_hash,
624
625
  "verification.commandSetHash": command_set_hash,
625
626
  "verification.ledgerHash": ledger_hash,
626
627
  "verification.toolchainHashes": verification.get("toolchainHashes"),
@@ -1047,6 +1048,14 @@ def certify_local_candidate(
1047
1048
  f"ledger={recorded_tree_hash} current={current_tree_hash}"
1048
1049
  )
1049
1050
  product_tree_hash = current_tree_hash
1051
+ environment_hashes = sorted(
1052
+ {str(item["environmentHash"]) for item in selected}
1053
+ )
1054
+ subject_environment_hash = (
1055
+ environment_hashes[0]
1056
+ if len(environment_hashes) == 1
1057
+ else _candidate_value_hash(environment_hashes)
1058
+ )
1050
1059
 
1051
1060
  receipt = {
1052
1061
  "schemaVersion": 2,
@@ -1057,6 +1066,7 @@ def certify_local_candidate(
1057
1066
  "subject": {
1058
1067
  "productCommit": product_commit,
1059
1068
  "productTreeHash": product_tree_hash,
1069
+ "environmentHash": subject_environment_hash,
1060
1070
  },
1061
1071
  "verification": {
1062
1072
  "requiredValidations": required,
@@ -1068,9 +1078,7 @@ def certify_local_candidate(
1068
1078
  "toolchainHashes": sorted(
1069
1079
  {str(item["toolchainHash"]) for item in selected}
1070
1080
  ),
1071
- "environmentHashes": sorted(
1072
- {str(item["environmentHash"]) for item in selected}
1073
- ),
1081
+ "environmentHashes": environment_hashes,
1074
1082
  "dependencyHashes": sorted(
1075
1083
  {str(item["inputsHash"]) for item in selected}
1076
1084
  ),
@@ -1495,6 +1503,14 @@ def build_workflow_timing(
1495
1503
  started = started_dt.isoformat() if started_dt else None
1496
1504
  cutoff = cutoff_dt.isoformat() if cutoff_dt else cutoff_text
1497
1505
 
1506
+ def elapsed_ms(start: Any, end: Any) -> int:
1507
+ delta = end - start
1508
+ total_microseconds = (
1509
+ (delta.days * 86_400 + delta.seconds) * 1_000_000
1510
+ + delta.microseconds
1511
+ )
1512
+ return max(0, total_microseconds // 1_000)
1513
+
1498
1514
  def clipped_interval(
1499
1515
  start_value: Any,
1500
1516
  end_value: Any,
@@ -1527,7 +1543,7 @@ def build_workflow_timing(
1527
1543
  return sum(
1528
1544
  max(
1529
1545
  0,
1530
- int((interval_end - interval_start).total_seconds() * 1000),
1546
+ elapsed_ms(interval_start, interval_end),
1531
1547
  )
1532
1548
  for interval_start, interval_end in merged
1533
1549
  )
@@ -1628,7 +1644,7 @@ def build_workflow_timing(
1628
1644
  for segment_start, segment_end in zip(boundaries, boundaries[1:]):
1629
1645
  milliseconds = max(
1630
1646
  0,
1631
- int((segment_end - segment_start).total_seconds() * 1000),
1647
+ elapsed_ms(segment_start, segment_end),
1632
1648
  )
1633
1649
  if covered(segment_start, segment_end, active_intervals):
1634
1650
  categories["attributed"] += milliseconds
@@ -1640,7 +1656,7 @@ def build_workflow_timing(
1640
1656
  categories["unattributed"] += milliseconds
1641
1657
 
1642
1658
  workflow_wall = (
1643
- max(0, int((cutoff_dt - started_dt).total_seconds() * 1000))
1659
+ elapsed_ms(started_dt, cutoff_dt)
1644
1660
  if started_dt is not None and cutoff_dt is not None
1645
1661
  else 0
1646
1662
  )
@@ -1660,9 +1676,7 @@ def build_workflow_timing(
1660
1676
  "session": len(sessions) + 1,
1661
1677
  "startedAt": session_start.isoformat(),
1662
1678
  "endedAt": pause_start_dt.isoformat(),
1663
- "wallClockMs": int(
1664
- (pause_start_dt - session_start).total_seconds() * 1000
1665
- ),
1679
+ "wallClockMs": elapsed_ms(session_start, pause_start_dt),
1666
1680
  "terminalStatus": "PAUSED",
1667
1681
  }
1668
1682
  )
@@ -1677,9 +1691,7 @@ def build_workflow_timing(
1677
1691
  "session": len(sessions) + 1,
1678
1692
  "startedAt": session_start.isoformat(),
1679
1693
  "endedAt": cutoff_dt.isoformat(),
1680
- "wallClockMs": int(
1681
- (cutoff_dt - session_start).total_seconds() * 1000
1682
- ),
1694
+ "wallClockMs": elapsed_ms(session_start, cutoff_dt),
1683
1695
  "terminalStatus": "CUTOFF",
1684
1696
  }
1685
1697
  )