@hunter-harness/workflow-harness 0.2.85 → 0.2.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/harness/bundles/general/claude-code/.harness-build.json +1 -1
- package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-plan/SKILL.md +3 -2
- package/harness/bundles/general/claude-code/harness-plan/checklist.md +18 -79
- package/harness/bundles/general/claude-code/harness-plan/protocols.md +3 -1
- package/harness/bundles/general/claude-code/harness-plan/reference.md +37 -8
- package/harness/bundles/general/claude-code/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +6 -4
- package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/scripts/harness_change.py +25 -7
- package/harness/bundles/general/claude-code/scripts/harness_context.py +62 -19
- package/harness/bundles/general/claude-code/scripts/harness_fixback.py +4 -0
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +208 -72
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +43 -0
- package/harness/bundles/general/claude-code/scripts/harness_paths.py +60 -0
- package/harness/bundles/general/claude-code/scripts/harness_phase.py +24 -6
- package/harness/bundles/general/claude-code/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/general/claude-code/scripts/harness_review.py +25 -4
- package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +3 -2
- package/harness/bundles/general/codebuddy/harness-plan/checklist.md +18 -79
- package/harness/bundles/general/codebuddy/harness-plan/protocols.md +3 -1
- package/harness/bundles/general/codebuddy/harness-plan/reference.md +37 -8
- package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +6 -4
- package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/scripts/harness_change.py +25 -7
- package/harness/bundles/general/codebuddy/scripts/harness_context.py +62 -19
- package/harness/bundles/general/codebuddy/scripts/harness_fixback.py +4 -0
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +208 -72
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +43 -0
- package/harness/bundles/general/codebuddy/scripts/harness_paths.py +60 -0
- package/harness/bundles/general/codebuddy/scripts/harness_phase.py +24 -6
- package/harness/bundles/general/codebuddy/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/general/codebuddy/scripts/harness_review.py +25 -4
- package/harness/bundles/general/codex/.harness-build.json +1 -1
- package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-plan/SKILL.md +3 -2
- package/harness/bundles/general/codex/harness-plan/checklist.md +18 -79
- package/harness/bundles/general/codex/harness-plan/protocols.md +3 -1
- package/harness/bundles/general/codex/harness-plan/reference.md +37 -8
- package/harness/bundles/general/codex/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +6 -4
- package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/codex/scripts/harness_change.py +25 -7
- package/harness/bundles/general/codex/scripts/harness_context.py +62 -19
- package/harness/bundles/general/codex/scripts/harness_fixback.py +4 -0
- package/harness/bundles/general/codex/scripts/harness_gate.py +208 -72
- package/harness/bundles/general/codex/scripts/harness_ledger.py +43 -0
- package/harness/bundles/general/codex/scripts/harness_paths.py +60 -0
- package/harness/bundles/general/codex/scripts/harness_phase.py +24 -6
- package/harness/bundles/general/codex/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/general/codex/scripts/harness_review.py +25 -4
- package/harness/bundles/general/cursor/.harness-build.json +1 -1
- package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-plan/SKILL.md +3 -2
- package/harness/bundles/general/cursor/harness-plan/checklist.md +18 -79
- package/harness/bundles/general/cursor/harness-plan/protocols.md +3 -1
- package/harness/bundles/general/cursor/harness-plan/reference.md +37 -8
- package/harness/bundles/general/cursor/harness-pull/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-push/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +6 -4
- package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/general/cursor/scripts/harness_change.py +25 -7
- package/harness/bundles/general/cursor/scripts/harness_context.py +62 -19
- package/harness/bundles/general/cursor/scripts/harness_fixback.py +4 -0
- package/harness/bundles/general/cursor/scripts/harness_gate.py +208 -72
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +43 -0
- package/harness/bundles/general/cursor/scripts/harness_paths.py +60 -0
- package/harness/bundles/general/cursor/scripts/harness_phase.py +24 -6
- package/harness/bundles/general/cursor/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/general/cursor/scripts/harness_review.py +25 -4
- package/harness/bundles/java/claude-code/.harness-build.json +1 -1
- package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-plan/SKILL.md +3 -2
- package/harness/bundles/java/claude-code/harness-plan/checklist.md +18 -79
- package/harness/bundles/java/claude-code/harness-plan/protocols.md +3 -1
- package/harness/bundles/java/claude-code/harness-plan/reference.md +37 -8
- package/harness/bundles/java/claude-code/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +6 -4
- package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/scripts/harness_change.py +25 -7
- package/harness/bundles/java/claude-code/scripts/harness_context.py +62 -19
- package/harness/bundles/java/claude-code/scripts/harness_fixback.py +4 -0
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +208 -72
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +43 -0
- package/harness/bundles/java/claude-code/scripts/harness_paths.py +60 -0
- package/harness/bundles/java/claude-code/scripts/harness_phase.py +24 -6
- package/harness/bundles/java/claude-code/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/java/claude-code/scripts/harness_review.py +25 -4
- package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
- package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +3 -2
- package/harness/bundles/java/codebuddy/harness-plan/checklist.md +18 -79
- package/harness/bundles/java/codebuddy/harness-plan/protocols.md +3 -1
- package/harness/bundles/java/codebuddy/harness-plan/reference.md +37 -8
- package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +6 -4
- package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/scripts/harness_change.py +25 -7
- package/harness/bundles/java/codebuddy/scripts/harness_context.py +62 -19
- package/harness/bundles/java/codebuddy/scripts/harness_fixback.py +4 -0
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +208 -72
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +43 -0
- package/harness/bundles/java/codebuddy/scripts/harness_paths.py +60 -0
- package/harness/bundles/java/codebuddy/scripts/harness_phase.py +24 -6
- package/harness/bundles/java/codebuddy/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/java/codebuddy/scripts/harness_review.py +25 -4
- package/harness/bundles/java/codex/.harness-build.json +1 -1
- package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-plan/SKILL.md +3 -2
- package/harness/bundles/java/codex/harness-plan/checklist.md +18 -79
- package/harness/bundles/java/codex/harness-plan/protocols.md +3 -1
- package/harness/bundles/java/codex/harness-plan/reference.md +37 -8
- package/harness/bundles/java/codex/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +6 -4
- package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/codex/scripts/harness_change.py +25 -7
- package/harness/bundles/java/codex/scripts/harness_context.py +62 -19
- package/harness/bundles/java/codex/scripts/harness_fixback.py +4 -0
- package/harness/bundles/java/codex/scripts/harness_gate.py +208 -72
- package/harness/bundles/java/codex/scripts/harness_ledger.py +43 -0
- package/harness/bundles/java/codex/scripts/harness_paths.py +60 -0
- package/harness/bundles/java/codex/scripts/harness_phase.py +24 -6
- package/harness/bundles/java/codex/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/java/codex/scripts/harness_review.py +25 -4
- package/harness/bundles/java/cursor/.harness-build.json +1 -1
- package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-plan/SKILL.md +3 -2
- package/harness/bundles/java/cursor/harness-plan/checklist.md +18 -79
- package/harness/bundles/java/cursor/harness-plan/protocols.md +3 -1
- package/harness/bundles/java/cursor/harness-plan/reference.md +37 -8
- package/harness/bundles/java/cursor/harness-pull/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-push/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +6 -4
- package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
- package/harness/bundles/java/cursor/scripts/harness_change.py +25 -7
- package/harness/bundles/java/cursor/scripts/harness_context.py +62 -19
- package/harness/bundles/java/cursor/scripts/harness_fixback.py +4 -0
- package/harness/bundles/java/cursor/scripts/harness_gate.py +208 -72
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +43 -0
- package/harness/bundles/java/cursor/scripts/harness_paths.py +60 -0
- package/harness/bundles/java/cursor/scripts/harness_phase.py +24 -6
- package/harness/bundles/java/cursor/scripts/harness_plan_finalize.py +124 -1
- package/harness/bundles/java/cursor/scripts/harness_review.py +25 -4
- package/harness/manifests/general/claude-code.json +26 -26
- package/harness/manifests/general/codebuddy.json +26 -26
- package/harness/manifests/general/codex.json +26 -26
- package/harness/manifests/general/cursor.json +26 -26
- package/harness/manifests/java/claude-code.json +28 -28
- package/harness/manifests/java/codebuddy.json +28 -28
- package/harness/manifests/java/codex.json +28 -28
- package/harness/manifests/java/cursor.json +28 -28
- package/hunter-workflow-family.json +4 -4
- package/package.json +1 -1
|
@@ -351,7 +351,8 @@ status: approved
|
|
|
351
351
|
| `.harness/changes/<change>/plans/<change>-plan.md` | ✅(派生) | ✅ |
|
|
352
352
|
| `.harness/changes/<change>/plans/<change>-implementation-detail.md` | ✅(派生) | ✅ |
|
|
353
353
|
| `.harness/changes/<change>/plans/<change>-test-scenarios.md` | ✅(派生) | ✅ |
|
|
354
|
-
| `.harness/changes/<change>/meta/gate-policy.json` |
|
|
354
|
+
| `.harness/changes/<change>/meta/gate-policy.json` | ✅(**classify 写,非发布产物**) | ✅ |
|
|
355
|
+
| `.harness/changes/<change>/meta/plan-profile.json` | ✅(派生) | — |
|
|
355
356
|
| `.harness/changes/<change>/meta/worktree.json` | ✅ | ✅ |
|
|
356
357
|
| `.harness/changes/<change>/meta/implementation-checkpoints.json` | ✅ | ✅ |
|
|
357
358
|
| `.harness/changes/<change>/meta/scenario-manifest.json` | ✅ | ✅ |
|
|
@@ -363,6 +364,25 @@ status: approved
|
|
|
363
364
|
|
|
364
365
|
legacy 的 `plan-finalization.json.files` 必须完整列出 design、plan、implementation-detail、test-scenarios、gate-policy、worktree 六项标准输入。`verify` 对缺项、重复项、越界路径以及 symlink/junction/reparse point 一律 fail-closed;不得通过删减收据文件集后重算哈希来绕过完整性检查。
|
|
365
366
|
|
|
367
|
+
### 两套分类模型的边界(别把它们当同一件事)
|
|
368
|
+
|
|
369
|
+
| | Python `tier` | TS `mode` |
|
|
370
|
+
|---|---|---|
|
|
371
|
+
| 取值 | `fast` / `standard` / `full` | `quick` / `standard` / `assurance` |
|
|
372
|
+
| 写到哪 | `meta/gate-policy.json`(`schemaVersion:1`,camelCase) | `meta/plan-profile.json`(artifact 包装体,snake_case) |
|
|
373
|
+
| 谁写 | `harness_gate.py classify`(阶段 0.5 由 bootstrap-plan 调起) | `hunter-harness plan finalize`(阶段 8 发布) |
|
|
374
|
+
| 地位 | **门禁权威**:驱动 `requiredGateDag`、`requiredValidationsByPhase`,run/test 开门读它 | **派生视图**:供展示与下游只读消费,门禁不读 |
|
|
375
|
+
| 输入 | 计划文档的「风险等级」正则 + capabilityGates 信号 | 自然输入里手填的 `risk_signals` |
|
|
376
|
+
|
|
377
|
+
**两者不共用文件名。** v2 发布对 `binding.ownership_paths` 逐个原子覆盖,若派生视图占用 `meta/gate-policy.json`,阶段 8 会把 classify 写的那份换成包装体,之后 `gate begin --phase run` 直接 `POLICY_LOAD_FAILED`——`harness_gate.effective_workflow_policy` 读 `schemaVersion` 拿不到就 raise。
|
|
378
|
+
|
|
379
|
+
**为什么派生视图目前不能当权威**(将来要接通就得先解决这两条):
|
|
380
|
+
|
|
381
|
+
1. `plan evidence-pack` 对 `risk_signals` **不做任何推断**——不读 git diff、不扫路径、不解析 frontmatter,值完全来自自然输入里手填的那个数组。拿它当门禁权威等于让 agent 自声明低风险来跳门禁。
|
|
382
|
+
2. 命令里的 `capabilities` 是写死的(`is_git:true, has_remote:true, uses_worktree:false`),用户在阶段 0.6 通过 `configure-plan` 选的阶段计划被完全忽略,`planned_phases` 退化成 mode 的纯函数。
|
|
383
|
+
|
|
384
|
+
`meta/implementation-checkpoints.json` 的情况不同:v2 包装体里的 `content.foundation_gate` 信息是够的,所以门禁在**只读侧**解包(`checkpoint_status` 同时认 `checkpoints[]`、顶层 `foundationGate` 与 v2 包装体三种形状),不改文件名。注意写回路径(`gate checkpoint approve`)仍然操作原始文档——用归一化结构覆盖会破坏 v2 产物的哈希绑定。
|
|
385
|
+
|
|
366
386
|
### 阶段 8 v2 路径(结构化证据包流程,新 change 优先)
|
|
367
387
|
|
|
368
388
|
阶段 8 v2 标准三步流(证据包自举,阶段 14 起可用):
|
|
@@ -422,13 +442,22 @@ npx hunter-harness plan finalize --input .harness/changes/<cn>/meta/plan-evidenc
|
|
|
422
442
|
| `context` | project_id/run_id/branch_name/attempt(复用 plan-run-id 与 attempt) | 0.5 |
|
|
423
443
|
| `expected_baseline` | 首次发布 `{state:"absent", manifest_hash:null, generation:0}` | 8 |
|
|
424
444
|
|
|
425
|
-
>
|
|
426
|
-
>
|
|
427
|
-
>
|
|
428
|
-
> `
|
|
429
|
-
>
|
|
430
|
-
>
|
|
431
|
-
>
|
|
445
|
+
> **场景契约与门禁的对接**(曾经的已知缺口,现已打通)
|
|
446
|
+
>
|
|
447
|
+
> v2 派生的 `meta/scenario-manifest.json` 是 artifact 包装体,键名与门禁消费的不同。消费端
|
|
448
|
+
> (`harness_gate` 的 C9、`harness_ledger` 的三处)统一调 `harness_plan_finalize.unpack_v2_scenario_manifest`
|
|
449
|
+
> 解成 legacy 形状再判定:`scenario_id→id`、`owner_phase→ownerPhase`、`required_evidence_kind→requiredEvidenceKind`
|
|
450
|
+
> 、可执行三元 `executable_test_id/test_file/test_title→executableTestId/testFile/testTitle`。
|
|
451
|
+
> `required_evidence_kind` 由 `priority` 派生(P0/P1→`ledger`,P2→`advisory`),写在 artifact 里,
|
|
452
|
+
> 消费侧不重推。
|
|
453
|
+
>
|
|
454
|
+
> 因此自然输入的 `scenarios` **必须**带 `priority`(P0/P1/P2)与 `owner_phase`。缺任一项,
|
|
455
|
+
> 门禁**逐场景**校验后报 `SCENARIO_MANIFEST_V2_UNSUPPORTED` 并列出 `missingFields`,绝不静默放行
|
|
456
|
+
> ——逐场景而不是取键的并集:并集只要有一条场景带了 `priority` 就算通过,其余缺字段的会静默
|
|
457
|
+
> 落进非必需集,"必需场景"随之缩水。
|
|
458
|
+
>
|
|
459
|
+
> 可执行三元是**可选**的,但要么整组给全、要么整组省略。ledger 场景全部带齐 → manifest 声明
|
|
460
|
+
> `schemaVersion 2`,关门可绑结构化执行收据;否则降为 1。
|
|
432
461
|
|
|
433
462
|
- **证据包**(`plan-evidence.json`)是命令推导的产物(trusted/publication/context/baseline),不得手改;任何字段变化必须改自然输入后重跑 evidence-pack。
|
|
434
463
|
- **成功语义**:finalize exit 0 且 `code:"PLAN_FINALIZED"`。落盘事实 = 八 target(plans/*.md ×4 + meta/*.json ×4)+ `meta/publication-journals/<op>.json`(状态 committed)+ `meta/plan-events.ndjson`(artifact_published/phase_ended)。确定性门失败 exit 1 且 `code:"PLAN_FINALIZE_DETERMINISTIC_FAILED"` 附 findings——此时必须回到对应阶段修正规划内容,**不得**手改证据包或 staged 内容绕过。
|
|
@@ -3,7 +3,7 @@ name: harness-pull
|
|
|
3
3
|
description: 从 Hunter Platform 下拉配置/规则/架构/指令(及显式来源分支的分支文件恢复)。仅当用户显式调用
|
|
4
4
|
/harness-pull 或明确说'从平台拉取/恢复'时使用;不得自动触发。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=874039c57f9d1bc4; overlay=java; agent=codex; do not edit -->
|
|
7
7
|
# harness-pull — 从 Hunter Platform 下拉与恢复
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -3,7 +3,7 @@ name: harness-push
|
|
|
3
3
|
description: 上传本地配置/规则/架构/指令(及显式归档)到 Hunter Platform。仅当用户显式调用 /harness-push
|
|
4
4
|
或明确说'上传到平台'时使用;不得因存在本地修改就自动触发。
|
|
5
5
|
---
|
|
6
|
-
<!-- generated by harness_deploy.py; core=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=874039c57f9d1bc4; overlay=java; agent=codex; do not edit -->
|
|
7
7
|
# harness-push — 上传到 Hunter Platform
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -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=
|
|
7
|
+
<!-- generated by harness_deploy.py; core=874039c57f9d1bc4; overlay=java; agent=codex; do not edit -->
|
|
8
8
|
# harness-review — 代码审查
|
|
9
9
|
|
|
10
10
|
## Purpose
|
|
@@ -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=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=874039c57f9d1bc4; overlay=java; agent=codex; do not edit -->
|
|
7
7
|
# harness-run — 需求编码
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -83,13 +83,15 @@ python <skills-root>/scripts/harness_test_runner.py exec --project . --timeout-s
|
|
|
83
83
|
|
|
84
84
|
返回 `TEST_RUN_ALREADY_ACTIVE`(退出码 3)说明**已有构建在跑**:等它结束或用 `lock-status` 查明持有者,**不得**改用裸跑绕开锁,也不得另起一个并行构建。确认持有进程已消失时才用 `lock-reap` 回收。
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
**长阶段租约**:`gate begin` 的租约默认 TTL 3600 秒,而 run 阶段常常跑得更久。租约过期不会中断执行,**也不再阻断收尾**:`gate close` 发现租约过期而 run-id 仍是本阶段的,会自动用原 run-id 重取并照常关门,只在返回体的 `leaseLapsed` 里记下这个阶段跑过了 TTL。过期本身不说明所有权变了——抢占会重写租约文件把 run-id 换掉,那时报的是 `LEASE_OWNER_MISMATCH`。
|
|
87
|
+
|
|
88
|
+
因此**不需要**为了长阶段定期续租。确实想让租约始终有效时,用本阶段原 run-id 刷新即可(同 run-id 重复 claim 即刷新,不会新开 attempt):
|
|
87
89
|
|
|
88
90
|
```text
|
|
89
91
|
python <skills-root>/scripts/harness_change.py claim --change <id> --phase run --run-id <本阶段 run-id> --ttl-seconds 3600 --json
|
|
90
92
|
```
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
仍然报 `LEASE_ABSENT` 说明这个阶段**根本没有租约记录**(从未 begin,或已被释放),不是超时;先确认 `gate begin` 真的跑过。报 `LEASE_INVALID` 说明租约文件损坏,无法证明没被抢占,需人工确认无并发后再用上面的命令重取。两种情况都**不要**重跑 `gate begin`——那会新开 attempt 并丢失本轮 capsule。
|
|
93
95
|
|
|
94
96
|
**执行器边界**:优先使用项目 build profile 和已有测试入口。禁止为了绕过 ESM、路径或参数问题临时生成 `.js`、`require` 脚本;需要文件式 runner 时使用项目已有入口,确需新增时遵循项目模块类型(例如 ESM 使用 `.mjs`)。runner 包装说明写入 `runnerCommand` 元数据,不得拼进账本的规范 `command`。
|
|
95
97
|
|
|
@@ -131,7 +133,7 @@ python <skills-root>/scripts/harness_change.py claim --change <id> --phase run -
|
|
|
131
133
|
| **关门/状态** | 10 项关门检查;持久化 run-task-status;仅 run-owned P0 静态-only 导致 WARN;test-owned 待办正常移交 |
|
|
132
134
|
| **Worktree** | `requested=true` 时代码只写 worktree |
|
|
133
135
|
| **构建/测试** | 一律经 `harness_test_runner.py exec`;禁止裸跑 mvn/gradle/npm test;`TEST_RUN_ALREADY_ACTIVE` 表示已有构建在跑,等待而非另起 |
|
|
134
|
-
| **租约** | 阶段超
|
|
136
|
+
| **租约** | 阶段超 TTL 由 close 自动用原 run-id 重取,无需续租;`LEASE_ABSENT`(无记录)/`LEASE_INVALID`(文件损坏)才需人工 `harness_change.py claim`,一律不重跑 begin |
|
|
135
137
|
| **PowerShell** | 所有 git 经 `powershell.exe -NoProfile -Command` |
|
|
136
138
|
|
|
137
139
|
### 陈旧测试安全修复与精确跟踪
|
|
@@ -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=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=874039c57f9d1bc4; overlay=java; agent=codex; 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, remote knowledge ownership, instruction entrypoints,
|
|
5
5
|
config origins, or CodeGraph status.
|
|
6
6
|
---
|
|
7
|
-
<!-- generated by harness_deploy.py; core=
|
|
7
|
+
<!-- generated by harness_deploy.py; core=874039c57f9d1bc4; overlay=java; agent=codex; 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=
|
|
6
|
+
<!-- generated by harness_deploy.py; core=874039c57f9d1bc4; overlay=java; agent=codex; do not edit -->
|
|
7
7
|
# harness-test — 测试执行
|
|
8
8
|
|
|
9
9
|
## Purpose
|
|
@@ -564,18 +564,36 @@ def _lease_expired(lease: dict[str, Any]) -> bool:
|
|
|
564
564
|
return dt.datetime.now().astimezone() >= exp_dt
|
|
565
565
|
|
|
566
566
|
|
|
567
|
-
def
|
|
568
|
-
"""
|
|
567
|
+
def inspect_lease_state(project_root: Path, change_id: str) -> dict[str, Any]:
|
|
568
|
+
"""Read the lease without mutating it, keeping the three failure modes apart.
|
|
569
|
+
|
|
570
|
+
``inspect_lease`` collapses absent / expired / corrupt into ``None``, so a
|
|
571
|
+
caller cannot tell "nobody ever held this" from "the phase outlived its
|
|
572
|
+
TTL". Those need different answers: an expired lease still carries the
|
|
573
|
+
runId that proves who owns the phase, a corrupt one proves nothing, and an
|
|
574
|
+
absent one may just mean the phase already closed.
|
|
575
|
+
|
|
576
|
+
state is one of ``active`` | ``expired`` | ``absent`` | ``corrupt``. The
|
|
577
|
+
lease dict is returned for ``active`` and ``expired``; ``None`` otherwise.
|
|
578
|
+
"""
|
|
569
579
|
path = _lease_path(project_root, change_id)
|
|
570
580
|
if not path.is_file():
|
|
571
|
-
return None
|
|
581
|
+
return {"state": "absent", "lease": None}
|
|
572
582
|
try:
|
|
573
583
|
lease = _read_json(path)
|
|
574
584
|
except (OSError, json.JSONDecodeError):
|
|
575
|
-
return None
|
|
576
|
-
if not isinstance(lease, dict)
|
|
577
|
-
return None
|
|
578
|
-
|
|
585
|
+
return {"state": "corrupt", "lease": None}
|
|
586
|
+
if not isinstance(lease, dict):
|
|
587
|
+
return {"state": "corrupt", "lease": None}
|
|
588
|
+
if _lease_expired(lease):
|
|
589
|
+
return {"state": "expired", "lease": lease}
|
|
590
|
+
return {"state": "active", "lease": lease}
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def inspect_lease(project_root: Path, change_id: str) -> dict[str, Any] | None:
|
|
594
|
+
"""Return the current non-expired lease without mutating it."""
|
|
595
|
+
state = inspect_lease_state(project_root, change_id)
|
|
596
|
+
return state["lease"] if state["state"] == "active" else None
|
|
579
597
|
|
|
580
598
|
|
|
581
599
|
def _claim_lease_locked(
|
|
@@ -21,6 +21,7 @@ if str(SCRIPTS_DIR) not in sys.path:
|
|
|
21
21
|
sys.path.insert(0, str(SCRIPTS_DIR))
|
|
22
22
|
|
|
23
23
|
import harness_ledger as hl # noqa: E402
|
|
24
|
+
import harness_paths as hpaths # noqa: E402
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
PHASE_GRAPH = {
|
|
@@ -31,17 +32,8 @@ PHASE_GRAPH = {
|
|
|
31
32
|
"submit": (),
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"run",
|
|
37
|
-
"test",
|
|
38
|
-
"review",
|
|
39
|
-
"package",
|
|
40
|
-
"apidoc",
|
|
41
|
-
"submit",
|
|
42
|
-
"merge",
|
|
43
|
-
"archive",
|
|
44
|
-
)
|
|
35
|
+
# 唯一权威清单在 harness_paths(叶子模块,harness_phase 引的是同一个对象)。
|
|
36
|
+
WORKFLOW_PHASES = hpaths.WORKFLOW_PHASES
|
|
45
37
|
|
|
46
38
|
DISPLAY_TITLE_MAX_LENGTH = 80
|
|
47
39
|
|
|
@@ -270,13 +262,24 @@ def _contract(project: Path, change: str) -> tuple[Path, dict[str, Any], Path]:
|
|
|
270
262
|
|
|
271
263
|
|
|
272
264
|
def _phase_plan(contract_root: Path) -> tuple[list[str] | None, str]:
|
|
265
|
+
"""读出阶段计划;无法采信时说明原因,而不是悄悄退成 legacy。
|
|
266
|
+
|
|
267
|
+
以前这里遇到未知阶段名一律返回 (None, "legacy"):阶段计划整个失效,
|
|
268
|
+
`_allowed_next_phases` 退回硬编码的 PHASE_GRAPH,而调用方看不出发生过这件事。
|
|
269
|
+
未知阶段名不是假想问题——阶段清单少一个 merge 时,worktree 变更的
|
|
270
|
+
plannedPhases 就会带着 merge 走到这里。
|
|
271
|
+
|
|
272
|
+
未知名先过 LEGACY_PHASE_ALIASES 读时映射(阶段改名后历史 change 靠它继续可读),
|
|
273
|
+
仍然解析不了才降级,并把原因与具体阶段名带在 source 里。
|
|
274
|
+
"""
|
|
273
275
|
policy_path = contract_root / "meta" / "gate-policy.json"
|
|
274
276
|
if not policy_path.is_file():
|
|
275
277
|
return None, "legacy"
|
|
276
278
|
try:
|
|
277
279
|
policy = _read_json(policy_path)
|
|
278
280
|
except (OSError, ValueError, json.JSONDecodeError):
|
|
279
|
-
return None, "legacy"
|
|
281
|
+
return None, "legacy:policy-unreadable"
|
|
282
|
+
unknown: list[str] = []
|
|
280
283
|
for field, source in (
|
|
281
284
|
("plannedPhases", "change"),
|
|
282
285
|
("defaultPhases", "policy-default"),
|
|
@@ -285,12 +288,17 @@ def _phase_plan(contract_root: Path) -> tuple[list[str] | None, str]:
|
|
|
285
288
|
if not isinstance(raw, list):
|
|
286
289
|
continue
|
|
287
290
|
phases = [str(item).strip() for item in raw if str(item).strip()]
|
|
288
|
-
if (
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
291
|
+
if not phases or len(phases) != len(set(phases)):
|
|
292
|
+
continue
|
|
293
|
+
resolved = [hpaths.resolve_phase_name(item) for item in phases]
|
|
294
|
+
missing = [item for item, hit in zip(phases, resolved) if hit is None]
|
|
295
|
+
if missing:
|
|
296
|
+
unknown.extend(missing)
|
|
297
|
+
continue
|
|
298
|
+
# 映射后可能出现重复(两个旧名合并成同一个新阶段),保序去重。
|
|
299
|
+
return list(dict.fromkeys(str(item) for item in resolved)), source
|
|
300
|
+
if unknown:
|
|
301
|
+
return None, "legacy:unknown-phases=" + ",".join(dict.fromkeys(unknown))
|
|
294
302
|
return None, "legacy"
|
|
295
303
|
|
|
296
304
|
|
|
@@ -405,6 +413,7 @@ def _paths(state_root: Path) -> dict[str, Path]:
|
|
|
405
413
|
"begins": runtime / "transition-begins.ndjson",
|
|
406
414
|
"current": runtime / "current-context.json",
|
|
407
415
|
"lease": runtime / "context-lease.json",
|
|
416
|
+
"adoptions": runtime / "context-adoptions.ndjson",
|
|
408
417
|
}
|
|
409
418
|
|
|
410
419
|
|
|
@@ -604,8 +613,14 @@ def _claim_prepared_context(
|
|
|
604
613
|
)
|
|
605
614
|
except (OSError, ValueError, json.JSONDecodeError):
|
|
606
615
|
return {"ok": False, "code": "CONTEXT_CURRENT_INVALID"}
|
|
616
|
+
# 跨阶段推进必须有 receipt 证明它合法;同一个阶段换执行者不需要。
|
|
617
|
+
# 以前两者都要 receipt,于是上一阶段崩溃没能正常 close 时,接手的工具
|
|
618
|
+
# 连"继续把这个阶段干完"都做不到。并发保护不受影响:租约未过期而
|
|
619
|
+
# owner 不同,上面 CONTEXT_LEASE_HELD 已经拦下了,能走到这里只剩
|
|
620
|
+
# 「租约已过期」和「租约已被上一阶段 close 删除」两种情况。
|
|
621
|
+
adoption: dict[str, Any] | None = None
|
|
607
622
|
if recovery is None and isinstance(current, dict) and (
|
|
608
|
-
current.get("
|
|
623
|
+
current.get("phase") != phase
|
|
609
624
|
):
|
|
610
625
|
valid_receipt = (
|
|
611
626
|
isinstance(latest, dict)
|
|
@@ -621,6 +636,19 @@ def _claim_prepared_context(
|
|
|
621
636
|
"toExecutor": executor,
|
|
622
637
|
"toPhase": phase,
|
|
623
638
|
}
|
|
639
|
+
executor_changed = (
|
|
640
|
+
isinstance(current, dict) and current.get("executor") != executor
|
|
641
|
+
)
|
|
642
|
+
if recovery is not None or executor_changed:
|
|
643
|
+
adoption = {
|
|
644
|
+
"previousExecutor": (
|
|
645
|
+
current.get("executor") if isinstance(current, dict) else None
|
|
646
|
+
),
|
|
647
|
+
"newExecutor": executor,
|
|
648
|
+
"reason": (
|
|
649
|
+
"lease_expired" if recovery is not None else "same_phase_handoff"
|
|
650
|
+
),
|
|
651
|
+
}
|
|
624
652
|
|
|
625
653
|
try:
|
|
626
654
|
execution_root = _execution_root(project, contract_root, state_root)
|
|
@@ -657,6 +685,20 @@ def _claim_prepared_context(
|
|
|
657
685
|
current_context["preparationId"] = preparation_id
|
|
658
686
|
_write_json_atomic(paths["lease"], lease)
|
|
659
687
|
_write_json_atomic(paths["current"], current_context)
|
|
688
|
+
if adoption is not None:
|
|
689
|
+
# 接管必须留痕。过期租约本来就允许任何执行者顶替,但以前只在返回体
|
|
690
|
+
# 里挂一个 recovery,退出进程就没了——事后查"这个阶段是谁接手的"
|
|
691
|
+
# 无据可依。收据形状照 harness_archive.adopt_existing_range。
|
|
692
|
+
adoption = {
|
|
693
|
+
"schemaVersion": 1,
|
|
694
|
+
"changeName": change,
|
|
695
|
+
"phase": phase,
|
|
696
|
+
**adoption,
|
|
697
|
+
"previousOwner": recovery.get("previousOwner") if recovery else None,
|
|
698
|
+
"expiredAt": recovery.get("expiredAt") if recovery else None,
|
|
699
|
+
"adoptedAt": now.isoformat(),
|
|
700
|
+
}
|
|
701
|
+
_append_ndjson(paths["adoptions"], adoption)
|
|
660
702
|
return {
|
|
661
703
|
"ok": True,
|
|
662
704
|
"lease": lease,
|
|
@@ -664,6 +706,7 @@ def _claim_prepared_context(
|
|
|
664
706
|
"transitions": transitions,
|
|
665
707
|
"latestTransition": latest,
|
|
666
708
|
"recovery": recovery,
|
|
709
|
+
"adoption": adoption,
|
|
667
710
|
"executionRoot": str(execution_root),
|
|
668
711
|
}
|
|
669
712
|
|
|
@@ -405,6 +405,10 @@ def _default_gate_begin(**kwargs: Any) -> dict[str, Any]:
|
|
|
405
405
|
str(kwargs["run_id"]),
|
|
406
406
|
"--note",
|
|
407
407
|
"开始处理评审中确认需要修改的代码问题。",
|
|
408
|
+
# 显式标记这一轮是 review fixback。以前靠 gate 嗅探 note 里有没有
|
|
409
|
+
# "fixback" 字样——而上面这条 note 一个都没有,于是 fixback 的 run 事件
|
|
410
|
+
# 从来没被打上 trigger/from_phase。
|
|
411
|
+
"--fixback",
|
|
408
412
|
]
|
|
409
413
|
for option, key in (
|
|
410
414
|
("--executor-tool", "executor_tool"),
|