@aeondave/pi-persona 1.15.2 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/AGENTS.md +32 -6
  2. package/CHANGELOG.md +97 -0
  3. package/README.md +27 -8
  4. package/SECURITY.md +42 -0
  5. package/docs/ARCHITECTURE.md +52 -7
  6. package/docs/EXPERIENCE.md +21 -5
  7. package/docs/README.md +2 -0
  8. package/docs/REFERENCE.md +84 -14
  9. package/docs/STRATEGIES.md +58 -31
  10. package/docs/TELEMETRY.md +14 -0
  11. package/package.json +18 -11
  12. package/src/bus/broker/paths.ts +3 -2
  13. package/src/core/brief.ts +1 -1
  14. package/src/core/nudge.ts +3 -4
  15. package/src/core/pi-compat.ts +3 -3
  16. package/src/engine/adapter.ts +11 -6
  17. package/src/engine/async.ts +12 -6
  18. package/src/engine/inproc.ts +14 -6
  19. package/src/extension/engine.ts +25 -4
  20. package/src/extension/hooks.ts +68 -21
  21. package/src/extension.ts +233 -57
  22. package/src/orchestration/model-retry.ts +32 -61
  23. package/src/orchestration/params.ts +27 -1
  24. package/src/orchestration/roster.ts +80 -3
  25. package/src/orchestration/sdk.ts +150 -36
  26. package/src/orchestration/strategies/compete.ts +14 -8
  27. package/src/orchestration/strategies/council-rounds.ts +8 -1
  28. package/src/orchestration/strategies/critic-loop.ts +25 -11
  29. package/src/orchestration/strategies/judge.ts +18 -9
  30. package/src/orchestration/strategies/magi.ts +42 -93
  31. package/src/orchestration/strategies/map.ts +41 -19
  32. package/src/orchestration/strategies/pipeline.ts +2 -2
  33. package/src/orchestration/strategies/synthesize.ts +18 -11
  34. package/src/orchestration/types.ts +15 -0
  35. package/src/persona/model-participants.ts +240 -0
  36. package/src/persona/orchestrate.ts +44 -2
  37. package/src/persona/persona.ts +86 -14
  38. package/src/telemetry/contract.ts +1 -1
  39. package/src/telemetry/producer.ts +241 -8
  40. package/src/tools/council.ts +36 -8
  41. package/src/tools/delegate-tool.ts +162 -24
  42. package/src/tools/intercom-tool.ts +119 -32
  43. package/src/ui/agent-overlay.ts +15 -6
  44. package/src/ui/agent-tree.ts +39 -2
package/AGENTS.md CHANGED
@@ -30,8 +30,18 @@ the shared behavioral prompt layer: [`docs/SPINE.md`](docs/SPINE.md).
30
30
  `@earendil-works/pi-*`; never bundle copies.
31
31
  - npm publishes as `@aeondave/pi-persona`. Pi supplies the four `@earendil-works/pi-*` packages
32
32
  and `typebox`: keep them as `peerDependencies: "*"` with development-only copies, never runtime
33
- dependencies. The supported host floor lives in `MIN_PI_VERSION` and the README. Keep the npm
33
+ dependencies. The supported host floor is Pi ≥ 1.0.0 (`MIN_PI_VERSION` and the README); Node.js
34
+ must be ≥ 22.19 to match that host. Keep the npm
34
35
  `files` allowlist explicit for docs/artwork, inspect `npm pack --dry-run`, and never publish drafts.
36
+ - Supply-chain controls: pin every GitHub Action to a verified full commit SHA; keep top-level
37
+ token permissions read-only, grant write permissions only to the reporting job that needs them,
38
+ and disable persisted checkout credentials. Dependabot proposes updates; it does not auto-merge.
39
+ Keep the four Pi development packages in one update group so their APIs stay aligned.
40
+ Match `@types/node` to the oldest supported Node major, including in CI; upgrade them together.
41
+ Keep security overrides scoped to the affected development dependency and version; remove them
42
+ when upgrading Pi if the new dependency graph no longer needs them.
43
+ Run the full dependency audit (including development dependencies), tests and typecheck after
44
+ lockfile updates. A development override does not patch a user's installed Pi host.
35
45
  - **Cross-OS**: use Pi's spawn/kill/path/temp helpers (`getPiInvocation`, `killProcessTree`), not raw
36
46
  `child_process`. Windows kill goes straight to `taskkill /F /T`; always attach an `error` listener.
