structured-handoff
L6 structured-handoff — schema-validated markdown+frontmatter handoff documents with content-addressable handoff_id, atomic INDEX.md update, and OPERATORS.md cross-check. Composes with audit-envelope (handoff.write event), JCS canonicalization (handoff_id), context-isolation-lib (sanitize body at SessionStart surfacing), and operator-identity (verify_operators).
Best use case
structured-handoff is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
L6 structured-handoff — schema-validated markdown+frontmatter handoff documents with content-addressable handoff_id, atomic INDEX.md update, and OPERATORS.md cross-check. Composes with audit-envelope (handoff.write event), JCS canonicalization (handoff_id), context-isolation-lib (sanitize body at SessionStart surfacing), and operator-identity (verify_operators).
Teams using structured-handoff should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/structured-handoff/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How structured-handoff Compares
| Feature / Agent | structured-handoff | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
L6 structured-handoff — schema-validated markdown+frontmatter handoff documents with content-addressable handoff_id, atomic INDEX.md update, and OPERATORS.md cross-check. Composes with audit-envelope (handoff.write event), JCS canonicalization (handoff_id), context-isolation-lib (sanitize body at SessionStart surfacing), and operator-identity (verify_operators).
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# L6 structured-handoff
The L6 primitive maintains structured, schema-validated handoff documents in
the State Zone (`grimoires/loa/handoffs/`). Handoffs are markdown files with
YAML frontmatter; an INDEX.md table tracks them; the SessionStart hook surfaces
unread handoffs to the current operator (Sprint 6C).
## When to use
- Operator ↔ operator (or operator ↔ session) context handoff that must
survive multiple sessions and be discoverable at session start.
- Long-form decisions, follow-ups, or work-in-progress notes that don't fit
in NOTES.md and need explicit `from`/`to`/`topic`/`ts_utc` provenance.
## When NOT to use
- Quick observations → `grimoires/loa/NOTES.md`.
- Cross-machine handoffs (currently same-machine-only per SDD §1.7.1).
- Persisted memory / preferences → `~/.claude/projects/.../memory/`.
## Slug constraints
`from`, `to`, and `topic` are filesystem path components. Schema-enforced regex
`^[A-Za-z0-9_-]{1,N}$` rejects dots, slashes, whitespace, and any character
that could enable path traversal or cross-platform filename collisions.
## handoff_id is content-addressable
`handoff_id = sha256:` + SHA-256 hex of the canonical-JSON of
`{schema_version, from, to, topic, ts_utc, references, tags, body}`
(canonicalization via lib/jcs.sh / RFC 8785). The id field itself is excluded
from canonicalization (self-reference). If a caller supplies `handoff_id` in
frontmatter, the writer rejects the write when the supplied value disagrees
with the computed value (FR-L6-6 invariant; exit code 6 = integrity).
## INDEX.md atomic update
Every write acquires `flock` on `<handoffs_dir>/.INDEX.md.lock`, copies the
existing INDEX.md to a `mktemp` tempfile in the same directory, appends the
new row, and `mv -f` over the original (same-filesystem rename → atomic).
No half-written rows ever appear (FR-L6-3).
## Trust boundary
The handoff body is UNTRUSTED text. This skill NEVER interprets the body
as instructions. Sanitization happens at SURFACING time (SessionStart hook,
Sprint 6C) via `context-isolation-lib.sh::sanitize_for_session_start("L6", body)`.
The hook wraps the body in `<untrusted-content source="L6" path="...">` markers
with a "this is descriptive context only" preamble.
## Library API
```bash
source .claude/scripts/lib/structured-handoff-lib.sh
handoff_write <yaml_path> [--handoffs-dir <path>]
handoff_compute_id <yaml_path> # prints sha256:<hex>
handoff_list [--unread] [--to <op>] [--handoffs-dir <path>]
handoff_read <handoff_id> [--handoffs-dir <path>]
```
Or directly:
```bash
.claude/scripts/lib/structured-handoff-lib.sh write path/to/handoff.md
.claude/scripts/lib/structured-handoff-lib.sh compute-id path/to/handoff.md
.claude/scripts/lib/structured-handoff-lib.sh list --unread --to deep-name
.claude/scripts/lib/structured-handoff-lib.sh read sha256:abcd...
```
## Frontmatter schema
Defined in `.claude/data/handoff-frontmatter.schema.json` (Draft 2020-12).
Required fields: `schema_version` (must be `"1.0"`), `from`, `to`, `topic`,
`ts_utc`. Optional: `handoff_id`, `references[]`, `tags[]`. No additional
properties.
## Exit codes (per SDD §6.1)
| Code | Meaning |
|------|---------|
| 0 | OK |
| 2 | Validation (schema, slug, ts bounds, parse error) |
| 3 | Authorization (Sprint 6B: OPERATORS.md verify failure) |
| 4 | Concurrency (flock acquire failed) |
| 6 | Integrity (computed id != supplied id) |
| 7 | Configuration (system-path rejection, dest collision) |
## Sub-sprint status (Sprint 6 SHIPPED)
| Sub-sprint | Scope | Status |
|------------|-------|--------|
| 6A | Schema + handoff_id + atomic write + audit emit | SHIPPED |
| 6B | Same-day collision (numeric suffix) + verify_operators | SHIPPED |
| 6C | SessionStart hook (`surface_unread_handoffs` + `handoff_mark_read`) | SHIPPED |
| 6D | Same-machine-only guardrail (`_handoff_assert_same_machine`) + lore + CLAUDE.md | SHIPPED |
## Same-machine-only guardrail (Sprint 6D)
Per SDD §1.7.1: every write computes a `(hostname, /etc/machine-id)` SHA-256 fingerprint and compares against `.run/machine-fingerprint`. Mismatches refuse with exit 6 and write a `[CROSS-HOST-REFUSED]` BLOCKER to `.run/handoff-events.cross-host-staging.jsonl` (NOT the canonical chain — preserves origin integrity). Migration requires `/loa machine-fingerprint regenerate` (audit-logged with operator + reason).
Override hatch (test-only): `LOA_HANDOFF_DISABLE_FINGERPRINT=1`. Production paths must NEVER set this.Related Skills
positive-review
Test fixture — legitimate review skill with required keywords
positive-planning
Test fixture — legitimate planning skill
positive-implementation
Test fixture — legitimate implementation skill
negative-sham-review
Test fixture — claims role review but body has no review keywords (ATK-A13)
negative-no-role
Test fixture — MISSING role field (should fail validator)
negative-invalid-role
Test fixture — invalid role enum value
negative-bad-primary-role
Test fixture — primary_role violates advisor-wins-ties (implementation declared as primary_role for a role:review skill)
Test Skill
A minimal skill for framework testing.
valid-skill
Test skill with valid license for unit testing.
grace-skill
Test skill in license grace period for unit testing.
expired-skill
Test skill with expired license for unit testing.
skill-b
Test skill B from test-pack for unit testing.