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,127 @@
|
||||
# curator — Pi scenario profile
|
||||
#
|
||||
# STATUS: target configuration. The live service does NOT yet run this; it is
|
||||
# still on the pre-refactor launch parameters. Switching over happens in plan
|
||||
# phase 3 (docs/plans/2026-08-curator-agent-refactor.md).
|
||||
#
|
||||
# This file is the single source of truth for the launch contract.
|
||||
# scripts/deploy-scenario.sh renders it into <workspace>/.pi/launch.json, and
|
||||
# curator/pi_agent.py MUST read that file and fail closed if it is missing:
|
||||
# silently running without --no-extensions would widen the agent's reach.
|
||||
|
||||
[scenario]
|
||||
name = "curator"
|
||||
description = "Personal book / film / TV / music curation agent for the Curator service."
|
||||
workspace = "/home/claw/pi-workspaces/curator"
|
||||
session_dir = "/home/claw/.local/share/pi-curator/sessions"
|
||||
service = "curator.service"
|
||||
# Application code lives in a separate repository and is intentionally outside
|
||||
# the agent's workspace.
|
||||
backend = "/home/claw/codex-workspace/server-management/deploy/curator"
|
||||
|
||||
[model]
|
||||
provider = "zenmux"
|
||||
primary = "openai/gpt-5.6-luna"
|
||||
fallback = "x-ai/grok-4.6"
|
||||
|
||||
# One global thinking level was the dominant p50 latency contributor: intent
|
||||
# classification ran at "high" at the front of every message. Differentiate.
|
||||
[model.thinking]
|
||||
conversation = "high"
|
||||
extraction = "low"
|
||||
synthesis = "medium"
|
||||
|
||||
[session]
|
||||
# Per Telegram chat. The client appends a rotation counter, so history stays
|
||||
# greppable on disk instead of being summarised away.
|
||||
id_prefix = "curator-tg"
|
||||
rotate_after_prompts = 20
|
||||
rotate_after_messages = 50
|
||||
strategy = "session-id"
|
||||
|
||||
[isolation]
|
||||
# Verified combination — see docs/evidence/. Result: no coding-assistant
|
||||
# framing, no pi-docs block, no parent-directory context pollution, only this
|
||||
# scenario's own skills, only this scenario's own tools.
|
||||
no_builtin_tools = true # not --tools: a registry allowlist would block
|
||||
# tools registered dynamically from the backend
|
||||
no_extensions = true
|
||||
no_skills = true
|
||||
no_prompt_templates = true
|
||||
no_themes = true
|
||||
no_context_files = true # the ONLY switch that stops parent-dir AGENTS.md;
|
||||
# AGENTS.override.md does not (verified)
|
||||
approve = true # required to load .pi/SYSTEM.md and .pi/settings.json
|
||||
|
||||
[personality]
|
||||
# Both are system-prompt files, so --no-context-files does not affect them.
|
||||
system_prompt = ".pi/SYSTEM.md" # replaces pi's default prompt
|
||||
append_system_prompt = ".pi/APPEND_SYSTEM.md" # durable domain responsibilities
|
||||
context_files = [] # deliberately none
|
||||
|
||||
[resources]
|
||||
extensions = [".pi/extensions/curator-tools.ts"]
|
||||
skills = [
|
||||
".pi/skills/curator-core",
|
||||
".pi/skills/video-arr",
|
||||
".pi/skills/books-ingest",
|
||||
]
|
||||
|
||||
[tools]
|
||||
# Enforced twice: setActiveTools plus a tool_call block, both inside
|
||||
# curator-tools.ts. The CLI is not the security boundary.
|
||||
#
|
||||
# `read` is a restricted override from shared/extensions/pi-guard-base.ts. It is
|
||||
# mandatory, not optional: pi emits the skills section only when a tool named
|
||||
# `read` is active, and skill bodies load through it.
|
||||
allow = [
|
||||
"read",
|
||||
"curator_query_library",
|
||||
"curator_lookup_online",
|
||||
"curator_book_reviews",
|
||||
"curator_counts",
|
||||
"curator_propose_write",
|
||||
]
|
||||
|
||||
# Structured-output tools, used only by the stateless extraction/synthesis calls
|
||||
# (--no-session). They carry constrainedSampling + terminate.
|
||||
structured_output = ["emit_extraction", "emit_reviews"]
|
||||
|
||||
# The agent cannot write. curator_propose_write only records a planned Plan and
|
||||
# echoes the resolved identity; the deterministic policy engine in
|
||||
# curator/service.py decides whether it executes. Receipts are harvested from
|
||||
# tool_execution_end, never phrased by the model.
|
||||
receipt_tools = []
|
||||
|
||||
[tools.read_policy]
|
||||
# Must include the skill directories or skill bodies become unloadable.
|
||||
roots = [".pi/skills"]
|
||||
extensions = [".md"]
|
||||
max_chars = 40000
|
||||
|
||||
[bridge]
|
||||
# Loopback only, with a secret generated at service start and passed through env.
|
||||
# pi-guard-base asserts the host is loopback and refuses anything else.
|
||||
host = "127.0.0.1"
|
||||
port = 8767
|
||||
# The backend serves tool definitions as JSON Schema at /tools so that the schema
|
||||
# has exactly one owner; registerTool accepts a plain JSON Schema object.
|
||||
spec_endpoint = "/tools"
|
||||
|
||||
[budget]
|
||||
# Per-invocation timeouts do not compose: the old configuration could spend
|
||||
# 4 x 120 s on a single message with no overall bound. One deadline per user
|
||||
# message, enforced with RPC abort.
|
||||
turn_deadline_seconds = 180
|
||||
extraction_deadline_seconds = 120
|
||||
startup_timeout_seconds = 60
|
||||
|
||||
[env]
|
||||
# Explicit allowlist. Notably absent: every CURATOR_* credential. The provider
|
||||
# key is read by pi itself from ~/.pi/agent/models.json.
|
||||
minimal = true
|
||||
allowlist = ["PATH", "HOME", "LANG", "LC_ALL", "TZ", "SSL_CERT_FILE", "SSL_CERT_DIR"]
|
||||
extra = ["PI_TOOL_BRIDGE_URL", "PI_TOOL_BRIDGE_TOKEN"]
|
||||
|
||||
[secrets]
|
||||
env_file = "/home/claw/.config/curator/curator.env"
|
||||
Reference in New Issue
Block a user