# File handoffs (Morning Star SDD)

PM and subagents move artifacts as **files**, not pasted text. Pasted content stays in PM context for every later turn.

## Before implementer dispatch

**PM owns helper execution and shared coordination writes.** Keep one canonical per-plan `{SDD_DIR}` root; only PM writes its `context.json` and `progress.md`. Subdirectories namespace artifacts, not a second SDD root. Scheduling → `mstar-sdd` § Ready-task scheduling.

The primary coordinator runs context-dependent workspace/task-brief/review-package helpers serially for their assigned checkout/branch. Before dispatch, it fixes absolute artifact paths and copies the registered row metadata.worktree_path/metadata.working_branch, or an explicitly assigned isolated L2 track, into the leaf Assignment; verify actual Git checkout facts. Missing/corrected row source facts use ordinary revisable prepare, never a per-row lease or Assignment seal. Context updates for another task never alter dispatched inputs; parallel leaves do not invoke shared-context helpers.

1. `export SDD_DIR=$(mstar sdd workspace <plan-id>)`
   - Iteration L1 (implementer cwd = feature worktree):
     `export MSTAR_CONTROL_ROOT=<main-repo-root>` — the **derived main worktree** root, verified by Git probing before the fail-closed guard
     or `mstar sdd workspace <plan-id> <main-repo-root>`
     so `{SDD_DIR}` lands on the control harness (default-gitignored plans/status/sdd). Do not create a second SDD tree under the feature checkout.
2. PM writes `$SDD_DIR/context.json` for the current helper operation — parallel hosted handoffs pin these values in their Assignment instead of consulting mutable plan context:

   ```json
   {
     "planId": "<plan-id>",
     "controlHarnessRoot": "<absolute control harness root>",
     "featureCwd": "<absolute feature worktree>",
     "workingBranch": "<assigned branch>",
     "planFile": "<absolute plan path under the control harness>",
     "sddDir": "<absolute $SDD_DIR>"
   }
   ```

   All paths absolute; `planFile`/`sddDir` must resolve inside the control harness; `featureCwd` must be the assigned feature worktree on `workingBranch`. The declared control root is authoritative — never re-inferred from the feature cwd, and it must canonicalize to the Git-derived main worktree root (an integration/foreign checkout is refused, not redirected).
3. `mstar sdd task-brief <plan-file> <N> --context "$SDD_DIR/context.json"` — bound producer: validates the artifact destination **before** mkdir/write and prints the absolute brief path (`{SDD_DIR}/task-N-brief.md`).
4. Record `BASE_SHA` (`BASE_SHA=$(git -C "$FEATURE_CWD" rev-parse HEAD)` before dispatch). For dependent tasks, first satisfy `mstar-sdd` § Ready-task scheduling: PM serially integrates reviewed prerequisite commits and records their ancestry in this base. Include those commit/base IDs and the check result in the handoff; review approval alone is insufficient.
5. Dispatch implementer with:
   - One line scene-setting (where task fits)
   - Absolute brief path: read first — verbatim requirements
   - Interfaces / decisions brief cannot know
   - Absolute report path: `$SDD_DIR/task-N-report.md` — the implementer's own output slot and L2's **input**; the reviewer's separate output is `$SDD_DIR/task-N-review.md`
   - Absolute control root, feature cwd, branch and plan paths, plus task-specific brief/report/diff paths fixed for this dispatch; the context path is PM coordination metadata, not a leaf checkout selector
   - **Inherited plan scope, no credentials:** artifact handoffs contain inherited plan id and absolute destinations only. The primary coordinator alone records ordinary progress and eventual direct complete and reads receipts; a leaf never selects/prepares rows, mutates workflow/root/shared ledger or releases integration exclusion. Never include session JSON/path/reference, revision/execution token or operation id in a leaf prompt.
   - **`SDD implementer session`**: `fresh` (new subagent) or `sticky` (resume — see **`sticky-implementer-session.md`**)

## Implementer report file

Implementer writes full report to `task-N-report.md` — its own output, and an **input** to L2; the task reviewer never writes this path and never overwrites it. Return to PM only:

