@mstar-harness/opencode 2.4.0 → 3.0.1

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 (61) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +1 -1
  3. package/dist/mstar.js +4532 -227
  4. package/harness-agents/code-reviewer.md +0 -8
  5. package/harness-skills/mstar-branch-worktree/SKILL.md +14 -14
  6. package/harness-skills/mstar-branch-worktree/references/parallel-writable-pre-dispatch.md +2 -2
  7. package/harness-skills/mstar-compound/SKILL.md +2 -2
  8. package/harness-skills/mstar-compound/references/compound-workflow.md +3 -3
  9. package/harness-skills/mstar-compound-refresh/SKILL.md +4 -4
  10. package/harness-skills/mstar-compound-refresh/references/project-knowledge-bootstrap.md +1 -1
  11. package/harness-skills/mstar-dispatch-gates/SKILL.md +2 -2
  12. package/harness-skills/mstar-engine-legacy/SKILL.md +53 -0
  13. package/harness-skills/mstar-engine-legacy/references/anti-recursion-checklists.md +58 -0
  14. package/harness-skills/mstar-engine-legacy/references/engine-check-boilerplate.md +26 -0
  15. package/harness-skills/mstar-engine-legacy/references/lease-protocol.md +92 -0
  16. package/harness-skills/mstar-engine-legacy/references/qc-seat-n-restatements.md +57 -0
  17. package/harness-skills/mstar-engine-legacy/references/status-field-history.md +186 -0
  18. package/harness-skills/mstar-harness-core/SKILL.md +6 -3
  19. package/harness-skills/mstar-host/references/_shared/plan-mode-bridge-core.md +8 -8
  20. package/harness-skills/mstar-host/references/codex.md +1 -1
  21. package/harness-skills/mstar-host/references/cursor-plan-mode-bridge.md +19 -8
  22. package/harness-skills/mstar-host/references/cursor.md +5 -5
  23. package/harness-skills/mstar-host/references/dsh.md +10 -7
  24. package/harness-skills/mstar-host/references/kimi-plan-mode-bridge.md +3 -3
  25. package/harness-skills/mstar-host/references/kimi.md +1 -1
  26. package/harness-skills/mstar-host/references/omp-plan-mode-bridge.md +2 -2
  27. package/harness-skills/mstar-host/references/omp.md +2 -2
  28. package/harness-skills/mstar-host/references/zcode-plan-mode-bridge.md +3 -3
  29. package/harness-skills/mstar-host/references/zcode.md +1 -1
  30. package/harness-skills/mstar-iteration/SKILL.md +38 -37
  31. package/harness-skills/mstar-iteration/references/autonomous-direction-lock.md +2 -2
  32. package/harness-skills/mstar-iteration/references/iteration-compass-template.md +3 -3
  33. package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +50 -38
  34. package/harness-skills/mstar-iteration/references/phase-3-iteration-close.md +7 -7
  35. package/harness-skills/mstar-iteration/references/phase-4-5-pr-delivery.md +2 -2
  36. package/harness-skills/mstar-phase-gates/SKILL.md +3 -3
  37. package/harness-skills/mstar-plan-artifacts/SKILL.md +21 -23
  38. package/harness-skills/mstar-plan-artifacts/references/knowledge-and-designs.md +6 -6
  39. package/harness-skills/mstar-plan-artifacts/references/plan-files-and-reports.md +10 -10
  40. package/harness-skills/mstar-plan-artifacts/references/status-and-residuals.md +190 -309
  41. package/harness-skills/mstar-plan-artifacts/templates/README.md +1 -3
  42. package/harness-skills/mstar-plan-artifacts/templates/status.empty.json +2 -4
  43. package/harness-skills/mstar-plan-conventions/SKILL.md +53 -13
  44. package/harness-skills/mstar-plan-conventions/references/artifact-storage-paths.md +6 -3
  45. package/harness-skills/mstar-plan-conventions/references/harness-bootstrap-and-agents-layering.md +9 -10
  46. package/harness-skills/mstar-project-governance/SKILL.md +118 -0
  47. package/harness-skills/mstar-review-qc/SKILL.md +3 -3
  48. package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +1 -1
  49. package/harness-skills/mstar-roles/references/project-manager/plan-management.md +6 -8
  50. package/harness-skills/mstar-roles/references/project-manager/qc-and-residuals.md +6 -6
  51. package/harness-skills/mstar-roles/references/project-manager.md +7 -7
  52. package/harness-skills/mstar-roles/references/qc-specialist/deep-review-lenses.md +1 -1
  53. package/harness-skills/mstar-roles/references/qc-specialist/report-template.md +1 -1
  54. package/harness-skills/mstar-roles/references/qc-specialist/reviewer-workflow.md +1 -1
  55. package/harness-skills/mstar-roles/references/qc-specialist-shared.md +2 -2
  56. package/harness-skills/mstar-sdd/SKILL.md +2 -2
  57. package/harness-skills/mstar-sdd/references/file-handoffs.md +1 -1
  58. package/package.json +1 -1
  59. package/harness-skills/mstar-plan-artifacts/references/done-compaction.md +0 -88
  60. package/harness-skills/mstar-plan-artifacts/templates/notes.empty.json +0 -5
  61. package/harness-skills/mstar-plan-artifacts/templates/plans-done.empty.json +0 -3
@@ -1,21 +1,55 @@
1
- # `{HARNESS_DIR}/status.json` and Residual Findings (Morning Star)
1
+ # `{HARNESS_DIR}/status.json` (v2), Workflow Snapshots and Project Registers (Morning Star)
2
2
 
3
3
  > **Load order (same as other `mstar-*` skills):** Before changing SSOT / residual fields using this reference, Read **`mstar-harness-core`** (SKILL.md; same-repo branches and worktrees → **`mstar-branch-worktree`**). On conflict, **`mstar-harness-core` wins**; skill index in that SKILL.md.
4
4
 
5
- `status.json` lives at **`{HARNESS_DIR}/status.json`**. It is the **single source of truth (SSOT)** for **`plans[]` row status** and **open residual findings**.
6
- Canonical vs legacy residual definitions → **`mstar-plan-artifacts` SKILL.md** (“`status.json` and open residual (summary)”); this file covers **fields, severity, lifecycle, archive, and `jq` examples**.
7
- **Closed** residuals should not accumulate here long-term; authoritative archive → **`{HARNESS_DIR}/archived/residuals/<plan-id>.json`** (see “Residual findings lifecycle”).
5
+ v3 布局把 v1 的「单文件 `status.json`(根 `plans[]` + 根级 `residual_findings` + `metadata`)」拆成三层。**只使用 v2 地址;v1 地址(根 `plans[]` / 根级 `residual_findings` / `archived/residuals/`)由 `mstar migrate` 一次性迁移,不再读写**。v1 字段形状/历史全文(v1 行表、v1 `metadata` 表、jq/flock 读路径示例)→ **`mstar-engine-legacy`** `references/status-field-history.md`(engine-absent 历史 + fallback);本文件只保留 v2 地址与一次性 legacy 只读警告。
8
6
 
9
- **Why this matters:** Within a working copy, the open list in `status.json` and `archived/residuals/` are the **local session SSOT** for risk and decisions. Non-blocking conclusions that stay only in chat or a gitignored review bundle **without local SSOT update** cannot be inherited reliably in that session; `Done` drifts from visible known debt. **`@project-manager`** should register trackable open items soon after review closure; close/archive after verification per **`QA gate`** (`qa-engineer` when `mandatory`, else PM acceptance checklist).
7
+ - **根 `{HARNESS_DIR}/status.json`(v2)** 活跃生命周期登记:`{ "version": 2, "updated_at", "workflows": [...] }`。只登记 **active**(`running` / `paused`)lifecycle;terminal 时先写 snapshot 再从根列表移除(removal-at-terminal)。由 engine `validateStatus`(v2)/ `registerWorkflow` / `unregisterWorkflow` 读写。
8
+ - **`{WORKFLOW_DIR}/<id>/snapshot.json`** — 每 lifecycle 的运行态快照(`schema_version: 1`):**`plans[]` 行(legacy PlanRow 形状逐字保留)**、per-row **`execution_lease`**、顶层 **`integration_merge_lease`** / **`execution_policy`** / **`branch` anchors** / **`control_worktree_path`** / `compass_ref`。`<id>` = plan id 或 iteration id。
9
+ - **`{PROJECT_DIR}/<id>/roadmap.md` + `residuals.json`** — 项目层:roadmap frontmatter(machine-checkable)+ residual **register**(`entries[<plan-id>]` 数组;severity 枚举与 lifecycle 语义**逐字保留**)。无项目的流程回落到 `_default` 项目。
10
10
 
