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
106 lines
6.1 KiB
Markdown
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.
|