# Rules for an autonomous stream session
<!-- Role: the one place the overnight/weekend session rules live. Every /stream-* command
     points here instead of repeating them (build plan §3c: one home per mechanism). -->

You are one of several sessions working in the same working tree at the same time. Nobody is
watching. These rules are what make that safe.

## Where you are
- Your cwd must be `/srv/apps/dutyfreeprofessor`. If `pwd` says otherwise, stop and say so;
  the checkpoint hook and the project commands only work from here.
- Read, in this order and nothing more to start: your stream brief (the command names it),
  `agents.md`, `brief.md`, build plan `.logs/planning/build-plan-2026-09.md` §2 (tokens and
  migration order), §7 (your row), §9 (decisions), and `.logs/decisions-for-rian.md` (generated from the running list; read, never edit). Do not
  read all of `.logs/handoff.md`; the last three entries at most.

## What you may touch
- Only the files your brief lists under **Owns**. Everything under **Must not touch** is another
  session's. If your task genuinely needs a change there, write the exact request under
  the running list as an issue owned by that stream (`python3 main/scripts/items.py add --kind issue --owner <X> --by "Stream <you>" --title ... --detail "file, change, why"`) and continue with work
  that does not depend on it. Never edit another stream's file "just this once".
- `main/check.sh` is run by everyone and edited only by Docs tonight.

## What you never do
- **Never deploy.** Rian holds the deploy token. Say "green and ready" in your handoff line.
- **Never run a migration against the live database**; use `dfp-devdb` (127.0.0.1:5433).
- **Never run a network collection or crawl** unless your brief names it for tonight and you
  have announced it in `.logs/runs/`. A single robots.txt read per host to test code is fine.
- Never `git push`, never rewrite history, never touch `.env`, `.app.env`, `.bw-auth.env`.
- Never write client-facing text with em dashes, or the words "cheap", "free", or anything
  implying the code is the client's or can move without rian.

## How you work
- **Plan-gate proportionally**: a structural or multi-file change gets a short written plan in
  your handoff entry before code; a one-file fix does not.
- **Delegate to conserve tokens.** You (Fable) design, decide, and review. Hand mechanical
  subtasks to a subagent with the Agent tool: `model: "sonnet"` for test scaffolding, fixture
  trimming, docstring passes, backfill scripts, generated maps, bulk edits from a precise spec;
  `model: "haiku"` for pure text transformations. Give the subagent the exact files and the
  acceptance test; **verify its output yourself** (run the tests, read the diff) before you
  commit it. Never delegate a decision, a security-relevant change, or anything touching
  identity/matching rules.
- **A bug that shipped becomes a test** with the real record that failed and what it cost.
- Run `../.venv-dev/bin/pytest tests -q` and `main/check.sh` before every commit.

## When you are blocked on something only rian can decide
Do not stop. Add it to the running list (`python3 main/scripts/items.py add --kind decide --by "Stream <X>" --blocks <task id> --weight blocking|costly --title ... --detail ... --option ... --assumption ...`): the question, the
options, **the assumption you are proceeding under**, and what you will have to redo if he
chooses otherwise. Then continue with everything that does not depend on it.

## How you record progress (this is how rian sees the night's work)
- When you start a task: `python3 main/scripts/plan-set.py <ID> doing "Stream <X>"`.
- When it is verified done: `python3 main/scripts/plan-set.py <ID> done "Stream <X>" --note "<what proves it>"`.
- Blocked: `... blocked ... --note "<why>"`. The `/plan` page reads this live.
- Tasks carry `due` (ISO date) and some `rian: true`; the `quote` block maps the sixteen accepted
  lines to task ids and their status is derived. Never edit those by hand in a stream session; if a
  task's date must move, say so in the hand-back note and the planning session moves it.
- Commit each finished task with your stream prefix (`A:`, `B:`, `Docs:`, `A2:`, `Q:`), a
  subject line, and a body that says what it cost or what it prevents. One task, one commit.
- Add a line under `## Unreleased` in `main/CHANGELOG.md` for anything a user or the client
  would notice. Do not bump the version; rian does that at the deploy checkpoint.
- Before the loop ends (or every ~3 hours of work), prepend a handoff entry to
  `.logs/handoff.md`: ≤25 lines, **state not summary**: what landed and how it was verified,
  what is in flight, what is next, what you need from rian. Link to docs; do not explain
  mechanisms there. Then run the project `/checkpoint`.

## Telling rian as you go (Telegram)
Rian is not watching `/plan` at 3am. `srv-gw notify --from "<stream>" "<message>"` puts one line on
his phone. The bot token and the destination live in the gateway and never reach your argv or the
transcript, so **never put a password, key, token or URL with a secret in a message** (it leaves the
server). Owner sessions only; a developer session gets 403 and should carry on silently.

Send one line, and only at these moments:
- **Starting**: `srv-gw notify --from "K3" "K3 starting: 7 tasks, identity"`.
- **Each task done**, with the count so progress is obvious: `"K3.2 done (2/7): options come from
  the collector's own fields"`. On a stream of more than ten tasks, send only at roughly a quarter,
  a half and three quarters instead, plus the two below.
- **Blocked or needing rian**: say what you need and what you assumed, and that you have carried on
  or stopped: `"K3 BLOCKED on K3.4: the boundary needs rian's call; assumed the narrow list and
  continued"`.
- **Hand-back**: `"K3 done: 7/7, check green, handoff written; K5 may start"` or, if you stopped
  early, what remains.
Nothing else. No per-commit messages, no "still working", no long text: a phone line is about a
hundred characters. If `srv-gw notify` fails, record it in the handoff and carry on; a failed
message never stops or delays the work.

## The loop
Each iteration: take the next unfinished task from your brief in order; finish it to the
verified-and-committed standard; record it; move on. When the brief's tonight list is
exhausted, do "If time remains". When that is exhausted, or you have been going for eight
hours, write the final handoff and **stop the loop** (do not idle-poll). If a task turns out to
need more than about three hours, split it, record the split on `/plan` with a note, and keep
the part that lands tonight.

## Urgency comes from the plan, not the calendar
Every item you raise names the plan task it gates (`--blocks A8`, repeatable) and a weight:
`blocking` (that task must not start until rian answers), `costly` (work can proceed under
the stated assumption, but reversing it later is expensive), `info` (nothing waits on it).
The page ranks items from those gates and the live task statuses, so rian sees what to
answer before the work goes further. An item with no gate and no weight is informational and
sits at the bottom; do not raise a decision that way if a task really depends on it.
