Files
6krrt/plans/docs-lift-a-pass.md
adlee-was-taken 69c969d104 plans: declare a valid Status on the six plans this branch adds
tests/test_plans_declare_status.py requires 'Status: <done|planned|in
progress|parked|reference> -- <reason>' in the first 8 lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N9biTbFC63yDfYfUsZmhgd
2026-09-26 21:46:15 -04:00

106 lines
6.1 KiB
Markdown

# Docs pass after Lift A (PR #102)
Status: done -- executed on branch docs/lift-a-docs-pass
Date: 2026-09-26
This brief is the contract. Keep the plan small: one todo per doc, each with
exact section anchors. Do NOT read `plans/no-progress-detection.md` (reference
only).
## Goal
Bring the docs in line with what PR #102 shipped and what is running now. The
docs describe the code as it is on this branch; where a doc and the code
disagree, the code wins, and the todo says which line it checked.
## Where the work happens
- Worktree: `/home/alee/Sources/6krrt-worktrees/docs-lift-a-pass`, branch
`docs/lift-a-docs-pass`, based on `origin/main` `a24de1b` plus three commits
that already carry North Star #4 in `CLAUDE.md`, the incident #8 rewrite in
`docs/incidents.md`, and the plans. Build on them; do not rewrite them.
- **Docs only.** No code, config, test or unit-file changes.
- **Do not touch** `README.md`, `AGENTS.md`, `deploy/README.md`: the owner has
uncommitted edits to them in the main checkout. Anything that belongs in
`deploy/README.md` goes in `docs/watchdog.md` instead, and the done report
lists it for the owner to fold in.
## What shipped (verify each against the code before writing it)
- `src/progress_detect.py`: pure detector. Signals dup, top, slow, coverage;
landed gating; read-only agents; canonical (sorted-key) args; bash command
normalization (comment lines, `cd dir &&`, `VAR=x` prefixes dropped).
- `src/watchdog.py` + `deploy/llm-router-watchdog.{service,timer}`: 5-minute
oneshot. Judges only sessions with a tool call since the last tick, on their
full history, per session; landed counts the session's own descendants only.
Alert lifecycle in `watchdog_alerts`: trigger once, escalate once (LLM yes or
3 ticks), resolve once. Quiet `no_opencode` tick when opencode is closed.
Optional local-model second opinion (does not veto).
- `src/notifier.py`: `desktop` channel (`notify-send`), PagerDuty-Events-v2
shaped `AlertEvent`, per-channel `min_severity`, rate limit backed by the DB.
- `src/watchdog_store.py`: tables `watchdog_ticks`, `watchdog_verdicts`,
`watchdog_alerts`, `watchdog_channel_settings`.
- Admin: Loops panel (`index.html#loops`), Watchdog card on Controls (last
tick, verdicts, channels, Send test alert), per-model stall rollup and
Block/Unblock on Models. New availability value `blocked`, excluded from
routing and from pinned requests via `_admin_excluded_models`.
- Endpoints: `GET /admin/api/watchdog/status`, `POST /admin/api/watchdog/channels`,
`POST /admin/api/watchdog/test-alert`; availability endpoint accepts `blocked`.
- Config: `watchdog.*` (incl. `detector.*`, `dashboard_base_url`),
`notifications.channels`. Watchdog knobs are persisted-only (separate process).
- `deploy/opencode-plugin/router-link.js`: the `parentCache` export made
opencode 1.18 reject the whole plugin ("Plugin export is not a function" in
`~/.local/share/opencode/log/opencode.log`), so identity headers never
reached the router from #99 until this fix. A loader-contract test now asserts
every export is a function.
- `scripts/progress_backtest.py` (`--fixture` replays the 15 labelled sessions;
expect 8/15 flagged) and `scripts/export_progress_fixture.py`.
- Operator state 2026-09-26: timer enabled ~15:18 EDT with unit paths repointed
from `%h/llm-router` to `%h/Sources/6krrt` (production still runs from the
dev checkout; see `plans/deploy-separation.md`); plugin fix installed and
opencode restarted 15:19; router restarted 15:19:57.
## Todos (one per doc)
1. **New `docs/watchdog.md`**: what it catches and does not (steady spend is not
waste), signals and thresholds, alert lifecycle, the admin surfaces, knobs,
install (the `sed` repoint + `enable --now`), how to run `--once`, backtest,
re-exporting the fixture, and known limits: sessions under 40 calls are
invisible; the Atlas must-flag case sits exactly at `cover_min` 4.0; the
stale `localhost:4096` entry in `rc-servers.json` logs a harmless probe
warning.
2. **`CLAUDE.md`**: "What's built and working" (anchor `## What's built and
working`): add the modules above in the existing one-bullet style, linking
`docs/watchdog.md`; update the `tests/` bullet count from the real
`pytest --collect-only -q` total. "Run as a service" (anchor `## Run as a
service`): one short paragraph on the watchdog timer. Do not edit the North
Star section.
3. **`docs/incidents.md` #8**: under Status, add that Lift A shipped (PR #102,
`a24de1b`) and the timer is live; add the plugin-loader finding as Evidence
(with the log line) and to the Human response timeline; add a symptom-table
row "opencode plugin does nothing -> grep opencode.log for `failed to load
plugin`". Keep the Evidence / labelled Theory convention in the file header.
4. **`docs/admin-portal.md`**: sections for the Loops panel, the Watchdog card,
and the Models rollup with Block/Unblock (where `blocked` differs from
`deprecated`: an operator's reasoned stop, one click to undo).
5. **`docs/api.md`**: the three watchdog endpoints and `blocked` on the
availability endpoint (request/response shapes read from `src/admin.py`).
6. **`docs/data-model.md`**: the four watchdog tables (from `config/schema.sql`),
and `blocked` in the `availability` row at the `models` section (line ~34)
and wherever `admin_model_overrides` is described.
7. **`docs/clients.md`** (anchor `## Session-directory attribution (opencode
plugin)`) and `docs/api.md` near the `X-Router-*` table (line ~151): the
plugin loader contract (every export must be a function) and how to confirm
the plugin loaded.
## Rules
- ASCII only; no middle dots. Match each file's existing style and heading
depth. Admin-portal docs describe the UI, they do not add prose to it.
- Numbers and names come from the code on this branch, never from this brief.
- Commit per todo, by explicit path. Never `git add -A`.
- Do not push and do not open a PR. The done report lists commits and the
items for `deploy/README.md`.
- If a worker's context passes ~150k tokens, stop it and start a fresh one.
Write `.omo/plans/docs-lift-a-pass.md`, then stop and report.