11
- **Cross-clone handoff** (default git policy): tracked `{HARNESS_DIR}/AGENTS.md`, `{KNOWLEDGE_DIR}/**`, `{SPECS_DIR}/**`, and root `CONCEPTS.md` / `STRATEGY.md` when used. Residuals that must survive clone must be **promoted** (compound) or written into those tracked results — do not treat `status.json` / `plans/` as the default clone handoff surface.
11
+ `status.json`(根)、workflow snapshot project register 都是 **SSOT**:plan 行状态与 lease snapshot,open residual register。
12
+ Canonical vs legacy residual definitions → **`mstar-plan-artifacts` SKILL.md**("`status.json`, workflow snapshots, and open residual (summary)");本文件 covers **fields, severity, lifecycle, v2 地址与 engine-check 命令**。
13
+ **Closed** residuals close **in place** in the register(`lifecycle` / `closed_at` / `closure_note`)— v1 的 `archived/residuals/<plan-id>.json` 归档路径与 `archive-residuals` 已移除(`mstar status archive-residuals` 在 v3 仅报错并指向 register 状态变更)。
14
+
15
+ **Why this matters:** Within a working copy, the workflow snapshot and project registers are the **local session SSOT** for risk and decisions. Non-blocking conclusions that stay only in chat or a gitignored review bundle **without local SSOT update** cannot be inherited reliably in that session; `Done` drifts from visible known debt. **`@project-manager`** should register trackable open items soon after review closure; close after verification per **`QA gate`** (`qa-engineer` when `mandatory`, else PM acceptance checklist).
16
+
17
+ **Cross-clone handoff** (default git policy): tracked `{HARNESS_DIR}/AGENTS.md`, `{KNOWLEDGE_DIR}/**`, `{SPECS_DIR}/**`, and root `CONCEPTS.md` / `STRATEGY.md` when used. Residuals that must survive clone must be **promoted** (compound) or written into those tracked results — do not treat `status.json` / `workflows/` / `projects/` / `plans/` as the default clone handoff surface.
12
18
 
13
19
  ## Basic structure
14
20
 
21
+ **Root `{HARNESS_DIR}/status.json` (v2)** — active lifecycle register:
22
+
23
+ ```json
24
+ {
25
+ "version": 2,
26
+ "updated_at": "YYYY-MM-DD",
27
+ "workflows": [
28
+ {
29
+ "id": "<plan-id-or-iteration-id>",
30
+ "type": "plan | iteration",
31
+ "started_at": "YYYY-MM-DD",
32
+ "dir": "workflows/<id>"
33
+ }
34
+ ]
35
+ }
36
+ ```
37
+
38
+ - `dir` is **harness-relative** (`workflows/<id>`), never absolute.
39
+ - Terminal writers unregister AFTER the snapshot write (removal-at-terminal): terminal snapshots are **not** listed in the root.
40
+
41
+ **`workflows/<id>/snapshot.json`** — lifecycle snapshot (`schema_version: 1`; engine `validateWorkflowSnapshot` / `writeWorkflowSnapshot`):
42
+
15
43
  ```json
16
44
  {
17
- "version": 1,
45
+ "schema_version": 1,
46
+ "id": "<plan-id-or-iteration-id>",
47
+ "type": "plan | iteration",
48
+ "status": "running | paused | completed | failed | stopped",
49
+ "started_at": "YYYY-MM-DD",
50
+ "ended_at": null,
18
51
  "updated_at": "YYYY-MM-DD",
52
+ "phase": "phase-2-execute",
19
53
  "plans": [
20
54
  {
21
55
  "id": "plan-id",
@@ -29,11 +63,34 @@ Canonical vs legacy residual definitions → **`mstar-plan-artifacts` SKILL.md**
29
63
  "created_at": "YYYY-MM-DD",
30
64
  "updated_at": "YYYY-MM-DD",
31
65
  "done_at": null,
32
- "notes": "",
33
- "metadata": {}
66
+ "notes": [],
67
+ "metadata": {},
68
+ "execution_lease": {}
34
69
  }
35
70
  ],
36
- "residual_findings": {
71
+ "execution_policy": {
72
+ "plan_parallelism": "serial",
73
+ "worktree_mode": "",
74
+ "push_policy": ""
75
+ },
76
+ "integration_merge_lease": {},
77
+ "branch": { "base": "", "integration": "", "target": "" },
78
+ "control_worktree_path": "/abs/repo/root",
79
+ "legacy_metadata": {},
80
+ "compass_ref": "iterations/<iteration-id>/delivery-compass.md"
81
+ }
82
+ ```
83
+
84
+ - `plans[]` rows are the **legacy PlanRow shape verbatim** (unknown row fields preserved, never re-bucketed). Per-row `execution_lease` stays on the row; `integration_merge_lease` is **top-level** (the v1 root-`metadata` home is gone).
85
+ - Terminal statuses (`completed` / `failed` / `stopped`) require `ended_at` and no dangling leases.
86
+ - `execution_policy` keys are copied from v1 root `metadata` at migrate; values are accepted-but-opaque this iteration (no semantic gate).
87
+ - `notes`: a plan row's `notes` array is the **legacy verbatim copy** preserved at migrate; the **runtime ledger is `notes.jsonl`** in the workflow dir (see `workflows/<id>/notes.jsonl` below). New notes append to the ledger only — never dual-write the row `notes`.
88
+
89
+ **`projects/<id>/residuals.json`** — project register (entries keyed by plan id, each an ARRAY):
90
+
91
+ ```json
92
+ {
93
+ "entries": {
37
94
  "plan-id": [
38
95
  {
39
96
  "id": "R1",
@@ -45,15 +102,42 @@ Canonical vs legacy residual definitions → **`mstar-plan-artifacts` SKILL.md**
45
102
  "owner": "@fullstack-dev",
46
103
  "target": "Before plan 02 / YYYY-MM-DD / milestone",
47
104
  "tracking": "Issue URL or null",
48
- "detail_doc": "{PLAN_DIR}/residuals/plan-id/R1-short-label.md"
105
+ "detail_doc": "{PLAN_DIR}/residuals/plan-id/R1-short-label.md",
106
+ "source_plan": "plan-id",
107
+ "registered_at": "YYYY-MM-DD",
108
+ "lifecycle_id": "<workflow id when owned by an iteration>"
49
109
  }
50
110
  ]
51
- },
52
- "metadata": {}
111
+ }
53
112
  }
54
113
  ```
55
114
 
56
- **Empty-repo templates:** **`templates/status.empty.json`**; optional **`templates/notes.empty.json`** `{HARNESS_DIR}/notes.json`. See **`templates/README.md`**.
115
+ - `entries[<plan-id>]` values are **arrays** v1 `residual_findings[plan-id]` multi-finding semantics preserved verbatim (a plan may hold 2+ open residuals).
116
+ - Register entries = the v1 residual entry **verbatim** + provenance: `source_plan` (must equal its entries key), `registered_at` (`YYYY-MM-DD`), optional `lifecycle_id` (owning workflow id when an iteration owns the plan).
117
+ - Project-less flows use the fallback **`_default`** project (`projects/_default/`).
118
+ - Register document validation delegates verbatim to `validateResidual` (severity enum + lifecycle states preserved at the new address).
119
+
120
+ **`projects/<id>/roadmap.md`** — roadmap frontmatter (engine `validateRoadmap`):
121
+
122
+ ```markdown
123
+ ---
124
+ project_id: <id>
125
+ title: <title>
126
+ status: active | paused | completed
127
+ created_at: YYYY-MM-DD
128
+ milestones: [ ... ] # optional
129
+ residuals_ref: residuals.json # optional
130
+ ---
131
+
132
+ # <title>
133
+
134
+ ## Direction
135
+ ...
136
+ ```
137
+
138
+ Body conventions (`## Direction` + goal items as `- [ ]` / `- [x]` markdown task-list items) are **warnings only** — never a hard gate.
139
+
140
+ **Empty-repo template:** **`templates/status.empty.json`** — the v2 shape (`version: 2`, `updated_at`, `workflows: []`). See **`templates/README.md`**.
57
141
 
