Add artifact vault contents

This commit is contained in:
2026-08-01 14:05:09 -04:00
parent 361bde2621
commit 3230f9395b
78 changed files with 6156 additions and 42 deletions

1
.counter Normal file
View File

@@ -0,0 +1 @@
82

View File

@@ -0,0 +1,46 @@
# AI Artifacts Context
This context defines the vocabulary for the AI artifacts vault and its naming conventions.
It keeps agent-authored notes, attachments, Tags, and cross-project entries named consistently.
## Language
**AI artifacts vault**:
The Obsidian vault that stores agent-generated artifacts across projects.
_Avoid_: artifact repository, notes repo
**Artifact**:
A Markdown note or attachment created by an agent to preserve useful project work or cross-project knowledge.
_Avoid_: document, output, file
**Project artifact**:
An artifact stored under a specific project directory because it belongs to that project rather than the whole vault.
_Avoid_: project note, project document
**Wiki entry**:
A cross-project Markdown note stored under `wiki/` for knowledge that is not owned by a single project.
_Avoid_: wiki artifact, knowledge artifact
**Tag**:
A content-free Markdown note under `tags/` that exists only to cluster related notes in the Obsidian graph.
_Avoid_: tag note, hashtag file
**Artifact identifier**:
The numeric prefix allocated from the vault counter and preserved when an artifact is renamed.
_Avoid_: ID, number, sequence
**Naming convention**:
A vault rule that defines how artifacts or attachments are named in a specific location.
_Avoid_: naming scheme, filename pattern
**Project artifact name**:
The identifier-bearing filename used for Markdown artifacts under `projects/`.
_Avoid_: project filename, project note name
**Artifact type**:
The final descriptive slug in a project artifact name that identifies the kind of artifact.
_Avoid_: suffix, file type
**Slug**:
A lowercase filename component that uses hyphens instead of spaces.
_Avoid_: name part, filename segment

View File

@@ -1,38 +0,0 @@
# AI Artifacts Context
This context defines the shared language for the repository that houses agent-generated artifacts across projects.
## Language
**Artifact**:
An output created by an agent during or after work, kept because it may be useful later.
_Avoid_: Generated file, output
**Project**:
A named body of work that owns project-specific artifacts.
_Avoid_: Repository, codebase, workspace
**Project Key**:
The lowercase directory basename used to identify a project under `projects/`.
_Avoid_: Project ID, slug, repo name
**Spec**:
A project-specific description of intended behavior, design, or acceptance criteria.
_Avoid_: Requirements doc, design note
**Task**:
A project-specific unit of planned or completed work.
_Avoid_: Todo, ticket
**ADR**:
A project-specific record of an architectural decision that is costly to reverse and would be surprising without context.
_Avoid_: Decision note, rationale
**Wiki Entry**:
A cross-project knowledge artifact intended to be found directly by name in the flat `wiki/` directory.
_Avoid_: Knowledge page, note
**Tag File**:
An empty Markdown file in the flat `tags/` directory whose name exists only to create graph clusters.
_Avoid_: Label, category, index

View File

@@ -1,4 +0,0 @@
# Top-level artifact layout
Agent-generated artifacts are organized with a hybrid layout: `projects/<project>/...` holds project-specific artifacts, while `wiki/` and `tags/` hold cross-project Markdown files in strictly flat directories.
This keeps project-bound work local to its project, keeps reusable knowledge directly discoverable, and uses empty tag files only to form Obsidian graph clusters.

View File

@@ -0,0 +1,83 @@
---
status: open
tags:
- wayfinder/map
---
# Pi subagents decision
## Destination
Produce an implementation-ready specification for a new neutral Pi subagent extension.
The specification must preserve Pi configuration ownership of subagent types, support frequent context-clean child spawning, and leave Herdr as an optional later adapter rather than the core design target.
## Notes
The original adopt, adapt, or build decision is resolved: build a new neutral Pi extension.
The expanded destination is an implementation-ready specification, not the implementation itself.
Treat no bundled subagent types as a hard architectural boundary: mechanism belongs in the extension, while named agents, prompts, and policy belong in Pi configuration.
Prioritize Pi-native behavior first: runtime model, context modes, status UI, lifecycle supervision, trust boundaries, and dotfiles deployment seam.
## Frontier
- [[047-pi-subagents-lifecycle-controls-task]]
- [[048-pi-subagents-config-agents-tool-profiles-task]]
- [[049-pi-subagents-batch-concurrency-task]]
- [[050-pi-subagents-fork-context-task]]
- [[051-pi-subagents-status-ui-task]]
## Blocked
- [[052-pi-subagents-final-deployment-verification-task]]
## Decisions so far
Herdr compatibility cannot rely on arbitrary background Pi child processes.
Current evidence says independent Herdr agents-section entries are pane-oriented, while parent-pane metadata can project child status but cannot create true per-child visibility.
The best off-the-shelf Pi subagent candidate found is `mjakl/pi-subagent`, but it appears to need adaptation for Herdr visibility and for the no-opinionated-agent-types boundary.
Firstmate is not a suitable direct adoption target because it is an opinionated agent distro, but its Herdr backend is a strong design reference for robust pane identity and recovery.
Local dotfiles already manage Pi and Herdr declaratively, but they manage no Pi extensions or subagent definitions yet, and Herdr's optional Pi integration is not installed because its target path is Nix-managed.
For development, throwaway Pi extensions can be created where Pi normally expects them, but finished deployment should still go through the flake-managed module.
Herdr's Pi integration reports lifecycle for interactive Pi processes in Herdr panes, but it does not make background or JSON-mode Pi child processes appear as independent Herdr agents.
Herdr has plugins and pane-reporting APIs, but independent agent reporting appears pane-bound, so a host-neutral Pi subagent core likely needs a Herdr adapter or Herdr pane strategy for clean agents-section visibility.
`pi-fork` contributes the key context-engineering pattern: fork the active branch into an isolated child transcript, keep noisy work out of parent context, and return a compact evidence-bearing report.
The subagent core must support both active-branch forked children and completely independent children, because adversarial review, red-green refactor checks, code review, and document sanity checks can be harmed by shared context.
Reusable Firstmate patterns are exact host endpoint identity, durable lifecycle events separate from current truth, unknown-preserving recovery, incarnation tokens, and host adapters that keep presentation separate from semantic subagent identity.
Build a new neutral Pi extension, focus on Pi-native subagent behavior first, show headless subagent status inside Pi, and leave Herdr support as an optional adapter rather than a core dependency.
Use a hybrid child-runtime boundary with subprocess RPC as the first implementation and an in-process SDK runner as a later optimization, while representing independent, forked, and persistent children through session inputs rather than separate runtime semantics.
Version one supports only `independent` and `fork` context modes, with `independent` as the global default.
`independent` receives the task prompt, selected agent definition, and normal trusted project context, but no parent transcript or generated parent summary by default.
`fork` receives the full active-branch transcript snapshot as-is plus a small delegated-role wrapper, and child Pi handles normal compaction if needed.
Parent conversation context is opt-in through `fork`, but `fork` itself needs no special confirmation beyond the risky-capability confirmation rules.
The parent receives the final textual result plus compact metadata by default, not selected evidence snippets or child transcript content.
Named agent definitions should use Markdown files with YAML frontmatter and a Markdown body prompt, with `name` and `description` required.
User-level definitions should live under `~/.pi/agent/agents/`, project-level definitions under `.pi/agents/`, and project definitions should load only after project trust.
Project definitions should override user definitions, while duplicate names inside one precedence tier should be configuration errors.
Extension-wide defaults live in dedicated JSON files: global `~/.pi/agent/subagents.json` and trusted project `.pi/subagents.json`, with project config overriding global config after trust.
`subagents.json` owns extension defaults, optional UI settings, concurrency, timeouts, guardrails, and named tool profiles, but not inline named agents.
Version one agent frontmatter supports optional `context`, `model`, `thinking`, `tools`, `allowedContexts`, and `hidden`.
Tool profiles are named profiles that compile to Pi active tools and optional tool-call gates, with reserved built-ins `none`, `read-only`, `read-only-with-safe-bash`, and `full-tools`.
The spawn surface is non-blocking, accepts a single `prompt` field, optionally references a named `agent`, supports ad hoc runtime subagents when no agent is named, and exposes post-spawn list, status, result, and cancel controls.
Exact tool names are deferred to the implementation specification.
The extension must not claim sandbox isolation.
Children run in the local user's trust boundary unless routed through a real container, VM, micro-VM, remote sandbox, or equivalent OS boundary.
Child spawns should default to a conservative environment, explicit tool/resource inheritance, sanitized environment variables, and user confirmation or headless preauthorization for risky capabilities.
Lifecycle should be owned by a central parent-extension supervisor, with subprocess RPC children driven by events, abort signals, process lifecycle, and bounded timers rather than sleep-loop polling.
Use `agent_settled` as semantic completion, followed by process close for subprocess cleanup.
The status architecture should separate status data from presentation.
The default subagent extension should own the data model, status endpoints, durable child records, and neutral events, while its Pi-native UI should be optional and replaceable by another extension.
The bundled optional UI should use three progressive Pi-native layers: a collapsed live summary by default, an expanded live inspector on demand, and durable transcript milestone entries for historical record.
Durable deployment should place the neutral extension under `modules/agents/pi/extensions/subagents/`, optionally add `modules/agents/pi/agents/` for managed user definitions, and avoid `pi install` or package installation without explicit consent.
The Nix seam keeps the extension Nix-unaware and marks detailed dotfiles module option design out of scope for the extension specification.
The spec should require only stable runtime paths such as `~/.pi/agent/subagents.json` and `~/.pi/agent/agents/*.md`, while this repository's Pi module may later decide whether to link plain files, render JSON from Nix attrs, or expose typed options.
## Result
The implementation-ready specification is complete in [[027-pi-subagents-implementation-spec-task]].
The minimal subagent extension tracer bullet is complete in [[046-pi-subagents-minimal-tracer-bullet-task]].
## Out of scope
Implementing subagent support is outside this map.
The implementation-ready extension specification is now in scope.
Herdr-specific adapter implementation is outside the initial Pi-extension focus and can be revisited after the Pi-native subagent behavior is designed.

View File

@@ -0,0 +1,61 @@
---
status: resolved
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/research
---
# Herdr compatibility research
## Question
How does Herdr discover, display, and control agent processes or sessions, and what does that imply for Pi-spawned subagents that must appear under Herdr's agents section?
## Resolution
## Findings
Herdr has a first-class agent list and snapshot surface.
On this machine, `herdr agent list` returns agents with `agent`, `agent_status`, `cwd`, `foreground_cwd`, `pane_id`, `tab_id`, `terminal_id`, title, workspace, focus, revision, and state-change fields.
`herdr api snapshot` includes the same agent records plus pane, tab, workspace, and layout data.
Citation: local Herdr 0.7.5 CLI output from `herdr agent list` and `herdr api snapshot`.
Herdr's built-in status vocabulary is `idle`, `working`, `blocked`, `done`, and `unknown`.
The API schema defines that enum under `AgentStatus`, and pane records expose `agent_status`.
Citation: `herdr api schema --json`, schema definitions `event.$defs.AgentStatus` and `event.$defs.PaneInfo`.
Herdr exposes both discovery/control commands for agents and lower-level pane metadata APIs.
The CLI help lists `agent list/get/read/send-keys/prompt/rename/focus/wait/attach/start/explain`.
The API schema exposes `pane.report_agent`, `pane.report_agent_session`, and `pane.report_metadata` requests.
`pane.report_metadata` can set `agent`, `display_agent`, `title`, `state_labels`, bounded `tokens`, and TTL, while `pane.report_agent_session` can bind an `agent_session_id` or `agent_session_path` to a pane.
Citation: `herdr agent --help`, `herdr agent start --help`, and `herdr api schema --json` definitions for `PaneReportMetadataParams`, `PaneReportAgentSessionParams`, and request methods.
Herdr has built-in agent integrations, including Pi.
`herdr integration status` says the Pi integration would install to `~/.pi/agent/extensions/herdr-agent-state.ts`, and `herdr integration install --help` lists `pi` as an install target.
This implies that a Pi extension is Herdr's expected path for Pi status reporting.
Citation: `herdr integration status` and `herdr integration install --help`.
Herdr can start supported interactive agents in existing panes, and Pi is one of the supported kinds.
`herdr agent start <NAME> --kind pi --pane <ID>` waits until Herdr detects the expected agent in the same terminal and it is ready for input.
Citation: `herdr agent start --help`.
Firstmate's Herdr backend treats Herdr as a session-provider backend and records a target shaped like `<herdr-session>:<pane-id>`.
Its adapter uses Herdr workspaces/tabs/panes for visible direct reports and explicitly treats label-only matching as insufficient authority for recovery.
Citation: `/tmp/firstmate-research/firstmate/bin/backends/herdr.sh` header and `/tmp/firstmate-research/firstmate/bin/fm-spawn.sh` header from `github.com/kunchenguid/firstmate`.
## Implications
The minimum compatibility bar should be stronger than mere process launch.
A viable Pi subagent solution should create or use Herdr panes/tabs and report enough pane metadata or Pi session metadata for Herdr's agents section to show each child as a Pi agent with useful lifecycle state.
A headless child `pi --mode json` or `pi --mode rpc` process spawned outside Herdr is unlikely to satisfy the visibility requirement by itself, because Herdr's agent list is pane-centered.
The child needs either to run in a Herdr-managed pane or to be deliberately projected/reported into Herdr's pane metadata model.
The likely integration path is one of two shapes: spawn child Pi sessions through Herdr panes and rely on Herdr's Pi integration, or extend the subagent mechanism to call Herdr's pane APIs when starting and updating child sessions.
The latter needs a concrete pane target, so it is still much easier when children are visible Herdr panes.
## Limitations
I did not install Herdr's Pi integration to inspect the generated `herdr-agent-state.ts`, because that would mutate the operator's managed Pi extension directory.
The exact status protocol used by that generated extension remains to be inspected in a later task if needed.

View File

@@ -0,0 +1,77 @@
---
status: resolved
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/research
---
# Pi extension ecosystem research
## Question
What Pi extension APIs, official examples, pi-fork work, and discoverable third-party Pi subagent or popular extensions exist, and do any provide neutral subagent spawning primitives suitable for Herdr-compatible use?
## Resolution
## Findings
Pi extensions can register tools, commands, shortcuts, flags, event handlers, UI components, message renderers, providers, and resource paths.
They are TypeScript modules auto-discovered from `~/.pi/agent/extensions` and project-local `.pi/extensions`, with package distribution through npm or git.
Citation: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Pi extension commands have session-control APIs that can create, fork, switch, and message Pi sessions, but the official subagent example instead spawns separate Pi processes.
The docs warn that background processes should not be started from the extension factory, and should instead be scoped to session events, commands, tools, or other needful hooks.
Citation: Pi `docs/extensions.md`, especially `ExtensionCommandContext`, `ctx.newSession`, `ctx.fork`, `ctx.switchSession`, and long-lived resource guidance.
The official Pi examples include `examples/extensions/subagent/`.
It registers a `subagent` tool, discovers user and project Markdown agent definitions, supports single, parallel, and chained modes, and launches a separate `pi --mode json -p --no-session` process for each subagent invocation.
It also ships sample agents named `scout`, `planner`, `reviewer`, and `worker` plus workflow prompts.
Citation: Pi `examples/extensions/subagent/README.md`, `index.ts`, and `agents.ts`.
The official subagent example is useful mechanism, but it violates the desired policy boundary if adopted as-is because it ships opinionated sample agent definitions and workflow prompts.
The core code separates discovery from execution well enough to be mined or adapted, but an adopted extension should not bundle named roles unless those files are excluded from installation.
Citation: Pi `examples/extensions/subagent/README.md` structure and sample-agent table.
A targeted GitHub search found several third-party Pi extensions, including `mjakl/pi-subagent`, `nicobailon/pi-messenger`, `nicobailon/pi-intercom`, `owainlewis/pi-extensions`, and others.
`mjakl/pi-subagent` is the closest off-the-shelf subagent extension: it supports Markdown-defined agents, fresh or persistent child sessions, parallel calls, parent-context seeding, depth/cycle guards, streaming updates, rich rendering, and Pi 0.80.5 or newer.
Citation: GitHub search API result for `"pi-coding-agent" extension` and `/tmp/pi-ext-research/pi-subagent/README.md` cloned from `github.com/mjakl/pi-subagent`.
`mjakl/pi-subagent` is not purely neutral as packaged.
Its README says that if no agents exist, it creates a starter `explore` agent automatically, and it documents example `explore` and `review` definitions.
It is closer to the desired boundary than extensions that ship full crews, but automatic starter creation is still opinionated configuration unless it can be disabled or patched.
Citation: `/tmp/pi-ext-research/pi-subagent/README.md`.
`mjakl/pi-subagent` spawns separate Pi child processes in headless RPC mode, sets `PI_OFFLINE=1`, and inherits relevant parent CLI configuration.
That design is good for frequent context-isolation and latency, but the README does not claim Herdr integration.
Citation: `/tmp/pi-ext-research/pi-subagent/README.md`, technical reference section.
`nicobailon/pi-messenger` is a broader multi-agent coordination and crew orchestration extension.
It ships crew agents, a crew skill, planner/worker/reviewer flows, team roles, approval gates, shared presence, messaging, file reservations, and project-local crew state.
It is therefore too opinionated for the requested subagent primitive, though pieces such as presence and orchestration may be informative.
Citation: `/tmp/pi-ext-research/pi-messenger/README.md`.
`nicobailon/pi-intercom` is a same-machine session-to-session messaging extension, not a subagent spawner.
It can integrate with a subagent extension by giving delegated child agents a `contact_supervisor` tool when bridge metadata is supplied.
It could complement a subagent solution, but it does not satisfy spawning or Herdr visibility by itself.
Citation: `/tmp/pi-ext-research/pi-intercom/README.md`.
`owainlewis/pi-extensions` contains experimental workflow automation and status-message extensions rather than a neutral subagent primitive.
Its context-isolated workflow focuses on compaction, testing, review, and iteration inside a workflow command.
Citation: `/tmp/pi-ext-research/pi-extensions/README.md`.
## Implications
No researched off-the-shelf Pi subagent extension clearly satisfies all stated criteria today.
The best candidate for adaptation is `mjakl/pi-subagent`, because it already solves repeated isolated child Pi invocations, persistent child sessions, parallelism, and context control.
Its likely gaps are Herdr visibility and automatic starter/opinionated agent behavior.
The official Pi subagent example is a strong reference implementation but not a direct adoption target.
It is useful for understanding Pi's supported APIs and minimal spawning mechanics.
A new or adapted extension should keep subagent type definitions out of the extension package, avoid automatic starter-agent creation unless explicitly configured, and add a Herdr-aware spawning mode or bridge.
## Limitations
GitHub discovery was targeted rather than exhaustive.
The `pi-fork` term did not resolve to a clearly authoritative source during this pass, so it remains an evidence gap unless a specific repository or package name is provided.

View File

@@ -0,0 +1,64 @@
---
status: resolved
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/research
---
# Firstmate and related tools research
## Question
What do Kun Chen's Firstmate and related tools provide for spawning or coordinating coding agents, and can their approach be adopted or adapted for neutral Pi subagents that Herdr can observe?
## Resolution
## Findings
Firstmate describes itself as an agent distro rather than a model, harness, skill, MCP server, or CLI.
It is a portable directory of instructions, skills, tooling, policies, and state conventions that turns a supported terminal coding agent into a first mate that supervises a crew.
Citation: `/tmp/firstmate-research/firstmate/README.md` cloned from `github.com/kunchenguid/firstmate`.
Firstmate supports Pi as a primary harness alongside Claude Code and Grok, with Codex and OpenCode also verified.
Its quick-start says to launch `pi` inside the cloned firstmate repo and approve Pi project trust so tracked `.pi/extensions/*.ts` files auto-load.
Citation: `/tmp/firstmate-research/firstmate/README.md`.
Firstmate's model is intentionally much broader than a neutral subagent primitive.
It includes captain/crew roles, project modes, worktree management, PR delivery, supervision, secondmates, optional X-mode, state directories, and strict workflow policies.
Citation: `/tmp/firstmate-research/firstmate/README.md` and `AGENTS.md`.
Firstmate has a Herdr backend that can make every crewmate visible in Herdr.
The README says every crewmate works in its own tmux window, experimental Herdr or Zellij tab, cmux workspace, or Orca terminal.
The `fm-spawn.sh` header says a Herdr crewmate or scout is placed in the workspace of the launching firstmate or secondmate process, and `bin/backends/herdr.sh` says the authoritative target string is `<herdr-session>:<pane-id>`.
Citation: `/tmp/firstmate-research/firstmate/README.md`, `/tmp/firstmate-research/firstmate/bin/fm-spawn.sh`, and `/tmp/firstmate-research/firstmate/bin/backends/herdr.sh`.
Firstmate treats Herdr as a session provider only.
The Herdr backend header states that the worktree provider stays Treehouse, just like tmux, and Herdr owns the visible session endpoint shape.
Citation: `/tmp/firstmate-research/firstmate/bin/backends/herdr.sh`.
Firstmate's Herdr implementation is careful about identity and recovery.
It does not trust labels alone, records exact pane targets, uses home/session/workspace/tab/pane bindings, and treats presentation workspaces as non-authoritative visual projections.
Citation: `/tmp/firstmate-research/firstmate/bin/backends/herdr.sh` header and `/tmp/firstmate-research/firstmate/bin/fm-spawn.sh` header.
A secondary setup repository, `harish-nair-ai/agentic-workflow-setup`, confirms that Firstmate is one of Kun Chen's open-source tools and positions it among `lavish-axi`, `no-mistakes`, `gnhf`, and `treehouse` for agent-heavy workflows.
That repository is a checklist and source-grounded notes package, not the tool implementation.
Citation: `/tmp/firstmate-research/agentic-workflow-setup/README.md`.
A `shipmates` repository exists as a Hermes plugin for a Herdr/OpenCode/Firstmate-style experience, but its README is a short setup note and the cloned content does not establish a Pi subagent primitive.
Citation: `/tmp/firstmate-research/shipmates/README.md` and `plugin-guide.md`.
## Implications
Firstmate should not be adopted as the Pi subagent extension.
It is intentionally an opinionated operational distro with roles, policies, project lifecycle, and worktree/PR machinery, which conflicts with the desired boundary that the extension provides mechanism and Pi configuration provides subagent types.
Firstmate is highly relevant as a design reference for Herdr compatibility.
Its Herdr backend demonstrates that Herdr-visible agent spawning is feasible and that robust integration should treat pane identity as authoritative rather than relying on labels or loose process discovery.
Treehouse and related tools may be useful if the future destination includes isolated worktrees or PR-oriented crew workflows, but those are outside this decision map's neutral subagent capability.
## Limitations
This research inspected Firstmate source headers and README-level architecture rather than running Firstmate.
Running it would mutate local state and is unnecessary for the current adopt/adapt/build decision.

View File

@@ -0,0 +1,49 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T19:59:55-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/task/afk
---
# Local Pi and Herdr config inventory
## Question
Inventory the local dotfiles entry points for Pi, Herdr, and agent tooling so the later adoption decision can distinguish upstream capability from repo-specific configuration work.
## Resolution
Pi and Herdr are enabled on `neogaia` through `hosts/neogaia/default.nix`.
The relevant toggles are `modules.agents.pi.enable = true` and `modules.agents.herdr.enable = true`.
Pi is declared in `modules/agents/pi/pi.nix`.
That module enables `programs.pi-coding-agent`, sets the default provider to `openai-codex`, the default model to `gpt-5.5`, and the default thinking level to `medium`.
It force-manages `~/.pi/agent/settings.json`, symlinks `~/.pi/agent/extensions` from `modules/agents/pi/extensions`, and symlinks `~/.pi/agent/prompts` from `modules/agents/pi/prompts`.
Both declared directories currently contain only `.gitkeep`, so no subagent or Herdr Pi extension is managed there yet.
Shared Pi skills are home-manager-generated under `~/.pi/agent/skills` from the flake's skills module.
The dotfiles checkout contributes only the project-local `.agents/skills/gitea-axi` symlink.
There is no local `.pi/agents` directory, no managed `~/.pi/agent/agents` directory, and no subagent-type definitions currently present.
The live `~/.pi/agent/settings.json` matches the flake-managed defaults.
`~/.pi/agent/trust.json` trusts `/home/alexion/wrk` and `/home/alexion/wrk/dotfiles`.
`~/.pi/agent/auth.json`, `models-store.json`, and session files are live state rather than flake-managed configuration.
Herdr is declared in `modules/agents/herdr.nix`.
That module installs `pkgs.herdr` and writes `~/.config/herdr/config.toml` with keybindings and `prompt_new_tab_name = false`.
The live Herdr client and server are version `0.7.5` with protocol `17`, and the server is running.
Herdr's Pi integration is not installed.
`herdr integration status` reports `pi: not installed (/home/alexion/.pi/agent/extensions/herdr-agent-state.ts)`.
That path falls under the Pi extensions directory currently symlinked from the Nix store, so an imperatively installed integration would be local development state rather than durable deployment.
For throwaway development, it is acceptable to create extensions where Pi normally expects them, with the understanding that a later Home Manager activation may overwrite or hide those files.
A finished solution should package or copy the integration through `modules/agents/pi/extensions` or add an equivalent managed extension path rather than treating `herdr integration install pi` against the live home as deployment.
Herdr's local detection cache includes `remote/pi.toml`, whose Pi rule marks a pane `working` when recent terminal output contains `Working...`.
That cache is local state under `~/.local/state/herdr/agent-detection`, not dotfiles configuration.
Current Herdr session state contains workspaces for `ai-artifacts`, `dotfiles`, and `skills`, each with a Pi pane visible to `herdr agent list`.
This proves ordinary interactive Pi sessions already appear in Herdr's agents section even without the optional Pi integration installed, but it does not prove headless child processes spawned outside Herdr will appear.

View File

@@ -0,0 +1,33 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T20:54:32-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by:
- "[[003-pi-subagents-herdr-compatibility-research]]"
- "[[004-pi-subagents-pi-extension-ecosystem-research]]"
- "[[005-pi-subagents-firstmate-and-related-tools-research]]"
- "[[006-pi-subagents-local-config-inventory-task]]"
- "[[011-pi-subagents-herdr-pi-integration-research]]"
- "[[012-pi-subagents-herdr-extension-boundary-research]]"
- "[[013-pi-subagents-pi-fork-research]]"
- "[[014-pi-subagents-firstmate-patterns-research]]"
- "[[019-pi-subagents-herdr-status-projection-prototype]]"
tags:
- ticket/grill
---
# Adopt adapt or build decision
## Question
Given the researched Herdr compatibility model, Pi extension ecosystem, Firstmate-related options, and local configuration constraints, should this effort adopt an existing solution, adapt companion tooling, or build a neutral Pi extension?
## Resolution
Build a new neutral Pi extension rather than adopting Firstmate, adapting `mjakl/pi-subagent`, or extending `pi-fork` directly.
The extension should focus on Pi-native subagent behavior first and should not focus on Herdr integration in the initial decision route.
Subagent types, prompts, and policy remain Pi configuration, not extension-bundled opinion.
The extension should support both active-branch forked children for context-preserving investigation and fully independent children for adversarial review, red-green refactor checks, code review, and document sanity checks.
Subagent status should be shown inside Pi for headless/background children.
Herdr support, if added later, should be optional and adapter-shaped rather than a core dependency.

View File

@@ -0,0 +1,46 @@
---
status: resolved
parent: "[[003-pi-subagents-herdr-compatibility-research]]"
blocked-by: []
tags:
- ticket/research
---
# Herdr Pi integration research
## Question
What does Herdr's Pi integration extension actually report or enable, and how does that change the requirements for Pi-spawned subagents to appear with useful lifecycle state in Herdr?
## Resolution
## Findings
Herdr's Pi integration is a Pi lifecycle reporter, not a launcher or subagent manager.
A safe fake install generated `/tmp/herdr-pi.12G0B5/.pi/agent/extensions/herdr-agent-state.ts` without touching the real home.
The generated extension enables itself only when `HERDR_ENV === "1"`, `HERDR_SOCKET_PATH`, and `HERDR_PANE_ID` are present.
Citation: generated `herdr-agent-state.ts` inspected under `/tmp/herdr-pi.12G0B5`.
The extension reports to Herdr through pane-bound API calls.
It uses `pane.report_agent_session` for Pi session identity, `pane.report_agent` for lifecycle state, and `pane.release_agent` on real quit.
It reports `working` on Pi `agent_start`, `idle` on `agent_settled` when Pi is idle, and `blocked` through a custom `herdr:blocked` event.
Citation: generated `herdr-agent-state.ts` and `herdr api schema --json` definitions for pane reporting methods.
The integration runs only for Pi contexts with UI.
On `session_start`, the generated extension returns early unless `ctx.hasUI === true`.
Pi docs state `ctx.hasUI` is false in print and JSON modes.
Citation: generated `herdr-agent-state.ts` and Pi `docs/extensions.md` mode behavior.
Pi's official subagent example launches children with `--mode json -p --no-session` and no Herdr pane assignment.
Those children would not pass the integration's UI guard, and any inherited Herdr pane env vars would identify the parent pane rather than an independent child pane.
Citation: Pi `examples/extensions/subagent/index.ts`.
## Implications
The Herdr Pi integration makes interactive Pi processes inside Herdr panes authoritative lifecycle reporters.
It does not make background or JSON-mode Pi subprocesses appear as independent Herdr agents.
Useful Herdr visibility for Pi subagents therefore requires either running each visible child in a Herdr-addressable pane with the Pi integration loaded, or building a separate mechanism that maps child lifecycle into a Herdr pane or parent-pane metadata representation.
If blocked or waiting state matters, the subagent workflow must emit or translate a blocked-state signal.
The default Pi lifecycle only provides working and idle through the generated integration.

View File

@@ -0,0 +1,47 @@
---
status: resolved
parent: "[[003-pi-subagents-herdr-compatibility-research]]"
blocked-by: []
tags:
- ticket/research
---
# Herdr extension boundary research
## Question
What extension or plugin surfaces does Herdr provide, and would a Herdr-side adapter let Pi subagents stay host-agnostic while still integrating cleanly with Herdr's agents section?
## Resolution
## Findings
Herdr exposes a runtime socket and CLI API for session state and control.
`herdr api snapshot` exposes live agents, panes, tabs, and workspaces.
`herdr agent list/get/read/prompt/send-keys/wait/start` operates on detected agent panes.
`herdr pane report-agent`, `report-agent-session`, `release-agent`, and `report-metadata` allow external reporters to set pane-bound agent state, identity, and display metadata.
Citation: `herdr --help`, `herdr agent --help`, `herdr pane report-agent --help`, and `herdr api schema --json`.
Herdr also has a plugin system available through `herdr plugin`.
The CLI exposes install, uninstall, link, unlink, enable, disable, list, config-dir, action, log, and pane commands.
Plugin manifests use `herdr-plugin.toml` and schema fields include build, startup, actions, events, panes, and link handlers.
Plugin event hooks can subscribe to runtime events such as `pane.agent_detected` and `pane.agent_status_changed`.
Citation: `herdr plugin --help`, `herdr plugin action --help`, `herdr plugin pane --help`, and `herdr api schema --json` plugin definitions.
Herdr plugins and API clients can observe the Herdr agent model, but reporting independent agents is pane-bound.
The reporting APIs require `pane_id`, so Herdr's agents section appears derived from panes that host or report agents rather than from arbitrary logical child-agent records.
Citation: `herdr api schema --json` request definitions for `pane.report_agent`, `pane.report_agent_session`, and `pane.release_agent`.
Herdr has built-in agent integrations for host tools including Pi.
Those integrations install host-side hooks or extensions, such as Pi's `~/.pi/agent/extensions/herdr-agent-state.ts`.
Citation: `herdr integration status`.
## Implications
A Herdr-side adapter can help keep Pi subagents host-agnostic only if the Pi-side subagent mechanism emits host-neutral lifecycle events or exposes child state for the adapter to consume.
Herdr cannot cleanly infer invisible Pi child subprocesses as separate agents on its own.
The cleanest boundary is likely a host-neutral Pi subagent core plus optional host adapters.
A Herdr adapter can translate subagent lifecycle into Herdr pane APIs when a Herdr pane exists, while other future hosts can provide different adapters.
A pure Herdr plugin may be useful for observing, presentation, and translating events, but independent entries in Herdr's agents section still need a pane target or a Herdr-supported virtual-agent concept that was not found in the inspected schema.

View File

@@ -0,0 +1,52 @@
---
status: resolved
parent: "[[004-pi-subagents-pi-extension-ecosystem-research]]"
blocked-by: []
tags:
- ticket/research
---
# Pi fork research
## Question
What is pi-fork, what context-engineering model does it offer, and can its approach help Pi subagents preserve useful context isolation without coupling the subagent mechanism to Herdr?
## Resolution
## Findings
The likely authoritative source is `elpapi42/pi-fork` at `https://github.com/elpapi42/pi-fork`.
The repository package name is `pi-fork`, version `0.1.0`, and the package description is `Cache-friendly fork tool for Pi coding agent`.
Citation: GitHub API for `elpapi42/pi-fork` and `/tmp/pi-fork-research/package.json`.
`pi-fork` is a Pi extension that registers a `fork` tool.
Its README describes it as a context-management extension first and a parallelism extension second.
Citation: `/tmp/pi-fork-research/README.md`.
The core model is active-branch snapshotting.
The extension captures `ctx.sessionManager.getHeader()` and `ctx.sessionManager.getBranch()`, serializes them to temporary JSONL, and starts a child `pi --mode json -p --session <tmp/fork.jsonl>` with the delegated task appended as the final user message.
Citation: `/tmp/pi-fork-research/src/index.ts` and `/tmp/pi-fork-research/src/runner.ts`.
This differs from the official Pi subagent example.
The official example starts isolated child processes with `--no-session` plus optional agent system prompts, while `pi-fork` gives the child the current active conversation branch and keeps the child's tool-heavy transcript out of the parent history.
Citation: Pi `examples/extensions/subagent/README.md`, Pi `examples/extensions/subagent/index.ts`, and `/tmp/pi-fork-research/README.md`.
`pi-fork` uses a structured return contract: `Result`, `Output`, `Evidence`, and `Learnings`.
Its prompt emphasizes decision-useful evidence, ruled-out paths, assumptions, validation meaning, and reusable learnings.
Citation: `/tmp/pi-fork-research/src/runner.ts`.
The repository includes an in-process runtime proposal, but it warns that in-process execution shares memory, extension module state, model registry, event loop, and cancellation surfaces.
It recommends preserving subprocess fallback for strict isolation and per-child environment behavior.
Citation: `/tmp/pi-fork-research/IN_PROCESS_RUNTIME_PROPOSAL.md`.
## Implications
`pi-fork` is highly relevant to the desired context-engineering behavior.
It suggests the subagent primitive should not be defined only as a named persona with a blank context.
A default mode that forks the active branch, runs noisy work elsewhere, and returns a dense evidence-bearing report may better match frequent spawning to keep the parent context clean.
This context model does not require Herdr.
Herdr can remain an optional presentation and lifecycle adapter layered around a host-neutral Pi fork or subagent core.
A future design should consider combining `pi-fork`'s active-branch snapshot model with optional agent overlays for model, tools, instructions, and persistence.

View File

@@ -0,0 +1,62 @@
---
status: resolved
parent: "[[005-pi-subagents-firstmate-and-related-tools-research]]"
blocked-by: []
tags:
- ticket/research
---
# Firstmate reusable patterns research
## Question
Which specific Firstmate patterns could be useful for neutral Pi subagents, especially around Herdr pane identity, lifecycle tracking, supervision, recovery, worktree isolation, and keeping orchestration policy separate from mechanism?
## Resolution
## Findings
Firstmate treats exact Herdr pane identity as authoritative and treats labels and focus as non-authoritative.
Its Herdr placement logic uses injected `HERDR_PANE_ID`, socket/session verification, and live Herdr reads of pane to tab to workspace.
If parent identity is stale, cross-session, missing socket identity, or inconsistent, spawn refuses before creating a worker.
Citation: `/tmp/firstmate-research/firstmate/docs/herdr-backend.md` and `bin/backends/herdr.sh`.
Firstmate distinguishes selection signals from authority signals.
`HERDR_ENV=1` can select the Herdr backend, but pane and socket identity are required to prove launcher ancestry.
Citation: `/tmp/firstmate-research/firstmate/bin/fm-backend.sh` and `bin/backends/herdr.sh`.
Firstmate persists endpoint IDs rather than labels.
Task metadata records Herdr session, workspace, tab, and pane identifiers, while labels support discovery or recovery but not destructive authority.
Citation: `/tmp/firstmate-research/firstmate/docs/herdr-backend.md` and `AGENTS.md`.
Firstmate treats lifecycle logs as events, not truth.
Status files are append-only wake history, while current state is recomputed from structured semantic sources.
Missing or stale busy signals become `unknown`, not idle.
Citation: `/tmp/firstmate-research/firstmate/AGENTS.md` and `docs/architecture.md`.
Firstmate uses durable queues and incarnation-bound records for supervision.
Actionable watcher events are appended before detector state advances, and lifecycle events are bound to tokens minted when wiring is armed so old events cannot update new incarnations.
Citation: `/tmp/firstmate-research/firstmate/docs/architecture.md`.
Firstmate uses recovery-grade liveness states.
Herdr panes are mapped to states such as alive, dead, missing, and unreadable.
Restart sweeps relaunch only confirmed dead or missing targets and preserve ambiguous or unreadable cases.
Citation: `/tmp/firstmate-research/firstmate/docs/herdr-backend.md` and `AGENTS.md`.
Firstmate asserts isolation before launch.
Ship and scout spawns refuse unless the task path is a real git worktree root distinct from the primary checkout.
Secondmates use persistent homes as durable identity for recovery.
Citation: `/tmp/firstmate-research/firstmate/bin/fm-spawn.sh`, `docs/architecture.md`, and secondmate lifecycle tests.
Firstmate separates policy from mechanism through backend adapters and single-owner scripts.
`bin/fm-backend.sh` dispatches backend-neutral operations, `bin/backends/herdr.sh` owns Herdr mechanics, and harness-specific supervision prose is selected by `bin/fm-supervision-instructions.sh` from per-harness protocol docs.
Citation: `/tmp/firstmate-research/firstmate/bin/fm-backend.sh`, `bin/backends/herdr.sh`, and `bin/fm-supervision-instructions.sh`.
## Implications
Useful patterns for neutral Pi subagents are: exact host endpoint identity, durable lifecycle events separate from current truth, unknown-preserving recovery, incarnation tokens, host adapters, and policy-free mechanism boundaries.
Patterns that should remain optional are worktree isolation, persistent homes, PR workflow, and supervision daemon behavior.
Those belong to higher-level orchestration policy, not the neutral subagent primitive.
A Herdr adapter for Pi subagents should persist pane/session identifiers, refuse ambiguous recovery, avoid label authority, and treat host presentation as an adapter rather than as the subagent's semantic identity.

View File

@@ -0,0 +1,48 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T20:37:00-04:00"
parent: "[[012-pi-subagents-herdr-extension-boundary-research]]"
blocked-by: []
tags:
- ticket/prototype/afk
---
# Herdr status projection spike
## Question
Safely test whether a Herdr plugin or API-side adapter can make a non-interactive spawned Pi child appear, or at least project useful status, in Herdr's agents section without requiring the child itself to run as an interactive Herdr-pane Pi session.
## Resolution
A non-interactive child cannot be made into its own independent Herdr agents-section entry through the pane reporting APIs unless there is a Herdr pane to attach it to.
Herdr's agent reporting model is pane-bound: `herdr pane report-agent` requires a real `pane_id`, and reporting to a nonexistent pane fails with `pane_not_found`.
Reporting a second agent label to the current pane replaces that pane's single agent row rather than creating a second child row.
After releasing the prototype source, the pane had to be re-reported as the current Pi session, which confirms the API is assigning authority for one pane record, not adding logical children.
Useful status projection is possible on the parent pane.
`herdr pane report-metadata` with a distinct source can set `display_agent`, `state_labels`, and bounded `tokens` on the existing Pi row.
In the prototype, setting `display_agent = "pi child: scout"`, a `working` state label, and a child token appeared in both `herdr agent list` and `herdr api snapshot` for the current pane.
A 5-second TTL removed that projected metadata automatically, returning the row to the ordinary Pi display.
A Herdr plugin could therefore show spawned-child status only by either receiving child lifecycle events and projecting summary metadata onto an existing pane, or by creating/using real Herdr panes for children and reporting those panes as agents.
A Pi-side extension or host-neutral subagent core with a Herdr adapter is the more natural owner of the lifecycle events, because Herdr cannot infer invisible Pi subprocess state on its own.
Verdict: independent agents-section entries require Herdr panes.
Parent-pane status projection without child panes is feasible and safe enough for optional summary status, but it is not a substitute for true per-child Herdr visibility.
## Evidence
Current environment contained `HERDR_ENV=1`, `HERDR_PANE_ID=w6:p1`, and `HERDR_SOCKET_PATH=/home/alexion/.config/herdr/herdr.sock`, so the prototype could safely target the current pane.
Before projection, `herdr agent list` showed one row for the current pane with `agent = "pi"` and `agent_status = "working"`.
Running `herdr pane report-metadata "$HERDR_PANE_ID" --source pi-subagent-prototype --display-agent 'pi child: scout' --state-label working='child working' --token child='scout-1' --ttl-ms 5000` added `display_agent`, `state_labels`, and `tokens` to the same row.
After six seconds, `herdr api snapshot` showed those fields had returned to `null` while the pane remained the ordinary Pi agent row.
Running `herdr pane report-agent "$HERDR_PANE_ID" --source pi-subagent-prototype --agent pi-subagent-child --state blocked --message 'prototype child blocked'` changed the current pane's single agent row to `agent = "pi-subagent-child"` and `agent_status = "blocked"`.
It did not create a second agent row.
Running `herdr pane release-agent "$HERDR_PANE_ID" --source pi-subagent-prototype --agent pi-subagent-child` removed that source's authority and left the pane as `agent = null`, `agent_status = "unknown"` until the current Pi session was re-reported.
The current pane was restored with `herdr pane report-agent "$HERDR_PANE_ID" --source herdr:pi --agent pi --state working --agent-session-id "$PI_SESSION_ID"`.
Running `herdr pane report-agent w999:p999 --source pi-subagent-prototype --agent pi-subagent-child --state working` failed with `pane_not_found`, confirming there is no report-only path for a logical agent without a real pane id.

View File

@@ -0,0 +1,91 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:01:06-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/research
---
# Pi runtime model research
## Question
Which Pi runtime model should the new neutral subagent extension use for child agents: subprocess JSON/RPC, Pi session APIs, an in-process runner, or a hybrid, given isolation, startup latency, cancellation, extension state, session persistence, and context cleanliness requirements?
## Resolution
Use a hybrid runtime boundary, with subprocess RPC as the initial implementation path and an in-process SDK runner as an explicit later optimization.
Do not use extension command session APIs such as `ctx.newSession`, `ctx.fork`, or `ctx.switchSession` as the child runtime, because those replace the current interactive session rather than running independent child agents in parallel.
The implementation spec should define a `ChildRunner` boundary with at least two planned implementations: `subprocess-rpc` and `in-process-sdk`.
Version one should implement `subprocess-rpc` first because it gives the strongest isolation, per-child environment control, compatibility with Pi's real CLI behavior, persistent child session support, process-tree cancellation, timeout enforcement, and clean separation of extension module state.
The in-process SDK runner should remain a design-compatible optimization for lower latency once the subprocess contract is stable.
Prefer RPC mode over print JSON mode for the subprocess runner.
RPC mode is Pi's headless JSON protocol over stdin/stdout, accepts exact prompt bytes through a JSON `prompt` command, streams events on stdout, supports `abort`, exposes state commands, and is intended for embedding.
The `mjakl/pi-subagent` runner already uses `pi --mode rpc`, writes the prompt to stdin as JSON, cancels extension UI requests, streams events, and handles settlement, persistent sessions, timeouts, aborts, process groups, and stderr truncation.
Pi's official subagent example and `pi-fork` prove print/JSON subprocesses work, but RPC is the better implementation target for a durable extension because it avoids argv/stdin prompt reinterpretation and gives a richer control protocol.
Represent context modes through session inputs, not through separate runtime implementations.
A fully independent child should use `--no-session` or an in-memory SDK session.
An active-branch forked child should serialize the parent session header plus active branch entries to a temporary JSONL session and launch the child with that session.
A persistent child should use a stable child session id and a child session directory.
This preserves context cleanliness because child transcript noise remains in the child session or temp file, while the parent receives only the extension's chosen result summary and details.
Keep subprocess mode as a permanent fallback even after an in-process runner exists.
In-process `AgentSession` is officially supported by the Pi SDK and avoids process startup and JSON stdout parsing, but it shares process memory, event loop, extension module state, model runtime, and cancellation surface with the parent extension.
It also cannot safely provide per-child `process.env` overlays or `PI_OFFLINE` behavior during parallel child runs unless Pi exposes per-session equivalents.
Therefore an eventual `auto` runtime may prefer in-process only when the requested child has no per-child environment isolation needs and the user accepts shared-process extension behavior.
Cancellation and lifecycle should be runner-specific behind the same contract.
The subprocess runner should use a detached process group on Unix, SIGTERM followed by SIGKILL, timeout timers, and semantic settlement detection.
The in-process runner should use `session.abort()`, unsubscribe from events, dispose the child session, and clean up temporary session files in `finally`.
Both runners should normalize results to one result shape containing prompt/task, context mode, session metadata, messages or summarized final output, usage, model, stop reason, error details, lifecycle events, and whether the result came from subprocess or in-process execution.
## Findings
Pi's SDK supports direct in-process agent sessions through `createAgentSession`, `SessionManager`, and `ModelRuntime`.
`AgentSession` exposes `prompt`, `steer`, `followUp`, `subscribe`, `abort`, `dispose`, message state, model and thinking controls, lifecycle events, tool execution events, and compaction.
`createAgentSessionRuntime` exists for session replacement flows like new session, switch session, fork, clone, and import.
Citation: Pi `docs/sdk.md` sections `createAgentSession`, `AgentSession`, `createAgentSessionRuntime`, `Events`, and `Session Management`.
Pi's RPC mode is a first-class headless embedding protocol.
It runs as `pi --mode rpc`, accepts JSONL commands over stdin, streams JSON events over stdout, supports exact `prompt` messages, steering, follow-up messages, `abort`, `get_state`, and session replacement commands.
The RPC docs explicitly say Node or TypeScript applications can use `AgentSession` directly instead of spawning a subprocess, but also document RPC as the subprocess-based embedding surface.
Citation: Pi `docs/rpc.md`.
Pi sessions are JSONL files whose first line is a session header and whose entries form a tree through `id` and `parentId`.
`SessionManager` exposes `getHeader`, `getBranch`, `getEntries`, `getPath`, `branch`, `createBranchedSession`, `open`, `create`, and in-memory sessions.
Citation: Pi `docs/session-format.md` and Pi `docs/sdk.md` session-management section.
`pi-fork` implements active-branch context isolation by serializing `ctx.sessionManager.getHeader()` and `ctx.sessionManager.getBranch()` into a temporary JSONL session, then spawning a child Pi process with that session and an appended task prompt.
Its in-process runtime proposal keeps the same exact JSONL snapshot semantics and recommends `runtime: "auto" | "in-process" | "subprocess"`, while preserving subprocess fallback for strict isolation and per-child environment/offline behavior.
Citation: `/tmp/pi-fork-research/src/index.ts`, `/tmp/pi-fork-research/src/runner.ts`, and `/tmp/pi-fork-research/IN_PROCESS_RUNTIME_PROPOSAL.md`.
`mjakl/pi-subagent` implements named child agents through subprocess RPC.
It builds child Pi CLI args for independent, parent-context, and persistent session modes, uses `--mode rpc`, passes the prompt as a JSON command over stdin, rewrites the parent snapshot header cwd when needed, propagates depth and cycle-prevention environment variables, forces `PI_OFFLINE=1`, handles UI requests by cancelling them, tracks settlement, enforces timeouts, and kills the process group on abort.
Citation: `/tmp/pi-ext-research/pi-subagent/index.ts` and `/tmp/pi-ext-research/pi-subagent/runner.ts`.
Pi extension command APIs can create or switch sessions, but they are explicitly session-replacement APIs.
The docs warn that `withSession` receives a fresh replacement-session context and captured old session-bound objects become stale.
This is useful for replacing the current session, not for running many child subagents while the parent session remains active.
Citation: Pi `docs/extensions.md`, `ExtensionCommandContext`, `ctx.newSession`, `ctx.fork`, `ctx.switchSession`, and session replacement footguns.
## Implications
The spec should not choose between pi-fork and subagent semantics at the runtime layer.
Both forked and independent children can be represented by the same child runner with different session inputs.
The first implementation should optimize for correctness and safety over startup latency.
Subprocess RPC already matches Pi's real CLI, supports current extension behavior, and isolates child process state.
An in-process runner can later reduce spawn overhead if it preserves the same result contract.
The runtime choice should be configuration or capability-driven, not hardwired into named subagent types.
A future `auto` runtime can prefer in-process for ordinary fast children and fall back to subprocess for per-child environment, strict isolation, recursive delegation risk, or debugging.
## Limitations
This research did not build an in-process runner.
It relies on Pi's SDK documentation and `pi-fork`'s proposal for feasibility, so the implementation spec should leave room for a spike before making in-process the default.

View File

@@ -0,0 +1,81 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:47:35-04:00"
completed-at: "2026-07-31T22:17:24-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by:
- "[[028-pi-subagents-agent-definition-conventions-research]]"
tags:
- ticket/grill
---
# Subagent configuration boundary
## Question
What configuration model should the extension expose for named subagents, prompts, tools, models, defaults, and project overrides while keeping the extension itself policy-free?
## Decisions
- Extension-wide defaults live in dedicated JSON config files.
- Global config path is `~/.pi/agent/subagents.json`.
- Project config path is `.pi/subagents.json` using Pi's `CONFIG_DIR_NAME` rather than hardcoding `.pi` in implementation.
- Project config is honored only when project trust is active.
- Project config overrides global config.
- Named subagent definitions live only as Markdown files.
- User named definitions live under `~/.pi/agent/agents/*.md`.
- Project named definitions live under `.pi/agents/*.md` using Pi's `CONFIG_DIR_NAME` in implementation.
- `subagents.json` does not define named agents inline.
- `subagents.json` is reserved for extension defaults, optional UI behavior, concurrency, timeouts, and guardrails.
- Named subagent frontmatter requires only `name` and `description`.
- The Markdown body is the subagent prompt or instructions.
- All other frontmatter fields are optional and inherit from config defaults when absent.
- Version-one optional frontmatter fields are `context`, `model`, `thinking`, `tools`, `allowedContexts`, and `hidden`.
- `thinking` controls the Pi reasoning or effort level for the subagent when the selected model supports it.
- Agent frontmatter `tools` references a named tool profile.
- Tool profiles are defined in `subagents.json` and compile down to Pi active tools plus optional tool-call gates.
- The extension may provide in-code built-in tool profiles as fallback defaults, but it must not write a default config file without an explicit user command.
- Built-in neutral tool profile names are reserved in version one.
- User config may add custom tool profiles and choose the default profile, but may not overwrite built-in profile names.
- Version one ships reserved built-in tool profiles `none`, `read-only`, `read-only-with-safe-bash`, and `full-tools`.
- `read-only` is local-only and includes `read`, `grep`, `find`, and `ls`.
- `read-only-with-safe-bash` is local-only and adds `bash` with a read-only command allowlist.
- `full-tools` means the normal full local Pi tool surface rather than a sandbox permission level.
- `full-tools` is not guarded by an extension confirmation prompt during the subagent run.
- Version one does not add special restrictions preventing `full-tools` from being used as a global default, agent default, or spawn override.
- If a request is ambiguous about whether `full-tools` is appropriate, the main agent may ask the user before spawning, but the extension does not enforce that policy.
- Built-in profiles do not include web or network access except insofar as `full-tools` exposes ordinary bash.
- The in-code default tool profile is `read-only` when no config overrides it.
- The default tool profile is configurable in `subagents.json`.
- Trusted project `.pi/subagents.json` may loosen or tighten global defaults.
- This follows Pi extension convention: project config overrides global config after trust.
- Version one should not implement special tighten-only merge semantics.
- Optional built-in UI settings live under `ui` in `subagents.json`.
- UI settings gate only the extension-provided UI components, not the status data model, status endpoints, neutral events, or durable child records.
- The spawn tool uses a single `prompt` field for the actual delegated work request instead of splitting prose across `task` and `instructions` fields.
- A spawn request may optionally reference a named `agent` as a base definition.
- If `agent` is absent, `prompt` is sufficient for an ad hoc runtime subagent.
- If `agent` is present, `prompt` is the per-call request sent with that agent's base prompt.
- Version one exposes both single-spawn and batch-spawn tool surfaces.
- The single-spawn surface handles one subagent request.
- The batch-spawn surface accepts multiple subagent requests.
- All subagent spawns are non-blocking in version one.
- Spawn tools return after spawn acceptance with child ids and initial metadata.
- Subagent results arrive later through the status data model, neutral events, and durable milestone entries.
- The main agent decides whether and when it makes sense to wait for, poll, or retrieve subagent results.
- The extension should avoid over-prescribing waiting behavior.
- Version one exposes explicit post-spawn control tools: `subagent_list`, `subagent_status`, `subagent_result`, and `subagent_cancel`.
- `subagent_list` shows active subagents plus a bounded recent terminal history by default.
- The default recent terminal history should be small, such as the last 10 completed, failed, cancelled, or timed-out subagents in the current parent session.
- Results and status persist through Pi session state and child session storage only in version one.
- Version one does not write separate result files or artifact files.
- A later `web-research` style profile can be user-defined when an explicit web tool or bash-network policy exists.
- Version one supports both named Markdown subagents and ad hoc runtime subagents.
- The spawn tool uses `prompt` for the delegated request in both named and ad hoc spawns.
- A spawn call may optionally reference a named `agent` as a base definition.
- If `agent` is absent, the spawn is an ad hoc runtime subagent driven by `prompt`.
- If `agent` is present, the named definition supplies the base prompt and defaults, while `prompt` supplies the per-call request.
- Ad hoc runtime subagents are not persisted as named definitions and inherit global defaults unless the spawn call explicitly overrides context, model, thinking, or tools.
- Status should label ad hoc runtime subagents with a generated short label such as `ad-hoc` plus the child id.
- Exact tool names are deferred to the implementation specification.

View File

@@ -0,0 +1,41 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:38:17-04:00"
completed-at: "2026-07-31T21:46:58-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by:
- "[[020-pi-subagents-pi-runtime-research]]"
tags:
- ticket/grill
---
# Subagent context modes
## Question
What exact context modes should the extension support for child agents, including active-branch forked work, fully independent work, parent-summary seeding, persistent sessions, and adversarial review isolation?
## Decisions
- Version one supports only first-class `fork` and `independent` context modes.
- Persistent child lifetimes are intentionally out of version one.
- Summary-seeded context is not a first-class version-one mode.
- `fork` uses the full active-branch transcript snapshot, not a summarized or tool-output-stripped transform.
- `fork` adds a small wrapper that defines the delegated role, context boundary, and expected return shape.
- User-facing wording should avoid "child agent".
Prefer "delegated agent", "subagent", or "worker" depending on context.
- `independent` receives the task prompt, selected agent definition, and normal trusted project context such as `AGENTS.md`.
- `independent` receives no parent transcript and no generated parent summary by default.
- Spawn requests may include explicit attachments or snippets for `independent` runs.
- Context mode precedence is layered: global extension default, then agent definition default, then explicit spawn override.
- Agent definitions may optionally constrain allowed context modes when an agent should never receive parent conversation context.
- The version-one global default context mode is `independent`.
- Parent conversation context is opt-in through `fork`, not inherited by default.
- `fork` does not require special user confirmation in version one.
- Confirmation is reserved for risky capabilities such as write tools, shell access, project extension inheritance, external directories, or higher-cost model selection.
- `fork` copies the active branch as-is and lets child Pi handle any normal compaction.
- Version one should not preflight context size into refusal or hidden summarization.
- The parent receives the final textual result plus compact metadata by default.
- Compact metadata includes agent name, context mode, elapsed time, stop reason, and child status/session id.
- The default result should not copy selected evidence snippets or the child transcript into the parent context.

View File

@@ -0,0 +1,187 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:19:20-04:00"
completed-at: "2026-07-31T21:19:53-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by:
- "[[020-pi-subagents-pi-runtime-research]]"
tags:
- ticket/prototype/afk
---
# Pi subagent status UI prototype
## Question
Prototype the Pi-native status surface for headless or background subagents so the implementation spec can decide what users and parent agents can observe without relying on Herdr.
## Prototype
I built a throwaway text-rendering prototype at `/tmp/pi-subagent-status-prototype.js`.
It models three child records and renders three candidate Pi-native status surfaces:
1. A compact footer/widget summary.
2. An expanded table widget.
3. A grouped transcript entry.
I ran it with:
```bash
nix shell nixpkgs#nodejs --command node /tmp/pi-subagent-status-prototype.js
```
The first attempt with plain `node` failed because this host has no `node` on the ordinary PATH.
Using `nix shell nixpkgs#nodejs` resolved the runtime without installing anything permanently.
The prototype was not committed to a throwaway branch because the repository worktree is already dirty with unrelated user changes and this AFK planning ticket only needed an observable design verdict.
The primary source is the script path and transcript captured below.
## Output transcript
```text
=== compact footer/widget ===
subagents 3 active 1 queued
● review fork 01:42 grep modules/agents/pi
◒ sanity independent 01:05 writing final summary
○ adversary independent -- waiting for concurrency slot
=== table widget ===
id agent context state elapsed trust tools last event
● c1 review fork running 01:42 user read,grep grep modules/agents/pi
◒ c2 sanity independent settling 01:05 project read writing final summary
○ c3 adversary independent queued -- user read,bash waiting for concurrency slot
=== grouped transcript entry ===
subagents
● review (c1)
state=running context=fork trust=user model=openai-codex/gpt-5.5
elapsed=01:42 tools=read,grep last=grep modules/agents/pi
◒ sanity (c2)
state=settling context=independent trust=project model=inherit
elapsed=01:05 tools=read last=writing final summary
○ adversary (c3)
state=queued context=independent trust=user model=inherit
elapsed=-- tools=read,bash last=waiting for concurrency slot
verdict:
Use compact footer/widget for live awareness, table widget for expanded live details, and grouped transcript entry only for durable milestones.
The table is the best default expanded state because it exposes state, context, trust, tools, elapsed time, and last event without reading like chat content.
```
## Verdict
Use a three-layer Pi-native status surface.
The always-visible layer should be a compact `ctx.ui.setStatus()` footer item and, when space permits, a short `ctx.ui.setWidget()` summary.
It should show active count, queued count, and one-line rows for active children.
This answers the basic question "are child agents running?" without relying on Herdr panes.
The expanded live layer should be a table-like widget rendered above the editor through Pi extension UI.
It should show child id, agent name, context mode, lifecycle state, elapsed time, trust source, effective tool policy, and last event.
The table prototype was the clearest surface because it exposes the fields that matter for supervision without making them look like assistant prose.
The durable history layer should be a custom transcript entry created with `pi.appendEntry()` and rendered with `pi.registerEntryRenderer()`.
It should appear only on durable milestones such as spawn accepted, child completed, child failed, child cancelled, and child timed out.
It should not stream every child event into the parent transcript and should not participate in LLM context.
Pi docs explicitly say custom entries created with `pi.appendEntry()` do not participate in LLM context.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
## Implications for implementation
Represent each child with this status record shape:
```typescript
interface ChildStatus {
id: string;
agent: string;
context: "fork" | "independent" | string;
state: "queued" | "starting" | "running" | "settling" | "completed" | "failed" | "cancelled" | "timed_out";
trust: "user" | "project" | "explicit" | "unknown";
model: string;
cwd: string;
tools: string[];
startedAt?: string;
completedAt?: string;
elapsedMs: number;
lastEvent: string;
lastEventAt?: string;
summary?: string;
childSession?: string;
}
```
Use icon-only state markers in dense surfaces:
- `○` for queued.
- `◐` for starting.
- `●` for running.
- `◒` for settling.
- `✓` for completed.
- `✗` for failed.
- `⊘` for cancelled.
- `⏱` for timed out.
Use words as well as icons in expanded and durable surfaces for accessibility and log readability.
Do not expose secrets, full prompts, full tool output, environment variables, or provider credentials in status rows.
Show trust source and tool policy because they are safety-relevant.
Show child session id or file path only in expanded detail, not the compact footer.
## Mapping to Pi APIs
Use `ctx.ui.setStatus()` for the one-line footer status.
Pi docs list `ctx.ui.setStatus("my-ext", "Processing...")` as a footer status API.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Use `ctx.ui.setWidget()` for the compact or expanded live widget.
Pi docs list `ctx.ui.setWidget("my-ext", ["Line 1", "Line 2"])` as a widget above the editor.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Use `pi.appendEntry()` plus `pi.registerEntryRenderer()` for durable transcript milestones.
Pi docs say custom entries do not participate in LLM context and can render inside the chat transcript in interactive mode when paired with an entry renderer.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Use plain text fallback for RPC/headless clients.
In RPC mode, extension UI exists but some TUI-specific methods are no-ops or return defaults, so status must also be represented in durable entries and runner events.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md` and `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`.
## Acceptance criteria for implementation
- A user can tell that child agents are running without opening Herdr.
- A user can see how many children are active and queued.
- A user can inspect each child's context mode, lifecycle state, model, trust source, tool policy, elapsed time, and last event.
- A parent agent can receive a final compact result without inheriting child transcript noise.
- The parent transcript records durable child milestones but not every streaming child token.
- Cancelling or timing out a child updates the live and durable status surfaces.
- The same status model works when Herdr is absent.
## HITL follow-up verdict
A second HITL prototype was created at `/tmp/pi-subagent-status-hitl-tui-prototype.html` after the first HTML prototype targeted a web-facing interface instead of Pi's default TUI.
The replacement artifact mocks Pi's default dark terminal UI and compares three variants:
- A live widget above the editor.
- A durable transcript milestone entry.
- An expanded inspector above the editor.
The user preferred a combined model rather than one variant alone.
The collapsed live display should be a small widget or footer-style summary that shows a quick overview such as `2 running · 1 queued`.
The expanded live display should use the inspector shape from variant C.
The transcript milestone entry from variant B should record what happened, but it should not be the only status surface.
Implementation should therefore model status with three progressive layers:
1. Collapsed live summary by default.
2. Expanded live inspector on demand or by later user configuration.
3. Durable transcript milestone entries for historical record.
The status data model should be separate from the UI that renders it.
The default subagent extension should provide the child status records, status endpoints, durable entries, and neutral update events.
The Pi-native UI should be optional and replaceable by another extension that consumes the same data model.
This preserves the neutral core and lets a later user-specific or Herdr-oriented UI replace the default presentation without forking child lifecycle code.
## Limitations
This prototype tested information layout and state readability, not the actual Pi TUI renderer.
A later implementation spike should verify exact `ctx.ui.setWidget()` rendering width, wrapping, color support, and keyboard affordances inside Pi.

View File

@@ -0,0 +1,268 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:16:07-04:00"
completed-at: "2026-07-31T21:16:34-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by:
- "[[020-pi-subagents-pi-runtime-research]]"
tags:
- ticket/research
---
# Subagent lifecycle supervision research
## Question
What lifecycle, cancellation, timeout, event delivery, and long-running supervision model should the extension use, including whether Firstmate-style event-driven supervision patterns are relevant and how to avoid brittle sleep-loop orchestration?
## Answer
Use an explicit supervisor inside the parent Pi extension and isolate child execution behind the `ChildRunner` boundary selected in [[020-pi-subagents-pi-runtime-research]].
For version one, the supervisor should run subprocess RPC children and track them as durable child records with event-driven state transitions.
Do not supervise by sleeping and polling files.
Use RPC events, process lifecycle events, abort signals, and bounded timers as the primary coordination primitives.
A child lifecycle should be a small state machine: `queued`, `starting`, `running`, `settling`, `completed`, `failed`, `cancelled`, and `timed_out`.
Transitions should be driven by observed events: spawn success, RPC prompt acceptance, `agent_start`, streaming updates, tool events, `agent_settled`, process close, abort request, timeout expiry, and parse/protocol errors.
The parent should persist status entries in Pi with `pi.appendEntry()` so status survives reloads without putting full child logs into parent LLM context.
Source: Pi extension docs for `appendEntry`, lifecycle events, `session_shutdown`, and agent/tool events in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Cancellation should be cooperative first and forceful second.
For RPC subprocesses, send the RPC `abort` command when the child has reached protocol readiness, close stdin if needed, then signal the child process group with SIGTERM and escalate to SIGKILL after a short grace period.
For in-process children later, call `AgentSession.abort()`, unsubscribe from events, dispose the session, and clean temporary files in `finally`.
Source: Pi RPC `abort` docs in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`, Pi extension abort-signal docs in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`, and the subprocess runner design in [[020-pi-subagents-pi-runtime-research]].
Timeouts should be wall-clock limits owned by the supervisor, not prompts asking the model to stop.
Each spawn should have optional `startTimeoutMs`, `idleTimeoutMs`, and `runTimeoutMs` fields.
The first guards child boot and prompt acceptance, the second guards no-progress hangs, and the third guards total runtime.
Any timeout should produce a structured `timed_out` result and then execute the same cancellation path.
Firstmate-style patterns are relevant at the design level, not as code to import.
The useful pattern is event-normalized supervision: backend-specific events are converted into a backend-neutral transition model, ambiguous recovery fails closed, locks serialize identity-sensitive spawn and metadata publication, and presentation metadata is never treated as lifecycle authority.
The Pi extension should apply those patterns to child-agent supervision while using Pi-native RPC events instead of Herdr panes, tmux windows, or filesystem sentinels.
Source: `/tmp/firstmate-research/firstmate/bin/fm-spawn.sh` and `/tmp/firstmate-research/firstmate/bin/backends/herdr.sh`.
## Findings
### Pi event surfaces
Pi extension lifecycle events include `session_start`, `resources_discover`, `before_agent_start`, `agent_start`, `message_start`, `message_update`, `message_end`, `tool_execution_start`, `tool_execution_update`, `tool_execution_end`, `agent_end`, `agent_settled`, and `session_shutdown`.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Pi docs say `agent_end` is not a final idle signal because Pi may still auto-retry, compact and retry, or continue with queued follow-up messages.
They recommend `agent_settled` when status integrations need to know Pi will not continue automatically.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md#agent_start--agent_end--agent_settled`.
Pi tool execution events are ordered only partly.
`tool_execution_start` is emitted in assistant source order during preflight, `tool_execution_update` events may interleave across tools, and `tool_execution_end` is emitted in tool completion order.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md#tool_execution_start--tool_execution_update--tool_execution_end`.
Pi custom tool execution receives an `AbortSignal`.
Extension handlers can use `ctx.signal` for nested async work so Esc cancels abort-aware operations started by the extension.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md#ctxsignal`.
Pi docs instruct extensions not to start background resources from the factory.
They should defer resources until `session_start` or the event/tool/command that needs them and register an idempotent `session_shutdown` handler to clean session-scoped resources.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md#long-lived-resources-and-shutdown`.
### Pi RPC child control
Pi RPC mode is a JSONL protocol over stdin and stdout.
It accepts `prompt`, `steer`, `follow_up`, `abort`, `new_session`, `get_state`, and other commands.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`.
The RPC `abort` command aborts the current agent operation and returns a success response.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md#abort`.
RPC `get_state` exposes whether the child is streaming, compacting, retrying, or waiting for bash.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md#get_state`.
RPC streams lifecycle events including `agent_settled`, `message_start`, `message_update`, `message_end`, `tool_execution_start`, `tool_execution_update`, and `tool_execution_end`.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md#events`.
RPC tool events include `toolCallId`, which can correlate start, update, and end events.
`tool_execution_update` contains accumulated partial output rather than just a delta.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md#tool_execution_start--tool_execution_update--tool_execution_end`.
### Prior Pi subagent runner evidence
The previously inspected `mjakl/pi-subagent` runner uses `pi --mode rpc` and sends the child prompt as a JSON `prompt` command.
It watches stdout JSON events, cancels extension UI requests, records streaming updates, watches for `agent_settled`, asks `get_state` if the prompt appears handled without an agent start, and normalizes the final result.
Source: `/tmp/pi-ext-research/pi-subagent/runner.ts`.
That runner uses a detached process group on Unix and `taskkill /T /F` on Windows.
It terminates with SIGTERM, escalates to SIGKILL after 500ms on Unix, and has a separate termination settle timeout.
Source: `/tmp/pi-ext-research/pi-subagent/runner.ts`.
That runner enforces optional run timeouts, caps oversized JSON event lines at 25 MiB, truncates stderr, handles unexpected signal exits, and cleans temporary prompt and session snapshot directories in `finally`.
Source: `/tmp/pi-ext-research/pi-subagent/runner.ts`.
The same runner waits briefly after semantic settlement for transient events, but it does not use unbounded sleep-loop orchestration.
It drives completion from RPC events, process close, timeout timers, and abort signals.
Source: `/tmp/pi-ext-research/pi-subagent/runner.ts`.
### Firstmate supervision patterns
Firstmate's spawn path is not a simple terminal launcher.
It resolves backend, harness, model, effort, task kind, worktree, parent identity, locks, metadata, and recovery conditions before endpoint creation.
Source: `/tmp/firstmate-research/firstmate/bin/fm-spawn.sh`.
Firstmate's Herdr adapter treats presentation workspaces as non-authoritative visual projections.
It stores exact endpoint metadata for recovery and refuses ambiguous recovered launches instead of guessing.
Source: `/tmp/firstmate-research/firstmate/bin/backends/herdr.sh`.
Firstmate's Herdr adapter normalizes `pane.agent_status_changed` edges through a shared transition model and falls back to polling only when the event surface is unavailable.
Source: `/tmp/firstmate-research/firstmate/bin/backends/herdr.sh`.
The transferable Firstmate idea is to separate endpoint authority from presentation, use normalized transitions, and fail closed on ambiguous recovery.
The non-transferable parts are tmux/Herdr pane IDs, treehouse worktree allocation, and shell metadata files as primary lifecycle signals.
## Lifecycle model
### State machine
Use these states:
- `queued`: accepted by the parent but not yet started.
- `starting`: process or in-process session is being created.
- `running`: child prompt was accepted or `agent_start` was observed.
- `settling`: `agent_settled` was observed and the runner is draining final events or waiting for process exit.
- `completed`: child produced a normal final result.
- `failed`: child failed due to spawn, protocol, model, tool, parse, or process error.
- `cancelled`: parent or user cancelled the child.
- `timed_out`: supervisor timeout fired.
Store timestamps for every state transition.
Store the last observed event type and a short status string for the UI.
Do not infer long-running state from lack of output alone unless an idle timeout expires.
### Event handling
The subprocess RPC runner should parse stdout as strict JSONL, matching Pi RPC framing rules.
It should keep stderr as diagnostic output, capped and tail-truncated.
It should reject oversized JSON lines with a protocol error.
It should handle malformed JSON lines as protocol errors unless Pi documents an out-of-band stdout channel for the launched mode.
Map events as follows:
- RPC prompt response success: `starting` to `running` if no `agent_start` arrives yet.
- `agent_start`: `starting` or `running` to `running`.
- `message_update`: update streaming preview and last-progress time.
- `tool_execution_start`: add or update a tool record and last-progress time.
- `tool_execution_update`: replace accumulated tool output preview and last-progress time.
- `tool_execution_end`: mark the tool record complete and last-progress time.
- `agent_settled`: `running` to `settling`.
- Process close with settled result: `settling` to `completed` or `failed` based on normalized result.
- Process close without settlement: `failed`, unless cancellation or timeout is already active.
Use `agent_settled`, not `agent_end`, as the semantic completion signal.
Keep a short drain grace period after `agent_settled` so trailing message and tool events are processed.
For persistent child sessions, wait for the child process to exit naturally up to a longer bounded flush timeout before killing it.
### Cancellation model
A cancellation request should be idempotent.
The first cancellation marks the child as cancellation-pending and records who initiated it.
Further cancellation calls should return the same pending or final state.
For subprocess RPC children:
1. If stdin is open and the RPC protocol is alive, send `{"type":"abort"}`.
2. End stdin when no further command is needed.
3. Send SIGTERM to the process group on Unix or `taskkill /T` on Windows if the process remains alive.
4. Escalate to SIGKILL or forced kill after a short grace period.
5. Resolve as `cancelled` with exit code 130 when cancellation was parent-initiated and no better child result exists.
For later in-process children:
1. Call the child `AgentSession.abort()`.
2. Unsubscribe event listeners.
3. Dispose the child session.
4. Clean temporary session snapshots in `finally`.
5. Resolve as `cancelled` unless the session had already completed.
Parent Pi `session_shutdown` must cancel or detach every running child according to a user-configured policy.
The safer default is to cancel foreground and supervised background children on parent shutdown.
A later persistent-child feature may allow detaching, but detached children must be visible in status and recoverable by session id.
### Timeout model
Support three supervisor-owned timers:
- `startTimeoutMs`: maximum time from process spawn to RPC prompt acceptance or first meaningful child event.
- `idleTimeoutMs`: maximum time without any message, tool, or state progress after the child starts.
- `runTimeoutMs`: maximum wall-clock duration from spawn to completion.
Timeouts should never be implemented by prompting the model to stop.
A timeout should set a structured error reason, run cancellation, and return a normalized `timed_out` result.
Timers must be cleared exactly once when the child reaches a terminal state.
### Persistence and recovery
Use `pi.appendEntry()` for durable parent-visible child status because custom entries do not participate in LLM context.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md#piappendentrycustomtype-data`.
Persist enough metadata to display and recover status:
- Child id.
- Parent session file path or id.
- Agent name and source path.
- Context mode.
- Working directory.
- Runtime kind.
- Process id when applicable.
- Child session file or id when persistent.
- Start and completion timestamps.
- Current lifecycle state.
- Last event timestamp.
- Stop reason.
- Short final summary.
Do not treat UI entries as the authority for killing a process.
Process handles in memory, persistent child session metadata, and explicit child ids are authority.
If Pi reload loses process handles, the extension should mark unknown still-running subprocesses as `orphaned` unless it has a deliberate reattach protocol.
Do not guess ownership from a title, status string, or terminal row.
### Concurrency model
Support bounded concurrency.
A global extension setting should limit concurrently running children.
Each tool invocation may additionally limit fan-out.
Queue excess children in `queued` state.
Use a central `Supervisor` map keyed by child id.
Do not let each tool invocation own untracked subprocesses independently.
This prevents orphaned children when multiple parent tool calls run concurrently.
### Avoiding brittle sleep loops
Avoid unbounded loops like `while child_running; sleep 1; poll status`.
Use event listeners and timers.
Polling is acceptable only as a compatibility fallback when a backend lacks events, and it must have an interval, deadline, and state reconciliation rule.
For subprocess RPC, no normal polling is needed.
The child already streams events.
`get_state` may be used as a targeted one-shot reconciliation command when prompt acceptance succeeds but no `agent_start` arrives within a short grace period.
Source: Pi RPC state docs and `/tmp/pi-ext-research/pi-subagent/runner.ts`.
## Implementation requirements
- Implement `Supervisor` as the only owner of child records, process handles, timers, and event subscriptions.
- Implement `ChildRunner` as a narrow interface with `start`, `abort`, and event callbacks.
- Make all cleanup idempotent.
- Clear every timer in the terminal path.
- Remove all event listeners in `finally` or equivalent disposal paths.
- Cap stdout line size, stderr size, and retained preview size.
- Normalize every terminal path to one result object.
- Expose progress via Pi status UI and durable non-context entries, not parent prompt messages by default.
- Use `agent_settled` for semantic completion.
- Use process close for final subprocess resource cleanup.
- Treat cancellation, timeout, protocol error, spawn error, and nonzero exit as distinct stop reasons.
- Add tests for cancellation before start, cancellation while running, timeout, malformed JSON, child process spawn failure, child exit before settlement, child settlement before process exit, persistent child flush timeout, and parent shutdown.
## Limitations
This ticket did not run a fresh prototype against Pi RPC.
It relies on Pi documentation, the previously inspected `mjakl/pi-subagent` runner, and Firstmate source patterns.
The implementation spec should still include a small runner test harness before coding the full extension UI.

View File

@@ -0,0 +1,197 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:14:15-04:00"
completed-at: "2026-07-31T21:14:49-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/research
---
# Subagent security and trust research
## Question
What security, trust, project-local configuration, tool inheritance, extension inheritance, and user-confirmation rules should the implementation spec require for spawning child Pi agents safely?
## Answer
Pi subagents must be specified as local-agent orchestration, not as a sandbox or privilege boundary.
Pi has no built-in sandbox, extensions run with the permissions of the user that started Pi, and project trust only controls whether project-local resources are loaded.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`.
The implementation should default to a conservative child environment.
A child should inherit the parent model and safe read/write tool surface only when explicitly allowed by the selected agent definition or spawn request.
It should not inherit project-local extensions, project-local settings, project packages, prompt files, MCP-like external services, or arbitrary environment variables by default.
If a child runs in the same process user account, any stronger isolation claim must be rejected unless the child is routed through a real container, VM, micro-VM, remote sandbox, or equivalent OS boundary.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/containerization.md`.
The parent extension may load user-level agent definitions without a project trust decision, because user/global Pi resources are already in the user's local trust boundary.
Project-level agent definitions should load only after the same project trust decision that protects `.pi/settings.json`, `.pi/extensions`, `.pi/skills`, `.pi/prompts`, `.pi/themes`, `.pi/SYSTEM.md`, `.pi/APPEND_SYSTEM.md`, and project `.agents/skills`.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`.
The child-spawn tool must be allowlisted by explicit active tools and must perform a local preflight before starting a subprocess.
That preflight should validate the agent name, context mode, working directory, tool policy, model, extension inheritance, project trust state, and whether the requested spawn can write to the workspace.
If the request asks for risky capabilities, the tool should ask for user confirmation in TUI/RPC modes and auto-deny or require a preconfigured allow rule in print/JSON headless modes.
Pi docs say extension UI has `hasUI` true in TUI and RPC modes and false in print and JSON modes, so the extension must not depend on dialogs when `ctx.hasUI` is false.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
## Findings
### Pi's security boundary
Pi runs as a local coding agent with the permissions of the user account that starts it.
It treats files writable by that user as inside the same local trust boundary.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`.
Pi does not include a built-in sandbox.
Built-in tools can read files, write files, edit files, and run shell commands with the permissions of the Pi process.
Extensions are TypeScript modules with the same permissions.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`.
Pi documentation explicitly says real isolation must come from an operating-system, virtualization, or container boundary.
For untrusted repositories, generated code that is not closely monitored, or unattended automation, Pi recommends running in a contained environment.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md` and `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/containerization.md`.
Containerization patterns documented by Pi include running the whole Pi process in Docker, routing built-in tools into a Gondolin micro-VM, or running Pi in OpenShell.
The docs warn that extensions run wherever the Pi process runs and that host Pi with tool-routing still leaves other custom extension tools running on the host unless they also delegate operations.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/containerization.md`.
### Project trust
Project trust controls whether Pi loads project-local settings, resources, packages, and extensions.
It is not a sandbox and does not restrict what the model can ask tools to do after work starts in a directory.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`.
Pi considers a project to need trust when it finds `.pi/settings.json`, `.pi/extensions`, `.pi/skills`, `.pi/prompts`, `.pi/themes`, `.pi/SYSTEM.md`, `.pi/APPEND_SYSTEM.md`, or project `.agents/skills` in the current directory or an ancestor.
A bare `.pi` directory does not require trust.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`.
When trust is declined, Pi skips protected resources.
`AGENTS.md` and `CLAUDE.md` context files still load regardless of project trust unless context loading is disabled.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`.
Project-local extensions load only after project trust is resolved.
Before trust is resolved, only context files, user/global extensions, and CLI extensions load, and only those extensions can handle the `project_trust` event.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md` and `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Non-interactive modes do not show a trust prompt.
Without a saved trust decision, `defaultProjectTrust: "ask"` and `"never"` ignore project resources, while `"always"` trusts them.
The CLI can override trust for one run with `--approve` or `--no-approve`.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md` and `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/settings.md`.
### Extension and tool inheritance risks
Extensions can register custom tools, intercept or block tool calls, inject context, customize compaction, and modify provider requests.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Extensions can override built-in tools such as `read`, `bash`, `edit`, `write`, `grep`, `find`, and `ls` by registering a tool with the same name.
Pi displays an interactive warning when this happens.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Custom tools are available to the model when registered and active.
Pi exposes `pi.setActiveTools()` and `pi.getActiveTools()` to enable or disable tools at runtime.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
A child Pi subprocess that starts normally in the same project may load its own global and trusted project resources.
Therefore "inherits parent tools" and "starts Pi in the same directory" are not equivalent.
The implementation must explicitly choose and document whether a child runs with only the subagent runner's controlled tools, with user/global Pi resources, or with full trusted project resources.
Source basis: Pi resource loading and trust behavior in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md`, `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/settings.md`, and `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
### Environment and credential inheritance
Commands run by Pi's built-in bash tool receive `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`.
Custom bash tools expose this session environment by default unless `exposeSessionEnvironment` is disabled.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/environment-variables.md`.
The Pi process also reads variables such as `PI_CODING_AGENT_DIR`, `PI_CODING_AGENT_SESSION_DIR`, `PI_PACKAGE_DIR`, `PI_OFFLINE`, `PI_SKIP_VERSION_CHECK`, and provider credentials such as API keys.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/environment-variables.md`.
A child subprocess will inherit the parent process environment unless the runner deliberately supplies a sanitized environment.
This is standard process behavior and follows from the subprocess-based runtime decision in [[020-pi-subagents-pi-runtime-research]].
The implementation should therefore pass only required Pi/provider/session variables and should strip stale parent `PI_SESSION_*` variables unless the child intentionally reports against the parent.
### User confirmation and headless behavior
Pi extensions can use UI helpers such as `confirm`, `select`, `input`, and `notify`.
`ctx.hasUI` is true in TUI and RPC modes, and false in print and JSON modes.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
A subagent extension cannot safely depend on interactive confirmation in print or JSON mode.
For headless runs, risky spawns should be denied unless a global user setting or explicit spawn parameter already authorizes the requested class of operation.
Source basis: non-interactive trust behavior in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/security.md` and UI mode behavior in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
## Required rules for the implementation spec
### Trust rules
- User-level agent definitions may load from `~/.pi/agent/agents/` without project trust.
- Project-level agent definitions in `.pi/agents/` must be treated as protected project resources.
- If Pi does not natively consider `.pi/agents/` a trust-triggering resource, the extension must only discover it after an already-trusted project decision or must create its own equivalent trust gate.
- Declined project trust must prevent project agent definitions, project extension inheritance, project package inheritance, and project prompt inheritance from affecting children.
- Untrusted project files may still be read by the child through normal tools after the user asks to work in that repository, so prompts must not describe project trust as prompt-injection protection.
### Spawn confirmation rules
Require user confirmation before a spawn when any of these are true:
- The child can write to the parent workspace.
- The child can run shell commands.
- The child can access paths outside the project worktree.
- The child can inherit project-local extensions, packages, or settings.
- The child can install packages or run package manager hooks.
- The child can access network tools beyond the model provider connection.
- The child can use a higher-cost model than the parent.
- The child is fully independent and not attached to the parent status/lifecycle view.
- The child is requested from an untrusted or project-supplied agent definition.
In modes without UI, deny those spawns unless an explicit global allow rule is present.
Do not let project-local config grant those allowances for itself.
### Tool policy rules
- Default children to a minimal tool set.
- Treat tool access as an allowlist, not inherited ambient authority.
- Provide named policy presets only as neutral mechanics, such as `read-only`, `workspace-write`, and `full-parent-tools`, not as opinionated agent types.
- Do not pass the parent extension's complete tool registry by default.
- If a child needs a custom tool from the parent, pass that tool explicitly through a typed adapter or reject the spawn when no safe adapter exists.
- Deny nested subagent spawning by default, and require explicit opt-in plus a depth limit.
- For writing tools, keep Pi's file mutation queue behavior or equivalent serialization so parallel writes cannot race destructively.
### Extension and resource inheritance rules
- Do not load project-local extensions in children by default.
- Do not inherit project settings in children by default, except for trusted project settings explicitly marked as safe for children.
- Do not inherit prompt templates, skills, themes, packages, or model provider extensions merely because the parent has them.
- Prefer starting child RPC processes with a subagent-specific config directory or with explicit CLI/settings inputs when Pi supports that cleanly.
- If the implementation cannot prevent child subprocesses from loading ambient global Pi extensions, document that user/global Pi config is in the local trust boundary and expose an opt-out mode for stricter child runs.
### Environment and credential rules
- Sanitize child process environment.
- Pass provider credentials only when needed for the selected model.
- Strip stale parent `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL` unless intentionally projecting parent metadata.
- Set child session storage explicitly so child transcripts are separated from parent transcripts.
- Do not expose parent session files to child prompts or status payloads unless the chosen context mode requires it.
- Avoid passing arbitrary shell environment variables into children, especially tokens and desktop/session variables, unless the user opts into ambient inheritance.
### Context and filesystem rules
- For `fork` mode, copy only the intended conversation/context slice and clearly label it as parent-derived.
- For `independent` mode, start with no parent transcript except the task prompt and selected agent definition.
- For workspace writes, prefer a temporary worktree or explicit output patch handoff when the task is adversarial, speculative, or review-oriented.
- Do not call a same-user subprocess "isolated" unless it is actually routed into an OS isolation boundary.
- If stronger isolation is requested, integrate with a container, VM, micro-VM, or OpenShell-like backend rather than adding in-process checks and calling them a sandbox.
### Audit and status rules
- Persist child spawn metadata in the parent session as non-prompt transcript entries where possible.
- Record child id, agent name, context mode, cwd, model, effective tool policy, trust source, start time, stop time, exit state, and output summary.
- Do not include secrets, full environment dumps, or provider auth material in parent-visible status.
- Show whether the child is running with project resources, user/global resources only, or sandboxed execution.
## Limitations
This research is based on Pi documentation and prior ticket decisions, not a fresh source-code audit of Pi's resource loader.
The implementation spec should verify exact CLI flags available for suppressing project resources or selecting config directories when the subprocess runner is designed.

View File

@@ -0,0 +1,239 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:17:55-04:00"
completed-at: "2026-07-31T21:18:12-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/task/afk
---
# Dotfiles deployment seam
## Question
Define the dotfiles deployment seam for the new Pi subagent extension, including development placement, flake-managed promotion, configuration files, and verification commands needed before implementation starts.
## Result
The extension should be developed as a Pi extension under `modules/agents/pi/extensions/subagents/` and deployed by the existing Home Manager file link from `modules/agents/pi/pi.nix` to `~/.pi/agent/extensions`.
Finished work must be promoted through the dotfiles module before it counts as deployed.
Direct files under `~/.pi/agent/extensions` are acceptable only for throwaway development or local experiments.
This matches the repository gotcha that flake-managed Pi extension, prompt, and skill directories may be written directly for experiments but durable deployment must go through the dotfiles module.
Source: `/home/alexion/wrk/dotfiles/AGENTS.md`.
No install step should be part of the implementation plan without explicit user consent.
The durable path should avoid `pi install`, npm package installation, or git package installation for version one.
If runtime dependencies become unavoidable, the implementation spec must pause for consent and then model the dependency declaratively in Nix rather than asking Pi to install it interactively.
Source: user constraint and Pi package security docs in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/packages.md`.
## Current Pi deployment shape
`modules/agents/pi/pi.nix` enables `programs.pi-coding-agent` through Home Manager.
It writes Pi settings with `defaultProvider`, `defaultModel`, `defaultThinkingLevel`, theme, and telemetry choices.
It force-manages `~/.pi/agent/settings.json` but intentionally leaves login credential state unmanaged.
Source: `modules/agents/pi/pi.nix`.
The same module recursively links `modules/agents/pi/extensions` to `~/.pi/agent/extensions`.
It also recursively links `modules/agents/pi/prompts` to `~/.pi/agent/prompts`.
Source: `modules/agents/pi/pi.nix`.
The current `modules/agents/pi/extensions` directory contains only `.gitkeep`.
That means a new extension can be added there without colliding with existing Pi extension code.
Source: `find modules/agents/pi -maxdepth 3 -type f` during this task.
Pi's extension docs say global extensions are auto-discovered from `~/.pi/agent/extensions/*.ts` and `~/.pi/agent/extensions/*/index.ts`.
Project-local extensions are auto-discovered from `.pi/extensions/*.ts` and `.pi/extensions/*/index.ts` after project trust.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Pi can hot-reload auto-discovered extension locations with `/reload`.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
## Proposed repository layout
Use this layout for version one:
```text
modules/agents/pi/extensions/subagents/
├── index.ts
├── agents.ts
├── config.ts
├── runner.ts
├── supervisor.ts
├── status.ts
├── types.ts
└── ui.ts
```
`index.ts` should be the extension entry point and should export the default Pi extension factory.
`agents.ts` should load and validate named agent definitions.
`config.ts` should resolve extension settings and default policy.
`runner.ts` should implement the subprocess RPC `ChildRunner`.
`supervisor.ts` should own child records, lifecycle, cancellation, timers, and concurrency.
`status.ts` should define parent-session entries and renderable status data.
`types.ts` should hold shared TypeScript types.
`ui.ts` should isolate optional TUI/RPC status and confirmation helpers.
Keep filenames lowercase.
This follows the user's global filename preference and the repository convention.
Source: `/home/alexion/.pi/agent/AGENTS.md` and `/home/alexion/wrk/dotfiles/AGENTS.md`.
Do not add a `package.json` unless implementation discovers an unavoidable external runtime dependency.
Pi extensions can import Pi-provided packages such as `@earendil-works/pi-coding-agent`, `@earendil-works/pi-ai`, `@earendil-works/pi-tui`, and `typebox` directly.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
## Agent definition deployment seam
The extension should load user-level agent definitions from `~/.pi/agent/agents/` and project-level definitions from `.pi/agents/` after trust.
Because the current dotfiles module does not link `modules/agents/pi/agents`, add this managed directory when real agent definitions are committed.
The module should link it recursively to `~/.pi/agent/agents` in the same style as extensions and prompts.
Proposed durable layout:
```text
modules/agents/pi/agents/
└── .gitkeep
```
Proposed Nix addition when needed:
```nix
"${piDir}/agents" = {
source = ./agents;
recursive = true;
};
```
The initial extension should not ship opinionated agent definition files.
The directory can contain `.gitkeep` only until the user intentionally adds named agents.
This satisfies the constraint that named agents, prompts, and policy belong in Pi config rather than the neutral extension.
## Settings seam
Do not add extension-specific settings to `programs.pi-coding-agent.settings` until the implementation schema is finalized.
When settings are needed, keep them under a clearly namespaced key such as `subagents` only if Pi preserves unknown settings for extension consumption.
If Pi's typed settings reject unknown keys, store extension config in a separate user-level file such as `~/.pi/agent/subagents.json` and manage it through Home Manager `home.file`.
The implementation spec must verify Pi's settings parser behavior before choosing this.
Recommended initial defaults should live in extension code and be neutral:
- Runtime: `subprocess-rpc`.
- Max concurrent children: `2` or `3`.
- Default context: unresolved by [[022-pi-subagents-context-modes-grill]].
- Project agents: disabled until project trust is confirmed.
- Project extension inheritance: disabled.
- Nested children: disabled.
- Tool policy: minimal and explicit.
Do not encode opinionated subagent types in settings.
Do not add Herdr settings to the Pi extension seam.
Herdr remains an optional later adapter and should not shape the core deployment.
## Development workflow
For quick experiments, it is acceptable to copy or create a throwaway extension directly under `~/.pi/agent/extensions/subagents/`.
That is not durable and may be overwritten or hidden by Home Manager activation.
Source: `/home/alexion/wrk/dotfiles/AGENTS.md` gotcha about flake-managed Pi directories.
For implementation work that should persist, edit `modules/agents/pi/extensions/subagents/` in the repository.
Then reload Pi or rebuild Home Manager depending on whether the current session sees the repository path through the existing symlink.
Because `modules/agents/pi/pi.nix` recursively links the entire `extensions` directory, editing the source tree should normally be enough for `/reload` in the running Pi session to see the change.
A rebuild is required to verify clean-machine deployment.
Use `pi -e ./path.ts` only for quick tests of an isolated file.
The Pi docs identify `-e` as a quick-test path and say auto-discovered global or project locations are the right placement for `/reload`.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
## Verification commands
Use these checks before implementation starts:
```bash
nix eval .#nixosConfigurations.neogaia.config.modules.agents.pi.enable
```
Expected result: `true`.
This verifies the Pi module is enabled for the current host.
```bash
nix eval .#nixosConfigurations.neogaia.config.home-manager.users.alexion.home.file.'"/home/alexion/.pi/agent/extensions"'.source
```
Expected result: a Nix store path sourced from `modules/agents/pi/extensions` after evaluation.
This verifies the deployment link remains declared.
```bash
nix eval .#nixosConfigurations.neogaia.config.home-manager.users.alexion.home.file.'"/home/alexion/.pi/agent/prompts"'.source
```
Expected result: a Nix store path sourced from `modules/agents/pi/prompts`.
This is a control check matching the existing prompt link.
After adding `modules/agents/pi/agents`, add and run this check:
```bash
nix eval .#nixosConfigurations.neogaia.config.home-manager.users.alexion.home.file.'"/home/alexion/.pi/agent/agents"'.source
```
Expected result: a Nix store path sourced from `modules/agents/pi/agents`.
Use the repository's primary verification seam before merging implementation:
```bash
nix flake check
```
The project gotcha says `nix flake check` builds `checks.x86_64-linux.<host>` and is the primary build/verify seam for any host.
Source: `/home/alexion/wrk/dotfiles/AGENTS.md`.
For cheap targeted evaluation during implementation, use `nix eval .#nixosConfigurations.neogaia.config...` rather than committing speculative host enablement.
Source: `/home/alexion/wrk/dotfiles/AGENTS.md`.
## Runtime verification after implementation
Use these manual checks after the extension exists:
```bash
pi --mode rpc --no-session
```
Then send a minimal JSONL prompt and confirm the process speaks RPC.
This verifies the child runtime target independently of the extension.
Source: Pi RPC docs in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/rpc.md`.
Inside Pi, run `/reload` after editing the managed extension source and confirm the extension reloads without restarting Pi.
This verifies the global extension discovery path.
Source: Pi extension docs in `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
After adding a status renderer, spawn a trivial read-only child and verify these properties:
- Parent transcript receives a compact status entry.
- Child transcript or session remains separate.
- Cancelling the parent tool call cancels the child.
- The child exits or is killed on timeout.
- No project-local agent definition loads before project trust.
- No Herdr-specific behavior is required.
## Files to change during implementation
Expected durable changes:
- `modules/agents/pi/extensions/subagents/index.ts`.
- `modules/agents/pi/extensions/subagents/*.ts` helper files.
- `modules/agents/pi/agents/.gitkeep` if the managed user-agent directory is introduced.
- `modules/agents/pi/pi.nix` only if the agents directory or extension config file is linked.
Avoid these changes unless explicitly justified:
- Do not edit `~/.pi/agent` directly for durable deployment.
- Do not modify generated Home Manager output.
- Do not install Pi packages with `pi install`.
- Do not add Herdr-specific config to the Pi module for version one.
- Do not add named opinionated subagents to the neutral extension.
## Open implementation questions
The implementation spec still needs decisions from [[021-pi-subagents-config-boundary-grill]] and [[022-pi-subagents-context-modes-grill]].
The status UI details still depend on [[023-pi-subagents-status-ui-prototype]].
This deployment seam is therefore ready for implementation planning but not by itself sufficient to start coding the extension.

View File

@@ -0,0 +1,579 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T22:23:32-04:00"
completed-at: "2026-07-31T22:23:42-04:00"
parent: "[[002-pi-subagents-map]]"
blocked-by: []
tags:
- ticket/task/afk
---
# Implementation ready specification
## Question
Synthesize the resolved route into an implementation-ready specification for the new neutral Pi subagent extension, including architecture, configuration schema, runtime model, context modes, status UI, lifecycle handling, trust boundaries, deployment seam, and verification plan.
## Goal
Build a new neutral Pi extension that can start context-clean subagents frequently.
The extension provides mechanism only.
Named agents, prompts, tool profiles, and policy live in Pi configuration.
The extension must not bundle opinionated subagent types.
Herdr support is out of the version-one core and may be added later as an adapter or replacement UI.
## Non-goals
Do not implement Herdr integration in version one.
Do not claim sandbox isolation.
Do not install Pi packages, npm packages, or git packages without explicit user consent.
Do not auto-write default config files.
Do not make the extension aware of Nix or Home Manager.
Do not ship opinionated named agents with the neutral extension.
Do not add persistent subagent lifetimes in version one.
Do not add summary-seeded context mode in version one.
Do not write separate result or artifact files in version one.
## Repository placement
Implement the extension under:
```text
modules/agents/pi/extensions/subagents/
├── index.ts
├── agents.ts
├── config.ts
├── runner.ts
├── supervisor.ts
├── status.ts
├── types.ts
└── ui.ts
```
`index.ts` is the Pi extension entry point.
`agents.ts` loads and validates named Markdown agent definitions.
`config.ts` loads global and trusted project config.
`runner.ts` implements the subprocess RPC child runner.
`supervisor.ts` owns child lifecycle, cancellation, timers, and status records.
`status.ts` defines child status records, durable entries, and status/result APIs.
`types.ts` holds shared types and schemas.
`ui.ts` owns the optional built-in Pi TUI presentation.
The existing `modules/agents/pi/pi.nix` recursively links `modules/agents/pi/extensions` to `~/.pi/agent/extensions`, so the extension is deployed through the existing durable dotfiles seam.
## Runtime files
The extension reads these Pi-native runtime paths:
- Global config: `~/.pi/agent/subagents.json`.
- Trusted project config: `.pi/subagents.json` through Pi's `CONFIG_DIR_NAME`.
- Global named agents: `~/.pi/agent/agents/*.md`.
- Trusted project named agents: `.pi/agents/*.md` through Pi's `CONFIG_DIR_NAME`.
Missing config files are normal.
Missing agent directories are normal.
The extension must not create them automatically.
The dotfiles module may later link plain files, render JSON from Nix attrs, or expose typed Nix options.
That module design is out of scope for the extension.
## Configuration model
### Config file ownership
Use dedicated JSON config files rather than unknown keys in Pi `settings.json`.
Global config is loaded from `~/.pi/agent/subagents.json`.
Project config is loaded from `.pi/subagents.json` only when `ctx.isProjectTrusted()` is true.
Project config overrides global config.
Do not implement tighten-only merge semantics.
Trusted project config may loosen or tighten global defaults.
### Config schema
Version one config shape:
```json
{
"defaultContext": "independent",
"defaultTools": "read-only",
"maxConcurrent": 3,
"timeouts": {
"startMs": 30000,
"idleMs": 0,
"runMs": 0
},
"ui": {
"enabled": true,
"defaultExpanded": false,
"showTranscriptMilestones": true
},
"toolProfiles": {
"local-review": {
"activeTools": ["read", "grep", "find", "ls"],
"bash": "deny"
}
}
}
```
`0` timeout values mean disabled.
Unknown config keys should be ignored with a warning, not fatal.
Invalid known values should disable the affected config file and surface a diagnostic.
### Built-in defaults
In-code defaults apply when no config file exists or a field is absent.
The in-code default context is `independent`.
The in-code default tool profile is `read-only`.
The implementation may choose an initial `maxConcurrent`, but it must be configurable.
### UI config
`ui` settings gate only the bundled optional UI components.
They must not disable the status data model, status endpoints, neutral events, or durable child records.
Another extension should be able to replace the default UI by consuming the same status data.
## Named agent definitions
Named agents are Markdown files with YAML frontmatter and a Markdown body.
They are the only durable named-agent definition format in version one.
Do not define named agents inline in `subagents.json`.
Required frontmatter:
```yaml
name: review
description: Review code and report risks.
```
Optional frontmatter:
```yaml
context: independent
model: inherit
thinking: high
tools: read-only
allowedContexts:
- independent
hidden: false
```
`name` is the canonical identity.
File names are storage only, but warn when the filename stem does not match `name`.
Names should be lowercase slugs with letters, numbers, and hyphens.
`description` is used for discovery, listing, and model-facing selection help.
The Markdown body is the base prompt or instruction text for the subagent.
### Definition precedence
Load definitions in this order:
1. Trusted project `.pi/agents/*.md`.
2. User `~/.pi/agent/agents/*.md`.
Project definitions override user definitions with the same name.
Duplicate names inside one precedence tier are configuration errors.
Do not resolve duplicates by filesystem order.
## Ad hoc runtime subagents
Version one supports ad hoc runtime subagents.
A spawn request may omit `agent` and provide only `prompt`.
This creates a one-off subagent that is not persisted as a named definition.
Ad hoc subagents inherit global and project defaults unless the spawn call overrides context, model, thinking, or tools.
Status should label ad hoc subagents with a generated short label such as `ad-hoc <child-id>`.
## Context modes
Version one supports exactly two context modes:
- `independent`.
- `fork`.
`independent` is the global default.
Parent conversation context is opt-in through `fork`.
### `independent`
`independent` receives:
- The spawn `prompt`.
- The selected named agent body if `agent` is present.
- Normal trusted project context such as `AGENTS.md`.
- Explicit attachments or snippets if the spawn request supports them later.
`independent` does not receive:
- Parent transcript.
- Generated parent summary.
- Hidden parent branch context.
### `fork`
`fork` receives the full active-branch transcript snapshot as-is.
It does not strip tool output.
It does not summarize before spawning.
It lets child Pi handle normal compaction if needed.
It appends a small wrapper that explains the delegated role, context boundary, and expected return shape.
Avoid the phrase "child agent" in user-facing text.
Prefer "subagent", "delegated agent", or "worker".
`fork` does not require special confirmation in version one.
Tool power and context inheritance are separate concerns.
### Context precedence
Resolve context mode in this order:
1. Spawn-call override.
2. Named agent frontmatter `context`.
3. Config `defaultContext`.
4. In-code default `independent`.
If a named agent has `allowedContexts`, reject a spawn that requests a context outside that list.
## Tool profiles
Agent frontmatter `tools` references a named tool profile.
Spawn calls may also override `tools` with a profile name.
Tool profiles compile to Pi active tools and optional tool-call gates.
This uses Pi-native mechanisms such as `pi.setActiveTools()` and `tool_call` blocking.
Do not build a broad permission DSL in version one.
Built-in profile names are reserved and cannot be overridden by config.
User config may add custom profiles and select the default profile.
Version-one built-in profiles:
- `none`.
- `read-only`.
- `read-only-with-safe-bash`.
- `full-tools`.
`none` has no tools.
`read-only` is local-only and includes `read`, `grep`, `find`, and `ls`.
`read-only-with-safe-bash` is local-only and adds `bash` with a read-only command allowlist.
`full-tools` means the normal full local Pi tool surface.
`full-tools` is not a sandbox permission level.
`full-tools` is not guarded by an extension confirmation prompt during the subagent run.
Version one does not restrict `full-tools` from being a global default, agent default, or spawn override.
Built-in profiles do not include web or network access except insofar as `full-tools` exposes ordinary bash.
A later `web-research` profile can be user-defined when an explicit web tool or bash-network policy exists.
Default tool profile resolution order:
1. Spawn-call override.
2. Named agent frontmatter `tools`.
3. Config `defaultTools`.
4. In-code default `read-only`.
## Model and thinking
Optional `model` can be `inherit` or a Pi model selector.
Optional `thinking` maps to Pi reasoning or effort levels such as `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.
The selected model may clamp or ignore unsupported thinking values.
Resolution order:
1. Spawn-call override.
2. Named agent frontmatter.
3. Config default if later added.
4. Parent Pi session values.
Do not require model or thinking in named definitions.
## Spawn tools
Exact tool names are intentionally deferred to implementation, but version one must expose these surfaces:
- Single spawn.
- Batch spawn.
- List subagents.
- Get subagent status.
- Get subagent result.
- Cancel subagent.
Spawn requests use a single prose field named `prompt`.
Do not split prose into `task` and `instructions`.
Single spawn request shape:
```json
{
"prompt": "Review the staged diff for rollback risks.",
"agent": "review",
"context": "independent",
"model": "inherit",
"thinking": "high",
"tools": "read-only"
}
```
`prompt` is required.
`agent` is optional.
If `agent` is present, the named definition supplies the base prompt and defaults while `prompt` supplies the per-call request.
If `agent` is absent, the spawn is ad hoc.
Batch spawn request shape:
```json
{
"subagents": [
{ "agent": "review", "prompt": "Review API risks." },
{ "prompt": "Independently sanity-check the deployment plan." }
]
}
```
Batch entries use the same shape as single spawn entries.
## Non-blocking behavior
All spawns are non-blocking in version one.
Single spawn and batch spawn return after spawn acceptance with child ids and initial metadata.
The extension must not block the parent tool call until the subagent completes.
The main agent decides whether and when to list, poll, retrieve, or cancel results.
Spawn acceptance result should include:
- Child id.
- Agent name or ad hoc label.
- Context mode.
- Tool profile.
- Model and thinking if resolved.
- Initial lifecycle state.
- Status/result retrieval hint.
## Result retrieval
Subagent results arrive through:
- Status data model.
- Neutral events.
- Durable milestone entries.
- Explicit result tool.
The parent receives final textual result plus compact metadata by default.
Metadata includes agent name, context mode, elapsed time, stop reason, and child status/session id.
Do not copy the child transcript into the parent context by default.
Do not copy selected evidence snippets into the parent context by default.
`subagent_list` should show active subagents plus bounded recent terminal history.
The default recent terminal history should be small, such as the last 10 terminal children in the current parent session.
Results and status persist through Pi session state and child session storage only in version one.
Do not write separate result files or artifact files.
## Runtime architecture
Use a `ChildRunner` interface so runtime can evolve without changing tools or status.
Version one implements `subprocess-rpc`.
An in-process SDK runner is an explicit later optimization.
Keep subprocess mode as permanent fallback.
`ChildRunner` responsibilities:
- Start a child Pi RPC process.
- Send a prompt command.
- Stream RPC events.
- Normalize lifecycle events.
- Abort or terminate the child.
- Return normalized terminal result to the supervisor.
Use Pi RPC mode instead of print mode.
RPC preserves prompt bytes, exposes events, supports `abort`, supports `get_state`, and is intended for embedding.
For `fork`, serialize the parent session header plus active branch entries to a temporary JSONL file.
Launch child Pi using that file as the starting session.
For `independent`, launch child Pi without parent session transcript.
## Supervisor architecture
The `Supervisor` is the only owner of child records, process handles, timers, event subscriptions, and lifecycle transitions.
Tool handlers must not spawn untracked child processes independently.
Lifecycle states:
- `queued`.
- `starting`.
- `running`.
- `settling`.
- `completed`.
- `failed`.
- `cancelled`.
- `timed_out`.
- `orphaned` if reload loses process ownership and no reattach protocol exists.
Use event-driven transitions.
Do not implement unbounded sleep-loop polling.
Use Pi RPC events, process lifecycle, abort signals, and bounded timers.
Use `agent_settled` as semantic completion.
Use process close for subprocess resource cleanup.
Timeouts:
- `startMs` guards process startup and prompt acceptance.
- `idleMs` guards no-progress hangs when nonzero.
- `runMs` guards total runtime when nonzero.
Timeout expiry marks the child as `timed_out` and runs the same cancellation path.
Cancellation is idempotent.
For subprocess RPC cancellation:
1. Send RPC `abort` when protocol is alive.
2. End stdin when appropriate.
3. Send SIGTERM to the process group on Unix.
4. Use `taskkill /T /F` on Windows.
5. Escalate to SIGKILL after a short grace period on Unix.
6. Resolve as `cancelled` unless a terminal result already exists.
On parent `session_shutdown`, cancel supervised children by default.
Detached persistence is out of version one.
## Status data model
Define a public status record that another extension can consume:
```typescript
interface SubagentStatus {
id: string;
label: string;
agent?: string;
adHoc: boolean;
context: "independent" | "fork";
state: "queued" | "starting" | "running" | "settling" | "completed" | "failed" | "cancelled" | "timed_out" | "orphaned";
cwd: string;
model?: string;
thinking?: string;
tools: string;
startedAt: string;
completedAt?: string;
elapsedMs: number;
lastEvent?: string;
lastEventAt?: string;
stopReason?: string;
resultAvailable: boolean;
childSession?: string;
error?: string;
}
```
Expose status through registered tools and extension-local events.
Persist durable milestone entries with `pi.appendEntry()`.
Durable status entries do not participate in LLM context.
Do not expose secrets, full environment, provider credentials, full prompts, or full child tool output in status rows.
## Optional built-in UI
The default UI is optional and replaceable.
It consumes the status data model.
It must not be required for subagent lifecycle correctness.
Use three progressive layers:
1. Collapsed live summary by default.
2. Expanded live inspector on demand or by configuration.
3. Durable transcript milestone entries for historical record.
Collapsed summary should show quick counts such as `2 running · 1 queued`.
Expanded inspector should show child id, label, context mode, lifecycle state, elapsed time, model, tool profile, trust/source, last event, and result availability.
Transcript milestones should record spawn accepted, completed, failed, cancelled, and timed out.
Do not stream every child event into the parent transcript.
UI config gates only these components.
Status tools and data remain available when UI is disabled.
## Trust and security
Project config and project agent definitions are honored only after project trust.
User/global config is in the user's local trust boundary.
The extension must not claim sandboxing.
Subagents run with the local user's permissions unless the user later routes them through an actual sandbox backend.
Do not inherit project-local extensions, project packages, or arbitrary project resources into child processes by default unless Pi's normal trusted project startup does so and the implementation explicitly documents it.
Sanitize child process environment.
Strip stale parent `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL` unless intentionally projecting parent metadata.
Pass provider credentials only as required by child Pi.
The extension does not add runtime confirmation gates for `fork` or `full-tools` in version one.
If a request is ambiguous, the main agent may ask the user before spawning.
The extension should avoid over-prescribing agent judgment.
## Diagnostics and validation
Startup or reload diagnostics should report:
- Invalid `subagents.json` syntax.
- Unknown built-in profile override attempts.
- Unknown default tool profile.
- Duplicate agent names in one precedence tier.
- Invalid frontmatter.
- Agent `context` outside `allowedContexts`.
- Unknown tool profile references.
Invalid project config should not break user/global config.
Invalid agent definitions should be skipped with diagnostics rather than crashing the extension.
## Tests and verification
Unit tests should cover:
- Config merge order.
- Project trust gating for project config and project agents.
- Agent frontmatter parsing.
- Duplicate name detection.
- Tool profile resolution.
- Built-in profile name reservation.
- Context resolution order.
- Spawn request validation.
- Non-blocking spawn acceptance result.
- Status state transitions.
- Result retrieval before and after completion.
- Cancellation idempotence.
- Timeout handling.
- Malformed RPC event handling.
- Oversized RPC line handling.
- Process exit before settlement.
- Settlement before process exit.
- Parent shutdown cleanup.
Manual verification:
```bash
nix eval .#nixosConfigurations.neogaia.config.modules.agents.pi.enable
```
```bash
nix eval .#nixosConfigurations.neogaia.config.home-manager.users.alexion.home.file.'"/home/alexion/.pi/agent/extensions"'.source
```
```bash
nix flake check
```
After implementation, verify inside Pi:
- `/reload` loads the extension.
- A single ad hoc subagent spawn returns a child id immediately.
- A batch spawn returns multiple child ids immediately.
- `subagent_list` shows active and recent terminal entries.
- `subagent_status` shows current lifecycle state.
- `subagent_result` returns still-running before completion and final result after completion.
- `subagent_cancel` cancels a running child.
- A `fork` run receives parent active-branch context.
- An `independent` run does not receive parent transcript.
- Disabling UI does not disable status/result tools.
## Open implementation choices left to coding
Choose exact tool names in the implementation.
Choose exact JSON schema names for timeout fields and UI toggles.
Choose exact read-only bash allowlist for `read-only-with-safe-bash`, using Pi plan-mode as the reference.
Choose the default `maxConcurrent` value.
Choose final status entry custom type names.
These are implementation details, not remaining design blockers.

View File

@@ -0,0 +1,187 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T21:10:49-04:00"
completed-at: "2026-08-01T02:08:00-04:00"
parent: "[[021-pi-subagents-config-boundary-grill]]"
blocked-by: []
tags:
- ticket/research
---
# Agent definition conventions research
## Question
What conventions do Pi subagent extensions and other coding-agent harnesses such as Claude Code, Antigravity, OpenCode, and adjacent tools use for named subagent or agent definition files, including location, frontmatter fields, body semantics, project/user precedence, and trust gating?
## Answer
The strongest shared convention is Markdown files with YAML frontmatter for metadata and a Markdown body for the agent's prompt or instructions.
Claude Code, OpenCode, Pi skills, and the Agent Skills specification all use that split, although OpenCode also supports JSON config and Pi skills are not subagents.
Claude Code and OpenCode both make the description field operational by using it for automatic delegation or task selection.
Claude Code uses an explicit `name` frontmatter field as identity, while OpenCode derives the agent name from the Markdown filename.
For Pi subagents, the safest neutral schema is therefore a Markdown file with frontmatter `name`, `description`, and optional runtime policy fields, with the body used only as the child system/developer instruction text.
The recommended locations for the Pi extension are `~/.pi/agent/agents/*.md` for user-level definitions and `.pi/agents/*.md` for project-level definitions.
This mirrors Pi's own user/project split for skills while avoiding `.agents/` unless cross-harness sharing becomes an explicit requirement.
Project definitions should load only after Pi's existing project trust gate approves the workspace.
If project and user definitions share a `name`, project definitions should override user definitions for that project, because project-specific agent prompts are the likely local intent.
Duplicate names within the same precedence tier should be reported as configuration errors rather than resolved by filesystem order.
## Findings
### Claude Code
Claude Code custom subagents are Markdown files with YAML frontmatter followed by a Markdown system prompt body.
The docs state that subagents run in their own context window, use a custom system prompt, can have specific tool access, and return results to the parent conversation.
Source: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md>.
Claude Code supports project-level `.claude/agents/` and user-level `~/.claude/agents/` definitions.
It also supports definitions passed through the `--agents` CLI flag, managed settings definitions, and plugin `agents/` directories.
The documented priority order places `--agents` highest, managed policies next, project definitions next, user definitions next, and plugin definitions lowest.
Source: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md#choose-the-subagent-scope>.
Claude Code discovers nested `.claude/agents/` directories by walking from the current working directory toward the repository root.
When nested project definitions share a name, the closest definition wins.
Within one scanned directory tree, duplicate names have no useful semantic distinction and Claude Code warns that filesystem read order decides which one loads.
Source: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md#choose-the-subagent-scope>.
Claude Code requires `name` and `description` in frontmatter.
It supports optional fields including `prompt`, `tools`, `disallowedTools`, `model`, `permissionMode`, `mcpServers`, `hooks`, `maxTurns`, `skills`, `initialPrompt`, `memory`, `effort`, `background`, `isolation`, and `color`.
The file body is equivalent to the `prompt` field for file-based subagents.
Source: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md#supported-frontmatter-fields>.
Claude Code treats `description` as delegation metadata.
The docs say Claude uses each subagent's description to decide when to delegate tasks, and recommend clear descriptions for proactive delegation.
Source: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md#understand-automatic-delegation>.
Claude Code has trust gating for project-level subagent hooks.
Project subagents still run before trust, but frontmatter hooks are skipped until the containing folder is trusted.
Source: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md#define-hooks-for-subagents>.
Claude Code also distinguishes subagent context from fully independent parallel sessions.
Its docs say subagents work within a single session and direct readers to background agents or agent teams for many independent sessions.
Source: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md>.
### OpenCode
OpenCode supports both JSON agent config in `opencode.json` and Markdown agent files.
Markdown agents live in `~/.config/opencode/agents/` globally and `.opencode/agents/` per project.
The Markdown filename becomes the agent name.
Source: <https://opencode.ai/docs/agents>.
OpenCode frontmatter uses fields such as `description`, `mode`, `model`, `temperature`, `permission`, `prompt`, `tools`, `hidden`, `color`, and provider-specific pass-through options.
Its `mode` can be `primary`, `subagent`, or `all`, with `all` as the default when omitted.
Source: <https://opencode.ai/docs/agents>.
OpenCode body semantics match the custom prompt pattern.
The Markdown example places YAML metadata first and then freeform instructions such as "You are in code review mode" in the body.
OpenCode also supports a `prompt` config field pointing at a custom system prompt file, with the path relative to the config file.
Source: <https://opencode.ai/docs/agents>.
OpenCode separates primary agents from subagents.
Primary agents handle the main conversation and can be switched with Tab, while subagents are invoked by primary agents or manually with `@` mentions.
Source: <https://opencode.ai/docs/agents>.
OpenCode exposes child-session navigation for subagents.
Its docs say subagents create child sessions and users can navigate from the parent to child sessions with `session_child_first` and related keybinds.
Source: <https://opencode.ai/docs/agents>.
OpenCode has permission controls that are both global and per-agent.
It supports `permission` entries such as edit, bash, webfetch, external directory access, and task invocation allow or deny patterns.
Source: <https://opencode.ai/docs/agents#permissions>.
I did not find an explicit OpenCode workspace trust gate in the agent docs section fetched for this research.
That is an evidence gap rather than evidence that no trust gate exists elsewhere in OpenCode.
### Pi and Agent Skills conventions
Pi's documented skill discovery uses global `~/.pi/agent/skills/` and `~/.agents/skills/`, project `.pi/skills/` and `.agents/skills/`, package `skills/` directories, settings `skills`, and CLI `--skill` paths.
Project skills load only after the project is trusted.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/skills.md`.
Pi skills use a directory with `SKILL.md` or supported direct `.md` files in some locations.
`SKILL.md` contains YAML frontmatter followed by instructions, with required `name` and `description` fields.
Pi says it implements the Agent Skills standard leniently.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/skills.md`.
The Agent Skills specification requires a `SKILL.md` file with YAML frontmatter and Markdown content.
It requires `name` and `description`, allows optional `license`, and says the Markdown body contains unrestricted skill instructions.
Source: <https://agentskills.io/specification>.
Pi skills are not named subagent definitions, but their discovery, trust, and progressive-disclosure shape is the closest native Pi precedent.
That makes `.pi/agents/` and `~/.pi/agent/agents/` a more Pi-native choice than copying `.claude/agents/` or `.opencode/agents/` directly.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/skills.md`.
### Antigravity
I attempted to fetch Antigravity documentation at `https://antigravity.google.com/docs/agents` and related Markdown URLs.
The page was served as a JavaScript application and the fetched source did not expose useful static text about custom agent definition files, frontmatter, precedence, or trust behavior.
The related guessed Markdown endpoints did not return usable Markdown documentation.
Source attempted: <https://antigravity.google.com/docs/agents>.
No primary Antigravity source available in this session established a named custom agent file convention.
Do not use Antigravity as a basis for Pi config schema until a primary doc, local installed product docs, or source artifact can be inspected.
### Adjacent tool patterns
The adjacent reusable-package pattern is the Agent Skills standard rather than subagent definitions.
It reinforces the `name` plus `description` frontmatter convention and the separation between startup metadata and body instructions.
Source: <https://agentskills.io/specification>.
Firstmate and related local prototypes inspected earlier use shell/backend orchestration patterns rather than a stable named-agent Markdown schema.
They are useful for process spawning and Herdr integration ideas, but not as schema authorities for Pi subagent definitions.
Source: `/tmp/firstmate-research/firstmate/README.md` and `/tmp/firstmate-research/shipmates/plugin-guide.md`.
## Recommendation for Pi subagents
Use Markdown definitions with YAML frontmatter and a Markdown body.
Require `name` and `description`.
Use `name` as canonical identity instead of deriving identity from the filename, because this matches Claude Code and Agent Skills and avoids rename churn when files are reorganized.
Require names to be lowercase slugs with letters, numbers, and hyphens.
Treat filenames as storage only, but warn when the filename stem does not match `name` because mismatches are easy to overlook.
Make the Markdown body the child instruction prompt.
Do not let the body define runtime, lifecycle, or permission policy implicitly.
Keep runtime and permission policy in typed frontmatter or Pi settings so the extension can validate it before launch.
Start with this minimal neutral frontmatter surface:
```yaml
name: review
description: Review recent changes and report risks without editing files.
model: inherit
context: fork
permissions:
tools:
read: allow
write: deny
hidden: false
color: blue
```
Treat `model`, `context`, `permissions`, `hidden`, and `color` as optional extension fields.
Do not bundle built-in named agent types in the extension.
Let users define these Markdown files in Pi config.
Resolve definitions in this order:
1. Explicit invocation object passed at spawn time.
2. Project `.pi/agents/` definitions from the trusted workspace, with nearest nested directory winning if nested support is implemented.
3. User `~/.pi/agent/agents/` definitions.
4. Package-provided definitions only if the user later enables a package source explicitly.
Reject duplicate names within the same directory tree with a diagnostic.
Do not silently choose by filesystem order.
For trust, load user definitions without a project trust prompt because the user controls their home Pi config.
Load project definitions only when the workspace is trusted.
Do not run project-defined lifecycle hooks, commands, MCP server declarations, or other active policy from an untrusted project.
If read-only project prompts are ever surfaced before trust, label them untrusted and require confirmation before spawning.
## Limitations
Antigravity findings are limited by lack of accessible static primary documentation in this session.
OpenCode agent docs provided locations and schema details, but this research did not separately inspect OpenCode source code for loader precedence or trust behavior.
Claude Code's documentation is unusually detailed and should not be copied wholesale into Pi, because its schema includes many Claude-specific concepts such as `permissionMode`, `memory`, and `isolation: worktree`.

View File

@@ -0,0 +1,128 @@
---
status: done
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-07-31T22:18:42-04:00"
completed-at: "2026-07-31T22:19:18-04:00"
parent: "[[021-pi-subagents-config-boundary-grill]]"
blocked-by:
- "[[021-pi-subagents-config-boundary-grill]]"
tags:
- ticket/task/afk
---
# Pi subagents Nix config seam
## Question
After the subagent configuration schema is settled, what Nix/Home Manager seam should deploy `subagents.json`, managed user agent definitions, and any related defaults without making the neutral extension Nix-aware?
## Result
Detailed dotfiles module option design is out of scope for the subagent extension specification.
This repository's Pi module can later decide whether to link plain files, render JSON from Nix attrs, or expose typed `modules.agents.pi.subagents` options.
The implementation-ready extension spec should only require stable runtime file paths and should not prescribe the dotfiles module's internal interface.
Keep the extension Nix-unaware.
The extension reads Pi-native runtime files:
- Global extension config: `~/.pi/agent/subagents.json`.
- Trusted project extension config: `.pi/subagents.json` through Pi's `CONFIG_DIR_NAME`.
- Global named agent definitions: `~/.pi/agent/agents/*.md`.
- Trusted project named agent definitions: `.pi/agents/*.md` through Pi's `CONFIG_DIR_NAME`.
The dotfiles module may choose to manage the global files declaratively, but the extension should not know or care whether they came from Home Manager, direct user edits, or another deployment tool.
This matches the configuration boundary from [[021-pi-subagents-config-boundary-grill]].
Do not create or manage `~/.pi/agent/subagents.json` until the user has actual overrides to declare.
The extension has in-code neutral defaults and must not write a default config file automatically.
A missing `subagents.json` is therefore a valid, expected state.
When global overrides are wanted, the dotfiles Pi module may manage the runtime JSON file however the module owner prefers.
A plain source file such as `modules/agents/pi/subagents.json` is a simple option, but it is not mandated.
Rendering the JSON from Nix attrs or adding typed module options is a dotfiles-module decision, not an extension-spec decision.
Do not make any particular Nix option interface a prerequisite for version one.
Do not link `~/.pi/agent/agents` until there are durable user agent definitions to manage.
An empty Home Manager-managed agent directory would make direct local experiments under `~/.pi/agent/agents` awkward, because Home Manager would own the path.
Until durable agent definitions exist, leave the directory unmanaged so the user can create throwaway local agents freely.
When durable agent definitions are added, create:
```text
modules/agents/pi/agents/
```
and link it with:
```nix
"${piDir}/agents" = {
source = ./agents;
recursive = true;
};
```
The first managed `agents/` rollout should include only user-intended Markdown agent definitions.
Do not add opinionated bundled agents as part of the neutral extension.
## Current module implications
`modules/agents/pi/pi.nix` already manages `~/.pi/agent/settings.json`, `~/.pi/agent/extensions`, and `~/.pi/agent/prompts`.
It intentionally leaves login credential state unmanaged.
Source: `modules/agents/pi/pi.nix`.
The implementation spec should extend that module only when there is an actual file or directory to deploy.
The extension code itself should still live under:
```text
modules/agents/pi/extensions/subagents/
```
and the existing recursive extension link will deploy it.
No package installation or `pi install` path is needed for version one.
## Recommended version-one Nix stance
Only the deployment paths are in scope here:
- `modules/agents/pi/extensions/subagents/` for the extension implementation.
- `~/.pi/agent/subagents.json` as the optional runtime config target.
- `~/.pi/agent/agents/*.md` as the optional global named-agent target.
Avoid these in the extension specification:
- Prescribing typed `modules.agents.pi.subagents.*` options.
- Prescribing a plain-file versus generated-json module implementation.
- Requiring a generated default `subagents.json` when no overrides exist.
- Requiring an empty managed `~/.pi/agent/agents` directory.
- Nix-aware logic in the extension.
- `pi install` or package-manager-managed Pi packages.
## Verification commands
Before implementation, existing checks still apply:
```bash
nix eval .#nixosConfigurations.neogaia.config.modules.agents.pi.enable
```
Expected result: `true`.
```bash
nix eval .#nixosConfigurations.neogaia.config.home-manager.users.alexion.home.file.'"/home/alexion/.pi/agent/extensions"'.source
```
Expected result: a Nix store path sourced from `modules/agents/pi/extensions`.
If the dotfiles module later manages `subagents.json` or `agents/`, verify the resulting Home Manager file entries with targeted `nix eval` commands chosen for that module implementation.
The exact attr paths depend on whether the module uses plain file links, generated JSON, or typed options, so they are intentionally left to that later dotfiles-module work.
Before merging any implementation, run the repository's primary verification seam:
```bash
nix flake check
```
## Implementation-spec notes
The implementation spec should state that missing global config and missing global agent directory are normal.
The extension should create neither automatically.
The extension may expose an explicit user-command to print or write a starter config later, but only after the user requests it.

View File

@@ -0,0 +1,88 @@
---
parent: "[[002-pi-subagents-map]]"
tags:
- ticket/research
---
# Herdr Pi integration Nix-pure deployment research
## Question
Can the Herdr Pi integration be installed declaratively through Nix/Home Manager without vendoring the generated Pi extension file by hand?
## Findings
Herdr exposes first-party integration management through the `herdr integration` command group.
`herdr --help` lists `herdr integration <subcommand>` as the built-in interface for managing agent integrations, and `herdr integration install --help` says the install command takes a single target argument whose possible values include `pi`.
On this host, `herdr --version` reports `herdr 0.7.5`.
The Pi integration installs a Pi-side extension file, not a Herdr config file.
`herdr integration status` reported `pi: not installed (/home/alexion/.pi/agent/extensions/herdr-agent-state.ts)` before installation, and `herdr integration install pi` reported `installed pi integration to /home/alexion/.pi/agent/extensions/herdr-agent-state.ts`.
After installation, `herdr integration status` reported `pi: current (v6) (/home/alexion/.pi/agent/extensions/herdr-agent-state.ts)`.
The generated file begins with Herdr-owned metadata: `HERDR_INTEGRATION_ID=pi` and `HERDR_INTEGRATION_VERSION=6`.
The installer does not create the Pi extension directory.
With a temporary `HOME` and no `~/.pi/agent/extensions`, `herdr integration install pi` failed with `pi extension directory not found at .../.pi/agent/extensions. install pi first`.
After creating that directory in the temporary home, the same command succeeded and wrote `herdr-agent-state.ts`.
This matters for Nix because the derivation or activation code must provide a fake Pi home layout before invoking the installer.
The installer can run in a Nix build derivation on this machine.
A test derivation using `pkgs.stdenvNoCC.mkDerivation`, `nativeBuildInputs = [ pkgs.herdr ]`, a fake `$TMPDIR/home/.pi/agent/extensions`, and `HOME=$TMPDIR/home herdr integration install pi` built successfully and copied the generated file to `$out/herdr-agent-state.ts`.
The generated store file was root-owned and read-only, as expected for a Nix build output.
Its SHA-256 matched the file produced by the imperative install in the real home: `12efd27592fbf185343f035ee4fd2b1999e9356e323e4b01225f7d6bc89b16de` for both files.
Therefore a Nix-pure deployment is feasible in this repository without manually vendoring the generated file.
The dotfiles module can create a small derivation that runs Herdr's own installer into a fake home and then expose the generated `herdr-agent-state.ts` as a Home Manager-managed Pi extension.
This keeps the generated adapter tied to the pinned `pkgs.herdr` package and avoids a stale checked-in copy.
## Recommended declarative shape
Keep the extension deployment in the Pi module because the runtime artifact is a Pi extension file:
```nix
let
herdrPiIntegration = pkgs.stdenvNoCC.mkDerivation {
name = "herdr-pi-integration";
nativeBuildInputs = [ pkgs.herdr ];
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $TMPDIR/home/.pi/agent/extensions
HOME=$TMPDIR/home herdr integration install pi
mkdir -p $out
cp $TMPDIR/home/.pi/agent/extensions/herdr-agent-state.ts $out/herdr-agent-state.ts
'';
};
in {
home-manager.users.${user}.home.file."${piDir}/extensions/herdr-agent-state.ts".source =
"${herdrPiIntegration}/herdr-agent-state.ts";
}
```
This uses Herdr as the source of truth for its adapter while leaving Pi to load the resulting file through its normal extension directory.
It should not require `herdr integration install pi` during activation.
It also avoids installing into `~/.pi/agent/extensions` imperatively, which is important because this repo already manages Pi extension deployment declaratively.
A slightly more structured version could package the generated file as `pkgs.herdr-pi-integration` in an overlay or local package helper if more modules need it.
For a single file used only by `modules/agents/pi/pi.nix`, an inline derivation is enough.
## Caveats
The build-time test establishes that Herdr 0.7.5's Pi installer can run in a Nix derivation on this host.
It does not prove future Herdr versions will remain build-sandbox friendly.
If a future installer starts requiring network access, a running Herdr server, or writable global config, the derivation will fail and reveal that at build time.
The generated file says it is "managed by herdr" and can be overwritten by reinstalling or updating the integration.
When Nix generates the file, the practical manager is the Nix derivation, but the content still belongs to Herdr.
Do not edit the generated TypeScript by hand.
The current direct install under `~/.pi/agent/extensions/herdr-agent-state.ts` is not the final declarative state.
A later implementation should either remove that unmanaged file or let Home Manager replace it with the generated store-backed file.
## Citations
- `herdr --help` on this host lists `herdr integration <subcommand>` as the interface for managing built-in agent integrations and reports config/log paths.
- `herdr integration install --help` on this host defines `install <TARGET>` and lists `pi` among supported targets.
- `herdr integration status` on this host reported the Pi integration path and current installed state before and after installation.
- `herdr integration install pi` on this host wrote `/home/alexion/.pi/agent/extensions/herdr-agent-state.ts` and reported success.
- Temporary-home installer test: `HOME=$(mktemp -d)` without `.pi/agent/extensions` failed with the missing-directory diagnostic, and the same command succeeded after creating `.pi/agent/extensions`.
- Nix derivation test at `/tmp/herdr-pi-integration-test.nix` built successfully with `nix build --impure --no-link --print-out-paths --file /tmp/herdr-pi-integration-test.nix` and generated `/nix/store/9qnkkqkv8f3smm09n4rzshwh961fbj9h-herdr-pi-integration-test/herdr-agent-state.ts`.

View File

@@ -0,0 +1,40 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-08-01T13:40:33-04:00"
completed-at: "2026-08-01T13:55:13-04:00"
parent: "[[027-pi-subagents-implementation-spec-task]]"
blocked-by: []
tags:
- ticket/task/afk
---
# Create the minimal subagent extension tracer bullet
## Question
Build a loadable neutral Pi extension that can start one ad hoc independent subagent non-blockingly, track it through the supervisor, and expose basic list, status, and result surfaces for that child.
## What to build
Create the narrowest end-to-end path for the subagent extension.
A prompt-only spawn should create an ad hoc worker in independent context, return a child id immediately, track lifecycle state through a supervisor, and let the parent inspect status and retrieve the final result later.
This slice should establish the extension skeleton, the child runner boundary, the initial status record shape, and the basic tool/command surfaces needed to prove the loop works.
## Acceptance criteria
- [x] `/reload` loads the extension from the managed Pi extensions directory.
- [x] A spawn call with only `prompt` returns a child id immediately.
- [x] The child runs in `independent` mode without parent transcript context.
- [x] Status transitions are visible from accepted through terminal state.
- [x] Result retrieval returns still-running before completion and the final answer after completion.
## Implementation Notes
Use subprocess RPC for the first runner implementation.
Keep exact public tool names consistent with the spec, but they may be finalized while coding.
Resolved in branch `pi-subagents-tracer-bullet`, commit `fdf0f89`.
Implemented a managed `subagents` extension skeleton with `subagent_spawn`, `subagent_list`, `subagent_status`, `subagent_result`, and `subagent_cancel` tool surfaces plus slash-command smoke surfaces.
The tracer bullet intentionally records `tools: "pi-default"` because actual tool-profile enforcement belongs to [[048-pi-subagents-config-agents-tool-profiles-task]].
Verified managed extension loading through a temporary `PI_CODING_AGENT_DIR`, live Pi RPC spawn/result behavior, extension derivation build, and `nix flake check`.

View File

@@ -0,0 +1,33 @@
---
status: open
parent: "[[027-pi-subagents-implementation-spec-task]]"
blocked-by:
- "[[046-pi-subagents-minimal-tracer-bullet-task]]"
tags:
- ticket/task/afk
---
# Add cancellation, timeout, and shutdown lifecycle controls
## Question
Extend the supervisor so cancellation, timeouts, process failures, and parent shutdown cleanup use the same tracked lifecycle path without leaking child processes.
## What to build
Make child lifecycle robust after the minimal spawn path exists.
The supervisor should own cancellation, startup and runtime timeout behavior, process failure handling, and shutdown cleanup.
Cancellation must be idempotent and should cooperate with Pi RPC before escalating to process-tree termination.
## Acceptance criteria
- [ ] Cancelling a running subagent is idempotent and reaches `cancelled`.
- [ ] Startup and runtime timeout paths reach `timed_out`.
- [ ] Child process exit before semantic settlement reaches a failure state with diagnostics.
- [ ] Parent session shutdown cancels supervised children.
- [ ] Lifecycle tests cover abort, process close, timeout, and repeated cancel calls.
## Implementation Notes
Use `agent_settled` as semantic completion.
Use process close for resource cleanup after settlement.

View File

@@ -0,0 +1,34 @@
---
status: open
parent: "[[027-pi-subagents-implementation-spec-task]]"
blocked-by:
- "[[046-pi-subagents-minimal-tracer-bullet-task]]"
tags:
- ticket/task/afk
---
# Support config files, named agents, and tool profiles
## Question
Implement config loading, Markdown named agents, defaults, diagnostics, and tool profile resolution so named subagent spawns work end to end.
## What to build
Add the configuration boundary around the minimal spawn path.
The extension should accept absent global and project config as normal, load trusted project configuration after global configuration, load Markdown named agents from user and trusted project locations, and resolve spawn settings from overrides, frontmatter, config, and in-code defaults.
Tool profiles should include the reserved built-ins and user-defined custom profiles, while preserving diagnostics for invalid input.
## Acceptance criteria
- [ ] Missing config files and missing agent directories are accepted as normal.
- [ ] Global config and trusted project config merge in the specified order.
- [ ] Markdown agent definitions load from user and trusted project paths with correct precedence.
- [ ] Duplicate definitions in one tier and invalid frontmatter produce diagnostics without crashing startup.
- [ ] A named spawn resolves prompt, context, model, thinking, and tools from spawn overrides, frontmatter, config, and in-code defaults.
- [ ] Built-in tool profile names cannot be overridden.
## Implementation Notes
Do not write starter config files.
Do not define named agents inline in `subagents.json`.

View File

@@ -0,0 +1,33 @@
---
status: open
parent: "[[027-pi-subagents-implementation-spec-task]]"
blocked-by:
- "[[046-pi-subagents-minimal-tracer-bullet-task]]"
tags:
- ticket/task/afk
---
# Add batch spawning and bounded concurrency
## Question
Add batch spawn support that accepts multiple subagent requests, returns child ids immediately, and runs all accepted children through the same supervisor with configurable concurrency.
## What to build
Extend the non-blocking spawn path from one child to many children.
Batch entries should use the same request semantics as single spawn entries.
The supervisor should preserve accepted child records, report per-child spawn failures, and enforce a configurable concurrency limit without hiding queued work from status surfaces.
## Acceptance criteria
- [ ] Batch spawn validates every entry with the same rules as single spawn.
- [ ] A batch request returns accepted child ids and initial metadata without waiting for completion.
- [ ] `subagent_list` shows active children and a bounded recent terminal history.
- [ ] `maxConcurrent` limits simultaneous running children while preserving queued records.
- [ ] Partial spawn failures are reported per requested child without losing accepted children.
## Implementation Notes
All spawns remain non-blocking.
Do not add a wait-mode parameter in this slice.

View File

@@ -0,0 +1,34 @@
---
status: open
parent: "[[027-pi-subagents-implementation-spec-task]]"
blocked-by:
- "[[046-pi-subagents-minimal-tracer-bullet-task]]"
tags:
- ticket/task/afk
---
# Implement fork context mode
## Question
Add fork context mode so a spawn can give the worker the parent active-branch transcript snapshot and delegated-role wrapper while independent context remains clean by default.
## What to build
Implement the second version-one context mode.
A forked worker should start from the active branch session snapshot and receive a small delegated-role wrapper with the per-call prompt.
Independent workers should remain transcript-clean.
Named agents that declare `allowedContexts` should reject disallowed spawn overrides.
## Acceptance criteria
- [ ] `fork` serializes the parent session header and active branch entries into a child-startable session.
- [ ] The forked worker receives the parent active-branch context plus the delegated request wrapper.
- [ ] `independent` workers still do not receive parent transcript context.
- [ ] `allowedContexts` rejects disallowed context overrides.
- [ ] Tests or manual checks distinguish forked and independent context visibility.
## Implementation Notes
Do not summarize, strip tool output, or compact before spawning.
Let child Pi handle normal compaction.

View File

@@ -0,0 +1,33 @@
---
status: open
parent: "[[027-pi-subagents-implementation-spec-task]]"
blocked-by:
- "[[046-pi-subagents-minimal-tracer-bullet-task]]"
tags:
- ticket/task/afk
---
# Add durable status milestones and optional Pi-native status UI
## Question
Connect the public status model to durable milestone entries and an optional Pi-native status UI without making the UI required for status or result retrieval.
## What to build
Add the presentation layer around the existing status data model.
The extension should append durable lifecycle milestones, show a collapsed live summary by default, offer an expanded inspector, and keep the UI replaceable by another extension.
Disabling the bundled UI should not disable status records, status events, or tools.
## Acceptance criteria
- [ ] Spawn accepted, completed, failed, cancelled, and timed-out milestones are appended as durable entries.
- [ ] Milestone entries do not inject child transcripts into normal LLM context.
- [ ] The collapsed UI summary shows live counts.
- [ ] The expanded inspector shows child id, label, context, state, elapsed time, model, tools, last event, and result availability.
- [ ] Disabling `ui` hides bundled UI components but leaves list, status, result, and cancel tools working.
## Implementation Notes
Use the status data model as the source of truth.
Do not stream every child event into the parent transcript.

View File

@@ -0,0 +1,37 @@
---
status: open
parent: "[[027-pi-subagents-implementation-spec-task]]"
blocked-by:
- "[[047-pi-subagents-lifecycle-controls-task]]"
- "[[048-pi-subagents-config-agents-tool-profiles-task]]"
- "[[049-pi-subagents-batch-concurrency-task]]"
- "[[050-pi-subagents-fork-context-task]]"
- "[[051-pi-subagents-status-ui-task]]"
tags:
- ticket/task/afk
---
# Finalize deployment and verification for the subagent extension
## Question
Wire the completed subagent extension through the existing dotfiles Pi module path and record a final verification pass across Nix, reload, spawning, status, results, cancellation, context modes, and UI toggling.
## What to build
Finish the implementation as a deployed feature rather than a collection of working slices.
The managed Pi extensions source should contain the complete extension, Nix evaluation should prove the deployment seam, and the manual verification checklist from the implementation spec should be exercised and recorded.
Any intentionally deferred choices should be written down as follow-up scope.
## Acceptance criteria
- [ ] The managed Pi extensions source includes the subagent extension.
- [ ] `nix flake check` passes.
- [ ] Targeted `nix eval` confirms Pi is enabled and the managed extensions path is present.
- [ ] Manual Pi checks from the spec are recorded in the task notes.
- [ ] Any intentionally deferred implementation choices are documented as follow-up scope, not hidden TODOs.
## Implementation Notes
This is the final integration slice.
Do not start it until the prerequisite behavior slices are complete.

View File

@@ -0,0 +1,47 @@
---
status: open
tags:
- wayfinder/map
---
# Pi UI customization
## Destination
Decide and specify a Pi TUI customization that reduces prompt-area dead space, consolidates footer information above the text prompt, represents context-window usage as a multi-colored bar, and exposes weekly ChatGPT Codex quota information if a reliable source exists.
## Notes
Plan first and preserve implementation for a later handoff unless a prototype ticket explicitly asks for throwaway local experimentation.
Prefer Pi extension APIs over patching Pi itself.
Finished customizations must be promoted through dotfiles rather than left as unmanaged files under `~/.pi/agent/extensions`.
The status bar should consolidate directory and branch, context-window usage, model, and thinking level.
The context-window bar should show total usage and, while under 90%, distinguish token categories when Pi exposes enough data.
Quota display must rely on an explicit API, local account source, or documented observable signal rather than scraping guesses.
## Frontier
- [[068-pi-ui-compact-status-extension-task]]
- [[070-pi-ui-flex-spacer-pi-patch-task]]
## Decisions so far
Pi extensions can replace the built-in footer and place a widget above the editor, so the compact prompt status idea can be prototyped without patching Pi.
Pi exposes total context-window usage through `ctx.getContextUsage()` and cumulative usage categories through session entries, but it does not expose a public exact breakdown of current context-window occupancy by content type.
Pi's docs and installed OpenAI Codex provider do not expose a documented proactive quota API, but third-party tools and OpenAI Codex source show a local first-party quota mechanism: ChatGPT/Codex usage endpoints plus Codex app-server `account/rateLimits/read` fallback.
The compact status prototype's preferred visual direction is above-prompt status with hidden footer, a visual directory/branch indicator, a thin full-width context bar, no context numbers, and the model/thinking label on the right.
The remaining prompt dead space is specifically an underfilled-stack issue: when transcript content is tall enough, the editor already reaches the bottom and looks good.
The prototype target is therefore a flexible spacer above the prompt/status/editor area, not a wholesale editor relocation.
The flex-spacer prototype received a positive HITL verdict and should be the preferred permanent layout direction.
Existing public prior art supports the patch direction: `pi-powerline-footer` shows the best extension-only compact status pattern, while `pi-local-mods` implements a private `FixedBottomScrollLayout` patch close to the desired bottom-pinned editor behavior.
## Not yet specified
The quota display prototype received a positive HITL verdict.
The permanent specification is complete in [[063-pi-ui-customization-spec-task]].
The implementation frontier includes [[068-pi-ui-compact-status-extension-task]].
The Pi patch implementation packaging was validated by [[073-pi-ui-community-pi-packaging-research]], which supports the package-override plan in [[072-pi-ui-patched-pi-packaging-research]].
## Out of scope
Replacing Pi's whole TUI or maintaining a fork of Pi is outside this effort unless research proves extension APIs cannot affect the target area at all.

View File

@@ -0,0 +1,79 @@
---
status: resolved
parent: "[[057-pi-ui-customization-map]]"
blocked-by: []
resolved-at: "2026-07-31T23:58:11-04:00"
tags:
- ticket/research
---
# Pi TUI layout customization research
## Question
What can Pi extensions change about the prompt-area layout, footer, widgets above or below the editor, working indicator, and editor chrome, and can the current below-prompt information be consolidated into a status bar above the text prompt without patching Pi itself?
## Findings
Pi extensions can replace the built-in footer without patching Pi.
The TUI docs describe `ctx.ui.setFooter((tui, theme, footerData) => component)` as the custom-footer API and state that it replaces the footer, while `ctx.ui.setFooter(undefined)` restores the built-in footer.
The implementation confirms the replacement behavior: `setExtensionFooter` removes either the existing custom footer or built-in footer from the UI, creates the custom footer from the factory, and adds it to the UI.
The same implementation restores the built-in footer when the factory is undefined.
Sources: `docs/tui.md` section “Pattern 6: Custom Footer”; `docs/extensions.md` section “Widgets, Status, and Footer”; `dist/modes/interactive/interactive-mode.js` `setExtensionFooter`.
Pi extensions can add persistent widgets above the editor or below the editor.
The documented `ctx.ui.setWidget("my-widget", ["Line 1", "Line 2"])` call places a widget above the editor by default, and `ctx.ui.setWidget(..., { placement: "belowEditor" })` places it below the editor.
The shipped `widget-placement.ts` example uses exactly those two calls on `session_start`.
This gives an extension-supported way to put a custom status bar directly above the text prompt.
Sources: `docs/tui.md` section “Pattern 5: Widgets Above/Below Editor”; `docs/extensions.md` section “Widgets, Status, and Footer”; `examples/extensions/widget-placement.ts`.
Pi extensions can customize the working indicator and working visibility.
The docs expose `ctx.ui.setWorkingMessage`, `ctx.ui.setWorkingVisible`, and `ctx.ui.setWorkingIndicator`.
This can reduce or alter the streaming “working” chrome, but it only affects the streaming loader row and indicator, not the entire prompt layout.
Sources: `docs/extensions.md` section “Widgets, Status, and Footer”; `docs/tui.md` section “Pattern 4b: Working Indicator Customization”; `examples/extensions/working-indicator.ts`.
Pi extensions can replace the editor component, but that is a more invasive path.
The TUI docs describe a `CustomEditor` pattern and advise extending `CustomEditor` rather than the base `Editor` to preserve app keybindings such as escape-to-abort, ctrl-d, and model switching.
The extensions docs list `modal-editor.ts` as the example for `setEditorComponent`.
The implementation exposes `setEditorComponent` and `getEditorComponent` in the extension UI context.
This means editor replacement is possible if footer plus above-editor widget does not remove enough dead space, but it should not be the first prototype.
Sources: `docs/tui.md` section “Pattern 7: Custom Editor”; `docs/extensions.md` examples reference; `dist/modes/interactive/interactive-mode.js` extension UI context.
Pi has a `setHeader` API in the implementation and a shipped `custom-header.ts` example, but the docs describe it as replacing the startup header rather than the prompt-area footer.
It is not the right primary hook for moving footer information above the prompt.
Sources: `examples/extensions/custom-header.ts`; `docs/extensions.md` examples reference; `dist/modes/interactive/interactive-mode.js` `setExtensionHeader`.
The built-in footer currently owns exactly the information the user wants to consolidate: cwd plus branch and session name, session usage totals, context usage, model, thinking level, and extension statuses.
The implementation constructs a `pwdLine`, a stats/model line, and an optional extension-status line.
The footer data provider exposes git branch and extension statuses to custom footers, while token stats and model info are expected to come from the session context and model.
Sources: `dist/modes/interactive/components/footer.js`; `dist/core/footer-data-provider.js`; `examples/extensions/custom-footer.ts`.
## Answer
Yes, the target customization can be prototyped without patching Pi.
The most promising extension-only design is:
1. Replace the built-in footer with a minimal or empty custom footer to remove below-prompt lines.
2. Add a one-line widget above the editor to show cwd, branch, context usage, model, and thinking level.
3. Customize or hide the working indicator only if the working row contributes meaningful dead space during streaming.
4. Avoid editor replacement unless the footer-plus-widget prototype proves insufficient.
## Limitations
The docs and implementation establish that a widget can be placed above the editor and that the footer can be replaced.
They do not prove the exact visual result will feel good in the live TUI.
That needs the HITL prototype ticket.
The footer APIs can replace the footer, but they do not literally move the built-in footer component above the editor.
The extension must recreate the desired data presentation in its own widget or custom footer.
## Citations
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`, sections “Pattern 5: Widgets Above/Below Editor”, “Pattern 6: Custom Footer”, and “Pattern 7: Custom Editor”.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`, section “Widgets, Status, and Footer” and examples reference table.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/widget-placement.ts`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/custom-footer.ts`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/custom-header.ts`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/components/footer.js`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/core/footer-data-provider.js`.

View File

@@ -0,0 +1,81 @@
---
status: resolved
parent: "[[057-pi-ui-customization-map]]"
blocked-by: []
resolved-at: "2026-07-31T23:58:11-04:00"
tags:
- ticket/research
---
# Pi context token data research
## Question
What token and context-window usage data does Pi expose to extensions, footer renderers, session state, or model state, and is there enough structured data to draw a multi-colored context usage bar by token category?
## Findings
Pi exposes a current context-usage API to extensions.
The extensions docs define `ctx.getContextUsage()` and say it returns current context usage for the active model, using last assistant usage when available and estimating tokens for trailing messages.
The implementation returns `{ tokens, contextWindow, percent }` when the model has a positive context window.
After compaction, if there is no valid assistant usage after the compaction boundary, it returns `{ tokens: null, contextWindow, percent: null }` because the context token count is unknown until the next LLM response.
Sources: `docs/extensions.md` section `ctx.getContextUsage()`; `dist/core/agent-session.js` `getContextUsage()`.
Pi's built-in footer already uses the same context-usage data.
The footer calls `this.session.getContextUsage()`, falls back to the active model's `contextWindow` when needed, formats percentage as either a number or `?`, and colors the text as warning above 70% and error above 90%.
It appends an `(auto)` marker when automatic compaction is enabled.
Sources: `dist/modes/interactive/components/footer.js`.
Pi session usage totals have structured categories for `input`, `output`, `cacheRead`, and `cacheWrite`.
The built-in footer iterates all session entries, adds assistant-message usage, tool-result nested usage, branch-summary usage, and compaction usage, then renders usage parts as `↑`, `↓`, `R`, and `W` plus cache-hit rate when cache data exists.
The session export helper likewise exposes totals with `input`, `output`, `cacheRead`, `cacheWrite`, `total`, `cost`, and `contextUsage`.
Sources: `dist/modes/interactive/components/footer.js`; `dist/core/agent-session.js` session stats export logic.
Custom footers can calculate usage totals by iterating `ctx.sessionManager.getBranch()` or broader session entries if available.
The shipped custom footer example sums `m.usage.input`, `m.usage.output`, and `m.usage.cost.total` from assistant messages and notes that token stats come from `ctx.sessionManager` and `ctx.model`.
That example does not include cache read/write or compaction/tool-result usage, but the built-in footer source shows those categories exist in session entries.
Sources: `examples/extensions/custom-footer.ts`; `dist/modes/interactive/components/footer.js`.
The model context-window size is exposed on the active model.
The model docs define `contextWindow` as a model field with a default of `128000`, and custom provider examples register models with `contextWindow` and `maxTokens`.
The built-in footer reads `state.model?.contextWindow`, and `ctx.getContextUsage()` reads `model.contextWindow`.
Sources: `docs/models.md` model field table; `docs/extensions.md` dynamic provider example; `dist/core/agent-session.js`; `dist/modes/interactive/components/footer.js`.
There is not enough public structured data for a true by-content-type context-window bar in version one.
`ctx.getContextUsage()` exposes total tokens, context window, and percent, but not a breakdown by prompt category such as system prompt, user messages, assistant messages, tool results, context files, skills, or summaries.
The session usage categories are billing/usage categories from provider responses and nested calls: input, output, cache read, and cache write.
They are not a decomposition of the current context window contents.
Sources: `docs/extensions.md` `ctx.getContextUsage()`; `dist/core/agent-session.js` `getContextUsage()`; `dist/modes/interactive/components/footer.js` usage aggregation.
A multi-colored bar is still feasible, but the honest v1 categories are limited.
The bar can show total context-window usage from `ctx.getContextUsage()` and, while below a chosen danger threshold, can color segments using available provider usage categories such as input, output, cache read, and cache write.
However, that would visualize cumulative usage totals rather than what is actually occupying the current context window.
If the user specifically wants “what type of tokens are taking up the context window,” the implementation needs either an approximation from session entries or a new Pi API that exposes context-preparation buckets.
## Answer
Pi exposes enough data for a compact context usage bar showing total context-window percentage and threshold coloring.
Pi exposes structured token usage categories for cumulative session accounting.
Pi does not currently expose a public structured breakdown of current context-window occupancy by content type.
The prototype should therefore test two layers:
1. A truthful total context bar using `ctx.getContextUsage()`.
2. Optional segment coloring from available usage categories, clearly treated as usage composition rather than exact context occupancy.
## Limitations
This research used Pi docs and installed package source.
It did not instrument a live extension to inspect all runtime context objects.
The prototype can confirm whether additional useful fields are reachable in practice.
The source code contains an `estimateContextTokens(this.messages)` call, but the public extension API returns only the aggregate estimate.
Without depending on private internals, a customization should not claim exact content-type breakdown.
## Citations
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`, section `ctx.getContextUsage()`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/models.md`, model field table and provider examples.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/custom-footer.ts`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/core/agent-session.js`, `getContextUsage()` and session stats export logic.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/components/footer.js`.

View File

@@ -0,0 +1,81 @@
---
status: resolved
parent: "[[057-pi-ui-customization-map]]"
blocked-by: []
resolved-at: "2026-07-31T23:58:11-04:00"
tags:
- ticket/research
---
# ChatGPT Codex quota research
## Question
Is there a reliable first-party API, local account state, or documented observable signal that can report remaining weekly ChatGPT Codex quota for the current account, and what authentication or privacy constraints would a Pi status integration need to respect?
## Findings
Pi supports ChatGPT Plus or Pro subscription authentication for OpenAI Codex through `/login`.
The providers docs list “ChatGPT Plus/Pro (Codex)” under subscription providers and state that OpenAI Codex requires a ChatGPT Plus or Pro subscription.
The OpenAI Codex provider implementation uses `https://chatgpt.com/backend-api` as its base URL and OAuth through `auth.openai.com`.
Sources: `docs/providers.md`; `node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.js`; `node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js`.
Pi stores OAuth credentials in `~/.pi/agent/auth.json` and refreshes expired tokens automatically.
The providers docs describe auth storage for subscription providers, and the OpenAI Codex OAuth implementation returns an access token, refresh token, expiration time, and ChatGPT account id extracted from the access-token JWT.
Requests include `Authorization: Bearer <token>` and `chatgpt-account-id` headers.
Sources: `docs/providers.md`; `node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js`; `node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js`.
The installed Pi/OpenAI Codex integration does not expose a proactive “remaining weekly quota” API.
Searching the installed Pi and `@earendil-works/pi-ai` code found no quota, balance, or remaining-usage endpoint for OpenAI Codex.
The OpenAI Codex provider code has streaming request handling and OAuth, but no first-party quota read operation.
Sources: `node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.js`; `node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js`; `node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js`.
Pi can detect some limit information only when the provider returns an error.
The OpenAI Codex response code treats error codes such as `usage_limit_reached`, `usage_not_included`, and `rate_limit_exceeded`, or HTTP 429, as usage-limit conditions.
If the error body includes `plan_type`, it includes that in a friendly message.
If the error body includes `resets_at`, it computes an approximate minutes-until-reset message.
This is useful for displaying “you are out” and reset time after a failing request, but it is not a reliable way to display remaining quota before the limit is hit.
Sources: `node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js` error handling.
Pi extensions can observe provider response status and normalized headers through `after_provider_response`, but header availability depends on provider and transport.
The docs show using this hook to inspect HTTP 429 and `retry-after`.
The OpenAI Codex transport uses both SSE and WebSocket paths, so relying on response headers for a stable weekly quota display would need live verification and may not work for all Codex requests.
Sources: `docs/extensions.md` section `after_provider_response`; `node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js`.
Authentication and privacy constraints are significant.
A quota integration that calls ChatGPT backend APIs directly would need access to the user's OAuth access token and ChatGPT account id.
Those are credentials and account identifiers.
Any status integration must avoid logging them, avoid exposing them through status rows or transcript entries, and should only call endpoints that are documented or already used by Pi's provider stack.
Sources: `docs/providers.md` auth storage description; `node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js`; `node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js` request headers.
## Answer
This research established only a narrower fact: Pi's installed OpenAI Codex provider and Pi's docs do not expose a documented proactive quota API.
That is not enough to conclude that no reliable quota source exists.
The user reported third-party applications that show this information, possibly including baby-menu, so the broader question remains open and is tracked in [[064-pi-ui-third-party-codex-quota-research]].
The reactive signal remains useful: a provider error can report that a usage limit was hit, and may include plan type and reset time.
A safe fallback can show:
- last known Codex limit error, if one occurs
- reset estimate from `resets_at`, when present
- `retry-after` from response headers, when present
- “quota unknown” otherwise
Do not rule out a proactive quota display until the third-party mechanism has been researched.
## Limitations
This research did not call ChatGPT backend APIs with the user's credentials.
That was intentional because probing undocumented authenticated endpoints has privacy and stability risks.
OpenAI may expose quota information in web UI internals or undocumented backend endpoints, but no first-party documented source was established here.
Treat that as an evidence gap rather than an implementation basis.
## Citations
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/providers.md`, “Subscriptions” and “OpenAI Codex”.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`, section `after_provider_response`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.js`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-ai/dist/auth/oauth/openai-codex.js`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js`.

View File

@@ -0,0 +1,50 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-08-01T00:07:30-04:00"
resolved-at: "2026-08-01T00:24:40-04:00"
parent: "[[057-pi-ui-customization-map]]"
blocked-by:
- "[[058-pi-ui-tui-layout-research]]"
- "[[059-pi-ui-context-token-data-research]]"
tags:
- ticket/prototype/hitl
---
# Compact prompt status prototype
## Question
Build a throwaway Pi extension prototype that consolidates directory, branch, context-window usage, model, and thinking level into a compact status bar near the text prompt, then let the user judge whether the layout actually reduces dead space and feels better.
## Prototype
Throwaway extension path:
```text
~/.pi/agent/extensions/compact-status-prototype.ts
```
Run instructions:
1. Run `/reload` in Pi.
2. Inspect the one-line status widget above the prompt.
3. Run `/compact-status` to cycle modes:
- above prompt with hidden footer
- above prompt with tiny footer
- off, restoring the built-in footer
Verdict: promising enough to carry forward the compact status style, especially `above-and-hidden-footer`, the colors, the thin bar, and the visual directory/branch treatment.
The remaining dead-space problem belongs to Pi's editor layout rather than this status widget prototype.
## Iteration notes
First feedback: the preferred mode is `above-and-hidden-footer`.
The `~/dotfiles:main` indicator felt boring.
The context bar felt too thick, and numeric token text beside it was unnecessary.
Second draft changes: the widget now uses a two-line above-prompt layout with a more visual cwd/branch indicator, a thin full-width context bar, no context numbers, and the footer hidden by default.
Second feedback: the visual style and colors are promising, but the remaining dead space below the prompt is the main problem.
The prompt box appears to move vertically, while the desired behavior is bottom anchoring with the editor growing upward.
Autocomplete suggestions should appear above the editor and may cover the status bar if needed.
This surfaced [[082-pi-ui-bottom-anchored-editor-research]].
That follow-up resolved that clean bottom anchoring needs a Pi TUI layout change rather than a durable extension-only status-widget trick.

View File

@@ -0,0 +1,67 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-08-01T01:10:00-04:00"
parent: "[[057-pi-ui-customization-map]]"
blocked-by: []
resolved-at: "2026-08-01T08:10:00-04:00"
tags:
- ticket/prototype/hitl
---
# Codex quota status prototype
## Question
If quota research finds a reliable data source, extend the throwaway status prototype with a quick way to inspect remaining weekly ChatGPT Codex quota and have the user judge whether the interaction belongs in the compact status surface.
## Prototype build
The throwaway compact status extension now reads Pi's local `openai-codex` OAuth credential from `~/.pi/agent/auth.json`, calls first-party ChatGPT/Codex usage endpoints, parses quota windows defensively, and caches only normalized non-secret percentages in memory.
It does not log or display tokens, account ids, or raw response bodies.
The compact status widget now renders context usage and Codex weekly quota as unlabeled stacked thin bars.
The context row uses the lower three-eighths block glyph `▃` after HITL comparison.
The Codex row remains an upper one-eighth bar `▔` because upper-aligned block characters have less granularity.
Codex quota is inverted: it fills as quota is consumed rather than as quota remains.
The quota color uses the theme border blue below 50% consumed so it contrasts with the green context bar, then yellow at 50% and red at 80%.
HITL verdict is positive.
Example shape:
```text
󰉋 ~/dotfiles 󰘬 main gpt-5.5 • medium
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀──────────────────────────────────────────────────────────
```
The `/codex-quota` notification may still include normalized percentage details for inspection.
A command is available:
```text
/codex-quota
```
It forces a refresh and shows a notification with the normalized quota summary or a non-secret error.
## Verification
A tmux smoke test launched the flex-spacer prototype and confirmed the status line rendered live quota data:
```text
codex W 94% S 94%
```
The visible prototype was then changed after HITL feedback to a one-row half-block bar instead of separate context and quota rows.
The prototype remains at:
```text
/home/alexion/.pi/agent/extensions/compact-status-prototype.ts
```
Launch with the flex-spacer Pi prototype for the combined visual test:
```bash
/home/alexion/.local/share/pi-flex-spacer-prototype/pi-flex-spacer
```

View File

@@ -0,0 +1,232 @@
---
status: resolved
parent: "[[057-pi-ui-customization-map]]"
blocked-by:
- "[[062-pi-ui-quota-status-prototype]]"
- "[[067-pi-ui-flex-spacer-bottom-anchor-prototype]]"
resolved-at: "2026-08-01T08:20:00-04:00"
tags:
- ticket/task/afk
---
# Specify permanent Pi UI customization
## Question
Turn the resolved research and prototype verdicts into an implementation-ready specification for the permanent dotfiles-managed Pi UI customization, including what to build, what to leave out, and how to verify it after reload.
## Decision
Build the permanent customization as two pieces:
1. A dotfiles-managed Pi extension that owns the compact status surface.
2. A small local Pi layout patch that inserts flexible space above the prompt area when the TUI stack is shorter than the terminal.
Do not try to solve bottom anchoring with an extension spacer widget.
The prototype showed the correct behavior comes from the layout layer, not from guessing terminal height in a widget.
Do not use `terminal.clearOnShrink` as the primary fix.
The flex-spacer layout makes the prompt area continue to occupy the terminal bottom after transient autocomplete rows disappear.
`terminal.clearOnShrink` can remain a separate rendering knob for unrelated stale-row cases.
## Compact status extension specification
The extension should be installed through the dotfiles Pi module under the managed Pi extension directory.
The throwaway file at `~/.pi/agent/extensions/compact-status-prototype.ts` is not the deployment target.
The extension should use in-code defaults only.
It should not write a default config file.
The extension should hide the built-in footer by default with an empty custom footer renderer.
It should place the compact status widget above the editor.
The status widget has three rows:
```text
󰉋 ~/dotfiles 󰘬 main gpt-5.5 • medium
▃▃▃▃▃▃▃▃▃▃▃▃───────────────────────────────────────────────────────────────
▔▔▔────────────────────────────────────────────────────────────────────────
```
Row 1 shows location and runtime state.
The left side is a visual cwd and branch indicator using `󰉋 <short-cwd> 󰘬 <branch>`.
The right side is `<model> • <thinking>`.
Use the session cwd when available, not `process.cwd()` as the primary source.
Use the current git branch when available.
If no branch exists, omit the branch segment.
Row 2 is the context-window usage bar.
It is unlabeled.
It uses full width.
It uses the lower three-eighths block glyph `▃`.
It fills by `ctx.getContextUsage().percent`.
It uses the theme success color under 70%, warning at 70%, and error at 90%.
The unfilled track uses the dim color.
If context usage is unknown, render a muted full-width track rather than inventing a percentage.
Do not show numeric context usage in the default status surface.
Do not attempt exact current-context category breakdown in the permanent default, because Pi does not expose that exact public data.
Row 3 is the ChatGPT Codex weekly quota consumed bar.
It is unlabeled.
It uses full width.
It uses the upper one-eighth block glyph `▔`.
It fills by consumed weekly quota, meaning `100 - weeklyRemaining`.
It starts empty when quota is unused.
It uses the theme border blue below 50% consumed so it contrasts with the green context bar.
It uses warning at 50% and error at 80%.
The unfilled track uses the dim color.
If quota is unknown, render a muted full-width track rather than inventing a percentage.
The extension should provide `/codex-quota`.
The command forces a quota refresh and shows a notification with normalized non-secret details.
The notification may include weekly remaining and any short-window value returned by the endpoint.
The default status surface should still show only the bars.
The extension may provide a development toggle command only if useful during implementation.
The finished default behavior should not require cycling modes.
## Quota data specification
The quota source is Pi's local OpenAI Codex OAuth credential at `~/.pi/agent/auth.json`, provider key `openai-codex`.
The extension must read only the fields it needs.
It must not log, display, or persist the access token, refresh token, account id, or raw response body.
It must not send OpenAI API keys to ChatGPT subscription quota endpoints.
The primary endpoints are:
```text
https://chatgpt.com/backend-api/wham/usage
https://chatgpt.com/backend-api/codex/usage
```
Requests use `Authorization: Bearer <access-token>`.
Requests include `ChatGPT-Account-Id` when the local OAuth credential has an account id.
Parsing must be defensive.
Accept snake_case and camelCase window fields.
Recognize the weekly window by approximately 604,800 seconds or by week-like names if duration is unavailable.
Recognize a short window only for the `/codex-quota` notification or fallback state.
The default status bar should prefer weekly quota.
Cache only normalized non-secret quota state in memory.
A five-minute refresh interval is acceptable for the status widget.
Manual `/codex-quota` refresh bypasses the freshness check.
Network errors, missing credentials, expired credentials, and unrecognized responses should produce an unknown/error state without throwing extension-load errors.
Do not add an app-server fallback in the first permanent version unless direct endpoint parsing proves unreliable during implementation.
The researched Codex app-server `account/rateLimits/read` path remains the preferred fallback if a fallback becomes necessary.
## Flex-spacer layout patch specification
Patch Pi's interactive TUI layout so normal content and prompt-area content are rendered as two groups.
Flow content:
- header container
- loaded resources container
- chat transcript container
Pinned prompt-area content:
- pending messages container
- terminal log container, if present in the installed Pi version
- status container
- above-editor widget container
- editor container
- below-editor widget container
- footer
During render, compute the rendered line count of both groups.
If `flowLines.length + pinnedLines.length` is less than the terminal row count, insert blank spacer rows between the groups.
If the combined line count is greater than or equal to the terminal row count, insert no spacer.
The patch should preserve the current visual behavior for long conversations.
It should only move spare empty space from below the editor to above the prompt area in underfilled screens.
The patch should recompute on each render and terminal resize.
It must not accumulate spacer rows as state.
The patch should keep autocomplete behavior otherwise unchanged.
Autocomplete may still render below the editor in the first permanent version.
Because the flex spacer fills the terminal, closing autocomplete should not leave the prompt visually floating above a blank bottom gap.
The patch should be implemented as a small local Pi package patch or upstreamable patch.
It should not be a runtime extension hack.
## Tool lookup hardening
The flex-spacer prototype exposed a NixOS-specific Pi tool lookup issue.
Pi can select `~/.pi/agent/bin/fd` before `PATH`, and that downloaded generic Linux binary can fail on NixOS with the stub-ld error.
The permanent Pi patch should also harden tool lookup if the local patch touches Pi internals.
A local tool path should count as available only if running `<tool> --version` exits with status 0.
If the local tool fails, Pi should continue to system `PATH`, where the Nix wrapper provides working `fd` and `rg`.
This hardening is not a UI feature, but it prevents `@` autocomplete from breaking under the patched Pi package.
## Dotfiles deployment specification
The finished extension must be promoted into the dotfiles Pi module's managed extension source tree.
It must not remain only under `~/.pi/agent/extensions`.
The finished Pi patch must be delivered through the flake-managed Pi package path.
The exact Nix module structure can be chosen during implementation, but the result should make the ordinary `pi` command use the patched layout after rebuild.
Do not manage `~/.pi/agent/auth.json`.
Login credentials remain user state.
Do not add a generated config file for this feature.
## Out of scope
Do not replace Pi's whole TUI.
Do not maintain an unrelated long-lived Pi fork.
Do not add opinionated quota policies or notifications beyond the manual `/codex-quota` command and passive status bar.
Do not display quota numbers in the default compact status surface.
Do not attempt to make exact token-category context breakdown claims from cumulative session usage.
## Verification
After implementation, run the repository's normal verification seam:
```bash
nix flake check
```
After switching to the new generation, launch normal Pi with:
```bash
pi
```
Verify after `/reload` that no extension load errors appear.
Verify the compact status visual shape:
- row 1 shows cwd/branch on the left and model/thinking on the right
- row 2 is an unlabeled `▃` context bar
- row 3 is an unlabeled `▔` Codex consumed weekly quota bar
- the built-in footer is hidden by default
Verify `/codex-quota`:
- it forces a refresh
- it shows a non-secret normalized notification
- it does not print tokens, account ids, or raw JSON
- it degrades to unknown/missing/error without crashing when credentials or network are unavailable
Verify flex-spacer behavior:
- a short conversation leaves spare rows above the status/editor area, not below the editor
- a long conversation behaves like stock Pi and does not insert visible spacer rows inside the transcript
- resizing the terminal recomputes the spacer
- `/` autocomplete and `@` autocomplete still work
- closing autocomplete leaves the editor visually bottom-aligned
## Follow-up implementation tickets
Implement this specification through:
- [[068-pi-ui-compact-status-extension-task]]
- [[070-pi-ui-flex-spacer-pi-patch-task]]
- [[071-pi-ui-final-deployment-verification-task]]

View File

@@ -0,0 +1,88 @@
---
status: resolved
parent: "[[060-pi-ui-codex-quota-research]]"
blocked-by: []
resolved-at: "2026-08-01T00:24:40-04:00"
tags:
- ticket/research
---
# Third-party ChatGPT Codex quota research
## Question
What mechanism do third-party tools such as baby-menu use to show remaining ChatGPT Codex quota, and can that mechanism be adapted safely for a Pi status integration?
## Findings
`baby-menu` does not ship a completed Codex quota extension in the checked repository snapshot.
It ships an extension recipe at `extensions/recipes/codex-quota.html` that instructs implementers to obtain real local Codex quota data from two sources: a direct ChatGPT backend usage call using local Codex credentials, then a Codex CLI app-server JSON-RPC fallback.
Source: `/tmp/pi-ui-quota-research/baby-menu/extensions/recipes/codex-quota.html`.
The direct `baby-menu` recipe endpoint is `GET https://chatgpt.com/backend-api/wham/usage` with `Authorization: Bearer <access_token>` and `ChatGPT-Account-Id` when available.
The recipe says usage lives under `rate_limit`, `used_percent` is percent used, `primary_window` is the short session window, `secondary_window` is the weekly window, and remaining is `100 - used_percent`.
Source: `/tmp/pi-ui-quota-research/baby-menu/extensions/recipes/codex-quota.html`.
The same first-party endpoint family is present in OpenAI's own Codex source.
The official Codex backend client selects `/wham/usage` for the ChatGPT API path and `/api/codex/usage` for the Codex API path, adds `ChatGPT-Account-Id` when it has a ChatGPT account id, and parses the returned rate-limit payload into Codex rate-limit snapshots.
Sources: `/tmp/pi-ui-quota-research/openai-codex/codex-rs/backend-client/src/client/rate_limit_resets.rs`; `/tmp/pi-ui-quota-research/openai-codex/codex-rs/backend-client/src/client.rs`.
OpenAI's `codex app-server` exposes the same information through a documented local JSON-RPC method.
Its app-server README documents `account/rateLimits/read` as fetching ChatGPT rate limits, monthly credit-limit data when available, spend-control state, and earned reset credits, with updates via `account/rateLimits/updated`.
The protocol schema defines `GetAccountRateLimitsResponse` with `rateLimits`, optional `rateLimitsByLimitId`, and optional `rateLimitResetCredits`, and defines `RateLimitWindow.usedPercent`, `windowDurationMins`, and `resetsAt`.
Sources: `/tmp/pi-ui-quota-research/openai-codex/codex-rs/app-server/README.md`; `/tmp/pi-ui-quota-research/openai-codex/codex-rs/app-server-protocol/src/protocol/v2/account.rs`.
`quota-axi` implements the same mechanism as a local data-only CLI.
For Codex it first reads OAuth tokens from `$CODEX_HOME/auth.json` or `~/.codex/auth.json`, calls `https://chatgpt.com/backend-api/wham/usage` and `https://chatgpt.com/backend-api/codex/usage`, and falls back to spawning `codex -s read-only -a untrusted app-server` and issuing `initialize`, `account/read`, and `account/rateLimits/read` JSON-RPC requests.
Sources: `/tmp/pi-ui-quota-research/quota-axi/src/providers/codex.ts`; `/tmp/pi-ui-quota-research/quota-axi/README.md`.
`quota-axi` normalizes Codex windows by duration rather than by position alone.
It maps 18,000-second windows to a session or five-hour window, 604,800-second windows to weekly windows, computes `percentRemaining` from `percentUsed`, handles additional named or per-model limits, and reports reset times and credit snapshots when available.
Source: `/tmp/pi-ui-quota-research/quota-axi/src/providers/codex.ts`.
There is an important discrepancy between sources about API-key auth.
The `baby-menu` recipe says a top-level `OPENAI_API_KEY` in Codex `auth.json` can be used directly as the bearer token.
`quota-axi` explicitly does not send `OPENAI_API_KEY` to ChatGPT OAuth usage endpoints, and OpenAI's app-server account/rate-limit path is documented as ChatGPT account rate limits rather than ordinary API-key billing quota.
For a Pi status integration, the safer interpretation is that ChatGPT Codex subscription quota should use ChatGPT OAuth credentials or the Codex app-server, not an OpenAI API key.
Sources: `/tmp/pi-ui-quota-research/baby-menu/extensions/recipes/codex-quota.html`; `/tmp/pi-ui-quota-research/quota-axi/src/providers/codex.ts`; `/tmp/pi-ui-quota-research/quota-axi/test/providers/codex-auth.test.ts`; `/tmp/pi-ui-quota-research/openai-codex/codex-rs/app-server/README.md`.
A Pi integration can adapt the mechanism, but not as a blind frontend-only widget.
The status integration would need a backend extension path that reads local credentials without logging them, calls first-party ChatGPT/Codex endpoints directly or shells out to a local Codex app-server fallback, parses defensively, caches only normalized non-secret quota snapshots, and treats missing or unparsable data as unknown rather than inventing quota.
Sources: `/tmp/pi-ui-quota-research/quota-axi/README.md`; `/tmp/pi-ui-quota-research/quota-axi/AGENTS.md`; `/tmp/pi-ui-quota-research/quota-axi/src/providers/codex.ts`; `/tmp/pi-ui-quota-research/baby-menu/extensions/recipes/codex-quota.html`.
Pi's own installed OpenAI Codex provider already has OAuth credentials and a ChatGPT account id in its auth flow, but the previously inspected Pi provider code does not itself expose a quota endpoint.
Therefore a Pi-native implementation can either add a small first-party endpoint client using Pi's existing OpenAI Codex OAuth credential shape, or run `quota-axi`/Codex CLI as an external local data source when available.
Using Pi's auth file directly is more integrated, while using `quota-axi` is lower risk for quota parsing because it already handles multiple endpoint shapes and app-server fallback.
Sources: `[[060-pi-ui-codex-quota-research]]`; `/tmp/pi-ui-quota-research/quota-axi/src/providers/codex.ts`.
## Answer
Third-party tools obtain ChatGPT Codex quota from first-party ChatGPT/Codex rate-limit surfaces, not from screen scraping.
The established mechanisms are:
1. call ChatGPT backend usage endpoints such as `/backend-api/wham/usage` or `/backend-api/codex/usage` with local ChatGPT OAuth credentials and account id
2. fall back to Codex CLI app-server JSON-RPC, especially `account/rateLimits/read`
This is adaptable for a Pi status integration if it is implemented as local, read-only, credential-safe backend code with defensive parsing and an unknown/stale state.
It should not send OpenAI API keys to ChatGPT quota endpoints.
It should not expose tokens, account ids, or raw response bodies through the TUI, logs, or transcript.
## Limitations
This research read source code and documentation but did not call the live ChatGPT endpoints with the user's credentials.
That avoids probing authenticated undocumented surfaces during research.
The direct ChatGPT backend endpoints are first-party and used by OpenAI's Codex code, but they are still not public stable API documentation for third-party clients.
The app-server JSON-RPC surface is the best documented local interface when the Codex CLI is available and signed in.
## Citations
- `/tmp/pi-ui-quota-research/baby-menu/extensions/recipes/codex-quota.html`.
- `/tmp/pi-ui-quota-research/quota-axi/README.md`.
- `/tmp/pi-ui-quota-research/quota-axi/AGENTS.md`.
- `/tmp/pi-ui-quota-research/quota-axi/src/providers/codex.ts`.
- `/tmp/pi-ui-quota-research/quota-axi/test/providers/codex-auth.test.ts`.
- `/tmp/pi-ui-quota-research/openai-codex/codex-rs/app-server/README.md`.
- `/tmp/pi-ui-quota-research/openai-codex/codex-rs/app-server-protocol/src/protocol/v2/account.rs`.
- `/tmp/pi-ui-quota-research/openai-codex/codex-rs/backend-client/src/client.rs`.
- `/tmp/pi-ui-quota-research/openai-codex/codex-rs/backend-client/src/client/rate_limit_resets.rs`.

View File

@@ -0,0 +1,118 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-08-01T00:30:00-04:00"
parent: "[[082-pi-ui-bottom-anchored-editor-research]]"
blocked-by: []
resolved-at: "2026-08-01T00:36:00-04:00"
tags:
- ticket/research
---
# Existing Pi extension layout survey
## Question
Do existing Pi extensions or public examples already implement bottom-anchored prompt/editor layout, above-editor autocomplete overlays, footer replacement, or compact prompt-area status patterns that should change the Pi UI customization plan?
## Scope
Survey the bundled Pi examples, known local research clones, and public repositories discoverable without authenticated code search.
Distinguish official extension APIs from private implementation hooks.
Record whether any candidate is durable enough for dotfiles-managed use or only useful as a throwaway spike.
## Findings
The most relevant public extension is `nicobailon/pi-powerline-footer`.
It implements a polished powerline-style status surface, replaces the footer with an empty renderer, uses above/below editor widgets for primary and secondary rows, and replaces the editor component with a custom `BashModeEditor` that wraps the default editor behavior.
It has configurable placement for the primary row, but placement is still limited to Pi's widget slots above or below the editor.
Sources: `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/README.md`; `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/index.ts`.
`pi-powerline-footer` is useful prior art for our compact status design.
It covers model, thinking, path, git, context usage, token/cost information, custom status items, welcome overlays, and editor rendering tweaks.
It does not implement a bottom-docked editor slot through extension APIs.
Its README explicitly describes that Pi owns native layout and the extension supplies widgets and custom editor integrations.
Sources: `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/README.md`; `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/index.ts`.
`pi-powerline-footer` includes a custom editor that modifies prompt rendering and shell-mode behavior, but not autocomplete placement above the editor.
Its `BashModeEditor.render()` calls `super.render(width)` and then injects ghost-text suggestions into the editor content line for shell completion.
It also wraps Pi's autocomplete provider to compose shell-aware suggestions with Pi's default provider, but it does not move Pi's dropdown to an overlay above the prompt.
Sources: `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/bash-mode/editor.ts`; `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/editor-composition.ts`; `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/index.ts`.
The most relevant non-extension prior art is `0x-rya/pi-local-mods`.
Its README says the useful changes are intentionally not Pi extensions because they patch internals not exposed to extensions, including transcript scrolling and selection.
Its patch introduces `FixedBottomScrollLayout`, separates scroll children from pinned children, replaces Pi's normal child stack with that fixed layout, and pins pending messages, terminal logs, status, widgets, editor, below-editor widgets, and footer while the header/resources/chat area scrolls above them.
That is structurally close to the desired bottom-anchored editor model.
Sources: `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/README.md`; `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/scripts/apply.py`.
`pi-local-mods` also patches Pi's custom editor internals to support border providers.
It adds `setTopBorderProvider()` and `setBottomBorderProvider()`, frames the editor with rounded borders, and lets interactive mode put main footer/status content into editor borders.
This is directly relevant to the idea of making status visually attached to the prompt without spending separate rows, but it confirms the mechanism is currently a private Pi patch rather than a supported extension API.
Source: `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/scripts/apply.py`.
Several public extensions implement footer replacement or status surfaces, but they stay inside the documented extension API.
Examples include `@fgladisch/pi-footer`, `luongnv89/statusline-pi`, and `tomsej/pi-ext`'s custom footer.
They use `ctx.ui.setFooter()`, `ctx.ui.setWidget()`, or `ctx.ui.setEditorComponent()` for prompt prefixes and compact lines, but none of the inspected implementations create a true bottom-docked editor layout.
Sources: `/tmp/pi-existing-extension-survey/repos/fgladisch__pi-extensions/packages/pi-footer/extensions/index.ts`; `/tmp/pi-existing-extension-survey/repos/fgladisch__pi-extensions/packages/pi-footer/README.md`; `/tmp/pi-existing-extension-survey/repos/luongnv89__pi-extensions/extensions/statusline-pi/src/index.ts`; `/tmp/pi-existing-extension-survey/repos/tomsej__pi-ext/extensions/custom-footer/custom-footer.ts`.
Several public extensions use overlays, including floating terminals and git-change viewers.
They demonstrate that overlays can be centered or otherwise positioned for temporary UI, and `nicobailon/pi-interactive-shell` exposes configurable overlay anchors.
They do not replace the main prompt with a durable bottom overlay, and they do not solve autocomplete placement for the built-in editor.
Sources: `/tmp/pi-existing-extension-survey/repos/joyanhui__pi-extension/pi-ext-float-term/float-term.ts`; `/tmp/pi-existing-extension-survey/repos/joyanhui__pi-extension/pi-ext-git-changes/git-changes.ts`; `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-interactive-shell/config.ts`.
Several custom editor extensions alter editor rendering, but they do not change the editor slot position.
`@fgladisch/pi-footer` adds a prompt prefix by wrapping `CustomEditor.render()`.
`joyanhui/pi-ext-bar-cursor` strips the fake block cursor so the hardware bar cursor can show.
These are useful examples of safe-ish render wrappers, but they still live inside Pi's existing editor container.
Sources: `/tmp/pi-existing-extension-survey/repos/fgladisch__pi-extensions/packages/pi-footer/extensions/index.ts`; `/tmp/pi-existing-extension-survey/repos/joyanhui__pi-extension/pi-ext-bar-cursor/bar-cursor.ts`.
Unauthenticated GitHub repository search and npm metadata found many Pi extension repositories, but the layout-related ones above were the relevant hits for this question.
GitHub code search requires authentication, so the survey used repository search, cloned likely candidates, bundled Pi examples, and local research clones.
Sources: `/tmp/pi-existing-extension-survey/github-repos-earendil-pi-coding-agent.json`; `/tmp/pi-existing-extension-survey/github-repos-pi-coding-agent.json`; `/tmp/pi-existing-extension-survey/npm-earendil-pi-coding-agent.json`; `/tmp/pi-existing-extension-survey/repos/BubblePtr__awesome-pi/README.en.md`.
## Answer
Existing extensions do not appear to provide a durable extension-only solution for a bottom-anchored prompt editor with above-editor autocomplete overlay.
They do provide two useful pieces of prior art:
1. `pi-powerline-footer` shows how far a polished compact prompt/status surface can go with public extension APIs.
2. `pi-local-mods` shows that the desired bottom-pinned layout is feasible as a Pi internals patch, specifically by replacing the top-flow child stack with a fixed-bottom scroll layout and by adding editor border status providers.
This changes the plan from “maybe patch Pi” to “there is already public prior art for exactly the kind of Pi patch needed.”
The permanent design should avoid fake spacer widgets and should either:
- keep the compact status as an extension-only improvement while accepting current Pi layout limits, or
- build a local/upstream Pi patch inspired by `FixedBottomScrollLayout` and editor border providers.
## Implications
For an extension-only implementation, reuse the `pi-powerline-footer` pattern rather than inventing all layout machinery from scratch.
That means widgets, hidden footer, custom editor rendering, and careful autocomplete-provider composition if needed.
For the preferred bottom-anchored behavior, write a separate Pi layout patch/spec.
The patch should split scrollable transcript content from pinned input-area content and should treat autocomplete as part of the editor/input area rather than as a normal line appended below the prompt.
## Limitations
GitHub code search was unavailable without authentication, so this was not an exhaustive public-code search.
The survey cloned and inspected likely repositories from unauthenticated repository search, npm metadata, an awesome list, bundled Pi examples, and existing local research clones.
No private or unlisted extensions were inspected.
## Citations
- `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/README.md`.
- `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/index.ts`.
- `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/bash-mode/editor.ts`.
- `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/editor-composition.ts`.
- `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/README.md`.
- `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/scripts/apply.py`.
- `/tmp/pi-existing-extension-survey/repos/fgladisch__pi-extensions/packages/pi-footer/README.md`.
- `/tmp/pi-existing-extension-survey/repos/fgladisch__pi-extensions/packages/pi-footer/extensions/index.ts`.
- `/tmp/pi-existing-extension-survey/repos/luongnv89__pi-extensions/extensions/statusline-pi/src/index.ts`.
- `/tmp/pi-existing-extension-survey/repos/tomsej__pi-ext/extensions/custom-footer/custom-footer.ts`.
- `/tmp/pi-existing-extension-survey/repos/joyanhui__pi-extension/pi-ext-bar-cursor/bar-cursor.ts`.
- `/tmp/pi-existing-extension-survey/repos/joyanhui__pi-extension/pi-ext-float-term/float-term.ts`.
- `/tmp/pi-existing-extension-survey/repos/joyanhui__pi-extension/pi-ext-git-changes/git-changes.ts`.
- `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-interactive-shell/config.ts`.
- `/tmp/pi-existing-extension-survey/repos/BubblePtr__awesome-pi/README.en.md`.

View File

@@ -0,0 +1,102 @@
---
status: resolved
claimed-by: "019fba91-eabf-76ae-b086-a37ac061d6e8"
claimed-at: "2026-08-01T00:45:00-04:00"
parent: "[[082-pi-ui-bottom-anchored-editor-research]]"
blocked-by: []
resolved-at: "2026-08-01T01:05:00-04:00"
tags:
- ticket/prototype/hitl
---
# Flex spacer bottom anchor prototype
## Question
Can a small Pi TUI patch prototype eliminate blank space below the prompt by inserting flexible empty space above the prompt/status/editor stack only when the rendered content is shorter than the terminal?
## Motivation
The screenshots show that the current editor looks good when enough transcript content pushes it to the bottom.
The bad case is not that the editor is always misplaced.
The bad case is that the linear Pi stack can be underfilled, leaving spare terminal rows after the editor.
The desired behavior is therefore narrower than a full prompt redesign.
When content is short, spare vertical rows should appear above the prompt area rather than below it.
When content is long, the current visual behavior should remain unchanged.
## Prototype shape
Build a throwaway local Pi patch or wrapper that preserves the existing component order but splits the rendered output into two conceptual groups:
1. Flow content: header, loaded resources, chat transcript, and other scrollable/top content.
2. Pinned input area: compact status widget, editor, below-editor widgets, and footer if enabled.
On render, compute available terminal rows.
If the combined flow and pinned lines are shorter than the terminal height, insert blank spacer lines between the flow content and pinned input area.
If the combined lines meet or exceed terminal height, insert no spacer and preserve normal scrolling behavior.
## Acceptance criteria
- In a short conversation, the editor appears at the terminal bottom with spare rows above the compact status/editor area.
- In a long conversation, the editor still appears naturally at the bottom with no extra gap inserted into the transcript.
- The compact status prototype remains visually attached to the editor.
- Hiding the footer does not create blank rows below the editor.
- Terminal resize recomputes the spacer without accumulating stale blank lines.
- Autocomplete behavior is observed and documented, even if not fixed in this prototype.
- The result is judged by HITL screenshots before any permanent spec chooses a Pi patch direction.
## Non-goals
Do not solve quota display in this ticket.
Do not make a durable dotfiles deployment in this ticket.
Do not replace Pi's whole TUI.
Do not claim this is extension-only unless the prototype actually avoids patching Pi internals.
## Prototype build
A throwaway patched Pi copy was created at:
```text
/home/alexion/.local/share/pi-flex-spacer-prototype/pi-monorepo
```
Launch it with:
```bash
/home/alexion/.local/share/pi-flex-spacer-prototype/pi-flex-spacer
```
The patch adds `FlexSpacerBottomLayout` in `dist/modes/interactive/interactive-mode.js`.
It renders header, loaded resources, and chat as flow content.
It renders pending messages, status, above-editor widgets, editor, below-editor widgets, and footer as the pinned input area.
When the combined lines are shorter than `ui.terminal.rows`, it inserts blank rows between those groups.
## HITL observations
The first launcher omitted Pi's Nix wrapper PATH additions for `fd` and `rg`.
That did not fully explain the `@` autocomplete failure.
Pi's tool lookup found `/home/alexion/.pi/agent/bin/fd` before `PATH`, and that downloaded generic Linux binary fails on NixOS with the stub-ld error.
The prototype now patches its copied `tools-manager.js` so `commandExists()` requires exit status `0` and the local tool path is validated before use.
This makes Pi fall back to the Nix `fd` on `PATH`.
A tmux-launched test confirmed `@` now opens file suggestions in `/home/alexion/wrk/dotfiles`.
Pi has a separate shrink-clearing issue after autocomplete.
The built-in editor renders autocomplete suggestions below the editor, and when suggestions disappear the TUI may leave stale rows because `terminal.clearOnShrink` defaults to `false`.
This can produce a massive apparent gap after an autocomplete interaction in both stock Pi and the prototype.
This ticket should distinguish that rendering artifact from the flex-spacer layout behavior.
## Verdict
HITL verdict is positive.
The flex-spacer behavior feels smooth and should be the preferred permanent layout direction.
It should be specified as a small Pi layout patch or upstreamable TUI layout change, not as a fragile extension spacer hack.
The prototype also effectively fixes the observed post-autocomplete gap in this prompt-area case because the rendered stack continues to fill the terminal height after the autocomplete list disappears.
That makes `terminal.clearOnShrink` less important for this customization.
Keep `clearOnShrink` as a separate Pi rendering knob for other stale-row cases, but do not make it the primary fix for prompt anchoring.
## Notes
`0x-rya/pi-local-mods` is relevant prior art because its `FixedBottomScrollLayout` separates scroll children from pinned children.
This ticket tests the simpler version first: a flexible spacer between the existing transcript flow and prompt area.

View File

@@ -0,0 +1,37 @@
---
status: open
parent: "[[063-pi-ui-customization-spec-task]]"
blocked-by: []
tags:
- ticket/task/afk
---
# Implement compact Pi status extension
## Question
Promote the accepted compact status prototype into the dotfiles-managed Pi extension tree with credential-safe Codex quota handling.
## What to build
Create a flake-managed Pi extension that replaces the throwaway `compact-status-prototype.ts` behavior with the permanent compact status surface.
The extension should hide Pi's built-in footer by default, render the cwd/branch and model/thinking row above the editor, render the unlabeled `▃` context bar, render the unlabeled `▔` consumed-weekly-Codex quota bar, and provide `/codex-quota` for a manual non-secret quota refresh notification.
The extension should read Pi's local `openai-codex` OAuth credential only for the access token and account id needed by the ChatGPT/Codex usage endpoints.
It should cache only normalized non-secret quota percentages in memory and degrade to an unknown/error state without crashing when credentials, network, or response shape are unavailable.
## Acceptance criteria
- [ ] The extension lives under the dotfiles Pi module's managed extension source tree, not only under `~/.pi/agent/extensions`.
- [ ] The built-in footer is hidden by default.
- [ ] The status widget shows cwd/branch on the left and model/thinking on the right.
- [ ] The context bar uses `▃`, fills from `ctx.getContextUsage().percent`, and uses success/warning/error thresholds 70% and 90%.
- [ ] The Codex quota bar uses `▔`, fills by consumed weekly quota, uses border blue below 50%, warning at 50%, and error at 80%.
- [ ] `/codex-quota` forces a refresh and displays only normalized non-secret details.
- [ ] Missing or expired credentials, network errors, and unrecognized quota responses do not break extension loading.
- [ ] No default config file is generated.
## Implementation Notes
Use `[[063-pi-ui-customization-spec-task]]` as the source of truth for row shape, colors, quota endpoints, and out-of-scope behavior.
The throwaway prototype at `~/.pi/agent/extensions/compact-status-prototype.ts` is useful reference code, but the finished implementation should be promoted into the repo-managed Pi extension source.

View File

@@ -0,0 +1,42 @@
---
status: open
parent: "[[063-pi-ui-customization-spec-task]]"
blocked-by:
- "[[073-pi-ui-community-pi-packaging-research]]"
tags:
- ticket/task/afk
---
# Patch Pi prompt-area layout
## Question
Make the ordinary flake-managed `pi` command use the accepted flex-spacer prompt-area layout and harden local tool lookup for NixOS.
## What to build
Add a small local Pi package patch through the dotfiles flake so Pi's interactive layout renders flow content separately from the pinned prompt-area content.
When the rendered TUI is shorter than the terminal, insert flexible blank rows between the flow content and the prompt-area group.
When the rendered TUI is long enough to fill the terminal, preserve stock scrolling behavior with no inserted spacer.
Also harden Pi tool lookup so unusable downloaded local binaries in `~/.pi/agent/bin` do not mask working Nix-provided `fd` and `rg` binaries on `PATH`.
A local tool should count as available only when `<tool> --version` exits successfully.
## Acceptance criteria
- [ ] The ordinary flake-managed `pi` command uses the patched layout after rebuild.
- [ ] Short conversations leave spare vertical space above the status/editor area, not below the editor.
- [ ] Long conversations preserve stock Pi scrolling behavior.
- [ ] Terminal resize recomputes spacer rows without accumulating stale blank lines.
- [ ] `/` autocomplete still works.
- [ ] `@` autocomplete still works even when `~/.pi/agent/bin/fd` is an unusable generic Linux binary.
- [ ] Closing autocomplete leaves the editor visually bottom-aligned.
- [ ] The patch is delivered through dotfiles, not by an unmanaged copy under `~/.local/share`.
## Implementation Notes
Use [[072-pi-ui-patched-pi-packaging-research]] for the packaging plan.
Patch `pkgs.pi-coding-agent` at the TypeScript source level with `overrideAttrs`, assign the result to `programs.pi-coding-agent.package`, and keep the ordinary `pi` command managed by Home Manager.
The prototype at `/home/alexion/.local/share/pi-flex-spacer-prototype/pi-monorepo` added `FlexSpacerBottomLayout` in Pi's `dist/modes/interactive/interactive-mode.js` and patched tool lookup in `dist/utils/tools-manager.js`.
Use it as behavior reference, but implement through the flake-managed Pi package path.

View File

@@ -0,0 +1,37 @@
---
status: open
parent: "[[063-pi-ui-customization-spec-task]]"
blocked-by:
- "[[068-pi-ui-compact-status-extension-task]]"
- "[[070-pi-ui-flex-spacer-pi-patch-task]]"
tags:
- ticket/task/afk
---
# Verify permanent Pi UI deployment
## Question
Verify the compact status extension and flex-spacer Pi patch together through the normal dotfiles deployment path, then retire prototype-only assumptions from the active plan.
## What to build
Run the final verification pass after the extension and Pi package patch both land.
Confirm the ordinary `pi` command has the accepted visual behavior after rebuild, the managed extension loads without errors, quota refresh remains credential-safe, autocomplete still works, and no unmanaged prototype path is required for the finished feature.
## Acceptance criteria
- [ ] `nix flake check` passes.
- [ ] Normal `pi` launches with no extension load errors after `/reload`.
- [ ] The compact status shows cwd/branch, model/thinking, a `▃` context bar, and a `▔` consumed-weekly-Codex quota bar.
- [ ] The footer is hidden by default.
- [ ] `/codex-quota` refreshes quota and reports only non-secret normalized details.
- [ ] A short conversation keeps the prompt/status/editor area at the bottom.
- [ ] A long conversation preserves normal transcript scrolling.
- [ ] `/` and `@` autocomplete work in the deployed `pi` command.
- [ ] The final notes identify any remaining throwaway prototype files as non-deployment artifacts.
## Implementation Notes
This is a verification and cleanup ticket, not a place to redesign the UI.
If the implementation diverges from `[[063-pi-ui-customization-spec-task]]`, record the reason in the ticket before closing it.

View File

@@ -0,0 +1,109 @@
---
status: resolved
parent: "[[070-pi-ui-flex-spacer-pi-patch-task]]"
blocked-by: []
resolved-at: "2026-08-01T08:35:00-04:00"
tags:
- ticket/research
---
# Patched Pi packaging research
## Question
How should the flex-spacer Pi layout patch be packaged in this dotfiles flake so the ordinary `pi` command uses it after rebuild?
## Findings
The flex-spacer change is not an extension-only change.
Pi's interactive mode source adds TUI children directly in `packages/coding-agent/src/modes/interactive/interactive-mode.ts`: header, loaded resources, chat, pending messages, status, widgets above editor, editor, widgets below editor, and footer.
That is the layout stack the flex-spacer must change.
Source: `/nix/store/7dv5wnq7ncw0mrhv5cldj5v6lar7lis7-source/packages/coding-agent/src/modes/interactive/interactive-mode.ts`.
The installed Pi package is the nixpkgs `pi-coding-agent` package at version `0.82.1`.
Its nixpkgs derivation builds from the upstream GitHub tag `v0.82.1`, restores the generated model catalog from the published npm package, builds TypeScript workspace packages, and wraps `$out/bin/pi` with Nix-provided `ripgrep` and `fd` on `PATH` plus default telemetry/version-check environment variables.
Source: `/nix/store/bzc7kf828kg6zlan92766rb2inciclc4-source/pkgs/by-name/pi/pi-coding-agent/package.nix`.
The active installed wrapper confirms the nixpkgs wrapper shape.
`/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/bin/pi` prepends Nix-store `fd` and `rg` paths, sets `PI_SKIP_VERSION_CHECK` and `PI_TELEMETRY`, then execs `.pi-wrapped` inside the same package output.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/bin/pi`.
The current dotfiles Pi module uses Home Manager's `programs.pi-coding-agent` module.
It currently sets `enable`, `settings`, managed extension files, and managed prompt files, but does not override the Pi package.
Source: `modules/agents/pi/pi.nix`.
The Home Manager Pi configuration does expose a `package` option in this evaluated system.
A targeted eval of `home-manager.users.alexion.programs.pi-coding-agent` returned keys including `package`, and an `extendModules` eval setting `home-manager.users.alexion.programs.pi-coding-agent.package = pkgs.pi-coding-agent.overrideAttrs (...)` changed the evaluated package name to `pi-coding-agent-test-0.82.1`.
Source: `nix eval .#nixosConfigurations.neogaia.config.home-manager.users.alexion.programs.pi-coding-agent`; command verification in this research session.
The patch should therefore be applied by overriding `programs.pi-coding-agent.package`, not by installing a competing wrapper or copying a patched tree under home.
A package override keeps the ordinary `pi` command managed by Home Manager and preserves the nixpkgs wrapper behavior unless deliberately changed.
Sources: `modules/agents/pi/pi.nix`; `/nix/store/bzc7kf828kg6zlan92766rb2inciclc4-source/pkgs/by-name/pi/pi-coding-agent/package.nix`.
The safest patch point is source-level patching before the TypeScript build, not post-install editing of generated JavaScript.
The nixpkgs package builds from upstream TypeScript source and already runs the TypeScript build in `buildPhase`, so a `patches = [...]` or `postPatch` override can modify `packages/coding-agent/src/modes/interactive/interactive-mode.ts` and `packages/coding-agent/src/utils/tools-manager.ts` before compiled output is produced.
Source: `/nix/store/bzc7kf828kg6zlan92766rb2inciclc4-source/pkgs/by-name/pi/pi-coding-agent/package.nix`.
The tool lookup hardening belongs in the same package override if the layout patch already overrides Pi.
Upstream `tools-manager.ts` currently treats a local tool path as available if the file exists and treats `spawnSync(cmd, ["--version"])` as success whenever there is no spawn error, without requiring exit status `0`.
On NixOS this allowed an unusable generic Linux `~/.pi/agent/bin/fd` to mask the working Nix `fd` on `PATH`.
Source: `/nix/store/7dv5wnq7ncw0mrhv5cldj5v6lar7lis7-source/packages/coding-agent/src/utils/tools-manager.ts`.
A package override avoids the hardcoded-wrapper problem that a post-install copied package would create.
If we copied the already-built installed package manually, its `bin/pi` script would still contain hardcoded store paths to the original `.pi-wrapped` and original Nix `fd`/`rg` inputs.
Using `pkgs.pi-coding-agent.overrideAttrs` and the original derivation's `postFixup` lets Nix regenerate the wrapper for the patched output.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/bin/pi`; `/nix/store/bzc7kf828kg6zlan92766rb2inciclc4-source/pkgs/by-name/pi/pi-coding-agent/package.nix`.
The likely dotfiles shape is:
```nix
let
patchedPi = pkgs.pi-coding-agent.overrideAttrs (old: {
patches = (old.patches or [ ]) ++ [ ./patches/pi-flex-spacer.patch ];
});
in {
home-manager.users.${user}.programs.pi-coding-agent = {
enable = true;
package = patchedPi;
# existing settings unchanged
};
}
```
If the patch is implemented with `postPatch` instead of a patch file, preserve any upstream `old.postPatch` first.
A patch file is preferable for reviewability because it makes the layout and tool-lookup changes explicit.
## Answer
Package the flex-spacer as a source-level patch to `pkgs.pi-coding-agent` and set `home-manager.users.${user}.programs.pi-coding-agent.package` to that overridden package in `modules/agents/pi/pi.nix`.
Do not package it as a separate extension.
Do not use the throwaway copied tree under `~/.local/share` for deployment.
Do not copy the built package output and edit generated JavaScript unless no source-level override works, because the installed wrapper hardcodes store paths and Nix's original derivation already knows how to rebuild and rewrap Pi correctly.
## Implementation notes
Create a reviewed patch file under the dotfiles Pi module, for example `modules/agents/pi/patches/pi-flex-spacer.patch`.
Patch these upstream source files:
- `packages/coding-agent/src/modes/interactive/interactive-mode.ts`
- `packages/coding-agent/src/utils/tools-manager.ts`
Then override the package in `modules/agents/pi/pi.nix` and assign it to `programs.pi-coding-agent.package`.
The implementation ticket `[[070-pi-ui-flex-spacer-pi-patch-task]]` should prefer this packaging plan.
## Limitations
This research verified the package option by evaluation and inspected the current nixpkgs package source.
It did not build the final override or run the patched source-level derivation.
The upstream Pi source path was realized with `nix build --no-link` during research because the fetched source store path had not yet been materialized.
## Citations
- `modules/agents/pi/pi.nix`.
- `/nix/store/bzc7kf828kg6zlan92766rb2inciclc4-source/pkgs/by-name/pi/pi-coding-agent/package.nix`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/bin/pi`.
- `/nix/store/7dv5wnq7ncw0mrhv5cldj5v6lar7lis7-source/packages/coding-agent/src/modes/interactive/interactive-mode.ts`.
- `/nix/store/7dv5wnq7ncw0mrhv5cldj5v6lar7lis7-source/packages/coding-agent/src/utils/tools-manager.ts`.

View File

@@ -0,0 +1,119 @@
---
status: resolved
parent: "[[070-pi-ui-flex-spacer-pi-patch-task]]"
blocked-by: []
resolved-at: "2026-08-01T08:48:00-04:00"
tags:
- ticket/research
---
# Community Pi packaging research
## Question
How do community Nix or dotfiles projects package patched Pi builds or local Pi extensions, and does that evidence change the planned `programs.pi-coding-agent.package = pkgs.pi-coding-agent.overrideAttrs ...` approach for the flex-spacer patch?
## Findings
Unauthenticated GitHub repository search found several Pi packaging and Pi dotfiles repositories, including `cyprx/pi.nix`, `peedrr/nix-pi-coding-agent`, `rrvsh/pi-coding-agent-nix`, `takinbo/pi-nix`, `tienedev/pi-mono-nix`, `ChauDucToan/pi-flake`, and Pi config/dotfiles repositories such as `devnos/pi-dotfiles` and `maolonglong/dot-pi-agent`.
The cloned survey set did not reveal a community project patching Pi internals for TUI layout.
Sources: `/tmp/pi-community-packaging/repos`; `/tmp/pi-community-packaging/repos/*` inspected below.
Nix packaging projects generally build or wrap Pi as a package rather than editing a live installed tree.
`rrvsh/pi-coding-agent-nix` packages Pi with `pkgs.buildNpmPackage`, fetches the upstream `earendil-works/pi` tag, builds the TypeScript workspaces, replaces workspace symlinks in `postInstall`, wraps `$out/bin/pi` with Nix `ripgrep` and `fd` on `PATH`, and runs a version install check.
Source: `/tmp/pi-community-packaging/repos/rrvsh__pi-coding-agent-nix/nix/pi-coding-agent.nix`.
`peedrr/nix-pi-coding-agent` similarly packages Pi from source with `buildNpmPackage`, fetches `earendil-works/pi`, seeds generated `pi-ai` model data from the published npm tarball, builds TypeScript workspaces, fixes workspace symlinks, and exposes a Nix wrapper module.
Its wrapper module sets `PI_PACKAGE_DIR`, `PI_CODING_AGENT_DIR`, optional resource path environment variables, and includes runtime packages such as `git`, `ripgrep`, `fd`, `gnutar`, and `unzip`.
Sources: `/tmp/pi-community-packaging/repos/peedrr__nix-pi-coding-agent/packages/pi/package.nix`; `/tmp/pi-community-packaging/repos/peedrr__nix-pi-coding-agent/wrapper-module.nix`; `/tmp/pi-community-packaging/repos/peedrr__nix-pi-coding-agent/flake.nix`.
`ChauDucToan/pi-flake` packages Pi from upstream source with Bun and provides Home Manager and NixOS modules.
Its module exposes a package option, then uses `cfg.package` in `home.packages` or `environment.systemPackages`; when extra environment is requested it wraps `cfg.package}/bin/pi` in a `symlinkJoin` wrapper.
It installs extension strings imperatively by running `pi install` during activation.
Sources: `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/package-src.nix`; `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/base-module.nix`; `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/hm-module.nix`; `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/module.nix`.
`takinbo/pi-nix` packages Pi from upstream source with `buildNpmPackage`, exports an overlay that provides `pi`, skips network model generation in `preBuild`, and wraps Node with the Pi CLI plus Nix runtime tools on `PATH`.
It is a full package/overlay pattern, not a live-tree patch pattern.
Source: `/tmp/pi-community-packaging/repos/takinbo__pi-nix/flake.nix`.
`tienedev/pi-mono-nix` packages a prebuilt Pi release tarball rather than source.
It wraps the prebuilt binary with runtime tools and environment settings, and on Linux adds library path support.
This pattern is convenient for distributing an unchanged binary but is a poor fit for our flex-spacer source patch because it provides no TypeScript source-level patch seam.
Source: `/tmp/pi-community-packaging/repos/tienedev__pi-mono-nix/package.nix`; `/tmp/pi-community-packaging/repos/tienedev__pi-mono-nix/README.md`.
`cyprx/pi.nix` has two relevant patterns.
It packages Pi from the published npm tarball in `nix/pi-coding-agent/default.nix`, using `buildNpmPackage`, a vendored lockfile, and a Node wrapper.
It also has `mk-pi.nix`, a composition wrapper that bakes extension derivations into `$out/share/pi-extensions`, dispatches selected extensions via `-e`, and wraps the underlying Pi package with extension runtime inputs.
This supports the idea that extensions and Pi runtime wrapping can be handled declaratively, but it is still a wrapper/composition pattern rather than patching TUI internals through an extension.
Sources: `/tmp/pi-community-packaging/repos/cyprx__pi.nix/nix/pi-coding-agent/default.nix`; `/tmp/pi-community-packaging/repos/cyprx__pi.nix/nix/lib/mk-pi.nix`; `/tmp/pi-community-packaging/repos/cyprx__pi.nix/nix/home-manager-module.nix`.
Pi dotfiles repositories usually deploy extension/config trees rather than patching Pi itself.
`maolonglong/dot-pi-agent` treats the repository as the live `~/.pi/agent` directory, registers `extensions/` and `themes/` through the `package.json` `pi` field, and documents that changes take effect on next Pi launch.
`devnos/pi-dotfiles` copies settings and extension files into `~/.pi/agent`, installs npm dependencies, and replays `pi install` for selected packages.
`abboskhonov/pi-dotfiles` tracks selected `.pi/agent` settings, models, themes, and extensions, while excluding auth, sessions, and binaries.
Sources: `/tmp/pi-community-packaging/repos/maolonglong__dot-pi-agent/README.md`; `/tmp/pi-community-packaging/repos/maolonglong__dot-pi-agent/AGENTS.md`; `/tmp/pi-community-packaging/repos/maolonglong__dot-pi-agent/package.json`; `/tmp/pi-community-packaging/repos/devnos__pi-dotfiles/README.md`; `/tmp/pi-community-packaging/repos/devnos__pi-dotfiles/install.sh`; `/tmp/pi-community-packaging/repos/abboskhonov__pi-dotfiles/README.md`.
The earlier community UI/layout survey remains relevant for the patch-vs-extension boundary.
`0x-rya/pi-local-mods` patches Pi internals for fixed-bottom layout behavior rather than packaging it as an extension, while UI extensions such as `pi-powerline-footer` stay within widget/footer/editor APIs.
This reinforces that the flex-spacer belongs in Pi internals/package patching, while the compact status belongs in an extension.
Sources: `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/README.md`; `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/scripts/apply.py`; `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/README.md`; `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/index.ts`.
No inspected community project showed an established pattern of overriding Home Manager's nixpkgs `programs.pi-coding-agent.package` specifically with `pkgs.pi-coding-agent.overrideAttrs` for a local source patch.
However, multiple community packages expose or use a package option / wrapper composition boundary, and nixpkgs itself exposes the same `programs.pi-coding-agent.package` option in this system as established by `[[072-pi-ui-patched-pi-packaging-research]]`.
The absence of an exact community example does not undermine the plan; it mostly means the plan is using the standard Nix package override seam rather than copying a community recipe.
Sources: `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/base-module.nix`; `/tmp/pi-community-packaging/repos/cyprx__pi.nix/nix/home-manager-module.nix`; `[[072-pi-ui-patched-pi-packaging-research]]`.
## Answer
Community evidence supports, rather than changes, the planned packaging approach.
For a Pi internals change, use a Nix package-level source patch.
For extension/config deployment, use a managed extension/config tree or a package-composition wrapper.
The flex-spacer should remain a source-level patch to `pkgs.pi-coding-agent` assigned through Home Manager's `programs.pi-coding-agent.package` option.
This matches the community norm of treating Pi itself as a Nix package and avoids the fragile live-copy pattern.
The compact status extension should remain separate and dotfiles-managed as an extension.
Community config repositories frequently track or package extensions, and wrapper projects demonstrate declarative extension composition, but none of that makes the flex-spacer extension-only.
## Implications for implementation
Keep `[[070-pi-ui-flex-spacer-pi-patch-task]]` as a Pi package patch task.
Use `[[072-pi-ui-patched-pi-packaging-research]]` as the concrete packaging plan.
This follow-up adds confidence that community patterns do not point to a better wrapper-only or extension-only route.
If implementation wants to reduce rebuild cost or improve modularity later, `cyprx/pi.nix` and `peedrr/nix-pi-coding-agent` are useful references for extension composition and wrapper modules.
They do not replace the need for source patching the layout.
## Limitations
GitHub code search was not authenticated, so this research used repository search, cloned likely repositories, and local grep.
It is not exhaustive.
Some community packages target older Pi package names or versions and are useful for packaging shape, not exact current implementation details.
## Citations
- `/tmp/pi-community-packaging/repos/rrvsh__pi-coding-agent-nix/nix/pi-coding-agent.nix`.
- `/tmp/pi-community-packaging/repos/peedrr__nix-pi-coding-agent/packages/pi/package.nix`.
- `/tmp/pi-community-packaging/repos/peedrr__nix-pi-coding-agent/wrapper-module.nix`.
- `/tmp/pi-community-packaging/repos/peedrr__nix-pi-coding-agent/flake.nix`.
- `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/package-src.nix`.
- `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/base-module.nix`.
- `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/hm-module.nix`.
- `/tmp/pi-community-packaging/repos/ChauDucToan__pi-flake/module.nix`.
- `/tmp/pi-community-packaging/repos/takinbo__pi-nix/flake.nix`.
- `/tmp/pi-community-packaging/repos/tienedev__pi-mono-nix/package.nix`.
- `/tmp/pi-community-packaging/repos/tienedev__pi-mono-nix/README.md`.
- `/tmp/pi-community-packaging/repos/cyprx__pi.nix/nix/pi-coding-agent/default.nix`.
- `/tmp/pi-community-packaging/repos/cyprx__pi.nix/nix/lib/mk-pi.nix`.
- `/tmp/pi-community-packaging/repos/cyprx__pi.nix/nix/home-manager-module.nix`.
- `/tmp/pi-community-packaging/repos/maolonglong__dot-pi-agent/README.md`.
- `/tmp/pi-community-packaging/repos/maolonglong__dot-pi-agent/AGENTS.md`.
- `/tmp/pi-community-packaging/repos/maolonglong__dot-pi-agent/package.json`.
- `/tmp/pi-community-packaging/repos/devnos__pi-dotfiles/README.md`.
- `/tmp/pi-community-packaging/repos/devnos__pi-dotfiles/install.sh`.
- `/tmp/pi-community-packaging/repos/abboskhonov__pi-dotfiles/README.md`.
- `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/README.md`.
- `/tmp/pi-existing-extension-survey/repos/0x-rya__pi-local-mods/scripts/apply.py`.
- `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/README.md`.
- `/tmp/pi-existing-extension-survey/repos/nicobailon__pi-powerline-footer/index.ts`.

View File

@@ -0,0 +1,88 @@
---
status: resolved
parent: "[[061-pi-ui-compact-status-prototype]]"
blocked-by: []
resolved-at: "2026-08-01T00:24:40-04:00"
tags:
- ticket/research
---
# Bottom anchored editor research
## Question
Can Pi extensions make the prompt editor stay anchored to the bottom and grow upward, with autocomplete menus rendered above the editor as overlays that may cover the status bar, or does that require a Pi TUI layout change outside extension APIs?
## Findings
Pi's interactive layout is a linear top-to-bottom component stack.
During initialization, `interactive-mode.js` adds the header container, loaded resources, chat, pending messages, status, widgets above the editor, the editor container, widgets below the editor, and then the footer.
There is no flex spacer, bottom dock, or extension-controlled layout manager in this stack.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`.
Pi extension widgets are limited to persistent content above or below the editor.
The TUI docs document `ctx.ui.setWidget("key", content)` above the editor by default and `{ placement: "belowEditor" }` below it.
The source implementation stores widgets in above or below maps and rerenders those widget containers, but it does not expose a way to move the editor stack to the terminal bottom.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`; `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`.
Replacing or hiding the footer does not bottom-anchor the editor.
`ctx.ui.setFooter()` swaps the footer component, but the footer is still simply the final child in the same linear stack.
An empty custom footer removes footer text, but it does not add a bottom dock or change where previous components render.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`; `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`.
The underlying `Container` component simply concatenates child render lines.
It calls each child's `render(width)` and appends every returned line to one array.
That component model has no layout constraints such as grow, shrink, align-bottom, or overlay-by-default children.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/tui.js`.
Pi's overlay system can draw components at terminal-relative positions, including bottom anchors, but it is separate from the normal editor stack.
The TUI docs document `ctx.ui.custom(..., { overlay: true, overlayOptions: { anchor: "bottom-center", ... } })`, and the TUI implementation pads to the terminal height for overlay placement and composites overlays over existing lines.
This can place a separate component at the bottom, but it does not make the built-in editor itself bottom anchored.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`; `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/tui.js`.
Extensions can replace the editor component with `ctx.ui.setEditorComponent()`.
The docs describe this for custom editor behavior, and the implementation creates the custom editor inside the existing `editorContainer`, copies the default editor submit/change handlers, copies autocomplete providers when supported, and focuses the replacement editor.
This is enough to change editor rendering and autocomplete order inside the editor component, but not enough to change the editor container's position in the main stack.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`; `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`.
The built-in editor currently renders autocomplete below the editor box.
In `Editor.render()`, it renders the top border, visible editor lines, bottom border, and then appends `autocompleteList.render(contentWidth)` when autocomplete is active.
Therefore the current menu pushes content below the editor rather than overlaying above it.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/components/editor.js`.
A custom editor subclass could probably move the autocomplete list above the prompt box because the default editor's autocomplete state and list are normal JavaScript fields in the distributed code.
However, that would be a fragile implementation detail rather than a public autocomplete-placement API, and it would still leave the editor container in the linear top-flow layout.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/components/editor.js`; `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`.
A pure extension hack could render blank lines in an above-editor widget to push the editor downward.
That would require estimating the height of all content above the widget from terminal rows and previous render state, and it would be vulnerable to streaming output, overlays, terminal resize, autocomplete, and other extensions.
No public Pi extension API provides the needed stable measurement or a flexible spacer primitive.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`; `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/tui.js`.
## Answer
Pi extensions cannot cleanly make the built-in prompt editor stay bottom anchored and grow upward with the current public APIs.
They can hide or replace the footer, add widgets above or below the editor, replace the editor component inside the same editor slot, and show independent overlays.
Those APIs do not move the editor slot to the bottom of the terminal or make autocomplete an above-editor overlay.
The desired behavior should be specified as a Pi TUI layout change, not as a durable extension-only implementation.
The likely core change is a bottom-docked input area whose fixed bottom stack contains status, editor, and optional footer, while the transcript area occupies the remaining space above it.
Autocomplete should be rendered as an overlay anchored immediately above the editor, with status as lower-priority content it may cover.
## Implementation implications
For the current prototype, keep the compact status widget and hidden footer as a visual draft, but do not treat its remaining dead space as fixable through `setWidget()`.
A short-term experiment may subclass `CustomEditor` to render autocomplete above the editor, but that should be labeled a throwaway spike.
The robust path is an upstream Pi change or local Pi patch that introduces bottom docking and editor-owned overlay autocomplete placement.
## Limitations
This research is based on the installed Pi 0.82.1 documentation and distributed JavaScript source.
It did not patch Pi or build a replacement TUI layout.
## Citations
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/tui.md`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/dist/modes/interactive/interactive-mode.js`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/tui.js`.
- `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/node_modules/@earendil-works/pi-tui/dist/components/editor.js`.

View File

@@ -0,0 +1,50 @@
---
status: complete
tags:
- wayfinder/map
---
# Slice skill
## Destination
Implement a packaged `slice` skill in the skills repository.
The skill turns a settled plan, spec, conversation, or artifact into Wayfinder task tickets for tracer-bullet implementation slices.
## Notes
The skill name is `slice`.
The repository source lives under `skills/slice/`.
Runtime enablement in dotfiles or another consumer repository is out of scope.
The skill should produce Wayfinder-compatible `ticket/task/afk` and `ticket/task/human` artifacts in the resolved AI-artifacts project destination, using that destination's naming and wikilink conventions.
The user's invocation is sufficient permission to slice the provided source material.
Implementation slices are destination work, not Wayfinder decision tickets.
The skill should not create `.claude/tasks/` files.
Task-ticket bodies should include implementation-oriented sections such as `## What to build`, `## Acceptance criteria`, and `## Implementation Notes` when useful.
`## Implementation Notes` may contain concise handoff guidance from slicing and later execution notes from the implementing agent.
## Frontier
None.
## Decisions so far
Preserve the old `to-tasks` source-intake, optional codebase exploration, tracer-bullet slicing, prefactoring-first bias, review loop, blockers, acceptance criteria, and anti-stale-detail guidance, but replace `.claude/tasks` output, feature-slug metadata, four-digit numbering, filename-stem blockers, and legacy completion semantics with Wayfinder artifacts.
Preserve Matt Pocock's explicit invocation, broad source intake, tracer-bullet discipline, blocker and frontier model, review loop, useful issue-body semantics, and wide-refactor expand-contract exception, adapt sizing toward coherent single-commit slices rather than fresh-context limits, and replace tracker, `.scratch`, label, native-link, and parent-issue mechanics with Wayfinder task-ticket artifacts.
Create open, unclaimed Wayfinder task tickets in the resolved artifact destination, use destination naming, identifier, wikilink, parent, blocker, status, claim, and Frontier rules, keep implementation detail in task artifacts rather than maps, and treat research, prototype, and grill tickets as planning work rather than implementation slices.
The implementation-ready `slice` specification defines explicit invocation, broad source handling, destination and parent resolution, coherent single-commit tracer-bullet slicing, the wide-refactor exception to strict vertical slicing, Wayfinder blocker and Frontier semantics, AFK versus human task classification, task body structure, review-before-write behavior, and verification expectations.
The packaged skill source lives at `skills/slice/SKILL.md`, is explicitly invoked, writes Wayfinder task artifacts rather than legacy `.claude/tasks`, and was tightened through `/design-skill` structural review.
`nix flake check "path:$PWD"` passes and verifies that the repository discovers and packages the new `slice` skill.
## Result
The packaged `slice` skill is implemented at `skills/slice/SKILL.md` and repository verification passes.
## Not yet specified
None.
## Out of scope
Enabling the skill in dotfiles or another consumer repository is outside this map.
Writing legacy `.claude/tasks/` files is outside this map.

View File

@@ -0,0 +1,61 @@
---
status: resolved
parent: "[[031-slice-skill-map]]"
blocked-by: []
claimed-by: "019fbb2a-dbcd-79d2-ae72-c5bcdd1d714e"
claimed-at: "2026-07-31T22:57:30-04:00"
tags:
- ticket/research
---
# Slice skill old to-tasks research
## Question
What behavior should `slice` preserve, adapt, or reject from the old local `to-tasks` skill?
## Findings
The old skill accepts source material from the current conversation or an explicit argument such as a spec path, and only derives a feature slug when a `.claude/spec/<feature-slug>.md` source exists.
`slice` should preserve the source-material flexibility but reject the `.claude/spec`-specific slug contract because Wayfinder artifact provenance and parent links replace that field.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/SKILL.md`.
The old skill treats codebase exploration as optional when the agent has not already explored the area.
It says task titles and descriptions should use the project's domain glossary vocabulary and respect ADRs, and it explicitly looks for prefactoring that makes the implementation easier before slicing.
`slice` should preserve this behavior, but resolve glossary and ADR context through the active project and artifact destination rather than Claude-specific paths.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/SKILL.md`.
The core slicing rule is durable: each slice is a tracer bullet that delivers a narrow complete path through every layer the change requires, is demoable or verifiable on its own, and puts any prefactoring first.
`slice` should preserve this as a central contract.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/SKILL.md`.
The old skill requires a user review loop before writing task files.
It presents the proposed breakdown with file stem, blockers, and covered user stories when available, then asks whether granularity, dependency relationships, and merge or split choices are correct.
`slice` should preserve review-before-write by default, while allowing an explicitly noninteractive caller mode only if the new skill chooses to support one.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/SKILL.md`.
The old global numbering sequence is a legacy `.claude/tasks` mechanic.
It scans for the highest four-digit prefix under `.claude/tasks/` and never restarts per feature.
`slice` should reject that mechanism because Wayfinder artifacts use the AI-artifacts destination's naming and identifier allocation rules instead.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/SKILL.md`.
The old `blocked-by` field is a durable dependency concept but not a reusable representation.
It stores permanent dependencies by full task filename stem and treats a slice as pickable when every blocker has all acceptance criteria resolved.
`slice` should preserve permanent blocking edges and frontier pickability, but adapt them to Wayfinder `blocked-by` wikilinks and ticket statuses.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/TASK-FORMAT.md`.
The old body format is worth carrying forward in adapted form.
It uses `## What to build` for a concise end-to-end behavior description and `## Acceptance criteria` for checklist completion.
It also says not to include brittle file paths or code snippets unless a prototype snippet encodes a settled decision more precisely than prose can.
`slice` should preserve these body sections and the anti-staleness rule inside Wayfinder task tickets.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/TASK-FORMAT.md`.
The old completion model is acceptance-criteria-centered.
A task is done when every criterion is checked as satisfied or deliberately dropped, with dropped work recorded in Implementation Notes by the implementation flow.
`slice` should preserve acceptance criteria as execution checklist content, but final lifecycle state must be the Wayfinder ticket `status` rather than a separate `.claude/tasks` convention.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/TASK-FORMAT.md`.
## Conclusion
`slice` should preserve the old skill's flexible source intake, optional codebase exploration, tracer-bullet vertical slicing, prefactoring-first bias, default user review loop, permanent blocker semantics, end-to-end task body, acceptance criteria, and anti-stale-detail guidance.
It should reject `.claude/tasks` output, `.claude/spec` feature-slug metadata, four-digit task numbering, filename-stem blockers, and `.claude/tasks` completion semantics in favor of Wayfinder artifacts.

View File

@@ -0,0 +1,175 @@
---
status: resolved
parent: "[[031-slice-skill-map]]"
claimed-by: "019fbb2a-dbcd-79d2-ae72-c5bcdd1d714e"
claimed-at: "2026-07-31T23:19:15-04:00"
blocked-by:
- "[[032-slice-skill-old-to-tasks-research]]"
- "[[036-slice-skill-matt-to-tickets-research]]"
- "[[037-slice-skill-wayfinder-contract-research]]"
tags:
- ticket/task/afk
---
# Slice skill implementation spec
## Question
Produce an implementation-ready specification for the `slice` skill.
## What to build
Write the skill specification that a later implementation step can translate directly into `skills/slice/SKILL.md` and any support files.
The spec should define invocation inputs, source-material handling, Wayfinder parent resolution, task-ticket artifact creation, blocking-edge rules, AFK versus human task classification, user review before writes, and verification expectations.
## Specification
### Purpose
`slice` turns settled source material into implementation-ready Wayfinder task tickets.
The source material may be a plan, spec, current conversation, issue text, existing artifact, or other explicit reference supplied by the caller.
The output is a set of open, unclaimed Wayfinder `ticket/task/afk` and `ticket/task/human` artifacts that represent tracer-bullet implementation slices.
### Invocation boundary
`slice` is explicitly invoked.
It should not be implicitly selected by the model because it writes multiple durable handoff artifacts and shapes future implementation work.
The caller's invocation is sufficient permission to slice the provided source material.
The skill does not require the source map to be complete, and it does not second-guess the user's decision to slice.
If the source material clearly contains unresolved planning questions rather than settled implementation input, `slice` should surface that as a problem in the proposed breakdown rather than inventing implementation work.
### Source handling
The skill works from conversation context first.
If the caller passes paths, artifact links, issue references, or URLs, the agent reads the referenced body and relevant comments or surrounding artifact context before slicing.
When source material names a Wayfinder artifact, that artifact should be the default provenance parent.
When no source artifact exists, use the active map if one is clear from context.
When neither exists, create or select the minimal Wayfinder parent required by the artifact contract rather than writing orphaned task tickets.
The agent may explore the codebase when the current implementation state is not already understood.
Titles and descriptions should use the project's established vocabulary and respect relevant ADRs or context artifacts.
The agent should look for prefactoring that makes the change easier before slicing implementation behavior.
### Artifact destination and naming
Resolve the artifact destination before naming files.
Use an explicitly supplied destination directory exactly.
Otherwise use Wayfinder's default destination resolution.
Read the destination's `AGENTS.md` before any artifact write.
Follow the destination's naming, identifier allocation, slug, and wikilink conventions.
For the AI-artifacts vault, project artifacts are flat files named `<NNN>-<scope-slug>[-<subject-slug>]-<artifact-type>.md`.
Task slice artifacts use the `task` artifact-type suffix because Wayfinder forbids `ticket` as a ticket filename suffix.
Allocate identifiers by incrementing the vault root `.counter` before artifact creation when the destination convention requires identifiers.
Preserve identifiers and update wikilinks if any file is renamed.
### Slicing discipline
Each normal slice is a tracer bullet.
It must deliver a narrow complete path through every layer the change requires, not a horizontal layer-only chunk.
A completed slice must be demoable or verifiable on its own.
A slice should make sense as one coherent commit.
Prefactoring that makes the implementation easy should appear before dependent behavior slices.
Wide mechanical refactors are the exception to strict vertical slicing.
When one mechanical change has a blast radius that prevents any vertical slice from landing green, use expand-contract sequencing instead of forcing artificial vertical slices.
Create an expand task that adds the new form beside the old one, migration batch tasks sized by blast radius, and a contract task blocked by all migrations.
If migration batches cannot stay green alone, preserve the sequence but identify the integration-branch constraint and add a final integrate-and-verify task.
### Blocking edges and Frontier
Every slice declares its blockers.
Use Wayfinder `blocked-by` wikilinks, not filename stems, issue IDs, or prose-only references.
Use `parent` only for provenance.
Use `blocked-by` for prerequisites that must resolve before the slice is actionable.
A slice with no blockers can be worked immediately.
After writing task artifacts, re-read the map and recompute its Frontier from ticket metadata.
Open, unclaimed, unblocked task tickets belong on the Frontier.
### AFK versus human tasks
Use `ticket/task/afk` when an agent can complete and verify the slice without live human input.
Use `ticket/task/human` when execution or validation depends on the user, such as subjective UI judgment, physical device checks, credentials the agent cannot access, or behavior only the human can confirm.
Do not mark a task human merely because it is important.
Make the required human involvement precise in the task body.
### Task artifact shape
Each created slice task starts with Wayfinder frontmatter:
```markdown
---
status: open
parent: "[[<source-artifact-or-map>]]"
blocked-by: []
tags:
- ticket/task/afk
---
```
Use `ticket/task/human` for human-dependent slices.
The body contains:
```markdown
# <task name>
## Question
<one precise implementation action sized to one agent session>
## What to build
<concise end-to-end behavior or implementation result, not a layer-by-layer checklist>
## Acceptance criteria
- [ ] <observable criterion>
## Implementation Notes
<concise handoff guidance when useful>
```
`## Implementation Notes` may be empty when no guidance is useful.
Later implementing agents may append execution notes, verification results, and reasons for deliberately dropped criteria.
Avoid brittle file paths and code snippets unless a prototype or prior decision snippet encodes the decision more precisely than prose can.
### Review loop
Before writing artifacts, present the proposed breakdown and wait for approval unless the caller explicitly asks for noninteractive output.
For each proposed slice show the title, task type, blockers, what it delivers, and relevant user stories or source requirements.
Ask the user to validate granularity, blocking edges, and whether any slices should be merged or split.
Iterate until the breakdown is approved.
In explicitly noninteractive mode, write the best breakdown and record any assumptions in `## Implementation Notes`.
### Relationship to other Wayfinder tickets
`slice` creates implementation task tickets.
It does not create research, prototype, or grill tickets as part of normal slicing.
If slicing reveals a precise unresolved planning question, report it and either stop or create the appropriate Wayfinder ticket only when the caller asks for that planning work.
Implementation detail belongs in task artifacts, not in the map's Decisions so far.
The map records only concise route decisions and keeps the Frontier as its only ticket-link section.
### Verification expectations
The implemented skill should be packaged as `skills/slice/SKILL.md` in this repository.
It should not write `.claude/tasks/` as an output target.
It may mention the legacy format only to say it is intentionally replaced.
Repository verification should include `nix flake check "path:$PWD"` while the new skill files are untracked.
## Acceptance criteria
- [x] The spec states that `slice` creates Wayfinder `ticket/task/afk` and `ticket/task/human` artifacts rather than legacy `.claude/tasks/` files.
- [x] The spec explains how `slice` resolves the artifact destination and chooses the parent artifact or map according to Wayfinder artifact rules.
- [x] The spec preserves tracer-bullet vertical slicing and the wide-refactor expand-contract exception.
- [x] The spec defines task body sections for `## What to build`, `## Acceptance criteria`, and `## Implementation Notes`.
- [x] The spec requires a review loop before writing artifacts unless the caller explicitly asks for noninteractive output.
- [x] The spec distinguishes implementation task tickets from Wayfinder research, prototype, and grill decision tickets.
## Implementation Notes
The specification uses the old `to-tasks`, Matt `to-tickets`, and Wayfinder contract research as its evidence base.
Sizing is specified around coherent single commits rather than fresh context windows.
The wide-refactor exception is framed as an exception to strict vertical slicing.
Keep the implementation focused on skill behavior rather than adding repository-specific execution helpers.

View File

@@ -0,0 +1,39 @@
---
status: resolved
parent: "[[031-slice-skill-map]]"
claimed-by: "019fbb2a-dbcd-79d2-ae72-c5bcdd1d714e"
claimed-at: "2026-07-31T23:27:00-04:00"
blocked-by:
- "[[033-slice-skill-implementation-spec-task]]"
tags:
- ticket/task/afk
---
# Slice skill source
## Question
Implement the packaged `slice` skill source from the approved implementation-ready specification.
## What to build
Use `/design-skill` to add the `slice` skill under the repository's packaged skill source tree.
The skill should guide agents through slicing source material into Wayfinder task tickets, including artifact destination handling, review-before-write behavior, blocking-edge recording, and implementation-oriented task bodies.
## Acceptance criteria
- [x] `/design-skill` has been applied to draft and verify the skill structure.
- [x] `skills/slice/SKILL.md` exists and follows the approved specification.
- [x] Any companion reference files needed by the skill live under `skills/slice/`.
- [x] The skill description is concise and accurately describes when to use `slice`.
- [x] The skill does not instruct agents to write `.claude/tasks/` files.
- [x] The skill uses Wayfinder artifact terminology consistently with `ARTIFACTS.md`.
## Implementation Notes
Created `skills/slice/SKILL.md` with `disable-model-invocation: true`.
No companion reference files were needed.
The skill source embeds the minimum Wayfinder ticket contract and tells agents to follow destination artifact conventions.
Applied `/design-skill` structurally by checking invocation mode, information hierarchy, completion criteria, duplication, sediment, sprawl, no-op behavior, and leading-word fit against `skills/design-skill/GLOSSARY.md`.
A headless Pi smoke-test with `--skill skills/slice` did not reliably exercise the user-invoked skill and produced horizontal slices, so I tightened the skill text to reject layer-only slices and to give an exact review shape.
The smoke-test evidence is under `/tmp/slice-smoke/`.

View File

@@ -0,0 +1,33 @@
---
status: resolved
parent: "[[031-slice-skill-map]]"
claimed-by: "019fbb2a-dbcd-79d2-ae72-c5bcdd1d714e"
claimed-at: "2026-07-31T23:33:26-04:00"
blocked-by:
- "[[034-slice-skill-source-task]]"
tags:
- ticket/task/afk
---
# Slice skill package verification
## Question
Verify that the new `slice` skill is correctly packaged by the skills repository.
## What to build
Run the repository validation required for a newly added untracked skill source and fix any packaging or formatting issues that appear.
## Acceptance criteria
- [x] `nix flake check "path:$PWD"` passes.
- [x] The new `slice` skill is included by the repository's skill discovery.
- [x] No generated skill links are edited as source.
## Implementation Notes
Ran `nix flake check "path:$PWD"` from `/home/alexion/wrk/skills`.
The check passed and evaluated `packages.x86_64-linux.slice` plus `checks.x86_64-linux.slice`.
The command warned that incompatible systems `aarch64-darwin` and `aarch64-linux` were omitted.
`git status --short` shows only the new untracked `skills/slice/` source directory inside this repository.

View File

@@ -0,0 +1,69 @@
---
status: resolved
parent: "[[031-slice-skill-map]]"
blocked-by: []
claimed-by: "019fbb2a-dbcd-79d2-ae72-c5bcdd1d714e"
claimed-at: "2026-07-31T22:58:13-04:00"
tags:
- ticket/research
---
# Slice skill Matt to-tickets research
## Question
What behavior should `slice` preserve, adapt, or reject from Matt Pocock's `to-tickets` skill?
## Findings
Matt Pocock's skill is explicitly non-implicit.
Its frontmatter disables model invocation, and its OpenAI agent policy sets `allow_implicit_invocation: false`.
`slice` should likely preserve explicit invocation as a safety boundary because it writes multiple handoff artifacts and can shape future implementation work.
Sources: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`, `/home/alexion/Downloads/skills/skills/engineering/to-tickets/agents/openai.yaml`.
The input model is broader than a spec file.
`to-tickets` can break down a plan, spec, current conversation, issue number, or URL, and it fetches full issue bodies and comments for issue references.
`slice` should preserve broad source intake and avoid spec-only naming or behavior.
Sources: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`, `/home/alexion/Downloads/skills/docs/engineering/to-tickets.md`.
The central output concept is a set of tracer-bullet vertical slices with blocking edges.
Each slice cuts through all relevant integration layers, avoids horizontal layer-only work, is demoable or verifiable on its own, and puts prefactoring first.
Matt's source skill sizes each slice for a single fresh context window, but `slice` should adapt sizing toward a coherent single commit instead of making context-window size the main boundary.
Source: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`.
Blocking edges are the main handoff contract.
Every ticket declares the tickets that block it, tickets with no blockers can start immediately, and the frontier is the set whose blockers are all done.
`slice` should preserve this model, but represent edges as Wayfinder `blocked-by` wikilinks and use Wayfinder ticket status to determine the frontier.
Sources: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`, `/home/alexion/Downloads/skills/docs/engineering/to-tickets.md`.
The review loop is part of the source skill's safety model.
It presents title, blockers, and delivered behavior for each proposed ticket, then asks about granularity, blocking edges, and merge or split choices before publishing.
`slice` should preserve review-before-write by default because artifact creation fixes names, identifiers, and dependency structure.
Source: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`.
The local-file versus real-tracker split is source-specific.
Matt's skill publishes either `.scratch/<feature>/issues/<NN>-<slug>.md` local files or real tracker issues with native blocking links and `ready-for-agent` labels.
`slice` should reject that publishing abstraction and target Wayfinder artifacts only, because this skill's destination is the AI-artifacts project destination rather than an issue tracker.
Sources: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`, `/home/alexion/Downloads/skills/docs/engineering/to-tickets.md`.
The issue templates overlap with Wayfinder metadata but still supply useful execution-body semantics.
Matt's template includes parent reference, end-to-end `What to build`, acceptance criteria, and `Blocked by`.
Wayfinder already owns parent and blocker representation through frontmatter, while `slice` should preserve `What to build` and `Acceptance criteria` as task body sections and optionally add `Implementation Notes` for handoff and execution details.
Source: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`.
The wide-refactor exception is important enough to preserve.
A wide mechanical refactor should not be forced into vertical slices when no slice can land green.
It should be sequenced as expand, migration batches, and contract, with an integration-branch and final integrate-and-verify step only when batches cannot stay green alone.
`slice` should include this exception so agents do not cargo-cult vertical slicing into unsuitable refactors.
Sources: `/home/alexion/Downloads/skills/skills/engineering/to-tickets/SKILL.md`, `/home/alexion/Downloads/skills/docs/engineering/to-tickets.md`.
The documentation frames `to-tickets` as a step after an agreed plan or written spec, not as the planning skill itself.
It says to produce a spec first if the change has not been written up.
`slice` should preserve that boundary in Wayfinder terms: it should slice source material the caller treats as settled enough to implement, not resolve unresolved design fog.
Source: `/home/alexion/Downloads/skills/docs/engineering/to-tickets.md`.
## Conclusion
`slice` should preserve Matt Pocock's explicit invocation, broad source intake, tracer-bullet discipline, blocker/frontier model, review loop, useful issue-body semantics, and wide-refactor expand-contract exception.
It should adapt sizing toward coherent single-commit slices rather than emphasizing fresh-context-window limits.
It should reject the configured-tracker prerequisite, `.scratch` local-file output, real issue tracker publishing, `ready-for-agent` labels, platform-native blocker links, and tracker-specific parent issue behavior in favor of Wayfinder task-ticket artifacts.

View File

@@ -0,0 +1,76 @@
---
status: resolved
parent: "[[031-slice-skill-map]]"
blocked-by: []
claimed-by: "019fbb2a-dbcd-79d2-ae72-c5bcdd1d714e"
claimed-at: "2026-07-31T22:58:59-04:00"
tags:
- ticket/research
---
# Slice skill Wayfinder contract research
## Question
What Wayfinder artifact rules must `slice` follow when creating implementation task tickets?
## Findings
Wayfinder normally plans rather than implements.
It creates a durable map of questions whose resolutions are decisions, findings, prototypes, or completed prerequisites, and says implementing the destination usually marks the edge of the map and the handoff point.
`slice` therefore needs an explicit contract that it creates implementation handoff tickets only when invoked, rather than silently turning unresolved planning fog into destination work.
Source: `/home/alexion/.pi/agent/skills/wayfinder/SKILL.md`.
The user-facing reference rule is human-readable artifact titles through the destination's link style, not bare identifiers or slugs.
`slice` should present proposed and written artifacts by wikilink title such as `[[034-slice-skill-source-task]]`, not by an unlinked filename stem or numeric identifier alone.
Source: `/home/alexion/.pi/agent/skills/wayfinder/SKILL.md`.
Artifact destinations are resolved before naming files.
When a caller provides a destination directory, it must be used exactly.
Otherwise the default is `$(xdg-user-dir DOCUMENTS)/ai-artifacts/projects/<project>` when the AI-artifacts vault exists, falling back to `./docs` in the current project.
`slice` must read the destination's `AGENTS.md` before writing artifacts.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
This vault's project artifact convention is flat and identifier-bearing.
Project Markdown artifacts are named `<NNN>-<scope-slug>[-<subject-slug>]-<artifact-type>.md`, with identifiers allocated by incrementing the vault root `.counter` before artifact creation.
The creating skill chooses the artifact-type slug, but Wayfinder ticket filenames use `research`, `prototype`, `grill`, or `task`, and maps should use the normal `map` artifact-type suffix.
Sources: `/home/alexion/Documents/ai-artifacts/AGENTS.md`, `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Wayfinder maps are route summaries, not stores for detailed ticket results.
Only the Frontier links to tickets or other artifacts, Decisions so far contains concise plain-language decisions without links, and map status is open while live tickets or fog remain.
`slice` should not store implementation slice bodies in the map.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Wayfinder tickets are self-resolving artifacts with authoritative metadata.
A new ticket has `status: open`, a singular `parent` wikilink, `blocked-by: []`, and one ticket tag.
Task tickets use `ticket/task/afk` or `ticket/task/human`.
`slice` should create one implementation slice per Wayfinder task ticket and choose AFK when an agent can complete it without live human input, or human when the task's execution or validation requires the user.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
`parent` and `blocked-by` mean different things.
`parent` records provenance, while `blocked-by` records upstream artifacts that must resolve before the ticket becomes actionable.
A ticket is on the Frontier when it is open, every blocker is satisfied, and it has no claim.
`slice` should put the source artifact or map in `parent`, and put prerequisite slices or unresolved prerequisite artifacts in `blocked-by`.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Claims are part of the execution protocol and should not be pre-created by `slice`.
A ticket is claimed only when an agent is about to work it, by setting `status: claimed`, `claimed-by`, and `claimed-at` before doing work.
`slice` should create open unclaimed task tickets, then recompute the map Frontier.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Research and prototype tickets have called-skill completion contracts, while task tickets perform prerequisite work where possible or give the human a checklist.
Because `slice` output is implementation work, it should not create research, prototype, or grill tickets unless slicing reveals a precise unresolved planning question instead of an implementation slice.
Source: `/home/alexion/.pi/agent/skills/wayfinder/SKILL.md`.
The existing full map in the dotfiles project shows the artifact style in practice: a map artifact `[[002-pi-subagents-map]]`, decision summaries in the map, task tickets such as `[[026-pi-subagents-dotfiles-deployment-task]]` and `[[027-pi-subagents-implementation-spec-task]]`, and detailed task results living in those task artifacts rather than in the map.
Some completed historical tickets use `status: done`, but the current Wayfinder artifact contract lists `resolved` as the resolved ticket status, so `slice` should follow the current contract rather than copying that older status spelling.
Sources: `/home/alexion/Documents/ai-artifacts/projects/dotfiles/002-pi-subagents-map.md`, `/home/alexion/Documents/ai-artifacts/projects/dotfiles/026-pi-subagents-dotfiles-deployment-task.md`, `/home/alexion/Documents/ai-artifacts/projects/dotfiles/027-pi-subagents-implementation-spec-task.md`, `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Concurrent writes require re-reading shared artifacts immediately before editing them and reconciling duplicate identifiers or filenames after parallel creation.
`slice` should allocate artifact identifiers sequentially, create approved task artifacts, then re-read and repair the map Frontier after the files exist.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
## Conclusion
`slice` must write open, unclaimed Wayfinder task tickets in the resolved artifact destination, using destination naming, identifier, wikilink, parent, blocker, status, claim, and Frontier rules.
It should keep implementation slice detail in each task artifact, not the map, and it should treat research, prototype, and grill tickets as planning work rather than implementation slices.

View File

@@ -0,0 +1,62 @@
---
status: complete
tags:
- wayfinder/map
---
# Implement workflow
## Destination
Create an implementation-ready plan for migrating the packaged implementation workflow to Wayfinder-aware skills in this skills repository.
The route ends when the `implement`, `test-driven-development`, and review skill contracts, dependencies, artifact lifecycle, git and PR handling, and migration scope are decided enough to hand off implementation.
## Notes
The workflow includes packaged `implement`, `test-driven-development`, and review skills.
The review skill is named `review`.
The old Claude Code skill sources live under `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/test-driven-development/`, and `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/review-uncommitted/`.
The new packaged skill sources, if implemented later, would live under `skills/implement/`, `skills/test-driven-development/`, and `skills/review/` in this repository.
Runtime enablement in dotfiles or another consumer repository is out of scope unless a later decision explicitly broadens the destination.
Wayfinder-aware implementation should work with Wayfinder task tickets and preserve useful execution, review, commit, and PR mechanics from the old workflow only where they still fit the artifact contract.
Research comes before HITL decisions.
## Frontier
None.
## Decisions so far
The migration scope includes the complete implementation workflow: packaged `implement`, packaged `test-driven-development`, and packaged `review`.
Preserve explicit task selection, blocker safety, conservative git branching from `main`, no automatic stashing or destructive resets, TDD where appropriate, regular verification, specific staging, pre-commit review, deviation notes, one commit per task, and useful PR reporting, but adapt task identity, blocker readiness, branch naming, spec source, task closeout, PR references, and lifecycle state from legacy `.claude/tasks` conventions to Wayfinder task-ticket artifacts.
Execute exactly one actionable implementation task ticket per session at a time, claim it in metadata before code changes, respect `blocked-by` and existing claims, record implementation results in the same ticket artifact, transition it to `resolved`, and repair the owning map's Frontier without storing implementation detail in the map.
HITL task tickets can be implemented until they reach the point requiring human input, where the skill must pause and surface the precise human checkpoint.
Create dedicated follow-up research for Matt Pocock's `implement`, `to-tickets`, `tdd`, `code-review`, and `wayfinder` skills, but not for handoff skills unless the destination expands to session handoff automation.
Use Matt Pocock's `implement` as a simplicity reference, but keep stricter local handling for Wayfinder claiming, branch setup, artifact closeout, and PR or handoff reporting.
Preserve Matt Pocock's tracer-bullet, blocker, frontier, and wide-refactor concepts from `to-tickets`, but reject tracker labels and issue-specific publication mechanics in favor of Wayfinder task metadata.
Preserve public-seam, anti-tautology, one-test-at-a-time TDD discipline, while leaving the timing and authority of refactoring as a human decision.
Use the Wayfinder task as the primary review spec source, preserve separate Standards and Spec axes plus the smell baseline, and decide whether to retain the local Risk axis and pre-commit review timing.
Adapt Matt Pocock's Wayfinder planning-versus-execution boundary, HITL protection, and frontier/claim concepts, while rejecting tracker-specific labels, child-issue assumptions, assignee claims, issue IDs, and native blocking mechanics.
Learn from Kun Chen's `no-mistakes` that preventing AI slop requires a fixed ordered gate, rich intent, isolated validation, structured findings, bounded auto-fix, human escalation for judgment calls, trusted validation configuration, and CI-backed proof before public handoff.
Worktree isolation is expected to be essential for parallel Wayfinder implementation.
Treehouse leasing is the strongest candidate when available: acquire an isolated reusable worktree, create or check out the task branch inside it, record lease identity in the ticket, avoid destructive cleanup when dirty, and release with identity checks after successful handoff.
Keep Herdr worktree and pane orchestration external to the core skill unless the destination expands, while remaining compatible with Herdr-managed worktrees, setup hooks, and `.worktreeinclude`-style ignored-file copying.
Do not package `codebase-design` as part of this workflow; fold the small amount of useful seam and public-interface testing guidance into `test-driven-development` and `review` instead.
Treat worktree orchestration, dirty-repo guards, lease cleanup, visible Herdr panes, and multi-agent execution as Pi extension or external-tool integrations outside this skill migration.
The `implement` skill defines execution protocol rather than policing admissible work sources: when selected work has a Wayfinder task artifact it follows Wayfinder claim, blocker, result, resolution, and Frontier protocol, and when no artifact exists the implementation artifact is simply the working code plus normal review, commit, and handoff output.
The `implement` skill is worktree-compatible rather than a worktree orchestrator: it assumes the session already has the right checkout, checks dirty state, never auto-stashes, uses or creates a non-default branch from an updated default branch when needed, follows repository, user, or orchestrator branch naming, preserves the old blocker-reachability guardrail, and only uses integration-branch or wide-refactor branch strategy when the plan explicitly calls for that exception.
The review skill is named `review`; it selects a context-appropriate change set, states that scope, emits a structured report rather than a gate artifact or pass/fail verdict, covers Risk, Standards, Intent, Evidence, and Documentation when applicable, may run targeted checks, remains report-only, uses independent dimension reviewers with single-agent fallback, keeps reviewer prompts as self-contained files under the skill directory, and preserves ambiguity where agent judgment is useful.
The `test-driven-development` skill folds in minimal public-interface and seam guidance instead of depending on packaged `codebase-design`, requires tests to be written by someone other than the implementation agent with an explicit fallback only when independent workers are unavailable, isolates the implementation agent's behavior backlog from the test writer, runs red-green one behavior at a time, requires independent expected-value sources, forbids implementation agents from editing test-writer-authored tests, and preserves the old local refactor-after-green behavior.
The code is the implementation artifact; Wayfinder task closeout records durable coordination facts only, uses `status` as lifecycle authority, may update acceptance-criterion checkboxes as useful detail, keeps Implementation Notes concise, leaves partial or ambiguous outcome disposition to agent judgment, and must keep lifecycle recording honest.
No extras are in scope beyond the packaged `implement`, `test-driven-development`, and `review` skills: do not add legacy `.claude/tasks` compatibility shims, dedicated worktree-extension documentation, Herdr integration, or Treehouse integration.
The `implement` skill uses `test-driven-development` as a strong default when behavior can usefully be specified and tested before implementation, consumes it as process discipline rather than a report artifact, must run `review` before final handoff or Wayfinder task resolution, lets the agent choose review timing as long as review covers the final intended handoff state, fixes or explicitly accepts blocking review findings, uses judgment for non-blocking findings, and prescribes no other supporting skill invocations.
## Not yet specified
None.
## Out of scope
Implementing the migrated skills is outside this map until the route is complete and the user explicitly asks for destination work.
Building a Pi extension for worktree orchestration, dirty-repo guards, lease cleanup, visible Herdr panes, or multi-agent execution is outside this skill migration.
The skill workflow should remain compatible with such an extension.

View File

@@ -0,0 +1,67 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:42:05-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement skill old workflow research
## Question
What behavior should the migrated `implement` skill preserve, adapt, or reject from the old local `/implement` skill and the old skills it depends on?
## Findings
The old `/implement` skill is task-file driven and explicitly refuses to infer a task from context.
It expects a `.claude/tasks/<NNNN>-slug.md` path produced by `/to-tasks`, checks any `blocked-by` entries by reading referenced task files, and treats a blocker as unresolved if it has any unchecked acceptance criterion.
A Wayfinder-aware migration should preserve explicit work selection, but adapt readiness checks from legacy task-file checkboxes to Wayfinder ticket metadata: an implementation task is actionable when the ticket is unblocked by resolved blockers and claimed by the current session before work starts.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`.
The old workflow has strong git guardrails.
It syncs `main` with `git pull --ff-only`, branches as `task-<NNNN>-<slug>`, never branches from a sibling task branch, refuses to stash uncommitted work automatically, never resets diverged `main`, and reuses an existing task branch without rebasing it.
A migrated skill should preserve the safety properties, but must redesign branch naming because Wayfinder artifact names are human-readable artifact links with identifiers inside filenames, not legacy `.claude/tasks` stems.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`.
The old workflow treats blocker work not reachable from `main` as a stop-and-ask condition because the blocker's PR is likely unmerged.
Wayfinder metadata can prove planning blockers are resolved, but it cannot prove code from prerequisite implementation tickets has landed on `main`.
A migrated skill should keep an explicit reachability check for implementation blockers that correspond to prior code changes, or else record a policy decision that Wayfinder task resolution is allowed to precede merge.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`.
The old implementation step delegates test-first work to `/test-driven-development` where possible and tells the agent to run typechecking regularly, focused tests regularly, and the full suite at the end.
The local `/test-driven-development` dependency adds stricter rules: tests verify behavior through public interfaces, avoid tautological assertions, proceed one test at a time through tracer bullets, and use a test-writer sub-agent while the main agent writes implementation.
A migrated skill should preserve the intent to use TDD at agreed seams, but should not blindly import Claude-specific sub-agent mechanics if the target runtime lacks them.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/test-driven-development/SKILL.md`.
The old staging rule is intentionally conservative: stage created and modified files specifically, not with `git add -A`, so unrelated untracked work is not swept in.
This remains valid for a Wayfinder-aware implementation workflow and should be preserved.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`.
The old review step runs `/review-uncommitted` with the task file as the spec source, then addresses findings before continuing.
The review dependency reviews `git diff HEAD` across Risk, Standards, and Spec axes, requires new files to already be tracked so they appear in the diff, and aggregates the Risk block plus Standards and Spec findings.
A migrated skill should preserve a pre-commit review gate, but adapt the spec source to the Wayfinder task ticket artifact and decide whether the risk axis belongs in the new review contract.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/review-uncommitted/SKILL.md`.
The old closeout updates the task artifact as part of the implementation commit.
It marks each acceptance criterion `[x]` when satisfied or `[-]` when deliberately dropped, appends `## Implementation Notes` for deviations, keeps permanent provenance and blocker frontmatter untouched, and stages the task file with code.
A migrated skill should preserve recording deviations and acceptance-criterion outcomes in the task artifact, but adapt lifecycle status to Wayfinder's `claimed` to `resolved` transition rather than treating checkboxes as the authoritative lifecycle.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/TASK-FORMAT.md`.
The old commit and PR mechanics are opinionated.
It makes one commit for the whole task, follows the repository's commit convention, references the task in the subject, pushes `task-<NNNN>-<slug>`, opens a ready PR against `main` using the repo forge CLI, includes the task path, summary, deviations, the review Risk block, and only unaddressed Standards and Spec findings, and does not ask before pushing or opening the PR.
A migrated skill should preserve the one-task-one-commit bias and PR body usefulness, but adapt task references to Wayfinder artifact links and decide whether automatic push and PR creation remain acceptable for every target repo.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`.
The legacy `/to-tasks` dependency produces tracer-bullet vertical slices as files under `.claude/tasks`, with `spec` and `blocked-by` frontmatter and checkbox acceptance criteria.
The already-packaged `slice` migration replaced that output with open, unclaimed Wayfinder task tickets in the AI-artifacts destination, using Wayfinder parent and `blocked-by` links instead of legacy stems.
The migrated `implement` skill should consume the Wayfinder task-ticket format created by `slice`, not the old `.claude/tasks` format.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/to-tasks/TASK-FORMAT.md`, `/home/alexion/Documents/ai-artifacts/projects/skills/031-slice-skill-map.md`.
## Conclusion
The migrated `implement` skill should preserve explicit task selection, blocker safety, conservative git branching from `main`, no automatic stashing or destructive resets, TDD where appropriate, regular verification, specific staging, pre-commit review, deviation notes, one commit per task, and useful PR reporting.
It should adapt task identity, blocker readiness, branch naming, spec source, task closeout, PR references, and lifecycle state from legacy `.claude/tasks` conventions to Wayfinder task-ticket artifacts.
It should reject legacy assumptions that a task is identified by a `.claude/tasks` basename, that checkbox completion is the authoritative lifecycle, and that `spec` or `blocked-by` frontmatter from `.claude/tasks` exists.

View File

@@ -0,0 +1,56 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:42:05-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement skill Matt skills discovery research
## Question
Which Matt Pocock `mattpocock/skills` skills are relevant primary sources for migrating `implement`, and which ones need dedicated follow-up research tickets?
## Findings
The primary repository is `mattpocock/skills`, described by GitHub as "Skills for Real Engineers. Straight from my .agents directory." and organized under `skills/engineering`, `skills/productivity`, `skills/in-progress`, `skills/misc`, and `skills/deprecated`.
The engineering directory contains `implement`, `to-tickets`, `tdd`, `code-review`, and `wayfinder`, which are directly relevant to an implementation workflow that consumes tickets, builds code, tests, reviews, and understands Wayfinder semantics.
Source: `https://api.github.com/repos/mattpocock/skills`, `https://api.github.com/repos/mattpocock/skills/contents/skills/engineering?ref=main`.
Matt Pocock's `implement` skill is the closest direct comparison.
It implements work from a spec or set of tickets, uses `/tdd` where possible at pre-agreed seams, runs typechecking and tests, reviews with `/code-review`, and commits to the current branch.
It is much shorter and less prescriptive than the local old `/implement`, so it needs dedicated research to decide what simplicity to import and what local guardrails to keep.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/implement/SKILL.md`.
Matt Pocock's `to-tickets` skill is relevant because it defines the producer side of ticket implementation work.
It creates tracer-bullet tickets, blocking edges, a frontier concept, tracker publication, and a wide-refactor expand-contract exception.
It needs dedicated research to compare its ticket assumptions with local `slice` and Wayfinder task artifacts.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/to-tickets/SKILL.md`.
Matt Pocock's `tdd` skill is relevant because both Matt's and the old local implementation workflows delegate test-first mechanics to TDD.
It emphasizes pre-agreed seams, one test and one minimal implementation per cycle, and defers refactoring to review.
It needs dedicated research because the local TDD skill differs by using a test-writer sub-agent and more detailed anti-tautology mechanics.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/tdd/SKILL.md`.
Matt Pocock's `code-review` skill is relevant because Matt's `implement` uses it as the review gate.
It reviews a branch against a fixed point with Standards and Spec axes in parallel sub-agents, whereas the old local review skill reviews uncommitted changes and also includes a Risk axis.
It needs dedicated research for deciding which review gate a migrated `implement` skill should require.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/code-review/SKILL.md`.
Matt Pocock's `wayfinder` skill is relevant because it is the upstream-like version of the planning map workflow.
It uses issue trackers, labels, child issues, assignees, and native blocking relationships, while the local Wayfinder uses AI-artifacts Markdown, metadata claims, wikilinks, and self-resolving tickets.
It needs dedicated research only for contrast, so the migrated `implement` skill does not accidentally import tracker-specific assumptions.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/wayfinder/SKILL.md`.
The productivity `handoff` and in-progress `claude-handoff` skills are adjacent but not central.
They summarize a conversation for a fresh agent and can suggest skills, but they do not define implementation execution, task lifecycle, review, branch, worktree, or PR policy.
They do not need dedicated follow-up research for this map unless a later decision expands the destination to session handoff automation.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/productivity/handoff/SKILL.md`, `https://raw.githubusercontent.com/mattpocock/skills/main/skills/in-progress/claude-handoff/SKILL.md`.
## Conclusion
Create dedicated follow-up research tickets for Matt Pocock's `implement`, `to-tickets`, `tdd`, `code-review`, and `wayfinder` skills.
Do not create follow-up research for Matt's handoff skills unless the map later expands into session handoff automation.

View File

@@ -0,0 +1,73 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:42:05-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement skill Wayfinder contract research
## Question
What Wayfinder artifact and lifecycle rules must a migrated `implement` skill follow when claiming, executing, resolving, and reporting Wayfinder task tickets?
## Findings
Wayfinder plans by default and treats implementation as the edge of the map unless an effort explicitly permits execution in its Notes.
A general `implement` skill can be the explicit destination-work executor, but it should not silently execute arbitrary Wayfinder planning tickets.
It should restrict itself to Wayfinder task tickets that represent implementation handoff work or to maps whose Notes explicitly allow execution.
Source: `/home/alexion/.pi/agent/skills/wayfinder/SKILL.md`.
Every Wayfinder ticket is either HITL or AFK and has one ticket tag.
Task tickets use `ticket/task/afk` or `ticket/task/human`; Research, Prototype, and Grill tickets have separate resolution skills and are not implementation slices.
A migrated `implement` skill can execute a `ticket/task/human` when it represents implementation work, but it must block and surface a precise human-input checkpoint when the task reaches the human-dependent step.
It should stop with a plain explanation when asked to execute a non-task decision ticket.
Sources: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`, user correction in this session.
Ticket metadata is authoritative for lifecycle and readiness.
A ticket is on the Frontier when `status: open`, every `blocked-by` artifact is satisfied, and it has no claim.
A ticket blocker is satisfied when its status is `resolved`, and a non-ticket blocker is satisfied when the artifact exists.
The migrated skill should verify these metadata conditions before claiming, rather than using legacy acceptance-checkbox completion as the readiness source.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Claims must be persisted before work starts.
Claiming means setting `status: claimed`, `claimed-by` to the current execution-session identifier, and `claimed-at` to the current timestamp.
The acting agent should use `PI_SESSION_ID` when available.
The migrated `implement` skill should claim exactly one actionable ticket before changing code, and should avoid consuming multiple tickets implicitly.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Wayfinder tickets are self-resolving artifacts.
The canonical result lives in the same ticket artifact, and a resolved implementation task should leave enough result detail for future readers without moving the result into the map.
For `implement`, this implies appending implementation notes, verification results, commit hash, branch name, PR URL when available, deliberately dropped acceptance criteria, and any unaddressed review findings to the ticket artifact before setting `status: resolved`.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
The map is a route summary, not the store for ticket-level detail.
Only the Frontier links to tickets or artifacts, and Decisions so far contains concise plain-language decisions for resolved Wayfinder decision tickets.
Implementation task completion should update the map lifecycle and Frontier if the task belongs to a Wayfinder map, but the detailed implementation report belongs in the task ticket.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Wayfinder requires shared artifacts to be re-read immediately before writes because concurrent sessions may be editing the same effort.
A migrated `implement` skill should re-read the task ticket before claim, before closeout, and before any map Frontier repair.
It should detect stale status, foreign claims, and changed blockers rather than overwriting them.
Source: `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Wayfinder's user-facing reference rule is by human-readable title in the destination's link style, never by bare identifier, filename, or slug.
The migrated skill should refer to the task as a wikilink title when reporting, recording PR text, or writing related map updates, while file paths may still appear where tools need concrete paths.
Sources: `/home/alexion/.pi/agent/skills/wayfinder/SKILL.md`, `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
The AI-artifacts vault convention requires project artifacts to be flat and named `<NNN>-<scope-slug>[-<subject-slug>]-<artifact-type>.md`, with identifiers allocated by incrementing the root `.counter` before creation.
`implement` usually consumes an existing ticket rather than allocating new artifacts, but any follow-up task artifacts it creates must honor the destination's `AGENTS.md` and counter rules.
Source: `/home/alexion/Documents/ai-artifacts/AGENTS.md`.
The existing `slice` skill map records the intended producer side of the same contract: implementation slices become Wayfinder task tickets with `## What to build`, `## Acceptance criteria`, and optional `## Implementation Notes`, and the tickets are open and unclaimed until an implementer claims them.
The migrated `implement` skill should be compatible with that produced format.
Source: `/home/alexion/Documents/ai-artifacts/projects/skills/031-slice-skill-map.md`.
## Conclusion
A Wayfinder-aware `implement` skill should execute exactly one actionable implementation task ticket at a time, claim it in metadata before code changes, respect `blocked-by` and existing claims, record implementation results in the same ticket artifact, transition it to `resolved`, and repair the owning map's Frontier without storing implementation detail in the map.
It may execute HITL task tickets when they are implementation work, but must pause at the point human input is required and record the blocked state plainly.
It should not execute research, prototype, grill, blocked, claimed, or out-of-scope tickets as normal implementation work.

View File

@@ -0,0 +1,110 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:46:29-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement skill no mistakes research
## Question
What should the migrated `implement` skill learn from Kun Chen's `no-mistakes` code review workflow?
## Findings
Kun Chen's `no-mistakes` is a local git proxy and validation gate.
Its README says pushing to the `no-mistakes` remote spins up a disposable worktree, runs review, tests, docs, lint, push, PR, and CI, and forwards the branch only after every check is green.
The migrated `implement` skill should consider separating local implementation from final shipping validation, rather than treating one in-context review pass as the whole quality gate.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/README.md`.
`no-mistakes` is explicitly agent-agnostic and supports agents including `pi`.
Its skill drives `no-mistakes axi`, a non-interactive TOON interface, and the pipeline can apply safe fixes while escalating intent-touching findings to the human.
A local `implement` skill can remain tool-agnostic while optionally detecting and delegating to `no-mistakes` when installed and initialized.
Sources: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/README.md`, `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/skills/no-mistakes/SKILL.md`.
The `no-mistakes` skill distinguishes validate-only mode from task-first mode.
Task-first mode checks scope with `git status`, preserves unrelated pre-existing uncommitted changes, commits only task changes, creates a feature branch when the user is on the default branch, then validates committed work.
The migrated `implement` skill should preserve this strict scope boundary and should treat committed branch state as the input to any downstream validation gate.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/skills/no-mistakes/SKILL.md`.
`no-mistakes` requires a rich `--intent`, defined as the user's objective in their terms plus decisions, tradeoffs, constraints, and approaches ruled in or out.
The migrated `implement` skill should derive review and PR context from the Wayfinder task's `## What to build`, acceptance criteria, parent decisions, and implementation notes, not merely from the diff or file list.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/skills/no-mistakes/SKILL.md`.
The `no-mistakes` test-quality rule rejects tests that only grep, parse, snapshot, or inspect implementation source strings as proof of behavior.
It requires public or executable interfaces, observable behavior, typed or normalized semantic models for declarative artifacts, and regression tests that fail before the fix when feasible.
The migrated `implement` skill should import this as a review and TDD standard because skill and artifact repos are prone to source-string pseudo-tests.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/skills/no-mistakes/SKILL.md`.
The `no-mistakes` gate has clear custody rules while a run is active.
At a gate, the driver reads structured findings and responds approve, fix, or skip; it does not edit code manually while the pipeline owns findings and fixes.
The migrated `implement` skill should either avoid invoking such a pipeline or respect custody strictly once it has delegated validation.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/skills/no-mistakes/SKILL.md`.
The anti-slop mechanism is not just "run a code review".
The documented claim is that a stable pipeline gives "passed the gate" a fixed meaning: intent, rebase, review, test, document, lint, push, PR, and CI happen in order, and push/PR/CI happen only after local checks pass.
This prevents a common agent failure mode where the agent declares done after a narrow local edit or a self-selected test subset.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/concepts/pipeline.md`.
Concretely, it attacks slop by removing the implementing agent's discretion over what "done" means.
The implementer cannot choose to skip rebase, skip docs, skip lint, skip CI, or call a cherry-picked test enough.
The fixed ordered gate externalizes those checks into a separate executor and stops before public push if any step produces unresolved findings.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/pipeline-steps.md`.
It attacks plausible-but-wrong code by feeding author intent into review, test detection, evidence validation, documentation checks, lint fixes, CI fixes, and PR drafting.
The review step treats authoritative intent as enforceable for source-verifiable acceptance criteria, so a diff can fail because it does not do the requested thing even when it compiles and looks tidy.
The test step validates the change and requested intent with the smallest relevant evidence-oriented tests or manual checks, and when no targeted check can establish intent it must write or improve a focused test, produce evidence, or report a warning finding.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/pipeline-steps.md`.
It attacks fake tests by making source-content-only tests a first-class violation for agents that write, repair, or review tests.
Review flags newly added violations and requires same-pattern tests encountered in the accepted change's scope to be removed or made semantic.
The test guidance requires observable behavior, state, output, side effects, failure modes, or a typed or normalized semantic model instead of grepping implementation text.
Sources: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/pipeline-steps.md`, `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/internal/testguidance/guidance.go`.
It attacks "review theater" by requiring structured output.
The review agent returns severity, file location, description, and action, while approval rules require a pause for error or warning findings and for ask-user findings.
That makes defects machine-actionable and prevents them from disappearing inside a flattering narrative summary.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/pipeline-steps.md`.
It attacks unsafe autonomous cleanup by distinguishing mechanical fixes from intent questions.
`auto-fix` can be handed back to the pipeline, but `ask-user` is for findings that challenge the author's intent or product behavior, and review auto-fix is disabled by default.
That keeps the validation agent from silently rewriting product decisions to make its own review pass.
Sources: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/skills/no-mistakes/SKILL.md`, `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/pipeline-steps.md`.
It attacks stale-base and unreviewed-history slop through rebase and push binding.
The rebase step rebases onto the latest upstream and reports conflicts, and the push step reloads the durable review-approved commit before remote mutation.
Push refuses when the approval binding is missing or when the proposed commit does not equal or descend from the reviewed commit, so later unreviewed changes cannot slip through as if they had passed review.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/pipeline-steps.md`.
It attacks "works locally but fails publicly" by putting PR creation and CI monitoring after local gates.
The CI step watches hosted CI, fetches failed job logs where supported, auto-fixes failures within limits, and pauses with findings when failures or merge conflicts persist.
This closes the gap between local agent confidence and actual host validation.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/pipeline-steps.md`.
The pipeline requires every step either to complete, return structured findings with severity and action, trigger bounded auto-fix, pause for approval when blocking or ask-user findings remain, or fail fatally.
This prevents silent degradation: unresolved review, test, docs, or lint issues become explicit findings instead of prose buried in an agent summary.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/concepts/pipeline.md`.
`no-mistakes` uses intent before review and evidence collection.
The review step can compare the diff to the user's actual goal, while the test step can run targeted validation and gather user-facing evidence when intent is known.
This targets slop where code is syntactically plausible but does not satisfy the requested behavior.
Sources: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/concepts/pipeline.md`, `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/repo-config.md`.
Repository configuration separates trusted default-branch settings from pushed-branch settings.
By default, code-executing fields such as test, lint, format commands and selected agent are read from the trusted default-branch copy, so a feature branch cannot self-authorize weaker validation commands on the daemon host.
This prevents a slop or malicious branch from weakening its own gate.
Source: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/src/content/docs/reference/repo-config.md`.
The review and fix loop classifies findings as auto-fix, ask-user, or no-op, with ask-user reserved for product intent or judgment calls.
That design limits autonomous fixing to mechanical work and forces human attention where an AI could otherwise paper over a disagreement with the user's intent.
Sources: `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/README.md`, `https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/skills/no-mistakes/SKILL.md`.
## Conclusion
The migrated `implement` skill should learn from `no-mistakes` that preventing AI slop requires a fixed ordered gate, rich intent, isolated validation, structured findings, bounded auto-fix, human escalation for judgment calls, trusted validation configuration, and CI-backed proof before public handoff.
It should preserve unrelated changes, commit only task scope, provide rich reviewer intent, reject source-grep pseudo-tests, and optionally hand shipping validation to an external gate that runs in a disposable worktree.
It should not blindly replace the local workflow with `no-mistakes`, because that would require repository initialization, a configured pipeline agent, and accepting the gate's branch custody model.

View File

@@ -0,0 +1,51 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:46:29-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement skill treehouse research
## Question
What should the migrated `implement` skill learn from Kun Chen's `treehouse` workflow about using git worktrees for implementation sessions?
## Findings
Kun Chen's `treehouse` manages a pool of reusable isolated git worktrees per repository under a configured root, defaulting to `~/.treehouse/`.
It is designed so each agent gets its own environment instantly without cloning, conflicts, or coordination overhead, while preserving dependencies and build cache between sessions.
The migrated `implement` skill should consider worktree isolation as a stronger default than mutating the user's current checkout when the tool is available.
Source: `https://raw.githubusercontent.com/kunchenguid/treehouse/main/README.md`.
Treehouse worktrees use detached HEAD reset to the local or remote default branch that is further ahead, avoiding branch-name conflicts at acquisition time.
An implementation skill that expects to create a named branch may need to create the task branch after entering or leasing the worktree, rather than relying on the worktree manager to allocate the feature branch.
Source: `https://raw.githubusercontent.com/kunchenguid/treehouse/main/README.md`.
Treehouse marks worktrees as in-use through process scans and short-lived owner reservations, and has durable leases for automation with `treehouse get --lease`.
A leased worktree is never handed out later and never pruned until released with `treehouse return`.
For a non-interactive `implement` workflow, `treehouse get --lease --lease-holder <session> --json` is more appropriate than opening a subshell.
Source: `https://raw.githubusercontent.com/kunchenguid/treehouse/main/README.md`.
Treehouse leases include a random `lease_id`, `lease_holder`, and `leased_at`, and `treehouse return` can require `--if-lease-id` and `--if-lease-holder`.
This gives automation ABA protection so cleanup cannot accidentally release a later acquisition of the same path.
A migrated skill should record the lease path and identity in the Wayfinder task artifact if it uses Treehouse, and release with identity checks during cleanup.
Source: `https://raw.githubusercontent.com/kunchenguid/treehouse/main/README.md`.
Treehouse treats tracked changes and untracked files as dirty, even when repository config hides untracked files from normal `git status` output.
Its prune and destroy commands are dry-run or safe by default and skip dirty, unmerged, unverifiable, in-use, and leased worktrees unless explicit destructive flags are provided.
The migrated `implement` skill should preserve this safety stance and should not destroy or return a dirty leased worktree without surfacing the risk.
Source: `https://raw.githubusercontent.com/kunchenguid/treehouse/main/README.md`.
Treehouse supports user-level lifecycle hooks, including `post_create`, and routes hook stdout to stderr when using `get --lease` so stdout remains machine-readable.
This makes it suitable for dependency installation, environment setup, and cache reuse outside the `implement` skill itself.
The migrated skill should avoid duplicating environment bootstrap when a worktree manager's hooks own it.
Source: `https://raw.githubusercontent.com/kunchenguid/treehouse/main/README.md`.
## Conclusion
If worktree automation is in scope, the migrated `implement` skill should prefer optional Treehouse leasing over ad hoc `git worktree` management: acquire an isolated reusable worktree, create or check out the task branch inside it, record lease identity in the ticket, avoid destructive cleanup when dirty, and release with `--if-lease-id` after successful handoff.
This should remain optional unless the user decides every implementation must run outside the current checkout.

View File

@@ -0,0 +1,60 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:46:29-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement skill Herdr worktree research
## Question
What Herdr worktree conventions or plugins are relevant to the migrated `implement` skill's branch and workspace handling?
## Findings
Herdr itself has built-in worktree management according to `herdr-worktrunk`'s README, which says Herdr ships `herdr worktree create/open/remove/list`.
The same source says the Worktrunk plugin exists because Worktrunk adds lifecycle hooks that Herdr's built-in worktree commands lack.
The migrated `implement` skill should not assume it must create panes itself if Herdr is already the user's workspace manager, but lifecycle setup may need a plugin or external manager.
Source: `https://raw.githubusercontent.com/devashish2203/herdr-worktrunk/main/README.md`.
`herdr-worktrunk` opens existing or newly created worktrees as either Herdr tabs or native linked-worktree workspaces, and it delegates unmerged branch and untracked-file safety to Worktrunk during removal.
This suggests an implementation workflow can treat Herdr as presentation and Worktrunk as branch/worktree lifecycle, rather than combining all responsibilities inside `implement`.
Source: `https://raw.githubusercontent.com/devashish2203/herdr-worktrunk/main/README.md`.
`herdr-sessionizer` fuzzy-opens projects and Git worktrees into configured Herdr workspaces, using layouts to bootstrap tabs, pane splits, commands, and per-repo overrides.
It supports a Worktree action to create or reopen a Git worktree workspace.
This is relevant for interactive human-driven session startup, but less relevant for a skill that should run inside an already-started Pi process.
Source: `https://raw.githubusercontent.com/andrewchng/herdr-sessionizer/main/README.md`.
`herdr-plugin-workspace-manager` applies declarative tab, pane, environment, startup-command, and agent layouts automatically to every new worktree.
It can wait until Herdr reports an agent ready for input and optionally hand it a prompt, and it can remove worktrees whose upstream branch is gone.
A future orchestration layer could use this to launch implementer/reviewer/tester panes, but the core `implement` skill should not depend on it unless the destination expands to Herdr orchestration.
Source: `https://raw.githubusercontent.com/razajamil/herdr-plugin-workspace-manager/main/README.md`.
`herdr-worktree-setup` listens for Herdr's `worktree.created` event and runs per-project setup steps such as copying `.env`, `mise trust`, `direnv allow`, and package installation.
It exposes `HERDR_MAIN_REPO`, `HERDR_WORKTREE`, and `HERDR_BRANCH` to those steps.
If `implement` uses Herdr-created worktrees, it should rely on such setup hooks rather than scripting environment copying itself.
Source: `https://raw.githubusercontent.com/tdi/herdr-worktree-setup/main/README.md`.
`herdr-worktree-from-linear` and `herdr-worktree-from-pr` create worktrees from external tracker items or PRs and open them as Herdr workspaces.
They are useful references for selecting a branch base, reusing an existing worktree, and separating worktree creation from setup plugins.
They are less directly applicable to Wayfinder Markdown task tickets unless a later decision adds a tracker bridge.
Sources: `https://raw.githubusercontent.com/tdi/herdr-worktree-from-linear/main/README.md`, `https://raw.githubusercontent.com/tdi/herdr-worktree-from-pr/main/README.md`.
`herdr-worktreeinclude` copies gitignored files matching `.worktreeinclude` into newly created Herdr worktrees and explicitly cites Claude Code's `.worktreeinclude` convention.
For implementation worktrees, this is a safer project-declared way to copy local config than having `implement` guess which ignored files are needed.
Source: `https://raw.githubusercontent.com/tanshio/herdr-worktreeinclude/main/README.md`.
`pi-herd` is a Pi-first Herdr orchestration project that creates visible lead and worker sessions, keeps source-changing roles in isolated git worktrees, and stores durable run artifacts under `.pi-herd/runs/`.
This is relevant if the implement workflow later becomes multi-agent orchestration, but it is broader than a single-ticket `implement` skill.
Source: `https://raw.githubusercontent.com/ribbons-digital/pi-herd/main/README.md`.
## Conclusion
Herdr research supports keeping worktree and pane orchestration optional and external to the core `implement` skill.
The skill should be compatible with Herdr-managed worktrees, should not duplicate lifecycle setup hooks, and should prefer project-declared mechanisms such as `.worktreeinclude` or worktree setup plugins for ignored local config.
Dedicated Herdr orchestration belongs outside the first migrated `implement` contract unless the user explicitly broadens the destination.

View File

@@ -0,0 +1,59 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:46:29-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement skill Pi worktree extensions research
## Question
What Pi extension APIs or examples are relevant if the migrated `implement` workflow should integrate with git worktrees or session/workspace automation?
## Findings
Pi extensions can subscribe to lifecycle events, register custom tools, intercept tool calls, add commands, prompt users through `ctx.ui`, persist session state through entries, and customize rendering.
Extension use cases explicitly include git checkpointing, path protection, file watchers, external integrations, and CI triggers.
This means worktree integration is better suited to an optional Pi extension or external command than to static skill prose when automation needs session lifecycle hooks.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Pi extension placement supports global and project-local extensions, with project-local `.pi/extensions` loaded only after trust resolution.
A worktree integration that runs project-controlled setup commands must respect trust boundaries and should not make the `implement` skill silently load project-local automation.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
Pi exposes session lifecycle hooks including `session_before_switch`, `session_before_fork`, `session_shutdown`, `agent_end`, and `agent_settled`.
These hooks are appropriate for guarding dirty repositories, releasing leases, updating status, or coordinating cleanup when a Pi session moves or exits.
A static skill cannot reliably perform those cleanup duties if the user abandons or forks the session mid-run.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`.
The `dirty-repo-guard.ts` example blocks session changes when `git status --porcelain` shows uncommitted changes, defaulting to block in non-interactive mode and asking in UI-capable modes.
This is directly aligned with the old `implement` guardrail against automatic stashing or context switching over dirty work.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/dirty-repo-guard.ts`.
The `git-checkpoint.ts` example creates `git stash create` checkpoints at each turn and offers to restore the code state when forking.
It demonstrates how Pi can bind source state to conversation entries, but it also relies on stash refs and UI choice rather than durable worktree leases.
The migrated `implement` skill should not depend on this for branch isolation, but a future extension could adapt the concept to record worktree lease state against session entries.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/git-checkpoint.ts`.
The `git-merge-and-resolve.ts` example fetches and merges the upstream tracking ref after each agent turn only when the working tree is clean, and sends a follow-up user message listing conflict blocks when conflicts appear.
This shows Pi extensions can safely perform git maintenance and feed actionable conflict context back to the model, but automatic merge behavior is a separate policy decision from implementing one Wayfinder task.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/git-merge-and-resolve.ts`.
The subagent extension example runs separate `pi` subprocesses with isolated contexts, supports parallel and chained workflows, and includes workflow prompts such as implement-and-review.
It can load user-level and trusted project-local agent definitions, and it warns that project-local agents are repo-controlled prompts.
This is relevant if implementation later becomes a visible multi-agent pipeline, but it is not required for a single-ticket skill.
Source: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions/subagent/README.md`.
Pi's docs and examples do not provide a built-in git worktree manager in the inspected extension set.
They provide the extension hooks and subprocess execution APIs needed to integrate external managers such as Treehouse, Herdr, or raw `git worktree`.
Sources: `/nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs/extensions.md`, `rg "worktree" /nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/docs /nix/store/rg248h9sz8dylm8p6a9w9fj4zrv4sgm5-pi-coding-agent-0.82.1/lib/node_modules/pi-monorepo/examples/extensions`.
## Conclusion
Pi supports worktree-adjacent automation through extensions, but not a built-in worktree manager in the inspected docs and examples.
Since parallel Wayfinder implementation needs isolated working trees, the migrated `implement` workflow should plan for worktree acquisition as a real execution concern.
Dirty-repo guards, lease cleanup, visible Herdr panes, and multi-agent execution can still live in extensions or external tools unless the package-scope decision pulls them into the skill itself.

View File

@@ -0,0 +1,43 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T07:38:25-04:00"
blocked-by:
- "[[039-implement-skill-old-workflow-research]]"
- "[[042-implement-skill-no-mistakes-research]]"
- "[[078-implement-skill-matt-code-review-research]]"
tags:
- ticket/grill
---
# Implement workflow review skill contract grill
## Question
What should the packaged review skill be named, and what standalone review contract should it expose?
## Resolution
The packaged review skill should be named `review`.
The previous conflict with Claude Code built-ins does not apply to this packaged workflow.
`review` should preserve agent flexibility rather than overprescribing a rigid mode taxonomy.
It reviews the change set the agent selects from current context, such as uncommitted changes, branch changes, a PR, explicit files, or another clear source.
It states what change set it selected before reviewing, and asks or stops only when the scope is ambiguous enough that a trustworthy review cannot proceed.
`review` produces a structured review report, not a gate artifact and not a pass/fail verdict.
The report should cover Risk, Standards, Intent, Evidence, and Documentation when those dimensions apply.
The skill may run targeted checks when useful, but it remains report-only and does not edit code.
The skill should use independent dimension reviewers when the runtime supports subagents or isolated workers, with a single-agent fallback that preserves separate sections.
Reviewer prompt files should live under the skill directory, for example `skills/review/reviewers/`.
Each reviewer file should be self-contained about its purpose, boundary, rubric, and output expectations.
The top-level `SKILL.md` should orchestrate input capture and aggregation without overdefining each reviewers judgment.
Findings should use a flexible shared base schema with dimension-specific additions where useful.
The base shape includes severity, blocking yes/no, location, finding, why it matters, and suggested fix.
Reviewers classify findings as blocking or non-blocking, while the caller or user decides final disposition.
Intent handling should remain flexible.
The reviewer may use a Wayfinder task, issue, spec, direct request, branch context, or other available context as intent source when relevant, but `review` itself should not know about or mutate implementation lifecycle, Wayfinder claiming, task resolution, PR creation, or ticket closeout.

View File

@@ -0,0 +1,34 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T11:22:04-04:00"
blocked-by:
- "[[039-implement-skill-old-workflow-research]]"
- "[[041-implement-skill-wayfinder-contract-research]]"
- "[[079-implement-skill-matt-wayfinder-research]]"
tags:
- ticket/grill
---
# Implement skill ticket closeout grill
## Question
Exactly what should `implement` write into the Wayfinder task ticket, parent map, commit, and PR body when the implementation succeeds, partially succeeds, or fails?
## Resolution
The decision tree is fully walked at the level this workflow should specify.
Do not overprescribe closeout taxonomy.
The code is the implementation artifact.
The Wayfinder ticket closeout records durable coordination facts only.
Wayfinder `status` is the lifecycle authority.
Acceptance criteria checkboxes may be updated as useful closeout detail, with `[x]` for satisfied criteria and `[-]` for deliberately dropped criteria when practical, but checkbox state is not the source of truth.
Implementation Notes should stay concise and capture only what future agents or humans need: deviations, dropped or changed scope, verification, branch, commit, PR, or why the ticket remains unresolved.
The agent uses judgment for partial or ambiguous outcomes, but must keep the recorded lifecycle honest and must not imply completion when the work is not complete.
The parent map should receive only a concise decision or outcome summary as required by Wayfinder.
Detailed implementation records belong in the task ticket, commit, PR, and working code, not in the map.

View File

@@ -0,0 +1,50 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T10:57:40-04:00"
blocked-by:
- "[[039-implement-skill-old-workflow-research]]"
- "[[042-implement-skill-no-mistakes-research]]"
- "[[077-implement-skill-matt-tdd-research]]"
- "[[065-implement-workflow-codebase-design-research]]"
tags:
- ticket/grill
---
# Implement workflow TDD skill contract grill
## Question
What standalone `test-driven-development` skill contract should the workflow expose, and how should it carry the necessary public-interface, seam-placement, test-quality, prefactoring, and refactoring guidance without requiring a separate packaged `codebase-design` skill?
## Resolution
`codebase-design` should not be packaged as part of this workflow.
The useful public-interface and seam guidance should be folded into `test-driven-development` and `review` instead.
`test-driven-development` should include only minimal practical seam guidance: test public behavior through the interface the code exposes or the task requires, identify the smallest public seam that can prove the behavior when unclear, and avoid testing internals just to make RED easy.
Tests are always written by someone other than the agent doing implementation.
The normal contract requires an independent test writer.
If the runtime truly cannot spawn an independent worker, the implementation agent must state that limitation before writing tests and preserve the role separation in-process as much as possible.
The implementation agent must not silently skip this requirement.
Use role names by function.
The implementation agent changes production code and drives the loop.
The test writer writes and edits tests.
The implementation agent gives the test writer one behavior, the public seam and context, an independent expected-value source, and failure output.
The implementation agent must not edit test-writer-authored tests.
Mechanical test defects go back to the test writer.
Semantic disagreement pauses for user or intent clarification.
The implementation agent may keep a private behavior backlog, but that backlog is isolated from the test writer.
The test writer receives one behavior at a time, writes one failing test, and then the implementation agent makes the minimal production change to pass.
Repeat the loop one behavior at a time.
Each test needs an independent source of truth for expected values, such as a spec, task, intent excerpt, worked example, known-good literal, existing behavior being preserved, user clarification, or external standard.
The implementation agent's derived computation is not enough.
Refactoring should match the old local `test-driven-development` behavior.
Never refactor while RED.
After tests pass, the implementation agent may refactor production code.
Test writer updates tests only for deliberate public seam changes or test defects.

View File

@@ -0,0 +1,28 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T11:32:36-04:00"
blocked-by:
- "[[041-implement-skill-wayfinder-contract-research]]"
- "[[045-implement-skill-pi-worktree-extensions-research]]"
tags:
- ticket/grill
---
# Implement skill package scope grill
## Question
Beyond the now-in-scope packaged `implement`, `test-driven-development`, and `review` skills, should this migration also deliver legacy compatibility shims or documentation for how an out-of-scope Pi worktree extension should integrate?
## Resolution
No extras are in scope.
This migration should deliver only the three packaged skills: `implement`, `test-driven-development`, and `review`.
Do not add legacy `.claude/tasks` compatibility shims.
Old task files may be ordinary context only if an agent chooses to read them, but this workflow should not preserve their lifecycle semantics.
Do not add dedicated documentation for a future Pi worktree extension, Herdr, or Treehouse integration.
Worktree orchestration remains out of scope and can define its own contract later.

View File

@@ -0,0 +1,53 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T00:00:00-04:00"
blocked-by: []
tags:
- ticket/research
---
# Implement workflow codebase design research
## Question
What role should `codebase-design` have in the packaged Wayfinder-aware implementation workflow, especially for `test-driven-development` and review?
## Findings
The old local `codebase-design` skill and Matt Pocock's `codebase-design` skill are nearly the same direct counterpart.
Both define deep-module vocabulary around module, interface, implementation, depth, seam, adapter, leverage, and locality.
Both aim to make code more testable and maintainable by placing behavior behind a small interface at a clean seam.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/codebase-design/SKILL.md`, `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/codebase-design/SKILL.md`.
The old local `test-driven-development` skill explicitly invokes `/codebase-design` during planning to identify deep modules and testability checks, regardless of what triggered TDD.
That makes `codebase-design` part of the old implementation workflow's dependency graph, not just an opportunistic extra.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/test-driven-development/SKILL.md`.
The important testing contract is that the interface is the test surface.
Codebase-design says callers and tests cross the same seam, and if tests need to reach past the interface then the module is probably the wrong shape.
This directly supports the TDD and no-mistakes anti-slop rules against implementation-coupled tests.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/codebase-design/SKILL.md`.
The deepening reference classifies dependencies as in-process, local-substitutable, remote-but-owned, or true external, and maps each category to a testing strategy.
This gives `test-driven-development` a concrete way to choose where a seam goes and what adapter or stand-in is legitimate for tests.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/codebase-design/DEEPENING.md`.
The deepening reference also says to replace, not layer, tests when deepening shallow modules.
Old unit tests on shallow modules become waste once tests exist at the deepened module interface, and tests should assert observable outcomes through the interface rather than internal state.
This is relevant to implementation slices that include prefactoring before behavior.
Source: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/codebase-design/DEEPENING.md`.
The design-it-twice reference is a heavier HITL or parallel-agent pattern for exploring alternative interfaces.
It is useful when a task reveals that seam placement or interface shape is a substantive design decision, but it should not become a mandatory step in every implementation slice.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/codebase-design/DESIGN-IT-TWICE.md`, `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/codebase-design/DESIGN-IT-TWICE.md`.
The packaged local skills repository does not currently contain a packaged `codebase-design` skill.
If the workflow includes a packaged `test-driven-development` skill that depends on codebase-design vocabulary, either `codebase-design` should be packaged too, or the TDD skill must inline enough of the deep-module and seam-placement contract to stand alone.
Source: `/home/alexion/wrk/skills/skills`.
## Conclusion
Add `codebase-design` to the implementation workflow scope or explicitly inline its deep-module seam guidance into `test-driven-development` and review.
The cleaner workflow is to package `codebase-design` as a supporting skill because TDD, review, and implementation all need the same vocabulary for seams, interfaces, adapters, test surfaces, and prefactoring.

View File

@@ -0,0 +1,40 @@
---
status: resolved
parent: "[[053-implement-skill-review-validation-grill]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T11:35:19-04:00"
blocked-by:
- "[[053-implement-skill-review-validation-grill]]"
- "[[055-implement-skill-tdd-refactor-grill]]"
tags:
- ticket/grill
---
# Implement workflow dependency orchestration grill
## Question
How should `implement` invoke, sequence, and consume the workflow's supporting skills and tools, including `test-driven-development` and `review`?
## Resolution
`implement` should use `test-driven-development` as a strong default when behavior can be usefully specified and tested before implementation.
It may skip TDD when the work is mechanical, documentation-only, exploratory, or when test-first would not add value.
Skipping TDD should be an agent judgment rather than an accident.
`test-driven-development` is process discipline, not a separate artifact.
`implement` records only durable outcomes such as tests added or changed, verification run, and deviations worth noting.
It should not require a TDD report or per-cycle log.
`implement` must run `review` before final handoff or Wayfinder task resolution.
Timing is left to agent judgment: review may happen before commit, after commit, or both.
The review must cover the final intended handoff state, or the agent must explain why it does not.
Blocking review findings should be fixed unless explicitly accepted by the agent or user.
When code changes are made in response to review, `implement` reruns review on the relevant change set.
Accepted blocking findings are recorded where appropriate.
Non-blocking findings are handled by agent judgment: fix when cheap or high-value, otherwise report or record only when useful.
No other supporting skill invocations are prescribed.
The agent may use any skill or tool it judges relevant, but only `test-driven-development` and `review` are named workflow dependencies.
External validation gates such as `no-mistakes` are not part of this implementation workflow.

View File

@@ -0,0 +1,200 @@
---
parent: "[[038-implement-skill-map]]"
tags:
- spec
---
# Implement workflow implementation spec
## Goal
Package the Wayfinder-aware implementation workflow as three skills in this repository: `implement`, `test-driven-development`, and `review`.
The implementation should create source under `skills/implement/`, `skills/test-driven-development/`, and `skills/review/`.
The packaged workflow should carry forward the old Claude Code execution, TDD, and review behavior named in this spec while avoiding legacy `.claude/tasks` lifecycle mechanics.
## Source references
Use these old local skills as source material:
- `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/`
- `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/test-driven-development/`
- `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/review-uncommitted/`
Use `[[038-implement-skill-map]]` as the authoritative decision record.
## Deliverables
Create exactly these packaged skills:
- `skills/implement/SKILL.md`
- `skills/test-driven-development/SKILL.md`
- `skills/review/SKILL.md`
Create these reviewer prompt files under `skills/review/reviewers/` for independent review dimensions:
- `skills/review/reviewers/risk.md`
- `skills/review/reviewers/standards.md`
- `skills/review/reviewers/intent.md`
- `skills/review/reviewers/evidence.md`
- `skills/review/reviewers/documentation.md`
Do not package `codebase-design` as part of this workflow.
Fold only the necessary public-interface and seam guidance into `test-driven-development` and `review`.
## Scope exclusions
Do not add legacy `.claude/tasks` compatibility shims.
Old task files may be ordinary context if an agent chooses to read them, but this workflow must not preserve their lifecycle semantics.
Do not build a Pi extension for worktree orchestration, dirty-repo guards, lease cleanup, visible Herdr panes, or multi-agent execution.
Do not add dedicated Herdr, Treehouse, or future worktree-extension integration documentation.
The skills should remain compatible with external orchestration by assuming the current checkout is the assigned execution checkout.
Do not integrate external validation gates such as `no-mistakes` into `implement`.
The no-mistakes research informs local review and TDD design, not a direct runtime dependency.
## `implement` skill contract
`implement` is a workflow executor for scoped implementation work.
It must not police what work the agent is allowed to implement.
It defines execution protocol.
When selected work has a Wayfinder task artifact, `implement` must follow Wayfinder claim, blocker, result, resolution, and Frontier protocol.
When selected work has no Wayfinder artifact, `implement` proceeds with normal implementation, review, commit, and handoff protocol.
In both cases, the implementation artifact is the working code.
`implement` is worktree-compatible, not a worktree orchestrator.
It assumes the current session already has the right checkout.
It should report the checkout and branch it used.
It should not create, lease, clean up, or switch worktrees.
Before changing code, `implement` checks dirty state.
It stops on unrelated or ambiguous uncommitted changes.
It continues only when dirty state is clearly already part of the selected work.
It never auto-stashes.
When starting new work, `implement` uses or creates a non-default branch from an updated default branch when needed.
If an appropriate non-default branch is already prepared, it continues there.
If it must create a branch, branch naming follows repository, user, or orchestrator convention.
If no convention is discoverable, it chooses a clear short descriptive branch name and reports it.
`implement` preserves the old blocker reachability guardrail.
It checks declared blockers where they exist.
It stops when prerequisite implementation work is not reachable from the current base and reports the likely unmerged prerequisite.
It does not automatically branch from, merge, or cherry-pick sibling task work.
Explicit integration-branch or wide-refactor exceptions follow the plan that names the exception.
`implement` uses `test-driven-development` as a strong default when behavior can usefully be specified and tested before implementation.
It may skip TDD when the work is mechanical, documentation-only, exploratory, or when test-first would not add value.
Skipping TDD should be agent judgment, not omission.
`implement` must run `review` before final handoff or Wayfinder task resolution.
Review timing is agent judgment.
Review may happen before commit, after commit, or both.
The review must cover the final intended handoff state, or the agent must explain why it does not.
Blocking review findings should be fixed unless explicitly accepted by the agent or user.
When code changes are made in response to review, `implement` reruns review on the relevant change set.
Accepted blocking findings are recorded in the final handoff or Wayfinder closeout when they affect a future reader's decision to trust or continue the work.
Non-blocking findings are handled by agent judgment.
`implement` should record only durable closeout facts.
For Wayfinder task closeout, `status` is the lifecycle authority.
Acceptance criteria checkboxes may be updated as useful detail with `[x]` for satisfied and `[-]` for deliberately dropped criteria when practical.
Checkbox state is not the source of truth.
Implementation Notes should stay concise and capture only what future agents or humans need: deviations, dropped or changed scope, verification, branch, commit, PR, or why the ticket remains unresolved.
Partial or ambiguous outcomes are left to agent judgment, but lifecycle recording must be honest.
## `test-driven-development` skill contract
`test-driven-development` is process discipline, not a report-producing artifact.
Its result is working behavior plus useful tests.
Tests are always written by someone other than the agent doing implementation.
The normal contract requires an independent test writer.
If the runtime truly cannot spawn an independent worker, the implementation agent must state that limitation before writing tests and preserve role separation in-process as much as possible.
The implementation agent must not silently skip this requirement.
Use role names by function.
The implementation agent changes production code and drives the loop.
The test writer writes and edits tests.
The implementation agent gives the test writer one behavior, public seam and context, an independent expected-value source, and failure output.
The implementation agent must not edit test-writer-authored tests.
Mechanical test defects go back to the test writer.
Semantic disagreement pauses for user or intent clarification.
The implementation agent may keep a private behavior backlog, but that backlog is isolated from the test writer.
The test writer receives one behavior at a time, writes one failing test, and then the implementation agent makes the minimal production change to pass.
Repeat one behavior at a time.
Each test needs an independent source of truth for expected values.
Acceptable sources include a spec, task, intent excerpt, worked example, known-good literal, existing behavior being preserved, user clarification, or external standard.
The implementation agent's derived computation is not enough.
Include minimal public-interface and seam guidance.
Tests should target public behavior through the interface the code exposes or the task requires.
When the seam is unclear, identify the smallest public seam that can prove the behavior.
Avoid testing internals just to make RED easy.
Preserve the old local refactoring behavior.
Never refactor while RED.
After tests pass, the implementation agent may refactor production code.
The test writer updates tests only for deliberate public seam changes or test defects.
## `review` skill contract
The review skill is named `review`.
It is standalone and context-driven.
It does not know about implementation lifecycle, Wayfinder claiming, task resolution, PR creation, or ticket closeout.
`review` selects the relevant change set from current context.
The selected change set may be uncommitted changes, branch changes, a PR, explicit files, or another clear source.
It states what change set it selected before reviewing.
It asks or stops only when scope ambiguity would make the review untrustworthy.
`review` produces a structured review report, not a gate artifact and not a pass/fail verdict.
It remains report-only and must not edit code.
It may run targeted checks when useful.
The report should cover Risk, Standards, Intent, Evidence, and Documentation when those dimensions apply.
Do not overprescribe mode selection or intent-source taxonomy.
The skill should leave room for agent judgment when the selected change set and intent source are clear enough to review.
Use independent dimension reviewers when the runtime supports subagents or isolated workers.
Fallback to a single-agent review when independent workers are unavailable, but preserve separate report sections.
Reviewer prompt files live under `skills/review/reviewers/`.
Each reviewer file should be self-contained about its purpose, boundary, rubric, and output expectations.
The top-level `SKILL.md` orchestrates input capture and aggregation without overdefining each reviewers judgment.
Findings should use a flexible shared base schema with dimension-specific additions where useful.
The base shape includes severity, blocking yes/no, location, finding, why it matters, and suggested fix.
Reviewers classify findings as blocking or non-blocking.
The caller or user decides final disposition.
The Evidence reviewer should incorporate the anti-slop lessons from no-mistakes.
It should reject source-grep pseudo-tests as proof of behavior.
It should prefer evidence that demonstrates observable behavior, state, output, side effects, failure modes, or semantic meaning.
## Verification
After implementing the skills, run the repository verification expected for packaged skills.
At minimum run:
```bash
nix flake check "path:$PWD"
```
Use `nix flake check "path:$PWD"` rather than plain `nix flake check` when new skill files are untracked, because plain flake evaluation uses the Git snapshot.
## Acceptance criteria
- [ ] `skills/implement/SKILL.md` exists and implements the contract above.
- [ ] `skills/test-driven-development/SKILL.md` exists and implements the contract above.
- [ ] `skills/review/SKILL.md` exists and implements the contract above.
- [ ] `skills/review/reviewers/risk.md`, `skills/review/reviewers/standards.md`, `skills/review/reviewers/intent.md`, `skills/review/reviewers/evidence.md`, and `skills/review/reviewers/documentation.md` exist.
- [ ] The workflow does not add packaged `codebase-design`.
- [ ] The workflow does not add legacy `.claude/tasks` lifecycle compatibility.
- [ ] The workflow does not build or document a dedicated worktree orchestration integration.
- [ ] Repository verification passes with `nix flake check "path:$PWD"`.

View File

@@ -0,0 +1,42 @@
---
status: resolved
parent: "[[040-implement-skill-matt-skills-discovery-research]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:47:59-04:00"
blocked-by:
- "[[040-implement-skill-matt-skills-discovery-research]]"
tags:
- ticket/research
---
# Implement skill Matt implement research
## Question
What should the migrated local `implement` skill preserve, adapt, or reject from Matt Pocock's `skills/engineering/implement` skill?
## Findings
Matt Pocock's `implement` skill is explicitly invoked and disabled for model invocation, like the old local skill.
It accepts "a spec or set of tickets" rather than a single required task-file path.
The migrated local skill should keep explicit invocation, but decide whether to allow maps, specs, or multiple tickets or to preserve one-ticket execution for Wayfinder claim safety.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/implement/SKILL.md`.
Matt's skill says to implement the work described by the user in the spec or tickets, use `/tdd` where possible at pre-agreed seams, run typechecking regularly, run single test files regularly, and run the full test suite once at the end.
This aligns with the old local workflow and should be preserved.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/implement/SKILL.md`.
Matt's skill reviews with `/code-review` once done and commits work to the current branch.
It does not prescribe syncing `main`, creating a branch, staging specifically, pushing, opening a PR, or closing out a ticket artifact.
The migrated skill should not import this omission wholesale because Wayfinder task lifecycle and old local guardrails need stronger state handling.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/implement/SKILL.md`.
There is no packaged local `implement` counterpart yet, so the practical local counterpart is the old dotfiles `/implement` skill.
Compared with Matt's minimal version, the old local skill owns branch creation, blocker reachability checks, review report reuse, task-file closeout, commit convention discovery, push, PR creation, and final reporting.
The migration should deliberately choose which of those local responsibilities remain in the packaged skill rather than defaulting to Matt's current-branch commit-only model.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/implement/SKILL.md`, `/home/alexion/wrk/skills/skills`.
## Conclusion
Matt's `implement` is useful as a simplicity reference: implement from an explicit spec or tickets, use TDD at agreed seams, verify regularly, review, and commit.
The migrated local skill should remain stricter than Matt's around Wayfinder claiming, branch setup, artifact closeout, and PR or handoff reporting.

View File

@@ -0,0 +1,43 @@
---
status: resolved
parent: "[[040-implement-skill-matt-skills-discovery-research]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:47:59-04:00"
blocked-by:
- "[[040-implement-skill-matt-skills-discovery-research]]"
tags:
- ticket/research
---
# Implement skill Matt to tickets research
## Question
What should the migrated local `implement` skill learn from Matt Pocock's `skills/engineering/to-tickets` ticket, blocker, frontier, and slicing model?
## Findings
Matt's `to-tickets` creates tracer-bullet vertical tickets with blocking edges and a frontier of tickets whose blockers are all done.
Each ticket should deliver a complete path through every required layer, be demoable or verifiable on its own, and fit in a single fresh context window.
The migrated `implement` skill should expect tickets to be coherent implementation slices, not arbitrary file-edit lists.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/to-tickets/SKILL.md`.
Matt's skill includes a wide-refactor exception to strict vertical slicing.
For one mechanical change whose blast radius breaks too many call sites, it recommends expand-contract: add the new form, migrate batches, then delete the old form, with an integration branch only when batches cannot stay green alone.
The migrated `implement` skill needs special handling for task tickets that declare an integration-branch exception, because the old local rule of always branching from `main` may not fit that exceptional path.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/to-tickets/SKILL.md`.
Matt's publishing model depends on an issue tracker, native blocking links where available, and a `ready-for-agent` label.
The local `slice` skill has already adapted this to Wayfinder Markdown task artifacts with `status`, `parent`, `blocked-by`, and Frontier semantics.
The migrated `implement` skill should consume the local Wayfinder representation rather than Matt's tracker labels.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/to-tickets/SKILL.md`, `/home/alexion/Documents/ai-artifacts/projects/skills/031-slice-skill-map.md`.
Compared with the packaged local `slice` skill, Matt's `to-tickets` sizes tickets to a fresh context window and publishes to a tracker, while `slice` sizes slices as coherent single commits and writes Wayfinder `ticket/task/afk` or `ticket/task/human` artifacts.
`slice` also has explicit review-before-write output shape, destination artifact rules, parent-vs-blocker distinction, and map Frontier repair.
`implement` should treat `slice` as the authoritative local producer contract and Matt's skill as upstream rationale for tracer bullets and wide-refactor handling.
Sources: `/home/alexion/wrk/skills/skills/slice/SKILL.md`, `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/to-tickets/SKILL.md`.
## Conclusion
Matt's `to-tickets` reinforces tracer-bullet, blocker, frontier, and wide-refactor concepts.
The migrated `implement` skill should preserve those concepts but reject tracker labels and issue-specific publication mechanics in favor of Wayfinder task metadata.

View File

@@ -0,0 +1,43 @@
---
status: resolved
parent: "[[040-implement-skill-matt-skills-discovery-research]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:47:59-04:00"
blocked-by:
- "[[040-implement-skill-matt-skills-discovery-research]]"
tags:
- ticket/research
---
# Implement skill Matt TDD research
## Question
What should the migrated local `implement` skill learn from Matt Pocock's `skills/engineering/tdd` testing workflow?
## Findings
Matt's TDD skill centers testing on public seams.
It says tests verify behavior through public interfaces, not implementation details, and that seams must be agreed before writing tests.
The migrated `implement` skill should preserve pre-agreed seams and should source them from the Wayfinder task when present instead of re-litigating them by default.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/tdd/SKILL.md`.
Matt's TDD skill rejects implementation-coupled tests, tautological expected values, and horizontal slicing.
It requires red before green, one seam, one test, one minimal implementation per cycle, and no speculative features.
These rules align with the old local TDD dependency and Kun Chen's no-mistakes test-quality rule.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/tdd/SKILL.md`.
Matt's TDD skill says refactoring belongs to the review stage, not the red-green implementation cycle.
The local old TDD skill allows refactoring after all tests pass.
The migrated `implement` skill should decide whether to keep local post-green refactoring or adopt Matt's stricter review-stage boundary.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/tdd/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/test-driven-development/SKILL.md`.
The packaged local skills repository does not currently contain a packaged `tdd` skill.
The available local counterpart is the old Claude Code `test-driven-development` skill in dotfiles, which is more prescriptive than Matt's skill: it uses a test-writer sub-agent, forbids the main agent from editing sub-agent-authored tests, and carries detailed anti-tautology and mocking guidance.
If `implement` is packaged before `tdd`, it cannot declare a packaged `tdd` dependency without also migrating that skill or inlining the necessary testing rules.
Sources: `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/test-driven-development/SKILL.md`, `/home/alexion/wrk/skills/skills`.
## Conclusion
The migrated `implement` skill should preserve Matt's public-seam, anti-tautology, one-test-at-a-time TDD discipline.
The remaining decision is whether refactoring is allowed as a post-green implementation step or only after review.

View File

@@ -0,0 +1,46 @@
---
status: resolved
parent: "[[040-implement-skill-matt-skills-discovery-research]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:47:59-04:00"
blocked-by:
- "[[040-implement-skill-matt-skills-discovery-research]]"
tags:
- ticket/research
---
# Implement skill Matt code review research
## Question
What should the migrated local `implement` skill learn from Matt Pocock's `skills/engineering/code-review` workflow?
## Findings
Matt's `code-review` reviews the diff between `HEAD` and a fixed point supplied by the user, using three-dot diff against the merge base and listing commits with `git log <fixed-point>..HEAD --oneline`.
This branch-level review fits a committed implementation branch better than the old local `/review-uncommitted`, which reviews `git diff HEAD` before commit.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/code-review/SKILL.md`.
Matt's review has two axes: Standards and Spec.
It deliberately keeps the axes separate so spec fidelity cannot hide code-quality problems and standards compliance cannot hide incorrect behavior.
The old local review adds a Risk axis.
A migrated `implement` skill should decide whether to run uncommitted three-axis review before commit, branch-level two-axis review after commit, or both.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/code-review/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/review-uncommitted/SKILL.md`.
Matt's review locates spec sources from issue references in commits, explicit arguments, matching PRD/spec files, or user clarification, and it asks for tracker setup if issue tracker docs are missing.
For Wayfinder, the explicit task ticket artifact should be the primary spec source, with parent map or artifacts loaded only when needed.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/code-review/SKILL.md`.
Matt's Standards axis includes a Fowler-smell baseline and documented-standard override, matching the old local review's standards approach.
This should be preserved because it gives review teeth even when the repository has sparse standards docs.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/code-review/SKILL.md`, `/home/alexion/wrk/dotfiles/modules/agents/claude-code/skills/review-uncommitted/SKILL.md`.
The packaged local skills repository does not currently contain a direct `code-review` or `review-uncommitted` counterpart.
Its packaged `axi-review` skill is a black-box CLI conformance review against AXI principles, not a code diff review, so it is not a substitute for Matt's `code-review` in the migrated `implement` workflow.
A migrated packaged `implement` must either package or depend on a new local review skill, inline a review gate, or call an external review workflow explicitly.
Source: `/home/alexion/wrk/skills/skills/axi-review/SKILL.md`.
## Conclusion
Matt's `code-review` suggests branch-level review against a fixed point may be a better final gate than uncommitted review alone.
The migrated `implement` skill should preserve separate Standards and Spec axes, keep the smell baseline, use the Wayfinder task as spec source, and decide whether to retain the local Risk axis and pre-commit timing.

View File

@@ -0,0 +1,46 @@
---
status: resolved
parent: "[[040-implement-skill-matt-skills-discovery-research]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-07-31T23:47:59-04:00"
blocked-by:
- "[[040-implement-skill-matt-skills-discovery-research]]"
tags:
- ticket/research
---
# Implement skill Matt Wayfinder research
## Question
What should the migrated local `implement` skill learn from Matt Pocock's `skills/engineering/wayfinder` workflow, and what tracker-specific assumptions should it reject?
## Findings
Matt's Wayfinder is planning by default and says the pull to do the work usually means the map has reached its edge and should hand off.
This matches the local Wayfinder contract and confirms that `implement` should be explicitly invoked as the executor rather than folded into Wayfinder's normal planning loop.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/wayfinder/SKILL.md`, `/home/alexion/.pi/agent/skills/wayfinder/SKILL.md`.
Matt's Wayfinder stores maps and tickets as issue-tracker issues with labels, child issues, assignees as claims, native blocking relationships, and tracker frontier queries.
The local packaged Wayfinder stores them as AI-artifacts Markdown files with YAML `status`, `parent`, `blocked-by`, `claimed-by`, `claimed-at`, tags, and wikilinks.
The migrated `implement` skill should reject Matt's issue IDs, labels, assignees, and native tracker blocking as local storage assumptions.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/wayfinder/SKILL.md`, `/home/alexion/wrk/skills/skills/wayfinder/SKILL.md`, `/home/alexion/.pi/agent/skills/wayfinder/ARTIFACTS.md`.
Compared with packaged local Wayfinder, Matt's version treats tasks as prerequisites that unblock decisions, while the local ecosystem also has `slice` creating implementation handoff task artifacts.
This means `implement` must not infer implementation intent from Matt-style Wayfinder task semantics alone.
It should require the local implementation-task producer contract, map Notes, or explicit user selection to distinguish implementation tasks from planning prerequisite tasks.
Sources: `/home/alexion/wrk/skills/skills/wayfinder/SKILL.md`, `/home/alexion/wrk/skills/skills/slice/SKILL.md`.
Matt's Wayfinder defines Research, Prototype, Grilling, and Task tickets, and says Task work earns its place by unblocking a decision rather than delivering the destination.
The local Wayfinder makes the same distinction but also has `slice` produce implementation task tickets as explicit destination-work handoff artifacts.
The migrated `implement` skill should distinguish planning tasks from implementation tasks by map Notes, ticket body, and producer convention instead of treating every `ticket/task/afk` as implementation work.
Sources: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/wayfinder/SKILL.md`, `/home/alexion/Documents/ai-artifacts/projects/skills/031-slice-skill-map.md`.
Matt's Wayfinder says HITL tickets only resolve through live exchange and the agent never speaks for the human's side.
The migrated `implement` skill should preserve this by refusing to execute HITL tickets as AFK implementation.
Source: `https://raw.githubusercontent.com/mattpocock/skills/main/skills/engineering/wayfinder/SKILL.md`.
## Conclusion
Matt's Wayfinder reinforces the planning-versus-execution boundary, HITL protection, and frontier/claim concepts.
The migrated local `implement` skill should adapt only those concepts and reject tracker-specific labels, child-issue assumptions, assignee claims, issue IDs, and native blocking mechanics.

View File

@@ -0,0 +1,29 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T07:12:41-04:00"
blocked-by:
- "[[039-implement-skill-old-workflow-research]]"
- "[[041-implement-skill-wayfinder-contract-research]]"
- "[[075-implement-skill-matt-implement-research]]"
- "[[079-implement-skill-matt-wayfinder-research]]"
tags:
- ticket/grill
---
# Implement skill ticket scope grill
## Question
Should the migrated `implement` skill execute only one explicit actionable Wayfinder implementation task ticket, or should it also accept maps, specs, multiple tickets, or legacy task files?
## Resolution
The `implement` skill should not prescribe what work the agent is allowed to implement.
It defines the execution protocol, not the admissible work-source taxonomy.
The artifact produced by implementation is the working code.
When the selected work has a Wayfinder task artifact, `implement` follows the Wayfinder protocol for claim, blocker awareness, result recording, resolution, and Frontier repair.
When the selected work does not have a Wayfinder artifact, `implement` proceeds with the normal implementation, review, commit, and handoff protocol without creating or requiring a tracking artifact.
The skill should not police whether the work should have been a Wayfinder ticket.

View File

@@ -0,0 +1,42 @@
---
status: resolved
parent: "[[038-implement-skill-map]]"
claimed-by: "019fbb66-80d0-7a01-8ac9-01255adfc7b2"
claimed-at: "2026-08-01T07:19:49-04:00"
blocked-by:
- "[[039-implement-skill-old-workflow-research]]"
- "[[043-implement-skill-treehouse-research]]"
- "[[044-implement-skill-herdr-worktree-research]]"
- "[[045-implement-skill-pi-worktree-extensions-research]]"
- "[[076-implement-skill-matt-to-tickets-research]]"
tags:
- ticket/grill
---
# Implement skill branch worktree policy grill
## Question
What branch and worktree policy should `implement` follow for normal tickets, parallel Wayfinder task execution, and wide-refactor or integration-branch exceptions?
## Resolution
`implement` should assume the caller, current session, future Pi extension, Treehouse, Herdr, or human operator has already provided the right checkout.
It is worktree-compatible, not a worktree orchestrator.
It verifies and reports the checkout where it is working, but it does not create, lease, clean up, or switch worktrees.
Before starting, `implement` checks for uncommitted changes.
It stops when changes are unrelated or ambiguous, and continues only when the dirty state is clearly already part of the selected work.
It never auto-stashes.
When starting new work, `implement` uses or creates a non-default branch from an updated default branch.
If it is already on an appropriate non-default branch prepared for this work, it continues.
If it is on the default branch, it fast-forwards the default branch and creates a task branch.
If the default branch cannot fast-forward cleanly, it stops.
Branch naming follows repository, user, or orchestrator convention.
If no convention is discoverable and `implement` must create a branch, it chooses a clear short descriptive name and reports it.
Dependency branch handling preserves the old `/implement` guardrail.
`implement` checks declared blockers and stops when prerequisite implementation work is not reachable from the current base, reporting which prerequisite appears unmerged.
It does not automatically branch from, merge, or cherry-pick sibling task work.
Explicitly planned integration-branch or wide-refactor exceptions may use the branch strategy stated by the plan.