@hunter-harness/workflow-harness 0.2.80 → 0.2.81

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 (146) 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 +13 -3
  3. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +13 -3
  4. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +13 -3
  5. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +13 -3
  6. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +13 -3
  7. package/harness/bundles/general/claude-code/harness-pull/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-push/SKILL.md +1 -1
  9. package/harness/bundles/general/claude-code/harness-review/SKILL.md +13 -3
  10. package/harness/bundles/general/claude-code/harness-run/SKILL.md +13 -3
  11. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +13 -3
  12. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-test/SKILL.md +13 -3
  14. package/harness/bundles/general/claude-code/scripts/harness_context.py +77 -3
  15. package/harness/bundles/general/claude-code/scripts/harness_events.py +35 -2
  16. package/harness/bundles/general/claude-code/scripts/harness_plan_finalize.py +6 -1
  17. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  18. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +13 -3
  19. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +13 -3
  20. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +13 -3
  21. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +13 -3
  22. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +13 -3
  23. package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +1 -1
  24. package/harness/bundles/general/codebuddy/harness-push/SKILL.md +1 -1
  25. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +13 -3
  26. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +13 -3
  27. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +13 -3
  28. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  29. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +13 -3
  30. package/harness/bundles/general/codebuddy/scripts/harness_context.py +77 -3
  31. package/harness/bundles/general/codebuddy/scripts/harness_events.py +35 -2
  32. package/harness/bundles/general/codebuddy/scripts/harness_plan_finalize.py +6 -1
  33. package/harness/bundles/general/codex/.harness-build.json +1 -1
  34. package/harness/bundles/general/codex/harness-archive/SKILL.md +13 -3
  35. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +13 -3
  36. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +13 -3
  37. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +13 -3
  38. package/harness/bundles/general/codex/harness-plan/SKILL.md +13 -3
  39. package/harness/bundles/general/codex/harness-pull/SKILL.md +1 -1
  40. package/harness/bundles/general/codex/harness-push/SKILL.md +1 -1
  41. package/harness/bundles/general/codex/harness-review/SKILL.md +13 -3
  42. package/harness/bundles/general/codex/harness-run/SKILL.md +13 -3
  43. package/harness/bundles/general/codex/harness-submit/SKILL.md +13 -3
  44. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  45. package/harness/bundles/general/codex/harness-test/SKILL.md +13 -3
  46. package/harness/bundles/general/codex/scripts/harness_context.py +77 -3
  47. package/harness/bundles/general/codex/scripts/harness_events.py +35 -2
  48. package/harness/bundles/general/codex/scripts/harness_plan_finalize.py +6 -1
  49. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  50. package/harness/bundles/general/cursor/harness-archive/SKILL.md +13 -3
  51. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +13 -3
  52. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +13 -3
  53. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +13 -3
  54. package/harness/bundles/general/cursor/harness-plan/SKILL.md +13 -3
  55. package/harness/bundles/general/cursor/harness-pull/SKILL.md +1 -1
  56. package/harness/bundles/general/cursor/harness-push/SKILL.md +1 -1
  57. package/harness/bundles/general/cursor/harness-review/SKILL.md +13 -3
  58. package/harness/bundles/general/cursor/harness-run/SKILL.md +13 -3
  59. package/harness/bundles/general/cursor/harness-submit/SKILL.md +13 -3
  60. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  61. package/harness/bundles/general/cursor/harness-test/SKILL.md +13 -3
  62. package/harness/bundles/general/cursor/scripts/harness_context.py +77 -3
  63. package/harness/bundles/general/cursor/scripts/harness_events.py +35 -2
  64. package/harness/bundles/general/cursor/scripts/harness_plan_finalize.py +6 -1
  65. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  66. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +13 -3
  67. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +13 -3
  68. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +13 -3
  69. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +13 -3
  70. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +13 -3
  71. package/harness/bundles/java/claude-code/harness-package/SKILL.md +13 -3
  72. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +13 -3
  73. package/harness/bundles/java/claude-code/harness-pull/SKILL.md +1 -1
  74. package/harness/bundles/java/claude-code/harness-push/SKILL.md +1 -1
  75. package/harness/bundles/java/claude-code/harness-review/SKILL.md +13 -3
  76. package/harness/bundles/java/claude-code/harness-run/SKILL.md +13 -3
  77. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +13 -3
  78. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  79. package/harness/bundles/java/claude-code/harness-test/SKILL.md +13 -3
  80. package/harness/bundles/java/claude-code/scripts/harness_context.py +77 -3
  81. package/harness/bundles/java/claude-code/scripts/harness_events.py +35 -2
  82. package/harness/bundles/java/claude-code/scripts/harness_plan_finalize.py +6 -1
  83. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  84. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +13 -3
  85. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +13 -3
  86. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +13 -3
  87. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +13 -3
  88. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +13 -3
  89. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +13 -3
  90. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +13 -3
  91. package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +1 -1
  92. package/harness/bundles/java/codebuddy/harness-push/SKILL.md +1 -1
  93. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +13 -3
  94. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +13 -3
  95. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +13 -3
  96. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  97. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +13 -3
  98. package/harness/bundles/java/codebuddy/scripts/harness_context.py +77 -3
  99. package/harness/bundles/java/codebuddy/scripts/harness_events.py +35 -2
  100. package/harness/bundles/java/codebuddy/scripts/harness_plan_finalize.py +6 -1
  101. package/harness/bundles/java/codex/.harness-build.json +1 -1
  102. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +13 -3
  103. package/harness/bundles/java/codex/harness-archive/SKILL.md +13 -3
  104. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +13 -3
  105. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +13 -3
  106. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +13 -3
  107. package/harness/bundles/java/codex/harness-package/SKILL.md +13 -3
  108. package/harness/bundles/java/codex/harness-plan/SKILL.md +13 -3
  109. package/harness/bundles/java/codex/harness-pull/SKILL.md +1 -1
  110. package/harness/bundles/java/codex/harness-push/SKILL.md +1 -1
  111. package/harness/bundles/java/codex/harness-review/SKILL.md +13 -3
  112. package/harness/bundles/java/codex/harness-run/SKILL.md +13 -3
  113. package/harness/bundles/java/codex/harness-submit/SKILL.md +13 -3
  114. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  115. package/harness/bundles/java/codex/harness-test/SKILL.md +13 -3
  116. package/harness/bundles/java/codex/scripts/harness_context.py +77 -3
  117. package/harness/bundles/java/codex/scripts/harness_events.py +35 -2
  118. package/harness/bundles/java/codex/scripts/harness_plan_finalize.py +6 -1
  119. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  120. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +13 -3
  121. package/harness/bundles/java/cursor/harness-archive/SKILL.md +13 -3
  122. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +13 -3
  123. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +13 -3
  124. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +13 -3
  125. package/harness/bundles/java/cursor/harness-package/SKILL.md +13 -3
  126. package/harness/bundles/java/cursor/harness-plan/SKILL.md +13 -3
  127. package/harness/bundles/java/cursor/harness-pull/SKILL.md +1 -1
  128. package/harness/bundles/java/cursor/harness-push/SKILL.md +1 -1
  129. package/harness/bundles/java/cursor/harness-review/SKILL.md +13 -3
  130. package/harness/bundles/java/cursor/harness-run/SKILL.md +13 -3
  131. package/harness/bundles/java/cursor/harness-submit/SKILL.md +13 -3
  132. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  133. package/harness/bundles/java/cursor/harness-test/SKILL.md +13 -3
  134. package/harness/bundles/java/cursor/scripts/harness_context.py +77 -3
  135. package/harness/bundles/java/cursor/scripts/harness_events.py +35 -2
  136. package/harness/bundles/java/cursor/scripts/harness_plan_finalize.py +6 -1
  137. package/harness/manifests/general/claude-code.json +17 -17
  138. package/harness/manifests/general/codebuddy.json +17 -17
  139. package/harness/manifests/general/codex.json +17 -17
  140. package/harness/manifests/general/cursor.json +17 -17
  141. package/harness/manifests/java/claude-code.json +19 -19
  142. package/harness/manifests/java/codebuddy.json +19 -19
  143. package/harness/manifests/java/codex.json +19 -19
  144. package/harness/manifests/java/cursor.json +19 -19
  145. package/hunter-workflow-family.json +3 -3
  146. package/package.json +1 -1
