# `@pzzld/pi-shepherd`

The Pi adapter is a thin host extension over `@pzzld/component-runtime`.
Identity normalization, guard evaluation, lifecycle planning, provider
capability validation, and request-to-response exchange validation are implemented once by the
`fl03:shepherd@6.7.1` Rust WebAssembly component.

Pi contributes its extension API; an operator may separately select a launch
adapter. At `session_start`, after tools are registered, the production
extension reads Pi's public `pi.getAllTools()` inventory. Readiness requires an
explicit bounded provider identity, the `dispatch_once` capability, a real
`launch()` method, and an explicit tool name present in that inventory. No
provider brand implies a tool name, and a tool name alone never establishes a
launch capability. The legacy `subagent` and `fabric_exec` names remain guarded
when unselected so a raw host orchestration call cannot bypass the fail-closed
path. A configured adapter with missing, contradictory, or unobserved facts
leaves the session readable and blocks orchestration with this remediation:

```text
Pi orchestration provider unavailable. Configure an operator-selected Native-bound adapter that explicitly provides dispatch_once, a launch method, and a registered tool identity; installing a host tool alone is insufficient.
```

Shepherd does not prescribe or depend on a provider package. Stock provider
installation is not sufficient: the selected adapter must expose the explicit
Native-bound contract above. Native `shepherd` bind and resolve requests remain
the only identity authority. With no adapter configured, the Pi root remains
Native-only and legacy raw orchestration calls are denied as unsupported rather
than treated as an installed provider.
Every bind, resolve, start, resume, and stop response is correlated by the
Component across its operation, optional run, harness, session, agent, lane,
role, tool-call ID, and operation-specific lifecycle fields before Pi consumes
it. Native `ExecutionContext` owns project and working-directory facts; the
guard separately cross-checks input-derived write paths. The lower-level
embedding adapter retains typed capability-envelope checks for direct provider
lifecycle calls. Production readiness combines the selected adapter's explicit
capability envelope with the exact Pi configured-tool observation.
That readiness report proves only adapter admission. It does not prove that an
installed stock provider exposes the Native-bound launch contract or that a Pi
host tool call can be consumed or replaced. Ordinary Write, Edit, and Bash
remain governed independently by the Component and Native identity checks when
no orchestration adapter is available.
The machine-readable contract is
[`shepherd.pi.json`](./shepherd.pi.json); no shell fallback is used.

## Install

```sh
pi install npm:@pzzld/pi-shepherd
```

Configure the separately installed, operator-selected orchestration adapter to
expose the required Native-bound `dispatch_once` contract. Shepherd does not
claim that an unadapted stock provider supplies that contract.

Pi discovers everything this package contributes from the `pi` key in
`package.json`: `extensions`, `skills`, `prompts`, and `subagents.agents`. With
that declaration absent Pi loads no Shepherd agent definitions even when the
role prompts are present.

The nine skills, nine role prompts, and seven dispatchable agent definitions are
**generated**, not committed. The Rust compiler is their only authority, and a hand-copied
tree in this package would be a second, inevitably stale one -- `scripts/tests/test-generated-carrier-authority.sh`
fails if `skills/`, `prompts/`, or `agents/` appears in the repository. Release staging runs
`scripts/stage-harness-carriers.sh`, which invokes `shepherd compile --target pi` into
the staged package immediately before `npm pack`, so the published tarball
carries the carrier and the repository does not.

The published carrier is project-neutral. An `inherit-caller` role carries
`model: inherit`. Every other role carries `model: model-required/model-required`,
a generic intentionally impossible sentinel that prevents direct provider launch from
falling back to a parent or global default. Supported dispatch passes the exact concrete
`provider/model:thinking` result of `shepherd models resolve ROLE --harness pi` as a
per-run model override; the selected adapter must preserve that override.

Each generated agent explicitly reloads `src/extension.mjs` in nested children.
Tool registration does not grant dispatch authority. Native prepares and starts
each accepted child as an isolated process, registers its real PID, and supplies
the exact broker launch, session, agent, and adapter-local agent-type metadata.
At child `session_start`, the extension accepts only that complete broker
metadata and requires Pi's actual `SessionManager.getSessionId()` to equal the
Native-prepared session. Child-local `message_end` and `session_shutdown`
callbacks can request completion only for that exact active Native record.
Provider results, session-file paths, parent observations, and caller-supplied
status values cannot activate or complete a child.

To materialize the same tree yourself against a checkout, use `shepherd compile
--target pi --out <absolute-directory>`; the adapter exposes no separate
materializer or CLI.

Pi loads the generated component from the adjacent authority-checked runtime
packaged in `@pzzld/component-runtime/runtime`. Test injection is exposed only
through the separate component-runtime test-support entrypoint. Release staging is performed by
`scripts/stage-component-runtime.sh`; generated `.wasm`, `.js`, and `.d.ts`
files are not committed to the repository.

Node 20 or newer is required. The published runtime is JavaScript; separate
declarations preserve the Pi extension types without runtime type stripping.
Run the adapter gate with:

```sh
node test.mjs
```
