Files
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

109 lines
4.3 KiB
TOML

# memo-inbox — Pi scenario profile
#
# STATUS: as-found mirror. This file records what the live service actually does
# as of 2026-08-27. It is NOT yet the target configuration.
#
# The migration into this repository is deliberately zero-behaviour-change: the
# service is in daily use, so its launch flags are transcribed rather than fixed.
# The gaps below are tracked in docs/isolation-baseline.md and are scheduled for
# a separate pass (plan phase 5).
[scenario]
name = "memo-inbox"
description = "Routes Kai's Telegram/WeChat messages into Google Calendar, today's Obsidian todo list, or a journal memo."
workspace = "/home/claw/pi-workspaces/memo-inbox"
session_dir = "/home/claw/.local/share/pi-memo-telegram/sessions"
service = "pi-memo-telegram.service"
# "mirror": this file records what the live host does; it is not yet the source
# of truth. deploy-scenario.sh refuses --apply for mirrors so that a service in
# daily use cannot be changed by a migration commit. Promote to "managed" only
# together with the phase-5 isolation work.
deploy = "mirror"
# The gateway application lives inside the agent's own cwd, which is not ideal:
# the workspace an agent can read should not contain the code that drives it.
# Moving it is tracked as a follow-up; it is not a configuration change.
gateway = "/home/claw/pi-workspaces/memo-inbox/telegram-gateway/gateway.py"
[model]
provider = "zenmux"
primary = "x-ai/grok-4.6"
# No fallback model is configured for this scenario.
thinking = "medium"
[session]
# Implemented in gateway.py: PI_SESSION_ROTATE_AFTER_PROMPTS, plus an
# additional messageCount >= 60 check in rotate_if_oversized().
rotate_after_prompts = 24
rotate_after_messages = 60
# Uses --continue rather than --session-id, so continuity depends on "most
# recent session in this project" rather than an explicit identifier.
strategy = "continue"
[isolation]
# ---- as-found ----
# Layers 3 and 4 are correct and are the reference implementation for the other
# scenarios: memo-guard.ts calls setActiveTools(ALLOWED_TOOLS) on session_start
# and resources_discover, and blocks anything else in a tool_call hook.
capability_guard = true # pi.setActiveTools
invocation_guard = true # pi.on("tool_call") -> block
read_override = true # restricted read, workspace + vault only
# Layer 1 is NOT applied: user-global extensions and skills load into this
# agent. Measured leak from ~/.agents/skills: find-skills, modsearch, summarize.
no_extensions = false # gap
no_skills = false # gap
no_prompt_templates = false # gap
no_themes = false # gap
no_builtin_tools = false # gap — relies on setActiveTools alone
approve = true # passed on the command line
# Layer 2 is NOT applied: the agent runs on pi's default coding-assistant system
# prompt, with AGENTS.md layered on top as project context.
system_prompt_file = "" # gap — no .pi/SYSTEM.md
context_files = "AGENTS.md"
[env]
# gateway.py inherits the full process environment, so ASR_API_KEY and whatever
# else the unit carries reach the node process and every extension it loads.
minimal = false # gap
[tools]
# Enforced by ALLOWED_TOOLS in .pi/extensions/memo-guard.ts.
# Note: SKILL.md also declares an `allowed-tools:` frontmatter field, but pi
# 0.84.3 does not consume it. The array below is the only real enforcement.
allow = [
"read",
"image_view",
"document_parse",
"document_ocr",
"vault_search",
"journal_append",
"journal_batch_append",
"calendar_list",
"calendar_create",
"calendar_update",
"calendar_delete",
]
# Tools whose results are user-visible state changes. gateway.py harvests their
# text from tool_execution_end and reports that, instead of trusting the model's
# prose — the pattern the curator scenario should adopt.
receipt_tools = [
"journal_append",
"journal_batch_append",
"calendar_create",
"calendar_update",
"calendar_delete",
]
[backends]
parser_base_url = "http://127.0.0.1:8090" # PI_MEMO_PARSER_BASE_URL
ocr_base_url = "http://192.168.50.100:8001" # PI_MEMO_OCR_BASE_URL, LAN not loopback
ocr_model = "firered-ocr"
vault = "/home/claw/obsidian-vault"
calendar_cli = "/home/claw/.npm-global/bin/gws"
[secrets]
# Not in this repository.
env_file = "/home/claw/.secrets/pi-memo-telegram.env"