@mstar-harness/opencode 1.5.3 → 1.5.5
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 +12 -0
- package/harness-skills/mstar-branch-worktree/SKILL.md +20 -4
- package/harness-skills/mstar-dispatch-gates/SKILL.md +2 -1
- package/harness-skills/mstar-harness-core/SKILL.md +1 -0
- package/harness-skills/mstar-host/references/cursor.md +79 -1
- package/harness-skills/mstar-host/references/parallel-dispatch.md +1 -1
- package/harness-skills/mstar-iteration/SKILL.md +9 -4
- package/harness-skills/mstar-iteration/references/phase-2-worktree-lease.md +17 -4
- package/harness-skills/mstar-plan-artifacts/references/status-and-residuals.md +1 -1
- package/harness-skills/mstar-plan-conventions/SKILL.md +2 -0
- package/harness-skills/mstar-roles/references/project-manager/dispatch-and-assignment.md +16 -3
- package/harness-skills/mstar-roles/references/project-manager.md +1 -0
- package/harness-skills/mstar-sdd/SKILL.md +2 -2
- package/harness-skills/mstar-sdd/references/file-handoffs.md +4 -0
- package/harness-skills/mstar-sdd/scripts/sdd-workspace +69 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to the `@mstar-harness/opencode` package are documented in t
|
|
|
4
4
|
|
|
5
5
|
The monorepo root [CHANGELOG.md](../../CHANGELOG.md) summarizes cross-surface releases.
|
|
6
6
|
|
|
7
|
+
## 1.5.5
|
|
8
|
+
|
|
9
|
+
- Version alignment with harness **1.5.5** (bundled skills: control-path harness under default gitignore + `sdd-workspace` `MSTAR_CONTROL_ROOT`).
|
|
10
|
+
|
|
11
|
+
See root [CHANGELOG.md](../../CHANGELOG.md) **1.5.5**.
|
|
12
|
+
|
|
13
|
+
## 1.5.4
|
|
14
|
+
|
|
15
|
+
- Version alignment with harness **1.5.4** (bundled skills/commands: Cursor Task flat invoke schema in `mstar-host`).
|
|
16
|
+
|
|
17
|
+
See root [CHANGELOG.md](../../CHANGELOG.md) **1.5.4**.
|
|
18
|
+
|
|
7
19
|
## 1.5.3
|
|
8
20
|
|
|
9
21
|
- Version alignment with harness **1.5.3** (bundled skills/commands: frontmatter YAML quotes + `/iteration-loop` scale `XL`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mstar-branch-worktree
|
|
3
|
-
description: "Morning Star business-repo Git feature branches, worktree isolation layers **L1** (iteration cross-plan — control worktree + per-plan feature worktrees + `execution_lease
|
|
3
|
+
description: "Morning Star business-repo Git feature branches, worktree isolation layers **L1** (iteration cross-plan — control worktree + per-plan feature worktrees + `execution_lease`; under default gitignore, process harness SSOT via absolute control paths — plans/iterations/status/sdd — while product edits stay on the feature worktree; do not waive worktree because feature lacks plans) and **L2** (within-plan — `references/parallel-writable-pre-dispatch.md`; N parallel Task invokes do NOT satisfy isolation), plan/Spec integration branches, and QC/QA checkout alignment (`Review cwd`, `Working branch`, `plan_id`, `Review range` / `Diff basis` must match verbatim across three QC reviewers and QA). Read when PM writes `Working branch` / `Branch policy`, iteration Phase 2 control vs feature worktree paths, dispatches ≥2 concurrent writable implement tracks on one repo, `Worktree isolation: required`, two or more writable streams touch one repo, dispatching QC tri-review or QA after merging to a single `HEAD`, dev/QA/ops before first `git commit`, or explaining worktree paths. Required for `project-manager` parallel implement or pre-QC orchestration; `fullstack-dev*` / `frontend-dev` / `qa-engineer` / `ops-engineer` on repo writes; `qc-specialist*` before review. Does not replace the state machine (`mstar-harness-core`)."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## Load order(必读顺序)
|
|
@@ -121,16 +121,32 @@ Established at iteration **Phase 2 entry** (Phase 1 Review & Edit may stay on th
|
|
|
121
121
|
|
|
122
122
|
| Worktree role | Checked-out branch | Path recorded in `status.json` | Writable product edits |
|
|
123
123
|
|---------------|-------------------|-------------------------------|------------------------|
|
|
124
|
-
| **Control worktree** | Resolved `spec_integration_branch` (same across active plans) | `metadata.control_worktree_path` — canonical **repository root** (not `{HARNESS_DIR}`) | **Forbidden** — coordination
|
|
124
|
+
| **Control worktree** | Resolved `spec_integration_branch` (same across active plans) | `metadata.control_worktree_path` — canonical **repository root** (not `{HARNESS_DIR}`) | **Forbidden** — harness coordination SSOT + serial integration merge only |
|
|
125
125
|
| **Feature worktree** (per plan) | Plan `Working branch` / feature branch from integration | `plans[].execution_lease.worktree_path` | **Required cwd** for that plan's product/source edits |
|
|
126
126
|
|
|
127
|
+
### Harness path SSOT under default gitignore (L1)
|
|
128
|
+
|
|
129
|
+
Default process artifacts (`plans/`, `iterations/`, `status.json`, `sdd/`, `notes.json`, `archived/`) are **gitignored** (`mstar-plan-conventions`「Git 跟踪策略」). `git worktree add` does **not** copy them into a new feature checkout. They live on the **control worktree filesystem** (the checkout of `spec_integration_branch`), not as Git blobs on that branch.
|
|
130
|
+
|
|
131
|
+
| Path role | Resolve from |
|
|
132
|
+
|-----------|--------------|
|
|
133
|
+
| **Control harness root** | `<control_worktree_path>/{HARNESS_DIR}/` |
|
|
134
|
+
| **Process / coordination SSOT** (read + write) | Absolute under control harness root: `status.json`, `plans/`, `iterations/`, `sdd/<plan-id>/`, `notes.json`, `archived/` |
|
|
135
|
+
| **Tracked results** (`AGENTS.md`, `knowledge/`, `specs/`) | Available in any worktree via Git; absolute control paths in Assignment are still fine |
|
|
136
|
+
| **Product / source edits** | Feature worktree only (`execution_lease.worktree_path`) |
|
|
137
|
+
|
|
127
138
|
**Hard rules**
|
|
128
139
|
|
|
129
140
|
- `execution_lease.worktree_path` **MUST** differ from `metadata.control_worktree_path`.
|
|
130
|
-
-
|
|
131
|
-
- Absolute **`Worktree path`** MUST appear in the writable Assignment and in `execution_lease.worktree_path` before first writable implement dispatch for that plan.
|
|
141
|
+
- A feature worktree's same-looking `{HARNESS_DIR}` path is **not** the SSOT — **never** treat it as the source of plans/status/SDD, and **never** bootstrap a second plans/status/SDD tree there.
|
|
142
|
+
- Absolute **`Worktree path`** (feature) MUST appear in the writable Assignment and in `execution_lease.worktree_path` before first writable implement dispatch for that plan.
|
|
143
|
+
- When L1 lease gate is active (not `Worktree mode: waived`), Assignment **`Plan Path`** and **`SDD dir`** MUST be **absolute paths under the control harness root** (not relative `.mstar/...` resolved from the feature cwd). Prefer also writing **`Control harness root: <control_worktree_path>/{HARNESS_DIR}`**.
|
|
132
144
|
- Writable dispatch for a plan requires a **verified** `execution_lease` (same read-check-replace-verify discipline as the iteration reference). Full claim tables are **not** duplicated here.
|
|
133
145
|
|
|
146
|
+
**Anti-pattern (forbidden)**
|
|
147
|
+
|
|
148
|
+
- Inferring `Worktree mode: waived` because “feature worktree has no plans” under default gitignore. Correct response: keep feature worktrees; route harness I/O through control absolute paths. Missing same-host write lock → **`Plan parallelism: serial`** only — that is a **separate** gate and does **not** waive worktree/lease.
|
|
149
|
+
|
|
134
150
|
**Naming conventions (PM / ops; examples only — paths MUST be canonical absolute)**
|
|
135
151
|
|
|
136
152
|
1. **Control worktree** — usually the primary checkout or a PM-designated path on `spec_integration_branch`; record once in `metadata.control_worktree_path`.
|
|
@@ -86,7 +86,7 @@ When **`Execution mode: sdd`** (`mstar-sdd`):
|
|
|
86
86
|
|
|
87
87
|
- 独立模块可并行 **implement 轨道**(不同 dev Assignment);**同仓 ≥2 可写并发** → **`mstar-branch-worktree`** **`references/parallel-writable-pre-dispatch.md`**(先于 invoke;同 plan 多轨 = L2)。
|
|
88
88
|
- **SDD 单 plan 内**:task / implementer **仍串行**(`mstar-sdd`);**禁止**同一 plan 内并行 SDD implementer(写冲突)。
|
|
89
|
-
- **跨 plan(迭代 Phase 2)≠ 单 plan 内并行**:不同 `plan_id` 的 feature implement **允许** lease 门控并行(每 plan 独立 verified `plans[].execution_lease` + feature worktree,L1)**仅当** coordination 路径 same-host 独占写锁可用且每次协调变更持锁 → **`mstar-iteration`** §2.0 #5 · **`mstar-plan-artifacts`**。**跨主机 / 无共享 flock** → 默认 **`Plan parallelism: serial`** 或 Assignment 仍写并行 → **Blocked**(用户本轮 `Cross-host lease race: accepted` + audit `notes`
|
|
89
|
+
- **跨 plan(迭代 Phase 2)≠ 单 plan 内并行**:不同 `plan_id` 的 feature implement **允许** lease 门控并行(每 plan 独立 verified `plans[].execution_lease` + feature worktree,L1)**仅当** coordination 路径 same-host 独占写锁可用且每次协调变更持锁 → **`mstar-iteration`** §2.0 #5 · **`mstar-plan-artifacts`**。**跨主机 / 无共享 flock** → 默认 **`Plan parallelism: serial`** 或 Assignment 仍写并行 → **Blocked**(用户本轮 `Cross-host lease race: accepted` + audit `notes` 除外)。**无 flock 不豁免** control/feature worktree 或 lease。**`Worktree mode: waived` 不豁免**跨 plan 并行安全闸。**禁止**因默认 gitignore 导致 feature 缺 plans 而 waive worktree(harness 经 control 绝对路径)→ **`mstar-branch-worktree`**。**禁止**无 lease 的跨 plan 可写派发(lease 闸未 waive 时)。
|
|
90
90
|
- **`integration_merge_lease`**:`spec_integration_branch` 上的 merge **始终串行**(一次仅一 holder)→ **`mstar-iteration`** · **`mstar-plan-artifacts`**。
|
|
91
91
|
- **`Plan parallelism: serial`**:仅强制跨 plan implement **调度串行**;**不** waive control worktree / `execution_lease` / `integration_merge_lease`(`Worktree mode: waived` 才是 lease/worktree 豁免)→ **`mstar-iteration`** §2.0 #5。
|
|
92
92
|
- **Plan QC tri** after SDD task loop(`Execution mode: sdd`);**单席**仅 `inline` / hotfix。共用 `Review cwd` / `Working branch` / `plan_id` / `Review range`(**`mstar-branch-worktree`**)。
|
|
@@ -111,6 +111,7 @@ When **`Execution mode: sdd`** (`mstar-sdd`):
|
|
|
111
111
|
- 跨 plan 可写派发无 verified `execution_lease`;steal / 覆盖活跃 `execution_lease` 或 `integration_merge_lease`;并行 integration merge。
|
|
112
112
|
- 跨 plan **并行**可写派发在 **无** same-host 独占写锁(跨主机 / 无共享 flock)且 **无** 用户本轮 `Cross-host lease race: accepted` + audit `notes` — **无论** `Worktree mode: waived`。
|
|
113
113
|
- 将 **`Worktree mode: waived`** 当作跨 plan 无锁并行授权(须 serial 或 race-accepted + audit)。
|
|
114
|
+
- 因 feature worktree 在默认 gitignore 下看不到 `plans/` 而设 **`Worktree mode: waived`**(应保留 feature worktree + control 绝对 `Plan Path` / `SDD dir`)。
|
|
114
115
|
- `InProgress` 无 `execution_lease` 未走 orphan recovery 即 writable-dispatch。
|
|
115
116
|
- 同仓多轨 writable implement:**N invoke ≠ worktree 隔离**(L2)→ **`mstar-branch-worktree`** **`references/parallel-writable-pre-dispatch.md`**。
|
|
116
117
|
- 递归同角色 subagent;把 Handoff / 多轨编排措辞当 invoke。
|
|
@@ -143,6 +143,7 @@ Read **`mstar-host`** after this skill; detect host per its table, then Read the
|
|
|
143
143
|
| 递归误派 / 误读 Handoff | `mstar-dispatch-gates` |
|
|
144
144
|
| `quick` 跳过 Prepare | 上表 + `mstar-phase-gates` |
|
|
145
145
|
| 多 worktree 未归并就 QC | `mstar-branch-worktree` |
|
|
146
|
+
| 因默认 gitignore 致 feature 缺 plans 而 `Worktree mode: waived`(应保留 feature worktree + control 绝对 Plan Path / SDD dir;无 flock 仅 → `Plan parallelism: serial`) | `mstar-branch-worktree` · `mstar-iteration` §2.0 #5 · `phase-2-worktree-lease` |
|
|
146
147
|
| 并行 writable implement 无隔离(L2 同 plan 多轨:N invoke ≠ worktree;L1 跨 plan:无 verified `execution_lease` + feature worktree) | `mstar-branch-worktree` L1/L2 · `mstar-iteration` §2.6 · `references/parallel-writable-pre-dispatch.md` |
|
|
147
148
|
| 跨 plan 可写派发无 verified `execution_lease` / steal 活跃 lease / 并行 merge 入 `spec_integration_branch` | `mstar-iteration` · `mstar-plan-artifacts`(leases)· `mstar-branch-worktree` L1 |
|
|
148
149
|
| `InProgress` 无 `execution_lease` 未恢复即可写派发 | `mstar-plan-artifacts` — orphan recovery |
|
|
@@ -64,7 +64,7 @@ When Assignment has **`SDD implementer session: sticky`** (`mstar-sdd/references
|
|
|
64
64
|
|
|
65
65
|
## Dispatch execution(canonical)
|
|
66
66
|
|
|
67
|
-
Cursor PM dispatch = **`Task`** with `subagent_type` matching the Assignment `Execute as` role.
|
|
67
|
+
Cursor PM dispatch = **`Task`** with `subagent_type` matching the Assignment `Execute as` role. Flat JSON field shape → **Task invoke schema (Cursor)** below.
|
|
68
68
|
|
|
69
69
|
- **1 Assignment ⇒ 1 Task**; parallel batches ⇒ **N Tasks in one message** (`parallel-dispatch.md`, `mstar-dispatch-gates`).
|
|
70
70
|
- 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).
|
|
@@ -73,6 +73,84 @@ Cursor PM dispatch = **`Task`** with `subagent_type` matching the Assignment `Ex
|
|
|
73
73
|
- Concurrent writers / QC cwd alignment → **`mstar-branch-worktree`** (not a separate “mode”).
|
|
74
74
|
- Implement subagents: recipient is already `Execute as`; **no** recursive Task with same `subagent_type`. Assignment wins (`Delegation: forbidden` unless stated).
|
|
75
75
|
|
|
76
|
+
## Task invoke schema (Cursor)
|
|
77
|
+
|
|
78
|
+
Cursor’s live **Task** tool expects a **flat** JSON argument object. `prompt` and `subagent_type` are **sibling fields** — not nested, not stringified. Official behavior docs cover subagents/parallel/resume; the flat field shape below is Morning Star’s operational SSOT for Cursor (live-tool contract).
|
|
79
|
+
|
|
80
|
+
### Canonical flat shape
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"description": "3-5 word UI title",
|
|
85
|
+
"prompt": "<full Assignment Markdown body>",
|
|
86
|
+
"subagent_type": "<Execute as role id or built-in>",
|
|
87
|
+
"model": "<optional host slug>",
|
|
88
|
+
"run_in_background": false
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Required vs optional fields
|
|
93
|
+
|
|
94
|
+
| Field | Required | Notes |
|
|
95
|
+
|-------|----------|-------|
|
|
96
|
+
| `prompt` | yes | Full Assignment Markdown string (IDENTITY, gates, Plan Path, Working branch, …) |
|
|
97
|
+
| `subagent_type` | yes | Must equal Assignment `Execute as` (Morning Star role id when using custom agents) |
|
|
98
|
+
| `description` | recommended | Short UI title only (3–5 words); never the Assignment body |
|
|
99
|
+
| `model` | optional | Host slug from Assignment **Model tier** mapping |
|
|
100
|
+
| `run_in_background` | optional | Default false unless PM intentionally backgrounds |
|
|
101
|
+
| `resume` | sticky continue only | Omit on fresh dispatch; see sticky section |
|
|
102
|
+
|
|
103
|
+
### Must-have example (single dispatch)
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
Task(
|
|
107
|
+
description: "Implement auth middleware",
|
|
108
|
+
prompt: "<full Assignment body>",
|
|
109
|
+
subagent_type: "fullstack-dev",
|
|
110
|
+
model: "<optional>",
|
|
111
|
+
run_in_background: false
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Rules:
|
|
116
|
+
|
|
117
|
+
- `subagent_type` **=** Assignment `Execute as` — never OpenCode’s `subagent` key.
|
|
118
|
+
- `prompt` = plain Markdown Assignment text, **not** a JSON object string of the whole call.
|
|
119
|
+
- `description` = UI title only; do not put the Assignment there.
|
|
120
|
+
|
|
121
|
+
### Parallel batch (N Tasks, one message)
|
|
122
|
+
|
|
123
|
+
When `N ≥ 2`, emit **N** separate Task tool calls in **one** assistant message (`parallel-dispatch.md`). Each call is still a flat object with its own `prompt` + `subagent_type`.
|
|
124
|
+
|
|
125
|
+
### Anti-patterns (do not send)
|
|
126
|
+
|
|
127
|
+
| Anti-pattern | Correct |
|
|
128
|
+
|--------------|---------|
|
|
129
|
+
| Args as one stringified JSON blob | Flat sibling fields on the Task tool |
|
|
130
|
+
| Field name `subagent` (OpenCode) | `subagent_type` |
|
|
131
|
+
| `CallMcpTool` / MCP wrap for Task | Native Task tool only |
|
|
132
|
+
| Missing `subagent_type` | Always set; match `Execute as` |
|
|
133
|
+
| Assignment JSON stuffed only into `prompt`, no top-level `subagent_type` | Both `prompt` and `subagent_type` present |
|
|
134
|
+
| Nested `{ "arguments": { ... } }` Task payload | Flat object at tool-call top level |
|
|
135
|
+
| Treating paste-only `## Assignment` as dispatch | Must emit Task call(s) |
|
|
136
|
+
|
|
137
|
+
### Self-check before send
|
|
138
|
+
|
|
139
|
+
1. Tool name is **Task** (not MCP, not OpenCode `task`+`subagent`).
|
|
140
|
+
2. Top-level keys include **`prompt`** and **`subagent_type`** (siblings).
|
|
141
|
+
3. `subagent_type` equals Assignment `Execute as`.
|
|
142
|
+
4. `prompt` is Markdown Assignment text, not stringified JSON of the whole call.
|
|
143
|
+
5. If sticky continue: `resume` + continuation prompt per sticky section; else omit `resume`.
|
|
144
|
+
6. If `N ≥ 2`: this message contains **exactly N** Task calls (`parallel-dispatch.md`).
|
|
145
|
+
|
|
146
|
+
### Sticky / resume (pointer)
|
|
147
|
+
|
|
148
|
+
First vs resume field set → **SDD sticky implementer (Cursor Task resume)** above. Do not restate those tables here.
|
|
149
|
+
|
|
150
|
+
- Fresh: `subagent_type` + full implementer prompt; capture agent id.
|
|
151
|
+
- Continue: `resume: <host_agent_id>` + continuation prompt; still flat sibling fields.
|
|
152
|
+
- Reviewers: never `resume`.
|
|
153
|
+
|
|
76
154
|
## Clarify
|
|
77
155
|
|
|
78
156
|
- No `question` tool: structured Markdown or Cursor UI.
|
|
@@ -17,7 +17,7 @@ Printing `## Assignment` in the main thread **without** matching host invocation
|
|
|
17
17
|
|
|
18
18
|
1. Finalize all `N` Assignment payloads (after any prerequisite turn).
|
|
19
19
|
2. Count distinct `Execute as` sessions (`N`).
|
|
20
|
-
3. Issue **`N` host invocations first** — OpenCode: **N `task` tool** calls with **subagent**; Cursor: **N `Task`** with `subagent_type
|
|
20
|
+
3. Issue **`N` host invocations first** — OpenCode: **N `task` tool** calls with **subagent**; Cursor: **N `Task`** with `subagent_type` (JSON field shape → `cursor.md` § Task invoke schema); Kimi: **N `Agent`** calls (each prompt carries **Act as** + skill load; `subagent_type` ∈ {`coder`,`explore`,`plan`} only — see `kimi.md` C5/C5b); each with one Assignment body. For parallel work, **all `N` tool calls in one assistant message** when the host allows.
|
|
21
21
|
4. Optionally post a short **Status Update** after invocations (audit trail only — does not replace step 3).
|
|
22
22
|
|
|
23
23
|
## Hard rules
|
|
@@ -216,7 +216,7 @@ Phase 1 与 §1.6 须遵守 **`references/iteration-artifact-boundaries.md`**(
|
|
|
216
216
|
2. **Pre-implement gate = GO**:plan 已 locked、tasks ready(见 `mstar-phase-gates`)
|
|
217
217
|
3. 用户意图为 **continue Autonomous Execute**(推进迭代 Execute、继续 per-plan 循环等)
|
|
218
218
|
4. **Branch metadata gate**:root `metadata.iteration_base_branch`、`metadata.target_branch` 已登记,且至少一条 active plan 有 `metadata.spec_integration_branch`(或可从 compass 同轮 backfill)。**缺失 → STOP**,不得用 `main`/`master` 补位。
|
|
219
|
-
5. **Control-worktree + lease defaults**(iteration 命令;可被 `Worktree mode: waived` 豁免):除非本轮 Assignment 显式 `Worktree mode: waived`(或等价用户指令),Phase 2 **必须**在入口建立 control worktree、经 control
|
|
219
|
+
5. **Control-worktree + lease defaults**(iteration 命令;可被 `Worktree mode: waived` 豁免):除非本轮 Assignment 显式 `Worktree mode: waived`(或等价用户指令),Phase 2 **必须**在入口建立 control worktree、经 control 路径读写默认 gitignored 的 harness 进程产物(`status.json`、`{PLAN_DIR}`、`{ITERATION_DIR}`、`{SDD_DIR}` 等),并在可写派发前 claim `plans[].execution_lease` / `integration_merge_lease`。可写 Assignment 须含绝对 feature **`Worktree path`** + 绝对 control 系 **`Plan Path`** / **`SDD dir`**(见 **`mstar-branch-worktree`**「Harness path SSOT under default gitignore」)。**禁止**因 feature worktree 在默认 gitignore 下看不到 plans 而推断 `Worktree mode: waived`。`Plan parallelism: serial` **不** waive 本闸——仅强制跨 plan **implement** 串行调度;control worktree + lease 仍须满足。**跨 plan 并行安全闸**(**不可**被 `Worktree mode: waived` 豁免):跨 plan **并行可写 implement** 须满足下列之一——(a) coordination 路径(control 或 waived 时主 checkout `{HARNESS_DIR}/status.json`)上 **same-host 独占写锁可用且每次 status/协调变更持锁**;(b) 默认 **`Plan parallelism: serial`**(**waived 时尤其优先默认串行**;**无 flock / 无共享锁时只触发本条,不豁免 worktree**);(c) 用户本轮显式 `Cross-host lease race: accepted`(或等价)+ `plans[].notes` 审计。**禁止**将 `Worktree mode: waived` 当作跨主机无锁并行的授权。细则 → **`references/phase-2-worktree-lease.md`**。
|
|
220
220
|
|
|
221
221
|
任一 false → **stop**。Phase 1 / Prepare 未完成 → 先完成 Phase 1 或 per-plan Prepare,再进入本 Phase。
|
|
222
222
|
|
|
@@ -253,9 +253,13 @@ SSOT = `{HARNESS_DIR}/status.json` + `{PLAN_DIR}/`。todos 只追踪本轮下一
|
|
|
253
253
|
1. 解析或创建 **control worktree**(通常 primary checkout 或 PM 指定路径),检出到上一步的 `spec_integration_branch`
|
|
254
254
|
2. `git fetch`(按需);`git branch --show-current` 确认在 `spec_integration_branch`
|
|
255
255
|
3. 将规范绝对仓库根路径写入 control 副本 `metadata.control_worktree_path`(仓库根,非 `{HARNESS_DIR}` 子路径)
|
|
256
|
-
4. 此后 **
|
|
256
|
+
4. 此后 **harness 进程产物 SSOT**(默认 gitignored)均经 control 绝对路径解析:
|
|
257
257
|
- `<control_worktree_path>/{HARNESS_DIR}/status.json`
|
|
258
|
+
- `<control_worktree_path>/{PLAN_DIR}/`(主 plan)
|
|
259
|
+
- `<control_worktree_path>/{ITERATION_DIR}/`(compass / iteration package)
|
|
258
260
|
- `<control_worktree_path>/{HARNESS_DIR}/sdd/<plan-id>/`
|
|
261
|
+
- 同树:`notes.json`、`archived/`(若使用)
|
|
262
|
+
Feature worktree 只承载产品/源码编辑;其同名 `{HARNESS_DIR}` **不是** SSOT。Assignment **`Plan Path`** / **`SDD dir`** 须写 control 绝对路径。
|
|
259
263
|
5. 若 integration 分支尚不存在:在 control worktree 内 `git checkout -b <spec_integration_branch> <iteration_base_branch>`(**必须**从记录的 base 创建)
|
|
260
264
|
|
|
261
265
|
**Git 操作(无 control worktree 时 — 仅 `Worktree mode: waived`)**:
|
|
@@ -279,7 +283,7 @@ SSOT = `{HARNESS_DIR}/status.json` + `{PLAN_DIR}/`。todos 只追踪本轮下一
|
|
|
279
283
|
- 若 `status: InProgress` 但 **无** `execution_lease` → **STOP** 升级(孤儿状态恢复 → **`mstar-plan-artifacts`**;本 skill 不自行补 lease)
|
|
280
284
|
- 否则按 **`references/phase-2-worktree-lease.md`** claim:`Todo`/`Blocked` → `InProgress` + 写入完整 `execution_lease`;verify 通过前 **禁止**可写派发
|
|
281
285
|
2. **Plan start — feature worktree + branch**:创建/校验 dedicated feature worktree;Assignment 须含绝对 `Worktree path` + `Working branch`(与 lease 一致)。plan 内多可写并行轨 → **`mstar-branch-worktree`** **`references/parallel-writable-pre-dispatch.md`**
|
|
282
|
-
3. **Implement → InReview**(`§ 2.5`;产品编辑在 feature worktree
|
|
286
|
+
3. **Implement → InReview**(`§ 2.5`;产品编辑在 feature worktree;plans / status / iterations / SDD 经 control 绝对路径):
|
|
283
287
|
- **默认 `Execution mode: sdd`**(多 task plan;hotfix 可 `inline`)。
|
|
284
288
|
- PM 载入 **`mstar-sdd`** 后,按 plan task 顺序 **串行** per-task 循环(**不是**一次派发 dev 做全部 tasks):
|
|
285
289
|
1. `sdd-workspace <plan-id>` → `{SDD_DIR}`
|
|
@@ -561,5 +565,6 @@ PR **merge** 本身可仍由用户手动执行,除非 Assignment 明确授权
|
|
|
561
565
|
- **不要把 harness 流程(Review 链 / QC / QA / compound / close / PR 等)计进 Scale budget 的 plan 数量**,也不得为此单独建 process plan 占坑
|
|
562
566
|
- **不要在 Phase 2 无 verified `execution_lease` 就做可写 implement 派发**(resume 仅限同 `holder` verify-held-lease)
|
|
563
567
|
- **不要 steal / 覆盖他人 `execution_lease` 或 `integration_merge_lease`**(除非用户本轮显式 override + audit `notes`)
|
|
564
|
-
- **不要从 feature worktree 的 `{HARNESS_DIR}` 路径当作 status/SDD SSOT**(control worktree
|
|
568
|
+
- **不要从 feature worktree 的 `{HARNESS_DIR}` 路径当作 plans / status / iterations / SDD SSOT**(control worktree 绝对路径为准;默认 gitignore 下 feature 缺 plans **不得**推断 `Worktree mode: waived`)
|
|
569
|
+
- **不要把「无 flock」与「gitignore / feature 缺 plans」捆成一次 waive**(无锁 → `Plan parallelism: serial` only;gitignore → control-path harness)
|
|
565
570
|
- **不要并行 merge 入 `spec_integration_branch`**(merge 必须经 `integration_merge_lease` 串行)
|
|
@@ -28,13 +28,21 @@ starts at **Phase 2 entry**.
|
|
|
28
28
|
tree clean before merge operations.
|
|
29
29
|
4. Record canonical absolute repository-root path in
|
|
30
30
|
`metadata.control_worktree_path` (not `{HARNESS_DIR}`; canonicalize symlinks).
|
|
31
|
-
5. Resolve coordination paths from that root:
|
|
31
|
+
5. Resolve coordination paths from that root (default-gitignored process artifacts live on the **control filesystem**, not as Git blobs):
|
|
32
32
|
- status SSOT: `<control_worktree_path>/{HARNESS_DIR}/status.json`
|
|
33
|
+
- plans SSOT: `<control_worktree_path>/{PLAN_DIR}/` (or `<control>/{HARNESS_DIR}/plans/`)
|
|
34
|
+
- iterations SSOT: `<control_worktree_path>/{ITERATION_DIR}/`
|
|
33
35
|
- SDD tree: `<control_worktree_path>/{HARNESS_DIR}/sdd/<plan-id>/`
|
|
36
|
+
- also under control harness root when used: `notes.json`, `archived/`
|
|
34
37
|
|
|
35
38
|
All sessions MUST reread the **control copy** of `status.json` immediately before
|
|
36
39
|
claim, release, transfer, plan-status transition, or merge-lease mutation.
|
|
37
40
|
|
|
41
|
+
**Do not** set `Worktree mode: waived` because a feature worktree lacks
|
|
42
|
+
`plans/` under default gitignore — keep feature worktrees and pass absolute
|
|
43
|
+
control **`Plan Path`** / **`SDD dir`** in Assignments
|
|
44
|
+
(`mstar-branch-worktree` 「Harness path SSOT under default gitignore」).
|
|
45
|
+
|
|
38
46
|
### Same-host exclusive write lock
|
|
39
47
|
|
|
40
48
|
All control-path lease mutations (claim, release, transfer, merge-lease
|
|
@@ -49,7 +57,9 @@ this same-host lock is **available on the coordination `status.json` path and
|
|
|
49
57
|
used for every status/coordination mutation** in that Phase 2 session (control
|
|
50
58
|
path when lease gate active; primary checkout `{HARNESS_DIR}/status.json` when
|
|
51
59
|
waived). Agents on **different hosts** or with **no shared flock/lockdir** →
|
|
52
|
-
default **`Plan parallelism: serial`** (preferred when waived).
|
|
60
|
+
default **`Plan parallelism: serial`** (preferred when waived). **No flock
|
|
61
|
+
does not waive** control worktree / feature worktree / leases — serial
|
|
62
|
+
scheduling only. Assignment still
|
|
53
63
|
claiming cross-plan parallel without lock availability → **Blocked** until PM
|
|
54
64
|
sets serial scheduling or the user gives current-turn override
|
|
55
65
|
`Cross-host lease race: accepted` (or equivalent) + audit on `plans[].notes`.
|
|
@@ -68,8 +78,11 @@ mismatch → **STOP**.
|
|
|
68
78
|
edits).
|
|
69
79
|
- `Worktree path` MUST appear in the writable Assignment and in
|
|
70
80
|
`plans[].execution_lease.worktree_path` before first writable implement dispatch.
|
|
71
|
-
- Product/source edits run from the feature worktree;
|
|
72
|
-
coordination reads/writes run through
|
|
81
|
+
- Product/source edits run from the feature worktree; plans, iterations,
|
|
82
|
+
status, and SDD coordination reads/writes run through **absolute control
|
|
83
|
+
paths** (never relative `.mstar/...` from the feature cwd when L1 is active).
|
|
84
|
+
- Assignment MUST include absolute feature **`Worktree path`** and absolute
|
|
85
|
+
control **`Plan Path`** / **`SDD dir`** before writable implement dispatch.
|
|
73
86
|
- Default **L1**: one writable track per plan. Within-plan multi-writable tracks
|
|
74
87
|
still follow L2 `parallel-writable-pre-dispatch` (`mstar-branch-worktree`).
|
|
75
88
|
|
|
@@ -207,7 +207,7 @@ Cooperative coordination through the **control worktree** copy of `{HARNESS_DIR}
|
|
|
207
207
|
|
|
208
208
|
**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).
|
|
209
209
|
|
|
210
|
-
**Path SSOT:** status
|
|
210
|
+
**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」.
|
|
211
211
|
|
|
212
212
|
### Same-host exclusive write lock (control `status.json`)
|
|
213
213
|
|
|
@@ -92,6 +92,8 @@ PM 在需要持久化追踪时:
|
|
|
92
92
|
|
|
93
93
|
Legacy `.agents/` 项目:将上表路径前缀 `.mstar/` 换为 `.agents/`。
|
|
94
94
|
|
|
95
|
+
**多 worktree(iteration L1)**:默认 gitignored 的进程产物**不会**随 `git worktree add` 进入 feature 检出。读写须经 **control worktree** 绝对路径(`<control_worktree_path>/{HARNESS_DIR}/…`);产品代码改在 feature worktree。细则与反模式(禁止因 feature 缺 plans 而 `Worktree mode: waived`)→ **`mstar-branch-worktree`**「Harness path SSOT under default gitignore」。
|
|
96
|
+
|
|
95
97
|
**Canonical `.gitignore` snippet**(skills 与 CLI `init` 对齐):
|
|
96
98
|
|
|
97
99
|
```gitignore
|
|
@@ -75,7 +75,7 @@ The **`**You are a leaf executor. You MUST NOT:**`** section (previously just pr
|
|
|
75
75
|
**Delegation**: forbidden | allowed (...)
|
|
76
76
|
**Execution mode**: sdd | inline | N/A
|
|
77
77
|
**SDD implementer session**: fresh | sticky | N/A — **default `fresh`**; `sticky` reuses same implementer subagent across tasks (reviewers stay fresh). See `mstar-sdd/references/sticky-implementer-session.md`
|
|
78
|
-
**SDD dir**: `{HARNESS_DIR}/sdd/<plan-id>/` | N/A
|
|
78
|
+
**SDD dir**: absolute `<control_worktree_path>/{HARNESS_DIR}/sdd/<plan-id>/` when L1 lease gate active | `{HARNESS_DIR}/sdd/<plan-id>/` when waived / single checkout | N/A
|
|
79
79
|
**Model tier**: fast | standard | capable | N/A
|
|
80
80
|
**QC mode**: full tri-review | single | N/A — **default `full tri-review` when `Execution mode: sdd`**; `single` only for `inline` / override
|
|
81
81
|
**Review package path**: <branch-review diff file> | N/A
|
|
@@ -90,10 +90,11 @@ The **`**You are a leaf executor. You MUST NOT:**`** section (previously just pr
|
|
|
90
90
|
- Execute: `plan locked` [done|n/a], `tasks` [done|n/a], `implement` [this assignment|done]
|
|
91
91
|
- Gate decision: `go` | `blocked` (<reason>)
|
|
92
92
|
**Working branch**: <branch policy or create-from policy> — formal iteration: from `metadata.spec_integration_branch`; integration cut from `metadata.iteration_base_branch` (`mstar-iteration` §2.3)
|
|
93
|
+
**Control harness root**: `<control_worktree_path>/{HARNESS_DIR}` when L1 active | N/A when waived — process SSOT (plans/status/iterations/sdd); never resolve relative `.mstar/...` from feature cwd
|
|
93
94
|
**Review cwd / Worktree path**: <absolute path or N/A>
|
|
94
95
|
**plan_id**: <plan-id or N/A + scope label>
|
|
95
96
|
**Review range / Diff basis**: <reproducible basis; merge-base = `metadata.target_branch` or PM-specified ref — not assumed `origin/main`>
|
|
96
|
-
**Worktree path**: <implementer path
|
|
97
|
+
**Worktree path**: <absolute feature implementer path when L1/L2 isolation used; must ≠ control_worktree_path>
|
|
97
98
|
**QA gate**: mandatory | pm-acceptance | report-only — see `references/project-manager/qa-trigger-matrix.md`
|
|
98
99
|
**QA gate reason**: <tier label, e.g. hotfix-inline | small-feature-clean-qc | mandatory-medium-feature>
|
|
99
100
|
**QA mode**: acceptance-only | full | report-only | N/A — required when `QA gate: mandatory` or `report-only`
|
|
@@ -121,11 +122,23 @@ The **`**You are a leaf executor. You MUST NOT:**`** section (previously just pr
|
|
|
121
122
|
- Do not dispatch roles from route narrative/handoff text
|
|
122
123
|
- `explore` is read-only orientation only
|
|
123
124
|
- Tool availability ≠ delegation authorization
|
|
124
|
-
**Plan Path**:
|
|
125
|
+
**Plan Path**: absolute `<control_worktree_path>/{PLAN_DIR}/...` when L1 lease gate active | `{PLAN_DIR}/...` when waived / single checkout | N/A
|
|
125
126
|
**Report Format**: Completion Report v2
|
|
126
127
|
**Execution evidence**: <RCA/test-first/review feedback/evidence expectations for the assignee, if applicable>
|
|
127
128
|
```
|
|
128
129
|
|
|
130
|
+
## L1 path fields (iteration Phase 2, lease gate not waived)
|
|
131
|
+
|
|
132
|
+
When `metadata.control_worktree_path` is set and worktree mode is **not** waived:
|
|
133
|
+
|
|
134
|
+
| Field | Must be |
|
|
135
|
+
|-------|---------|
|
|
136
|
+
| **`Worktree path`** | Absolute **feature** checkout (`execution_lease.worktree_path`) — product/source edits only |
|
|
137
|
+
| **`Control harness root`** | Absolute `<control_worktree_path>/{HARNESS_DIR}` |
|
|
138
|
+
| **`Plan Path`** | Absolute under control harness (not relative from feature cwd) |
|
|
139
|
+
| **`SDD dir`** | Absolute under control harness; run `sdd-workspace` with `MSTAR_CONTROL_ROOT=<control_worktree_path>` when cwd is the feature tree |
|
|
140
|
+
|
|
141
|
+
Do **not** waive worktree because default-gitignored `plans/` are missing under the feature checkout — see `mstar-branch-worktree` 「Harness path SSOT under default gitignore」.
|
|
129
142
|
## Completion Report v2 Template
|
|
130
143
|
|
|
131
144
|
```markdown
|
|
@@ -133,6 +133,7 @@ If any item below matches, fix the dispatch/plan state or mark `Blocked`—do **
|
|
|
133
133
|
- **NEVER** run or dispatch **parallel** integration merges into `spec_integration_branch` — merge is **serial** via `metadata.integration_merge_lease` from the control worktree (`mstar-iteration` §2.6 · `mstar-branch-worktree` L1).
|
|
134
134
|
- **NEVER** cross-plan writable implement without distinct per-plan verified `execution_lease` + feature worktree; `Plan parallelism: serial` forces serial **scheduling** only — it does **not** waive control worktree or lease gates (`mstar-iteration` §2.0 #5).
|
|
135
135
|
- **NEVER** dispatch **cross-plan parallel** writable implement when same-host exclusive write lock is **not** available on the coordination `status.json` path (cross-host / no shared flock) — default **`Plan parallelism: serial`** or **Blocked** if Assignment still claims parallel; exception only on current-turn user `Cross-host lease race: accepted` (or equivalent) + audit `plans[].notes` — **including when `Worktree mode: waived`** (`mstar-plan-artifacts` — “Hard gate — cross-plan parallel writable implement”).
|
|
136
|
+
- **NEVER** set `Worktree mode: waived` because default-gitignored `plans/` are missing under a feature worktree — keep feature worktrees; put absolute control **`Plan Path`** / **`SDD dir`** / **`Control harness root`** on Assignments (`mstar-branch-worktree` 「Harness path SSOT under default gitignore」). No flock → serial scheduling only, not worktree waiver.
|
|
136
137
|
|
|
137
138
|
---
|
|
138
139
|
|
|
@@ -39,7 +39,7 @@ Batch all findings for the human in one message. If clean, proceed silently.
|
|
|
39
39
|
## Per-task loop (PM only)
|
|
40
40
|
|
|
41
41
|
1. Record `BASE_SHA` (never use `HEAD~1` later)
|
|
42
|
-
2. `sdd-workspace <plan-id>` → `SDD_DIR`
|
|
42
|
+
2. `sdd-workspace <plan-id>` → `SDD_DIR`(iteration L1 从 feature cwd 调用时:`MSTAR_CONTROL_ROOT=<control_worktree_path>` 或 `sdd-workspace <plan-id> <control_worktree_path>`;缺 status.json 的 linked worktree 会 fail closed)
|
|
43
43
|
3. `task-brief <plan> N` → brief file
|
|
44
44
|
4. Dispatch implementer:
|
|
45
45
|
- **`SDD implementer session: fresh`** (default) — new subagent; templates: `references/implementer-prompt.md`
|
|
@@ -113,7 +113,7 @@ From repo: `skills/mstar-sdd/scripts/` (bundled in OpenCode as `harness-skills/m
|
|
|
113
113
|
|
|
114
114
|
| Script | Usage |
|
|
115
115
|
|--------|--------|
|
|
116
|
-
| `sdd-workspace` | `PLAN_ID` → creates `{SDD_DIR}
|
|
116
|
+
| `sdd-workspace` | `PLAN_ID [CONTROL_ROOT]` → creates `{SDD_DIR}` under control harness when set (`MSTAR_CONTROL_ROOT` or 2nd arg); fail closed on linked worktree without `status.json` |
|
|
117
117
|
| `task-brief` | `PLAN_FILE TASK_N [OUTFILE]` |
|
|
118
118
|
| `review-package` | `BASE HEAD [OUTFILE]` |
|
|
119
119
|
|
|
@@ -5,6 +5,10 @@ PM and subagents move artifacts as **files**, not pasted text. Pasted content st
|
|
|
5
5
|
## Before implementer dispatch
|
|
6
6
|
|
|
7
7
|
1. `export SDD_DIR=$(skills/mstar-sdd/scripts/sdd-workspace <plan-id>)`
|
|
8
|
+
- Iteration L1 (implementer cwd = feature worktree):
|
|
9
|
+
`export MSTAR_CONTROL_ROOT=<control_worktree_path>`
|
|
10
|
+
or `sdd-workspace <plan-id> <control_worktree_path>`
|
|
11
|
+
so `{SDD_DIR}` lands on the control harness (default-gitignored plans/status/sdd). Do not create a second SDD tree under the feature checkout.
|
|
8
12
|
2. `skills/mstar-sdd/scripts/task-brief <plan-file> <N> "$SDD_DIR/task-N-brief.md"`
|
|
9
13
|
3. Record `BASE_SHA` (`git rev-parse HEAD` before dispatch).
|
|
10
14
|
4. Dispatch implementer with:
|
|
@@ -1,18 +1,82 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Resolve and ensure {SDD_DIR} for Morning Star SDD artifacts.
|
|
3
|
-
# Usage: sdd-workspace PLAN_ID
|
|
3
|
+
# Usage: sdd-workspace PLAN_ID [CONTROL_ROOT]
|
|
4
|
+
# CONTROL_ROOT — optional absolute repo root of the control worktree
|
|
5
|
+
# (or set MSTAR_CONTROL_ROOT). Required when cwd is a linked feature
|
|
6
|
+
# worktree that lacks harness status.json (default gitignore).
|
|
4
7
|
# Prints absolute path to {HARNESS_DIR}/sdd/<plan-id>/ (or legacy .agents/sdd/).
|
|
5
8
|
set -euo pipefail
|
|
6
9
|
|
|
7
|
-
if [ $# -
|
|
8
|
-
echo "usage: sdd-workspace PLAN_ID" >&2
|
|
10
|
+
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
|
|
11
|
+
echo "usage: sdd-workspace PLAN_ID [CONTROL_ROOT]" >&2
|
|
12
|
+
echo " Set MSTAR_CONTROL_ROOT=<control_worktree_path> when running from a feature worktree." >&2
|
|
9
13
|
exit 2
|
|
10
14
|
fi
|
|
11
15
|
|
|
12
16
|
plan_id=$1
|
|
13
|
-
|
|
17
|
+
control_root="${2:-${MSTAR_CONTROL_ROOT:-}}"
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
abs_dir() {
|
|
20
|
+
(cd "$1" && pwd -P)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if [ -n "$control_root" ]; then
|
|
24
|
+
if [ ! -d "$control_root" ]; then
|
|
25
|
+
echo "sdd-workspace: CONTROL_ROOT / MSTAR_CONTROL_ROOT is not a directory: $control_root" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
root=$(abs_dir "$control_root")
|
|
29
|
+
else
|
|
30
|
+
root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
31
|
+
root=$(abs_dir "$root")
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
resolve_harness_with_status() {
|
|
35
|
+
local r=$1
|
|
36
|
+
if [ -f "$r/.mstar/status.json" ]; then
|
|
37
|
+
printf '%s\n' "$r/.mstar"
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
if [ -f "$r/.agents/status.json" ]; then
|
|
41
|
+
printf '%s\n' "$r/.agents"
|
|
42
|
+
return 0
|
|
43
|
+
fi
|
|
44
|
+
return 1
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Linked worktree from `git worktree add`: --git-dir ≠ --git-common-dir
|
|
48
|
+
is_linked_worktree() {
|
|
49
|
+
local r=$1
|
|
50
|
+
local git_dir common
|
|
51
|
+
git_dir=$(git -C "$r" rev-parse --git-dir 2>/dev/null) || return 1
|
|
52
|
+
common=$(git -C "$r" rev-parse --git-common-dir 2>/dev/null) || return 1
|
|
53
|
+
case "$git_dir" in
|
|
54
|
+
/*) ;;
|
|
55
|
+
*) git_dir="$r/$git_dir" ;;
|
|
56
|
+
esac
|
|
57
|
+
case "$common" in
|
|
58
|
+
/*) ;;
|
|
59
|
+
*) common="$r/$common" ;;
|
|
60
|
+
esac
|
|
61
|
+
# Path contains /worktrees/ → definitely linked
|
|
62
|
+
case "$git_dir" in
|
|
63
|
+
*/.git/worktrees/*|*/worktrees/*) return 0 ;;
|
|
64
|
+
esac
|
|
65
|
+
local gd_parent cm_abs
|
|
66
|
+
gd_parent=$(abs_dir "$(dirname "$git_dir")")
|
|
67
|
+
cm_abs=$(abs_dir "$common")
|
|
68
|
+
[ "$gd_parent/$(basename "$git_dir")" != "$cm_abs" ] && [ "$git_dir" != "$cm_abs" ]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if harness=$(resolve_harness_with_status "$root"); then
|
|
72
|
+
:
|
|
73
|
+
elif [ -z "$control_root" ] && is_linked_worktree "$root"; then
|
|
74
|
+
echo "sdd-workspace: linked worktree at $root has no {HARNESS_DIR}/status.json (default gitignore)." >&2
|
|
75
|
+
echo " Refusing to create a second SDD tree under the feature checkout." >&2
|
|
76
|
+
echo " Re-run with MSTAR_CONTROL_ROOT=<control_worktree_path> or: sdd-workspace $plan_id <control_worktree_path>" >&2
|
|
77
|
+
echo " See mstar-branch-worktree «Harness path SSOT under default gitignore»." >&2
|
|
78
|
+
exit 1
|
|
79
|
+
elif [ -d "$root/.mstar" ]; then
|
|
16
80
|
harness="$root/.mstar"
|
|
17
81
|
elif [ -d "$root/.agents" ]; then
|
|
18
82
|
harness="$root/.agents"
|