58
142
  **Closed entries** add: `lifecycle`, `closed_at`, `closure_note`; optional `closure_evidence`, `superseded_by`. See “Residual findings lifecycle”.
59
143
 
@@ -61,7 +145,7 @@ Canonical vs legacy residual definitions → **`mstar-plan-artifacts` SKILL.md**
61
145
 
62
146
  ## Fail-loud handoff contract
63
147
 
64
- Findings must pass engine validation **before** registration into `residual_findings`: `validateResidual(entry)` per entry, `validateStatus(doc)` for the whole file (`mstar status validate` / engine import). Malformed entries — **non-object**, missing any of the nine required fields (`id`, `title`, `severity`, `source`, `scope`, `decision`, `owner`, `target`, `tracking` — mirroring engine `RESIDUAL_REQUIRED_FIELDS` in `packages/engine/src/status.ts`), or **severity** outside the enum — are **rejected** (`ok:false` + violation): fix and rewrite — never silent pass-through, downgrade-write, or “write then patch”.
148
+ Findings must pass engine validation **before** registration into the project register: `validateResidual(entry)` per entry, `validateProjectRegister(doc)` for the whole register, `validateWorkflowSnapshot(doc)` for the snapshot, `validateStatus` for the v2 root (`mstar status validate <path>` / engine import). Malformed entries — **non-object**, missing any of the nine required fields (`id`, `title`, `severity`, `source`, `scope`, `decision`, `owner`, `target`, `tracking` — mirroring engine `RESIDUAL_REQUIRED_FIELDS` in `packages/engine/src/status.ts`), or **severity** outside the enum — are **rejected** (`ok:false` + violation): fix and rewrite — never silent pass-through, downgrade-write, or “write then patch”.
65
149
 
66
150
  dsh-derived findings map their keys per the engine-residual validation verification spec §5; dsh keys never enter the schema.
67
151
 
@@ -69,7 +153,7 @@ dsh-derived findings map their keys per the engine-residual validation verificat
69
153
 
70
154
  ## Residual findings: `severity` (SSOT, machine field)
71
155
 
72
- Each `residual_findings[<plan-id>][]` entry’s **`severity`** must be from this enum (legacy read paths → **`jq` examples** at end). QC report Markdown **Critical / Warning / Suggestion** are **section titles** — **do not** copy them verbatim into JSON `severity`.
156
+ Each register entry (`projects/<id>/residuals.json` → `entries[<plan-id>][]`)’s **`severity`** must be from this enum. QC report Markdown **Critical / Warning / Suggestion** are **section titles** — **do not** copy them verbatim into JSON `severity`.
73
157
 
74
158
  ### 1. Allowed values
75
159
 
@@ -92,13 +176,13 @@ Only these five, **lowercase English**:
92
176
  | `high` | Not blocking but high impact (security, correctness, data, significant tech debt); fix, escalate, or open residual with PM follow-up. |
93
177
  | `medium` | Should address this or next milestone; may be open residual. |
94
178
  | `low` | Small impact, cheap fix; may be open residual. |
95
- | `nit` | Style, naming, wording, non-behavior doc nits; **lighter than `low`**. PM may omit from `residual_findings` if no tracking needed. |
179
+ | `nit` | Style, naming, wording, non-behavior doc nits; **lighter than `low`**. PM may omit from the register if no tracking needed. |
96
180
 
97
181
  Summary vs `mstar-review-qc`: unresolved **`critical`** → usually `Request Changes`; **`high`** often “fix or explicit decision before merge”; **`medium` / `low` / `nit`** may ship with residual tracking (final **Verdict** = PM consolidation).
98
182
 
99
183
  ### 4. QC report section → JSON `severity`
100
184
 
101
- When registering into root **`residual_findings`** (template in `mstar-review-qc`):
185
+ When registering into the project register (template in `mstar-review-qc`):
102
186
 
103
187
  | Report Findings section | JSON `severity` |
104
188
  | ----------------------- | --------------- |
@@ -116,14 +200,15 @@ In old JSON, **`"severity": "warning"`** is read and rolled up as **`low`**. **F
116
200
 
117
201
  ## Findings cleanup modes
118
202
 
119
- Plan-level policy for whether non-blocking QC/QA findings may remain as open residuals or must be cleared in the current plan session.
203
+ Plan-level policy for whether non-blocking QC/QA findings may remain as open residual entries or must be cleared in the current plan session.
120
204
 
121
- ### Assignment + metadata
205
+ ### Assignment (SSOT)
122
206
 
123
207
  | Surface | Values |
124
208
  | ------- | ------ |
125
209
  | Assignment **`Findings cleanup`** | `zero-residual` \| `allow-residual` |
126
- | `plans[].metadata.findings_cleanup` | same strings (optional mirror; Assignment wins when both set) |
210
+
211
+ The v1 `plans[].metadata.findings_cleanup` mirror is **deleted** in v3 — no dual-track. Assignment wins; the register is the only residual store.
127
212
 
128
213
  **Defaults**
129
214
 
@@ -141,23 +226,26 @@ Intent: clear findings in the current plan session whenever possible. Open resid
141
226
  3. **`nit`**: fix in-session **or** drop with no R# (existing “no tracking needed”); **never** open residual for style-only nits.
142
227
  4. **`Approve with residuals`** only when every remaining open item is a true blocker-defer (`decision: defer`, `target` = next iteration/milestone, Durable Roadmap Gate written).
143
228
  5. **True defer** only: external dependency; product/scope decision for a later iteration; or explicit **current-turn** user defer — plus Durable Roadmap Gate.
144
- 6. **`waived` / `risk-accepted`**: still require PM + user/architect alignment; **close/archive** (do not leave open). Prefer a cheap fix over waive-as-shortcut.
145
- 7. Plan **Done**: prefer empty `residual_findings[<plan_id>]`. If any open R# remain, **every** entry must be blocker-defer + roadmap; otherwise keep `InReview` / `Blocked`.
229
+ 6. **`waived` / `risk-accepted`**: still require PM + user/architect alignment; **close in the register** (do not leave open). Prefer a cheap fix over waive-as-shortcut.
230
+ 7. Plan **Done**: prefer an empty `entries[<plan_id>]` in the register. If any open entries remain, **every** one must be blocker-defer + roadmap; otherwise keep `InReview` / `Blocked`.
146
231
 
147
232
  ### `allow-residual` (legacy default)
148
233
 
149
- Non-blocking Warning/Suggestion may ship with open R# registration and `Approve with residuals` when no unresolved Critical remains (existing residual lifecycle unchanged).
234
+ Non-blocking Warning/Suggestion may ship with open register entries and `Approve with residuals` when no unresolved Critical remains (existing residual lifecycle unchanged).
235
+
236
+ > **Engine check (when available):** run `mstar status findings-cleanup <plan-id> [--project <id>] [--mode zero-residual|allow-residual]` (or import `findingsCleanupGate` from `@mstar-harness/engine` in a host hook) to enforce the mode above against the plan's register entries. On `fail` -> do not proceed; fix and re-run. Skill text below remains authoritative when the runtime is absent.
150
237
 
151
238
  ---
152
239
 
153
- ## `plans[].metadata` standard optional fields
240
+ ## Snapshot plan-row fields (`plans[].metadata` standard optional fields)
241
+
242
+ Snapshot plan rows keep the v1 PlanRow shape verbatim; the standard optional `metadata` keys below are unchanged from v1:
154
243
 
155
244
  | Key | Type | Purpose |
156
245
  | --- | --- | --- |
157
- | `findings_cleanup` | `zero-residual` \| `allow-residual` | Mirror of Assignment **`Findings cleanup`**; see **Findings cleanup modes** |
158
246
  | `working_branch` | string | Implementation branch; aligns with Assignment **`Working branch`** (SSOT) |
