Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 28 additions & 11 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ usage() {
usage: install.sh [-y | --print-pstack-skills]

Copies the pi-stack overlay into $HOME/.pi/agent.
Writes pstack-aligned user agents into $HOME/.pi/agent/agents/.
Installs poteto-agent and retires the six old role profiles in $HOME/.pi/agent/agents/.
Disables builtin agents. Existing children keep their prompts until respawn.
Dated backups go to $HOME/.pi/agent/backups/subagents/.
Rewrites Cursor skill names into $HOME/.pi/agent/skills-pstack. Does not edit pstack.
Copies the Jig launcher, controller, skill, and references into $HOME/.pi/agent/jig/.
Expand Down Expand Up @@ -365,6 +366,7 @@ if [[ ${#conform_src[@]} -gt 0 ]]; then
fi

export PI_AGENT_DIR="$agent"
export OVERLAY="$overlay"
python3 - "${#pstack_skill_names[@]}" "${pstack_skill_names[@]}" "${required_packages[@]}" <<'PY'
import json
import os
Expand Down Expand Up @@ -399,16 +401,18 @@ data["skills"] = skills
def is_cursor_model(value):
return isinstance(value, str) and (value == "cursor" or value.startswith("cursor/"))

subs = data.get("subagents")
if isinstance(subs, dict):
if is_cursor_model(subs.get("defaultModel")):
subs["defaultModel"] = "inherit"
overrides = subs.get("agentOverrides")
if isinstance(overrides, dict):
for spec in overrides.values():
if isinstance(spec, dict) and is_cursor_model(spec.get("model")):
spec["model"] = "inherit"
data["subagents"] = subs
policy = json.loads((Path(os.environ["OVERLAY"]) / "settings.json").read_text())["subagents"]
subs = data.setdefault("subagents", {})
overrides = subs.setdefault("agentOverrides", {})
if is_cursor_model(subs.get("defaultModel")):
subs["defaultModel"] = "inherit"
for name, spec in overrides.items():
if is_cursor_model(spec.get("model")):
spec["model"] = "inherit"
spec["disabled"] = name != "poteto-agent"
subs["disableBuiltins"] = policy["disableBuiltins"]
for name, spec in policy["agentOverrides"].items():
overrides.setdefault(name, {}).update(spec)

def npm_package_name(entry):
if isinstance(entry, str):
Expand Down Expand Up @@ -559,6 +563,7 @@ export PSTACK="$pstack"
export OVERLAY="$overlay"
export PI_AGENT_DIR="$agent"
python3 - <<'PY'
import json
import os
from datetime import datetime, timezone
from pathlib import Path
Expand All @@ -577,6 +582,14 @@ if backup_root.is_dir():

pending_backups = []
pending_writes = []
pending_deletes = []
policy = json.loads((overlay_agents.parent / "settings.json").read_text())["subagents"]
retired = [name for name, spec in policy["agentOverrides"].items() if spec["disabled"]]
for name in retired:
dest = dest_dir / (name + ".md")
if dest.is_file():
pending_backups.append((name + ".md", dest.read_bytes()))
pending_deletes.append(dest)
for src in sorted(overlay_agents.glob("*.md")):
name = src.stem
wanted = src.read_text().replace("__SKILLS_PSTACK__", skills_pstack).replace("__PSTACK__", pstack)
Expand All @@ -587,6 +600,7 @@ for src in sorted(overlay_agents.glob("*.md")):
pending_writes.append((dest, wanted))
else:
pending_writes.append((dest, wanted))
for name in [*retired, *(src.stem for src in overlay_agents.glob("*.md"))]:
pkg = pkg_dir / (name + ".md")
if pkg.is_file():
original = pkg.read_bytes()
Expand All @@ -602,6 +616,9 @@ if pending_backups:
out.parent.mkdir(parents=True, exist_ok=True)
out.write_bytes(data)

for dest in pending_deletes:
dest.unlink()

for dest, text in pending_writes:
if dest.exists() and dest.read_text() == text:
continue
Expand Down
4 changes: 3 additions & 1 deletion overlay/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ This file maps Cursor verbs onto Pi. It is process, not repository architecture.

`Task` is the `subagent` tool from pi-subagents. One child is `{ agent, task }`. Several children are one `{ workflowScript }` with `await runs.all`. Set `cwd` when the child must run in another tree. Do not run `pi -p` from bash. That nested process blocks the parent and has no fleet status. `--tools` that omit `subagent` is how that bash spawn happens. jig.sh is a human launcher and may pin tools. Agents inside Pi may not. `pi -c` continues a session. It is not cwd.

These names are pstack-aligned user overrides that install.sh writes to `~/.pi/agent/agents/`. `scout` is the how explorer. `researcher` is web and why. `worker` is the poteto-agent writer. `reviewer` is interrogate checks. `oracle` is the how explainer and second opinion. `delegate` is the poteto-agent child that stays close to the parent. `poteto-agent` is `delegate` or `worker` whose task says to read `__PSTACK__/skills/poteto-mode/SKILL.md` in full, including the Principles index. The dest files also say that themselves.
When delegation is needed, use only `{ agent: "poteto-agent", task }`. `install.sh` installs this child in `~/.pi/agent/agents/`, disables builtins, and retires the six old role profiles. Give the child a bounded implementation, investigation, or read-only task instead of selecting a different persona. Do not use a parallel worker+reviewer workflow as the default bug-fix loop. Tiny known-mechanism fixes stay parent-inline.

The child reads poteto-mode in full and decides reversible details without supervisor gates. It returns missing authorization or genuine product ambiguity in its normal result before taking the blocked action. New sessions see the installed settings and prompts. Existing children keep their old prompts until respawn.

Leave `async` on. That is the default. `async:false` only when this turn cannot continue without the child. Do not sleep-poll. Use blocking `subagent_wait` only when this turn must consume the result.

Expand Down
14 changes: 0 additions & 14 deletions overlay/agents/delegate.md

This file was deleted.

21 changes: 0 additions & 21 deletions overlay/agents/oracle.md

This file was deleted.

17 changes: 17 additions & 0 deletions overlay/agents/poteto-agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: poteto-agent
description: Poteto child for a bounded implementation, investigation, or review task
systemPromptMode: append
inheritProjectContext: true
inheritSkills: false
defaultContext: fork
tools: read, grep, find, ls, bash, edit, write
---

Read `__SKILLS_PSTACK__/poteto-mode/SKILL.md` in full, including the Principles index. Read each leaf principle you apply.

Execute the assigned task inline. Do not spawn children or use supervisor coordination. Follow an explicit read-only task without edits. For implementation, make the smallest coherent change and run the relevant checks yourself.

Decide reversible details and report the choice. Test order, commit order, and confirmation that a diff is frozen do not require approval. If an irreversible action lacks authorization or genuine product ambiguity blocks the task, stop before that action and return the required decision in your normal result. Never treat silence as approval.

Return the result, changed files, verification evidence, and unresolved risks. Report blockers honestly. Do not claim implementation success without the requested edits and verification.
19 changes: 0 additions & 19 deletions overlay/agents/researcher.md

This file was deleted.

19 changes: 0 additions & 19 deletions overlay/agents/reviewer.md

This file was deleted.

21 changes: 0 additions & 21 deletions overlay/agents/scout.md

This file was deleted.

23 changes: 0 additions & 23 deletions overlay/agents/worker.md

This file was deleted.

14 changes: 13 additions & 1 deletion overlay/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
{
"defaultTools": ["read", "write", "edit", "bash", "grep", "find", "ls"],
"skills": []
"skills": [],
"subagents": {
"disableBuiltins": true,
"agentOverrides": {
"scout": {"disabled": true},
"researcher": {"disabled": true},
"reviewer": {"disabled": true},
"oracle": {"disabled": true},
"worker": {"disabled": true},
"delegate": {"disabled": true},
"poteto-agent": {"disabled": false}
}
}
}
18 changes: 18 additions & 0 deletions scripts/check-agent-discovery.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { resolve } from 'node:path';

const packageDir = resolve(process.argv[2]);
const require = createRequire(resolve(packageDir, 'package.json'));
const { createJiti } = require('jiti');
const jiti = createJiti(import.meta.url);
const { discoverAgents } = await jiti.import(resolve(packageDir, 'src/agents/agents.ts'));
const { agents } = discoverAgents(process.cwd(), 'both');
assert.deepEqual(agents.map(agent => agent.name).sort(), ['poteto-agent']);
const [agent] = agents;
assert.equal(agent.source, 'user');
assert.equal(agent.disabled, false);
assert.deepEqual(agent.tools, ['read', 'grep', 'find', 'ls', 'bash', 'edit', 'write']);
assert.match(agent.systemPrompt, /poteto-mode\/SKILL\.md/);
assert.match(agent.systemPrompt, /Do not spawn children or use supervisor coordination/);
console.log('check-agent-discovery ok: only poteto-agent; no children launched');
Loading