@@ -4,7 +4,7 @@ description: 6维度代码审查(架构/安全/规范/兼容/测试/性能)
4
4
  .harness/context-index.json)和测试场景表,在隔离上下文运行。仅当用户显式调用 /harness-review 时使用;不得在
5
5
  test 结束后自动接续执行。
6
6
  ---
7
- <!-- generated by harness_deploy.py; core=ad06ee73d8c86613; overlay=java; agent=cursor; do not edit -->
7
+ <!-- generated by harness_deploy.py; core=718eb530eef010b8; overlay=java; agent=cursor; do not edit -->
8
8
  # harness-review — 代码审查
9
9
 
10
10
  ## Purpose
@@ -144,13 +144,23 @@ review 读取 `state-snapshot.json`(`harness_state.py` / state-layout-protocol
144
144
 
145
145
  `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
146
146
 
147
+ **`phase.start` 由 `harness_gate.py begin` 写,不要再手工追加一次。** 两条同 `run-id` 的
148
+ `phase.start` 会让 `plan finalize` 以 `PHASE_START_DUPLICATE` 卡死,而且手工那次会先触发
149
+ auto-seal、把正在开始的 attempt 封成 `RECOVERED`。要补触发指令说明就带 `--note` 跑 `gate begin`。
150
+ (重复追加现已按 `(phase, run-id)` 判为幂等 no-op,但依赖它不如不写。)
151
+
147
152
  ```powershell
148
- python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --run-id <phase-run-id> --attempt <n> --note "<触发指令>"
153
+ # 阶段开始:gate begin 负责,note 在这里给
154
+ python <skills-root>/scripts/harness_gate.py begin --change-dir ".harness/changes/<change-name>" --phase <phase> --note "<触发指令>"
155
+ # 阶段中的其他事件才用 append
156
+ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type <command|issue|verification> --run-id <phase-run-id> --note "<摘要>"
149
157
  ```
150
158
 
151
159
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
152
160
 
153
161
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
154
162
 
155
- 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
163
+ 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。**`attempt` 按 phase 全局递增,不是按 run-id**:一个 run-id 只绑定一个 attempt,重试必须「新 run-id + 下一个 attempt」两者同时换,只换其一会撞 `EVENT_ATTEMPT_CONFLICT` `PHASE_ALREADY_CLOSED`。已发布的 plan 用 `harness_plan_finalize.py republish` 自动分配两者。
164
+
165
+ 阶段跑得久(plan/run 常见)时用 `harness_context.py renew --project . --change <cn> --executor <tool>` 续租;租约到期本身不再阻断 `close`(同一 owner 的过期租约不构成冲突,收据里记 `leaseLapsed`),但续租能让 `view` 的状态如实反映在跑。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
156
166
  > 片段:logging · phase=`review` · 事件:phase/decision/verification/issue/artifact
@@ -3,7 +3,7 @@ name: harness-run
3
3
  description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编译验证),逐变更簇实现计划中的任务。仅当用户显式调用
4
4
  /harness-run 时使用;不得因用户提到编码/实现就自动触发,也不得被其他阶段 skill 自动接续。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=ad06ee73d8c86613; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=718eb530eef010b8; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-run — 需求编码
8
8
 
9
9
  ## Purpose
@@ -156,13 +156,23 @@ python <skills-root>/scripts/harness_test_guard.py record --project . --change-d
156
156
 
157
157
  `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
158
158
 
159
+ **`phase.start` 由 `harness_gate.py begin` 写,不要再手工追加一次。** 两条同 `run-id` 的
160
+ `phase.start` 会让 `plan finalize` 以 `PHASE_START_DUPLICATE` 卡死,而且手工那次会先触发
161
+ auto-seal、把正在开始的 attempt 封成 `RECOVERED`。要补触发指令说明就带 `--note` 跑 `gate begin`。
162
+ (重复追加现已按 `(phase, run-id)` 判为幂等 no-op,但依赖它不如不写。)
163
+
159
164
  ```powershell
160
- python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --run-id <phase-run-id> --attempt <n> --note "<触发指令>"
165
+ # 阶段开始:gate begin 负责,note 在这里给
166
+ python <skills-root>/scripts/harness_gate.py begin --change-dir ".harness/changes/<change-name>" --phase <phase> --note "<触发指令>"
167
+ # 阶段中的其他事件才用 append
168
+ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type <command|issue|verification> --run-id <phase-run-id> --note "<摘要>"
161
169
  ```
162
170
 
163
171
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
164
172
 
165
173
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
166
174
 
167
- 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
175
+ 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。**`attempt` 按 phase 全局递增,不是按 run-id**:一个 run-id 只绑定一个 attempt,重试必须「新 run-id + 下一个 attempt」两者同时换,只换其一会撞 `EVENT_ATTEMPT_CONFLICT` `PHASE_ALREADY_CLOSED`。已发布的 plan 用 `harness_plan_finalize.py republish` 自动分配两者。
176
+
177
+ 阶段跑得久(plan/run 常见)时用 `harness_context.py renew --project . --change <cn> --executor <tool>` 续租;租约到期本身不再阻断 `close`(同一 owner 的过期租约不构成冲突,收据里记 `leaseLapsed`),但续租能让 `view` 的状态如实反映在跑。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
168
178
  > 片段:logging · phase=`run`
@@ -3,7 +3,7 @@ name: harness-submit
3
3
  description: 最终提交封装:验证→中文 commit→提交/推送;worktree 模式含 --no-ff 合并回主分支。仅当用户显式调用
4
4
  /harness-submit(或 /harness-merge 重入合并段)时使用;用户口头说'提交/commit/push'时必须先确认,不得自动触发。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=ad06ee73d8c86613; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=718eb530eef010b8; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-submit — 最终提交(含 worktree 合并)
8
8
 
9
9
  ## Purpose
@@ -167,13 +167,23 @@ git 经 PowerShell;commit/报告不得含明文密钥。遵循 `../protocols/s
167
167
 
168
168
  `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
169
169
 
170
+ **`phase.start` 由 `harness_gate.py begin` 写,不要再手工追加一次。** 两条同 `run-id` 的
171
+ `phase.start` 会让 `plan finalize` 以 `PHASE_START_DUPLICATE` 卡死,而且手工那次会先触发
172
+ auto-seal、把正在开始的 attempt 封成 `RECOVERED`。要补触发指令说明就带 `--note` 跑 `gate begin`。
173
+ (重复追加现已按 `(phase, run-id)` 判为幂等 no-op,但依赖它不如不写。)
174
+
170
175
  ```powershell
171
- python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --run-id <phase-run-id> --attempt <n> --note "<触发指令>"
176
+ # 阶段开始:gate begin 负责,note 在这里给
177
+ python <skills-root>/scripts/harness_gate.py begin --change-dir ".harness/changes/<change-name>" --phase <phase> --note "<触发指令>"
178
+ # 阶段中的其他事件才用 append
179
+ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type <command|issue|verification> --run-id <phase-run-id> --note "<摘要>"
172
180
  ```
173
181
 
174
182
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
175
183
 
176
184
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
177
185
 
178
- 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
186
+ 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。**`attempt` 按 phase 全局递增,不是按 run-id**:一个 run-id 只绑定一个 attempt,重试必须「新 run-id + 下一个 attempt」两者同时换,只换其一会撞 `EVENT_ATTEMPT_CONFLICT` `PHASE_ALREADY_CLOSED`。已发布的 plan 用 `harness_plan_finalize.py republish` 自动分配两者。
187
+
188
+ 阶段跑得久(plan/run 常见)时用 `harness_context.py renew --project . --change <cn> --executor <tool>` 续租;租约到期本身不再阻断 `close`(同一 owner 的过期租约不构成冲突,收据里记 `leaseLapsed`),但续租能让 `view` 的状态如实反映在跑。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
179
189
  > 片段:logging · phase=`submit`/`merge`
@@ -4,7 +4,7 @@ description: Use when the user asks to synchronize, refresh, or validate Harness
4
4
  metadata, adapters, remote knowledge ownership, instruction entrypoints,
5
5
  config origins, or CodeGraph status.
6
6
  ---
7
- <!-- generated by harness_deploy.py; core=ad06ee73d8c86613; overlay=java; agent=cursor; do not edit -->
7
+ <!-- generated by harness_deploy.py; core=718eb530eef010b8; overlay=java; agent=cursor; do not edit -->
8
8
  # harness-sync
9
9
 
10
10
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-test
3
3
  description: 测试执行:读取场景表,执行单元测试+API接口测试+数据兼容验证,输出测试报告。仅当用户显式调用 /harness-test
4
4
  时使用;不得在 run 结束后自动接续执行。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=ad06ee73d8c86613; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=718eb530eef010b8; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-test — 测试执行
8
8
 
9
9
  ## Purpose
@@ -233,13 +233,23 @@ python <skills-root>/scripts/harness_test_guard.py record --project . --change-d
233
233
 
234
234
  `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
235
235
 
236
+ **`phase.start` 由 `harness_gate.py begin` 写,不要再手工追加一次。** 两条同 `run-id` 的
237
+ `phase.start` 会让 `plan finalize` 以 `PHASE_START_DUPLICATE` 卡死,而且手工那次会先触发
238
+ auto-seal、把正在开始的 attempt 封成 `RECOVERED`。要补触发指令说明就带 `--note` 跑 `gate begin`。
239
+ (重复追加现已按 `(phase, run-id)` 判为幂等 no-op,但依赖它不如不写。)
240
+
236
241
  ```powershell
237
- python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --run-id <phase-run-id> --attempt <n> --note "<触发指令>"
242
+ # 阶段开始:gate begin 负责,note 在这里给
243
+ python <skills-root>/scripts/harness_gate.py begin --change-dir ".harness/changes/<change-name>" --phase <phase> --note "<触发指令>"
244
+ # 阶段中的其他事件才用 append
245
+ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type <command|issue|verification> --run-id <phase-run-id> --note "<摘要>"
238
246
  ```
239
247
 
240
248
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
241
249
 
242
250
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
243
251
 
244
- 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
252
+ 每个阶段的 `phase.start` 与对应 `phase.end` 必须复用同一 `--run-id` / `--attempt`;阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`。重试同一阶段时生成新的 run-id 并增加 `--attempt <n>`,不得覆盖或伪装成一次执行。**`attempt` 按 phase 全局递增,不是按 run-id**:一个 run-id 只绑定一个 attempt,重试必须「新 run-id + 下一个 attempt」两者同时换,只换其一会撞 `EVENT_ATTEMPT_CONFLICT` `PHASE_ALREADY_CLOSED`。已发布的 plan 用 `harness_plan_finalize.py republish` 自动分配两者。
253
+
254
+ 阶段跑得久(plan/run 常见)时用 `harness_context.py renew --project . --change <cn> --executor <tool>` 续租;租约到期本身不再阻断 `close`(同一 owner 的过期租约不构成冲突,收据里记 `leaseLapsed`),但续租能让 `view` 的状态如实反映在跑。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
245
255
  > 片段:logging · phase=`test` · 事件:phase/command/verification/decision/issue/artifact
@@ -1165,9 +1165,11 @@ def close_transition(
1165
1165
  "holder": lease.get("owner"),
1166
1166
  "leasePhase": lease.get("phase"),
1167
1167
  }
1168
+ # Owner and phase already matched above, so nobody took this lease over: a
1169
+ # takeover rewrites the file and would have produced CONTEXT_LEASE_MISMATCH.
1170
+ # A lapsed deadline therefore proves only that the phase outlived the TTL.
1168
1171
  expiry = _parse_time(lease.get("expiresAt"))
1169
- if expiry is None or _now() >= expiry:
1170
- return {"ok": False, "code": "CONTEXT_LEASE_EXPIRED"}
1172
+ lease_lapsed = expiry is None or _now() >= expiry
1171
1173
 
1172
1174
  previous_hash = transitions[-1].get("receiptHash") if transitions else None
1173
1175
  attempt = (
@@ -1192,6 +1194,12 @@ def close_transition(
1192
1194
  "closedAt": _now().isoformat(),
1193
1195
  "previousReceiptHash": previous_hash,
1194
1196
  }
1197
+ if lease_lapsed:
1198
+ # Recorded, not hidden: the phase ran past its lease without a renewal.
1199
+ receipt["leaseLapsed"] = {
1200
+ "expiresAt": lease.get("expiresAt"),
1201
+ "acquiredAt": lease.get("acquiredAt"),
1202
+ }
1195
1203
  receipt["receiptHash"] = _payload_hash(receipt)
1196
1204
  _append_ndjson(paths["transitions"], receipt)
1197
1205
  paths["lease"].unlink(missing_ok=True)
@@ -1267,7 +1275,11 @@ def _begin_transition_unlocked(
1267
1275
  "legacyBootstrap": True,
1268
1276
  "message": (
1269
1277
  "没有交接凭证。v2 计划应有 committed 的 meta/publication-journals/*.json "
1270
- "作为补录证据;legacy 计划需先完成 plan 阶段的 close"
1278
+ "作为补录证据;legacy 计划需先完成 plan 阶段的 close"
1279
+ "首次进入某阶段(还没有任何 transition 凭证)时不要用 context begin——"
1280
+ "改跑 `harness_gate.py begin --change-dir .harness/changes/<change> "
1281
+ "--phase <phase> --run-id <phase>_<uuid4hex> --note \"<触发指令>\"`,"
1282
+ "它会领取租约并写好 phase.start。"
1271
1283
  ),
1272
1284
  }
1273
1285
  receipt = transitions[-1]
@@ -1458,6 +1470,53 @@ def cancel_prepared_context(
1458
1470
  }
1459
1471
 
1460
1472
 
1473
+ def renew_lease(
1474
+ project: Path,
1475
+ change: str,
1476
+ *,
1477
+ executor: str,
1478
+ ttl_seconds: int = 3600,
1479
+ ) -> dict[str, Any]:
1480
+ """Extend the current phase lease in place.
1481
+
1482
+ Only the recorded owner may renew, and only while no other executor has
1483
+ taken the lease over. Renewal touches nothing but ``expiresAt``, so it is
1484
+ safe to call on a heartbeat during a long phase.
1485
+ """
1486
+ project = project.resolve()
1487
+ try:
1488
+ _, _, state_root = _contract(project, change)
1489
+ except ValueError as exc:
1490
+ return {"ok": False, "code": _contract_error_code(exc), "error": str(exc)}
1491
+ paths = _paths(state_root)
1492
+ if not paths["lease"].is_file():
1493
+ return {"ok": False, "code": "CONTEXT_LEASE_REQUIRED"}
1494
+ with _exclusive_state_lock(paths["runtime"] / "branch-selection.lock"):
1495
+ try:
1496
+ lease = _read_json(paths["lease"])
1497
+ except (OSError, ValueError, json.JSONDecodeError):
1498
+ return {"ok": False, "code": "CONTEXT_LEASE_INVALID"}
1499
+ if lease.get("owner") != executor:
1500
+ return {
1501
+ "ok": False,
1502
+ "code": "CONTEXT_LEASE_MISMATCH",
1503
+ "holder": lease.get("owner"),
1504
+ }
1505
+ expiry = _parse_time(lease.get("expiresAt"))
1506
+ lapsed = expiry is None or _now() >= expiry
1507
+ lease["expiresAt"] = (
1508
+ _now() + dt.timedelta(seconds=max(1, int(ttl_seconds)))
1509
+ ).isoformat()
1510
+ lease["renewedAt"] = _now().isoformat()
1511
+ _write_json_atomic(paths["lease"], lease)
1512
+ return {
1513
+ "ok": True,
1514
+ "code": "CONTEXT_LEASE_RENEWED",
1515
+ "lease": lease,
1516
+ "wasLapsed": lapsed,
1517
+ }
1518
+
1519
+
1461
1520
  def context_view(project: Path, change: str) -> dict[str, Any]:
1462
1521
  project = Path(project).resolve()
1463
1522
  try:
@@ -1536,6 +1595,14 @@ def build_parser() -> argparse.ArgumentParser:
1536
1595
  begin.add_argument("--change", required=True)
1537
1596
  begin.add_argument("--phase", required=True)
1538
1597
  begin.add_argument("--executor", required=True)
1598
+ renew = sub.add_parser(
1599
+ "renew", help="extend the current phase lease without touching context"
1600
+ )
1601
+ renew.add_argument("--json", action="store_true")
1602
+ renew.add_argument("--project", required=True, type=Path)
1603
+ renew.add_argument("--change", required=True)
1604
+ renew.add_argument("--executor", required=True)
1605
+ renew.add_argument("--ttl-seconds", type=int, default=3600)
1539
1606
  configure = sub.add_parser("configure-plan")
1540
1607
  configure.add_argument("--json", action="store_true")
1541
1608
  configure.add_argument("--project", required=True, type=Path)
@@ -1588,6 +1655,13 @@ def main(argv: list[str] | None = None) -> int:
1588
1655
  phase=args.phase,
1589
1656
  executor=args.executor,
1590
1657
  )
1658
+ elif args.command == "renew":
1659
+ result = renew_lease(
1660
+ args.project,
1661
+ args.change,
1662
+ executor=args.executor,
1663
+ ttl_seconds=args.ttl_seconds,
1664
+ )
1591
1665
  elif args.command == "configure-plan":
1592
1666
  result = configure_phase_plan(
1593
1667
  args.project,
@@ -1904,6 +1904,7 @@ def cmd_append(args: argparse.Namespace) -> int:
1904
1904
  file=sys.stderr,
1905
1905
  )
1906
1906
  phase_closed = False
1907
+ phase_start_duplicate = False
1907
1908
  projection_error: str | None = None
1908
1909
  attempt_error: str | None = None
1909
1910
  auto_sealed_events: list[dict[str, Any]] = []
@@ -1951,10 +1952,25 @@ def cmd_append(args: argparse.Namespace) -> int:
1951
1952
  except ValueError as exc:
1952
1953
  projection_error = str(exc)
1953
1954
  elif args.type == "phase.start":
1955
+ # Re-appending the same (phase, run_id) is the caller restating a
1956
+ # start that already exists — `gate begin` writes one, and the
1957
+ # logging protocol used to ask for a second. Treat it as a no-op
1958
+ # rather than a duplicate; two identical phase.start events make
1959
+ # `plan finalize` unrecoverable via PHASE_START_DUPLICATE.
1960
+ if run_id is not None and any(
1961
+ item.get("phase") == args.phase
1962
+ and item.get("type") == "phase.start"
1963
+ and item.get("run_id") == run_id
1964
+ for item in existing_events
1965
+ ):
1966
+ phase_start_duplicate = True
1954
1967
  # HH-WF-20260730-001: a new phase.start must not be appended
1955
1968
  # while a prior attempt for the same phase is still open —
1956
1969
  # auto-seal it first so timing never has two open attempts.
1957
- open_attempts = open_attempts_for_phase(existing_events, args.phase)
1970
+ open_attempts = (
1971
+ [] if phase_start_duplicate
1972
+ else open_attempts_for_phase(existing_events, args.phase)
1973
+ )
1958
1974
  if open_attempts:
1959
1975
  inferred_reason = infer_auto_seal_reason(
1960
1976
  open_attempts[-1].get("events") or []
@@ -1964,7 +1980,12 @@ def cmd_append(args: argparse.Namespace) -> int:
1964
1980
  phase=args.phase,
1965
1981
  seal_reason=inferred_reason,
1966
1982
  )
1967
- if not phase_closed and projection_error is None and attempt_error is None:
1983
+ if (
1984
+ not phase_closed
1985
+ and not phase_start_duplicate
1986
+ and projection_error is None
1987
+ and attempt_error is None
1988
+ ):
1968
1989
  for seal_event in auto_sealed_events:
1969
1990
  atomic_append_line(
1970
1991
  path,
@@ -1976,6 +1997,18 @@ def cmd_append(args: argparse.Namespace) -> int:
1976
1997
  )
1977
1998
  except (OSError, TimeoutError, ValueError) as exc:
1978
1999
  return emit_error(f"append failed: {exc}", as_json=as_json)
2000
+ if phase_start_duplicate:
2001
+ if as_json:
2002
+ print(json.dumps({
2003
+ "ok": True,
2004
+ "skipped": True,
2005
+ "reason": "phase-start-already-recorded",
2006
+ "phase": args.phase,
2007
+ "run_id": event.get("run_id"),
2008
+ }, ensure_ascii=False))
2009
+ else:
2010
+ print("ok (phase.start already recorded for this run id)")
2011
+ return 0
1979
2012
  if phase_closed:
1980
2013
  return emit_error(
1981
2014
  "PHASE_ALREADY_CLOSED: refusing a second phase.end for the same "
@@ -735,7 +735,12 @@ def _validate_plan_start(
735
735
  if len(matching) > 1:
736
736
  return _result_error(
737
737
  "PHASE_START_DUPLICATE",
738
- f"found {len(matching)} matching plan phase.start events",
738
+ f"found {len(matching)} matching plan phase.start events for run id "
739
+ f"{run_id}. `harness_gate.py begin` already appends phase.start; a "
740
+ "second manual append of the same run id creates this state. Recover "
741
+ "with a fresh run id and the next attempt number (attempts are global "
742
+ "per phase, not per run id): append phase.start with both, then "
743
+ "finalize with the same pair.",
739
744
  )
740
745
  return {"ok": True, "phaseStartCount": 1}
741
746
 
@@ -2,7 +2,7 @@
2
2
  "schema_version": 2,
3
3
  "profile": "general",
4
4
  "adapter": "claude-code",
5
- "bundle_version": "0.2.69",
5
+ "bundle_version": "0.2.70",
6
6
  "requires": {
7
7
  "minimumCliVersion": "0.2.88",
8
8
  "capabilities": [
@@ -25,7 +25,7 @@
25
25
  "files": [
26
26
  {
27
27
  "path": ".harness-build.json",
28
- "sha256": "0709912d6a1fe652fc76827d48d7305fd6ed392025da438c79f0c3d588317731"
28
+ "sha256": "ba966d7563aa4c5cf5a170d9af6c80a4a1c87613061d2e8bf7858a1f53001690"
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": "787cdc6fb1fe8a56f06ed9f18572aa297d7da05810286bf2447491e48170973e"
100
+ "sha256": "cb5686f5044f3dcf580497d8081ae0d7a3742a83c6910dc92d9622b21c4e3e94"
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": "a7e7d508d85578027d172b4fd1e1e27141d29b172f9267d362af66d70c20745c"
116
+ "sha256": "f60acc504b6227448a5879240ed75b5762e587a5908ac0207c558e20f81fc098"
117
117
  },
118
118
  {
119
119
  "path": "harness-codebase-map/templates/ARCHITECTURE.md",
@@ -153,11 +153,11 @@
153
153
  },
154
154
  {
155
155
  "path": "harness-knowledge-ingest/SKILL.md",
156
- "sha256": "9c6c176b2e2246335a41d04bd85473db88c99ded2ce4d456caddbd5f49448c65"
156
+ "sha256": "c3a2cdadfb78f0b38503d117def71098a0a2919e3a8eb939e70b4796e3cd84cc"
157
157
  },
158
158
  {
159
159
  "path": "harness-knowledge-query/SKILL.md",
160
- "sha256": "188ecf125fbd46e1011c4745832c531fd0a3e8d5ff2581eac781fa3091f18808"
160
+ "sha256": "46a06f2b9610093d11dfbe9d8a27fd8a62129d66c7aa6bb82e759b7893ad9e9b"
161
161
  },
162
162
  {
163
163
  "path": "harness-plan/checklist.md",
@@ -173,15 +173,15 @@
173
173
  },
174
174
  {
175
175
  "path": "harness-plan/SKILL.md",
176
- "sha256": "3d271beff56b142cee880ff50cee2ee2dde87ff1f41cf39ab9d541c525122a79"
176
+ "sha256": "79e1c84a92a8bf6370cdc6691dc5cc92bd3e5ff4a720864949a1d3c7de7782a3"
177
177
  },
178
178
  {
179
179
  "path": "harness-pull/SKILL.md",
180
- "sha256": "d64b8094e40121053f869d4681dbca28f98ff2b4f49211bf4bae277be8363ff0"
180
+ "sha256": "29df6f2b5b351c01c97c47db42f835706add2bfe84b4edd0968da1289a2e54c9"
181
181
  },
182
182
  {
183
183
  "path": "harness-push/SKILL.md",
184
- "sha256": "5d6a668e73275c57bb2bb619e064971f1f1e234534b7deb39017503eca4e9aa8"
184
+ "sha256": "ee723583548b7fa73fe113bfbb73d840f144ba1bc059a627cb57289cd8518705"
185
185
  },
186
186
  {
187
187
  "path": "harness-review/checklist.md",
@@ -197,7 +197,7 @@
197
197
  },
198
198
  {
199
199
  "path": "harness-review/SKILL.md",
200
- "sha256": "3fb87a1db89642a72962cc5cb34a85fc040933ae40b6466e0d17d9d3b9d4b2b3"
200
+ "sha256": "a70669bf6deabb442a855535283e22ea6edb6c2e3d50dc65543ab47f7e01f5f3"
201
201
  },
202
202
  {
203
203
  "path": "harness-run/checklist.md",
@@ -213,7 +213,7 @@
213
213
  },
214
214
  {
215
215
  "path": "harness-run/SKILL.md",
216
- "sha256": "fe8c64a333cf99ab1ba611f82538efd72d631b8586ff56736e38fd71580eeddd"
216
+ "sha256": "ad7fefb8891068fd4fbaf1890e21abcbe1a1eed037f3ab1cd751dca56bd651d0"
217
217
  },
218
218
  {
219
219
  "path": "harness-submit/checklist.md",
@@ -225,7 +225,7 @@
225
225
  },
226
226
  {
227
227
  "path": "harness-submit/SKILL.md",
228
- "sha256": "bf4d050815fb6f12ae97edf65839b77af71a2f2aed56436ca20ff528d24588f6"
228
+ "sha256": "3c222757ff63d702fb69002704931dc6cca246256ff2a2a5a7d093f04410844e"
229
229
  },
230
230
  {
231
231
  "path": "harness-sync/reference.md",
@@ -233,7 +233,7 @@
233
233
  },
234
234
  {
235
235
  "path": "harness-sync/SKILL.md",
236
- "sha256": "791904da89523f03a92c62bfb3f75949999eaf482ca6113b97f614d17b2ce532"
236
+ "sha256": "3c755bf5732e7d1f9945b08527668a33cde6e24a593b0636359d89a21418173e"
237
237
  },
238
238
  {
239
239
  "path": "harness-test/checklist.md",
@@ -257,7 +257,7 @@
257
257
  },
258
258
  {
259
259
  "path": "harness-test/SKILL.md",
260
- "sha256": "664585ffac4ed6bfa1912e0c1b40cb73261d43e6f46546d27c9f40947a2db099"
260
+ "sha256": "3b2cc724648e75fc310fc09e44a1737c669fc12d5d0933b278c564a72c7fd05a"
261
261
  },
262
262
  {
263
263
  "path": "protocols/archive-report-protocol.md",
@@ -341,7 +341,7 @@
341
341
  },
342
342
  {
343
343
  "path": "scripts/harness_context.py",
344
- "sha256": "e61bbeb3073d77a34ac9aefb13421c187a8d16c8f95597d1ca50d91b0c6af1d2"
344
+ "sha256": "c7ad3199bda332e853a24e6268fa32dcc253adb6dfe7e0de7aa3b7f0ae7ae312"
345
345
  },
346
346
  {
347
347
  "path": "scripts/harness_deploy.py",
@@ -361,7 +361,7 @@
361
361
  },
362
362
  {
363
363
  "path": "scripts/harness_events.py",
364
- "sha256": "3116137be32bd696adce47c79f2af99a8f1517a7555bd1bbaffe27e17fd12fbc"
364
+ "sha256": "e992498f7256d11ae98d6e71be4f88fc8e08331311ca74372bbc890a720eae43"
365
365
  },
366
366
  {
367
367
  "path": "scripts/harness_execution_contracts.py",
@@ -413,7 +413,7 @@
413
413
  },
414
414
  {
415
415
  "path": "scripts/harness_plan_finalize.py",
416
- "sha256": "af12b53ab5503eb5c0ead5bd58e8da9d5389c649958ac678bf448e4c8a286d5b"
416
+ "sha256": "6f4dcee06f92f7ed7a3bd0ee615e9dd7e8fd921502b132305e37c4871b97537b"
417
417
  },
418
418
  {
419
419
  "path": "scripts/harness_preflight.py",
@@ -2,7 +2,7 @@
2
2
  "schema_version": 2,
3
3
  "profile": "general",
4
4
  "adapter": "codebuddy",
5
- "bundle_version": "0.2.69",
5
+ "bundle_version": "0.2.70",
6
6
  "requires": {
7
7
  "minimumCliVersion": "0.2.88",
8
8
  "capabilities": [
@@ -25,7 +25,7 @@
25
25
  "files": [
26
26
  {
27
27
  "path": ".harness-build.json",
28
- "sha256": "9daf75dd4df259b9bff02aa0f088372ea9c8c96f39fba13cce05140696186f0d"
28
+ "sha256": "9ab6d7c436b5900ab0897bee47f5b21355a09ec516f7167607faa0943b8c36ad"
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": "085514f0e48afb17fc6cec4cb1bd057b5d32af7580bc63b702d02eceed26adb5"
100
+ "sha256": "f98a149eb196638fbb531944c3dba7e0ac252867b8269d92a83c0bbbaf930d51"
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": "e50091b3c44f31c0d2559c46760a1b07c2159dff8c918adee0e3c92f46616f95"
116
+ "sha256": "e941ccfbcf89d5a5aa53c3f49c43b702f8d75c3c6bfb4cf647cf76c6a5e98576"
117
117
  },
118
118
  {
119
119
  "path": "harness-codebase-map/templates/ARCHITECTURE.md",
@@ -153,11 +153,11 @@
153
153
  },
154
154
  {
155
155
  "path": "harness-knowledge-ingest/SKILL.md",
156
- "sha256": "1efecf8ac5eacb0dbae7670de68fed3b632369b2b9bcc8697e585cca0673c6a5"
156
+ "sha256": "82169a60cd3dedc637b072f7941cd64404a6314731233329e33083292ea4751e"
157
157
  },
158
158
  {
159
159
  "path": "harness-knowledge-query/SKILL.md",
160
- "sha256": "cbb4802bba062e59fce6d11ef0c15649c9f3242bf8f6d8fd6dc492a35964a73b"
160
+ "sha256": "13f50e255cb0f48aea12be4ad97ea9d84f260972088ef46aa1a923ef66035fa0"
161
161
  },
162
162
  {
163
163
  "path": "harness-plan/checklist.md",
@@ -173,15 +173,15 @@
173
173
  },
174
174
  {
175
175
  "path": "harness-plan/SKILL.md",
176
- "sha256": "60136f87601ccaf68dfd98c5cd05f299ad6b57d2c26beeeb3f1344453347ccb2"
176
+ "sha256": "918cd2e29e85f7404358425764283fa2a0a2e9bb89fef004b3206378a2e32230"
177
177
  },
178
178
  {
179
179
  "path": "harness-pull/SKILL.md",
180
- "sha256": "c03ff4e1d9e6c9db7f75334c997bcd3501364bffaf52d332acc66cd7c65c9d62"
180
+ "sha256": "bfdb39724415e798ef181d3dbb2cfd67c23aead486385168d5fbfb7d707084de"
181
181
  },
182
182
  {
183
183
  "path": "harness-push/SKILL.md",
184
- "sha256": "db1b46a4d506ef8c4d89c54074b476792db2027fb55ce07e43a5cc72e8da8202"
184
+ "sha256": "b5745430c60a7223938b0651fc03db6987a6ad91b7ea2166745dda09833156da"
185
185
  },
186
186
  {
187
187
  "path": "harness-review/checklist.md",
@@ -197,7 +197,7 @@
197
197
  },
198
198
  {
199
199
  "path": "harness-review/SKILL.md",
200
- "sha256": "64ccbc18fb31ddefbc60638507fdf86c9fa0ee5379abb3a1763283fda7388158"
200
+ "sha256": "320d3fa49650b78307c57dab6415596ce23ba4bdd70f6c94acae059f9e733a1d"
201
201
  },
202
202
  {
203
203
  "path": "harness-run/checklist.md",
@@ -213,7 +213,7 @@
213
213
  },
214
214
  {
215
215
  "path": "harness-run/SKILL.md",
216
- "sha256": "727922a067fba9016d65171a06a6a554072a9e86652936e4929fae498f06fbd6"
216
+ "sha256": "0175fb228d9a813c02f9bdc4bbff8ac873adf3d6c89d79f51e4f8a94be573980"
217
217
  },
218
218
  {
219
219
  "path": "harness-submit/checklist.md",
@@ -225,7 +225,7 @@
225
225
  },
226
226
  {
227
227
  "path": "harness-submit/SKILL.md",
228
- "sha256": "f56a332bf5a481f90bc293f351f07ef5ea0203391f0ed873a58d7dbe4503bfcc"
228
+ "sha256": "2d5d90af10f92347c2d88f6bfac01a0337ac2e413be352ba6a23353d5e9a0359"
229
229
  },
230
230
  {
231
231
  "path": "harness-sync/reference.md",
@@ -233,7 +233,7 @@
233
233
  },
234
234
  {
235
235
  "path": "harness-sync/SKILL.md",
236
- "sha256": "8407bf7fc3bf16044f4ea2f46e816249ec857a31eb7664f650c386064eefe554"
236
+ "sha256": "65fee072033a9ec0865a237f97671b53b744b1c354c7a2313e77421618097662"
237
237
  },
238
238
  {
239
239
  "path": "harness-test/checklist.md",
@@ -257,7 +257,7 @@
257
257
  },
258
258
  {
259
259
  "path": "harness-test/SKILL.md",
260
- "sha256": "4c262838b7619a78bd338d4eab453758b7b5aca237743cb205c407fad49c11a3"
260
+ "sha256": "5672497ba8022f01c97edf2991555160bdffadee6697e452dd44e35c7a100112"
261
261
  },
262
262
  {
263
263
  "path": "protocols/archive-report-protocol.md",
@@ -341,7 +341,7 @@
341
341
  },
342
342
  {
343
343
  "path": "scripts/harness_context.py",
344
- "sha256": "e61bbeb3073d77a34ac9aefb13421c187a8d16c8f95597d1ca50d91b0c6af1d2"
344
+ "sha256": "c7ad3199bda332e853a24e6268fa32dcc253adb6dfe7e0de7aa3b7f0ae7ae312"
345
345
  },
346
346
  {
347
347
  "path": "scripts/harness_deploy.py",
@@ -361,7 +361,7 @@
361
361
  },
362
362
  {
363
363
  "path": "scripts/harness_events.py",
364
- "sha256": "3116137be32bd696adce47c79f2af99a8f1517a7555bd1bbaffe27e17fd12fbc"
364
+ "sha256": "e992498f7256d11ae98d6e71be4f88fc8e08331311ca74372bbc890a720eae43"
365
365
  },
366
366
  {
367
367
  "path": "scripts/harness_execution_contracts.py",
@@ -413,7 +413,7 @@
413
413
  },
414
414
  {
415
415
  "path": "scripts/harness_plan_finalize.py",
416
- "sha256": "af12b53ab5503eb5c0ead5bd58e8da9d5389c649958ac678bf448e4c8a286d5b"
416
+ "sha256": "6f4dcee06f92f7ed7a3bd0ee615e9dd7e8fd921502b132305e37c4871b97537b"
417
417
  },
418
418
  {
419
419
  "path": "scripts/harness_preflight.py",