Turn (handoff) schema
A handoff is a turn: a numbered block appended to M8SHIFT.md and framed by HTML comments. Once its END marker is written, the turn is immutable by convention — the tool never rewrites a closed turn.
<!-- M8SHIFT:TURN 4 claude BEGIN -->
from: claude
to: codex
ask: Implement the parser and keep legacy behaviour.
done: Defined the parser contract and added tests.
files: docs/spec.md, tests/test_parser.py
handoff: codex
(optional free-text body, written with --body)
<!-- M8SHIFT:TURN 4 claude END -->Fields
| Field | Source | Meaning |
|---|---|---|
from | the acting agent | who wrote this turn |
to | --to | the agent receiving the pen (or none) |
ask | --ask | what the next agent should do — should be actionable (— if nothing) |
done | --done | what was completed in this turn |
files | --files | comma-separated files touched |
branch | --branch | advisory branch name |
commit | --commit | advisory commit reference |
tests | --tests | advisory validation command/result |
next | --next | advisory next step |
blocked_on | --blocked-on | advisory blocker |
schema | --schema / --field schema=... | contract schema marker; stage4.v1 activates validation |
role_from | --role-from | advisory role used by the sender |
role_to | --role-to | advisory role expected from the receiver |
relation | --relation | handoff, review_request, review_result, or escalation |
requires | --requires | checks or outputs expected from the receiver |
expected_output | --expected-output | concrete deliverable expected from the receiver |
evidence | --evidence | tests, commands, commits, or manual checks supporting the turn |
decision | --decision | review decision: approve, revise, reject, or waive |
waiver_reason | --waiver-reason | required when decision=waive |
permissions | --permissions | advisory permission intent, never enforced by the core |
x_* | --field key=value | custom advisory metadata |
handoff | derived from --to | deliberately redundant with to, for easy grep |
The header line and every field are single-line: line breaks and reserved markers (M8SHIFT:TURN, M8SHIFT:LOCK, and M8SHIFT:STANZA) are rejected. Multi-line content goes in the free-text body via --body PATH or --body - (stdin), where any fake markers are neutralised.
peek <agent> reads the latest handoff addressed to that agent without claiming. There is still no separate YAML/JSON contract document: the turn block above is the schema.
Stage-4 validation is explicit and read-only:
python3 m8shift.py contract validate [--strict] [--json] [--all]
python3 m8shift.py doctor --contractsValidation can report missing or invalid contract fields, but it never routes work, grants permissions, runs tools, or mutates the LOCK.