159
- | `spec_integration_branch` | string | (Multi-plan same **Spec**) integration branch name; created from root `metadata.iteration_base_branch`; plan branches merge here before final PR (`mstar-plan-conventions`) |
160
- | `merge_target` | string | Next merge target; multi-plan + Spec → usually `spec_integration_branch`; final PR target is root `metadata.target_branch` |
247
+ | `spec_integration_branch` | string | (Multi-plan same **Spec**) integration branch name; created from snapshot `branch.base` / `execution_policy` context; plan branches merge here before final PR (`mstar-plan-conventions`) |
248
+ | `merge_target` | string | Next merge target; multi-plan + Spec → usually `spec_integration_branch`; final PR target is snapshot `branch.target` |
161
249
  | `branch_policy` | string | One-line policy per `mstar-harness-core` |
162
250
  | `phase` | string | Program/roadmap label |
163
251
  | `priority` | `high` \| `medium` \| `low` | PM scheduling |
@@ -171,11 +259,12 @@ Non-blocking Warning/Suggestion may ship with open R# registration and `Approve
171
259
  | `primary_spec` | string | Main spec path (`{KNOWLEDGE_DIR}/…`, `{SPECS_DIR}/…`) |
172
260
  | `iteration_compass` | string | Optional `{ITERATION_DIR}/…` |
173
261
  | `iteration_refs` | string[] | Optional multiple compass paths |
174
- | `qc_status` / `tests` / `commits` | string | InReview/Done snapshots; not a substitute for durable plan gate summaries or root `residual_findings` |
262
+ | `knowledge_refs` | string[] | Optional knowledge-doc references (e.g. `{KNOWLEDGE_DIR}/…` paths or doc ids) linked from this plan; written by `mstar-compound` Phase 6 / `mstar-compound-refresh` Phase 4; v1 root `status.json` metadata references are legacy read-only |
263
+ | `qc_status` / `tests` / `commits` | string | InReview/Done snapshots; not a substitute for durable plan gate summaries or the project register |
175
264
  | `sdd_dir` | string | SDD scratch path, e.g. `{HARNESS_DIR}/sdd/<plan-id>/` (gitignored; `mstar-sdd`) |
176
265
  | `sdd_progress` | string | Optional pointer to `{SDD_DIR}/progress.md` ledger |
177
266
  | `review_bundle` | string | Optional pointer to `{SDD_DIR}/review/` for current ephemeral QC/QA evidence |
178
- | `task_commits` | array\<object\> | SDD recovery: `{ "task_id": "T1", "base": "<sha>", "head": "<sha>" }` per completed task |
267
+ | `task_commits` | array\<object\> | SDD recovery: `{ "task_id": "T1", "base": "<sha>", "head": "<sha>" }` per completed task — recorded on the snapshot plan row |
179
268
 
180
269
  ### `plans[].execution_lease` (iteration Phase 2)
181
270
 
@@ -185,223 +274,72 @@ Optional when a plan is not owned; **required** while a Phase 2 session owns wri
185
274
  | --- | --- | --- | --- |
186
275
  | `holder` | non-empty string | Yes | Opaque cooperative owner identity (recommended `<host>:<stable-session-id>`, e.g. `cursor:bc-1234`). Stable for claim lifetime; **no credentials**; used for ownership comparison — not `session_label`. |
187
276
  | `claimed_at` | RFC 3339 UTC (`Z`) | Yes | Acquisition time (audit only; **not** an expiry clock). |
188
- | `worktree_path` | absolute path string | Yes | Dedicated feature-worktree root; **MUST** differ from `metadata.control_worktree_path`. |
277
+ | `worktree_path` | absolute path string | Yes | Dedicated feature-worktree root; **MUST** differ from `control_worktree_path`. |
189
278
  | `working_branch` | non-empty string | Yes | Feature branch at `worktree_path`; MUST agree with Assignment **`Working branch`**. |
190
279
  | `session_label` | string | No | Human display only — **MUST NOT** authorize or compare ownership. |
191
280
 
192
281
  Writers **delete** `execution_lease` on release; `null` and tombstone objects are invalid.
193
282
 
194
- ### Optional delivery ledger (`phase` + `batches` + `verification`)
283
+ V1: **manual release only** — omit `expires_at`; readers **MUST NOT** treat unknown or draft `expires_at` as authority to steal or release.
195
284
 
196
- For multi-batch or multi-role plans:
285
+ ### Snapshot top-level fields
197
286
 
198
- | Key | Type | Purpose |
287
+ | Field | Type | Semantics |
199
288
  | --- | --- | --- |
200
- | `phase` | string | Delivery phase label |
201
- | `batches` | array\<object\> | Per-batch task coverage, owner, status, commits, self-audit |
202
- | `verification` | object | Command-level verification snapshot |
289
+ | `integration_merge_lease` | object | While one integration merge is owned; **absent** = unclaimed. Writers **delete** the key on release — never `null` or tombstones |
290
+ | `execution_policy` | object | `plan_parallelism` / `worktree_mode` / `push_policy` — first-class (copied from v1 root `metadata` at migrate; values accepted-but-opaque this iteration) |
291
+ | `branch` | object | Iteration branch anchors: `base` (from `iteration_base_branch`), `integration` (the `spec_integration_branch`), `target` (final PR target) |
292
+ | `control_worktree_path` | absolute path string | Iteration Phase 2: canonical **repository root** (not `{HARNESS_DIR}`) checked out to the `branch.integration` branch; coordination + serial merge cwd |
293
+ | `compass_ref` | string | Relative pointer to the iteration delivery compass |
294
+ | `legacy_metadata` | object | Catch-all for unmapped v1 root-`metadata` keys at migrate |
203
295
 
204
- Recommended `batches[]` subfields: `index`, `covers`, `status`, `owner`, `commits`, `a2_self_audit` (or synonym), `verification`.
205
-
206
- > `batches` / `verification` are evidence indexes — not replacements for durable plan gate summaries or root `residual_findings`.
207
-
208
- ### `plans[].notes` vs `{HARNESS_DIR}/notes.json`
209
-
210
- - `plans[].notes`: per-plan timeline (string array recommended).
211
- - `{HARNESS_DIR}/notes.json`: cross-plan program milestones.
212
-
213
- Legacy string `plans[].notes` is OK; new repos should use arrays with time + event + evidence anchor.
214
-
215
- ## Root `metadata` standard optional fields
216
-
217
- | Key | Type | Purpose |
218
- | --- | --- | --- |
219
- | `versioning` | object | Cross-plan conventions (team-defined) |
220
- | `iteration_base_branch` | string | Branch/ref used to create `spec_integration_branch`; required for formal iterations |
221
- | `target_branch` | string | Final PR target after iteration-close; required for formal iterations |
222
- | `notes` | array | **Legacy** — prefer **`{HARNESS_DIR}/notes.json`** |
223
- | `residual_findings_history` | object | **Legacy** — prefer **`archived/residuals/<plan-id>.json`** |
224
- | `tech_debt_summary` | object | Optional rollup over open R#; maintain via engine rollup (below) |
225
- | `control_worktree_path` | absolute path string | Iteration Phase 2: canonical **repository root** (not `{HARNESS_DIR}`) checked out to active `spec_integration_branch`; coordination + serial merge cwd |
226
- | `integration_merge_lease` | object | While one integration merge is owned; **absent** = unclaimed. Writers **delete** the key on release — never write `null` or tombstone objects |
296
+ ### Snapshot `notes` vs `{WORKFLOW_DIR}/<id>/notes.jsonl`
227
297
 
228
- **Formal iteration example** (root `metadata`; values are project-specific **do not** copy `main` by default):
229
-
230
- ```json
231
- "metadata": {
232
- "iteration_base_branch": "release/1.76",
233
- "target_branch": "release/1.77"
234
- }
235
- ```
236
-
237
- Plan row (per active iteration plan):
238
-
239
- ```json
240
- "metadata": {
241
- "spec_integration_branch": "iteration/v1.77-live-teels",
242
- "merge_target": "iteration/v1.77-live-teels",
243
- "iteration_refs": ["v1.77"]
244
- }
245
- ```
298
+ - `plans[].notes`: per-plan timeline **legacy verbatim copy** (read-only; preserved at migrate; never a dual-write target).
299
+ - `{WORKFLOW_DIR}/<id>/notes.jsonl`: **runtime notes ledger** — append-only; new notes go here only (`kind` + `ts` + `text` JSON lines; `mstar migrate` seeds it from v1 arrays).
246
300
 
