12 KiB
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:
- Orientation — one paragraph on what Panama is; pointers:
README.md(layout, thepanamacommand),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). - 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 inmodules/*require same-save qmldir registration; neverqs killfrom a copied configuration; neverhyprctl keyword— andevalexits 0 on error, so read back withgetoption; no duplicate IPC targets; annotate every IPC parameter and return type; no continuously-repainting animations; batch compositor reloads and announce them;readAsdescribes the answer, not the setting; don't touch the hyprlang configs that never moved to Lua; no new notification daemon; scripts carry no.shextension exceptmigrations/*.sh; no secrets underuser/. - The contract discipline — contracts live under
tests/, run viapanama test [pattern]or directly; run the covering contracts for what you touched (panama contracts <file>names them); during a desktop session runpanama test --safe— thetests/desktop-hijackingledger is the list of what it skips and why; regeneratedocs/settings.mdand 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. - Seams for testing — fixture env vars (
PANAMA_*_HELPER,PANAMA_*_FIXTURE,PANAMA_*_STATIC_ONLY), the harness discipline (distinct semantic entry file,qs -p, PID fromqs list --all, kill only that PID), hermetic-by-construction helpers (validated inputs, JSON out, stdin-only secrets). - 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-contractpin 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:
panama doctor— JSON by default (schemaVersion1),--summary,check <id>,--repair <id>; the 30 check ids by group.panama-action <verb>as the stable boundary for desktop actions (the verb list), andqs ipc call <target> <fn>beneath it for whatpanama-actiondoesn't cover — pointer toshell.qmlfor the target table rather than duplicating it.- 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). panama-launch --classfor focus-or-launch;panama test --safeif asked to verify the desktop;panama updatefor keeping the machine current.- Privilege: one line — load
panama-sudobefore 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:
- If
~/.claude/skillsis a symlink (today: →user/agents/skills), remove it (symlink removal never displaces toconfig/old, matchinglink-user's rule) andmkdir -pa real directory. - For each child of
$PANAMA_PATH/skills/, displace any existing real entry at~/.claude/skills/<name>toconfig/old/(housedisplacesemantics; symlinks just removed) and link~/.claude/skills/<name>→$PANAMA_PATH/skills/<name>. - 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
- The two shipped skills and
.claude/skills/panamaexist with valid frontmatter (namematches the directory, non-emptydescription, nothing else required). - Claim pinning: every
`panama <sub>`subcommand a skill names exists inbin/panama's dispatcher; every`panama-<tool>`exists inbin/or the quickshell scripts dir; every backticked repo path exists; everyPANAMA_*env var it names appears somewhere in the tree; everypanama-actionverb it names is inpanama-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.) link-skillsexists, is in STAGES andupgrade_stagesordered afterlink-dotfilesand beforelink-user; the manifest useslinkdirforagents/skills;link-userimplementslinkdir.
tests/setup/desktop-hijacking-contract
- Every ledger entry names an existing contract.
- Honesty sweep: every contract under
tests/that drives the live shell — matchesqs ipc callwithout booting its ownqs -pharness, or restartspanama-quickshell.service, or callsqs kill— must be listed; the sweep's heuristics live in this contract so a new hijacking contract cannot stay unlisted. cmd_testhonors the ledger: static check that--safereads 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,linkdirinsetup/scripts/link-user,user/manifest,user/README.md,installSTAGES +upgrade_stages,tests/setup/skills-contract, updates totests/setup/update-command-contractandtests/setup/user-content-contractwhere 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.