207 lines
12 KiB
Markdown
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.
|