247
301
  ---
248
302
 
249
303
  ## Iteration execution leases (Phase 2)
250
304
 
251
- Cooperative coordination through the **control worktree** copy of `{HARNESS_DIR}/status.json`. Not a distributed lock service — non-cooperating processes are out of scope. **Same-host** writers use an exclusive write lock (below) around lease mutations; **cross-plan parallel writable implement** is permitted only when that lock is available on the control path and held for every lease mutation (see hard gate below).
252
-
253
- **When fields apply:** iteration Phase 2 (after control worktree entry, or primary checkout when `Worktree mode: waived`). Control worktree + lease fields are waived only by explicit current-turn user instruction (`Worktree mode: waived` or equivalent). `Plan parallelism: serial` does **not** waive leases. **`Worktree mode: waived` does not waive the cross-plan parallel safety gate** (see hard gate below).
254
-
255
- **Path SSOT:** Default-gitignored process artifacts — `status.json`, `plans/`, `iterations/`, `sdd/`, `notes.json`, `archived/` — read/write via `<control_worktree_path>/{HARNESS_DIR}/…` (absolute). A feature worktree's same-looking `{HARNESS_DIR}` path is **not** the SSOT. Missing plans under a feature checkout (gitignore) is **not** grounds for `Worktree mode: waived` — keep feature worktrees and use control absolute **`Plan Path`** / **`SDD dir`**. Detail → **`mstar-branch-worktree`** 「Harness path SSOT under default gitignore」.
256
-
257
- ### Same-host exclusive write lock (control `status.json`)
305
+ Leases live in the **workflow snapshot** `{WORKFLOW_DIR}/<id>/snapshot.json` (`plans[].execution_lease` per row; `integration_merge_lease` top-level). Coordination happens through the **control worktree** copy of that file. This is cooperative, not a distributed lock service non-cooperating processes are out of scope.
258
306
 
259
- Lease mutations on the **control** copy of `{HARNESS_DIR}/status.json` execution claim/release/transfer, plan-status transitions that touch leases, and `integration_merge_lease` claim/release **MUST** run inside a **same-host exclusive write lock** for the full read-check-replace-verify sequence.
260
-
261
- **Preferred (same machine, shared filesystem):** advisory lock on `{HARNESS_DIR}/.status-write.lock` via `flock` (or equivalent). Hold from first read through post-write verify; release on all exit paths (success or failure).
262
-
263
- ```bash
264
- CONTROL_ROOT="<metadata.control_worktree_path>"
265
- HARNESS=".harness" # or resolved {HARNESS_DIR}
266
- STATUS="$CONTROL_ROOT/$HARNESS/status.json"
267
- LOCK="$CONTROL_ROOT/$HARNESS/.status-write.lock"
268
- (
269
- flock -x 9 || exit 1
270
- # read → mutate → temp file + atomic replace → re-read verify
271
- ) 9>"$LOCK"
272
- ```
307
+ **When fields apply:** iteration Phase 2 (after control worktree entry, or primary checkout when `Worktree mode: waived`). Control worktree + lease fields are waived only by explicit current-turn user instruction (`Worktree mode: waived` or equivalent). `Plan parallelism: serial` does **not** waive leases. **`Worktree mode: waived` does not waive the cross-plan parallel safety gate.**
273
308
 
274
- **Alternative when `flock` unavailable:** atomic `mkdir` on `{HARNESS_DIR}/.status-write.lockdir/` success acquires; existing dir **Blocked** (another writer holds the lock); remove the directory only after successful verify or explicit rollback.
309
+ **Path SSOT:** Default-gitignored process artifacts — `status.json`, `workflows/`, `projects/`, `plans/`, `iterations/`, `sdd/` read/write via `<control_worktree_path>/{HARNESS_DIR}/…` (absolute). A feature worktree's same-looking `{HARNESS_DIR}` path is **not** the SSOT. Missing plans under a feature checkout (gitignore) is **not** grounds for `Worktree mode: waived` keep feature worktrees and use control absolute **`Plan Path`** / **`SDD dir`**. Detail → **`mstar-branch-worktree`** 「Harness path SSOT under default gitignore」.
275
310
 
276
- **Hard gate cross-plan parallel writable implement:** Applies **whether or not** `Worktree mode: waived`. Lease-gated **cross-plan parallel** writable implement (when lease gate active) is allowed **only when** a same-host exclusive write lock is **available on the coordination `status.json` filesystem and held for every status/coordination mutation** in that Phase 2 session (execution claim/release/transfer, plan-status transitions, `integration_merge_lease` claim/release when lease gate active). When waived, the coordination path is primary checkout `{HARNESS_DIR}/status.json` the same lock discipline applies to any shared status mutation before parallel writable dispatch. If agents span hosts or the coordination path has **no shared flock/lockdir** (distinct machines, non-shared mount), **default `Plan parallelism: serial`** for cross-plan implement scheduling one plan writable wave at a time (**preferred default when waived**). If Assignment still claims cross-plan parallel implement without same-host lock availability → **Blocked** until PM aligns Assignment (`Plan parallelism: serial`) or the user supplies the override below. **`Worktree mode: waived` alone is not** the cross-host parallel override. v1 does **not** add a distributed CAS CLI.
311
+ **Protocol home (single canonical copy):** the full lease protocol prose same-host exclusive write lock, hard gate, claim-before-`InProgress`, hold/release/override, integration merge protocol, orphan recovery, lease prohibitions lives in **`mstar-engine-legacy`** `references/lease-protocol.md` (engine-absent fallback). The Phase 2 iteration-command **execution checklist** **`mstar-iteration`** `references/phase-2-worktree-lease.md`. This file carries the **field semantics** only (tables below + the lockdir location summary).
277
312
 
278
- **Exception documented cross-host residual:** Explicit **current-turn** user instruction such as `Cross-host lease race: accepted` (or equally unambiguous equivalent) **plus** audit entry on affected `plans[].notes` (timestamp, hosts/sessions involved, residual race risk acknowledged) permits cooperative multi-host cross-plan parallel with documented residual risk.
313
+ **Same-host exclusive write lock (snapshot / root):** all control-path lease mutations (execution claim/release/transfer, plan-status transitions that touch leases, `integration_merge_lease` claim/release) **MUST** run inside a same-host exclusive write lock for the full read-check-replace-verify sequence. Engine writers handle this automatically (`writeWorkflowSnapshot` / `registerWorkflow` acquire `<status-file dir>/.status-write.lockdir/` next to the file — for snapshots the lockdir lands inside `workflows/<id>/`). Prefer the engine-check commands below over hand-rolled `flock` snippets; the atomic-mkdir alternative (`.status-write.lockdir/` in the same directory as the file) remains the documented fallback when no engine writer exists. Hard gate, cross-host exception and pre-dispatch re-verify → `mstar-engine-legacy/references/lease-protocol.md`.
279
314
 
280
- **Pre-dispatch re-verify:** Immediately before **any** writable implement dispatch, reread control `status.json` and confirm this session still passes verify-held-lease (`holder`, `worktree_path`, `working_branch` match Assignment). Mismatch or absent lease **STOP** do not dispatch.
315
+ > **Engine check (when available):** run `mstar lease verify --workflow <id> [--plan <plan-id>]` or `mstar lease verify-integration --workflow <id>` (or import `validateExecutionLease` / `validateIntegrationMergeLease` from `@mstar-harness/engine` in a host hook) to validate the leases above on the workflow snapshot. On `fail` -> do not proceed; fix and re-run. Skill text below remains authoritative when the runtime is absent.
281
316
 
282
- ### Root `metadata.integration_merge_lease` (v1)
317
+ ### `integration_merge_lease` (snapshot top-level)
283
318
 
284
- Single global lease authorizing one plan feature branch integration into `spec_integration_branch`.
319
+ Single global lease authorizing one plan feature branch integration into `branch.integration` (the `spec_integration_branch`).
285
320
 
