## mcue access rules

This project uses [mcue](https://github.com/ck46/mcue) for its
operating state — current objective, blockers, next action, resume
pointer, and checkpoint history. mcue is a local-first CLI and its
state is file-backed under `~/.mcue/`.

**Agents working on this project must access mcue only through the
CLI or (when available) the MCP read surface. Do not read or edit files
under `~/.mcue/` directly.**

### Start here, every time

Before any project work, recover context from mcue. This is the first
step at the start of a chat, again after your context is compacted or
reset, and again whenever the operator switches project or workstream.
It applies to **every kind of request** — a review, a fix, an
explanation, a question about a named file, a new idea — not only to
"where were we". The one exception is an explicit operator instruction
to skip it. Reading instruction files and discovering your tools first
is fine; searching the repository for the answer is not.

1. **Find the project.** A project the operator names wins. Otherwise
   start from the cwd: `mcue review` with no id resolves the `.mcue`
   footprint there. If neither settles it, `mcue index` lists every
   project — pick the one the operator is talking about, not the one you
   saw last.
2. **Discover its lanes.** `mcue review <project-id>` lists the active
   lanes by name with each one's next action. Lanes are streams of work,
   not branches; the list is dynamic, so read it rather than assuming.
3. **Select the lane by the operator's current request.** Match what
   they asked for now against the lane names and next actions in that
   list; where two or three look plausible, `mcue review <project-id>
   --lane <lane-id>` shows each one's objective — check those, not all
   of them. When two candidates' objectives do not separate them, read
   both packets and say which fact decided it. Never select by recency,
   by the Git branch name, or by an assumed default. If nothing matches,
   read the nearest candidate's packet before deciding; if it still does
   not fit, say so and continue on the project's context — do not force
   the request into an unrelated lane and do not create a lane silently.
4. **Read the bounded packet for that lane.** `mcue resume <project-id>
   --lane <lane-id>` (`--tier expanded` when you are reviewing or
   deciding, or when the minimal packet arrives truncated). It tells you
   what was decided, what is known to be open, and where the last
   session stopped.
5. **Only then open the artifacts and code**, and check the recorded
   state against what is actually there now.

Reuse that context for ordinary follow-ups in the same lane; do not
re-read state on every message. Re-run the procedure on the triggers
above, not on a timer: from step 1 when the project changes, from step 2
when the workstream changes inside the same project. If re-running lands
on the same lane, keep the packet you have unless something was written
since; only a changed lane needs a fresh read.

**Say which lane you are using, in one line, when you select or switch
it** — for example "Using `agents-contract`: this request changes how
agents select and write to lanes." It is a statement, not a question;
ordinary follow-ups reuse the selection without repeating it, and a
re-selection that lands on the same lane needs no new statement. A wrong
assumption is cheap to correct here and expensive after the work.


Skipping this is the failure mcue exists to prevent: an agent that
searches the repo first will re-derive findings the lane already holds
and miss the decisions behind the artifact it is looking at.

### The operator's request decides the work

Recorded state tells you what was decided, what is known, and where
things stood. Preserve it, its provenance, and its signals. It does
**not** tell you what to do now: the operator's current instruction
determines the requested work, and a saved next action never overrides
it. If they ask for a review, review; do not start executing the lane's
next action because it is recorded.

Keep three things distinguishable in what you say: what mcue recorded
(and who wrote it — an agent-authored checkpoint is a proposal that was
accepted, not a verified fact), what you are proposing, and what you
have verified in the current code or artifacts this session. When the
current implementation contradicts recorded state, say so; do not
silently pick one.

### One source of state at a time

Local state and Hub state can differ. Every mcue read comes from one of
them, and you must know which.

- If output carries a warning — "Hub refresh skipped", "not logged in",
  a stale-local note — keep that warning in your answer and treat the
  state as possibly behind. Do not present stale local state as the
  accepted Hub state.
- A clean read on one surface never resolves a conflict reported on
  the other. If the Hub says a lane has unreconciled perspectives and
  the local CLI says none, those are two views of the lane; switching
  surfaces is not reconciliation. Surface the difference to the
  operator and stop there.
- Fully offline local use is valid. Say which source you read and move
  on.

### When you must propose a closeout

Closeout is the **only way** session work survives into the next
session. If you observe any of these signals during work and the
operator hasn't already closed out, **proactively propose** a
`mcue closeout <project-id> --lane <lane-id>` command before the
session ends:

- Operator sign-off cues: "thanks, that's all," "good for today,"
  "stopping for now," "that's it," "we're done here"
- A discrete unit of work just shipped — a feature, a bug fix, a
  draft, a documented decision
- A ship event just happened — a release cut, a PR merged, an issue
  closed, a deploy completed. **Propose the closeout in the same
  message that reports the ship**; a proposal deferred to
  end-of-session is usually forgotten, and the lane's recorded
  next-action goes stale while the work it describes is already done
- Before moving to a *different* project mid-session
- After substantial work has happened in a single session without
  a checkpoint (rough heuristic: ~30+ minutes of meaningful changes)
- When the operator asks "what did we do today?" or asks for any
  session summary

Closeout remains operator-owned: **propose once**, then run only if
the operator confirms in the same turn. Use `--provenance agent` and
let trust cap at medium — that is correct, not a bug to bypass. Write
to the lane you selected in the startup procedure; if the work drifted
into another lane, say which and let the operator choose.

On a Hub-linked project a confirmed closeout also runs a full Hub sync
(push and pull) once the write commits — say so when you propose, so
the operator knows the session will converge with the Hub. Pass
`--no-sync` only when the operator asks for an intentionally local
closeout. A sync failure never fails the closeout; relay the pending
count and the `mcue sync` retry command from stderr instead of
retrying yourself.

**Do not wait to be asked.** The cost of forgetting: any work the
operator did during the session that wasn't closed out is invisible
to mcue on the next session. The next `mcue review` will
report "no work yesterday" even when the operator clearly worked.
Volunteer the closeout proactively; let them choose to skip it if
they want.

**Check alignment before you propose.** Compare the completed work and
the proposed next action with the objective of the lane you selected.
Do not broaden the lane's objective to justify where the work happened.
If the work belongs to another lane, route the closeout there. If the
session produced work for two independent streams, prepare two
closeouts. If no suitable lane exists, that is one concise scope
decision for the operator — never a silent write to the nearest lane.
When ownership or scope genuinely changed, say so and propose updating
the lane's stored objective, next action, and pointer in the same turn,
not just a note in the checkpoint; the next agent selects by the stored
objective.

### Commands you may use

Read-only:

- `mcue index` — cross-project portfolio view. Use to see what's
  active and pick a project. `--expand-lanes` shows lane rows.
- `mcue review [<project-id>]` — current operating state for a
  single project: objective, active lanes with their next actions,
  blockers, resume pointer, clarity / cost / freshness / trust / drift
  signals, latest checkpoint summary, active plan progress. If the
  operator's cwd has a `.mcue` footprint, the project id can be
  omitted.
- `mcue resume [<project-id>] [--lane <id>]` — bounded resume packet
  for re-entry. Use this when starting work on a lane. `--tier
  expanded` for the longer packet. Same cwd-resolution behavior as
  review.
- `mcue drift [<project-id>] [--lane <id>]` — show observed Git drift
  across active lanes (or one lane with `--lane`).
- `mcue plan show [<project-id>] [--lane <id>]` — show the active
  plan on a lane: objective, steps with completion state, current
  step, blockers.

Mutating (operator-owned):

- `mcue closeout [<project-id>] --lane <id> --intent ... --outcome ... --next-action ... --resume-pointer ... --provenance agent`
  — end-of-session closeout. **Propose once**, then run only if the
  operator confirms in the same turn. Always include
  `--provenance agent` when you compose the content; trust will cap
  at medium, which is the correct behavior — do not try to bypass it.
  - For long prose, prefer `--intent-from-file` / `--outcome-from-file`
    / `--blockers-from-file` / `--next-action-from-file` so the shell
    quoting wall doesn't fight you. The path is a normal file on the
    operator's machine.
  - For full automation, `--from-stdin-json` accepts the whole payload
    as JSON.
  - To advance an active plan in the same closeout, pass
    `--plan-step <n> --plan-status done|in_progress|blocked`.
  - **Do not pass `--objective`** unless the operator has explicitly
    asked you to update the project's stable goal. The objective is a
    long-lived field the operator owns; closeout should leave it
    untouched in the normal case. `--next-action` is the right place
    for the immediate next step.
- `mcue update <project-id> --objective "..."` — set or update the
  project's stable objective without doing a closeout. Operator-owned
  metadata change; **propose, do not execute** unless the operator
  confirms.
- `mcue lane update <project-id> <lane-id> --objective "..."` — update
  a lane's stored objective (or `--name`) when its ownership or scope
  has changed; this is the update the pre-closeout alignment check asks
  you to propose. Operator-owned; **propose, do not execute** unless the
  operator confirms.
- `mcue lane create <project-id> <lane-id> --name ... --objective ...`
  — open a new stream of work. Only when the operator asks for it or
  agrees in the same turn that the work is a new stream; never as a
  side effect of not finding a matching lane.
- `mcue attach <project-id>` — write a `.mcue` footprint in cwd
  so subsequent commands resolve the project from cwd. Safe to run;
  refuses on conflict.
- `mcue recover <project-id>` — recover an interrupted session.
  Only run when an explicit stale lock is visible and the operator
  has approved.

### Agent mode (path scrubbing)

If you produce output that other tools will consume (logs,
transcripts, diffs), prefix the invocation with
`MCUE_AGENT_MODE=1` or pass `--agent` to replace the operator's
home directory with `~` in command output. This keeps absolute paths
out of artifacts that may be shared.

### What you must not do

- Do **not** read `~/.mcue/projects/<id>/project_state.md`, any
  file under `~/.mcue/projects/<id>/checkpoints/`,
  `~/.mcue/registry/projects.yaml`, or any other file under
  `~/.mcue/` directly. Reading these bypasses token budgets,
  freshness / trust signals, validation, and the audit log — it
  consumes unbounded context and defeats the purpose of the tool.
- Do **not** edit any file under `~/.mcue/` directly.
- Do **not** re-summarize mcue output into something else or override
  its signals. Quote it, then add what you verified and what you
  propose, labelled as such.

### If `mcue` isn't on PATH

Fresh shells sometimes don't inherit the operator's profile PATH. If
`mcue: command not found`, try:

```bash
source ~/.zshrc && mcue <...>
```

(or `source ~/.bashrc` on bash systems). Do **not** fall back to
direct file reads — that is not a valid workaround for a PATH hiccup.

### When mcue refuses or blocks

mcue's refusals are designed states, not errors to work around. Each
has a correct next move:

- **"Lane has N unreconciled perspectives"** — the lane carries
  divergent writes and `review`/`resume` refuse to pick a winner. Run
  `mcue reconcile <project-id> --lane <lane-id>` **without `--pick`**:
  that form is read-only and lists every candidate's intent, outcome,
  next-action, and blockers. Ground what you can in that listing, then
  surface the divergence to the operator with a recommendation.
  Reconciliation is operator-owned: pass `--pick` only when the
  operator names the winner in the same turn. Reading the same lane on
  another surface does not resolve it.
- **"project has multiple active lanes"** — not an error. Re-run with
  `--lane <lane-id>` chosen by the operator's current request from the
  listed options, or ask.
- **"lane locked by ..."** — another writer holds the closeout lock.
  Retry briefly. If the operator confirms no writer is live (a crashed
  session), propose `mcue recover`; never run it unprompted.
- **Anything else you can't act on** — a refusal with no listed next
  step, or state that contradicts what the operator just told you:
  **raise it with the operator in the moment as a product finding.**
  mcue is dogfooding; friction you silently absorb is a bug report
  lost.

### If the CLI doesn't have the affordance you need

Ask the operator. A missing CLI affordance is a product gap worth
logging, not a reason to fall back to direct file access. Continue
with whatever part of the request does not depend on it.

### Where this file lives

Codex, Cursor, and Aider read `AGENTS.md`; Claude Code reads
`CLAUDE.md`. Keep this text in the file your client reads at the root
of the repository the agent starts in. A workspace-level file is not
loaded when the agent starts inside a child repository, so each
repository that carries mcue state needs its own copy or a one-line
file that points to the root one. To verify loading, open a fresh chat
and ask "what is the first thing you do before project work here?" —
the answer should be the Start-here procedure, given without a search.

### One-line rule

**Treat mcue as an opaque service reached through `mcue`. Read the
lane before the repo. The operator's request decides the work; the CLI
output is the contract.**

<!-- generated from mcue v0.22.0 by scripts/generate-agent-assets.mjs -->
