## Envelope fields and example

**No-progress guard note (`workflow_observations`, requires `--last-envelope`,
see the crash-recovery checklist above)** — when the hint's `next.recommended`
targeted `/unit-lane <slug>` and this run still
classifies that same unit at the same pre-advance status, append a note of the
exact shape:
`"<slug> still 'defined' after the hint's /unit-lane <slug> recommendation — triage not yet applied"`
(the note fires for a `defined` unit; the lane's triage write is what moves it
off `idea`/`defined`). The recommendation itself is unaffected — this only adds visibility.

**Shape vs. current output — read this before trusting the example below.** The
example is the envelope's **intended shape**, not everything the deterministic
producer emits today: per-unit `review`, `closure`, and `issues_born` (steps
10–12) are **not yet mechanized** by `scripts/workflow-status.mjs` and do not
appear in its output (`next.suggested[]`, step 13, is emitted — as an empty
array when nothing fired). A consumer
must read their absence as "not computed", never as `closure:
absent-legacy` or `issues_born.n: 0`; the owning note is
`ENVELOPE_CORE.md` §Not yet mechanized.

```json
{
  "skill": "workflow-status",
  "state": "OK",
  "summary": "2 features merged, 07 in-progress at P2/4 awaiting review, 05 startable, fix #43 pending triage, 08 needs design.",
  "unit": {"type": "none", "id": null, "issue": null, "branch": "main"},
  "phase": {"current": null, "total": null, "completed": null},
  "pr": {"number": null, "url": null, "state": "none", "head_sha": null, "merge_ready": null, "ci": null},
  "gates": {"verification": null, "review_pending": null, "audit_pending": null},
  "findings": {"fix_now": [{"id": "F1", "file": "src/export/handler.ts:88", "axis": "security", "severity": "high", "class": "fix-now", "route": "fold into phase", "suggested_tier": "strong"}], "issues_filed": [], "untriaged": 2, "decisions_recorded": 0},
  "blockers": [],
  "dependencies": {"unmet": [], "build_order": []},
  "recommendations": {"product_audit": false, "reason": null},
  "needs_input": null,
  "next": {"recommended": "/review-change", "alternatives": ["/unit-lane 05"], "tier": "strong",
           "suggested": [{"command": "/review-change", "trigger": "accumulation: 420 changed lines since last-reviewed sha", "source_skill": "execute-phase"}]},
  "detail": {
    "design_candidates": [{"id": "08-billing-webhooks", "status": "idea", "next": "/unit-lane 08-billing-webhooks"}],
    "pre_execution": [{"unit": "12-export-api", "unitDir": "docs/features/12-export-api", "stage": "lane", "label": "current", "verdict": "READY", "boundDigest": null, "observedDigest": null, "recommended": "/unit-lane 12-export-api", "reason": "unit-doc currency is checked per step by unit-lane/execute-phase"}],
    "features": [
      {"id": "07-csv-export", "status": "in-progress", "deps": ["01"], "deps_unmet": [],
       "phase": {"current": "P2", "total": 4}, "pr": null,
       "review_pending": true, "audit_pending": null, "merge_ready": null,
       "review": {"last_checkpoint_sha": "a1b2c3d", "unreviewed_diff": {"lines": 420, "files": 9},
                   "terminal_done": false, "adversarial": {"ran": null, "n": null}},
       "closure": {"state": "present"}, "issues_born": {"n": 0, "with_descope_amendment": 0}},
      {"id": "05-auth", "status": "defined", "deps": [], "deps_unmet": [],
       "phase": {"current": null, "total": null}, "pr": null,
       "review_pending": null, "audit_pending": null, "merge_ready": null,
       "review": {"last_checkpoint_sha": null, "unreviewed_diff": {"lines": null, "files": null},
                   "terminal_done": false, "adversarial": {"ran": null, "n": null}},
       "closure": {"state": "absent-legacy"}, "issues_born": {"n": 0, "with_descope_amendment": 0}}
    ],
    "fixes": [
      {"id": "43-null-crash", "issue": 43, "status": "planned", "deps_unmet": [], "pr": null,
       "review": {"last_checkpoint_sha": null, "unreviewed_diff": {"lines": null, "files": null},
                   "terminal_done": false, "adversarial": {"ran": null, "n": null}},
       "closure": {"state": "n/a"}, "issues_born": {"n": 0, "with_descope_amendment": 0}}
    ],
    "startable_now": ["05-auth", "fix-43"],
    "blocked_units": {"09-billing": {"unmet": ["05-auth"], "build_order": ["05-auth", "09-billing"]}},
    "open_prs": [{"number": 13, "unit": "07-csv-export", "ci": "green", "merge_ready": false}],
    "pending_triage": [{"source": "docs/features/07-csv-export/known-issues.md", "title": "empty-file edge"}],
    "untriaged_issues": {"count": 3, "oldest_open": [21, 33, 40]},
    "workflow_observations": ["branch feat/07-csv-export is 1 commit ahead of origin"],
    "urgent": {
      "issues": [{"number": 51, "title": "prod webhook signature check bypassed", "label": "urgent"}],
      "interruptibility": {"unit": "07-csv-export", "phase": "P2", "dirty": true, "tasks_from_boundary": 2}
    },
    "crash_recovery": {
      "verdict": "CLEAN",
      "branches": [
        {"branch": "feat/07-csv-export", "evidence": "1 commit ahead of origin; ledger coherent", "verdict": "CLEAN", "resume_command": null}
      ]
    }
  }
}
```