286
321
  | Field | Type | Required | Semantics |
287
322
  | --- | --- | --- | --- |
288
323
  | `holder` | non-empty string | Yes | Same format and comparison rules as `execution_lease.holder`. |
289
324
  | `claimed_at` | RFC 3339 UTC (`Z`) | Yes | Acquisition time (audit only). |
290
- | `plan_id` | non-empty string | Yes | `plans[].id` (or legacy `plan_id`) of the feature being integrated. |
325
+ | `plan_id` | non-empty string | Yes | `plans[].id` of the feature being integrated. |
291
326
  | `source_branch` | non-empty string | Yes | Plan feature branch to integrate. |
292
327
  | `target_branch` | non-empty string | Yes | Resolved `spec_integration_branch` — no other target is valid. |
293
328
  | `session_label` | string | No | Display only. |
294
329
 
295
- Example fragments:
296
-
297
- ```json
298
- {
299
- "metadata": {
300
- "control_worktree_path": "/repo",
301
- "integration_merge_lease": {
302
- "holder": "cursor:bc-1234",
303
- "claimed_at": "2026-07-22T04:00:00Z",
304
- "plan_id": "plan-a",
305
- "source_branch": "feature/plan-a",
306
- "target_branch": "iteration/2026-07",
307
- "session_label": "Integrate plan A"
308
- }
309
- },
310
- "plans": [
311
- {
312
- "id": "plan-a",
313
- "status": "InProgress",
314
- "execution_lease": {
315
- "holder": "cursor:bc-1234",
316
- "claimed_at": "2026-07-22T02:30:00Z",
317
- "worktree_path": "/repo-worktrees/plan-a",
318
- "working_branch": "feature/plan-a",
319
- "session_label": "Plan A implementation"
320
- },
321
- "metadata": {
322
- "spec_integration_branch": "iteration/2026-07",
323
- "merge_target": "iteration/2026-07"
324
- }
325
- }
326
- ]
327
- }
328
- ```
329
-
330
- ### Claim-before-`InProgress` (execution lease)
331
-
332
- A Phase 2 session **MUST** claim **before** moving a plan from `Todo` or `Blocked` to `InProgress` and **before** any writable dispatch for that plan:
333
-
334
- 1. Reread the control copy of `status.json`; locate exactly one plan row (`id` or `plan_id` read compatibility).
335
- 2. **Resume (not steal):** if `execution_lease` exists and `holder` **equals this session** → verify-held-lease: confirm `worktree_path` and `working_branch` match the Assignment; continue (this is **not** Blocked and **not** a new claim).
336
- 3. **Blocked:** if `execution_lease` exists and `holder` **differs** → stop. No timestamp, TTL, or inactivity makes it stealable.
337
- 4. **Orphan:** if `status` is `InProgress` but `execution_lease` is absent → **STOP** (see “Orphan recovery” below). Do not writable-dispatch or invent a lease.
338
- 5. Create or verify the dedicated feature worktree and branch (`worktree_path` ≠ `control_worktree_path`).
339
- 6. Acquire same-host write lock (see above); reread `status.json`; if row, status, or lease state changed, restart from step 1.
340
- 7. In **one complete-file update** (under lock), set `status: "InProgress"` and write the full `execution_lease` object. Use a temp file in the same directory and atomically replace `status.json`.
341
- 8. Reread the stored row; verify `holder`, `worktree_path`, and `working_branch` exactly match the attempted claim. Writable dispatch is forbidden until verification succeeds.
342
-
343
- V1: **manual release only** — omit `expires_at`; readers **MUST NOT** treat unknown or draft `expires_at` as authority to steal or release.
344
-
345
- ### Hold, release, and override
346
-
347
- - Lease remains active across `InProgress` and `InReview` (including review fix rounds) unless deliberately released or transferred.
348
- - **Release:** reread control `status.json`; stored `holder` must match this session (mismatch → **Blocked**, not permission to delete). Delete `execution_lease` in the same complete-file update — never `null`.
349
- - Voluntary abandonment: may set `status: "Blocked"` and delete the lease in one update.
350
- - **`Done` authority** deletes any `execution_lease` in the **same** complete-file update as `status: "Done"` — **only after** successful integration merge into `spec_integration_branch` when Phase 2 lease gate is not waived (see “Integration merge protocol” and `mstar-iteration` §2.4). After QC/QA pass, plan stays **`InReview`** with lease retained until merge succeeds.
351
- - Temporary blockage may retain the lease when the same holder remains responsible and the plan record explains the next action.
352
- - **Override (only exception to no-steal):** explicit **user instruction in the current turn** may remove or replace another holder's lease. Append an audit entry to `plans[].notes` with timestamp, prior holder, new holder (or release), and that the user authorized override. Agents **MUST NOT** infer override from age, inactivity, `Blocked` status, or a failed session.
353
- - Cooperative handoff: current holder explicitly agrees; receiving worktree/branch verified; one complete-file update — otherwise old holder releases and new holder follows normal claim.
354
-
355
- ### Integration merge protocol
356
-
357
- Feature implementation may run in parallel across plan IDs **only when** the cross-plan parallel hard gate above is satisfied (same-host lock on coordination `status.json`, default **`Plan parallelism: serial`**, or current-turn `Cross-host lease race: accepted` + audit `plans[].notes` — **not** by `Worktree mode: waived` alone); when lease gate is active, each plan also needs a verified `execution_lease` and distinct feature worktree. Mutations of `spec_integration_branch` are **serial**. Plan status after QC/QA is **`InReview`** with `execution_lease` retained until merge succeeds (when lease gate active); **`Done`** + lease deletion happen **after** the integration merge commit is recorded.
358
-
359
- 1. From `control_worktree_path`: clean working tree; checked-out branch = resolved `spec_integration_branch`.
360
- 2. Reread root `metadata` under the same-host write lock (above). If `integration_merge_lease` exists:
361
- - **Resume (not steal):** `holder` **equals this session** → verify-held-merge-lease: confirm `plan_id`, `source_branch`, and `target_branch` match the intended merge; confirm control worktree state (clean or documented in-progress resolution); continue (this is **not** Blocked).
362
- - **Blocked:** `holder` **differs** → stop. No timestamp, TTL, or inactivity makes it stealable.
363
- 3. If unclaimed, claim merge lease with the same read-check-replace-verify discipline as execution claims. `source_branch` and `plan_id` must match the feature; `target_branch` must match `spec_integration_branch`.
364
- 4. Only the stored merge-lease `holder` runs integration from `control_worktree_path`.
365
- 5. On success: record merge commit/evidence per plan/status conventions; **delete** `integration_merge_lease`; in the **same** locked update set plan `status: "Done"` and **delete** `execution_lease`.
366
- 6. On conflict/failure: retain both leases; plan stays **`InReview`** — do **not** set `Done`. Release merge lease only after control worktree is clean and in a known state.
367
-
368
- Execution and merge leases may coexist; merge lease does not grant execution ownership for the source plan.
369
-
370
- ### Orphan recovery (`InProgress` without `execution_lease`)
371
-
372
- Runtime skills that detect this state (e.g. `mstar-iteration`) **STOP** and defer recovery here — they **MUST NOT** silently add a lease or writable-dispatch.
373
-
374
- **Immediate gate:** no writable dispatch until recovery completes and a verified `execution_lease` exists (or plan is returned to a non-active status).
375
-
376
- **Resolver:** `@project-manager` (or explicit human/PM ownership resolution after race or corruption).
377
-
378
- | Path | When | Actions |
379
- | ---- | ---- | ------- |
380
- | **Reset to `Todo`** | Work abandoned, unknown owner, or safe to restart claim | One complete-file update under write lock: `status: "Todo"`; ensure `execution_lease` absent; append `plans[].notes` audit (timestamp, reason, actor). |
381
- | **Recover with claim (same holder)** | Legitimate in-progress work; feature worktree/branch verified on disk; **this session's stable `holder`** matches the prior owner | Unattended recovery permitted **only** for the **same** stable `holder`. Follow claim-before-`InProgress` from step 5 under write lock; append `plans[].notes` audit (orphan recovery, same `holder`, paths verified). |
382
- | **Recover with claim (different holder)** | New session must take over live work | **Blocked** for unattended recovery. Requires **verified quiescence** of the prior writer (no live writable work on the feature branch/worktree) **and** explicit cooperative handoff from the prior holder, **or** **current-turn user override** + audit `notes` (prior holder, new holder, user authorized). Then normal claim under write lock. |
383
- | **Escalate / `Blocked`** | Ambiguous ownership, conflicting worktrees, or partial/corrupt `status.json` | Set `status: "Blocked"` with `metadata.blocked_reason`; do **not** writable-dispatch until human/PM resolves. Restore coherent `status.json` from latest complete state if needed. |
384
-
385
- After any recovery path, the next session must pass verify-held-lease before writable dispatch.
386
-
387
- ### Agent prohibitions (lease SSOT)
330
+ ### Claim-before-`InProgress`, hold/release/override, integration merge, orphan recovery, prohibitions
388
331
 