- Status: `DONE` | `DONE_WITH_CONCERNS` | `NEEDS_CONTEXT` | `BLOCKED`
- Commits (SHAs)
  Report task commits using the configured identity; missing/failing identity is Blocked, never fabricate or use `-c` identity overrides → `mstar-roles/references/_shared/leaf-executor-core.md` § Git NEVER (repo writes).
- One-line verification summary (affected tests or scoped static evidence)
- Concerns (if any)

## Verification evidence

Choose evidence from the actual diff, not the file extension. Scope limits → `mstar-harness-core` § 定向执行与验证边界.

- **Executable logic**: report the affected test file(s), exact command/selector and actual output; bug fixes include the reproduction red/green evidence. No `Verification mode` is needed for this test triple.
- **Non-executable documentation or prompt/skill policy**: use `Verification mode: scoped-check` with real scoped static or before/after observable evidence. This mode cannot exempt executable code, configuration logic or executable snippets from corresponding tests. Mixed changes retain executable test evidence and do not claim a scoped-check exemption for the task.

```markdown
Verification mode: scoped-check
Changed files: <actual non-executable files>
Tests: N/A
Reason: <why scoped evidence fits the actual change>
Check command: <exact targeted command actually run>
Check result: <actual exit/result and observed output>
```

`Check result` accepts concrete static-tool output (for example `docs/guide.md:12: scoped rule`); a test-style PASS/exit token is not required. It must be nonempty and non-placeholder. Whether an observation is truthful and sufficient remains PM/QC's responsibility.

For appended fixes, begin each new block with `## Verification round: <concrete label>` (for example `fix 1`). Only the last such round is active; earlier rounds remain history and cannot fill missing fields. A report without round headings is one active block. The active round supplies its complete applicable evidence, including `Verification mode` for scoped checks; executable rounds retain their own test triple without a mode. A blank/placeholder round label is invalid.

Replace every placeholder with actual evidence. Unknown or duplicate modes within the active round, missing/empty/placeholder fields, and bare `Tests: N/A` fail; do not copy the template as a report. `assertSddTddTriple` / `mstar lint <task-report>` validate structure only. PM/QC check the actual changed range, applicability and evidence honesty; the checker cannot establish that commands ran or intercept arbitrary shell execution. For policy changes, record the before/after expectation and triggering scenario alongside the concrete check; no broad model-eval matrix is implied.

### Captured check evidence (`sdd evidence`)

An already-authorized check can run **once** and retain raw evidence plus provenance digests in canonical SDD for read-only review, rather than repeating the child command. **PM publishes the task capture request** (task-specific JSON naming context, coverage declaration, declared inputs and selected environment keys); the **developer captures** the authorized check; QC/QA inspect it without repeating the child. The request is separate from rotating `context.json` and is not a checkout selector. Capture authorizes no dispatch, test/full-suite/E2E permission, or report-byte seal.

Exact public command shapes (angle-bracket terms are required CLI values):

```text
mstar sdd evidence capture --request <absolute-task-request.json> -- <executable> [args...]
mstar sdd evidence verify --sdd-dir <absolute-dir> --plan <id> --task <id> --run <uuid> [--target <absolute-target.json>]
```

