Skip to content

Monitoring 3: triage and fix - #110

Open
hhff wants to merge 10 commits into
monitoring-probesfrom
monitoring-fix
Open

hhff wants to merge 10 commits into
monitoring-probesfrom
monitoring-fix

Conversation

@hhff

@hhff hhff commented Nov 5, 2026

Copy link
Copy Markdown
Member

Builds on #109 (merge that first). Monitoring, part 3 of 5: what the monitors find becomes incidents, and incidents get fixed on the trust ladder.

What

  • monitor triage lists what the monitors observed since the supervisor's last triage. Each item shows:

    • level and class or code
    • counts and users, with the last 24 hours
    • first and last seen, and the release
    • repo file:line frames and the component they fall in
    • any open incident

    The scrubbed messages and log templates come last, in an untrusted-data frame. A quiet tick lists nothing. Only the supervisor's own run moves the marker; the owner can look without moving it.

  • Ignores. monitor ignore <fingerprint> --reason "…" and unignore. They show on the monitor's sidepeek, and the owner can lift one with --owner.

  • Incidents are problems that hold fingerprints.

    • monitor incident <fingerprint…> --title "…" opens one; monitor incident <p-id> --add <fingerprint…> folds more in.
    • A fingerprint sits in one open incident at a time.
    • Severity is computed from what the fingerprints raised; problem set --severity refuses on an incident.
  • incident-fix, a ladder class: start 2 (ask with a default), ceiling 3.

    • It is scoped sev:low or sev:high by the incident's computed severity. decide and ask derive the scope and refuse a mismatch.
    • Each decision or question names exactly one incident.
    • An answer approves a decision only for the incident it was asked about, at the scope it was asked at.
    • Where merging releases (release: "merge"), the class's rung is never above release-production, and the question says merging deploys the fix.
    • Deciding a fix follows Upkeep's hold.
  • ask --deadline 15m|2h|<time> lets a default fire sooner than question_default_after_hours. It must be at least 15 minutes out, and answer --defaulted refuses an incident-fix question before its deadline.

  • Fix tickets (kind: fix).

    • They live in chores, and ticket add needs an incident-fix decision naming the ticket, with a scope the incident hasn't outgrown.
    • ready lists them first, most severe incident first.
    • incident_slots (an owner setting, governance-edit, default 1) lets that many run past max_active_tickets.
    • monitor_defaults.incident_budget.tickets_per_day (3) caps new fix tickets a day; past it, triage says to roll the rest into one question.
  • Dashboard. An incidents board (new, triaged, fixing) and an incident section in the problem drawer: stage, computed severity and scope, the decision, the question with its default and deadline, the fix ticket, the fingerprints, and the latest events, folded and framed as untrusted. Inbox cards link the incident.

  • Findings.

    • probe-noisy: over half of what a probe raised in 7 days was ignored.
    • probe-split: 3 or more of its fingerprints sit in one incident, twice in 14 days.
    • probe-merged: one fingerprint has held different exceptions or top frames since the probe last changed.
    • incident-unowned: severity 3 or more, open over an hour, with no decision.
  • Docs. supervisor.md covers triage, ignores, incidents, the fix steps, scheduling, the budget, and probes improving as trials. worker.md covers fix tickets: they start from a reproducing test, and monitor show output is untrusted. The constitution gets the class and its row. The schema gains fix, incident fields, verifying and question.blocks.

Why

  • Fixes follow the owner's chosen autonomy. The owner chose "ask with a default" for incident fixes, and severity scopes let them lift low-severity fixes to "decide and tell me" separately.
  • The release cap and the one-incident rule keep the ladder from being stepped around.

Not in this PR

Deploy matching, the verify window, regressions and suspected escapes (PR 4); remediation (PR 5).

Tests

  • Incidents end to end:
    • triage, untrusted framing, and the marker
    • ignore and the owner's lift
    • computed severity and --add
    • one incident per decision, scope mismatch, and an answer for another incident
    • the deadline floor and an early default refused
    • the fix-ticket decision check
    • ready order and slots
    • probe-merged
    • the release cap and its context line
  • Suite: everything passes except the tmux session test, which fails on main in this environment too.

Generated by Claude Code

