Files
Panama/docs/superpowers/specs/2026-08-25-agent-integration.md
T

207 lines
12 KiB
Markdown

# Agent integration: the machine carries its own manual for AI hands
Approved direction (2026-08-25 interview): three Claude-Code skills, delivery approach A
(per-skill symlinks under a real `~/.claude/skills`), a ledger-backed `panama test --safe`,
and `panama contracts <file>`. Factual content only — Gabriel's personal preferences stay in
his own CLAUDE.md and are out of scope. Everything the skills claim is contract-pinned,
because an agent believes the manual verbatim.
## Decisions log
| Decision | Choice |
|---|---|
| Audience | Claude Code skills; no AGENTS.md (YAGNI until another tool is in use) |
| Skill count | Three: `panama` (develop), `panama-desktop` (operate), `panama-sudo` (privilege) |
| Gating | Shipped to every machine, un-gated; personal content stays gated as today |
| Dev-skill home | In-repo `.claude/skills/panama/` (project-level, auto-discovered in the checkout) |
| Global delivery | Approach A: real `~/.claude/skills` dir + per-skill symlinks; new `linkdir` manifest kind for personal skills |
| CLI expansion | Moderate: `panama contracts <file>` + `panama test --safe`; `doctor` already speaks JSON |
| Test safety | `tests/desktop-hijacking` ledger + `--safe` flag + honesty contract |
| Coverage lookup | Heuristic grep, tier-marked from the ledger, honest when empty |
| Skill claims | Pinned by a new `skills-contract` |
## The three skills
House format per `user/agents/skills/writing-for-agents/`: frontmatter is `name` +
`description` only, H1 matches the name, ~100-column wrap, sibling files via relative links.
The rule for all three: **point, don't duplicate**. A skill orients and warns; the facts live
in the documents and commands the repo already maintains, so the rot surface is the pointer,
not the prose. Skills are written by the orchestrator (not fanned out) — they are the heart
of the feature and draw on session knowledge.
### `.claude/skills/panama/` — developing Panama (project-level)
Discovered automatically for any session inside the checkout; needs no delivery machinery and
works in forks. Description triggers on working in the Panama repo. Contents:
1. **Orientation** — one paragraph on what Panama is; pointers: `README.md` (layout, the
`panama` command), `config/dot/hypr/README.md` (Lua-not-hyprlang, the one thing to know
first), `config/dot/quickshell/modules/settings/README.md` (adding a setting, ownership,
"things that will bite you", where state lives), `docs/settings.md` (generated reference).
2. **The live-desktop covenant** — the distilled never-list, each item one line with its
source pointer: every save of `config/dot/quickshell/**` hot-reloads the live shell, so
every save must leave valid QML; check the journal for errors AND "Unable to assign" after
each batch (command form included); components in `modules/*` require same-save qmldir
registration; never `qs kill` from a copied configuration; never `hyprctl keyword` — and
`eval` exits 0 on error, so read back with `getoption`; no duplicate IPC targets; annotate
every IPC parameter and return type; no continuously-repainting animations; batch
compositor reloads and announce them; `readAs` describes the answer, not the setting;
don't touch the hyprlang configs that never moved to Lua; no new notification daemon;
scripts carry no `.sh` extension except `migrations/*.sh`; no secrets under `user/`.
3. **The contract discipline** — contracts live under `tests/`, run via `panama test
[pattern]` or directly; run the covering contracts for what you touched
(`panama contracts <file>` names them); during a desktop session run
`panama test --safe` — the `tests/desktop-hijacking` ledger is the list of what it skips
and why; regenerate `docs/settings.md` and the settings commands after schema/route
changes (`panama-settings-docs`, `panama-settings-commands`, both `--check`-able); the
README pins the contract count and subcommand list.
4. **Seams for testing** — fixture env vars (`PANAMA_*_HELPER`, `PANAMA_*_FIXTURE`,
`PANAMA_*_STATIC_ONLY`), the harness discipline (distinct semantic entry file, `qs -p`,
PID from `qs list --all`, kill only that PID), hermetic-by-construction helpers
(validated inputs, JSON out, stdin-only secrets).
5. **Safety idioms** — ConfirmAction/ErrorRow/NotMeasuredRow/SettingsNote exist; destructive
actions are two-stage; stored actions are data resolved through whitelists, never
commands (`settings-idiom-contract`, `keybind-rebind-contract` pin these).
### `skills/panama-desktop/` — operating the desktop (global)
For an agent doing *any* task on a Panama machine: how to drive the desktop honestly.
Description triggers on desktop interaction (opening settings, checking system health,
screenshots, notifications, audio/network/display questions) on a Panama machine. Contents:
1. `panama doctor` — JSON by default (`schemaVersion` 1), `--summary`, `check <id>`,
`--repair <id>`; the 30 check ids by group.
2. `panama-action <verb>` as the stable boundary for desktop actions (the verb list), and
`qs ipc call <target> <fn>` beneath it for what `panama-action` doesn't cover — pointer
to `shell.qml` for the target table rather than duplicating it.
3. Settings: open pages via `panama-action settings-page <id>`; change values through the
Settings UI or IPC, not by editing `~/.config/panama/settings.json` (the shell's
in-memory model wins for keys it has touched); where state lives (the state-paths table
pointer).
4. `panama-launch --class` for focus-or-launch; `panama test --safe` if asked to verify the
desktop; `panama update` for keeping the machine current.
5. Privilege: one line — load `panama-sudo` before anything needing root.
### `skills/panama-sudo/` — privilege etiquette (global)
Small. Description triggers on any need for root/sudo/pkexec on a Panama machine. Contents:
never bare `sudo`/`pkexec`; use `panama-sudo --reason "why" -- cmd args`; `--reason` must be
first; the reason appears beside (never instead of) polkitd's own action text; degrades to
plain pkexec with no shell running; migrations already follow this rule
(`bin/panama-migrate`). Include the one-line trust model so agents phrase reasons honestly:
state what the command does, not why it is safe.
## Delivery: approach A
### New root `skills/`
`skills/panama-desktop/SKILL.md`, `skills/panama-sudo/SKILL.md` (+ sibling files if needed).
Repo-root `README.md` layout table gains the row (readme-contract pins the layout block).
### New stage `setup/scripts/link-skills`
Un-gated. Behavior:
1. If `~/.claude/skills` is a symlink (today: → `user/agents/skills`), remove it (symlink
removal never displaces to `config/old`, matching `link-user`'s rule) and `mkdir -p` a
real directory.
2. For each child of `$PANAMA_PATH/skills/`, displace any existing real entry at
`~/.claude/skills/<name>` to `config/old/` (house `displace` semantics; symlinks just
removed) and link `~/.claude/skills/<name>` → `$PANAMA_PATH/skills/<name>`.
3. Report `Agent skills: N linked.`
`install` STAGES gains `link-skills` **after `link-dotfiles`, before `link-user`** (personal
must win name collisions by linking last, mirroring Claude Code's personal-over-project
precedence), in both the full list and `upgrade_stages`. `tests/setup/update-command-contract`
pins STAGE_NAMES — its list gets the new entry as part of this work.
### `linkdir` manifest kind (link-user)
`user/manifest` line `link agents/skills ~/.claude/skills` becomes
`linkdir agents/skills ~/.claude/skills`: for each child of the source, displace and link it
as a direct child of the destination (creating the destination as a real directory if
needed). Whole-dir `link` entries (`~/.agents/skills`, CLAUDE.md, rules) are untouched.
`user/README.md` documents the new kind. Known behavior, recorded not fixed: a personal
skill named like a shipped one shadows it (deliberate — personal wins); a *new* personal
skill needs a re-link (`panama update` or `setup/scripts/link-user`) to appear, where the
old whole-dir link showed it instantly.
## CLI additions (`bin/panama`)
House three-touchpoint rule: header comment, `usage()`, `main()` — plus the README
subcommand list (readme-contract cross-checks it).
### `panama contracts <file>`
Heuristic: resolve the argument to a repo-relative path; scan `tests/` (excluding
`fixtures/`, `__pycache__`) for contracts whose text contains the path, any parent-trimmed
suffix of it, or the basename. Output one line per hit: `tests/<name> [safe|desktop]`,
tier read from the ledger. No hits → `No contract mentions <path> — coverage may be
indirect (a harness or a generated artifact); nothing verified.` and exit 1. No options.
### `panama test --safe [pattern]`
`--safe` (position-independent, before or after the pattern): filter out every contract
listed in `tests/desktop-hijacking`, run the rest exactly as today, and end the summary with
`Skipped N desktop-hijacking contract(s) (tests/desktop-hijacking).` Plain `panama test`
is unchanged.
## The ledger: `tests/desktop-hijacking`
Package-list style: one repo-relative contract path per line, `#` comments; each entry's
comment says what it does to the session (restarts the shell; latches caffeine; opens live
overlays; writes every schema key against the real compositor; touches real xdg-mime
defaults; …). Seeded from the tier-3 inventory in the exploration (focus-session-restart,
focus-session-expiry, settings-window, overview-live-actions, switcher, welcome, cheatsheet,
status-events, activity-*, accessibility, calendar-agenda, screen-intelligence,
panama-action-ipc, panama-commands, panama-doctor, polkit-reason, signal-glass,
settings-write-sweep, settings-system, default-apps-*, gnome-handoff — verified individually
during the build, not copied blind).
## New contracts
### `tests/setup/skills-contract`
1. The two shipped skills and `.claude/skills/panama` exist with valid frontmatter (`name`
matches the directory, non-empty `description`, nothing else required).
2. Claim pinning: every `` `panama <sub>` `` subcommand a skill names exists in
`bin/panama`'s dispatcher; every `` `panama-<tool>` `` exists in `bin/` or the
quickshell scripts dir; every backticked repo path exists; every `PANAMA_*` env var it
names appears somewhere in the tree; every `panama-action` verb it names is in
`panama-action`'s dispatch. (Convention this imposes on skill prose: commands, paths and
variables are always backticked and exact — which is how they should be written anyway.)
3. `link-skills` exists, is in STAGES and `upgrade_stages` ordered after `link-dotfiles`
and before `link-user`; the manifest uses `linkdir` for `agents/skills`; `link-user`
implements `linkdir`.
### `tests/setup/desktop-hijacking-contract`
1. Every ledger entry names an existing contract.
2. Honesty sweep: every contract under `tests/` that drives the live shell — matches
`qs ipc call` without booting its own `qs -p` harness, or restarts
`panama-quickshell.service`, or calls `qs kill` — must be listed; the sweep's heuristics
live in this contract so a new hijacking contract cannot stay unlisted.
3. `cmd_test` honors the ledger: static check that `--safe` reads the file.
README test count: +2 (the "N of them" line — orchestrator's, updated at the end).
## Build plan and ownership
- **Orchestrator**: this spec; the three skills' content; final seam audit; README count.
- **Agent A**: `bin/panama` (`cmd_contracts`, `--safe`), `tests/desktop-hijacking` (verifying
each seeded entry by reading the contract), `tests/setup/desktop-hijacking-contract`,
README subcommand-list rows.
- **Agent B**: `setup/scripts/link-skills`, `linkdir` in `setup/scripts/link-user`,
`user/manifest`, `user/README.md`, `install` STAGES + `upgrade_stages`,
`tests/setup/skills-contract`, updates to `tests/setup/update-command-contract` and
`tests/setup/user-content-contract` where their pins move, README layout row.
Disjoint by construction; the skills (orchestrator) reference what A and B build, so the
skills land last and `skills-contract` runs after both.
## Out of scope (recorded)
Generic `AGENTS.md`; a Claude Code plugin; `panama map`/`agent` namespace; JSON output for
`panama test`; shipping any of Gabriel's personal preferences; per-contract header
annotations (the ledger supersedes); auto-relink on personal-skill creation.