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.
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# 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"
|
||||
Reference in New Issue
Block a user