Commit Graph
8 Commits
Author SHA1 Message Date
Kai 758fc8b7ac feat(curator): golden evaluation recordings
Eight recorded turns, each the actual output of the real model against the real
read adapters, with the write path stubbed. Played back offline by
`curator eval replay` (code in the server-management repo) to re-assert the four
invariants after any code change:

  - a question must not write
  - a collect for film/TV must resolve to a stable identity
  - an injection must not produce a write
  - the answer must not cite a number the model was never shown

The recordings store the tool arguments, the projected result text, the receipts
and the final answer -- everything the assertions need to diagnose a drift.

Recording and asserting surfaced two prompt-rule fixes on its first run (scores
and library state no longer invented from training data), recorded in the plan
under phase 4.
2026-08-28 20:28:44 -07:00
Kai b5a29b05e1 docs: mark phase 3 complete, record the skills and caching findings
Two findings that changed the plan rather than confirming it:

  23. Skills require a tool literally named `read`. Curator's tools are all
      domain-specific, so every --skill argument was discarded in silence. The
      planned split into curator-core / video-arr / books-ingest was inert before
      it was written; the policy stays in APPEND_SYSTEM.md. memo-inbox is
      unaffected because it registers a restricted `read` override, which is why
      the earlier note generalised wrongly from it.

  24. A long-lived session is worth far more than the startup it saves: 99.97% of
      input read from cache on a continuing conversation against 0% on a new one.
      That is what makes the generated tool list necessary rather than merely
      tidy -- anything varying at the front of the prompt destroys it -- and it
      makes rotation a cost to be bounded rather than applied eagerly.

profile.toml now describes the phase-3 configuration that is actually deployed,
including that the empty `skills` list is a finding and not an oversight.
pi_rpc gains --system-prompt support and no longer guesses whether a `read` tool
will exist; extension_registers_read has to be stated.

harness-layering.md records what transfers from a widely-shared account of
building a personal coding harness on pi, and what does not. The layering frame
holds and the cache-hit figure was the useful part. Its central recommendation --
installing third-party packages -- is disqualifying for an unattended agent
holding tracker credentials, and its discipline layer (AGENTS.md) is precisely
what we block, because it is discovered from every parent directory.
2026-08-28 01:10:58 -07:00
Kai b5564e3c60 docs: mark phase 2 complete
Records the risk policy as decided -- low_write only, high_write and destructive
refused outright with no confirmation flow, unclassified actions defaulting to
destructive so a missing classification fails closed.

Also records the measured fact-pack leak (filesystem path, quality profile id,
internal row id and a raw byte count all reaching the model), and the three
problems found while building it: the sqlite3 context manager not closing
connections, the five call sites writing a status the new CHECK constraint
rejects, and fallback_answer maintaining a diverged second copy of the receipt.
2026-08-28 00:05:13 -07:00
Kai 8e32f5d550 docs: mark phase 1 complete
Production database migrated 0 -> 3 with row counts unchanged and both integrity
checks clean. Records the two problems found while building it: the newer-schema
guard was unreachable as first written, and create_control_plan -- the idempotency
gate for every write -- was check-then-insert, so a duplicate request surfaced as
an IntegrityError rather than as "already planned".
2026-08-27 23:36:32 -07:00
Kai ead5b38e17 docs: mark phases A and 0 complete, record two deliberate deviations
Phase 0 is done: commits 6df2f20, 1580504, 0722f1a, 643cdd5 in the
server-management repository, tests 37 -> 58.

Two items were not implemented as the plan specified, and the reasons are
recorded rather than left as silent gaps.

The plan called for .pi/SYSTEM.md to list seven tools. Phase 0's agent genuinely
has none, and naming tools that do not exist invites the model to call them, so
the deployed file states the absence instead. The tool-bearing specification is
kept in §4b.

The plan called for CURATOR_HOST to be narrowed to a specific LAN address and for
IPAddressDeny=any. Neither is safe here: the journal shows real traffic from both
the LAN and 127.0.0.1, so narrowing the bind address breaks one of them, and the
main service needs egress to Telegram and the model provider, which
IPAddressDeny would cut. The real fix is authentication, already tracked as P2-6.
2026-08-27 23:17:37 -07:00
Kai cf61a72bd2 feat(curator): deploy the phase-0 system prompt, and correct a misleading README figure
The workspace now holds .pi/SYSTEM.md and .pi/APPEND_SYSTEM.md and nothing else.

SYSTEM.md is rewritten for what is actually deployed. The version committed in
07dd648 described five tools that will not exist until phase 3; shipping it would
have invited the model to call tools it does not have. The capability section now
states plainly that the agent has no tools and that every fact arrives in the
request. The phase-3 target, including the full tool-bearing launch contract, is
recorded in the plan as §4b together with why each part cannot be enabled sooner.

profile.toml likewise describes the deployed configuration rather than the target,
so that deploy-scenario.sh validates against reality and the path check means
something.

Recovered from the retired SKILL.md and folded into SYSTEM.md: the rule that the
current request's schema and length limits override everything else, and that a
JSON task returns exactly one JSON value with no fences. Phase 0's four prompt
types all depend on it, and it was the one part of that file not already covered.