389
- - **MUST NOT** steal or overwrite an active `execution_lease` or `integration_merge_lease` (no TTL, age, or inactivity authority in v1).
390
- - **MUST NOT** writable-dispatch without a verified `execution_lease` for that plan (resume counts only when same `holder` passes verify-held-lease).
391
- - **MUST NOT** write `null` or tombstone objects for lease keys — **delete** the key on release.
392
- - **PM NEVER** steal an active lease without explicit current-turn user override + audit `notes` (full list → `mstar-roles/references/project-manager.md` § PM-Specific NEVER Rules).
393
-
394
- Preservation: writers **MUST** preserve unrelated plan rows, root metadata, and `residual_findings` on every lease mutation.
332
+ These are **full-protocol prose** — the single canonical copy lives in **`mstar-engine-legacy`** `references/lease-protocol.md` (engine-absent fallback); the Phase 2 iteration-command **execution checklist** is **`mstar-iteration`** `references/phase-2-worktree-lease.md`. This file carries the field semantics (tables above) and the engine checks only — do not re-state the protocol here. `V1: manual release only` — omit `expires_at`; readers **MUST NOT** treat unknown or draft `expires_at` as authority to steal or release (see the `execution_lease` field table).
395
333
 
396
334
  ---
397
335
 
398
336
  ## General constraints
399
337
 
400
- - Each `plans[]` row may include optional **`metadata`** (`{}` or omit).
401
- - Init with `"residual_findings": {}`; **no dual-write** with legacy side (see SKILL.md). Program timeline **`notes.json`**, not long `metadata.notes` in `status.json`.
402
- - **`plans[].id`** keys must align with root **`residual_findings`** keys and `{SDD_DIR}` plan-id segments. Do not store `residual_findings_plan_id`.
403
- - **Empty `plan-id` key:** when no open items remain, **delete** the key from root **`residual_findings`** (and legacy side if present) — no `"plan-id": []`. Whether **`plans[]`** keeps the row is separate (`done-compaction.md`).
404
- - **`residual_summary` (optional):** one-line human summary of **open** items only.
338
+ - Each snapshot `plans[]` row may include optional **`metadata`** (`{}` or omit).
339
+ - A workflow root entry is **active only** (`running` | `paused`); terminal writers unregister the root entry after the snapshot write (removal-at-terminal).
340
+ - **`plans[].id`** keys must align with register `entries` keys and `{SDD_DIR}` plan-id segments. Do not store `residual_findings_plan_id`.
341
+ - **Empty `plan-id` key:** when no open entries remain, **delete** the key from the register (`entries`) — no `"plan-id": []`.
342
+ - **`residual_summary` (optional):** one-line human summary of **open** entries only.
405
343
 
406
344
  ---
407
345
 
@@ -424,156 +362,99 @@ Preservation: writers **MUST** preserve unrelated plan rows, root metadata, and
424
362
  | Action | Owner | When |
425
363
  | ------ | ----- | ---- |
426
364
  | Implement fix | `@fullstack-dev` / assignee | Completion Report cites R# + evidence |
427
- | Verify | `@qa-engineer` when **`QA gate: mandatory`**; else PM per acceptance checklist | Regression / acceptance; open R# close requires verify before archive |
428
- | Write `status.json` | **`@project-manager`** or **`@qa-engineer`** | After verification; waivers after PM + user/architect alignment |
365
+ | Verify | `@qa-engineer` when **`QA gate: mandatory`**; else PM per acceptance checklist | Regression / acceptance; open R# close requires verify before close |
366
+ | Write the register | **`@project-manager`** or **`@qa-engineer`** | After verification; waivers after PM + user/architect alignment |
429
367
 
430
368
  Do not claim “R3 fixed” in chat/plan only without SSOT update.
431
369
 
432
370
  PM should register open items after **`Approve with residuals`**; QA should state each related R# (open / resolved this round / needs waiver).
433
371
 
434
- ### Recommended: archive to `archived/residuals/<plan-id>.json`
372
+ ### Close in place (the only close path)
435
373
 
436
374
  After **`closed_at`**, **`closure_note`**, and PM/QA confirm close:
437
375
 
438
- 1. **Append** to **`{HARNESS_DIR}/archived/residuals/<plan-id>.json`**.
439
- 2. **Remove** from open list (root **`residual_findings[<plan-id>]`**; legacy side if used). Delete empty **`plan-id`** keys.
440
- 3. Update root **`updated_at`**; optional milestone in **`notes.json`**.
441
-
442
- Archive file shape (append to `entries`):
443
-
444
- ```json
445
- {
446
- "plan_id": "01-data-infrastructure",
447
- "schema_version": 1,
448
- "entries": [
449
- {
450
- "id": "R1",
451
- "severity": "medium",
452
- "lifecycle": "resolved",
453
- "closed_at": "2026-04-06",
454
- "closure_note": "…",
455
- "closure_evidence": "PR #42 / commit …",
456
- "archived_at": "2026-04-07"
457
- }
458
- ]
459
- }
460
- ```
376
+ 1. Set `lifecycle` / `closed_at` / `closure_note` on the entry **in place** in the register (`projects/<id>/residuals.json` → `entries[<plan-id>]`).
377
+ 2. Optional: delete the entry from the register instead when the team prefers an empty open list the closed record's `lifecycle` + `closed_at` is the durable record either way.
378
+ 3. Delete empty **`plan-id`** keys; update root `updated_at`; optional milestone entry in the workflow `notes.jsonl`.
461
379
 
462
- - Each archived entry needs **`archived_at`** (`YYYY-MM-DD`).
463
- - Closed records live in archive + durable plan summaries; raw review bundles are ephemeral and not part of the long-term open list.
464
- - After batch archive/close, **refresh `tech_debt_summary`** (engine rollup below).
380
+ Closed records live in the register + durable plan summaries; raw review bundles are ephemeral and not part of the long-term record.
465
381
 
466
382
  ### Short in-place close (transition only)
467
383
 
468
- May set `lifecycle` / `closed_*` in open list for one PR; **same milestone** move to archive + delete from open list.
469
-
470
- ### Legacy `metadata.residual_findings_history`
471
-
472
- Prefer **`archived/residuals/`**; migrate and delete history key when possible.
384
+ May set `lifecycle` / `closed_*` in the register for one PR; same milestone close/delete as above.
473
385
 
474
386
  ### Hard delete
475
387
 
476
388
  - **Forbidden** for **open** entries.
477
- - Do not delete archived entries; correct via new entry or new R# referencing old `id`.
478
- - Mistaken open-only entry: PM may delete or mark **`duplicate`** then close/archive.
389
+ - Do not delete closed entries; correct via new entry or new R# referencing old `id`.
390
+ - Mistaken open-only entry: PM may delete or mark **`duplicate`** then close.
479
391
 
480
- ### Query open and archived (examples)
392
+ ### Query open and closed (examples)
481
393
 