`detail.startable_now`, `detail.blocked_units` (with build orders),
`detail.pre_execution` (one lane row per open unit from step 6a, `{unit, unitDir, stage: "lane", label: "current", verdict: "READY",
boundDigest: null, observedDigest: null, recommended, reason}`) and
`detail.pending_triage` are the keys an
orchestrator routes on; every id in `startable_now`/`blocked_units` must appear
fully in `features`/`fixes` — an `idea` unit appears ONLY in
`design_candidates` (and `detail.features`), never in `startable_now`, since
it has no deps-met check to pass (design precedes dependency startability).
`05-auth` above illustrates `defined` (not yet `planned`): startable, next
`/unit-lane`, phase fields null (no planning artifacts yet).

## The `--compact` projection

The envelope above is the complete one. `--compact` emits the **same shape and the
same decisions** with repository history dropped, because a poll loop pays for
that history in context on every read while no consumer of "what can I do now"
reads it. On this repository it is roughly half the bytes.

Exactly two fields change:

- `detail.features` / `detail.fixes`: a `done` row is dropped **only on positive
  proof its linked PR merged** (the merge resolver). An unmerged `done` row is
  still at the merge gate and stays; every row in `idea`/`defined`/`planned`/
  `in-progress` stays in both modes, so `detail.startable_now` and
  `detail.blocked_units` keep naming every unit either way.
- `findings.fix_now[].route`: the reviewer's multi-paragraph evidence memo becomes
  `...(N char evidence, see the unit review-findings.md)` for a legacy carrier and
  `...(N char evidence, see the unit SPEC.md ## Findings)` for a migrated one (#308),
  keeping the original
  length visible. `id`, `file`, `axis`, `severity`, `class` and `suggested_tier`
  are untouched, and the memo is on disk in the unit's `review-findings.md`, which
  is where the fold reads it.

`detail.workflow_observations` is **not** reduced in either mode. Every note the
sensor writes is a signal — an unmapped roadmap status, a slug that refused its
files, a ledger severity outside the published enum, git and forge state, the
`--last-envelope` guard's divergence note — and they total about a kilobyte, so
trimming them would trade a real signal for no measurable win. The size comes from
`features` and the route memos, which are an order of magnitude larger and pure
history.

Everything else is byte-identical: `state`, `summary`, `unit`, `phase`, `pr`,
`gates`, `blockers`, `dependencies`, `recommendations`, `needs_input`, all of
`next` (`recommended`, `alternatives`, `tier`, `reason`, `candidate_count`,
`suggested`, `continuation`), `detail.repository_state`, `design_candidates`,
`pre_execution`, `review_loop_cycles`, `crash_recovery` and `urgent`. A consumer
may therefore switch modes per read without changing how it parses.
