Repository navigation
Operations runbook and review-outage diagnosis - #56
Conversation
…utage Add docs/OPERATIONS.md (what runs where, log paths, a host diagnosis checklist, outcome-to-fix table, and the code-based ranking of failure modes for the 2026-09-18 review outage) and manage/nightly_health.py, a stdlib-only, Python 3.9-compatible summary of the last N review runs' errors and the stage-0 P3 drift trigger from the host's site/cache logs.
- The current wrapper reached main on 2026-09-21 (PR #24), after the outage began, so the host most likely runs the older one: no Mathlib preflight and several steps under bare python3. The ranking now treats that as the expected state and adds the review-only Wikipedia fetch (pinned revision, requests, own UA, swallowed into fetch_failed). - Flat tokens place every failure inside annotate_one; post-agent failures keep their tokens. - 'Credit balance is too low' cannot come from the environment variable (batch_annotate pops it); point at the CLI's stored credentials. - Step 5 adds a one-off LaunchAgent probe, since a Terminal call cannot clear a keychain the LaunchAgent cannot read; the job PATH and python3 are derived from the wrapper in use; the CLI fallback works; step 7 passes WIKILEAN_PROPOSALS=1 and notes the flush. - nightly_health classifies the raw error with anchored patterns, separates API-key, Worker-write and Wikipedia causes, drops dry runs from the drift numbers, withholds the trigger below 20 slugs, and keeps review articles of moderate.py all runs.
|
Review status: merged in Update 2026-10-14 (re-checked at
Original review (2026-10-14)Independent adversarial review of Verdict: right approach. The runbook correctly places the per-article error text in Required before merge
Decisions for the maintainer
Merge order: release-neutral; merge before the status-health-alerts PR, whose alerts point at Fixes are in progress; this comment will be updated. Posted by the WikiLean PR swarm (lead); updated 2026-10-14. |
Status review (2026-10-14): 🔧 Needs changesThe #1-ranked cause, the Claude login on the nightly host, is right. Running this PR's own Fix before merge
Nits
Order: merge before #59, whose alerts link to 🤖 Automated status pass by Claude Code over all 18 open PRs (#46–#63), posted for the repo owner. An independent verifier re-checked each finding. All 18 heads were also merged and tested together in a scratch tree; the only test failure that comes from combining them is #47 × #55 (three other pairs had mechanical text conflicts). Reviewed head: |
- An expired or revoked token reaches the runner as "Failed to authenticate. API Error: 401 ...", which lacks the abort keyword "authentication", so it gives 15 of 15 on a current checkout too. The "What the code says" note and ranked items 1 and 2 no longer claim it aborts; PR #52 extends the abort keywords. - elapsed_s starts before annotate_one waits for a concurrency slot, so queued articles count the wait. nightly_health reports the fastest failing article instead of the median and no longer infers quota spend from slow failures; the outcome table and "Confirms it" lines drop their timing claims. - Classify "Control request timeout: initialize" (claude CLI startup timeout) and "API Error: Stream idle timeout" (API stream timeout), in nightly_health and the outcome table, with tests. - Step 1 writes the launchctl print dump to a private mktemp file. The setup token goes only in nightly.local.env, never a plist, and steps 5 and 7 show how to run their checks with it. - The fresh-checkout commands pass --job moderate to nightly-launchd.py. - backup-d1.yml runs its own wrangler export, not backup-d1.sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…kouts without #52 #52 adds the CLI's login failure strings to the abort keywords and starts elapsed_s once a concurrency slot is acquired, so "15 of 15 on any checkout" and "the clock includes the queue wait" now hold only for checkouts without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes pushed (2026-10-14)This addresses both "Fix before merge" items and the token, timeout and What changed
Verification
Not changed / still open
Merge notes: merge before #59. GitHub shows the branch behind 🤖 Posted by Claude Code for the repo owner. Each fix was checked by an independent verifier before it was pushed. Head: |
Operations runbook and review-outage diagnosis
Problem
The nightly AI review has failed on every article since the 2026-09-18 night, and nothing in the repository says where the job runs or how to diagnose it.
/stats(Pipeline runs, review row): 117 runs / 1,761 articles / 843 errors on 2026-10-12 22:17 UTC, then 118 / 1,776 / 858 on 2026-10-13 (read at 19:37 UTC and again at 20:28 UTC). Tokens were 26,345,645 at every read. Each night adds one run, 15 articles and 15 errors, with no new tokens.ai-moderate:reviewrevision appears after 2026-09-17 09:05 UTC. For example, see https://wikilean.jackmccarthy.org/Generalized_hypergeometric_function/history. Every row of https://wikilean.jackmccarthy.org/recent-changes iswp-update:stage0, so the zero-token stage-0 step of the same job still works.site/cache/logs. No tracked doc names that host, its checkout, its log paths, or how to read them.site/moderate.py:1200-1219and_AbortingSemstop a run after at most 7 errors on text containingcredit balanceorauthentication, or on five consecutive limit-type errors, andsite/ops/retry-lib.sh:50-55retries a 5-hour-window limit. Neither happened. The CLI's login failures (Not logged in, andFailed to authenticate. API Error: 401 …for an expired or revoked token) contain none of those keywords, so they fail all 15 articles on any checkout.Change
docs/OPERATIONS.md(new). It covers:What runs where, with fill-in fields for the host, user, checkout, commit, Python and Mathlib path.
Every log path, including the fact that
.decisions.jsonlhas no error text and.moderate_run.logdoes.A diagnosis checklist with exact commands:
launchctl print, the checkout commit and whether it contains b079500, the newest cron log, the error strings, thepython3and bundledclaudeCLI in the job's environment (including one real CLI call), the Mathlib path and disk, and a one-article confirmation run.A table mapping each error text to its meaning and fix.
A code-based ranking of the outage's likely causes. The ranking has seven candidates, each with code citations and the check that confirms it:
python3on the job's PATH (site/batch_annotate.py:60).Disk space, a missing MCP server, the Worker/token paths, and a failure at the save are ruled unlikely. Two code facts drive the ranking:
annotate_one, where an error returns 0 tokens even after the agents ran (site/batch_annotate.py:612-616).mainon 2026-09-21 (PR [Brain SQLite 07/15] Seal source acquisition pipelines #24), so the host most likely runs the older one: no Mathlib preflight, and several steps under barepython3.How the stage-0 P3 trigger ("stage-0 clears <90%") is measured.
manage/nightly_health.py(new). It reads only the host's local logs and makes no network calls or writes. It is stdlib-only and Python 3.9-compatible, so an old checkout can run the current version withgit show origin/main:manage/nightly_health.py | python3 - --cache site/cache. It prints:elapsed_s(on checkouts without Surface review failures without host access #52 the clock includes the wait for a concurrency slot, so the fastest is the closest to one article's own time) and a likely cause;.wp_update_report.jsonl;manage/test_nightly_health.py(15 tests), registered inscripts/ci-python.sh.How tested
python manage/test_nightly_health.py: 15 passed under Python 3.12 (CI interpreter) and under macOS system Python 3.9.6.python3 -(3.9.6) against an empty cache directory to check the stdin mode and the empty-log output.file:linecitation in the runbook againstmainat 37b7036.site/ops/brain_release_authority.pyblocking_changeson this branch's diff reports release-neutral.Risks
claude -pcalls: one from Terminal and one from a temporary LaunchAgent that is booted out afterwards. Each costs a few tokens. Step 7 is a real review: it flushes any checkpointed writes and, on success, writes one article revision to production. The doc says so at both steps.What Jack must do
pipeline_runs.notes(release-affecting), and a separate PR addsstatus.py --livehealth alerts. Success shows as/statsreview tokens rising and anai-moderate:reviewrow on/recent-changes.mainbecause the old one carries local data changes.