@mstar-harness/dsh 3.9.4 → 3.10.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 (45) hide show
  1. package/dist/gates/dispatch.d.ts +9 -3
  2. package/dist/index.js +175 -89
  3. package/harness-commands/iteration-start.md +15 -11
  4. package/harness-skills/mstar-artifacts/SKILL.md +4 -2
  5. package/harness-skills/mstar-artifacts/references/plan-files-and-reports.md +1 -1
  6. package/harness-skills/mstar-artifacts/references/plan-quality-bar.md +10 -0
  7. package/harness-skills/mstar-artifacts/references/plan-workflow-lifecycle-contract.md +115 -0
  8. package/harness-skills/mstar-artifacts/references/status-and-residuals.md +24 -3
  9. package/harness-skills/mstar-artifacts/templates/plan.main.md +6 -1
  10. package/harness-skills/mstar-compound/SKILL.md +4 -4
  11. package/harness-skills/mstar-conventions/SKILL.md +1 -0
  12. package/harness-skills/mstar-conventions/references/effort-estimation.md +2 -0
  13. package/harness-skills/mstar-dispatch-gates/SKILL.md +9 -9
  14. package/harness-skills/mstar-harness-core/SKILL.md +5 -13
  15. package/harness-skills/mstar-host/SKILL.md +41 -2
  16. package/harness-skills/mstar-host/references/_shared/plan-mode-bridge-core.md +2 -0
  17. package/harness-skills/mstar-host/references/cursor.md +3 -0
  18. package/harness-skills/mstar-host/references/dsh.md +23 -4
  19. package/harness-skills/mstar-host/references/kimi.md +3 -0
  20. package/harness-skills/mstar-host/references/omp.md +140 -1
  21. package/harness-skills/mstar-host/references/opencode.md +3 -0
  22. package/harness-skills/mstar-host/references/zcode.md +3 -0
  23. package/harness-skills/mstar-iteration/SKILL.md +1 -1
  24. package/harness-skills/mstar-iteration/references/command-shared-invariants.md +2 -0
  25. package/harness-skills/mstar-iteration/references/phase-1-prepare.md +11 -2
  26. package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +74 -10
  27. package/harness-skills/mstar-iteration/references/phase-3-iteration-close.md +3 -3
  28. package/harness-skills/mstar-iteration/references/phase-4-5-pr-delivery.md +3 -2
  29. package/harness-skills/mstar-iteration/references/phase-6-post-merge-close.md +5 -2
  30. package/harness-skills/mstar-iteration/references/plan-scoped-pm.md +3 -1
  31. package/harness-skills/mstar-phase-gates/SKILL.md +7 -5
  32. package/harness-skills/mstar-project-governance/SKILL.md +3 -3
  33. package/harness-skills/mstar-review-qc/SKILL.md +4 -4
  34. package/harness-skills/mstar-review-qc/references/review-responsibility-boundaries.md +1 -1
  35. package/harness-skills/mstar-roles/references/_shared/leaf-executor-core.md +1 -0
  36. package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +5 -2
  37. package/harness-skills/mstar-roles/references/project-manager/plan-management.md +15 -0
  38. package/harness-skills/mstar-roles/references/project-manager/qa-trigger-matrix.md +3 -3
  39. package/harness-skills/mstar-roles/references/project-manager/qc-and-residuals.md +7 -5
  40. package/harness-skills/mstar-roles/references/project-manager.md +12 -11
  41. package/harness-skills/mstar-sdd/SKILL.md +5 -2
  42. package/harness-skills/mstar-sdd/references/implementer-continuation-prompt.md +4 -1
  43. package/harness-skills/mstar-sdd/references/implementer-prompt.md +4 -0
  44. package/harness-skills/pm/SKILL.md +9 -10
  45. package/package.json +1 -1
@@ -52,14 +52,53 @@ On **dsh** only, read-only fan-out of **N ≥ 3** seats runs through the native
52
52
 
53
53
  ## `/goal` directive (host-agnostic)
54
54
 
