No error is a dead end: crash, click, and your agent is already looking
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -92,6 +92,21 @@ surfacing agent usage in the bar, and a plugin registry with a lockfile. The
|
||||
first shipped, as a bar widget with a switch of its own on Shell › Bar; the
|
||||
second remains deferred, see below.
|
||||
|
||||
**Omarchy** ([repo](https://github.com/basecamp/omarchy), MIT — DHH): the
|
||||
crash-to-agent escalation ladder and the multi-agent usage collectors, both
|
||||
taken as code, not just ideas, with attribution headers on every derived file.
|
||||
Specifically: the command-as-notification-data hint (the shell runs the click,
|
||||
so it survives shell restarts and never blocks the sender), the per-agent argv
|
||||
launch table with the skill-path-as-fallback trick for harnesses without a
|
||||
skill mechanism, the coredump PID+signal payload, and the Claude collector's
|
||||
hard-won honesty — model-scoped limits, cached numbers that expire on window
|
||||
rollover rather than age, waiting-vs-expired auth as distinct states, and
|
||||
retry-on-transport-but-not-HTTP-error. The diagnose-crash skill's structure
|
||||
("rule out OOM first", "never invent function names", "diagnosis reads; it
|
||||
does not fix") was adapted rather than rewritten, because it was already
|
||||
right. Their usage panel and menu system were not taken — Panama renders its
|
||||
own surfaces in its own design language.
|
||||
|
||||
### Declined, and why
|
||||
|
||||
- **Wallpaper-derived dynamic color** (HyDE wallbash, matugen). The headline
|
||||
|
||||
+17
-2
@@ -4,7 +4,7 @@
|
||||
Do not edit this file. Run `quickshell/scripts/panama-settings-docs`
|
||||
after changing the schema; a contract fails when this copy is stale.
|
||||
|
||||
175 settings across 36 groups. 77 of them are applied to the compositor and confirmed by reading the value back.
|
||||
183 settings across 37 groups. 77 of them are applied to the compositor and confirmed by reading the value back.
|
||||
|
||||
## accessibility
|
||||
|
||||
@@ -22,6 +22,21 @@ Found on **Accessibility**.
|
||||
| **Pointer size**<br>`cursorSize` | 24 px | Applies to the compositor and to applications. Range 16–64. |
|
||||
| **Text size**<br>`textScale` | 1.0 | Scales interface text everywhere; 1.00 is the design size. Range 0.75–2.0. |
|
||||
|
||||
## agents
|
||||
|
||||
Found on **System › Agents**.
|
||||
|
||||
| Setting | Default | What it does |
|
||||
|---|---|---|
|
||||
| **Preferred agent**<br>`preferredAgent` | none | Who answers when the desktop offers to investigate something Choices: None, Claude Code, Codex. |
|
||||
| **Offer to diagnose crashes**<br>`crashDiagnoseOffer` | true | When a program dumps core, the notification carries a click that opens the preferred agent mid-investigation with the crash details in hand |
|
||||
| **Offer help when the shell fails to reload**<br>`reloadFailureOffer` | true | A broken change to the shell's own configuration offers the failing log to the agent |
|
||||
| **System Health hands off unrepairable checks**<br>`healthAgentHandoff` | true | A red check with no repair, or whose repair failed, grows an Ask-the-agent button carrying the check's snapshot |
|
||||
| **Launched agents approve their own tools**<br>`agentAutoApprove` | true | Investigations run without permission prompts. The diagnose skill still holds agents to reading rather than fixing, and root still goes through panama-sudo, reason and all |
|
||||
| **Collect Claude Code usage**<br>`agentUsageClaude` | true | Limits from Anthropic's usage endpoint, tokens from the local transcripts |
|
||||
| **Collect Codex usage**<br>`agentUsageCodex` | true | Limits over the Codex app-server, sessions from its local files |
|
||||
| **Refresh interval**<br>`agentUsageRefreshMinutes` | 15 min | How often the usage collectors ask for fresh numbers, in minutes. Range 5–60. |
|
||||
|
||||
## appearance
|
||||
|
||||
Found on **Appearance**.
|
||||
@@ -380,7 +395,7 @@ Found on **Shell › Bar**.
|
||||
| **Graphics**<br>`showGpu` | true | Show graphics usage beside the workspace indicator |
|
||||
| **Battery**<br>`showBattery` | true | Show the charge level in the bar, on machines that have a battery |
|
||||
| **Battery percentage**<br>`showBatteryPercent` | false | Show the exact number beside the battery icon |
|
||||
| **Claude usage**<br>`showAgentUsage` | false | Show how much of the Claude subscription has been used, beside the other vitals |
|
||||
| **Agent usage**<br>`showAgentUsage` | false | Show how much of the busiest agent subscription has been used, beside the other vitals |
|
||||
| **Vitals refresh**<br>`vitalsIntervalMs` | 2000 ms | How often processor, memory, and graphics usage update. Range 500–10000. |
|
||||
|
||||
## wallpaper
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
# The escalation ladder, and usage worth trusting
|
||||
|
||||
Approved from mock `agents.html` (2026-08-25). Two builds in one cycle: no failure surface is a
|
||||
dead end (crash → one click → your agent mid-investigation), and the bar's usage number becomes a
|
||||
multi-agent panel backed by Omarchy's battle-tested collectors. Borrowed code is MIT — carry
|
||||
`Copyright (c) David Heinemeier Hansson` + the MIT permission notice in a header comment on every
|
||||
derived file, and add an Omarchy entry to `docs/UPSTREAM-INSPIRATION.md`.
|
||||
|
||||
## Decisions log
|
||||
|
||||
| Decision | Choice |
|
||||
|---|---|
|
||||
| Scope | Ladder + usage panel, one cycle |
|
||||
| Ladder surfaces v1 | App crashes, shell reload failures, Health red checks, update/migration failures, plus `panama diagnose` by hand |
|
||||
| Agent | Configurable via `preferredAgent`; **Claude and Codex both fully supported on the ladder** (per-agent argv table); default `none` — quiet until chosen, like Omarchy |
|
||||
| Permission posture | Auto-approve (user's explicit choice), behind a toggle; the diagnose skill still teaches reads-not-fixes; root still via `panama-sudo` |
|
||||
| Usage | Collectors ported near-verbatim (Claude + Codex), Panama-native popover panel, no cross-machine sync |
|
||||
| Settings home | New `agents` leaf under System |
|
||||
| Notification click mechanism | Omarchy's command-as-data hint (`panama-exec`), executed by the shell — survives restarts, never blocks the watcher |
|
||||
|
||||
## Schema (orchestrator adds first — do not re-add)
|
||||
|
||||
| key | type | def | group | notes |
|
||||
|---|---|---|---|---|
|
||||
| `preferredAgent` | enum `none/claude/codex` | `none` | agents | `none` = crash toasts carry no action |
|
||||
| `crashDiagnoseOffer` | bool | true | agents | gates the crash rung (still requires an agent chosen) |
|
||||
| `reloadFailureOffer` | bool | true | agents | shell-reload rung |
|
||||
| `healthAgentHandoff` | bool | true | agents | Health-page rung |
|
||||
| `agentAutoApprove` | bool | true | agents | off → agents launch in their default prompting mode |
|
||||
| `agentUsageClaude` / `agentUsageCodex` | bool | true | agents | per-collector enables |
|
||||
| `agentUsageRefreshMinutes` | int 5–60 | 15 | agents | collector fan-out interval |
|
||||
|
||||
`showAgentUsage` stays where it is (vitals) and keeps its meaning; the Bar page row remains, the
|
||||
Agents page gets the full set (declared mirror in `settings-ownership-contract` if both surface
|
||||
the same key). New group `agents` needs a `groupPages` route to the new leaf
|
||||
(`search-routing-contract`).
|
||||
|
||||
## The launcher: `bin/panama-agent`
|
||||
|
||||
Ported from `omarchy-agent`, trimmed to Panama's needs, attribution header included.
|
||||
|
||||
- Reads `preferredAgent` and `agentAutoApprove` from `~/.config/panama/settings.json` with jq at
|
||||
press time (the power-button precedent) — `none` exits 0 silently.
|
||||
- `cd "$PANAMA_PATH"` before spawning: the checkout is where the skills, the repo trust, and the
|
||||
pre-approved diagnostic permissions live.
|
||||
- Per-agent argv table — **verify every flag against the installed binaries' `--help`, do not
|
||||
trust the Omarchy source or this spec**: Claude ≈ `claude [auto-approve flag] -- "$prompt"`,
|
||||
Codex ≈ `codex [auto-approve flag] -- "$prompt"` (Omarchy used `--permission-mode auto` and
|
||||
`--approve-for-me`; use whatever the real flags are, and the prompting-mode variants when
|
||||
`agentAutoApprove` is off).
|
||||
- Spawn: `setsid kitty --directory "$PANAMA_PATH" -e <argv…>` (kitty is the house terminal, its
|
||||
own health check exists; `--app-id`-style fixed class `panama-agent` so window rules can target
|
||||
it later).
|
||||
- `--prompt "text"` input; no `--pick` menu in v1 (the Agents page is the picker).
|
||||
- Repo `.claude/settings.json` gains a pre-approved allowlist for the read-only diagnostic
|
||||
commands (`coredumpctl`, `journalctl`, `rpm -q`, `panama doctor`) so even non-auto-approve
|
||||
launches investigate smoothly.
|
||||
|
||||
## The rungs
|
||||
|
||||
**1. Crashes.** `bin/panama-crash-watch` gains `COREDUMP_PID` + `COREDUMP_SIGNAL_NAME`
|
||||
extraction. When `preferredAgent != none` and `crashDiagnoseOffer`, the notification carries the
|
||||
command as data: `notify-send … --hint=string:panama-exec:"$(printf 'panama-agent-crash %q %q %q %q' pid comm exe signal)"`
|
||||
with body "Click to diagnose with <Agent>". Otherwise today's actionless notification, verbatim.
|
||||
Existing session-dedupe and portal-crash rationale untouched. New `bin/panama-agent-crash` ports
|
||||
`omarchy-agent-crash`: coredump facts + `coredumpctl list` timestamp into a heredoc prompt naming
|
||||
the `diagnose-crash` skill **with its absolute path as fallback** (the harness-agnostic trick —
|
||||
this is what makes the ladder work for Codex too), then `exec panama-agent --prompt "$prompt"`.
|
||||
|
||||
**2. The `panama-exec` hint.** `services/Notifs.qml`: read hint `panama-exec` into the
|
||||
notification model (one field, carried through popup persistence like any other).
|
||||
`modules/notifications/NotificationCard.qml`: on body click, if the entry carries an exec, run it
|
||||
via `Quickshell.execDetached(["sh", "-c", command])` and dismiss — the branch sits beside the
|
||||
existing `defaultAction` handling and defers to it when both exist. Security note in-file: the
|
||||
session bus is local; any sender could carry the hint, which grants nothing an local process
|
||||
lacks.
|
||||
|
||||
**3. Shell reload failure.** `shell.qml`'s `onReloadFailed` (old shell keeps running — it can
|
||||
still notify): when `reloadFailureOffer` and an agent is chosen, send a notification through the
|
||||
shell's own Notifs with the exec hint → new `bin/panama-agent-reload` builds the prompt from the
|
||||
failure string plus the last ~40 matching journal lines.
|
||||
|
||||
**4. Health page.** Red check with no repair, or whose repair just failed → an "Ask the agent"
|
||||
SettingsButton beside it (visible only when `healthAgentHandoff` and an agent chosen), running
|
||||
`panama-agent --prompt` with the check's JSON snapshot (`panama doctor check <id>`) embedded.
|
||||
|
||||
**5. Update/migration failures.** The failure summary in `install` gains one line:
|
||||
`Hand it to an agent: panama diagnose`. `bin/panama-migrate-notify`'s failure path likewise.
|
||||
|
||||
**6. `panama diagnose` (cmd_diagnose).** By-hand rung: bundles `panama doctor --summary`, the
|
||||
last journal errors, and "what feels wrong" free text (`panama diagnose [words…]`) into a prompt
|
||||
and hands it to `panama-agent`. House three-touchpoint rule + README list (readme-contract).
|
||||
|
||||
## The skill: `skills/diagnose-crash/`
|
||||
|
||||
Written by the orchestrator, shipped un-gated like the other two, structure adapted from
|
||||
Omarchy's: triggers name the notification and `panama-agent-crash`; `coredumpctl info <pid>`
|
||||
first and read the command line; rule out OOM before blaming the program; correlate the crash
|
||||
time against recent package updates and journal context; Fedora debuginfod for symbols; the
|
||||
security rule (a core holds secrets — scratch files via mktemp, deleted after); "never invent
|
||||
function names"; "diagnosis reads; it does not fix"; report structure. Claims auto-pinned by
|
||||
`skills-contract` (it already scans every skill in `skills/`).
|
||||
|
||||
## Usage collectors and panel
|
||||
|
||||
- `config/dot/quickshell/scripts/panama-agent-usage-claude` — port of Omarchy's Python collector
|
||||
(attribution header): OAuth usage endpoint + model-scoped `limits[]`, transcript scan with
|
||||
message-id dedupe and scan cache, cached-limits-expire-on-window-rollover, waiting-vs-expired
|
||||
auth states, `retryAdvised` transport/HTTP distinction, percent-scale voting. Keep Panama's
|
||||
secrets discipline: the token stays out of argv and out of the record (their in-process Python
|
||||
read already satisfies it; the contract proves it).
|
||||
- `…/panama-agent-usage-codex` — port: app-server JSON-RPC limits, session-file token stats with
|
||||
the last_token_usage rule.
|
||||
- `…/panama-agent-usage-update` — fan-out: runs enabled collectors in parallel, `jq -e` validity
|
||||
gate, atomic writes to `$XDG_STATE_HOME/panama/agents/usage/<agent>.json`.
|
||||
- `services/AgentUsage.qml` → directory model: one FileView per record file, discovered by
|
||||
listing the dir; aggregate `headline` = fullest window across enabled agents; timer from
|
||||
`agentUsageRefreshMinutes`, running only while `showAgentUsage`.
|
||||
- `modules/bar/AgentUsageWidget.qml`: keeps the two-tier amber-75/red-90 coloring and the
|
||||
hide-when-nothing rule; click now opens the panel popover (right-click keeps Settings).
|
||||
- New `modules/bar/AgentUsagePanel.qml` (or popover home matching how other bar popovers are
|
||||
built — follow the house pattern found in the code): per the mock — agent tabs, tier chip,
|
||||
updated-ago line, limit meters with reset countdowns (model-scoped rows included), tokens by
|
||||
day (today bolded), by-model bars, honest auth states. No keyboard-nav requirement in v1;
|
||||
Escape closes like every popover.
|
||||
- Old `scripts/panama-agent-usage` retires (delete; its consumers migrate). The five pins of
|
||||
`tests/quickshell/agent-usage-contract` survive against the new collectors: token never in
|
||||
argv, never in any record, credentials never written, expired token → no request + honest
|
||||
state, widget hidden unless asked-for AND real numbers. Extend for: per-agent enables honored,
|
||||
record validity gate, atomic write.
|
||||
|
||||
## New settings leaf
|
||||
|
||||
`agents` under the System category: 4-file ceremony (SettingsRoutes categories entry,
|
||||
SettingsShell case + Component, qmldir, `AgentsPage.qml`), search entries, regen docs+commands
|
||||
(orchestrator). Page per the mock: preferred-agent picker (install-state aware: show "not
|
||||
installed" detail for an absent binary), the four escalation toggles (auto-approve copy states
|
||||
the trade in plain words), usage card (master switch mirroring `showAgentUsage`, per-agent
|
||||
enables, refresh interval).
|
||||
|
||||
## Contracts
|
||||
|
||||
- `crash-watch-contract`: extend for PID/signal fields and hint gating (none-agent → no hint;
|
||||
chosen → hint present; never both mechanisms).
|
||||
- `agent-usage-contract`: as above.
|
||||
- New `tests/quickshell/panama-agent-contract`: hermetic — stubbed `settings.json` +
|
||||
stub `kitty`/`claude`/`codex` on PATH; `none` → silent exit; claude/codex → correct argv shape
|
||||
including the auto-approve/prompting variants; prompt passed as one argv element; cwd is the
|
||||
repo. panama-agent-crash: prompt contains pid/comm/exe/signal + the skill path; never runs a
|
||||
real agent (stub PATH). NOT in the desktop-hijacking ledger — it must run stubbed.
|
||||
- `skills-contract` covers `diagnose-crash` automatically once the skill lands.
|
||||
- `settings-nav`/`search-routing`/`settings-docs`/`readme-contract` obligations as usual.
|
||||
|
||||
## Ownership (disjoint)
|
||||
|
||||
- **Orchestrator**: this spec; schema keys first; the `diagnose-crash` skill;
|
||||
`UPSTREAM-INSPIRATION.md` + license attribution file check; docs/commands regen; README count;
|
||||
seam audit.
|
||||
- **Agent A — usage**: the three collector scripts, `AgentUsage.qml`, `AgentUsageWidget.qml`,
|
||||
`AgentUsagePanel.qml` (+ its qmldir if bar modules use one), `agent-usage-contract`, deletion
|
||||
of the old collector.
|
||||
- **Agent B — ladder scripts**: `bin/panama-agent`, `bin/panama-agent-crash`,
|
||||
`bin/panama-agent-reload`, `bin/panama-crash-watch`, `bin/panama` (`cmd_diagnose`), `install`
|
||||
failure line, `bin/panama-migrate-notify` failure line, `.claude/settings.json` allowlist,
|
||||
`crash-watch-contract`, `panama-agent-contract`, README subcommand row.
|
||||
- **Agent C — shell & settings UI**: `services/Notifs.qml` (hint field), `NotificationCard.qml`
|
||||
(exec branch), `shell.qml` (`onReloadFailed` rung), `modules/settings/HealthPage.qml` ("Ask
|
||||
the agent"), `AgentsPage.qml` + routes/shell-case/qmldir, search entries in
|
||||
`SettingsSearch.qml`.
|
||||
|
||||
Standing rules apply: live desktop (valid QML every save, journal checks), no real agent
|
||||
launches or notifications left uncleaned during builds, contracts as you go, never the
|
||||
desktop-hijacking set unannounced.
|
||||
Reference in New Issue
Block a user