37
47
  - Two engines behind the `StrategyEngine` seam: **InProcessEngine** (`engine/inproc`,
@@ -78,6 +88,11 @@ the shared behavioral prompt layer: [`docs/SPINE.md`](docs/SPINE.md).
78
88
  policy (OpenAI-family → OpenAI providers; Claude-family → the native Claude provider). A caller may
79
89
  explicitly opt a pinned run into cross-provider recovery. Only `failureKind === "provider"` reroutes;
80
90
  abort/timeout/contract/unknown/agent are terminal.
91
+ Strategy/council/flow runs disable that provider search and use SDK-level main-only recovery:
92
+ `provider`/`unknown-model` may retry ONCE on the current supervisor model, including a saved or
93
+ inline-pinned choice (explicit user-authorized exception). Never borrow a peer model, never restart
94
+ a stopped/timed-out/contract-failed leg, and charge each attempt to child/token limits and usage.
95
+ Ordinary delegate pins remain strict. Recovery must remain visible in metadata/UI and MAGI rulings.
81
96
  Engines classify the cause on the `AgentResult` (`failureKind` + resolved `modelUsed`); keep those
82
97
  set when you touch `inproc.ts`/`adapter.ts` or the fallback silently stops working.
83
98
  - **Fork-bomb guard**: children run with env `PI_PERSONA_DISABLE=1` so pi-persona self-disables inside
@@ -93,11 +108,13 @@ the shared behavioral prompt layer: [`docs/SPINE.md`](docs/SPINE.md).
93
108
  blind retry loops are stopped by the runtime `DelegationLedger` (an identical agent+model+task
94
109
  delegation that failed twice is vetoed before it spawns).
95
110
  - Dynamic sub-agents: `delegate` shapes an on-the-fly specialist with `role` (extra system prompt,
96
- appended to the agent's own) + `skills` — prompt-level only, capabilities stay the gate. Async runs
97
- are joined with intercom `wait` (bounded ≤ the bus-ask timeout; collected results are discarded from
98
- the pending completion follow-up so they are never double-reported). In interactive sessions
99
- `delegate` is background-by-default (`sync: true` opts a call out; headless `pi -p` defaults to
100
- sync so the single turn carries the result).
111
+ appended to the agent's own) + `skills` — prompt-level only, capabilities stay the gate. Intercom
112
+ `wait` snapshots already-settled reports by default in interactive/RPC sessions; `sync: true` opts
113
+ into a bounded join (≤ the bus-ask timeout). Headless waits default to joining; `sync: false` takes
114
+ a snapshot. Collected reports are discarded from the pending completion follow-up so they are
115
+ never double-reported; snapshots leave running children active. In interactive sessions `delegate`
116
+ is background-by-default (`sync: true` opts a call out; headless `pi -p` defaults to sync so the
117
+ single turn carries the result). An explicit `async` flag takes precedence over `sync` and the default.
101
118
  Message ids and run ids are separate: `intercom message { messageId }` retrieves retained bus
102
119
  text, `intercom result { to: runId }` retrieves a settled run. Both explicit and automatic inbox
103
120
  drains retain bounded history (256 messages / 256,000 body characters). Ask settlement clears
@@ -120,6 +137,10 @@ the shared behavioral prompt layer: [`docs/SPINE.md`](docs/SPINE.md).
120
137
  fills with every leg's body, failures included), while `renderCompletion` scans only `status: "done"`
121
138
  runs. A background leg that FAILED while emitting `[BLOCKED]` therefore gets the failure block but no
122
139
  persistence note — deliberate (see the `renderCompletion` doc comment), not a bug to "fix" silently.
140
+ Nested reports from codemode's `ctx.executeTool` retain bounded provenance through Pi's explicit
141
+ `parentToolCallId`; never infer nesting from the call-id string. Only an outer result that relays
142
+ the surrender marker gets the note/card. Nested programmatic data is never patched with a reminder,
143
+ and discarded reports never generate an invisible one. Relay state clears at turn/session settlement.
123
144
  `config.nudge` (`PI_PERSONA_NUDGE=off`) silences all of it: the `tool_result` hook (the by-hand
124
145
  reminder and the sync-result persistence one) and both `renderCompletion` call sites, which take
125
146
  their `scan` through the same gate — so a background/`intercom wait` report carries no note either.
@@ -177,6 +198,8 @@ the shared behavioral prompt layer: [`docs/SPINE.md`](docs/SPINE.md).
177
198
 
178
199
  ## Testing
179
200
 
201
+ - Offline SDK harnesses must await `session_shutdown` before SDK `dispose()` and temporary-profile
202
+ deletion. `dispose()` disconnects SDK listeners; it does not join extension-owned writers.
180
203
  - TDD: write the failing test first for `core/*` and any behavior change; watch it fail, then fix.
181
204
  - Done = `npm run typecheck` clean **and** full suite green. The suite has **two** intentional skips,
182
205
  both Windows-only — the runner reports `skipped 2` on Windows and `skipped 0` elsewhere (see
@@ -190,6 +213,9 @@ the shared behavioral prompt layer: [`docs/SPINE.md`](docs/SPINE.md).
190
213
  persistence; `src/extension/identity.ts` registers `agent_name` and the pre-name context bootstrap.
191
214
  Exocom uses that same state. A delegate's optional `AgentRunSpec.name` is leader-assigned
192
215
  display identity, propagated to both engines without changing routing ids.
216
+ Async launch/control cards use that alias, with persisted tool-result snapshots for history.
217
+ Keep run IDs for routing/diagnostics, not primary display identity; disambiguate duplicate aliases.
218
+ Steering cards preview the accepted message and expose all of it with Pi's expand-key binding.
193
219
  Runtime metadata guidance belongs in the stable supervisor system prompt, not a new user-like
194
220
  acknowledgement message. Keep initial setup/actionable asks working, preserve user-visible history,
195
221
  and never re-inject a chosen identity. Progress `tokens` is cumulative input/output usage, not live
package/CHANGELOG.md CHANGED
@@ -6,6 +6,103 @@ used in its [GitHub releases](https://github.com/AeonDave/pi-persona/releases).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.16.1](https://github.com/AeonDave/pi-persona/releases/tag/v1.16.1) - 2026-10-06
10
+
11
+ ### Fixed
12
+
13
+ - Publish the real pending-supervisor-ask state as `agent.updated` telemetry for Flow. Refresh it on
14
+ ask delivery and reply/timeout/cancellation settlement, without duplicate events or text-based
15
+ guesses; queued and terminal state remain authoritative.
16
+ - Make the native offline codemode harness await extension shutdown before deleting its temporary
17
+ profile; SDK `dispose()` alone does not flush the extension's telemetry writer.
18
+
19
+ ### Packaging
20
+
21
+ - Add the npm author and focused Pi gallery keywords; align the banner preview and pinned install
22
+ examples with this release.
23
+
24
+ ## [1.16.0](https://github.com/AeonDave/pi-persona/releases/tag/v1.16.0) - 2026-10-03
25
+
26
+ ### Compatibility
27
+
28
+ - Require Pi ≥ 1.0.0 and Node.js ≥ 22.19. Update the development cohort to Pi 1.0's four coordinated
29
+ host-package pins and qualify its SDK and tool lifecycle. Pre-1.0 Pi hosts are no longer supported;
30
+ the host packages and TypeBox remain wildcard peers supplied by Pi, not bundled runtime copies.
31
+ - Update the live control harness to use Pi 1.0's session `modelRuntime` through the public
32
+ `ModelRegistry` facade instead of the removed session registry property.
33
+ - An authored `council.members` field is now validated. Older malformed fields that were ignored
34
+ must be corrected or removed; council calls fail with the field diagnostic instead of selecting
35
+ an unrelated fallback panel.
36
+
37
+ ### Fixed
38
+
39
+ - Reserve mandatory downstream child slots before optional model recovery in `map`, `pipeline`,
40
+ `critic-loop`, and `council-rounds`. Provider outages no longer spend the slots needed by later
41
+ workers, verifiers, steps, or rounds and turn completed work into a run-fatal admission error.
42
+ - Pass live supervisor-ask state to the `intercom peek` tool, including untargeted peeks; a child
43
+ waiting for its supervisor is not reported as stuck. Collapsed steer receipts identify the run.
44
+ - Honor members-only council profiles for active and explicitly selected personas, including their
45
+ params when MAGI is selected explicitly as the same default strategy. Evaluate each configured
46
+ agent-model lookup once.
47
+ - Carry persistence checkpoints through nested codemode reports when their `[BLOCKED]`/`FLAG:
48
+ UNKNOWN` marker is relayed to the model. Suppressed nested output stays unchanged; only the outer
49
+ visible result receives the checkpoint and its expandable card.
50
+ - Surface telemetry cleanup/write diagnostics without requiring debug mode; diagnostics remain
51
+ non-fatal. Failed admission removes only the empty directories created by that attempt.
52
+ - Release a telemetry writer lease after its terminal writes finish without waiting for the shared
53
+ retention sweep over unrelated sessions; explicit maintenance joins remain available.
54
+ - Harden the exported council-preset expansion boundary with normalized strategy names and the
55
+ same strategy/roster/params allowlist as the JSON loader; validated authored members remain intact.
56
+ - Resolve live tree and telemetry model labels for auxiliary actors through the same role-specific
57
+ participants as the picker, including inline model pins and repeated SDK keys. Ambiguous short
58
+ role hints omit an uncertain model rather than attributing a different participant's choice.
59
+
60
+ ### Changed
61
+
62
+ - Make general council guidance proportionate while preserving MAGI and Judge's specialized focus;
63
+ all eleven strategies remain available through the same tool. Add ephemeral inline council members
64
+ and specialized external actors without creating persona/team files.
65
+ - Include role-specific members and external arbiters in model selection; respect configured models
66
+ and remember prompts per participant rather than suppressing later teams for the whole persona.
67
+ - Recover model/provider failures across strategies and flows once on the supervisor's current model,
68
+ including unavailable saved or pinned choices. Remove MAGI's peer-model substitution; report the
69
+ switch, account both attempts, and preserve child/token limits and cancellation.
70
+ - Use worker aliases in async launch cards and targeted Intercom call headers, matching the live tree.
71
+ Persist display identity in tool results so history remains readable after reload or tracker eviction;
72
+ routing still uses run IDs, with a secondary ID shown when aliases collide.
73
+ - Show the accepted steering message as a compact preview, with Pi's expand-key hint for the full
74
+ message and diagnostic run ID. Replace repetitive soft-request/cancellation boilerplate with a
75
+ concise queued receipt; steering remains a request, not proof of execution or cancellation.
76
+ - Make context-burn checkpoints aware of Pi's nested-tool metadata: raw inner results do not
77
+ consume the model-visible output budget or receive invisible reminders. Permission gates,
78
+ telemetry and genuine successful hand-off resets still apply inside codemode.
79
+ - Show an immediate async completion banner with the worker's display name, including successful
80
+ runs. The semantic report still arrives once through the idle-gated completion path, and a failed
81
+ UI notification cannot swallow it.
82
+ - Replace the child watchdog test's load-sensitive kill-latency assertion with an observed blocked →
83
+ released → idle-timeout barrier; preserve the two intentional Windows-only skips.
84
+ - Clarify that automatic background completion follow-ups and end-turn guidance are the intended
85
+ async default: continue independent work, and do not monitor or join all workers when they are the
86
+ only remaining work. `intercom wait` now snapshots without blocking by default in interactive/RPC
87
+ sessions; `sync: true` opts into its bounded join, while headless remains blocking by default and
88
+ `sync: false` opts out. Snapshots collect only already-settled reports, leaving running work active.
89
+ Queued steering does not preempt an explicitly blocking join. A real Pi 1.0 SDK test with a local faux provider characterizes steering becoming
90
+ dormant when delayed input hooks outlast the active run. No unsafe input-triggered join abort ships.
91
+ - A council call that switches strategy no longer inherits unrelated profile params; params continue
92
+ to merge when the selected strategy is unchanged, and unknown explicit keys still warn.
93
+ - Show live supervisor asks as `waiting for supervisor`, rather than stalled, in the tree, F9 and
94
+ peek; refresh council parent clocks on child progress. A waiting worker becomes eligible for
95
+ stall detection again when its ask settles. Steering an already-settled run points to its result.
96
+ - Add age-based telemetry cleanup with a 30-day default; see
97
+ [`docs/TELEMETRY.md`](docs/TELEMETRY.md) for the retention contract.
98
+ - Reuse one tree snapshot per F9 list redraw for rows, selection and waiting state; remove an
99
+ unreachable delegate-title branch and distinguish event liveness from proof of useful progress.
100
+ - Align the README and technical guides on async snapshots/joins, steering delivery, model-selection
101
+ precedence, members-only councils, and automatic `map` verifier headroom.
102
+
103
+ After updating, let active workers settle and restart Pi (or use `/reload`). `/persona reload`
104
+ refreshes definitions, not extension code. Existing custom personas and provider pins are preserved.
105
+
9
106
  ## [1.15.2](https://github.com/AeonDave/pi-persona/releases/tag/v1.15.2) - 2026-09-28
10
107
 
11
108
  ### Distribution
package/README.md CHANGED
@@ -4,9 +4,12 @@
4
4
  <img src="assets/banner.png" alt="pi-persona — supervised multi-agent orchestration for Pi">
5
5
  </p>
6
6
 
7
+ [![CI](https://github.com/AeonDave/pi-persona/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/AeonDave/pi-persona/actions/workflows/test.yml) [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/AeonDave/pi-persona/badge)](https://scorecard.dev/viewer/?uri=github.com/AeonDave/pi-persona) [![npm version](https://img.shields.io/npm/v/@aeondave/pi-persona?logo=npm)](https://www.npmjs.com/package/@aeondave/pi-persona) [![License](https://img.shields.io/github/license/AeonDave/pi-persona)](LICENSE)
8
+
7
9
  **Give Pi a supervised team.**
8
- `pi-persona` brings supervised multi-agent orchestration to [Pi](https://github.com/earendil-works/pi):
9
- async workers, live steering, cross-session collaboration, and switchable personas.
10
+ `pi-persona` adds supervised multi-agent orchestration to [Pi](https://github.com/earendil-works/pi):
11
+ async workers, live steering, cross-session collaboration, and switchable personas. It builds on
12
+ Pi's native SDK and tool hooks; the extension adds worker supervision and coordination.
10
13
  Describe the outcome. A supervisor delegates work, gathers results, and checks the outcome;
11
14
  you can inspect workers, redirect them, or stop a run while it is in progress.
12
15
 
@@ -14,7 +17,7 @@ you can inspect workers, redirect them, or stop a run while it is in progress.
14
17
 
15
18
  ## Install
16
19
 
17
- Requires **Pi ≥ 0.83**, **Node.js 22+**, and **Git**. Configure a model provider in Pi first.
20
+ Requires **Pi ≥ 1.0.0**, **Node.js ≥ 22.19**, and **Git**. Configure a model provider in Pi first.
18
21
 
19
22
  Run in your terminal:
20
23
 
@@ -36,9 +39,9 @@ your customizations.
36
39
  | Install option | Command |
37
40
  |---|---|
38
41
  | This project only | `pi install -l npm:@aeondave/pi-persona` |
39
- | Pin this release | `pi install npm:@aeondave/pi-persona@1.15.2` |
42
+ | Pin this release | `pi install npm:@aeondave/pi-persona@1.16.1` |
40
43
  | Update an unpinned install | `pi update npm:@aeondave/pi-persona` |
41
- | Git alternative | `pi install git:github.com/AeonDave/pi-persona@v1.15.2` |
44
+ | Git alternative | `pi install git:github.com/AeonDave/pi-persona@v1.16.1` |
42
45
 
43
46
  Restart Pi after updating. For a pinned install, install the new version or tag explicitly.
44
47
  If switching from a Git install, remove that source first with
@@ -69,8 +72,12 @@ For example, specialists can investigate code paths, tests, and the API contract
69
72
  Their findings return to the **same supervisor**, which integrates them, verifies the fix, and reports
70
73
  the outcome. This is one possible workflow, not a fixed pipeline; dependent steps run in order.
71
74
 
72
- Interactive delegation runs in the background by default. The supervisor gathers results and keeps
73
- you informed; you can inspect or redirect a worker at any point.
75
+ Interactive delegation runs in the background by default. Results return automatically when the
76
+ supervisor is free; you can inspect or redirect a worker at any point.
77
+
78
+ Launch and control cards show the worker's name. Steering receipts preview the message sent;
79
+ expand with `Ctrl+O` (the default binding) to read it in full. A queued message is not proof that
80
+ the worker has acted on it.
74
81
 
75
82
  | Key or command | Action |
76
83
  |---|---|
@@ -135,6 +142,13 @@ everyday coding, or choose one for the work ahead.
135
142
  These are editable starting points. Browse the bundled [personas](personas) and [worker agents](agents),
136
143
  or read the [practical guide](docs/EXPERIENCE.md) for help choosing a workflow.
137
144
 
145
+ Strategies are not restricted to the similarly named persona: `council` can select `judge`, `magi`,
146
+ `debate`, `critic-loop`, or another installed shape when it adds value. Temporary `members` allow
147
+ custom role-based groups without team files. Model selection includes external arbiters. In councils
148
+ and flows, a provider failure or unavailable model can recover once on the supervisor's model, with
149
+ the switch visible and both attempts accounted; ordinary delegates keep explicit provider pins strict.
150
+ See [the reference](docs/REFERENCE.md) for an inline council example and recovery limits.
151
+
138
152
  ## Make it yours
139
153
 
140
154
  Edit installed personas and agents in `~/.pi/agent/persona/agents/`, or add project-specific
@@ -169,4 +183,9 @@ npm test
169
183
  ```
170
184
 
171
185
  Pi loads the TypeScript extension directly; there is no build step.
172
- See [AGENTS.md](AGENTS.md) for contribution conventions. Licensed under [MIT](LICENSE).
186
+ The [CI workflow](https://github.com/AeonDave/pi-persona/actions/workflows/test.yml) runs strict
187
+ typechecking, dependency auditing and the test suite on Linux and Windows. The OpenSSF badge links to the project's
188
+ scored supply-chain checks; it is not a certification that the code is free of vulnerabilities.
189
+
190
+ See [AGENTS.md](AGENTS.md) for contribution conventions and the [security policy](SECURITY.md)
191
+ for private vulnerability reporting. Licensed under [MIT](LICENSE).
package/SECURITY.md ADDED
@@ -0,0 +1,42 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes target the latest published version of
6
+ [`@aeondave/pi-persona`](https://www.npmjs.com/package/@aeondave/pi-persona).
7
+ Older versions do not have a guaranteed backport policy. Check the
8
+ [release notes](https://github.com/AeonDave/pi-persona/releases) for fixes and
9
+ upgrade instructions. Keep your Pi host and Node.js runtime updated as well.
10
+
11
+ ## Reporting a vulnerability
12
+
13
+ Use [GitHub private vulnerability reporting](https://github.com/AeonDave/pi-persona/security/advisories/new).
14
+ Do not open a public issue with exploit details, credentials, private session
15
+ logs, or other sensitive material. Ordinary bugs can use the public issue tracker.
16
+
17
+ Include the affected package version or commit, Pi and Node.js versions, operating
18
+ system, relevant configuration, expected security boundary, actual behavior, and
19
+ a minimal reproduction with synthetic data. Explain the impact and any safe
20
+ workaround you have verified. Do not test against other users' sessions or systems
21
+ without their permission.
22
+
23
+ Follow-up and disclosure coordination happen in the private advisory. This is a
24
+ maintainer-run project, with no guaranteed response or remediation deadline and
25
+ no paid bug bounty. Agree on public disclosure after triage so users can receive
26
+ a fix or mitigation before exploit details are published.
27
+
28
+ ## Security boundaries
29
+
30
+ Pi extensions and installed persona/agent definitions are trusted local code and
31
+ configuration, not an OS sandbox. Capability checks and Exocom's cooperative file
32
+ claims do not isolate a malicious local process. A workspace join code is a
33
+ same-host routing reference, not an authentication secret. See the
34
+ [architecture](docs/ARCHITECTURE.md) for the actual trust boundaries.
35
+
36
+ Reports of capability bypasses, broker/Exocom trust violations, unsafe handling of
37
+ untrusted worker output, or unintended disclosure of session data are welcome.
38
+ Use synthetic credentials and payloads in reproductions.
39
+
40
+ The npm package uses Pi-provided peer dependencies rather than shipping another
41
+ Pi runtime. Development lockfile fixes do not update an installed user's host;
42
+ host vulnerabilities must also be addressed by updating Pi itself.
@@ -54,6 +54,10 @@ rejected with the run id to wait on, so a later call cannot slip past the in-bat
54
54
  - **L3 — flow file.** `flows/<name>.flow.json` composes strategies into a resumable DAG.
55
55
 
56
56
  You climb only when you want determinism, structure, or reuse. Nothing forces the higher tiers.
57
+ The `council` tool is a gateway to all installed strategies, not a universal instruction to vote on
58
+ routine work. Choose a strategy when its topology adds value; MAGI and Judge retain their specialized
59
+ persona focus. A caller can supply ephemeral `members` with inline roles/models/skills instead of a
60
+ named team, without persisting a team or switching personas.
57
61
 
58
62
  ## Binding invariants (I1–I7)
59
63
 
@@ -193,7 +197,8 @@ engine, telemetry, UI, and tool surfaces; it is not part of the transport/domain
193
197
  constrained-turn allowlist), `install.ts` (the feature's composition adapter: session-scoped plane +
194
198
  ledger + wait/tool/hook wiring).
195
199
  - **`src/telemetry/`** — a generic, versioned observer/export contract for future plugins: projected
196
- lifecycle metadata only, never an agent-message router or control surface.
200
+ lifecycle metadata only, never an agent-message router or control surface. See
201
+ [`TELEMETRY.md`](./TELEMETRY.md) for privacy, retention, writer leases, and shutdown behavior.
197
202
  - **`src/persona/`** — identity: `persona.ts` (parse + `expandCouncilPreset` + `composeSystemPrompt`),
198
203
  `controller.ts`, `gating.ts`, `orchestrate.ts`, `config-store.ts`, `state.ts` (last-selected persona),
199
204
  `spine.ts` (the shared behavioral layer's SOURCE resolution — docs/SPINE.md; composition sits in
@@ -282,6 +287,19 @@ prevents an explicitly selected OpenAI or native Claude leg from silently moving
282
287
  provider. (`"verification"` is a further terminal value that never appears on an `AgentResult` — see
283
288
  `map`'s `verify` param in [`docs/STRATEGIES.md`](./STRATEGIES.md).)
284
289
 
290
+ Strategy/council/flow runs use a different, explicitly authorized recovery policy: the selected model
291
+ is tried first without arbitrary provider reroutes, then `makeSDK` may retry a `provider` or
292
+ `unknown-model` failure ONCE on the supervisor's current model. This main-only exception also applies
293
+ to saved and inline-pinned assignments; ordinary delegate provider pins remain strict. Missing main
294
+ models, repeated same-model attempts, stop/timeout/contract/agent/infrastructure failures, and exhausted
295
+ child/token budgets do not recover. Both attempts are accounted, and a warning plus result metadata
296
+ identify the switch. A per-role model assignment can supplement the legacy per-agent assignment;
297
+ preflight model selection includes external arbiters and other declared agent-valued parameters.
298
+ Live tree and telemetry labels use those participant identities for auxiliary actors too, with
299
+ inline model pins taking precedence. If distinct full roles share a short display hint, the display
300
+ keeps the hint (with `#N` suffixes for repeated node keys) but omits the uncertain model label rather
301
+ than borrowing another role's choice. Routing still resolves the full role key, not the display hint.
302
+
285
303
  ### MCP (and other `session_start`-scoped extensions) in sub-agents
286
304
 
287
305
  **A sub-agent does NOT share the supervisor's MCP session, and an in-process sub-agent gets NO MCP at
@@ -403,7 +421,9 @@ never simultaneously a telemetry event, a routed message, and a UI source of tru
403
421
  - **ProgressView** — a derived, read-only UI view computed *from* EngineEvents. Never authored, never
404
422
  a source of truth. The `f9` agent tree and `peek` digest are ProgressViews.
405
423
 
406
- Steering is always a Bus action; the peek digest is always a read-only ProgressView.
424
+ Steering is a supervisor-to-child control action, distinct from semantic Bus messages; requesting
425
+ steering does not establish that an active blocking join has been interrupted. The peek digest is
426
+ always a read-only ProgressView.
407
427
 
408
428
  External telemetry is not a fourth communication plane: it is a generic observer/export contract that
409
429
  future plugins may consume or produce, not an exclusive pi-persona protocol. It observes projected
@@ -459,6 +479,12 @@ for the supervisor and for explicit retrieval; the default TUI projection is del
459
479
  failed legs first, a failed council/flow card leads with the cause in its title, and an
460
480
  `intercom wait` card leads with the `N settled — X done, Y failed` tally (per-leg causes sit in the
461
481
  body, below the preview cut, so `wait`'s own success doesn't get a `failed` prefix);
482
+ - async launch cards and targeted Intercom call headers use the worker's canonical alias/model,
483
+ matching the tree rather than promoting its routing ID to display identity. Launch/control receipts
484
+ persist identity snapshots for history rendering; aliases never become routing keys. Colliding
485
+ aliases carry a secondary ID, and legacy receipts without a recoverable name retain their ID fallback.
486
+ Accepted steering receipts retain the exact sent message: collapsed cards preview it, expansion
487
+ shows all sanitized text and the diagnostic ID. A queued receipt does not prove the worker acted;
462
488
  - follow-up cards (`pi-persona`, exocom) retain their complete semantic content but render a bounded
463
489
  preview until expanded; terminal escape/control sequences are removed from the visible projection;
464
490
  - the sticky agent and exocom widgets have fixed row budgets — F9/`/agents` and paginated
@@ -606,15 +632,29 @@ a local process able to modify that directory is already inside the trust bounda
606
632
 
607
633
  - **sync** — the supervisor actively blocks on the delegate/strategy call (results still stream); no
608
634
  idle/peek/steer.
609
- - **async** — the supervisor returns control and goes **idle, spending no tokens**, until woken by an
610
- **event** (a child's `contact_supervisor`: a `decision`/`interview` blocks for a reply, `progress` is
611
- one-way) or the **peek watchdog**, which fires while async children run but stays SILENT unless there
612
- is something to act on — a healthy background run never interrupts. It surfaces on two independent
635
+ - **async** — interactive delegation is background-first; headless execution remains synchronous
636
+ by default. The prompt/runtime guidance is to continue independent work and, when only background
637
+ children remain, end the turn for automatic completion follow-ups rather than monitor or join the
638
+ whole batch. `intercom wait` collects a snapshot without blocking by default in interactive/RPC
639
+ sessions; settled results are reported and running children continue. Use `sync: true` for an
640
+ intentional bounded join. Headless sessions preserve the blocking default; `sync: false` requests a
641
+ snapshot. A snapshot does not wait, start timers/input hooks, or cancel children. Queued steering
642
+ does not release an explicitly active join. Input-triggered join interruption is
643
+ deliberately not implemented: a real Pi 1.0 SDK characterization shows steering can remain dormant
644
+ if delayed input hooks outlast the active run; no supported post-admission ordering guarantee
645
+ has been established. The supervisor otherwise returns control and
646
+ goes idle until a wake; the **peek watchdog** fires while async children run but stays SILENT unless
647
+ there is something to act on — a healthy background run should not interrupt. It surfaces on two independent
613
648
  signals: a **fast** wakeup (`PI_PERSONA_PEEK_MS`, ~30s, `0` disables) when a child NEWLY crosses the
614
649
  `STALL_FLAG_MS` (90s) stall window (a focused *possibly stuck* alert, framed patience-first — ask the
615
650
  leg, don't probe its environment) or messages the supervisor; and a **slow routine check-in**
616
651
  (`PI_PERSONA_CHECKIN_MS`, ~5 min, `0` disables) delivering the compact ProgressView digest — never
617
- full transcripts — so the supervisor can catch a leg going off-track early. Both let an idle
652
+ full transcripts — so the supervisor can catch a leg going off-track early. Live supervisor asks
653
+ are derived from the exact engine handle's optional `isWaitingForSupervisor` predicate: tree/F9/peek
654
+ show waiting, and the watchdog suppresses false stalls until the ask settles. Parent clocks advance
655
+ with child engine events (liveness, not proof of useful work); parents are waiting only when every
656
+ live descendant branch is waiting.
657
+ Both let an idle
618
658
  supervisor steer/stop a wedged or drifting child even with NO completion fired; the enforcing
619
659
  backstop is the engines' hard wall-clock cap (above). The full digest is also on demand via `/peek`.
620
660
  Progress tokens are labelled **cumulative input/output**, not context occupancy; cache-read/write
@@ -649,6 +689,11 @@ a persona directive lives at the TOP of the prompt and its pull decays as recent
649
689
  only `status === "done"` runs by design — a failed background/`wait` leg already gets a failure
650
690
  block, so a `[BLOCKED]` marker there doesn't also get the persistence note. Same marker, same leg,
651
691
  different counterweight depending on how it was collected.
692
+ Nested calls through codemode's `ctx.executeTool` leave their programmatic result untouched.
693
+ Pi's explicit `parentToolCallId` supplies the parent identity; call-id string shapes are never
694
+ used to infer nesting. A bounded set of parent call ids carries report provenance through wrappers
695
+ only while their output relays a surrender marker; the outer model-visible result alone gets the
696
+ note/card. Suppressed reports produce neither, and turn/session settlement clears abandoned relay state.
652
697
  - **The off switch covers every path.** `PI_PERSONA_NUDGE=off` silences DelegationNudge entirely and
653
698
  PersistenceNudge on every collection path (sync result, background notifier, `intercom wait`).
654
699
 
@@ -40,20 +40,36 @@ ask for a monitor. Pi runs a small event-producing program and brings the result
40
40
  supervisor is free. Keep the session open, and cancel a watch when its purpose ends. See
41
41
  [time and event wakes](MONITORS.md) for examples and limits.
42
42
 
43
- - **F9** opens the agent tree. Every running row shows its elapsed time and switches to `⚠ stalled
44
- <duration>` once it has gone 90 seconds without progress — the same threshold behind the
45
- supervisor's stall alert. Enter opens a selectable worker's output; `s` sends a course correction;
43
+ - **F9** opens the agent tree. Queued rows have not started their clocks. Live supervisor asks show
44
+ `waiting for supervisor`, not a stall; running rows otherwise show elapsed time and switch to
45
+ `⚠ stalled <duration>` after 90 seconds without progress — a suspicion, not proof of a deadlock.
46
+ Council parent clocks refresh on child engine events; that indicates liveness, not useful work.
47
+ A parent is waiting only when all its live descendant branches are waiting. Enter opens a selectable worker's output; `s` sends a course correction;
46
48
  `x` requests cancellation and appears only when the run can actually be stopped, marking the row
47
49
  `stopping…` at once; a stop that can't be applied says so instead of doing nothing. Escape goes
48
50
  back or closes the panel.
49
51
  - **`/peek`** gives a compact progress view. A quiet worker is a reason to inspect its last
50
52
  progress and current activity, not to launch a duplicate immediately.
51
53
  - **Background results arrive automatically.** A supervisor can continue independent work while
52
- they run. `intercom wait` joins results when the next step depends on them.
54
+ they run. When only background workers remain, end the turn and let completion follow-ups return
55
+ their results; do not monitor or poll healthy workers or automatically join the whole batch.
56
+ `intercom wait` snapshots immediately by default in interactive/RPC sessions; use `sync: true` for
57
+ an intentional bounded join when the next step depends on those results. Headless waits remain
58
+ blocking by default; pass `sync: false` for a snapshot.
53
59
  - **Answer a waiting worker before joining it.** A coaching worker may need a decision from its
54
60
  supervisor before it can finish. An unanswered question is actionable work.
55
61
  - **Steering is a request.** Check the subsequent output to see whether the worker incorporated
56
- it. Check the terminal result after requesting cancellation; changes already made are not undone.
62
+ it. In-process workers can receive guidance mid-run; child-engine workers (including MCP/worktree
63
+ runs) receive it as a queued follow-up. Neither promises to interrupt arbitrary tool work, and
64
+ steering does not preempt an explicitly blocking `intercom wait`. End the supervisor turn rather
65
+ than join merely to idle. Check the terminal result after requesting cancellation; changes already
66
+ made are not undone.
67
+
68
+ Launch cards and targeted Intercom calls show the same worker alias as the live tree. A steering
69
+ receipt previews the message that was actually queued; expand it (`Ctrl+O` by default, or your
70
+ configured key) to read the full message and diagnostic run ID. Aliases are display names, not
71
+ addresses: tools still route by run ID, and duplicate aliases show a secondary ID to distinguish them.
72
+ Saved launch/control receipts keep their display names even after the runtime tracker is gone.
57
73
 
58
74
  A truncated message includes a message id. The supervisor can retrieve its retained body with
59
75
  `intercom { action: "message", messageId: "m1" }`. A worker's final report has a run id instead:
package/docs/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # pi-persona documentation
2
2
 
3
3
  This folder contains the long-form documentation that defines how the project is designed and run.
4
+ It follows the current checkout; consult the [changelog](../CHANGELOG.md) for the release that
5
+ introduced a behavior. An `Unreleased` entry is not yet part of a published release.
4
6
 
5
7
  ## Canonical docs
6
8