55
- **Applicability is by capability, not host identity**: any host that exposes a `/goal` command (currently Codex Goal Mode and omp; other code agents may add it later) attaches a persistent objective to the thread. **Exception — dsh:** mstar **stops arming** a goal there and never uses a `/goal` objective or a goal round loop as the progression driver — dsh runs on the native workflow (workflow snapshot phases + dispatch gates + **subagent settle notifications**; Phase 2 is a PM-local dispatch → wait for the child's settle notification → next dispatch, and a manually armed `/goal` stays outside mstar's flow). Full rule → `references/dsh.md`. Rule — **always set the goal to running the complete flow to the end**, never a sub-stage:
55
+ **Applicability is by capability, not host identity**: any host that exposes a `/goal` command (currently Codex Goal Mode and omp; other code agents may add it later) attaches a persistent objective to the thread. **Exception — dsh:** mstar **stops arming** a goal there and never uses a `/goal` objective or a goal round loop as the progression driver — dsh runs on the native workflow (workflow snapshot phases + dispatch gates + **subagent settle notifications**; each settle notification is a **`result-settled` Rescheduling checkpoint** — run that checkpoint and dispatch the ready independent work before any wait, never "one settle → one dispatch", per `mstar-iteration` `references/phase-2-worktree-lease.md` §2.4; a manually armed `/goal` stays outside mstar's flow). Full rule → `references/dsh.md`. Rule — **always set the goal to running the complete flow to the end**, never a sub-stage:
56
56
 
57
57
  - **Advancing an iteration**: set the goal to **complete the entire iteration flow** (`iteration-start → per-plan cycles → iteration-close → PR delivery → PR merge-ready loop`). Do not set a sub-stage goal (e.g. "finish Phase 1 only").
58
- - **Advancing non-iteration work** (single plan / hotfix / one-off task): set the goal to **complete the entire per-plan flow** (`specify → clarify → plan → tasks → implement → plan QC tri + QA gate → Done`). Do not set a sub-stage goal (e.g. "write the plan" or "implement one task").
58
+ - **Advancing non-iteration work** (single plan / hotfix / one-off task): set the goal to **complete the entire per-plan flow** (`specify → clarify → plan → tasks → implement → plan QC tri + QA gate → Done`; standalone development plans continue through the delivery tail to verified merge + terminal close — `mstar-harness-core`「最小交付循环」/ `mstar-artifacts/references/plan-workflow-lifecycle-contract.md`). Do not set a sub-stage goal (e.g. "write the plan" or "implement one task").
59
59
  - **Scoped primary route** (`/iteration-drive --assignment | --workflow <id> --plan <id> | --resume <session.json>`): the goal is the **active plan scope only** — `mstar plan bind` → constrain → tasks → per-task review → plan QC tri / QA → `mstar plan handoff`. Never set a goal that spans the iteration flow, sibling plans, or Phase 3–6: those stay in the coordinator's own primary session, not this plan-scoped one (`mstar-iteration` `references/plan-scoped-pm.md` §5).
60
60
 
61
61
  Goal text is a session-level objective only: `{HARNESS_DIR}` / `{PLAN_DIR}` / `status.json` remain SSOT, and goal completion is **not** harness Done. Mirror goal success criteria into the SSOT plan; when the goal changes, update goal text and the SSOT in the same round.
62
62
 
63
+ ## Phase-transition todo refresh (host-agnostic)
64
+
65
+ At **every phase transition** (Prepare → Execute → InReview waves → Phase 3 close → Phase 4 PR → Phase 5 merge-ready → Phase 6 post-merge; likewise per-plan gate crossings), the PM refreshes the host session `todo` list **before the next action or dispatch**: close only the finished phase's **completed** entries, preserve any still-pending gate or future-phase item, and append the next phase's entries. Scoped primary sessions project only their assigned plan through handoff — never global Phase 3–6 tasks (`mstar-iteration` `references/command-shared-invariants.md` § Session todos; `references/phase-2-worktree-lease.md` §2.1).
66
+
67
+ `todo` entries are a projection, not SSOT: they reflect existing snapshot phase / plan states and named plan/gate evidence, and cannot authorize or invent a state transition. Snapshot and plan artifacts remain the state authorities; this is freshness discipline, not a new host hook anchor, tool, or deterministic enforcement mechanism.
68
+
69
+ ## Host hooks (anchor contract)
70
+
71
+ Shared lifecycle skills name **host-agnostic anchors** — named moments at which the active host obliges the PM to run a host-defined coordinator action. The anchor vocabulary is frozen and carries no host identity: tool names, exact parameters, prerequisites, refusal codes, native settings and auto-trigger scope live **only** in `references/<host>.md`.
72
+
73
+ | Anchor | Moment |
74
+ |--------|--------|
75
+ | `iteration-entry` | first preparation action of a new iteration — reached only once the workflow is registered and its id known |
76
+ | `phase-1-lock` | Phase 1 completion — once the integration worktree exists, the reviewed changes are committed there and that branch is pushed (the PM lock alone is not the moment) |
77
+ | `phase-2-entry` | the Phase 2 execute/resume entry — after the §2.0 gates, before the per-plan loop; **not** the Phase-1-reused integration-worktree step |
78
+ | `rescheduling-checkpoint` | each `Rescheduling checkpoint` re-evaluation |
79
+
80
+ **Execution rule.** At each anchor the PM executes whatever the **active host reference** declares under its own `## Host hooks` section for that anchor. A host reference that declares nothing for an anchor means **no-op**: never invent an action, never substitute another host's declaration, and never treat an absent declaration as permission to skip the anchor's shared step.
81
+
82
+ **Marker form.** A shared file that owns an anchor carries a comment marker plus a one-line pointer — neither names a host or a tool:
83
+
84
+ ```markdown
85
+ <!-- host-hook: <anchor> -->
86
+ > Execute the active host reference's `## Host hooks` declaration for `<anchor>`; this file defines no host action.
87
+ ```
88
+
89
+ Carrier locations — the four markers in the shared corpus (all four live under `skills/`, never in `commands/`):
90
+
91
+ | File | Location | Anchor |
92
+ |------|----------|--------|
93
+ | `mstar-iteration/references/phase-1-prepare.md` | §1.5 tail, after the v2 status registration (the workflow id exists there) | `iteration-entry` |
94
+ | `mstar-iteration/references/phase-2-worktree-lease.md` | §2.3 「Integration worktree (Phase 2 entry) + control root」 checklist tail, after step 7 (transfer + commit + push) — the Phase 1 route reaches it through `iteration-start` §6, which carries a pointer only | `phase-1-lock` |
95
+ | `mstar-iteration/references/phase-2-worktree-lease.md` | immediately before the `## 2.4 Per-plan loop` heading (the Phase 2 execute/resume entry; §2.3 is the Phase-1-reused step and triggers nothing) | `phase-2-entry` |
96
+ | `mstar-iteration/references/phase-2-worktree-lease.md` | `### Rescheduling checkpoint` | `rescheduling-checkpoint` (the five frozen reason names are handed off verbatim) |
97
+
98
+ **Prohibition (shared text — incremental rule).** **New or modified** shared-layer text — everything under `skills/**` except `skills/mstar-host/**`, plus `commands/**` — MUST NOT introduce a host name (`omp`, `oh-my-pi`, `dsh`, `OpenCode`, `Cursor`, `Codex`, `Kimi`, `ZCode`), a host tool/field name (`subagent`, `subagent_type`, `tasks[]`, `ask`, `hub`), a native settings key (`modelHandoff`, `phase2PlanInstances`, `maxPlanInstances`), or an extension file name. Capability phrasing ("when the host exposes an invoke tool") is the only permitted form for new text; host names belong to this skill and `references/<host>.md`.
99
+
100
+ **Enforcement surface.** The check applies to **the files a change touches**, never to the whole corpus: shared text that already violates the rule and is not part of the current change is **out of scope of the rule's enforcement** and is cleared in batches under roadmap goal **`host-seam-corpus-cleanup`** (`{PROJECT_DIR}/_default/roadmap.md`). Until that cleanup completes, a whole-tree grep over shared text is **not** a valid assertion for this rule — judge a change on the shared-layer text it adds or edits.
101
+
63
102
  ## Resolve loaded skill root
64
103
 
65
104
  Docs name assets as skill **`<name>`** → `scripts/…` / `references/…`. **Resolve the loaded skill directory first** — do **not** open `skills/<name>/…` from a consumer app cwd (that layout exists in the harness source / plugin package only).
@@ -49,6 +49,8 @@ Not allowed in the parent Build session by default: product implementation, test
49
49
  | **`spec-register`** | Register plan in SSOT | New root `workflows[]` entry (`{HARNESS_DIR}/status.json` v2) + `plans[]` row in `{WORKFLOW_DIR}/<id>/snapshot.json` (`id`, `status`, `file`, `metadata`); spec stub in `{SPECS_DIR}` or plan frontmatter |
50
50
  | **`mirror-plan`** | SSOT main plan file | `{PLAN_DIR}/<plan-id>-<name>.md` with task checkboxes aligned to the host plan body |
51
51
 
52
+ `spec-register` is an authorized domain operation (engine producer primitives), declares the workflow's delivery kind, and blocks implementation until complete — plan-mode resumes owe the same registration obligation. Semantics → `mstar-artifacts/references/plan-workflow-lifecycle-contract.md`.
53
+
52
54
  After the host plan is created, keep the host plan body and mirror file **in sync** when scope changes (update both in the same coordination round).
53
55
 
54
56
  ## Implement todo completion gate (every code todo)
@@ -67,6 +67,9 @@ When Assignment has **`SDD implementer session: sticky`** (`mstar-sdd/references
67
67
 
68
68
  Cursor PM dispatch = **`Task`** with `subagent_type` matching the Assignment `Execute as` role. Flat JSON field shape → **Task invoke schema (Cursor)** below.
69
69
 
70
+ **Role-binding field:** **`subagent_type`** (flat sibling of `prompt`) — must equal the Assignment `Execute as`.
71
+ **Engine scope (#156):** Cursor exposes no dispatcher identity, so the caller-scoped `antiRecursionPrecheck` leg is **skipped** on this host — the binding field carries the **spawn target**, and target == `Execute as` is the compliant C5 pattern — and the red line stays **prompt-level** (`mstar-dispatch-gates` § 承接方反递归红线). Caller-side hard enforcement exists only where the host declares a dispatcher binding (`dsh.md`).
72
+
70
73
  - **1 Assignment ⇒ 1 Task**; parallel batches ⇒ **N Tasks in one message** → **`parallel-dispatch.md`** (`mstar-dispatch-gates`).
71
74
  - Paste-only: Assignment Markdown **does not** start work; PM thread **must not** implement, review, or edit specialist deliverables by loading another role reference in the same session (`Acting as role: …` is **not** dispatch) → **`parallel-dispatch.md`** § Paste-only failure.
72
75
  - No callable `Task` / subagent for required work → **`Blocked`** — report to user; do not substitute in-thread execution.
@@ -321,6 +321,12 @@ assignees = N `subagent` calls = N independent delegations** (dispatch-gate
321
321
  dispatched Assignment). Paste-only Assignment without an invoke is **not**
322
322
  dispatch.
323
323
 
324
+ **Role-binding field:** none — binding is **prompt-only** on dsh (the tool has
325
+ no role field; the header region of the Assignment body is what the gate and
326
+ the role-persona channel read, so `Execute as` / `Act as` + skill load must be
327
+ in the prompt). A dispatch that drops those lines has no field to fall back on
328
+ — it is a bare delegation.
329
+
324
330
  **Execution: concurrent dispatch REQUIRES background mode.** The `subagent`
325
331
  tool does **not** declare `isConcurrencySafe` → fail-closed `exclusive`
326
332
  classification, so same-message invokes are issued one-at-a-time (the next
@@ -360,10 +366,14 @@ armed and the agent is idle, and it knows nothing about running subagents, so
360
366
  an operator who arms `/goal` manually can still get rounds firing while a
361
367
  dispatched child owns the critical path.
362
368
 
363
- **Phase 2 continuous execution is a PM-local loop**: dispatch → **wait for the
364
- child's settle notification** → next dispatch. When a dispatched child owns the
365
- critical path, the correct action is to **wait** — not to open another unit of
366
- work against the same worktree.
369
+ **Phase 2 continuous execution is a PM-local loop**, not a one-wave-at-a-time
370
+ queue: each child's settle notification is a **`result-settled`
371
+ `Rescheduling checkpoint`** — run that checkpoint and dispatch what is already
372
+ ready and authorized (independent plans and plan-local tasks, each in its own
373
+ isolated track) before waiting, and wait only when it finds none. Waiting stays
374
+ the correct action for work a running child already owns — never open another
375
+ unit of work **against the same worktree**. Procedure (and its frozen reason
376
+ vocabulary) → `mstar-iteration/references/phase-2-worktree-lease.md` §2.4.
367
377
 
368
378
  The **scoped plan route** changes none of this: `/iteration-drive --assignment |
369
379
  --workflow --plan | --resume` still never arms a goal on dsh, and its
@@ -485,6 +495,15 @@ The dsh web client resolves slash commands against a client-side lexicon driven
485
495
  enforcement with no binding, the plugin logs the absence AND every
486
496
  Assignment-shaped dispatch fails closed (`dispatch.anti-recursion.
487
497
  empty-binding` → deny) until the binding is set.
498
+ - **Caller-scoped engine enforcement (the dsh-only half of issue #156).** That
499
+ binding is what makes the precheck real here: with a declared dispatcher
500
+ identity the engine compares the **dispatching seat's own role** against the
501
+ Assignment `Execute as` and hard-enforces it (`callerRequired` — an unset
502
+ binding fails closed, never skipped). Hosts whose reference declares **no**
503
+ dispatcher binding expose only the **spawn target** in their role-binding
504
+ field — and target == `Execute as` is the compliant C5 pattern — so there the
505
+ leg is skipped and the red line stays **prompt-level**
506
+ (`mstar-dispatch-gates` § 承接方反递归红线).
488
507
 
489
508
  ## Files, shell, and approvals
490
509
 
@@ -61,6 +61,9 @@ Morning Star role ids (`project-manager`, `fullstack-dev`, `qc-specialist`, …)
61
61
 
62
62
  Role-binding contract + Assignment template → **`_shared/host-role-binding-core.md`** (C5/C5b). Kimi-specific invoke shapes, same turn:
63
63
 
64
+ **Role-binding field:** **`subagent_type`** — but on Kimi it selects a **built-in** type (`coder` / `explore` / `plan`), not the role, so the role itself travels in the prompt (C5b).
65
+ **Engine scope (#156):** no engine dispatch gate observes caller identity here (the binding field carries a **built-in invoke type**, not the dispatching seat), so this red line stays **prompt-level** (`mstar-dispatch-gates` § 承接方反递归红线). Caller-side hard enforcement exists only where the host declares a dispatcher binding (`dsh.md`).
66
+
64
67
  ```text
65
68
  Agent(
66
69
  subagent_type: "coder",
@@ -79,6 +79,8 @@ Single-task shorthand may exist depending on host version — always match the l
79
79
 
80
80
  **Envelope-first**: write `agent` + `name` as the first fields of each `tasks[]` entry, before the long `task` body — the body crowds them out and `agent` gets silently dropped (omp defaults to generic `task`, no error). SSOT → `parallel-dispatch.md` § Mandatory order.
81
81
 
82
+ **Role-binding field (single home)**: OMP binds the dispatched role through the `tasks[]` entry field **`agent`** — `agent: "<Execute as role-id>"`, in the batch shape `task(context: "…", tasks: [{name, agent, task}])`. This field name is omp's; no other host's invoke tool uses it. A round that writes the role only in the prompt body has set no binding.
83
+
82
84
  ## Role agents (C5 — hard constraint)
83
85
 
84
86
  **Live `task` tool schema is SSOT every session.** Exact `agent` names vary by omp version and which `agents/*.md` were discovered after plugin install/link. Read the tool's Available Agents list before dispatch — do not invent names; do not hard-code stale tables over the live list.
@@ -210,7 +212,9 @@ Cannot emit required **N** → **`Blocked`**.
210
212
 
211
213
  ## In-process engine binding (omp ≥ 17.2.11)
212
214
 
213
- - **Surfaces** (npm package root = plugin root; sources live in `packages/omp/src/`): `hooks/pre/mstar-gates.js` — one `tool_call` pre-hook that returns `{ block: true, reason }` (structured refusal the model sees as the tool error) or `undefined` (pass); `tools/mstar_{status_validate,dispatch_validate,lease_verify,path_resolve,iteration_gate,worktree_check}.js` — six model-callable validator tools (engine validators only, Zod params via `pi.zod`). omp discovers these by convention from the installed package root (`<pkg>/hooks/pre/` any file, `<pkg>/tools/` direct `*.js` files — the sub-directory scan only accepts `tools/<name>/index.ts`), not from `dist/`.
215
+ - **Surfaces** (npm package root = plugin root; sources live in `packages/omp/src/`): `hooks/pre/mstar-gates.js` — one `tool_call` pre-hook that returns `{ block: true, reason }` (structured refusal the model sees as the tool error) or `undefined` (pass); `extensions/model-handoff.js` — the coordinator model-handoff extension, published through the manifest `omp.extensions` entry (see **Model handoff** below); `tools/mstar_{status_validate,dispatch_validate,lease_verify,path_resolve,iteration_gate,worktree_check}.js` — six model-callable validator tools (engine validators only, Zod params via `pi.zod`). omp discovers `hooks/` and `tools/` by convention from the installed package root (`<pkg>/hooks/pre/` any file, `<pkg>/tools/` direct `*.js` files — the sub-directory scan only accepts `tools/<name>/index.ts`), not from `dist/`; `extensions/` is discovered from the manifest entry.
216
+
217
+ - **Surfaces** (npm package root = plugin root; sources live in `packages/omp/src/`): `hooks/pre/mstar-gates.js` — one `tool_call` pre-hook that returns `{ block: true, reason }` (structured refusal the model sees as the tool error) or `undefined` (pass); `extensions/phase2-orchestration.js` — the Phase-2 reminder + launch-bookkeeping extension (`mstar_phase2`), published through the manifest `omp.extensions` entry (see **Phase-2 plan instances** below); `tools/mstar_{status_validate,dispatch_validate,lease_verify,path_resolve,iteration_gate,worktree_check}.js` — six model-callable validator tools (engine validators only, Zod params via `pi.zod`). omp discovers these by convention from the installed package root (`<pkg>/hooks/pre/` any file, `<pkg>/tools/` direct `*.js` files — the sub-directory scan only accepts `tools/<name>/index.ts`), not from `dist/`.
214
218
  |- **Enforcement semantics**: block ONLY under `Enforcement: hard`. Both gates read the repo `.mstarc` `[config] enforcement`, else the harness compass frontmatter (`enforcement: hard`, active/locked iterations only); the dispatch gate ALSO honors each Assignment's own header flag (`assignmentHeaderRegion` — a body example never hardens). A hard repo setting therefore hardens flag-less dispatches (Gate 1 / dsh `resolveDispatchHard` parity). Soft-mode dispatch violations are warn-logged through the extension logger (never blocked); soft status-write violations stay a silent pass. Rollback = unset the flag (or `.mstarc` `soft`). Never global.
215
219
  - **Anti-recursion scope (issue #156)**: the engine's `antiRecursionPrecheck` is **caller-scoped** — it compares the DISPATCHING agent's own role against the new Assignment's `Execute as`. omp's `tool_call` event carries no caller identity and the task entry `agent` is the spawn TARGET, which equals `Execute as` on every compliant dispatch (C5 above) — so Gate 2 does NOT run the precheck on omp (the pre-#156 wiring hard-blocked every compliant hard-mode dispatch on `self-type`, or on `empty-binding` when `agent` was omitted). The NEVER red line stays prompt-level on this host (`mstar-dispatch-gates`); dsh enforces it in-engine via Config `dispatchBinding`.
216
220
  - **Engine dependency**: the npm package **bundles the engine inline** into every hook/tool bundle at build time — zero runtime package resolution, so module link can never fail on a missing package (the 2026-09-03 hotfix for the bare-import load failure). The maintainer `omp plugin link` path (now `<repo>/packages/omp`) still resolves the engine via the workspace member — run `bun install && bun run engine:build && bun run --cwd packages/omp build` in the checkout first (the member's `dist/` and the package's generated mirrors are gitignored).
@@ -220,6 +224,141 @@ Cannot emit required **N** → **`Blocked`**.
220
224
  - **Engine version compatibility**: the hook and tools degrade gracefully until the engine release exporting both `composeDispatchGate` and `parseCompassFrontmatter` (published 2.0.2 predates both). Missing exports never fail module load: the hook's dispatch gate needs `composeDispatchGate` — on older engines Gate 2 (task dispatch) is skipped with a one-time warning while Gate 1 (status) stays active — and `mstar_dispatch_validate` / `mstar_iteration_gate` report an explicit upgrade error instead of loading (no silent absence; CLI fallbacks: `mstar dispatch validate`, `mstar iteration gate`).
221
225
  - **Reload**: edits are picked up by a new session (`?mtime` cache-buster); in-session `/reload-plugins` (omp ≥ 17.2.11) applies them without a new session.
222
226
 
227
+ ## Model handoff (native settings)
228
+
229
+ A second extension entry from this package: `extensions/model-handoff.js` (manifest `omp.extensions`; engine inlined, its single `@oh-my-pi/pi-coding-agent` import resolved by the running host). It is a **coordinator model policy owned by native settings**, not a user command — no session, flag, goal or prose can enable it.
230
+
231
+ | Surface | Contract |
232
+ |---|---|
233
+ | Native path | `/settings` → **Plugins** → **`@mstar-harness/omp`** — the rows are the schema keys: `modelHandoff` (boolean, default `false`) and `handoffTarget` (`@default` \| `@smol`, default `@default`). No activation command, no harness settings file, no second settings UI. |
234
+ | Persistence | Host plugin settings (user-scope `omp-plugins.lock.json`, plus project `plugin-overrides.json`), reread through the exported helper at entry **and again at fire time** — a mid-flight enable never retro-arms an iteration already under way, and disabling at fire time suppresses the switch without terminalizing the binding. |
235
+ | Scope | That panel lists **user-scope** installs; a project-scope npm install has no native row (host limitation, documented rather than worked around). Use the user-scope path — never double-install or add a private settings parser/UI. |
236
+ | Supported entries | `/iteration-start`, `/iteration-loop`, and a natural-language / skill-driven start (`skill-start`) as labelled from the host's own `input` event. `/iteration-drive` in any form never arms — the scoped-plan route only restores the session's existing binding, and a start call after it is refused `scoped-plan-route`. |
237
+ | Inert contexts | Ordinary chat, unrelated commands, leaf/subagent sessions (host `session_init` marker), plan-scoped PM sessions, other hosts, and an iteration whose coordinator never armed. |
238
+ | PM binding | Tool `mstar_model_handoff`, executed at two host hook anchors — **`iteration-entry`** (`{operation:"start"}`) and **`phase-1-lock`** (`{operation:"phase1-complete"}`). Exact parameters, prerequisites, refusal codes and required-vs-optional per anchor → **§ Host hooks** below. Session identity, cwd, entry route, task-session state and coordinator authority are host-derived from the ledger, the workflow's own session envelopes and the root register. |
239
+ | Ownership | One explicitly named workflow and control root own the coordinator. Missing, foreign or ambiguous ownership fails closed — no `workflows[0]`, latest-mtime, unique-new-row or "most recent" inference, and a concurrent sibling iteration stays untouched. Only the bound coordinator session changes model; role mappings, other sessions, subagents, goal objective and workflow snapshot status are never written. |
240
+ | Full readiness | Fire requires the sequential specialist returns for that iteration, PM-confirmed Prepare gates for every registered plan with `compass status: locked`, a distinct same-repository integration checkout on its recorded branch, and a remote tip equal to the validated integration HEAD. `evaluatePhaseGate` is a later-phase gate and is never readiness evidence; a draft compass, a lock alone, a missing checkout or an unpushed commit is not ready. |
241
+ | Cancellation | While pending, an unowned model change — history or live model — cancels the not-yet-executed switch, and the arm's own transition can never cancel it. Cancellation is deliberately conservative (it can also catch another extension's change; there is no exact user-selection event), and it never clears the saved preference. Navigation arriving during an invoked action is refused immediately; navigation arriving first fences the action instead of letting it start. |
242
+ | Replay | Full session ledger with exact session-id filtering. A persisted attempt with no recorded outcome restores as `uncertain` — never retried, never reported as a successful handoff because the current model happens to match. Tree/branch/reload replay the ledger; a fork or new session id inherits nothing. |
243
+ | Failure visibility | Refusals appear in the tool result, state transitions also as a durable session notice; the session keeps the model it actually has and there is no automatic retry loop. Missing auth, an unresolvable role and missing evidence are reported as failures, never as a handoff. |
244
+ | Modes | Arming is observed from the host's `input` event, so it is documented for the interactive entries above only — no print/JSON/RPC automatic-behaviour claim exists (E1 boundary). The completion checkpoint is an ordinary tool call whose result the host renders like any other tool result. |
245
+
246
+ Do not describe this feature as a `pause` flag, as a goal, or as a switch performed by any other session, and do not require a provider-side or upstream change to use it.
247
+
248
+ ## Phase-2 plan instances (native settings + optional transport)
249
+
250
+ An extension entry from this package: `extensions/phase2-orchestration.js` (manifest `omp.extensions`; engine inlined, and its one runtime host import — `getPluginSettings` from `@oh-my-pi/pi-coding-agent/extensibility/plugins`, the public uncached settings reader — resolved by the running host, declared as an optional peer). It supplies one bounded Phase-2 advisory plus the `mstar_phase2` bookkeeping tool. It never spawns, merges, rewrites workflow state or releases leases — the optional skill below performs every CLI call, and engine scope/lease/revision/worktree/merge verbs stay authoritative.
251
+
252
+ Phase 2 only. Ordinary sessions, leaf/subagent sessions, scoped-plan PM sessions and Phase 1/3–6 never activate the reminder or a launch.
253
+
254
+ | Surface | Contract |
255
+ |---|---|
256
+ | Native path | `/settings` → **Plugins** → **`@mstar-harness/omp`** — the rows are the schema keys: `phase2PlanInstances` (boolean, default `false`) and `maxPlanInstances` (number, default `2`, minimum `1`, step `1`) with **no ceiling of 2**. |
257
+ | Launch-only opt-in | `phase2PlanInstances` gates **extra primary launches only**. Native background task concurrency and the bounded reminder are independent of it: a disabled opt-in neither silences the reminder nor limits ordinary `task` dispatch. |
258
+ | Configurable capacity | `maxPlanInstances` counts concurrently active **plan-scoped primaries** plus owned pending launch intents — the union by plan id, each counted once. The iteration coordinator and task subagents are excluded. Lowering it stops further launches and never kills running work. |
259
+ | Invalid values | A present-but-malformed key (non-boolean, non-integer, below 1, unparsable) **fails visibly** and authorizes no launch — never coerced to the default, never an unbounded mode, never a silent hard limit. Absent keys take the schema defaults. |
260
+ | Reminder | At most one advisory per **changed** opportunity observation, emitted at `agent_end` only; the observation key is recorded before the message, so identical unchanged state never re-fires and A→B→A does not re-nudge A. No timer, no polling, no invented job-settled event; a `null` snapshot means "unavailable", never "no jobs". Native completion delivery stays authoritative and is never duplicated. The advisory text asserts nothing about a plan being ready. |
261
+ | Checkpoint pointer | The advisory only points at the shared Phase-2 rescheduling checkpoint (`mstar-iteration/references/phase-2-worktree-lease.md` §2.4). It never copies the decision matrix — this section does not either. |
262
+ | Scope limitation (host behaviour) | The native `/settings` → Plugins panel lists **user-scope** plugin installs; a `--scope project` install has no row there (documented, not worked around). The runtime still reads the saved preference through the host's own settings helper. |
263
+
264
+ ### PM call sequence (tool `mstar_phase2`)
265
+
266
+ Not a user activation command: nothing is spawned, merged, leased or written to engine state by the tool, and no session/flag/goal/prose can substitute for the calls below.
267
+
268
+ 1. **`bind`** — the **`phase-2-entry`** anchor (→ **§ Host hooks**): the coordinator's **Phase 2 execute/resume entry** (immediately before the per-plan loop, after the §2.0 gates; §2.3's Phase-1-reused integration-worktree step is not this anchor), independent of any setting or model handoff, and also required on a no-argument `/iteration-drive` resume. Call shape, authority derivation, the rejection set and its refusal codes live in that section.
269
+ 2. **`checkpoint`** — the **`rescheduling-checkpoint`** anchor (→ **§ Host hooks**): acknowledge that PM ran the shared scheduling procedure against the sample taken at that moment, with `reason` from the five frozen names and `decision` ∈ `dispatched | wait | blocked`. The runtime attaches the sampled key; the caller cannot choose or reset it. `blocked` suppresses advisory continuation until a new explicit user turn or a later checkpoint clears it — never a timer or incidental snapshot churn. A checkpoint carries a decision and note, never a ready list.
270
+ 3. **`reserve-launch`** — `{operation:"reserve-launch", planId, transport:"herdr"|"tmux", skill:{name,source}, capability:{executable,version,target}}`. Admission additionally requires the enabled opt-in, a valid latest capacity, a coordinator-prepared row with no plan binding/lease/handoff, the identical prepared Assignment hash, an existing canonical **distinct** feature worktree on its assigned branch, and the transport prerequisites. Only `applied:true` authorizes a side effect; an identical duplicate returns the recorded intent with `applied:false` and authorizes nothing, while a different live intent/binding for that plan refuses. Intents are journaled at `<workflow dir>/omp-launches.json` — a plugin-owned transport journal, never a lifecycle register.
271
+ 4. **`record-launch`** — one transition per observed step, each recorded **before** its matching side effect: `{operation:"record-launch", intentId, observation, target?, evidencePath}` with `observation` ∈ `starting | created | submitting | submitted | refused | uncertain`. Strict forward order `reserved → starting → created → submitting → submitted`; `starting` permits pane creation, `created` (which **requires the returned opaque target**) permits starting OMP in it, `submitting` permits the single scoped prompt. Only a newly persisted transition reports `applied:true`; PM acts only on that. `refused` is legal only for an observed failure that provably precedes any process/prompt side effect; from `submitting` onward a lost outcome is `uncertain`, which is terminal. A recorded target is never re-pointed, and settings/capacity/ownership are re-read before each side-effecting transition.
272
+
273
+ Refusal codes for `reserve-launch` / `record-launch` — **not** anchor-triggered (the optional extra-primary path carries no shared anchor moment, so these belong to no anchor row): `launch.invalid-request`, `launch.session-denied`, `launch.phase-inactive`, `launch.snapshot-unreadable`, `launch.journal-corrupt`, `launch.plan-not-found`, `launch.plan-unavailable`, `launch.plan-not-prepared`, `launch.plan-occupied`, `launch.prepared-hash-drift`, `launch.worktree-unavailable`, `launch.capability-unavailable`, `launch.settings-disabled`, `launch.settings-invalid`, `launch.settings-read-failed`, `launch.capacity-exceeded`, `launch.intent-not-found`, `launch.transition-invalid`, plus the shared `tool-error`. Every one is a visible refusal that authorizes nothing; success codes are `reserved` / `recorded`, and `replayed` (`applied:false`) for an identical duplicate that likewise authorizes no side effect.
274
+
275
+ ### Optional transport (skill-driven — no compiled bridge)
276
+
277
+ Every prerequisite is required and checked per launch: the **corresponding optional skill actually present in the catalog and read** (the `herdr` skill today; a tmux skill only if one truly exists — binary existence is not skill availability), the CLI executable available, and this session actually inside the matching managed environment (`HERDR_ENV=1`; `TMUX` set for tmux). Two managed environments visible at once is a visible refusal, not a focus-based choice. A missing prerequisite is a **visible no-op**: no process start, no silently substituted plan, native background scheduling intact, never a fabricated success. This never becomes a mandatory load-order dependency of the standalone `mstar-*` skill set.
278
+
279
+ **Herdr** (the currently available contract — read the skill and its current group help/status at use): create the pane with `herdr pane split --current --direction <chosen> --cwd <prepared-worktree> --no-focus` and use the returned `result.pane.pane_id` verbatim as the opaque target; then `herdr agent start <unique-name> --kind omp --pane <returned-id>`; then submit exactly once with `herdr agent prompt <unique-name> "/iteration-drive --assignment <absolute-prepared-assignment>"`, without waiting for plan completion. Preserve CLI argument boundaries.
280
+
281
+ **tmux** (conditional): only where a matching tmux skill is actually present **and read**, the CLI supports that skill's command forms, `TMUX` identifies this caller, and its explicit target is resolved. Use the skill's detached/non-focus creation with explicit cwd and returned pane id, launch OMP in it, and submit the same absolute scoped route; inspect help instead of guessing flags, and never shell-type into the user's focused pane. **No tmux skill exists in the current catalog**, so tmux is unavailable here — an unsupported seam to be named honestly, not a failed implementation and not a silent Herdr substitution.
282
+
283
+ **Uncertainty, scope and ownership**: PM uses only returned opaque targets, records the observed command output before proceeding, and treats `agent_not_ready`, blocked UI, a timeout, a vanished response or a stalled submission as terminal — reported, never re-sent, never retried, with no fabricated id and no credential passed (no session JSON path, no `--expect` revision, no `--resume`). A created empty pane may be removed only with proven ownership and no possibly-active primary; panes are never killed to free capacity. Pane ready/idle/done means prompt transport is ready — never plan completion, lease release or ownership. The child obtains its own engine session through a fresh `plan bind`, runs only the prepared scope and stops at its durable handoff; the coordinator alone keeps serial integration and Phase 3–6 closure.
284
+
285
+ **Evidence boundary**: this transport guidance is supported by **simulated** scripted skill/CLI observation traces (PM action sequences scored for command order, prepared cwd, non-focus creation, credential absence, opaque-target reuse, stopping on uncertainty and no blind resend) — not by a native end-to-end Herdr/tmux run, not by any probe of user terminals, and not by a real OMP child process.
286
+
287
+ ## Host hooks
288
+
289
+ The four **host hook anchors** — `iteration-entry`, `phase-1-lock`, `phase-2-entry`, `rescheduling-checkpoint` — are defined host-agnostically in `mstar-host` § `## Host hooks (anchor contract)`. Shared skills carry only the marker `<!-- host-hook: <anchor> -->` plus a one-line pointer and declare no host action; **this section is the OMP declaration for all four**. When the shared step carrying an anchor is reached, the PM executes the call declared here. Tool names, parameters, refusal codes and settings keys for these two mechanisms live in this file and nowhere else.
290
+
291
+ Carrier moments — where the PM meets the marker:
292
+
293
+ | Anchor | Shared carrier |
294
+ |---|---|
295
+ | `iteration-entry` | `mstar-iteration/references/phase-1-prepare.md` §1.5 (tail, after the workflow is registered to the v2 status surface and its id is known) |
296
+ | `phase-1-lock` | `mstar-iteration/references/phase-2-worktree-lease.md` §2.3 (`## Integration worktree (Phase 2 entry) + control root` checklist tail — after the integration checkout is recorded, the reviewed changes are committed there and that branch is pushed; the Phase 1 route reaches it through `iteration-start` §6, which carries a pointer only) |
297
+ | `phase-2-entry` | `mstar-iteration/references/phase-2-worktree-lease.md` immediately before the `## 2.4 Per-plan loop` heading (the Phase 2 execute/resume entry after the §2.0 gates) |
298
+ | `rescheduling-checkpoint` | `mstar-iteration/references/phase-2-worktree-lease.md` §2.4 (`### Rescheduling checkpoint`) |
299
+
300
+ ### Auto-trigger boundary — the diagnosed failure mode
301
+
302
+ Neither extension ever arms, binds or checkpoints by itself:
303
+
304
+ - `extensions/model-handoff.js` observes the host `input` event only to **label** the entry route (`/iteration-start`, `/iteration-loop`, `skill-start`) — "It never authorizes anything". Arming happens **only** inside the `mstar_model_handoff {operation:"start"}` handler, and the authority for it is derived host/engine-side (task-session ledger, the workflow's own session envelopes, the root register), never from the call.
305
+ - `extensions/phase2-orchestration.js` emits its bounded advisory **only after** a recorded `bind`; `{operation:"checkpoint"}` likewise requires a live binding.
306
+
307
+ Enabling `modelHandoff` or `phase2PlanInstances` in `/settings` **never retro-arms or retro-binds** an iteration already under way (the preference is re-read at entry *and* again at fire time), and disabling it suppresses the action without terminalizing the binding. A coordinator that never calls therefore produces **no state and no signal at all** — not a refusal, not a warning, not a log line. That silence is the failure mode this anchor contract fixes: both mechanisms shipped with zero PM call sites in the load chain, so every anchor below is an explicit **required** call, never something the host does for the PM.
308
+
309
+ ### Anchor declarations
310
+
311
+ | Anchor | Call (exact) | When | Prerequisite | Required |
312
+ |---|---|---|---|---|
313
+ | `iteration-entry` | `mstar_model_handoff {operation:"start", workflowId}` | once the workflow is registered and its id is known — the PM's first preparation action that can name it (`phase-1-prepare.md` §1.5 tail); never before the register step | native `modelHandoff` enabled; an explicitly named workflow id; this session is that workflow's coordinator | **required** — the call itself is unconditional; the arm inside it is conditional |
314
+ | `phase-1-lock` | `mstar_model_handoff {operation:"phase1-complete", workflowId, coordinatorSessionPath, mainWorktreeBranch, reviews[], plans[]}` | Phase 1 completion — after the integration checkout exists, the reviewed changes are committed there and that branch is pushed (§2.3 integration-worktree checklist tail); the compass/PM lock alone is **not** ready and not the moment | a `pending` binding from `iteration-entry` **and** the four Phase-1 readiness facts | **required** — never a silent skip |
315
+ | `phase-2-entry` | `mstar_phase2 {operation:"bind", workflowId, coordinatorSessionPath}` | the **Phase 2 execute/resume entry** — immediately before the per-plan loop (§2.4), after the §2.0 gates; also required on a no-argument `/iteration-drive` resume. **Not** the Phase-1-reused integration-worktree step (§2.3), which triggers nothing | accepted phase `phase-2-execute`; a `coordinator`-role session envelope; the caller's checkout = main worktree or the recorded integration worktree | **required** |
316
+ | `rescheduling-checkpoint` | `mstar_phase2 {operation:"checkpoint", reason, decision, note}` | **one call per** `Rescheduling checkpoint` re-evaluation (§2.4), including every settle notification | a live `phase-2-entry` binding in this session | **required** per re-evaluation — never batched, never skipped |
317
+
318
+ #### `iteration-entry` — `mstar_model_handoff {operation:"start", workflowId}`
319
+
320
+ - **Exact parameters**: `workflowId` (string, required) — the only field a caller supplies that matters here; `coordinatorSessionPath` / `mainWorktreeBranch` are accepted by the schema but unused on this path. Authority, entry route, intent and task-session state are host-derived, never call-declared.
321
+ - **When**: once the workflow is registered to the v2 status surface and its **id is known** (`mstar-iteration/references/phase-1-prepare.md` §1.5 tail) — the PM's first preparation action that can name it. Never at the head of §1.1: the id does not exist yet, and the id must name a registered workflow so its coordinator envelope exists.
322
+ - **Required or optional**: **required** and unconditional — make the call even when the preference is off, because `preference-off` is then the expected non-fatal answer and its absence from the ledger is what makes the silence undiagnosable. One call per iteration; a second arm of the same workflow is refused.
323
+ - **No-op refusals** (visible in the tool result, **nothing changed**, model unchanged — not failures to fix beyond the stated cause): `preference-off` (not an error) · `already-bound` · `suspended` (state `none`; a navigation is in flight, retry in a moment) · `in-flight` / `arm-in-flight` (a previous handoff action is still running).
324
+ - **Authority refusals** (this session is not the iteration coordinator — fix the session, not the call; no model action, no binding written): `task-session` (leaf/subagent session, or a session with no id) · `scoped-plan-route` (the last observed entry was the scoped-plan PM route, which restores a binding and never arms a new one) · `plan-pm-session` · `coordinator-elsewhere` (this session coordinates another workflow, or the workflow belongs to another session) · `envelope-invalid` · `register-invalid` (unreadable or invalid v2 root register / workflow snapshot).
325
+ - **Visible arm failures** (reported as failures; **no automatic retry**): `settings-read-failed` · `record-failed` · `slow-unresolved` · `slow-selection-failed` · `slow-selection-refused` · `arm-evidence-conflict`.
326
+ - **Host-level**: `tool-error` (the tool threw without touching model, ledger or engine state).
327
+ - **Success code**: `armed` (state `pending`) — the coordinator holds it until `phase-1-lock` fires or the handoff is cancelled.
328
+
329
+ #### `phase-1-lock` — `mstar_model_handoff {operation:"phase1-complete", workflowId, coordinatorSessionPath, mainWorktreeBranch, reviews[], plans[]}`
330
+
331
+ - **Exact parameters**: `workflowId` (must equal the bound workflow) · `coordinatorSessionPath` (non-empty string) · `mainWorktreeBranch` (string — the recorded integration branch) · `reviews[]` — **exactly three ordered specialist returns** · `plans[]` — **at least one** bound-plan evidence entry. A missing or wrong-length input is refused, never inferred.
332
+ - **When**: Phase 1 completion — **after** the integration worktree exists (recorded `integration_worktree_path`), the reviewed changes are committed on that checkout and `spec_integration_branch` is pushed: the tail of the §2.3 integration-worktree checklist, whose **step 7** performs that transfer + commit + push (Phase 1 reaches it through `iteration-start` §6). The compass/PM lock alone is **not** the moment — it leaves readiness items 3–4 unmet, so `not-ready` returns, the binding stays `pending`, and no later marker retries it. The call is made once, on the Phase 1 route; a Phase 2 resume that walks the same section must not repeat it — the binding is already terminal, so a repeat call returns `not-pending` (flagged as an error, since no `pending` binding exists any more) and is not required.
333
+ - **Required or optional**: **required**, and never a silent skip — every refusal lands in the tool result, and every state transition additionally as a durable session notice.
334
+ - **Readiness prerequisite (all four, re-checked at fire time)**: the sequential specialist returns for that iteration; the PM-confirmed Prepare gate for every registered plan with `compass status: locked`; a distinct same-repository integration checkout on its recorded branch; a remote tip equal to the validated integration HEAD. `evaluatePhaseGate` is a later-phase gate and is never readiness evidence; a draft compass, a lock alone, a missing checkout or an unpushed commit is not ready.
335
+ - **Refusals that leave the binding `pending`** (fix the stated cause and call again — **nothing was switched**): `not-ready` (carries `codes[]` naming the unmet readiness facts; not an error) · `preference-off` (`modelHandoff` off at fire time; not an error) · `settings-read-failed` (read once before and once after the readiness work) · `suspended` · `in-flight` · `record-failed` · `not-pending` (no binding — run `iteration-entry` first) · `binding-mismatch` (the call names a different workflow) · `invalid-completion-input` (the evidence shape above).
336
+ - **Terminal refusals** (**no retry**; the session keeps the model it actually has): `cancelled` (an unowned model change arrived while pending; not an error) · `target-unresolved` (`handoffTarget` unresolvable) · `switch-refused` / `switch-threw` (the host refused the selection).
337
+ - **Host-level**: `tool-error`. **Success code**: `handed_off` (state `handed_off`, with the actual model reported).
338
+
339
+ #### `phase-2-entry` — `mstar_phase2 {operation:"bind", workflowId, coordinatorSessionPath}`
340
+
341
+ - **Exact parameters**: `workflowId` (must match both the session envelope and the workflow snapshot id) and `coordinatorSessionPath` (the coordinator's own session envelope). The request object is strict — nothing else is accepted, and authority is derived host-side, never from the call: host session id, control harness root, accepted phase and checkout root are all re-read.
342
+ - **When**: the **Phase 2 execute/resume entry** — immediately before the per-plan loop (`## 2.4 Per-plan loop`), after the §2.0 gates and after §2.3's branch/worktree resolution; also required on a no-argument `/iteration-drive` resume. It is explicitly **not** the Phase-1-reused integration-worktree step: Phase 1's `iteration-start` §6 walks §2.3 to create the integration checkout, and that step triggers no anchor (`phase-2-entry` fires only on the Phase 2 route, and `phase-1-lock` fires once at that checklist's tail).
343
+ - **Required or optional**: **required**. It records a session **identity pointer** only — plugin observation binding, not engine `plan bind` — and writes no engine credential and no engine state.
344
+ - **Prerequisite**: the snapshot's accepted phase is `phase-2-execute` (an unknown or missing phase disables the observation) · the envelope role is `coordinator` · the caller's checkout is the main worktree or the recorded integration worktree.
345
+ - **Refusals** (visible; **nothing bound**):
346
+ - `phase2.task-session` — a leaf/subagent (`session_init`) session, or a session with no id.
347
+ - `phase2.plan-pm-session` — a scoped-plan PM envelope: a scoped-plan PM never binds the Phase-2 observation.
348
+ - `phase2.envelope-unreadable` · `phase2.workflow-mismatch` (envelope or snapshot names another workflow) · `phase2.harness-unresolvable` · `phase2.snapshot-unreadable` · `phase2.workflow-terminal` · `phase2.coordinator-mismatch` (the snapshot is bound to a different coordinator envelope) · `phase2.scope-mismatch` (the caller's checkout is neither the main worktree nor the integration worktree) · `phase2.record-failed` · `tool-error`.
349
+ - **Non-failure**: `already-bound` (`applied:false`) — an identical re-bind is idempotent, the pointer is unchanged, and the call is safe to repeat. **Success code**: `bound` (`applied:true`).
350
+ - The tool's other two operations — `reserve-launch` / `record-launch` — are **not** anchor-triggered; their codes are in § Phase-2 plan instances above.
351
+
352
+ #### `rescheduling-checkpoint` — `mstar_phase2 {operation:"checkpoint", reason, decision, note}`
353
+
354
+ - **Exact parameters**: `reason` — **one of the five frozen names, verbatim**: `before-wait`, `result-settled`, `dependency-changed`, `ownership-changed`, `capacity-changed` · `decision` ∈ `dispatched | wait | blocked` · `note` (string, required). The argument schema is a strict union: any other value is rejected before anything is written. The runtime attaches the sampled observation key — the caller cannot choose or reset it.
355
+ - **When**: **one call per** re-evaluation of the shared `Rescheduling checkpoint` (`mstar-iteration/references/phase-2-worktree-lease.md` §2.4) — a call acknowledges that PM ran the shared scheduling procedure against the sample taken at that moment.
356
+ - **Required or optional**: **required** per re-evaluation — never batched into the next one, never skipped because "nothing changed". A checkpoint carries a decision and a note, never a ready list.
357
+ - **Prerequisite**: a live `phase-2-entry` binding in this session; the ownership probe is re-run on every call.
358
+ - **Refusals** (visible; **no checkpoint recorded**, advisory state unchanged): `phase2.not-bound` (run `phase-2-entry` first) · `phase2.record-failed` · `tool-error`, plus the ownership-probe codes shared with `bind`: `phase2.envelope-unreadable` · `phase2.ownership-drift` (the envelope or snapshot no longer belongs to the bound session — re-run `bind`) · `phase2.harness-unresolvable` · `phase2.snapshot-unreadable` · `phase2.workflow-mismatch` · `phase2.workflow-terminal` · `phase2.phase-inactive` (the workflow left `phase-2-execute`). Both stale codes mark the local binding not-current and tell the PM to re-run `{operation:"bind"}` before relying on this session.
359
+ - **Success code**: `recorded` (with the returned `observationKey` and `blocked` flag; `blocked` suppresses advisory continuation until a new explicit user turn or a later checkpoint — never a timer or incidental snapshot churn).
360
+ - **Not checkpoint refusals** — the advisory path's own sample refusals are `phase2.snapshot-unavailable` (a `null` snapshot means "unavailable", never "no jobs") and `phase2.settings-read-failed` / `phase2.invalid-settings` (the native settings read failed, or a present-but-malformed key fails visibly).
361
+
223
362
  ## Files, shell, and approvals
224
363
 
225
364
  - Prefer host search/edit tools over shell find/sed when available.
@@ -28,6 +28,9 @@ Harness **dispatch** on OpenCode = **one or more `task` tool calls**, each with
28
28
  | `Execute as: <role-id>` | **`subagent`** on **task tool** = same agent id |
29
29
  | Parallel batch **N** | **N task tool** calls in **one assistant message** when the host allows (`parallel-dispatch.md`) |
30
30
 
31
+ **Role-binding field:** **`subagent`** on the **task tool** (singular — there is no batch array here); it must equal the Assignment `Execute as`.
32
+ **Engine scope (#156):** OpenCode exposes no dispatcher identity, so the caller-scoped `antiRecursionPrecheck` leg is **skipped** on this host — the binding field carries the **spawn target**, and target == `Execute as` is the compliant C5 pattern — and the red line stays **prompt-level** (`mstar-dispatch-gates` § 承接方反递归红线). Caller-side hard enforcement exists only where the host declares a dispatcher binding (`dsh.md`).
33
+
31
34
  PM workflow: finalize Assignment → **call task tool** with **subagent** + generated prompt → wait for subagent Completion Report → update plan / status.
32
35
 
33
36
  **SDD sticky implementer:** if the task tool exposes **resume** / agent id, follow **`mstar-sdd/references/sticky-implementer-session.md`** and the active host reference. If resume is **not** available, use **micro-batch** (2–3 tasks, one invoke) or **`SDD implementer session: fresh`** per task — do not assume sticky without host support.
@@ -69,6 +69,9 @@ ZCode C5/C5b SSOT is **this file** — do **not** load `_shared/host-role-bindin
69
69
 
70
70
  Paste-only Assignment **without** an invoke call is **not** dispatch. Anti-recursion NEVER: leaf executors are already `Execute as` — no recursive invoke of the same role; Assignment wins (`Delegation: forbidden` unless stated). Independent ready implementers may run concurrently after isolation; scheduling → **`parallel-dispatch.md`** § SDD implement.
71
71
 
72
+ **Role-binding field:** **`subagent_type`** — the bare Morning Star role id per C5 (`general-purpose` / `Explore` fallbacks); the thin role shell still needs the C5b prompt binding above.
73
+ **Engine scope (#156):** no engine dispatch gate observes caller identity here (the binding field carries the **invoke target**, not the dispatching seat), so this red line stays **prompt-level** (`mstar-dispatch-gates` § 承接方反递归红线). Caller-side hard enforcement exists only where the host declares a dispatcher binding (`dsh.md`).
74
+
72
75
  ZCode invoke shape (same turn):
73
76
 
74
77
  ```text
@@ -99,7 +99,7 @@ Phase 6: post-merge close —— PR merged 后 §6.1–§6.4
99
99
  - 实际 Git ≠ `working_branch` → **同轮**更新 plan + snapshot + `execution_lease.working_branch`(如适用)
100
100
  - **跨 plan implement 并行安全闸**与 **integration merge 串行** → `references/phase-2-worktree-lease.md` §2.0 #5 /「Multi-plan parallelism」(**无论** `Worktree mode: waived`)
101
101
  - plan 内 SDD 独立 ready tasks **并行**,真实依赖与共享写目标串行 — phase-2 reference §2.4、§2.5、`mstar-sdd` Ready-task scheduling
102
- - **zero-residual(默认)**:单 plan QC findings 尽量当轮清干净;仅真 blocker 才 defer(须 Durable Roadmap)— 见 **`mstar-artifacts`** Findings cleanup modes
102
+ - **allow-residual(默认)**:open R# 先登记 project register,且各决策面披露(清单 + severity + 跟踪位置;close 面另含 blocker-defer 标记);unresolved `critical` 仍阻断 Approve;`zero-residual` 为显式 opt-in(可修当轮清干净,仅真 blocker-defer + Durable Roadmap)— 登记与披露职责 → **`mstar-artifacts`** Findings cleanup modes
103
103
  - iteration 命令共享的 PM invariants / preflight / todos / STOP → **`references/command-shared-invariants.md`**
104
104
 
105
105
  **Push cadence(§5.1a HARD)**:本地可提前修,**禁止**在 CI / AI review 波次未结束时 `git push` — 细则 → `references/phase-4-5-pr-delivery.md` §5.1a。
@@ -54,6 +54,8 @@ if command -v mstar-harness >/dev/null 2>&1; then mstar-harness dispatch validat
54
54
  | `phase-5-pr-merge-ready` | Phase 4 完成后 | Phase 5 §5.5 exit 全 `[x]` |
55
55
  | `phase-6-post-merge-close` | §5.2 exit 后 PR **已 merge**(mergeable ≠ merged) | Phase 6 §6.1–§6.4 完成(`mstar status workflow-close --workflow <id>` exit 0 + 投影一致) |
56
56
 
57
+ Phase/gate 转换时按 **`mstar-host`**「Phase-transition todo refresh (host-agnostic)」按上表刷新会话 todos:先按 snapshot / plan 证据勾掉已完成 phase 条目,保留未决 gate / 未来 phase 条目,再追加下一 phase 条目;todos 只是投影,不授权状态转换。
58
+
57
59
  ## Continuous execution STOP list(重叠行;start / drive / loop 共有)
58
60
 
59
61
  Execute **`mstar-iteration` §2.6**(Continuous execution SSOT:自 Phase 2 进入至 Phase 5 §5.5 exit 前 PM **连续编排**,进度汇报后下一条必须是 dispatch 或下一 phase 步骤,不向用户例行 yes/no check-in)。
@@ -124,6 +124,13 @@ iteration 正式全流程**必须**登记 `{HARNESS_DIR}/status.json`(v2 根
124
124
 
125
125
  compass frontmatter 的 `iteration_base_branch` / `target_branch` **必须与** snapshot `branch` 一致;若仅写在 compass 而 snapshot 缺失,Phase 2 §2.3 同轮 backfill。
126
126
 
127
+ **中途增减范围(已存在且仍在 Prepare 的 workflow)**:用户/产品批准的范围扩张**不得**手改受保护状态。先以 `mstar plan bind --coordinator --workflow <id>` 建立该 workflow 的 coordinator 会话,再经受守卫入口 `mstar workflow show-prepare` 读取快照与 compass 两个字节版本,并以 `mstar workflow amend-prepare` 追加已批准的 Todo 行、登记已 review 的 integration checkout 与 `plan_parallelism`(仅 Prepare 且无执行所有权时可用;无 force/replace/init 通道)。守卫与字段权威 → **`mstar-artifacts`** `references/status-and-residuals.md`「Prepare workflow amendment」;forms / exit codes → `docs/cli.md` § `mstar-harness workflow`。
128
+
129
+ <!-- host-hook: iteration-entry -->
130
+ > Execute the active host reference's `## Host hooks` declaration for `iteration-entry`; this file defines no host action.
131
+ >
132
+ > 本 anchor 只在 workflow 已登记到 v2 状态面(本条完成)**且其 id 已知**之后执行 —— 登记之前没有可用的 workflow id。
133
+
127
134
  ## 1.5.5 产物边界(specs · iterations · knowledge)
128
135
 
129
136
  Phase 1 与 §1.6 须遵守 **`references/iteration-artifact-boundaries.md`**(HARD):
@@ -148,10 +155,12 @@ Phase 1 与 §1.6 须遵守 **`references/iteration-artifact-boundaries.md`**(
148
155
  2. **writing-specialist** 完成 **corpus hygiene**:仅本轮修改的 `{SPECS_DIR}/` / iteration package 与直接相关 knowledge 引用;错放迁回 **`<iteration-id>/`** package;细则 → **`iteration-corpus-hygiene.md`**、**`iteration-artifact-boundaries.md`**
149
156
  3. PM 将 compass `status` 设为 `locked`,并确认各 plan 的 Prepare gate(specify / clarify / plan)
150
157
 
151
- **顺序理由**:产品范围与优先级 → 架构与长期契约(specs)→ 行文、规格库卫生与错放纠正(在 PM/architect 定稿后核对受影响文档)。本共享产物链存在真实依赖;独立文档可按 ownership 隔离并行。早期全局探索的既有结果复用,不因每次编辑重新扫全库。OpenCode:plain role id — **`mstar-host/references/opencode.md`** § Role-mention hygiene。
158
+ **顺序理由**:产品范围与优先级 → 架构与长期契约(specs)→ 行文、规格库卫生与错放纠正(在 PM/architect 定稿后核对受影响文档)。本共享产物链存在真实依赖;独立文档可按 ownership 隔离并行。早期全局探索的既有结果复用,不因每次编辑重新扫全库。角色名写法(role id 提及 hygiene)→ active host reference(**`mstar-host`** → `references/<host>.md`)。
152
159
 
153
160
  **完成证据** = 磁盘上的 compass / plans / specs / iteration 文档修订 + specs(与既有 knowledge)卫生/归档(如有)+ 索引与 metadata 更新 + compass `status: locked`。**不**要求单独的迭代审查报告——迭代审查的 SSOT 是被编辑的文档本身,无 per-plan QC 式审计链。
154
161
 
155
- **Uncommitted-docs exception(bounded — Phase 1 only)**:Review & Edit 链的文档编辑(compass / plans / specs / `<iteration-id>/` package)可以**未提交**状态落在主 checkout(control root = 主 worktree)——这是 worktree 默认在 Phase 1 的唯一例外,主 checkout 分支**不**切换、不产生 feature commit。**§6 创建 integration worktree 后**:只把**已 review 的本轮文档改动** transfer 到 integration worktree 并在其上 commit(tracked results 写在目标分支所在的检出),随后恢复主 checkout 上对应的未提交文档改动(不切分支);**禁止**搬运主 checkout 上无关的既有用户改动。
162
+ **Uncommitted-docs exception(bounded — Phase 1 only)**:Review & Edit 链的文档编辑(compass / plans / specs / `<iteration-id>/` package)可以**未提交**状态落在主 checkout(control root = 主 worktree)——这是 worktree 默认在 Phase 1 的唯一例外,主 checkout 分支**不**切换、不产生 feature commit。该例外在 **§6 的 integration-worktree 步骤**结束,其 transfer / commit / restore 序列的**唯一 home** 是 **`phase-2-worktree-lease.md` §2.3 checklist step 7**:只搬运**已 review 的本轮文档改动**,commit 落在 integration checkout,主 checkout 上对应的未提交改动随后恢复(不切分支);**禁止**搬运主 checkout 上无关的既有用户改动。
156
163
 
157
164
  **反模式**:PM 线程代替三角色完成全部编辑而不 invoke;或将本链三角色并行派发 —— 见 **`mstar-roles/references/_shared/leaf-executor-core.md`**「Shared anti-recursion NEVER」。
165
+
166
+ **Phase 1 完成 anchor(`phase-1-lock`)不在本文件触发**:compass `status: locked` 只是它的前置之一 —— 它只在 integration worktree 已建立(并记录 `integration_worktree_path`)、已 review 的改动在该 checkout 上 commit、且 `spec_integration_branch` 已 push 之后才执行,因此其 marker 由 **`phase-2-worktree-lease.md` §2.3**「Integration worktree (Phase 2 entry) + control root」checklist tail 承载(Phase 1 路线经 `iteration-start` §6 走到该 checklist)。
@@ -22,13 +22,13 @@ serial cross-plan **implement** scheduling while the worktree + lease gates rema
22
22
  required.
23
23
 
24
24
  Phase 1 Review & Edit may edit uncommitted docs on the primary checkout under the Prepare policy (bounded exception; the main worktree never switches branch). The integration-worktree + lease gate
25
- starts at **Phase 2 entry**.
25
+ starts at **Phase 2 entry** — Phase 1 did walk §2.3's integration-worktree checklist once at its end (`iteration-start` §6, which carries the `phase-1-lock` marker), but the gate those steps guard opens only when Phase 2's per-plan loop begins.
26
26
 
27
27
  **Phase scope**:本参考仅约束 **Phase 2**(含 serial integration merge 与「control root / integration worktree 禁止产品编辑 / 每 plan feature worktree」)。**Phase 5** PR merge-ready 修复同样 **不**直接在 integration checkout 上改——产品修复走独立 fix feature worktree,review 后 merge 回 integration worktree → **`phase-4-5-pr-delivery.md`** §5.0。
28
28
 
29
29
  **本 Phase 定义 per-plan 派发循环的完整流程**:前置条件检查、session todos、backlog 读取、integration 分支管理、per-plan dispatch 循环(分支→实现→QC→**QA gate**→Done→合并)、dispatch-first 约束。PM 读取本 Phase(含 §2.0–§2.5 与下方 lease 细则)即可执行迭代。
30
30
 
31
- **Findings cleanup(默认)**:Phase 2 每个 plan Assignment 默认 **`Findings cleanup: zero-residual`**(可修 findings 当轮 fix→re-review 清干净;仅真 blocker-defer + Durable Roadmap 可留 open R#,`critical` 不属 defer)。compass 或 Assignment 可显式覆写为 `allow-residual`。SSOT → **`mstar-artifacts`**「Findings cleanup modes」。
31
+ **Findings cleanup(默认)**:Phase 2 每个 plan Assignment 默认 **`Findings cleanup: allow-residual`**(open R# 先登记 project register,再离 InReview;各决策面披露 id/severity/跟踪位置;unresolved `critical` 仍阻断 Approve)。compass 或 Assignment 可显式覆写为 `zero-residual`(可修 findings 当轮 fix→re-review 清干净;仅真 blocker-defer + Durable Roadmap 可留 open R#,`critical` 不属 defer)。登记与披露职责 SSOT → **`mstar-artifacts`**「Findings cleanup modes」。
32
32
 
33
33
  ## 2.0 前置条件(五道闸)
34
34
 
@@ -46,16 +46,16 @@ starts at **Phase 2 entry**.
46
46
 
47
47
  ## 2.1 Session todos(派发前设护栏)
48
48
 
49
- 每个 plan wave 启动前设定 host todos,防止范围漂移:
49
+ 每个 plan wave 启动前设定 host session todos,防止范围漂移(具体 todo / plan UI 工具名 → active host reference):
50
50
 
51
- | Host | 工具 | 最小集合 |
52
- |------|------|---------|
53
- | **Cursor** | `TodoWrite` / CreatePlan todos | 当前 `plan_id`;下一批 gates(implement/QC/**QA gate**);分支 checkpoint;**仅剩 1 个非 Done plan 时追加 `phase-3-iteration-close`**(open 直至 §3.5);Phase 4 后 **`phase-5-pr-merge-ready`**(open 直至 §5.5) |
54
- | **Codex** | `update_plan` / Goal UI | 同上 |
55
- | **OpenCode** | host todo/plan UI(如有) | 同上 |
51
+ | 宿主会话 | 工具 | 最小集合 |
52
+ |----------|------|---------|
53
+ | 任意宿主(有 session todo / plan UI 时) | 宿主自身的 session todo / plan UI | 当前 `plan_id`;下一批 gates(implement/QC/**QA gate**);分支 checkpoint;**仅剩 1 个非 Done plan 时追加 `phase-3-iteration-close`**(open 直至 §3.5);Phase 4 后 **`phase-5-pr-merge-ready`**(open 直至 §5.5) |
56
54
 
57
55
  SSOT = `{WORKFLOW_DIR}/<id>/snapshot.json` + `{PLAN_DIR}/`。todos 只追踪本轮下一步。
58
56
 
57
+ Phase/gate 转换时按 **`mstar-host`**「Phase-transition todo refresh (host-agnostic)」刷新:先按 snapshot / plan 证据勾掉已完成条目,保留未决 gate 条目,再追加下一批条目;todos 只是投影,不授权状态转换。
58
+
59
59
  **Scoped route**:todos 是 **plan-local 任务列表**(本 plan 的 task / gate),**不**追加 `phase-3-*` / `phase-4-*` / `phase-5-*` / `phase-6-*`;scoped finish = handoff → **`plan-scoped-pm.md`** §4–§5。
60
60
 
61
61
  ## 2.2 Read backlog
@@ -68,6 +68,8 @@ SSOT = `{WORKFLOW_DIR}/<id>/snapshot.json` + `{PLAN_DIR}/`。todos 只追踪本
68
68
 
69
69
  ## 2.3 Branch anchors + integration branch + integration worktree(Phase 2 入口)
70
70
 
71
+ 本节的 integration-worktree checklist **也被 Phase 1 路线复用**(`iteration-start` §6)—— 在该路线上它承载 `phase-1-lock` marker,且**不**触发 `phase-2-entry`。
72
+
71
73
  **Branch anchors 解析顺序**(任一环节缺失则 STOP,**禁止**默认 `main`/`master`):
72
74
 
73
75
  1. workflow snapshot → `branch.base`(`iteration_base_branch`)、`branch.target`(`target_branch`)、`branch.integration`(`spec_integration_branch`);plan 行 → `metadata.spec_integration_branch`
@@ -112,6 +114,22 @@ SSOT = `{WORKFLOW_DIR}/<id>/snapshot.json` + `{PLAN_DIR}/`。todos 只追踪本
112
114
  - plans SSOT: `<main-repo-root>/{PLAN_DIR}/`
113
115
  - iterations SSOT: `<main-repo-root>/{ITERATION_DIR}/`
114
116
  - SDD tree: `<main-repo-root>/{HARNESS_DIR}/sdd/<plan-id>/`
117
+ 7. **Phase 1 route — publish.** Transfer only the reviewed Phase 1 changes into
118
+ this integration checkout, commit them there and push `spec_integration_branch`:
119
+ the changes come **from** the primary checkout, while the commit and the push
120
+ happen **in the integration worktree**; afterwards restore the primary
121
+ checkout's corresponding uncommitted docs without switching its branch
122
+ (Phase-1 bounded exception → `phase-1-prepare.md` §1.6; never carry unrelated
123
+ user changes).
124
+ **Every Phase 2 entry — first execute and resume alike, including the first
125
+ entry after an auto-continued Phase 1 (which has already published) — never
126
+ publishes again**: verify the checkout instead (branch =
127
+ `spec_integration_branch`, clean tree, remote tip already equal to the live
128
+ integration HEAD), do **not** re-publish, and do **not** repeat the
129
+ `phase-1-lock` anchor below — its binding is terminal by then (repeat-call
130
+ semantics and refusal codes → active host reference). On the Phase 1 route the
131
+ anchor instead requires that pushed remote tip to equal the live integration
132
+ HEAD, so it must not be executed before this step's publish.
115
133
 
116
134
  All sessions MUST reread the **control-root copy** of the workflow snapshot immediately before
117
135
  claim, release, transfer, plan-status transition, or merge-lease mutation.
@@ -121,6 +139,11 @@ claim, release, transfer, plan-status transition, or merge-lease mutation.
121
139
  control **`Plan Path`** / **`SDD dir`** in Assignments
122
140
  (`mstar-branch-worktree` 「Harness path SSOT under default gitignore」).
123
141
 
142
+ <!-- host-hook: phase-1-lock -->
143
+ > Execute the active host reference's `## Host hooks` declaration for `phase-1-lock`; this file defines no host action.
144
+ >
145
+ > **`phase-1-lock` 恰好触发一次**:只在 **Phase 1 路线**、且在 checklist **step 7 的 publish**(transfer → commit → push `spec_integration_branch`)之后 —— 该 anchor 的就绪合取要求已 push 的 remote tip 等于 live integration HEAD,因此**不得**在 step 7 之前执行。此后任何**再次走过 §2.3 的路线**(Phase 2 entry 首次 execute 或 resume,包括 auto-continue 进入的第一次 Phase 2 entry)都**不**触发它:那时 binding 已 terminal,也**不**需要重新调用(精确的重复调用语义与拒绝码 → active host reference)。
146
+
124
147
  ### Same-host exclusive write lock
125
148
 
126
149
  All control-path lease mutations (claim, release, transfer, merge-lease
@@ -175,11 +198,52 @@ mismatch → **STOP**.
175
198
 
176
199
  > **Lease Engine-check:** canonical callout lives in `mstar-artifacts` `SKILL.md`(Engine-check lease 行)— this file carries the execution checklist only.
177
200
 
201
+ <!-- host-hook: phase-2-entry -->
202
+ > Execute the active host reference's `## Host hooks` declaration for `phase-2-entry`; this file defines no host action.
203
+ >
204
+ > 这是 **Phase 2 execute/resume entry**:§2.0 五道闸与 §2.3 的 branch / worktree 解析之后的第一个 Phase 2 动作,位于 per-plan loop 之前。Phase 1 的 `iteration-start` §6 只**复用** §2.3 的 integration-worktree 步骤,**不**触发本 anchor。
205
+
178
206
  ## 2.4 Per-plan loop(直到全部 Done)
179
207
 
180
208
  **跨 plan 默认**(**无论** `Worktree mode: waived`):**不同 `plan_id` 可并行 implement** 须满足 §2.0 #5 跨 plan 并行安全闸——(a) coordination 路径 same-host 独占写锁可用且每次 status/协调变更持锁,或 (b) **`Plan parallelism: serial`**(waived 时默认),或 (c) 用户本轮 `Cross-host lease race: accepted` + audit `notes`;否则 Assignment 仍写并行 → **Blocked**。**merge 入 `spec_integration_branch` 仍串行**(snapshot 顶层 `integration_merge_lease`;waived 时无 merge lease 仍须串行 merge)。未 waive 时 **禁止**无 verified `execution_lease` 的跨 plan 可写派发。
181
209
 
182
- 对每个本轮要推进的 active `plan_id`(可交错/并行,非强制 plan A 全 Done 再 plan B):
210
+ ### Rescheduling checkpoint(主动调度检查点)
211
+
212
+ <!-- host-hook: rescheduling-checkpoint -->
213
+ > Execute the active host reference's `## Host hooks` declaration for `rescheduling-checkpoint`; this file defines no host action.
214
+
215
+ Phase 2 缺的不是新调度器,而是一个**具名的重新评估时刻** —— `Rescheduling checkpoint` 就是它。本文件是 procedure 的**唯一 home**:**不**新增 scheduler / DAG / 第二 ready-state register,判断仍由 PM 按下列步骤做出,结果只落在 PM 正常 transcript / ledger。
216
+
217
+ **五个冻结 reason**(checkpoint 触发词;宿主若在 `rescheduling-checkpoint` 锚点声明 receipt,消费的是**同一词汇** —— 该 receipt 只记录「已按本 procedure 评估」的事实 + decision/reason,**不**推断依赖就绪、**不**选择派发;**禁止**自造同义词 —— 锚点契约 → **`mstar-host`**「Host hooks (anchor contract)」):
218
+
219
+ | reason | 触发时刻 |
220
+ | --- | --- |
221
+ | `before-wait` | 进入任何 wait **之前** |
222
+ | `result-settled` | 结果落定后:子任务完成、review 返回,或消费已返回结果 |
223
+ | `dependency-changed` | 依赖事实变化(例如已审 prerequisite 已进入 dependent 的 assigned base) |
224
+ | `ownership-changed` | ownership 事实变化(lease claim / release / transfer、handoff / accept、作用域 holder 变化) |
225
+ | `capacity-changed` | 容量事实变化(槽位因完成释放、primary 起停、可选 transport 可用性变化) |
226
+
227
+ **决策步骤**(每次 checkpoint 按序执行):
228
+
229
+ 1. **用户 steering 与真实 blocker 优先于**任何调度续行;已返回结果**只消费一次**并判定其 acceptance —— **禁止**把 job completion 当作 accepted work。
230
+ 2. **确定作用域**:iteration coordinator 同时考虑其**已准备的独立 plan** 与 plan 本地 task;scoped plan primary 只考虑**自己的 tasks**(`plan-scoped-pm.md`)。任一方都**不得**把自己提升为对方的权限。
231
+ 3. **排除不可派发项**:已派发 / 已有 owner / 已终结 / 未准备 / 契约已漂移 / 真依赖未满足。prerequisite 仅在**已审 / 已接受 commit 进入 dependent task 的 assigned base** 时才满足(`mstar-sdd` § Dependent-task readiness)。活动 Assignment 的 scope 与 `BASE_SHA` **不可变**;**仅未派发**工作可 re-split / 重排,且依赖 / 接口变化须在派发前写回。
232
+ 4. **对剩余有用工作套用约束**:当前用户 / plan 的 serial 策略、task 容量、plan-primary 容量、engine scope / revision / lease 校验、same-host 锁与 L1/L2 隔离(首段 §2.0 #5)。**成立的具体串行边**:共享文件 / session / ledger、缺集成接口;**不成立**:task 编号、无关的 QC / QA。
233
+ 5. **启动完整已授权 ready batch**:默认传输是**原生 background task** —— transport 被禁用 / 不可用**不**关闭 task 并发;已准备的独立 plan 可走条件性 primary transport。只有 coordinator 的 integration merge 串行。
234
+ 6. **没有有用且已授权动作 → native wait 一次**,并写下真实 wait reason:`dependency` / `ownership` / `capacity` / `user-blocked` / `no-ready-work`。
235
+
236
+ **结果记录**:正常 PM transcript / ledger 的一行即可 —— checkpoint reason、考虑过的作用域、已派发 ID 或具体 wait / block reason。**禁止**:重复完成投递、tick 计数、「still waiting」报告、对**不变的空 ready 集合**反复自证或重跑同一推理、为保持忙碌而造工作、timer / 轮询循环。等待是合法结论 —— 同一组未变事实**只陈述一次**;只有新事实(显式用户消息、新的已接受结果、dependency / ownership / capacity 观察变化)才重新打开 checkpoint,「turn 结束」不是理由。
237
+
238
+ **checkpoint 不放宽任何既有安全条件**:
239
+
240
+ - 原生 background task 仍是默认 task 传输;额外 primary 是可选 plan 级工具,只受其自身配置 gate。
241
+ - `ctx.isIdle()` 仅表示未在流式输出,**不**代表没有未落定的 task / bash / eval job 或 plan primary;native adaptive wait 与 completion delivery 仍由宿主控制,**禁止**自建轮询替代。
242
+ - lease / revision / ownership 语义不变:**禁止**重复 owned / running / completed 工作、偷 lease、改活动 base;pane idle / age / 终端标签**不是** ownership 或完成依据(§ Execution lease · Hold, release, override)。
243
+ - integration merge 入 `spec_integration_branch` 仍**串行**;跨 plan 并行仍受本节首段跨 plan 安全闸约束。
244
+ - `execution_policy` 取值(如 `serial`)是 accepted-but-opaque:**禁止**描述为引擎强制的线性调度器;实际策略从当前用户 / plan 推导,并保留显式 serial 约束。
245
+
246
+ 对每个本轮要推进的 active `plan_id`(**可交错 / 并行**是默认读法:非强制 plan A 全 Done 再 plan B,plan 编号或 task 编号本身都不是串行理由):
183
247
 
184
248
  1. **Claim / resume — execution lease**(§2.0 #5 未 waive):按下方「Execution lease」claim/resume 规则——同 `holder` → resume(校验 `worktree_path` / `working_branch` 与 Assignment 一致);异 `holder` → **Blocked**;`InProgress` 无 lease → **STOP** 升级(孤儿恢复 → **`mstar-artifacts`**);verify 通过前 **禁止**可写派发。**Scoped route**:fresh claim 的唯一入口是 `mstar plan bind`(`--assignment` / `--workflow --plan`)——同 plan 的第二个 fresh 形态 → `coordination.duplicate-holder`;续接只经 `mstar plan bind --resume`,且为**只读校验**(不重新获取 ownership、不重启执行、不改 revision;无自动 attach / fallback plan / TTL 夺取)。
185
249
  2. **Plan start — feature worktree + branch**:创建/校验 dedicated feature worktree(默认 `<repoRoot>/.worktrees/<plan-id>-<slug>`);Assignment 须含绝对 `Worktree path` + `Working branch`(与 lease 一致)。plan 内多可写并行轨 → **`mstar-branch-worktree`** **`references/parallel-writable-pre-dispatch.md`**
@@ -247,7 +311,7 @@ Iteration Phase 2 附加:
247
311
  - PM **NEVER** 在 PM 线程实现产品代码(delegate dev;hotfix 例外见 **`mstar-phase-gates`**)
248
312
  - `Subagent invokes issued: 0` 而 Assignment 已写出 → **`dispatch incomplete`**;下一条补发 invoke,禁止 PM 顶替
249
313
  - QC 初轮:**SDD → N=3**;**inline → N=1**;plan QC tri 三席 **同条消息 N=3**(非 implement 轨数)
250
- - **`Findings cleanup: zero-residual`(默认)**:QC 后可修 Warning/Suggestion → 继续 fix→targeted re-review,直至 clean `Approve` 或仅剩真 blocker-defer(`critical` 不属 defer —— 定义 → **`mstar-artifacts`**「Findings cleanup modes」);**禁止**把可修项登记为 open residual 草草 `Approve with residuals`
314
+ - **`Findings cleanup: allow-residual`(默认)**:open R# 先登记 project register,且各决策面披露(清单 + severity + 跟踪位置;close 面另含 blocker-defer 标记),`Approve with residuals` 仅当无 unresolved `critical`;`zero-residual` 仍为显式 opt-in —— QC 后可修 Warning/Suggestion → fix→targeted re-review 直至 clean `Approve` 或仅剩真 blocker-defer(`critical` 不属 defer —— 定义与登记/披露职责 → **`mstar-artifacts`**「Findings cleanup modes」)
251
315
 
252
316
  ## Feature worktree (per plan)
253
317