Plan verification gate remediation

This commit is contained in:
Gabriel Brown
2026-08-26 21:11:25 -04:00
parent 0d894afe3e
commit 044139ed63
2 changed files with 729 additions and 5 deletions
@@ -0,0 +1,720 @@
# Verification Gate Remediation Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan.
**Goal:** Make Panama's contract gate honest, safe by default when requested, diagnostic on failure, and capable of proving the later repository-audit fixes.
**Architecture:** Replace the incomplete desktop-hijacking ledger with one explicit manifest covering every collected contract. `bin/panama` remains the public runner: it parses that manifest, applies capability policy, executes each selected contract under a bounded timeout, and preserves its diagnostics. Contracts that currently depend on the calendar, tracked files, the live settings store, or source-text inspection are changed to exercise disposable fixtures and real public commands.
**Tech Stack:** Bash 5, Python 3 standard library, Git fixture repositories, existing Panama contract executables, Quickshell test harnesses.
**Spec:** `docs/superpowers/specs/2026-08-26-repository-audit-remediation-design.md`, Package 1: Verification gate.
## Global Constraints
- Preserve the user's existing `config/bash/.bashrc` changes. Do not stage or edit that file.
- Do not run plain `panama test` during implementation. It is intentionally interactive once this plan lands and several entries manipulate the live desktop.
- Do not start or restart the production Quickshell, Hyprland, or system services.
- Use `apply_patch` for every repository edit.
- Test public behavior. Source inspection may enforce a narrow declarative invariant, but must not substitute for executing `bin/panama` or a helper.
- Keep every contract self-cleaning on success, failure, signal, and timeout.
- Commit after each task with only that task's files staged.
---
## Task 1: Replace the desktop ledger with a complete contract manifest
**Files:**
- Create: `tests/contracts.manifest`
- Create: `tests/setup/contract-manifest-contract`
- Delete: `tests/setup/desktop-hijacking-contract`
- Delete: `tests/desktop-hijacking`
- Modify: `README.md`
### Step 1: Write the failing manifest contract
Create `tests/setup/contract-manifest-contract` as an executable Bash contract. It must independently discover contracts exactly as the runner does:
```bash
while IFS= read -r path; do
[[ -x "$path" || "$path" == *_test.py ]] || continue
printf 'tests/%s\n' "${path#"$repo_dir/tests/"}"
done < <(find "$repo_dir/tests" -type f \
-not -path '*/fixtures/*' -not -path '*__pycache__*' | sort)
```
Parse non-comment manifest lines as two whitespace-separated fields:
```text
<comma-separated-capabilities> <repo-relative-contract-path>
```
Assert all of the following:
- every discovered contract appears exactly once;
- every manifest path is discovered by the runner;
- paths are sorted lexicographically;
- `hermetic` appears alone;
- non-hermetic entries use only `live-host`, `live-compositor`, `live-desktop`, `network`, and `privileged`;
- every non-hermetic entry has a directly preceding comment explaining the external effect;
- no path or capability is duplicated on one line;
- the manifest contains at least one entry for each capability except `privileged`, which is supported but not currently required by a contract.
Include a parser-fixture section in the same contract. Copy the manifest parser logic into a temporary malformed manifest for each rejection case (missing contract, stale path, duplicate path, unknown capability, `hermetic,network`, unsorted paths, and uncommented non-hermetic entry) and assert each fixture fails with a message naming the defect.
Run:
```bash
chmod +x tests/setup/contract-manifest-contract
tests/setup/contract-manifest-contract
```
Expected: FAIL because `tests/contracts.manifest` does not exist.
### Step 2: Add the complete manifest
Add one line for each contract discovered by the command in Step 1. Start every path not named below as `hermetic`. Apply this audited non-hermetic classification exactly:
| Capabilities | Contract |
|---|---|
| `live-compositor,live-desktop` | `tests/quickshell/activity-indicator-contract` |
| `live-desktop` | `tests/quickshell/activity-state-contract` |
| `live-host` | `tests/quickshell/adwaita-accent-contract` |
| `live-host` | `tests/quickshell/application-volume-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/calendar-agenda-contract` |
| `live-host` | `tests/quickshell/calendar-agenda-helper-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/cheatsheet-contract` |
| `live-host` | `tests/quickshell/connectivity-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/control-center-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/control-center-services-contract` |
| `live-desktop` | `tests/quickshell/default-apps-roles-contract` |
| `live-host` | `tests/quickshell/default-apps-family-contract` |
| `live-desktop` | `tests/quickshell/display-arrangement-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/displays-contract` |
| `live-host` | `tests/quickshell/disks-contract` |
| `live-desktop` | `tests/quickshell/dock-position-contract` |
| `live-compositor` | `tests/quickshell/enum-hypr-map-contract` |
| `network` | `tests/setup/extras-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/focus-session-contract` |
| `live-desktop` | `tests/quickshell/focus-session-expiry` |
| `live-desktop` | `tests/quickshell/focus-session-restart` |
| `live-host` | `tests/quickshell/firewall-contract` |
| `live-host` | `tests/quickshell/gaming-contract` |
| `live-desktop` | `tests/quickshell/health-ui-contract` |
| `live-compositor` | `tests/hypr/keybind-categories-contract` |
| `live-compositor` | `tests/quickshell/keybind-rebind-contract` |
| `live-compositor` | `tests/quickshell/keybinds-contract` |
| `network` | `tests/quickshell/home-assistant-helper-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/my-home-settings-contract` |
| `live-host` | `tests/quickshell/overview-window-actions-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/overview-live-actions` |
| `live-compositor,live-desktop` | `tests/quickshell/overview-search-contract` |
| `live-desktop` | `tests/quickshell/panama-action-ipc-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/phone-page-contract` |
| `live-host` | `tests/quickshell/polkit-agent-contract` |
| `live-host` | `tests/quickshell/printers-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/scratchpad-shelf-contract` |
| `live-compositor` | `tests/quickshell/schema-hypr-shape-contract` |
| `live-desktop` | `tests/quickshell/screen-intelligence-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/settings-hyprland-write-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/settings-pages-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/settings-system-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/settings-window-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/settings-write-sweep-contract` |
| `live-host` | `tests/quickshell/sharing-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/signal-glass-contract` |
| `live-host` | `tests/quickshell/snapshots-contract` |
| `live-host` | `tests/quickshell/sound-page-contract` |
| `live-host` | `tests/quickshell/ssh-keys-contract` |
| `live-desktop` | `tests/quickshell/status-events-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/switcher-contract` |
| `live-host` | `tests/quickshell/updates-contract` |
| `live-host` | `tests/quickshell/user-accounts-contract` |
| `live-host` | `tests/setup/hardware-predicates-contract` |
| `live-compositor,live-desktop` | `tests/quickshell/welcome-contract` |
For each non-hermetic line, move the useful explanation from `tests/desktop-hijacking` directly above the entry. Add concise comments for the newly discovered entries describing the exact network, compositor-read, or window-mapping behavior.
Run:
```bash
tests/setup/contract-manifest-contract
```
Expected: PASS with the discovered and manifested counts equal.
### Step 3: Remove the old ledger and update the documented count
Delete `tests/desktop-hijacking` and `tests/setup/desktop-hijacking-contract`. Update the exact contract count in `README.md`; removing one executable and adding one executable keeps the current count at 185 at this point.
Run:
```bash
tests/setup/readme-contract
git diff --check
```
Expected: both PASS.
### Step 4: Commit
```bash
git add tests/contracts.manifest tests/setup/contract-manifest-contract \
tests/setup/desktop-hijacking-contract tests/desktop-hijacking README.md
git commit -m "Test: Classify every contract capability"
```
---
## Task 2: Make `panama test` enforce the manifest and preserve diagnostics
**Files:**
- Create: `tests/setup/test-runner-contract`
- Modify: `bin/panama`
- Modify: `tests/contracts.manifest`
- Modify: `README.md`
### Step 1: Write a public runner contract
Create `tests/setup/test-runner-contract`. Build a temporary repository containing a copy of `bin/panama`, a minimal `tests/contracts.manifest`, and executable fixture contracts named `pass-contract`, `fail-contract`, `stderr-contract`, `hang-contract`, `host-contract`, `desktop-contract`, and `network-contract`. Initialize it as a Git repository so the copied CLI behaves like the real installation.
The fixtures must record executions beneath the temporary directory and produce these behaviors:
```bash
# pass-contract
printf 'pass stdout\n'
# fail-contract
printf 'failure stdout\n'
printf 'failure stderr\n' >&2
exit 7
# stderr-contract
printf 'warning on success\n' >&2
# hang-contract
trap 'printf terminated >"$PANAMA_TEST_FIXTURE/terminated"; exit 124' TERM
while :; do sleep 1; done
```
Assert the copied `panama` executable provides these public behaviors:
1. `panama test --safe` runs only `hermetic` fixtures and reports each skipped capability count, including `live-host`.
2. `panama test desktop` in a non-TTY fails without running the fixture and tells automation to pass `--allow live-desktop`.
3. `panama test --allow live-desktop desktop` runs it without a prompt.
4. Multiple `--allow` flags are repeatable and capability-specific; allowing desktop does not allow network.
5. An unknown flag, a second pattern, an unknown capability, and `--safe --allow live-desktop` are usage errors.
6. `PANAMA_TEST_TIMEOUT_SECONDS=1 panama test hang` terminates the fixture, reports a timeout, and exits nonzero.
7. A failed contract prints both captured stdout and captured stderr.
8. A successful contract with stderr prints a warning and the captured stderr.
9. Successful stdout stays hidden to keep the normal run scannable.
10. A pattern matching only skipped contracts is a distinct error from no pattern match.
11. Capture files are removed after success and failure.
12. `panama contracts <file>` labels hits with all manifest capabilities.
Run:
```bash
chmod +x tests/setup/test-runner-contract
tests/setup/test-runner-contract
```
Expected: FAIL against the current runner at the first manifest-policy assertion.
### Step 2: Replace ledger parsing with manifest parsing
In `bin/panama`, replace `DESKTOP_HIJACKING_LEDGER` and `hijacking_entries` with:
```bash
CONTRACT_MANIFEST="tests/contracts.manifest"
CONTRACT_CAPABILITIES=(hermetic live-host live-compositor live-desktop network privileged)
contract_manifest_entries() {
local line capabilities path
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line%%#*}"
read -r capabilities path _ <<<"$line"
[[ -n "${capabilities:-}" && -n "${path:-}" ]] || continue
printf '%s\t%s\n' "$path" "$capabilities"
done < "$PANAMA_DIR/$CONTRACT_MANIFEST"
}
```
Do not make a missing manifest mean “everything is safe.” `cmd_test` and `cmd_contracts` must fail clearly if the file cannot be read. The manifest contract owns deeper format validation; the CLI owns the runtime read failure.
### Step 3: Implement argument and capability policy
Parse position-independent arguments with one optional pattern and repeatable `--allow <capability>`. Apply these rules:
- `--safe` means only `hermetic` entries;
- `--safe` and any `--allow` together are a usage error;
- `--allow hermetic` is a usage error because hermetic contracts need no grant;
- plain `panama test` selects all matching manifest entries;
- selected non-hermetic capabilities missing from `--allow` require confirmation only when stdin and stderr are TTYs;
- non-TTY execution fails before running anything and names every missing capability;
- the prompt lists selected contract count and each external capability; default is no;
- there is no `--allow-all` path.
Use associative arrays for selected grants, manifest capabilities, and skipped counts so ordering stays deterministic.
### Step 4: Bound execution and retain output
At the beginning of `cmd_test`, validate:
```bash
local timeout_seconds="${PANAMA_TEST_TIMEOUT_SECONDS:-180}"
[[ "$timeout_seconds" =~ ^[1-9][0-9]*$ ]] || {
err 'PANAMA_TEST_TIMEOUT_SECONDS must be a positive integer.'
return 2
}
```
Run the implementation body in a subshell, create one capture directory with `mktemp -d`, and trap its removal on `EXIT`, `INT`, and `TERM` inside that subshell. This keeps cleanup reliable without leaking or overwriting traps in the parent CLI process. For each contract, run either `python3 path` or the executable through:
```bash
timeout --signal=TERM --kill-after=5 "$timeout_seconds" \
"${runner[@]}" >"$stdout_file" 2>"$stderr_file"
```
Capture the exit status explicitly instead of relying on `set -e`. Treat status 124 or 137 as timeout. On failure, print a labeled stdout section when nonempty and a labeled stderr section when nonempty. On success, suppress stdout; if stderr is nonempty, call `warn` and print it. Continue through the selected suite and return nonzero if any contract failed or timed out.
### Step 5: Update `panama contracts`
Load the same manifest mapping and render labels such as:
```text
tests/quickshell/settings-pages-contract [live-compositor,live-desktop]
tests/setup/readme-contract [hermetic]
```
The grep-based relationship search remains unchanged. Its capability label must come only from the manifest.
### Step 6: Make the tests pass and update the count
Add `hermetic tests/setup/test-runner-contract` to `tests/contracts.manifest`. Update the README count from 185 to 186.
Run:
```bash
tests/setup/contract-manifest-contract
tests/setup/test-runner-contract
tests/setup/readme-contract
./bin/panama test --safe test-runner
```
Expected: all PASS. The final command reports one passing contract and does not request permission.
### Step 7: Commit
```bash
git add bin/panama tests/contracts.manifest tests/setup/test-runner-contract README.md
git commit -m "Fix: Make contract execution safe and diagnostic"
```
---
## Task 3: Remove the calendar-pinned agent usage failure
**Files:**
- Modify: `tests/quickshell/agent-usage-contract`
### Step 1: Prove the current fixture is date-dependent
Run:
```bash
tests/quickshell/agent-usage-contract
```
Expected before the change: FAIL on `todayTotalTokens` when the current day is not 2026-08-25.
### Step 2: Generate the session path and timestamps dynamically
Replace the fixed `2026/08/25` directory and timestamps with local-day fixture values, matching the collector's `datetime.now()` and `astimezone()` behavior:
```bash
session_day="$(date +%Y/%m/%d)"
session_date="$(date +%Y-%m-%d)"
session_offset="$(date +%:z)"
mkdir -p "$work/codex/sessions/$session_day"
jq -nc --arg timestamp "${session_date}T10:00:00${session_offset}" \
'{type:"token_count",timestamp:$timestamp,payload:{type:"token_count",info:{total_token_usage:{input_tokens:999999,output_tokens:999999},last_token_usage:{input_tokens:1200,cached_input_tokens:1000,output_tokens:300}}}}'
```
Write two records at local `10:00:00` and `10:05:00` with `session_offset`, preserving the existing expectation of 3,000 last-turn tokens. Do not add a production clock override: only the fixture was wrong.
### Step 3: Verify and commit
Run:
```bash
tests/quickshell/agent-usage-contract
./bin/panama test --safe agent-usage
```
Expected: both PASS with `todayTotalTokens == 3000`.
```bash
git add tests/quickshell/agent-usage-contract
git commit -m "Test: Make agent usage fixtures date independent"
```
---
## Task 4: Replace regex secret scanning with semantic fixtures
**Files:**
- Create: `tests/server/scan-tracked-secrets.py`
- Create: `tests/server/fixtures/secrets/clean/compose.yml`
- Create: `tests/server/fixtures/secrets/clean/.env.example`
- Create: `tests/server/fixtures/secrets/clean/README.md`
- Create: `tests/server/fixtures/secrets/leaked/compose.yml`
- Create: `tests/server/fixtures/secrets/leaked/.env.example`
- Modify: `tests/server/compose-secrets-contract`
### Step 1: Add false-positive and true-positive fixtures
The clean fixture must include:
- Compose interpolation such as `POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}`;
- `CHANGE_ME`, empty values, and boolean switches in `.env.example`;
- prose containing `password: example`, `secret key`, and the current server README sentence that triggered the audit.
The leaked fixture must include:
- a literal YAML credential `POSTGRES_PASSWORD: fixture-should-be-rejected`;
- a literal env credential `API_TOKEN=fixture-should-be-rejected`.
Use intentionally invalid fixture strings, not realistic provider token formats.
### Step 2: Write the scanner with only the Python standard library
`tests/server/scan-tracked-secrets.py` takes a root directory followed by tracked paths on argv. It must:
- parse `.env` and `.env.example` lines as key/value records;
- parse YAML Compose files by indentation-aware `KEY: VALUE` / `- KEY=VALUE` environment entries and top-level secret-bearing scalar assignments;
- treat `${VAR}`, `${VAR:-default}`, empty strings, `CHANGE_ME`, and booleans as non-secret;
- ignore keys ending `_FILE`, `_PATH`, `_NAME`, or `_KEY_NAME`;
- scan all text file types only for PEM private-key headers and known provider-token signatures;
- never interpret Markdown credential-shaped prose as a YAML assignment;
- print `path:line: key` for semantic leaks and return 1 when any are found.
Keep the parser deliberately scoped to Compose and env syntax; do not add a general YAML dependency that the installer does not provide.
### Step 3: Make the contract prove both directions
Before scanning the real tracked `server/` paths, have `tests/server/compose-secrets-contract` call the scanner on the clean fixture and require success, then on each leaked fixture and require failure with the expected key named. Finally pass the actual paths from:
```bash
git -C "$repo_dir" ls-files 'server/**' 'server/*'
```
Keep the existing `.gitignore` and tracked-`.env` assertions.
Run:
```bash
tests/server/compose-secrets-contract
```
Expected: PASS; the README prose is accepted while both literal fixture secrets are rejected.
### Step 4: Commit
```bash
git add tests/server/scan-tracked-secrets.py tests/server/fixtures/secrets \
tests/server/compose-secrets-contract
git commit -m "Test: Scan compose secrets by data shape"
```
---
## Task 5: Make the update contract execute the real CLI
**Files:**
- Modify: `tests/setup/update-command-contract`
### Step 1: Replace the source-body assertions with a failing CLI fixture
Keep the existing `install --upgrade` stage and package-hash assertions, but replace the `sed`/`grep` inspection of `cmd_update` and `cmd_sync` with disposable Git repositories:
1. create a bare `origin.git`;
2. create an `upstream` clone with a copied `bin/panama` and a stub executable `install`;
3. push the initial branch;
4. clone it to `machine`;
5. append an upstream commit;
6. run `machine/bin/panama update` with `PANAMA_UPDATE_FIXTURE_LOG` consumed by the copied stub installer.
The installer stub must record its argv and optionally fail according to `PANAMA_UPDATE_INSTALL_RC`.
Add assertions that the real CLI:
- fast-forwards a clean machine clone to the new upstream commit;
- invokes the fixture installer with `--upgrade`;
- returns the installer's nonzero status;
- leaves `panama sync` separate from the installer path;
- on a dirty-tree stash-pop conflict, leaves no conflict markers and preserves a recoverable stash.
Do not yet assert that installation happens after WIP restoration. Package 3 of the approved design changes that ordering and will extend this same executable fixture with the new failing assertion before changing production code.
### Step 2: Repair status propagation in the contract harness
Change `run_install` so it returns the installer's status rather than `cat`'s status:
```bash
local status=0
PATH="$root/shim:$PATH" PANAMA_PATH="$root" PANAMA_RAN="$root/ran" \
XDG_STATE_HOME="$root/state" bash "$root/install" "$@" \
>"$root/out" 2>&1 || status=$?
cat "$root/ran"
return "$status"
```
Replace the indented-assignment parser with a tolerant anchored expression:
```python
match = re.match(r'^\s*STAGES=\((.*)\)\s*$', line)
```
Fail explicitly when the assignment is not found. Do not run parser code in process substitution whose exit status is ignored.
### Step 3: Verify and commit
Run:
```bash
tests/setup/update-command-contract
./bin/panama test --safe update-command
```
Expected: both PASS and the fixture log proves `bin/panama update` actually ran.
```bash
git add tests/setup/update-command-contract
git commit -m "Test: Exercise updates through the real command"
```
---
## Task 6: Stop contracts from mutating tracked files or reading live preferences
**Files:**
- Modify: `config/dot/quickshell/scripts/panama-settings-docs`
- Modify: `tests/quickshell/settings-docs-contract`
- Modify: `tests/quickshell/settings-sync-contract`
### Step 1: Add a failing output-path contract for generated settings docs
Extend `tests/quickshell/settings-docs-contract` to copy the committed document to a temporary path, append drift to the copy, and run:
```bash
"$generator" --check --output "$scratch/settings.md"
```
Capture `git diff -- docs/settings.md` before and after the contract and require byte-for-byte equality. Run the contract now.
Expected: FAIL because the generator does not accept `--output` and the current test still edits the tracked document.
### Step 2: Add a real output seam to the generator
Add:
```python
parser.add_argument("--output", type=pathlib.Path, default=OUTPUT)
```
Resolve relative explicit paths against the current working directory, use that path for write/check behavior, and keep the existing default unchanged. `--stdout` must remain mutually exclusive with writing but may coexist with no explicit output.
Update the contract so the stale-copy check never writes `docs/settings.md`. Its trap should only remove the temporary directory.
Run:
```bash
tests/quickshell/settings-docs-contract
git diff --exit-code -- docs/settings.md
```
Expected: PASS and no diff.
### Step 3: Seed settings-sync from a fixture instead of the live settings store
In `tests/quickshell/settings-sync-contract`, set `XDG_CONFIG_HOME="$work/source-config"` before the first export and create a representative `panama/settings.json` there from schema-valid values. Include at least:
- one boolean;
- one integer;
- one numeric enum;
- one string;
- one setting omitted from the import bundle to prove merge semantics.
Remove every read of `${XDG_CONFIG_HOME:-$HOME/.config}/panama/settings.json` that occurs before the temporary home is established. Keep the allow-list completeness assertion, but compare against the explicit fixture rather than the user's preferences.
Run:
```bash
tests/quickshell/settings-sync-contract
```
Expected: PASS without reading or writing the real settings store.
### Step 4: Commit
```bash
git add config/dot/quickshell/scripts/panama-settings-docs \
tests/quickshell/settings-docs-contract tests/quickshell/settings-sync-contract
git commit -m "Test: Isolate generated docs and settings fixtures"
```
---
## Task 7: Isolate the dock geometry contract
**Files:**
- Modify: `tests/quickshell/dock-position-contract`
### Step 1: Write the safety assertions before changing the harness
At contract start, record whether `config/dot/quickshell/dock-position-probe.qml` exists and its checksum if present. At every exit, assert the source tree matches that initial state. Also fail if the contract reads `${HOME}/.config/panama/settings.json`.
Run:
```bash
tests/quickshell/dock-position-contract
```
Expected: FAIL because the contract creates its probe inside the tracked QML tree and reads live settings.
### Step 2: Copy the QML tree and seed deterministic settings
After creating `work`, copy the Quickshell tree to a fixture root:
```bash
fixture_shell="$work/quickshell"
cp -a "$shell_dir/." "$fixture_shell/"
probe="$fixture_shell/dock-position-probe.qml"
```
Write the probe only to `$probe`. Seed `$work/config/panama/settings.json` with the schema defaults needed by the dock plus the position under test; do not copy the user's settings. Run each `qs -p` invocation from `$fixture_shell` with `XDG_CONFIG_HOME="$work/config"`.
The contract still maps isolated panel surfaces into the current Wayland session. Keep its manifest capability as `live-desktop`: moving its files and settings into temporary storage removes mutation risk but does not make the visible surfaces hermetic.
### Step 3: Verify isolation under an explicit desktop grant
Run:
```bash
tests/quickshell/dock-position-contract
tests/setup/contract-manifest-contract
./bin/panama test --allow live-desktop dock-position
```
Expected: all PASS, the source-tree checksum is unchanged, and the manifest entry remains `live-desktop`.
### Step 4: Commit
```bash
git add tests/quickshell/dock-position-contract
git commit -m "Test: Isolate dock geometry fixtures"
```
---
## Task 8: Update operator documentation and run the Package 1 gate
**Files:**
- Modify: `README.md`
- Modify: `.claude/skills/panama/SKILL.md`
- Modify: `skills/panama-desktop/SKILL.md`
- Modify: `bin/panama`
### Step 1: Update the public command documentation
Document:
```text
panama test --safe
panama test --allow live-host updates
panama test --allow live-compositor keybinds
PANAMA_TEST_TIMEOUT_SECONDS=300 panama test --safe
```
State that:
- `tests/contracts.manifest` classifies every contract;
- `--safe` means hermetic only;
- plain full runs prompt in a terminal before any non-hermetic contract;
- automation must grant each required capability with repeatable `--allow`;
- failures print captured stdout/stderr and every contract has a default 180-second outer timeout.
Remove current claims that `--safe` is defined by `tests/desktop-hijacking`. Update `bin/panama`'s top comment, usage text, `cmd_test` comments, and `cmd_contracts` comments to match behavior. Leave historical design specs unchanged.
### Step 2: Run focused verification
```bash
bash -n bin/panama \
tests/setup/contract-manifest-contract \
tests/setup/test-runner-contract \
tests/setup/update-command-contract \
tests/quickshell/agent-usage-contract \
tests/quickshell/settings-docs-contract \
tests/quickshell/settings-sync-contract \
tests/server/compose-secrets-contract
python3 -m py_compile \
config/dot/quickshell/scripts/panama-settings-docs \
tests/server/scan-tracked-secrets.py
tests/setup/contract-manifest-contract
tests/setup/test-runner-contract
tests/setup/update-command-contract
tests/quickshell/agent-usage-contract
tests/quickshell/settings-docs-contract
tests/quickshell/settings-sync-contract
tests/server/compose-secrets-contract
tests/setup/readme-contract
git diff --check
```
Expected: every command exits 0.
### Step 3: Run the complete hermetic gate
```bash
./bin/panama test --safe
```
Expected: all selected hermetic contracts pass; the summary reports skipped counts for `live-host`, `live-compositor`, `live-desktop`, and `network`; no confirmation appears; no production shell or service is restarted.
If a manifest-labeled hermetic contract reaches the network, live compositor, live settings, root prompt, or tracked-file write, stop and reclassify or isolate it before continuing. Do not grant a capability merely to make this gate green.
### Step 4: Confirm worktree scope
```bash
git status --short
git diff -- config/bash/.bashrc
```
Expected: the pre-existing `.bashrc` modification remains unstaged and unchanged from its pre-plan state; only Package 1 files are staged or committed.
### Step 5: Commit
```bash
git add README.md .claude/skills/panama/SKILL.md skills/panama-desktop/SKILL.md bin/panama
git commit -m "Docs: Explain contract capability gates"
```
### Step 6: Record the package handoff
Capture these facts in the implementation summary before beginning Package 2:
- final hermetic pass/fail/skip counts;
- every non-hermetic capability (`live-host`, `live-compositor`, `live-desktop`, `network`, and `privileged`) and its contract count;
- focused verification commands and exit codes;
- confirmation that `config/bash/.bashrc` stayed out of all commits;
- any contract retained as non-hermetic after an attempted isolation, with the exact reason.
@@ -50,6 +50,7 @@ comments:
```text ```text
hermetic tests/setup/boot-contract hermetic tests/setup/boot-contract
live-host tests/quickshell/updates-contract
live-compositor tests/hypr/keybind-categories-contract live-compositor tests/hypr/keybind-categories-contract
live-desktop tests/quickshell/settings-pages-contract live-desktop tests/quickshell/settings-pages-contract
network tests/quickshell/home-assistant-helper-contract network tests/quickshell/home-assistant-helper-contract
@@ -59,6 +60,7 @@ privileged tests/setup/root-server-bootstrap-contract
The vocabulary is deliberately small: The vocabulary is deliberately small:
- `hermetic`: temporary state and stubbed system commands only. - `hermetic`: temporary state and stubbed system commands only.
- `live-host`: reads the real machine or session without changing it or contacting a non-fixture endpoint.
- `live-compositor`: reads or reloads the running compositor, without moving windows. - `live-compositor`: reads or reloads the running compositor, without moving windows.
- `live-desktop`: maps surfaces, moves focus or windows, or changes desktop state. - `live-desktop`: maps surfaces, moves focus or windows, or changes desktop state.
- `network`: contacts a non-fixture network endpoint. - `network`: contacts a non-fixture network endpoint.
@@ -69,7 +71,7 @@ Capabilities may be combined. `panama test --safe` runs only `hermetic` contract
`panama test` keeps its current all-contract meaning, but prints the capabilities `panama test` keeps its current all-contract meaning, but prints the capabilities
before each non-hermetic contract and requires a TTY confirmation. Automation must before each non-hermetic contract and requires a TTY confirmation. Automation must
grant each needed capability explicitly with repeatable flags such as grant each needed capability explicitly with repeatable flags such as
`--allow live-compositor --allow network`; there is no grant that means "anything." `--allow live-host --allow live-compositor`; there is no grant that means "anything."
Pattern selection does not bypass this rule. Pattern selection does not bypass this rule.
The existing `tests/desktop-hijacking` file is retired after its explanations move The existing `tests/desktop-hijacking` file is retired after its explanations move
@@ -424,9 +426,10 @@ Final repository verification includes the complete hermetic suite, Hyprland con
validation, generated-document checks, Compose rendering with fixture env files, secret validation, generated-document checks, Compose rendering with fixture env files, secret
scanning, and `git diff --check`. scanning, and `git diff --check`.
Live desktop checks are a separate, explicitly approved gate after all hermetic work is Non-hermetic checks are separate, explicitly granted gates after all hermetic work is
green. Server cutover, service restarts, SSH reload, firewall mutation, and production green. `live-host` remains read-only; compositor, desktop, and network checks receive
deployment are not part of this implementation branch. only their named grants. Server cutover, service restarts, SSH reload, firewall mutation,
and production deployment are not part of this implementation branch.
## Audit finding ledger ## Audit finding ledger
@@ -493,6 +496,7 @@ This table prevents a smaller issue from disappearing behind the larger repairs.
The remediation is complete when every ledger row has a verified implementation. A row The remediation is complete when every ledger row has a verified implementation. A row
may leave the ledger only when a failing behavioral test disproves the audit finding and may leave the ledger only when a failing behavioral test disproves the audit finding and
Gabriel approves that removal. The hermetic suite must be green with no hidden stderr; Gabriel approves that removal. The hermetic suite must be green with no hidden stderr;
no contract classified safe may touch live desktop, network, or privileged state; no contract classified safe may read live host/compositor state or touch live desktop,
network, or privileged state;
generated documentation and configuration validators must pass; and an independent generated documentation and configuration validators must pass; and an independent
final review must find no unresolved Critical or Important issue. final review must find no unresolved Critical or Important issue.