482
394
  ```bash
483
- # Replace .mstar with your resolved {HARNESS_DIR}; legacy projects may use .agents.
484
- jq '.residual_findings["01-data-infrastructure"] // .metadata.residual_findings["01-data-infrastructure"]' .mstar/status.json
485
- jq '.entries[] | select(.id == "R1")' .mstar/archived/residuals/01-data-infrastructure.json
486
- # Engine rollup (read-only): import { techDebtRollup } from "@mstar-harness/engine" in a host hook — CLI form: mstar status tech-debt <path>
395
+ # Engine-check (read-only): validate the register / rollup / cleanup gate
396
+ mstar status validate <path-to-residuals-or-root.json> # schema
397
+ mstar status tech-debt <project-dir> # rollup over registers
398
+ mstar status findings-cleanup <plan-id> --project <id> # mode gate
487
399
  ```
488
400
 
489
- (`//` right-hand side = legacy read path.)
401
+ - The v1 read paths (root `residual_findings` / `metadata.residual_findings` / `archived/residuals/<plan-id>.json`) are **legacy read-only** — `mstar migrate` moved open entries into the register; old files may remain for history.
490
402
 
491
403
  ---
492
404
 
493
- ## `{HARNESS_DIR}/notes.json` (optional program timeline)
405
+ ## `{WORKFLOW_DIR}/<id>/notes.jsonl` (per-workflow notes ledger)
494
406
 
495
- Append-only log for merge closure, batch archive, `tech_debt_summary` refresh, etc. Does not compete with **`plans[].status`** / open residual SSOT.
407
+ Append-only JSON-lines log for merge closure, batch close, register refreshes, etc. Does not compete with **snapshot `plans[].status`** / open residual SSOT.
496
408
 
497
- ```json
498
- {
499
- "schema_version": 1,
500
- "updated_at": "YYYY-MM-DD",
501
- "entries": [
502
- { "at": "2026-04-08", "message": "Short milestone", "plan_id": "01-data-infrastructure" }
503
- ]
504
- }
409
+ ```jsonl
410
+ {"kind": "note", "ts": "2026-04-08", "text": "Short milestone"}
505
411
  ```
506
412
 
507
- - **`@project-manager`** maintains; do not rewrite past `entries` — add correction as new entry.
508
- - **`plans[].notes`**: per-plan; **`notes.json`**: cross-plan.
413
+ - **`@project-manager`** maintains; do not rewrite past lines — add a correction as a new line.
414
+ - **`plans[].notes`**: per-plan legacy verbatim array; **`notes.jsonl`**: runtime ledger — new notes append here only (no dual-write).
509
415
 
510
416
  ---
511
417
 
512
- ## `metadata.tech_debt_summary` (optional rollup)
418
+ ## `mstar status tech-debt` (project-register rollup)
513
419
 
514
- **Role:** Cross-plan aggregate over **open** R# in root **`residual_findings`** (and legacy read path if present). Does **not** replace per-entry SSOT.
420
+ **Role:** Cross-plan aggregate over **open** register entries across every `{PROJECT_DIR}/<id>/residuals.json` register. Does **not** replace per-entry SSOT. The v1 stored-summary drift check (`metadata.tech_debt_summary`) is a **v1 dead path** — the register is the source of truth, so `stored` is always null and the retained `checks`/`overall` fields report DRIFT (export-surface compatibility).
515
421
 
516
- **Compute (canonical):** engine import (do **not** hand-count):
422
+ **Compute (canonical):** engine / CLI (do **not** hand-count):
517
423
 
518
424
  ```ts
519
- // Engine check (when available) — pass status.json path if not .mstar/status.json
425
+ // Engine check (when available) — pass the project dir (default: resolved {PROJECT_DIR})
520
426
  import { techDebtRollup } from "@mstar-harness/engine";
521
- const rollup = techDebtRollup(".mstar/status.json"); // { computed, stored, checks, overall }
522
- // CLI form (same output; exit 1 on DRIFT): mstar status tech-debt <path> (default: {HARNESS_DIR}/status.json)
523
- ```
524
-
525
- - Prints computed `total_open`, `by_severity`, `by_target`, `by_plan`.
526
- - Prints **PASS** / **DRIFT** vs stored `metadata.tech_debt_summary`.
527
- - The engine call **does not write** `status.json` — PM copies computed values into `metadata.tech_debt_summary` after DRIFT or milestone refresh.
528
-
529
- **When to refresh:** after QC waves, batch archive of resolved items, or release freeze. Optional `notes.json` entry: “refreshed tech_debt_summary”.
530
-
531
- **Recommended stored shape** (`cross_cutting` optional; engine does not compute `cross_cutting` — maintain manually if used):
532
-
533
- ```json
534
- {
535
- "tech_debt_summary": {
536
- "updated_at": "YYYY-MM-DD",
537
- "total_open": 29,
538
- "by_severity": { "critical": 0, "high": 10, "medium": 10, "low": 5, "nit": 1 },
539
- "by_target": { "V1.0": 5, "V1.1": 18 },
540
- "by_plan": { "domain-models": 4, "cli-daemon-foundation": 11 },
541
- "cross_cutting": [
542
- {
543
- "id": "DEBT-X1",
544
- "title": "Cross-plan theme",
545
- "severity": "high",
546
- "relates_to": ["CLI-R9", "SYNC-R4"]
547
- }
548
- ]
549
- }
550
- }
427
+ const rollup = techDebtRollup("{HARNESS_DIR}/projects"); // { computed, stored: null, checks, overall }
428
+ // CLI form (same output; informational exit 0): mstar status tech-debt <path> (default: {PROJECT_DIR})
551
429
  ```
552
430
 
553
- - **`by_plan`** keys: short labels or `plans[].id` prefixes per repo convention.
554
- - **`cross_cutting`**: themes spanning plans/R#; explain intentional count differences in `notes.json` or here.
431
+ - Prints computed `total_open`, `by_severity`, `by_target`, `by_plan` (`by_plan` keyed by plan id — the snapshot/register plan linkage; legacy `"warning"` `low`, `null`/`""` → `medium`; closed entries skipped; missing `target` groups under `"unspecified"`).
432
+ - The engine call **does not write** anything.
555
433
 
556
434
  ---
557
435
 
558
- ## Pre-merge: `status.json` should match reality
436
+ ## Pre-merge: snapshot + register should match reality
559
437
 
560
- Before merge/PR, **`@project-manager`** (or delegate) should verify: `plans[].status`, `metadata.gates`, root **`residual_findings`** (no accidental dual-write), **`tech_debt_summary`** (if used — run engine rollup), **`notes.json`** (if used), vs review/CI.
438
+ Before merge/PR, **`@project-manager`** (or delegate) should verify: snapshot `plans[].status`, `metadata.gates`, project register (no accidental leftovers), vs review/CI.
561
439
 
562
440
  **Common gaps:**
563
441
 
564
- - R# added/closed but **`tech_debt_summary` not refreshed** (engine rollup shows DRIFT).
565
- - Finding only in **`plans[].notes`** or chat, not in **`residual_findings[<plan-id>]`**.
566
- - Major milestone with no **`notes.json`** entry when team uses program timeline.
442
+ - R# added/closed but the register was not updated.
443
+ - Finding only in `plans[].notes` or chat, not in the register `entries[<plan-id>]`.
444
+ - Major milestone with no `notes.jsonl` entry when team uses the workflow ledger.
567
445
 
568
446
  ## Compatibility: plan key names
569
447
 
570
- - Read: accept `id` or `plan_id`.
448
+ - Read: accept `id` or `plan_id` (v1 rows / entries read compatibility).
571
449
  - Write: one canonical key (prefer `id`).
572
- - Document canonical key in `{HARNESS_DIR}/AGENTS.md` if migrating.
450
+ - Document the canonical key in `{HARNESS_DIR}/AGENTS.md` if migrating.
573
451
 
574
452
  ## Common queries
575
453
 
576
454
  ```bash
577
- jq '.plans[] | select(.id == "01-data-infrastructure")' .mstar/status.json
578
- jq '.residual_findings["01-data-infrastructure"] // .metadata.residual_findings["01-data-infrastructure"]' .mstar/status.json
455
+ # Engine-check (recommended): validate any v2 artifact
456
+ mstar status validate .mstar/status.json # root v2
457
+ mstar status validate .mstar/workflows/<id>/snapshot.json # snapshot
458
+ mstar status tech-debt .mstar/projects # register rollup
579
459
  ```
460
+ v1 trees (root `plans[]` / `residual_findings`) are migrated first: `mstar migrate [--dry-run] [--path <root>]`.