docs: repository README, contributor rules, scenario template and authoring guide

README leads with the finding that motivated the repository -- pi emits the
skills section only when a tool named 'read' is active, so Curator's
--no-tools --skill combination made its policy unreachable -- with the measured
before/after table and instructions to reproduce it at zero token cost.

AGENTS.md sets seven rules for anyone changing this repository. The third is the
one that matters most: verify pi's behaviour with a probe rather than inferring it
from the docs. Three claims in the first draft of these documents were wrong and
were only corrected by running one.

The _template scenario carries the isolation defaults and inline warnings at the
places where mistakes have already cost time: --no-tools disabling the skills
mechanism, cwd anchoring .pi discovery, the read override being mandatory rather
than optional, and allowed-tools frontmatter not being enforced in 0.84.3.
This commit is contained in:
Kai
2026-08-26 23:19:19 -07:00
parent 07dd648b5f
commit f25082223e
8 changed files with 518 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
# pi-agent-config
Authoritative configuration for every [Pi](https://pi.dev) agent on this host:
the user-level Pi runtime, plus one directory per dedicated agent scenario.
The live locations (`~/.pi/agent`, `~/pi-workspaces/*`) are **runtime copies**.
Changes are made here and pushed out with `scripts/deploy-*.sh`, never the other
way round — except for scenarios explicitly marked `deploy = "mirror"`, which
record what a running service already does.
Verified against **pi 0.84.3**. Re-run the probes after every `pi update`.
## Scenarios
| Scenario | Purpose | Service | Status |
|---|---|---|---|
| [`curator`](scenarios/curator/) | Book / film / TV / music curation agent | `curator.service` | target config written, **not yet deployed** |
| [`memo-inbox`](scenarios/memo-inbox/) | Routes Telegram/WeChat messages to Calendar, Obsidian todo or journal | `pi-memo-telegram.service` | **mirror** of live config, zero behaviour change |
| [`pi-grok`](scenarios/pi-grok/) | Interactive Grok 4.6 coding agent | none (manual) | registered only |
## Start here
| Document | Contents |
|---|---|
| [`docs/pi-runtime-notes.md`](docs/pi-runtime-notes.md) | pi 0.84.3 mechanics that the official docs understate, each verified against source or a live probe |
| [`docs/isolation-baseline.md`](docs/isolation-baseline.md) | The four isolation layers and the flag set every scenario should use |
| [`docs/personality-layering.md`](docs/personality-layering.md) | How to choose between `SYSTEM.md`, `APPEND_SYSTEM.md`, `AGENTS.md`, `SKILL.md` and the request |
| [`docs/gateway-patterns.md`](docs/gateway-patterns.md) | Ten patterns for hosting an agent behind a long-running service |
| [`docs/plans/`](docs/plans/) | Active work plans |
## The finding that motivated this repository
pi emits the `<available_skills>` block **only when a tool named `read` is
active** (`dist/core/system-prompt.js:59,113`). The Curator service ran with
`--no-tools --skill …` for its entire lifetime, so:
- its 64-line media policy never reached the model,
- `--skill` was a no-op,
- and both the README and the deployment runbook described a mechanism that was
not happening.
Measured effect of fixing the flags and adding `.pi/SYSTEM.md`:
| Configuration | system prompt | active tools | skills visible | coding-assistant persona |
|---|---:|---|---|---|
| `--no-tools` (as found) | 1859 | none | **no** | yes |
| no isolation flags | 3413 | own + `read` | 3 foreign | yes |
| `+ --no-skills --skill` | 2619 | own + `read` | 1, correct | yes |
| `+ .pi/SYSTEM.md --approve` | **960** | own + `read` | 1, correct | **no** |
72 % smaller *and* strictly more capable. Reproduce with
[`docs/evidence/probe-harness/`](docs/evidence/probe-harness/) — it costs zero
model tokens, because a single RPC `get_state` starts the agent, fires
`session_start` and exits without contacting the provider.
## Layout
```
docs/ mechanics, baselines, plans, reproducible evidence
runtime/agent/ ~/.pi/agent — settings, models.json.template, extensions, prompts
shared/ cross-scenario code
lib/py/pi_rpc.py long-lived RPC client with rotation and budgets
extensions/pi-guard-base.ts path containment, restricted read, capability guard
scenarios/<name>/
profile.toml single source of truth for the launch contract
workspace/ what gets installed into the live workspace
eval/ recorded golden transcripts
scripts/ diff, deploy, backup, restore, secret guard
secrets/ host-local, untracked
```
## Usage
```bash
# What differs between this repository and the host?
scripts/pi-diff.sh
scripts/pi-diff.sh curator
# Push configuration out (dry run first; neither restarts a service)
scripts/deploy-runtime.sh
scripts/deploy-runtime.sh --apply
scripts/deploy-scenario.sh curator --apply
# Back up the live installation (archives land outside this repository)
scripts/pi-backup.sh
scripts/pi-restore.sh --from <backup dir>
# Verify the mechanics still hold after a pi upgrade
docs/evidence/probe-harness/collect-evidence.sh
shared/extensions/tests/run-guard-checks.sh
python3 shared/lib/py/tests/test_pi_rpc_smoke.py
```
## Secrets
Nothing real ever enters this repository. `models.json`, `auth.json`,
`trust.json` and every `*.env` are ignored; `secrets/` accepts only `.gitkeep`,
`README.md`, `*.example` and `*.template`.
`scripts/verify-no-secrets.sh` enforces this as a pre-commit hook. Install it in
a fresh clone:
```bash
ln -sf ../../scripts/verify-no-secrets.sh .git/hooks/pre-commit
scripts/verify-no-secrets.sh --all
```
Backups contain plaintext credentials and are written outside the work tree;
`pi-backup.sh` refuses any destination that resolves inside it.
## First-time setup on a new host
```bash
git clone gitea-45:kai/pi-agent-config.git && cd pi-agent-config
ln -sf ../../scripts/verify-no-secrets.sh .git/hooks/pre-commit
cp secrets/zenmux.env.example secrets/zenmux.env
chmod 600 secrets/zenmux.env && $EDITOR secrets/zenmux.env
npm install -g @earendil-works/pi-coding-agent@0.84.3
scripts/deploy-runtime.sh --apply
scripts/deploy-scenario.sh <scenario> --apply
```