- Capture runs the child once (literal argv, no shell), POSIX linux/darwin only (unsupported hosts refuse before spawn), and retains `{SDD_DIR}/evidence/<run-uuid>/` with fixed `record.json`, `stdout.log`, `stderr.log`; every retry is a fresh run UUID. Capture exits: child exit code preserved; missing executable 127; timeout 124; signal 128+n (parent SIGINT 130 / SIGTERM 143); gate/IO refusal 1; usage 2. Cite the raw log paths as evidence links — not paraphrased output.
- `verify` is read-only and portable: it never runs the recorded child, discovery or version probes, writes no assessment artifact, and emits exactly one JSON assessment. Without `--target`, exit 0 means complete **integrity only** — a retained failed run still verifies with outcome `failed` (stderr: `integrity only; outcome=<value>; acceptance not assessed`). With `--target`, exit 0 means reuse **candidate** (stderr adds `reuse candidate; coverage review required`); every non-candidate exits 1; usage 2.
- Four outputs stay separate — **integrity** (bundle completeness and valid semantic record/path structure, not unchanged bytes), **outcome** (recorded process result), **target applicability** (`not-assessed`/`candidate`/`changed`/`uncertain`), **coverage judgment** (always `review-required` in v1). Recorded hashes/byte counts are provenance only; equality or drift cannot decide integrity or reuse. There is no parser promise, pass/fail count or automatic coverage inference (`counts` stays null); the reviewer judges coverage.
- Reuse uses current declared semantic applicability: repository identity, path/existence/state, selected environment and semantic tool metadata, outcome and before/after observations. Digest-only input/tool/artifact movement remains eligible; relevant field/path/state or environment/tool observation changes identify an affected gap or uncertainty. Failed/incomplete proof, unknown scope or different repository remains `uncertain`; pre-fix failure stays `failed`, never a pre-feature baseline. Without a target, applicability is `not-assessed`. Empty environment allowlists and lockfile-only declarations remain reviewed assumptions, not automatic completeness.
- Non-executable documentation/policy never manufactures capture evidence — it uses `Verification mode: scoped-check` above. Historical manual evidence stays manual/unverified: cite it with provenance and reviewer reasoning; NEVER retrofit it into a v1 runner record.
- The old `mstar sdd exec` entry is unchanged and stays PM-only serialized launch (§ Bound child launch); hosted leaves never use it for their assigned checks.

## After implementer DONE

PM sets `FEATURE_CWD` from the completed task's immutable Assignment `Worktree path`, verifies its assigned branch, and restores context to that same checkout/branch. Generate the task-specific review package serially from this path; do not use the PM shell cwd for task endpoints. Leaves keep their dispatched inputs unchanged.

1. `HEAD_SHA=$(git -C "$FEATURE_CWD" rev-parse HEAD)`
2. `mstar sdd review-package "$BASE_SHA" "$HEAD_SHA" --context "$SDD_DIR/context.json"` — context `featureCwd` must equal the same `$FEATURE_CWD` used for `HEAD_SHA`; probes git there, writes the diff into the control sddDir, prints absolute paths.
3. Dispatch task reviewer with: brief path, implementer report path (`task-N-report.md` — an input it reads), diff path, **`REPORT_FILE` = `$SDD_DIR/task-N-review.md`** (the reviewer's own output — a different file, never the implementer's slot), Global Constraints (verbatim from plan).

**Never use `HEAD~1` as BASE** — multi-commit tasks truncate.

## Task review report file (L2 output)

The fresh task reviewer writes its full report to `task-N-review.md` — always, for every completed task under `Execution mode: sdd`: not optional, never conversation-only, separate from the implementer report it reads. Body sections and `Task quality` verdict → **`task-reviewer-prompt.md`**. This file is the L2 output only — not formal QC (`{SDD_DIR}/review/qcN.md`) and not QA, and no consumer silently searches another basename.

PM reads that named report before marking the task complete, and the ledger entry below records it. Partial findings and the `Task quality` verdict earned for the reviewed scope stay valid; assigned review scope left uncovered does **not**: PM routes the remaining scope through a fresh/tightened reviewer dispatch and does not append task-complete or release dependent work. A coverage gap is never converted into an invented code defect, and an `Approved` earned for checked scope is never overwritten.

## Bound child launch (CLI-launchable children)

**PM-only serialized launch:** when the implementer is a CLI command rather than a hosted subagent, PM holds the serialized context operation through context validation and child spawn, using the launch Assignment's fixed checkout/branch. Do not rotate context until the launch resolves. Hosted leaves never use this entry for their assigned checks; they run allowed commands directly from their verified assigned feature workdir and branch:

```bash
mstar sdd exec --context "$SDD_DIR/context.json" -- <argv...>
```