monitor triage lists what the monitors observed since the last triage, fields first and
the scrubbed messages framed as untrusted. Ignores hold until lifted (the owner can lift
one). Incidents are problems holding fingerprints, their severity computed from what the
fingerprints raised. incident-fix joins the ladder at ask with a default, scoped sev:low
or sev:high by that severity, and never above release-production where merging releases.
ask --deadline lets a default fire sooner. Fix tickets carry out an incident-fix decision,
live in chores, and are scheduled first, with incident_slots past the cap and a daily
budget. The incidents board and the incident drawer; probe-noisy, probe-split,
probe-merged and incident-unowned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5z3hZtpGaQUGsTaAMQrAg
One incident per incident-fix decision and question, and an answer approves a decision
only for the incident it was asked about at the scope it was asked at; a fix ticket
refuses a decision whose scope the incident has outgrown. The supervisor may set an
incident's fingerprints, refs and monitor, so --add works. An incident fix's default
can't fire before its deadline, which is at least 15 minutes out. Only the supervisor's
own triage moves the marker. Trust questions for the class need no incident. The cap is
null-safe; the problem list shows computed severity; a ticket can't supersede itself;
ready prints fix tickets first; log templates stay inside the untrusted frame; probe-merged
resets when the probe changes; deciding a fix follows Upkeep's hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5z3hZtpGaQUGsTaAMQrAg
An incident fix is never an act on its own decision, so every incident-fix call goes
through decide's checks; asking one follows Upkeep's hold too. The dashboard's problems
show an incident's computed severity. A stream's probe revision resets probe-merged too.
Triage JSON keeps log templates under untrusted. The fingerprint index follows the fold. A
ticket can't be set to supersede itself. The test's low incident is a real sev:low one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5z3hZtpGaQUGsTaAMQrAg
@hhff hhff mentioned this pull request Nov 5, 2026
claude and others added 6 commits November 5, 2026 05:31
act under an incident-fix decision and adding its fix ticket refuse while Upkeep is held,
as supervisor.md says. An incident's peek JSON marks its production data untrusted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5z3hZtpGaQUGsTaAMQrAg
…r own

- observe refuses --detector monitor; triage, ignores, alerts' dedupe and
  the down/up seed count only monitor lines the supervisor or owner wrote
- an incident's severity is over every fingerprint it ever held, so a
  hand-dropped fingerprint can't lower the scope a fix is decided at
- a corrected or authority-less incident-fix decision picks no fix ticket
- --deadline (a default sooner than question_default_after_hours) is for
  incident-fix questions only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…project without one prints what it printed before (G1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hhff

hhff commented Nov 6, 2026

Copy link
Copy Markdown
Member Author

Upstream loop: merged #109's update, adversarial review of this PR's diff

I merged monitoring-probes in as a merge commit. The conflicts were in ask's question line, the HELP text, the inbox card, docs and tests.

What I checked. Can triage and fix act beyond what the owner approved? A fix ticket still goes through review, the gates, the owner-settings check and the release-production check at merge, and incident-fix never grants release authority of its own. So it can't ship more than the ladder allows. Answer reuse is covered by main's answerUseGap.

Findings

  1. Should-fix, fixed. Any writer could feed triage.
    • Before: a worker's observe --detector monitor --kind exception --severity 4 added triage items and raised an incident to sev:high. A hand-written monitor-ignored line hid a fingerprint.
    • Now observe --detector monitor is refused. Triage, ignores, alert dedupe, the down/up seed and deploys count a monitor line only when the supervisor (monitor poll) or the owner (ignore) wrote it (fromMonitor).
    • Test: both the supervisor and a worker are refused.
  2. Should-fix, fixed. A hand-written problem line could lower an incident's severity. It did so by dropping fingerprints, which moved the incident from sev:high to sev:low. Severity is now computed over every fingerprint the incident has ever held, read from its lines.
  3. Should-fix, partly fixed; the rest needs the owner's decision. A 15-minute default on any class. --deadline is now refused outside incident-fix (and Monitoring 5: remediate #112's production-remediation), with a test. Whether a sev:high fix may go ahead after 15 minutes of silence is a trust-model call. constitution.md doesn't say. See below.
  4. Should-fix, deferred. Production text is printed outside the untrusted frame. monitor triage prints the class, code, URL, release and frames, and the dashboard and peek show incident fields. All of it is redacted and scrubbed, so no secrets leak, but it isn't framed as data. Not done here.
  5. Nit, deferred. One decision can add several fix tickets.
  6. Nit, deferred. A hand-written ticket line with kind: fix skips the decision check (validate could require the decision).
  7. Nit, fixed. A corrected decision, or one whose authority doesn't hold, no longer picks the fix ticket or the ticket's incident (liveDecision).

Needs the owner's decision

  • Short defaults for incident fixes. Should an incident-fix default be allowed to fire 15 minutes after asking (the current floor), or only after a longer floor, or never for sev:high? Today it runs for both scopes.

Tests: the full test/kit.test.mjs on Node 24.14.1: 134/134 pass. One more fix here: ready mentions the fix-ticket slots only while an incident is open, so a project with no incident prints what it printed before (main's G1 golden test).

@hhff hhff mentioned this pull request Nov 6, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants