# Workbench architecture and behavior

For agents, use the [compact counterpart](llm/architecture.md).

Workbench is a standalone native Pi extension. It registers two user commands, five model tools and native session-start, resource-discovery, settled and shutdown handlers. It does not add an agent loop, installer, resource registry or external-version service. Core operation needs no personal configuration, installed custom Skills or companion Extensions. Pi's native APIs and file tools remain host prerequisites; integrations in explicitly selected templates are optional.

## Source layout

- [extensions/index.ts](../extensions/index.ts) registers native entries and owns conversation guidance and background-task lifecycle.
- [extensions/backups.ts](../extensions/backups.ts) implements original archival, retention settings and selective cleanup.
- [extensions/quickdoku.ts](../extensions/quickdoku.ts) owns index readiness, search limits and worker completion.
- [extensions/index-worker.mjs](../extensions/index-worker.mjs) reads the installed documentation and transactionally builds SQLite FTS5.
- [guides/](../guides/workbench.md) contains package-local LLM instructions and adaptable Skill examples.

The explicit `pi.extensions` declaration selects only `extensions/index.ts`. Guides and examples are supporting package files, not automatically registered Skills. Their relative links resolve from the installed package, independently of the caller's working directory. `Type` is imported directly from the host-provided `typebox` peer, not through Pi's compatibility mapping for older `pi-ai` imports.

## Native entries

| Entry | Behavior |
| --- | --- |
| `/workbench [input]` | Reads the shared guide and sends hidden, explicitly Workbench-authored custom context through Pi's native follow-up continuation. Real supplied command input is preserved separately. |
| `workbench {}` | Returns the same complete guide through a normal native tool result. Pi owns tool execution and the following model response. |
| `/workbench-reload [JSON object]` | Waits for native idle, saves an optional continuation on the active branch, then requests native reload. No arguments means no continuation. |
| `workbench_reload { initPrompt? }` | Records a request and returns `terminate: true`; native `agent_settled` dispatches `/workbench-reload` with `expandPromptTemplates: true`, without a delivery flag. Reports a request, not completion. |
| `piquickdoku { words }` | Searches the current-version local index without starting or waiting for index construction. |
| `workbench_archive_original { sourcePath, projectRoot? }` | Archives an authorized Pi original outside Git without modifying it. Resolved repository targets and files outside the Pi agent directory return `skipped` without an archive. Paths must be absolute; a supplied root must contain the resolved source. |
| `workbench_set_backup_retention { days }` | Stores a required nonnegative integer number, including zero, without deleting anything itself. |

Natural-language selection belongs to the model. Merely quoting or mentioning Workbench is not an activation request. Loading the extension, unrelated conversation, documentation queries, archive calls and setting calls do not begin startup side work.

## Reload handoff

Both reload entries retain Pi's full native reload. The reviewed Pi 1.5.0 resource loader reloads settings and resolves configured and temporary package sources. This can install missing or mismatched configured packages and update temporary sources; it does not happen on every reload. A reload request alone is not install/update authorization. Before invoking either entry, the actual grant must cover relevant possible package effects; otherwise stop and clarify without invoking. Explicitly commissioned native package installs/updates remain allowed. Workbench adds no installer, reload clone or technical permission enforcer.

The reload tool validates its input and checks its abort signal before recording plain request data in the current runtime. It returns `terminate: true`. Pi omits the automatic model follow-up only when every result in that tool batch terminates; mixed batches continue normally without aborting sibling tools. At native `agent_settled`, Workbench removes the pending request and dispatches its command through `sendUserMessage` with `expandPromptTemplates: true` and no delivery flag. Pi defers that dispatch until all settled handlers finish. Expansion dispatches the command; it does not expand the JSON-encoded continuation prompt.

The command remains directly usable. It validates the JSON again and waits for native idle before appending a `workbench.reload` CustomEntry containing `{ initPrompt }` or `{}`. Only the active branch participates.

The schema leaves `initPrompt` as optional `Unknown` with an explicit string description, then enforces the string type in the shared validator. Pi's native argument normalization can coerce string schemas and remove optional nulls. Preserving the original value here lets Workbench reject null, wrong types and whitespace-only strings rather than silently accepting them. Extra fields are rejected.

A small runtime-local guard rejects overlapping tool or command requests while a tool request is pending or a command waits for idle and saves its entry. The pending data is cleared before settled dispatch; the command guard is released immediately before terminal `await ctx.reload(); return;`. The public `Promise<void>` cannot distinguish native refusal from success. No cleanup runs through stale post-reload state. Reload execution remains host-owned; these guards are not a global reload lock.

The replacement runtime's `session_start` reads the latest own entry through `getBranch()`. A reload retains its prompt locally; other start reasons discard it with an empty entry. In `resources_discover`, the runtime removes its local copy and appends an empty entry before sending one hidden `workbench.reload.init` CustomMessage with `triggerTurn: true` and `deliverAs: "followUp"`. The message includes model-origin provenance and a request to fully re-read relevant offered Skills and triggered references, followed by the unchanged prompt. Pi converts this content to user-role provider text; it is not a new human instruction or additional authority.

This hook runs after every `session_start` handler, not after all additional discovery or UI work. A send failure after consumption can lose the continuation; there is no retry. A failure after saving but before consumption can leave a prompt for a later ordinary reload. A no-prompt command or non-reload start discards that remainder. Normal later reloads do not replay consumed prompts, but navigating or forking back before consumption can expose old branch state again. No global deduplication or exactly-once model effect is claimed.

A pre-aborted tool call records nothing. Aborting a run after a successful request does not revoke it; native settlement can still dispatch the reload. Reload alone starts none of Workbench's kickoff, index or retention work. Existing shutdown cleanup remains in effect.

Previously documented local checks against Pi 1.5.0 exercised actual SDK loading with only Workbench, eight reloads, strict inputs, overlap, abort, mixed batches, literal continuation and normal no-replay behavior. Provider responses were an offline double; personal context, Skills and other Extensions were excluded. Earlier separate typechecks passed with local Pi 1.3.0 dependencies and installed Pi 1.5.0 declarations. Current local development dependencies resolve to Pi 1.3.0; native host peers remain `*`. The manifest declares Node.js 22.19.0 as its minimum, not proven minimum-runtime support. Pi 1.5.0 is a reviewed source/evidence version, not a latest-release guarantee. These checks do not prove real-model compliance, TUI behavior, minimum-Node support, concurrent direct commands or reload-refusal handling.

Separate visible smoke tests on 8 November 2026 used Pi 1.5.0 with only Workbench loaded as an Extension and the normal user model configuration, Skills and prompts retained. The `/workbench` command, `workbench({})` tool, PiQuickDoku search and reading an original hit section succeeded with a live model. Retention reported zero removals. No installation, updates, reload or original/settings edits ran. This is observed entry/search evidence, not configuration-free operation, archive-deletion or reload-recovery validation, general model compliance or minimum-Node proof.

## Startup and shutdown

Only a successful explicit Workbench command/tool entry starts the index check and background retention. The two tasks do not delay guidance delivery. Repeated starts share in-flight work.

The index builds on first use and after the installed public Pi version changes. Same-version starts reuse the committed index without traversing the documentation again. The worker commits index rows and completion metadata in one SQLite transaction. Failed or incomplete current-version construction is not presented as a ready index.

Retention observes its supplied abort signal. Shutdown aborts it immediately, then awaits both retention and index closure. Index closure terminates an active worker and awaits its actual exit. Retention notices are suppressed after cancellation so they do not appear in a replacement session.

## Search results

All search words must match one source line. Punctuation separates words; FTS operators are not exposed as query syntax. Results preserve full paths and explicitly 1-based source lines. Search output is limited to 100 hits, 500 UTF-16 code units per snippet plus its truncation marker, and 24 KiB of serialized hits. Omissions are disclosed rather than shortening provenance paths.

Ready, not-ready and error states are distinct. Early queries do not wait for construction and do not return a stale version as current. Search excerpts are leads: read surrounding source context before treating them as complete evidence.

## Original archives and retention

### Pre-edit backup scope

Automatic pre-edit backups are limited to Pi-owned configuration and authoring originals in the Pi directory, including its Append, Skills and settings. Resolve symlinks before classifying the source. If the resolved original belongs to a Git repository, do not create a Workbench backup, including for repository-backed Skills linked into Pi. Other project files, Extension repositories and files outside the Pi scope are not automatic backup targets. `~/.pi/agent/APPEND_SYSTEM.md` is a pre-edit backup target when not repository-backed.

The archive helper enforces this boundary before creating archive storage. It checks resolved paths against the actual Pi agent directory and detects ancestor `.git` directories or files, including linked worktrees. It does not inspect tracked files, commits or remotes. Skipped results contain `status: "skipped"`, resolved `sourcePath` and `reason` (`git-repository` or `outside-pi`), without archive metadata. Actual backups return `status: "archived"` with the archive identity below. Existing archives and retention remain unchanged.

Originals stay at their responsible locations. The archive helper resolves real paths, validates project containment, compresses actual bytes and publishes a completed gzip archive without overwriting an existing archive. Reversible path components retain project-relative hierarchy or identify an external original. The helper uses Pi's native same-file mutation queue; this is not a cross-process lock or a filesystem sandbox.

Settings, index and archives live outside the installed package under `<Pi-agent-directory>/workbench/`. Retention defaults to 30 days and uses the timestamp in a matching archive filename, not its filesystem modification time. Only regular eligible own-format archives strictly older than the cutoff expire; unknown formats and symlink targets are preserved. Cleanup is not transactional.

The [authoring guide](../guides/pi-authoring.md#3-establish-permission-and-pre-edit-backup) and [retention reference](../guides/pi-authoring.md#backup-retention-and-explicit-starts) contain the detailed format and edge conditions.

## Tool effect hints

All five tools declare native `annotations`. PiQuickDoku is local/read-only. Kickoff writes index data and can delete expired own backups. Archival writes new local files; changing retention settings writes local settings but does not itself delete archives. Reload changes runtime state, can initialize installed resources and may install configured packages or update temporary sources. These hints inform native integrations; they neither grant permission nor intercept other tools. Tool exposure and discovery remain unchanged.

## Workflow ownership

Project instructions use a verified native context original, normally `AGENTS.md` or an existing supported source such as `CLAUDE.md`. `.pi/Pi.md` is used only when its inclusion is independently verified; reload does not add it. Existing guidance is not migrated or overwritten without authorization. The complete internal agent-writing method ships with Workbench; additional human-prose writing Skills are optional.

Direct Prompt and Skill work uses the bundled original writing method and the Pi-only pre-edit backup scope above. Simple explicit reusable Markdown slashprompts with arguments use native prompt templates; richer workflows with references use Skills, executable integration uses an Extension handoff. The eleven shipped Skill examples are not native prompt templates. The [direct authoring guide](../guides/pi-authoring.md) covers the actual configured personal/project/package original, frontmatter, argument substitution and authorized discovery/effect checks.

Before claiming a global Append's effect, verify the actual agent directory, trusted project shadowing and explicit host prompt sources/overrides. A trusted `.pi/APPEND_SYSTEM.md` takes precedence over the corresponding agent-directory file; same-name files are not automatically combined. When needed and authorized, native `getSystemPromptOptions()` can inspect base construction inputs, not certify later prompt transformations. No prompt dump, automatic merge or new diagnostic tool is required. Document-grounded clarification uses the internal [Grill procedure](../guides/grill-with-docs.md), not another installed resource.

Existing package acquisition, configuration and updates remain native Pi operations under their actual task grants. For new technical projects and Extension code changes, Workbench prepares a usable handoff; the receiving agent owns detailed planning, implementation and tests.

The [Security Policy](../SECURITY.md) and [README](../README.md) distinguish implemented helpers, model-directed workflow and validation limits.