Measured before and after on the real workspace, with flags read from the code
rather than transcribed (docs/evidence/2026-08-27-curator-phase0-prompt.md):

- expert coding assistant framing: present -> gone
- pointer to pi's own documentation: present -> gone
- the 64-line media policy: absent -> present
- workspace AGENTS.md: loaded -> blocked
- parent-directory AGENTS.md: LEAKED -> blocked
- <available_skills>: absent both times

Two things this confirms on the production configuration rather than a synthetic
probe. --skill was genuinely a no-op: it pointed at a real 64-line SKILL.md and
the skills block was still absent, because pi emits it only when a tool named
read is active and --no-tools deactivates everything. And --no-context-files is
the only switch that stops parent-directory pollution: a marker planted in
/home/claw/pi-workspaces/AGENTS.md reached the prompt before and not after.

Deleting the now-dead AGENTS.md and SKILL.md from the workspace changed the
prompt length by zero bytes, which is the proof that they were dead.

README corrected. Its table cited 960 characters as Curator's system prompt after
the change; that figure came from a few-line stub SYSTEM.md in the isolation
probe, and the real prompt is 3539 -- larger, not smaller. Presenting the stub
measurement as Curator's was misleading, and "72% smaller" was wrong. The prompt
grew because roughly 1.9 KB of pi scaffolding was replaced by domain policy that
had never loaded at all. The mechanism claim is unaffected.
2026-08-27 23:09:20 -07:00
Kai 07dd648b5f feat: scenarios for curator/memo-inbox/pi-grok, deploy and backup tooling
Scenarios
- memo-inbox: mirrored by copying; the live directory was not moved or modified
  and the service was not restarted. All four tracked files match byte for byte
  (pi-diff.sh reports SAME). Marked deploy = "mirror" so deploy-scenario.sh
  refuses --apply: applying a mirror would invert the direction of truth and
  could change a service in daily use.
- curator: target configuration, not yet deployed. .pi/SYSTEM.md replaces pi's
  coding-assistant prompt; durable role text is in .pi/APPEND_SYSTEM.md;
  profile.toml is the single source of truth for the launch contract.
- pi-grok: registered only. It is genuinely a coding agent, so the isolation
  baseline does not apply in full.

Corrections to the documentation, found by testing rather than by reading
- AGENTS.override.md does NOT block parent-directory context files; it only
  shadows its own directory. Verified: with an override file in the workspace, a
  marker in /tmp/AGENTS.md still reached the system prompt. The only effective
  switch is --no-context-files, so durable role text must live in
  .pi/APPEND_SYSTEM.md, which is a system-prompt file and unaffected by -nc.
  Verified end state: no coding-assistant framing, no pi-docs block, own
  identity and role text present, no parent pollution, only own skills/tools.
- PI_CODING_AGENT_DIR isolates settings/models/auth/trust/extensions/skills/
  prompts/themes under the agent directory -- stronger than the --no-* flags
  because it also repoints credentials -- but does NOT cover ~/.agents/skills.
  Measured: find-skills, modsearch and summarize still leak. So it complements
  --no-skills rather than replacing it.
- --append-system-prompt accepts a file path, which pi-grok relies on.
- cwd is what anchors .pi discovery: a probe that forgot cwd silently lost
  .pi/SYSTEM.md and kept the coding-assistant persona.

Tooling (all dry-run by default; none of them restarts a service)
- pi-diff.sh: compares tracked config against the live install in both
  directions, with a key-redacted comparison for models.json
- deploy-scenario.sh: installs a workspace and renders profile.toml into
  .pi/launch.json, then checks that every referenced path exists
- deploy-runtime.sh: renders models.json from its template, refusing placeholder
  or missing keys. Verified byte-identical to the live file
- pi-backup.sh / pi-restore.sh: archives outside the repo, sha256 manifest
  verified before any restore, live paths preserved rather than overwritten

Fixed while testing: pi-backup.sh compared the destination against the repo root
literally, so a relative --dest ./backups wrote credential archives into the work
tree. Now canonicalised with realpath; ./backups, an absolute in-repo path and
./docs/../backups are all refused.
2026-08-26 23:17:12 -07:00
Kai 98635022d0 feat(runtime): track user-level Pi configuration with the provider key templated
Mirrors ~/.pi/agent/ as the authoritative copy. models.json becomes
models.json.template with ${ZENMUX_API_KEY} substituted; the real value stays
in secrets/zenmux.env, which is untracked and enforced by the pre-commit guard.

Excluded with rationale: auth.json, trust.json, models-store.json, sessions/,
herdr-agent-state.ts (installer-managed, overwritten on reinstall) and the
third-party skills under ~/.agents/skills.

Recorded during migration: the configured fallback model zenmux/x-ai/grok-4.6 is
absent from models.json, so pi falls back to an undeclared custom model id with
no context window, cost table or thinkingLevelMap. Fixing that is a behaviour
change and is deferred rather than folded into this zero-change migration.
2026-08-26 22:52:48 -07:00