@mstar-harness/opencode 2.4.1 → 3.1.0
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/CHANGELOG.md +38 -0
- package/README.md +1 -1
- package/dist/mstar.js +4563 -227
- package/harness-agents/code-reviewer.md +0 -8
- package/harness-skills/mstar-branch-worktree/SKILL.md +14 -14
- package/harness-skills/mstar-branch-worktree/references/parallel-writable-pre-dispatch.md +2 -2
- package/harness-skills/mstar-compound/SKILL.md +2 -2
- package/harness-skills/mstar-compound/references/compound-workflow.md +3 -3
- package/harness-skills/mstar-compound-refresh/SKILL.md +4 -4
- package/harness-skills/mstar-compound-refresh/references/project-knowledge-bootstrap.md +1 -1
- package/harness-skills/mstar-dispatch-gates/SKILL.md +2 -2
- package/harness-skills/mstar-engine-legacy/SKILL.md +53 -0
- package/harness-skills/mstar-engine-legacy/references/anti-recursion-checklists.md +58 -0
- package/harness-skills/mstar-engine-legacy/references/engine-check-boilerplate.md +26 -0
- package/harness-skills/mstar-engine-legacy/references/lease-protocol.md +92 -0
- package/harness-skills/mstar-engine-legacy/references/qc-seat-n-restatements.md +57 -0
- package/harness-skills/mstar-engine-legacy/references/status-field-history.md +186 -0
- package/harness-skills/mstar-harness-core/SKILL.md +6 -3
- package/harness-skills/mstar-host/references/_shared/plan-mode-bridge-core.md +8 -8
- package/harness-skills/mstar-host/references/codex.md +1 -1
- package/harness-skills/mstar-host/references/cursor-plan-mode-bridge.md +19 -8
- package/harness-skills/mstar-host/references/cursor.md +5 -5
- package/harness-skills/mstar-host/references/dsh.md +10 -7
- package/harness-skills/mstar-host/references/kimi-plan-mode-bridge.md +3 -3
- package/harness-skills/mstar-host/references/kimi.md +1 -1
- package/harness-skills/mstar-host/references/omp-plan-mode-bridge.md +2 -2
- package/harness-skills/mstar-host/references/omp.md +2 -2
- package/harness-skills/mstar-host/references/zcode-plan-mode-bridge.md +3 -3
- package/harness-skills/mstar-host/references/zcode.md +1 -1
- package/harness-skills/mstar-iteration/SKILL.md +38 -37
- package/harness-skills/mstar-iteration/references/autonomous-direction-lock.md +2 -2
- package/harness-skills/mstar-iteration/references/iteration-compass-template.md +3 -3
- package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +50 -38
- package/harness-skills/mstar-iteration/references/phase-3-iteration-close.md +7 -7
- package/harness-skills/mstar-iteration/references/phase-4-5-pr-delivery.md +2 -2
- package/harness-skills/mstar-phase-gates/SKILL.md +3 -3
- package/harness-skills/mstar-plan-artifacts/SKILL.md +21 -23
- package/harness-skills/mstar-plan-artifacts/references/knowledge-and-designs.md +16 -6
- package/harness-skills/mstar-plan-artifacts/references/plan-files-and-reports.md +10 -10
- package/harness-skills/mstar-plan-artifacts/references/status-and-residuals.md +190 -309
- package/harness-skills/mstar-plan-artifacts/templates/README.md +1 -3
- package/harness-skills/mstar-plan-artifacts/templates/status.empty.json +2 -4
- package/harness-skills/mstar-plan-conventions/SKILL.md +53 -13
- package/harness-skills/mstar-plan-conventions/references/artifact-storage-paths.md +7 -3
- package/harness-skills/mstar-plan-conventions/references/harness-bootstrap-and-agents-layering.md +9 -10
- package/harness-skills/mstar-project-governance/SKILL.md +119 -0
- package/harness-skills/mstar-review-qc/SKILL.md +3 -3
- package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +1 -1
- package/harness-skills/mstar-roles/references/project-manager/plan-management.md +6 -8
- package/harness-skills/mstar-roles/references/project-manager/qc-and-residuals.md +6 -6
- package/harness-skills/mstar-roles/references/project-manager.md +7 -7
- package/harness-skills/mstar-roles/references/qc-specialist/deep-review-lenses.md +1 -1
- package/harness-skills/mstar-roles/references/qc-specialist/report-template.md +1 -1
- package/harness-skills/mstar-roles/references/qc-specialist/reviewer-workflow.md +1 -1
- package/harness-skills/mstar-roles/references/qc-specialist-shared.md +2 -2
- package/harness-skills/mstar-sdd/SKILL.md +2 -2
- package/harness-skills/mstar-sdd/references/file-handoffs.md +1 -1
- package/package.json +1 -1
- package/harness-skills/mstar-plan-artifacts/references/done-compaction.md +0 -88
- package/harness-skills/mstar-plan-artifacts/templates/notes.empty.json +0 -5
- package/harness-skills/mstar-plan-artifacts/templates/plans-done.empty.json +0 -3
|
@@ -1,21 +1,55 @@
|
|
|
1
|
-
# `{HARNESS_DIR}/status.json` and
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
|
|
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
|
|
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 `
|
|
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
|
|
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
|
|
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
|
|
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
|
|
205
|
+
### Assignment (SSOT)
|
|
122
206
|
|
|
123
207
|
| Surface | Values |
|
|
124
208
|
| ------- | ------ |
|
|
125
209
|
| Assignment **`Findings cleanup`** | `zero-residual` \| `allow-residual` |
|
|
126
|
-
|
|
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
|
|
145
|
-
7. Plan **Done**: prefer empty `
|
|
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
|
|
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
|
|
160
|
-
| `merge_target` | string | Next merge target; multi-plan + Spec → usually `spec_integration_branch`; final PR target is
|
|
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
|
-
| `
|
|
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 `
|
|
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
|
-
|
|
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
|
-
|
|
285
|
+
### Snapshot top-level fields
|
|
197
286
|
|
|
198
|
-
|
|
|
287
|
+
| Field | Type | Semantics |
|
|
199
288
|
| --- | --- | --- |
|
|
200
|
-
| `
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
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
|
-
**
|
|
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
|
-
**
|
|
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
|
-
**
|
|
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
|
-
###
|
|
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`
|
|
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
|
-
|
|
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
|
-
- **
|
|
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
|
-
-
|
|
402
|
-
- **`plans[].id`** keys must align with
|
|
403
|
-
- **Empty `plan-id` key:** when no open
|
|
404
|
-
- **`residual_summary` (optional):** one-line human summary of **open**
|
|
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
|
|
428
|
-
| Write
|
|
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
|
-
###
|
|
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. **
|
|
439
|
-
2.
|
|
440
|
-
3.
|
|
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
|
-
|
|
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
|
|
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
|
|
478
|
-
- Mistaken open-only entry: PM may delete or mark **`duplicate`** then close
|
|
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
|
|
392
|
+
### Query open and closed (examples)
|
|
481
393
|
|
|
482
394
|
```bash
|
|
483
|
-
#
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
-
(
|
|
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
|
-
## `{
|
|
405
|
+
## `{WORKFLOW_DIR}/<id>/notes.jsonl` (per-workflow notes ledger)
|
|
494
406
|
|
|
495
|
-
Append-only log for merge closure, batch
|
|
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
|
-
```
|
|
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
|
|
508
|
-
- **`plans[].notes`**: per-plan; **`notes.
|
|
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
|
-
## `
|
|
418
|
+
## `mstar status tech-debt` (project-register rollup)
|
|
513
419
|
|
|
514
|
-
**Role:** Cross-plan aggregate over **open**
|
|
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
|
|
422
|
+
**Compute (canonical):** engine / CLI (do **not** hand-count):
|
|
517
423
|
|
|
518
424
|
```ts
|
|
519
|
-
// Engine check (when available) — pass
|
|
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("
|
|
522
|
-
// CLI form (same output; exit
|
|
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
|
-
-
|
|
554
|
-
-
|
|
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:
|
|
436
|
+
## Pre-merge: snapshot + register should match reality
|
|
559
437
|
|
|
560
|
-
Before merge/PR, **`@project-manager`** (or delegate) should verify: `plans[].status`, `metadata.gates`,
|
|
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
|
|
565
|
-
- Finding only in
|
|
566
|
-
- Major milestone with no
|
|
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
|
-
|
|
578
|
-
|
|
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>]`.
|