@hunter-harness/workflow-harness 0.2.39 → 0.2.41
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-archive/checklist.md +3 -0
- package/harness/bundles/general/claude-code/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/general/claude-code/harness-plan/reference.md +16 -16
- package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/claude-code/harness-run/reference.md +1 -1
- 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 +3 -1
- package/harness/bundles/general/claude-code/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/general/claude-code/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/general/claude-code/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/general/claude-code/scripts/harness_archive.py +413 -2
- package/harness/bundles/general/claude-code/scripts/harness_deploy.py +10 -51
- package/harness/bundles/general/claude-code/scripts/harness_environment.py +556 -39
- package/harness/bundles/general/claude-code/scripts/harness_gate.py +145 -0
- package/harness/bundles/general/claude-code/scripts/harness_ledger.py +581 -55
- package/harness/bundles/general/claude-code/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/general/claude-code/scripts/harness_service.py +291 -22
- package/harness/bundles/general/claude-code/scripts/harness_test_runner.py +405 -25
- 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-archive/checklist.md +3 -0
- package/harness/bundles/general/codebuddy/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/general/codebuddy/harness-plan/reference.md +16 -16
- package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codebuddy/harness-run/reference.md +1 -1
- 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 +3 -1
- package/harness/bundles/general/codebuddy/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/general/codebuddy/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/general/codebuddy/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/general/codebuddy/scripts/harness_archive.py +413 -2
- package/harness/bundles/general/codebuddy/scripts/harness_deploy.py +10 -51
- package/harness/bundles/general/codebuddy/scripts/harness_environment.py +556 -39
- package/harness/bundles/general/codebuddy/scripts/harness_gate.py +145 -0
- package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +581 -55
- package/harness/bundles/general/codebuddy/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/general/codebuddy/scripts/harness_service.py +291 -22
- package/harness/bundles/general/codebuddy/scripts/harness_test_runner.py +405 -25
- 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-archive/checklist.md +3 -0
- package/harness/bundles/general/codex/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/general/codex/harness-plan/reference.md +16 -16
- package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/codex/harness-run/reference.md +1 -1
- 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 +3 -1
- package/harness/bundles/general/codex/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/general/codex/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/general/codex/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/general/codex/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/general/codex/scripts/harness_archive.py +413 -2
- package/harness/bundles/general/codex/scripts/harness_deploy.py +10 -51
- package/harness/bundles/general/codex/scripts/harness_environment.py +556 -39
- package/harness/bundles/general/codex/scripts/harness_gate.py +145 -0
- package/harness/bundles/general/codex/scripts/harness_ledger.py +581 -55
- package/harness/bundles/general/codex/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/general/codex/scripts/harness_service.py +291 -22
- package/harness/bundles/general/codex/scripts/harness_test_runner.py +405 -25
- 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-archive/checklist.md +3 -0
- package/harness/bundles/general/cursor/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/general/cursor/harness-plan/reference.md +16 -16
- package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
- package/harness/bundles/general/cursor/harness-run/reference.md +1 -1
- 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 +3 -1
- package/harness/bundles/general/cursor/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/general/cursor/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/general/cursor/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/general/cursor/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/general/cursor/scripts/harness_archive.py +413 -2
- package/harness/bundles/general/cursor/scripts/harness_deploy.py +10 -51
- package/harness/bundles/general/cursor/scripts/harness_environment.py +556 -39
- package/harness/bundles/general/cursor/scripts/harness_gate.py +145 -0
- package/harness/bundles/general/cursor/scripts/harness_ledger.py +581 -55
- package/harness/bundles/general/cursor/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/general/cursor/scripts/harness_service.py +291 -22
- package/harness/bundles/general/cursor/scripts/harness_test_runner.py +405 -25
- 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-archive/checklist.md +3 -0
- package/harness/bundles/java/claude-code/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/java/claude-code/harness-plan/reference.md +16 -16
- package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
- 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 +3 -1
- package/harness/bundles/java/claude-code/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/java/claude-code/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/java/claude-code/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/java/claude-code/scripts/harness_archive.py +413 -2
- package/harness/bundles/java/claude-code/scripts/harness_deploy.py +10 -51
- package/harness/bundles/java/claude-code/scripts/harness_environment.py +556 -39
- package/harness/bundles/java/claude-code/scripts/harness_gate.py +145 -0
- package/harness/bundles/java/claude-code/scripts/harness_ledger.py +581 -55
- package/harness/bundles/java/claude-code/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/java/claude-code/scripts/harness_service.py +291 -22
- package/harness/bundles/java/claude-code/scripts/harness_test_runner.py +405 -25
- 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-archive/checklist.md +3 -0
- package/harness/bundles/java/codebuddy/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/java/codebuddy/harness-plan/reference.md +16 -16
- package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
- 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 +3 -1
- package/harness/bundles/java/codebuddy/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/java/codebuddy/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/java/codebuddy/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/java/codebuddy/scripts/harness_archive.py +413 -2
- package/harness/bundles/java/codebuddy/scripts/harness_deploy.py +10 -51
- package/harness/bundles/java/codebuddy/scripts/harness_environment.py +556 -39
- package/harness/bundles/java/codebuddy/scripts/harness_gate.py +145 -0
- package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +581 -55
- package/harness/bundles/java/codebuddy/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/java/codebuddy/scripts/harness_service.py +291 -22
- package/harness/bundles/java/codebuddy/scripts/harness_test_runner.py +405 -25
- 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-archive/checklist.md +3 -0
- package/harness/bundles/java/codex/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/java/codex/harness-plan/reference.md +16 -16
- package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
- 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 +3 -1
- package/harness/bundles/java/codex/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/java/codex/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/java/codex/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/java/codex/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/java/codex/scripts/harness_archive.py +413 -2
- package/harness/bundles/java/codex/scripts/harness_deploy.py +10 -51
- package/harness/bundles/java/codex/scripts/harness_environment.py +556 -39
- package/harness/bundles/java/codex/scripts/harness_gate.py +145 -0
- package/harness/bundles/java/codex/scripts/harness_ledger.py +581 -55
- package/harness/bundles/java/codex/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/java/codex/scripts/harness_service.py +291 -22
- package/harness/bundles/java/codex/scripts/harness_test_runner.py +405 -25
- 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-archive/checklist.md +3 -0
- package/harness/bundles/java/cursor/harness-archive/templates/render-summary.mjs +22 -0
- 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 +1 -1
- package/harness/bundles/java/cursor/harness-plan/reference.md +16 -16
- package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
- package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
- 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 +3 -1
- package/harness/bundles/java/cursor/protocols/archive-report-protocol.md +10 -0
- package/harness/bundles/java/cursor/protocols/ledger-protocol.md +12 -0
- package/harness/bundles/java/cursor/protocols/powershell-protocol.md +21 -0
- package/harness/bundles/java/cursor/protocols/state-layout-protocol.md +11 -0
- package/harness/bundles/java/cursor/scripts/harness_archive.py +413 -2
- package/harness/bundles/java/cursor/scripts/harness_deploy.py +10 -51
- package/harness/bundles/java/cursor/scripts/harness_environment.py +556 -39
- package/harness/bundles/java/cursor/scripts/harness_gate.py +145 -0
- package/harness/bundles/java/cursor/scripts/harness_ledger.py +581 -55
- package/harness/bundles/java/cursor/scripts/harness_plan_finalize.py +85 -6
- package/harness/bundles/java/cursor/scripts/harness_service.py +291 -22
- package/harness/bundles/java/cursor/scripts/harness_test_runner.py +405 -25
- package/harness/manifests/general/claude-code.json +29 -29
- package/harness/manifests/general/codebuddy.json +29 -29
- package/harness/manifests/general/codex.json +29 -29
- package/harness/manifests/general/cursor.json +29 -29
- package/harness/manifests/java/claude-code.json +30 -30
- package/harness/manifests/java/codebuddy.json +30 -30
- package/harness/manifests/java/codex.json +30 -30
- package/harness/manifests/java/cursor.json +30 -30
- package/hunter-workflow-family.json +4 -4
- package/package.json +1 -1
|
@@ -20,7 +20,7 @@ disallowed-tools:
|
|
|
20
20
|
- Bash(awk *)
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
---
|
|
23
|
-
<!-- generated by harness_deploy.py; core=
|
|
23
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
24
24
|
# harness-archive — 变更归档
|
|
25
25
|
|
|
26
26
|
## Purpose
|
|
@@ -13,6 +13,9 @@ description: harness-archive 的归档前检查项和归档后验证项。仅在
|
|
|
13
13
|
- final-summary 的统计只能来自 summary-data 或 manifest。
|
|
14
14
|
- before/after checksum 不一致时,不得删除原目录。
|
|
15
15
|
- 默认渲染器 `templates/render-summary.mjs`(finalize 内嵌调用)。
|
|
16
|
+
- 需要跨工作区恢复时传 `--durable-root <独立存储>`;成功必须为 `ARCHIVED_DURABLE`,并验证 content-addressed object 与 durable receipt 可读回。
|
|
17
|
+
- `restore-durable` 只恢复到不存在的目标;目标已存在或对象 digest 不符时 fail closed,禁止覆盖。
|
|
18
|
+
- 未配置 durable root 时显式记录 `ARCHIVED_LOCAL_ONLY` 风险,不得把同工作区 move 宣称为独立备份。
|
|
16
19
|
|
|
17
20
|
### Wave-A 状态机与身份(IA-1 / IA-4)
|
|
18
21
|
|
|
@@ -48,6 +48,8 @@ const identity = Object.keys(record(normalized.identity)).length
|
|
|
48
48
|
const verification = Object.keys(record(normalized.verification)).length
|
|
49
49
|
? record(normalized.verification)
|
|
50
50
|
: record(data.verification);
|
|
51
|
+
const scenarioCoverage = record(data.scenarioCoverage);
|
|
52
|
+
const unexecutedScenarios = list(scenarioCoverage.unexecuted);
|
|
51
53
|
const timing = Object.keys(record(normalized.timing)).length
|
|
52
54
|
? record(normalized.timing)
|
|
53
55
|
: record(data.timing);
|
|
@@ -200,6 +202,21 @@ const remoteCost = record(measurements.remoteCost);
|
|
|
200
202
|
const remoteCostTotals = record(remoteCost.totals);
|
|
201
203
|
const storage = record(measurements.artifactStorage);
|
|
202
204
|
const projection = record(data.projection);
|
|
205
|
+
const durability = record(data.archiveDurability);
|
|
206
|
+
const durabilityStatus = durability.status || "ARCHIVED_LOCAL_ONLY";
|
|
207
|
+
const scenarioCoverageStatus = scenarioCoverage.skipped
|
|
208
|
+
? "SKIPPED"
|
|
209
|
+
: scenarioCoverage.ok
|
|
210
|
+
? "OK"
|
|
211
|
+
: scenarioCoverage.code || "NOT_RUN";
|
|
212
|
+
const scenarioCoverageHtml = `
|
|
213
|
+
<article class="card"><h2>场景执行闭环</h2>
|
|
214
|
+
<div class="fact"><span>结构化运行回执</span>${pill(scenarioCoverageStatus)}</div>
|
|
215
|
+
<div class="fact"><span>已执行并通过</span><strong>${list(scenarioCoverage.passed).length}</strong></div>
|
|
216
|
+
<div class="fact"><span>未执行 / 未通过</span><span>${unexecutedScenarios.length
|
|
217
|
+
? `<code>${esc(unexecutedScenarios.join(", "))}</code>`
|
|
218
|
+
: "无"}</span></div>
|
|
219
|
+
</article>`;
|
|
203
220
|
|
|
204
221
|
const html = `<!doctype html>
|
|
205
222
|
<html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
@@ -227,12 +244,14 @@ const html = `<!doctype html>
|
|
|
227
244
|
<article class="metric"><small>代码范围</small><strong>${esc(record(data.diffStat).filesChanged ?? files.length)} 个文件</strong><small class="positive">+${esc(record(data.diffStat).insertions ?? 0)} · <span class="negative">-${esc(record(data.diffStat).deletions ?? 0)}</span></small></article>
|
|
228
245
|
</section>
|
|
229
246
|
<article class="card"><h2>验证概览</h2><div class="verification-grid">${groupHtml}</div></article>
|
|
247
|
+
${scenarioCoverageHtml}
|
|
230
248
|
<section class="two-column">
|
|
231
249
|
<article class="card"><h2>风险与动作</h2><div class="risk-actions"><section><h3>当前风险</h3><ul>${risksHtml}</ul></section><section><h3>人工动作</h3><ul>${actionsHtml}</ul></section></div></article>
|
|
232
250
|
<div>
|
|
233
251
|
${releaseHtml}
|
|
234
252
|
<article class="card"><h2>事实完整性</h2>
|
|
235
253
|
<div class="fact"><span>归档完整性</span>${pill(record(data.archiveIntegrity).ok === false ? "FAIL" : record(data.archiveManifest).checksumStatus || "UNKNOWN")}</div>
|
|
254
|
+
<div class="fact"><span>归档持久性</span><span>${pill(durabilityStatus === "ARCHIVED_DURABLE" ? "OK" : "WARN")} <code>${esc(durabilityStatus)}</code></span></div>
|
|
236
255
|
<div class="fact"><span>时间守恒</span>${pill(numeric(timing.conservationDeltaMs) === 0 ? "OK" : "WARN")}</div>
|
|
237
256
|
</article>
|
|
238
257
|
</div>
|
|
@@ -259,6 +278,9 @@ const html = `<!doctype html>
|
|
|
259
278
|
<dt>基线提交</dt><dd><code>${esc(identity.baseCommit || data.baseCommit || "N/A")}</code></dd>
|
|
260
279
|
<dt>报告数据版本</dt><dd>${esc(data.schemaVersion || "N/A")}</dd>
|
|
261
280
|
<dt>归档意图</dt><dd title="${esc(release.intent)}">${recordOnly ? "仅记录(未请求发布)" : esc(release.intent || "未声明")}</dd>
|
|
281
|
+
<dt>归档持久性</dt><dd><code>${esc(durabilityStatus)}</code>${durability.risk ? ` · ${esc(durability.risk)}` : ""}</dd>
|
|
282
|
+
<dt>保留策略</dt><dd>${esc(durability.retentionPolicy || "N/A")}</dd>
|
|
283
|
+
<dt>场景回执状态</dt><dd><code>${esc(scenarioCoverage.code || scenarioCoverageStatus)}</code></dd>
|
|
262
284
|
<dt>尝试记录</dt><dd>${attempts.length}</dd>
|
|
263
285
|
<dt>历史质量</dt><dd>${numeric(timing.unclosedAttemptCount) === 0 ? "无未闭合尝试" : `${esc(timing.unclosedAttemptCount ?? "N/A")} 个未闭合尝试`}</dd>
|
|
264
286
|
<dt>投影状态</dt><dd title="Projection / Fallback"><code>${esc(projection.code || projection.mode || "N/A")}</code></dd>
|
|
@@ -20,7 +20,7 @@ disallowed-tools:
|
|
|
20
20
|
- Bash(awk *)
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
---
|
|
23
|
-
<!-- generated by harness_deploy.py; core=
|
|
23
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
24
24
|
# harness-codebase-map — 代码库地图
|
|
25
25
|
|
|
26
26
|
## Purpose
|
|
@@ -20,7 +20,7 @@ disallowed-tools:
|
|
|
20
20
|
- Bash(awk *)
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
---
|
|
23
|
-
<!-- generated by harness_deploy.py; core=
|
|
23
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
24
24
|
# harness-knowledge-ingest
|
|
25
25
|
|
|
26
26
|
从 `.harness/archive/**/reports/final/summary-data.json` 抽取项目知识,生成并维护本地 `.harness/knowledge/` 索引。
|
|
@@ -20,7 +20,7 @@ disallowed-tools:
|
|
|
20
20
|
- Bash(awk *)
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
---
|
|
23
|
-
<!-- generated by harness_deploy.py; core=
|
|
23
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
24
24
|
# harness-knowledge-query
|
|
25
25
|
|
|
26
26
|
并行 change 中查询必须传 `--change <change-id>`;成功后以该 change 的 `meta/knowledge-context.json` 为稳定指针。全局 `context-packs/latest.json` 仅向后兼容,不得用于判断多个 active change 的上下文归属。
|
|
@@ -20,7 +20,7 @@ disallowed-tools:
|
|
|
20
20
|
- Bash(awk *)
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
---
|
|
23
|
-
<!-- generated by harness_deploy.py; core=
|
|
23
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
24
24
|
# harness-plan — 需求规划
|
|
25
25
|
|
|
26
26
|
## Purpose
|
|
@@ -228,35 +228,35 @@ status: approved
|
|
|
228
228
|
|
|
229
229
|
#### 1.1 <类名.方法名>
|
|
230
230
|
|
|
231
|
-
| ID | 优先级 | 分类 | 场景描述 | 输入 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
|
|
232
|
-
|
|
233
|
-
| UT-001 | P0 | 正常 | ... | ... | ... | affected | ≤10s | 1 worker / ≤512MB | 30s | inputsHash + command |
|
|
234
|
-
| UT-002 | P0 | 异常 | ... | ... | 抛 xxxException | affected | ≤10s | 1 worker / ≤512MB | 30s | inputsHash + command |
|
|
235
|
-
| UT-003 | P1 | 边界 | ... | ... | ... | module | ≤60s | ≤50% CPU / ≤1GB | 120s | ledger identity |
|
|
231
|
+
| ID | 优先级 | 分类 | 场景描述 | 输入 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 | 可执行测试 ID | 测试文件 | 测试标题 |
|
|
232
|
+
|:--:|:------:|:----:|----------|------|------|----------|----------|----------|------|------------|----------------|----------|----------|
|
|
233
|
+
| UT-001 | P0 | 正常 | ... | ... | ... | affected | ≤10s | 1 worker / ≤512MB | 30s | inputsHash + command | service::happy-path | tests/service.test.ts | returns expected result |
|
|
234
|
+
| UT-002 | P0 | 异常 | ... | ... | 抛 xxxException | affected | ≤10s | 1 worker / ≤512MB | 30s | inputsHash + command | service::invalid-input | tests/service.test.ts | rejects invalid input |
|
|
235
|
+
| UT-003 | P1 | 边界 | ... | ... | ... | module | ≤60s | ≤50% CPU / ≤1GB | 120s | ledger identity | service::boundary | tests/service.test.ts | handles boundary |
|
|
236
236
|
|
|
237
237
|
### 二、接口测试场景
|
|
238
238
|
|
|
239
239
|
#### 2.1 POST /xxx
|
|
240
240
|
|
|
241
|
-
| ID | 优先级 | 分类 | 场景描述 | 关键字段 | HTTP | code | message | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
|
|
242
|
-
|
|
243
|
-
| API-001 | P0 | 正常 | ... | ... | 200 | 0 | 成功 | module | ≤60s | 1 service / ≤1GB | 120s | environmentHash + ledger |
|
|
244
|
-
| API-002 | P1 | 校验 | ... | ... | 200 | xxx | ... | affected | ≤20s | 1 service / ≤1GB | 60s | environmentHash + ledger |
|
|
241
|
+
| ID | 优先级 | 分类 | 场景描述 | 关键字段 | HTTP | code | message | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 | 可执行测试 ID | 测试文件 | 测试标题 |
|
|
242
|
+
|:--:|:------:|:----:|----------|----------|:----:|:----:|--------|----------|----------|----------|------|------------|----------------|----------|----------|
|
|
243
|
+
| API-001 | P0 | 正常 | ... | ... | 200 | 0 | 成功 | module | ≤60s | 1 service / ≤1GB | 120s | environmentHash + ledger | api::success | tests/api.spec.ts | creates resource |
|
|
244
|
+
| API-002 | P1 | 校验 | ... | ... | 200 | xxx | ... | affected | ≤20s | 1 service / ≤1GB | 60s | environmentHash + ledger | api::validation | tests/api.spec.ts | rejects invalid body |
|
|
245
245
|
|
|
246
246
|
### 三、数据兼容场景
|
|
247
247
|
|
|
248
|
-
| ID | 优先级 | 分类 | 场景描述 | 操作 | 数据特征 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
|
|
249
|
-
|
|
250
|
-
| COM-001 | P1 | 旧数据 | ... | ... | ... | ... | module | ≤60s | isolated DB / ≤1GB | 120s | dbSchemaHash + ledger |
|
|
248
|
+
| ID | 优先级 | 分类 | 场景描述 | 操作 | 数据特征 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 | 可执行测试 ID | 测试文件 | 测试标题 |
|
|
249
|
+
|:--:|:------:|:----:|----------|:----:|----------|------|----------|----------|----------|------|------------|----------------|----------|----------|
|
|
250
|
+
| COM-001 | P1 | 旧数据 | ... | ... | ... | ... | module | ≤60s | isolated DB / ≤1GB | 120s | dbSchemaHash + ledger | db::legacy-row | tests/db-compat.spec.ts | reads legacy row |
|
|
251
251
|
|
|
252
252
|
### 四、集成场景
|
|
253
253
|
|
|
254
|
-
| ID | 优先级 | 分类 | 场景描述 | 前置条件 | 步骤 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
|
|
255
|
-
|
|
256
|
-
| INT-001 | P0 | 端到端 | ... | ... | N 步操作 | ... | candidate | ≤10m | ≤50% CPU / ≤2GB | 15m | verification identity |
|
|
254
|
+
| ID | 优先级 | 分类 | 场景描述 | 前置条件 | 步骤 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 | 可执行测试 ID | 测试文件 | 测试标题 |
|
|
255
|
+
|:--:|:------:|:----:|----------|----------|------|------|----------|----------|----------|------|------------|----------------|----------|----------|
|
|
256
|
+
| INT-001 | P0 | 端到端 | ... | ... | N 步操作 | ... | candidate | ≤10m | ≤50% CPU / ≤2GB | 15m | verification identity | e2e::workflow | tests/workflow.e2e.ts | completes workflow |
|
|
257
257
|
```
|
|
258
258
|
|
|
259
|
-
新计划必须显式使用 `ID
|
|
259
|
+
新计划必须显式使用 `ID`、`优先级`、`可执行测试 ID`、`测试文件`、`测试标题` 列;每个 P0/P1 场景都必须填写稳定的三元测试身份,缺任一字段时 plan finalize 返回 `PLAN_SCENARIO_EXECUTABLE_MAPPING_MISSING`。`P0/P1` 都要求结构化 runner receipt + ledger 证据,`P2` 才是 advisory。解析器兼容旧的 `#`、`分类`、`场景描述` 表头,旧表缺优先级时保守按 `P1` 处理。执行层级固定为 `affected`(快速反馈)、`module`(变更模块门禁)、`candidate`(产品候选)。禁止所有场景默认跑全仓库;无法给出预算或超时时必须说明原因,并拆分或隔离高成本场景。只有 command、inputs/toolchain/environment 身份一致,且 declared/selected/collected/executed/passed 闭环完整的成功 ledger 证据可以复用。
|
|
260
260
|
|
|
261
261
|
## 产物保存规则(跨阶段:阶段0.5/4/6/8)
|
|
262
262
|
|
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
- Bash(codegraph *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-review — 代码审查
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -21,7 +21,7 @@ disallowed-tools:
|
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
- Bash(codegraph *)
|
|
23
23
|
---
|
|
24
|
-
<!-- generated by harness_deploy.py; core=
|
|
24
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
25
25
|
# harness-run — 需求编码
|
|
26
26
|
|
|
27
27
|
## Purpose
|
|
@@ -533,7 +533,7 @@ python <skills-root>/scripts/harness_ledger.py record --change-dir ".harness/cha
|
|
|
533
533
|
|
|
534
534
|
> 这样 harness-test 的 Phase 1 可读取 ledger 判断是否复用 run 的 unitTest(diffHash commit-invariant + reuse 规则 #2 允许 HEAD 前移 → run 的 checkpoint commit 不破坏复用),submit 也可复用 compile 结果。详见 `../protocols/ledger-protocol.md`。
|
|
535
535
|
>
|
|
536
|
-
> **Ledger v3
|
|
536
|
+
> **Ledger v3**:`record` 自动解析并强制顶层身份(`schemaVersion=3/repositoryId/changeName/baseCommit/currentHead/diffHash/ownershipHash`),缺字段非零退出、不写账本;已有 v1/v2 ledger 在写前透明迁移,`migrationHistory` 回执记录原/目标 schema 与迁移前后 evidence identity。无法迁移时返回 `LEDGER_MIGRATION_REQUIRED` 和确定性 `rerecordCommand`,不得半升级。v2 契约下 `--metrics-json` 必须通过 typed schema(unit=`total/passed/failed`,apiContract=`scenariosTotal/passed/failed`,browserE2E=`total/passed/failed`,dbCompatibility=`applicability(+reason)`)。详见 `../protocols/ledger-protocol.md` 第十节。
|
|
537
537
|
|
|
538
538
|
阶段边界:`harness_gate.py begin/close`;测试跟踪:`harness_test_guard.py begin/close`。close 失败不得用自然语言覆盖。
|
|
539
539
|
|
|
@@ -20,7 +20,7 @@ disallowed-tools:
|
|
|
20
20
|
- Bash(awk *)
|
|
21
21
|
- Bash(curl *)
|
|
22
22
|
---
|
|
23
|
-
<!-- generated by harness_deploy.py; core=
|
|
23
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
24
24
|
# harness-submit — 最终提交(含 worktree 合并)
|
|
25
25
|
|
|
26
26
|
## Purpose
|
|
@@ -19,7 +19,7 @@ disallowed-tools:
|
|
|
19
19
|
- Bash(awk *)
|
|
20
20
|
- Bash(curl *)
|
|
21
21
|
---
|
|
22
|
-
<!-- generated by harness_deploy.py; core=
|
|
22
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
23
23
|
# harness-sync
|
|
24
24
|
|
|
25
25
|
## Purpose
|
|
@@ -22,7 +22,7 @@ disallowed-tools:
|
|
|
22
22
|
- Bash(node *)
|
|
23
23
|
- Bash(codegraph *)
|
|
24
24
|
---
|
|
25
|
-
<!-- generated by harness_deploy.py; core=
|
|
25
|
+
<!-- generated by harness_deploy.py; core=23e4a1b1c35dd556; overlay=none; agent=claude-code; do not edit -->
|
|
26
26
|
# harness-test — 测试执行
|
|
27
27
|
|
|
28
28
|
## Purpose
|
|
@@ -90,6 +90,8 @@ python harness/scripts/harness_test_runner.py unittest --profile safe --tests-di
|
|
|
90
90
|
|
|
91
91
|
Runner 强制同项目单实例、低调度优先级、逐命令超时、正常结束和异常结束的进程树清理。`HARNESS_TEST_MAX_WORKERS` 默认且最高为 `2`,只能调低,不能调高;技术栈自身的并发参数也必须收敛到该值。Windows detached-service 模块在执行前先做 nested-breakaway 能力探测,受限沙箱不支持时立即返回 `DETACHED_PROCESS_CAPABILITY_UNAVAILABLE`,不得让每个服务用例逐一超时。出现该错误、`TEST_RUN_ALREADY_ACTIVE`、`PROCESS_TREE_ISOLATION_UNAVAILABLE` 或 `TEST_COMMAND_TIMEOUT` 必须停止,不得绕过 Runner 重跑裸命令。完整约束见 `checklist.md`「0.0-A 资源安全档位」。
|
|
92
92
|
|
|
93
|
+
动态数据库/Redis/令牌字段必须先由 `harness_environment.py prepare` 生成 secret-free receipt,再用 `exec --environment-receipt <file> --required-environment-field <NAME>` 闭包注入;缺失或指纹变化在启动测试前返回 `VERIFICATION_ENVIRONMENT_INCOMPLETE`。复杂 JSON、Docker template 或含引号参数不得跨多层 `-Command` 传递,改用 `exec --argv-file <utf8-json> --runtime-receipt <file>`;参数文件记录 PowerShell edition/version,运行回执只存 argv hash。`harness_service.py ensure` 属于正式持久服务模式,禁止从 bounded runner 内启动;命中时返回 `PERSISTENT_SERVICE_MODE_REQUIRED`。
|
|
94
|
+
|
|
93
95
|
### Phase 0:环境准备(主会话执行,需要交互确认)
|
|
94
96
|
|
|
95
97
|
先 `harness_context.py prepare --phase test --executor <tool> [--change <id>] --json`,再 `harness_context.py begin --phase test --change <id> --executor <tool> --json` 校验最新 run→test receipt 的 artifact/hash/HEAD;然后 **`harness_gate.py begin --phase test --change <id>`**(禁止手工 phase.start / 手写 ledger)。执行各项强制环境检查 + **命令执行模式 preflight (0.1)**;只有首选执行器不可用时,才执行 fallback 执行器探测。
|
|
@@ -109,6 +109,16 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "harness-skills/harness-
|
|
|
109
109
|
- generatedFiles:archive 过程中生成的文件数;
|
|
110
110
|
- totalArchiveFiles:归档目录最终文件总数。
|
|
111
111
|
|
|
112
|
+
## Durable archive
|
|
113
|
+
|
|
114
|
+
同一工作区内从 `changes/` move 到 `archive/` 只属于 local archive。需要抗工作区删除时,finalize 必须配置独立 `--durable-root`:
|
|
115
|
+
|
|
116
|
+
- payload 以整树 digest 写入 `<durable-root>/objects/sha256/<digest>/payload/`,对象不可变且可内容寻址;
|
|
117
|
+
- `<durable-root>/receipts/<archive-id>.json` 记录 digest、来源 identity、保留策略与验证时间;
|
|
118
|
+
- durable 写入采用 staging → hash/readback verify → atomic publish;失败时保留原 change,且不得留下可被误认成功的 local archive;
|
|
119
|
+
- `restore-durable` 先验证 receipt 与对象 digest,只恢复到不存在的目标,完成后再次比对整树 digest;
|
|
120
|
+
- 成功状态区分 `ARCHIVED_DURABLE` 与 `ARCHIVED_LOCAL_ONLY`,后者必须进入 knownRisks。
|
|
121
|
+
|
|
112
122
|
## 页面内容
|
|
113
123
|
|
|
114
124
|
final-summary 必须突出:
|
|
@@ -351,3 +351,15 @@ v2 契约下 `record` 写入前强制解析并校验顶层身份字段,缺失
|
|
|
351
351
|
### 10.4 原子写入
|
|
352
352
|
|
|
353
353
|
`write_ledger` 采用 tmp → fsync → `os.replace`;replace 失败时旧账本字节不变、不留 `.tmp` 残骸。所有写路径(record / 其他命令)统一走原子写。
|
|
354
|
+
|
|
355
|
+
### 10.5 写前透明迁移
|
|
356
|
+
|
|
357
|
+
Reader 继续读取当前 v3 与前一支持窗口 v2(并保守识别无 schema 的 v1)。已有 schemaVersion 2 ledger,或显式携带 identity 参数的 legacy ledger,再次 `record` 时必须先完成身份迁移再修改任何 evidence;无 schema 且未显式请求 identity 的旧调用继续保持兼容行为:
|
|
358
|
+
|
|
359
|
+
- 解析 repository/change/base/current/diff/ownership identity,目标固定为 schemaVersion 3;
|
|
360
|
+
- 对 `validations`、`verificationTargets`、`integration`、`artifacts` 生成迁移前 evidence identity;
|
|
361
|
+
- 迁移只增加 schema/identity 元数据,迁移后 evidence identity 必须完全相同;
|
|
362
|
+
- 把 receipt 原子嵌入 `migrationHistory[]`,记录 original/target schema、before/after identity 与 `receiptId`;
|
|
363
|
+
- 版本超出支持窗口、仓库/ownership/diff 无法确认、或 evidence identity 漂移时不写文件,返回 `LEDGER_MIGRATION_REQUIRED` 与参数数组形式的 `rerecordCommand`。
|
|
364
|
+
|
|
365
|
+
submit/review/test/archive 只能通过 `harness_ledger.py` 读取/写入,禁止各自实现 schema 猜测或手工改 ledger。
|
|
@@ -195,3 +195,24 @@ Windows 默认常为 Windows PowerShell **5.1**。下列特性在 5.1 不可用
|
|
|
195
195
|
|
|
196
196
|
- 非 ASCII 路径(含中文)仓库:git/构建/文件操作一律 PowerShell;Bash 被 hook 拒绝(如 `Denied: non-ASCII path`)后**立即**改用 PowerShell 重发等价命令,禁止原样重试 Bash。
|
|
197
197
|
- Maven `-D` 参数在 PowerShell 中加引号:`"-Dmaven.test.skip=true"`。
|
|
198
|
+
|
|
199
|
+
## 13. PS5/PS7 原生参数合同
|
|
200
|
+
|
|
201
|
+
复杂 JSON、Docker Go template、here-string 内容及多层引号不得作为 native process 的内联参数跨 `Bash → powershell -Command → native executable` 传递。统一写 UTF-8 JSON 参数文件:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"schemaVersion": 1,
|
|
206
|
+
"transport": "utf8-json-argument-file",
|
|
207
|
+
"argv": ["python", "tool.py", "--template", "{{json .State}}"],
|
|
208
|
+
"powershell": {"edition": "Desktop", "version": "5.1"}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
执行入口:
|
|
213
|
+
|
|
214
|
+
```powershell
|
|
215
|
+
python harness/scripts/harness_test_runner.py exec --argv-file <file> --runtime-receipt <receipt>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Runner 直接把 `argv[]` 传给 native process(`shell=False`),不重新拼接或解析命令文本。PowerShell Desktop 5.1 与 Core 7 使用同一参数文件必须产生相同 argv。运行回执记录 edition/version、参数数量和 argv SHA-256,不写原始参数,避免凭证或模板内容泄漏。
|
|
@@ -4,6 +4,17 @@ description: harness .harness 状态目录分层协议。用于减少根目录
|
|
|
4
4
|
|
|
5
5
|
# State Layout Protocol
|
|
6
6
|
|
|
7
|
+
## 升级与本地状态保护边界
|
|
8
|
+
|
|
9
|
+
`.harness/archive/`、`.harness/changes/`、`.harness/knowledge/project-local/` 是 protected local roots。CLI init/configure/refresh/rules 操作前必须:
|
|
10
|
+
|
|
11
|
+
1. 综合 project marker、adapter `.harness-build.json`、managed block、恢复事务和非空 `.harness` 判断 `absent / valid / partial / recovery-required`;
|
|
12
|
+
2. 对 protected roots 记录文件数、目录数、字节数、Merkle root,以及 archive 首末 identity;
|
|
13
|
+
3. 事务 journal 声明每个允许修改的路径;任何未声明的 protected-root mutation 立即回滚;
|
|
14
|
+
4. partial 或 recovery-required 状态 fail closed,输出 sentinels、inventory 与恢复指引,禁止当成空项目自动 init。
|
|
15
|
+
|
|
16
|
+
事务提交前后 protected inventory 必须一致;除非当前命令显式以该 protected root 为操作目标。删除 `project.yaml` 但保留 archive,或删除 `.harness` 但保留 adapter marker,均属于 partial state,不是首次安装。
|
|
17
|
+
|
|
7
18
|
## 目标
|
|
8
19
|
|
|
9
20
|
`.harness/changes/<change-name>/` 是变更状态真相源,但根目录不得继续堆放所有文件。新产物按子目录分层;旧路径保留读取兼容。
|