- Resolves/revalidates coordinator authority, recorded source metadata, actual checkout/branch and nesting, then spawns literal argv in featureCwd with shell:false and inherited stdio/environment. No per-row identity/lease is required. Exits remain 1=context/gate refusal without child, 2=usage, 127=spawn not found, child exit preserved, signal 128+n.
- This binds the child's **starting cwd only** — it is not a sandbox. A child that later `chdir`s, passes an overriding cwd flag, writes an absolute path elsewhere, or uses host-native edit tooling (`apply_patch`, native-session edits) is **not blocked**; no arbitrary-shell interception is claimed.

## Native hosted subagents — destination contract

Hosted subagents are not cwd-bound by the launcher, so their dispatch prompt must carry the absolute destination contract (templates: `implementer-prompt.md`, `implementer-continuation-prompt.md`, `task-reviewer-prompt.md`) and their first step is to observe, then write:

1. Observe `pwd` and the checked-out branch in the tool's workdir; both must equal the immutable Assignment `Worktree path` / branch (`featureCwd`/`workingBranch`), never a newly read value from mutable plan context. On mismatch, stop and report — a declared-correct assignment does not make a wrong-checkout write safe.
2. Source edits go through the assigned feature workdir; write the report only to its fixed task-specific path and consume brief/diff artifacts only from the dispatched paths. Do not modify shared context/progress or invoke context-writing workspace/task-brief/review-package helpers; request missing artifacts from PM.

## Fix loop

Fix subagent appends a new `## Verification round: <concrete label>` to the same `task-N-report.md`, followed by the complete affected executable test triple or applicable `scoped-check` block above, with actual output (warnings remain findings). Reuse unaffected evidence, citing its original range and why it remains applicable. Re-dispatch the owning reviewer for the assigned finding/fix delta when the required evidence is present.

The per-task fix loop applies the same fix-round mechanics as plan-level QC fix waves (SKILL.md · "After all tasks" — unverified rounds count, affected finding/fix-delta re-entry, capped cross-round excerpt, honest non-convergence): from round ≥2 the excerpt of prior rounds' findings/dispositions goes into the fix dispatch brief, and the round tally/verification history lands in `$SDD_DIR/progress.md`.

## Progress ledger

On clean task review, PM alone appends to `$SDD_DIR/progress.md`:

```text
Task N: complete (<base>..<head>, review clean, review: task-N-review.md)
```

The entry names the L2 report path the review closed on. Minor findings: append under `## Minor (for plan QC)` in same file.

Task-complete here records earned task review only. Row progress and direct complete remain the primary coordinator's ordinary domain calls; no artifact handoff transfers workflow ownership. Completion fields → mstar-artifacts/references/status-and-residuals.md; iteration execution → mstar-iteration/references/phase-2-worktree-lease.md; distinct row/outer-delivery obligations → mstar-artifacts/references/plan-workflow-lifecycle-contract.md.

## Plan-level QC package

After all tasks, PM generates the package serially from the integrated checkout with its corresponding context:

```bash
MERGE_BASE=$(git merge-base <target-branch> HEAD)
mkdir -p "$SDD_DIR/review"
mstar sdd review-package "$MERGE_BASE" HEAD --context "$SDD_DIR/context.json" "$SDD_DIR/review/branch-review-....diff"
```

Pass **branch** diff path and bundle report paths (`$SDD_DIR/review/qc1.md` …) to QC dispatch — not task-level diffs. Raw QC/QA files stay in the gitignored review bundle; PM records durable summary and open residuals in authored main plan / store.db-backed plan row through public plan verbs, and captures open findings as store.db issues (`mstar plan issue-add` / `mstar issue add`; project register only migration history) and promotes cross-clone decisions into tracked knowledge/specs/`AGENTS.md` per `mstar-conventions` git policy.

## PM context hygiene

Do not paste:

- Full plan text
- Prior task summaries ("state after Tasks 1-3")
- Full diff content

Fresh subagent gets: brief + interfaces + constraints + file paths only.

**Sticky implementer** (task 2+): resume same session; read new brief path + `progress.md` — do not re-paste prior task summaries. PM updates `implementer-session.json`.
