pi-delegation-policy 0.22.0 → 0.22.2
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.
- package/CHANGELOG.md +33 -0
- package/README.md +10 -4
- package/SECURITY.md +5 -4
- package/package.json +1 -1
- package/src/advisor-executor.ts +15 -8
- package/src/agent-launch.ts +8 -2
- package/src/context-shunt-executor.ts +1 -1
- package/src/index.ts +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.22.2 - 2026-10-28
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- The Advisor no longer rejects a verified `pi-subagents` build. Each launch definition now declares
|
|
8
|
+
the exact list of package versions whose launch contract it was checked against: the Advisor admits
|
|
9
|
+
`0.76.1` and `0.83.1`, while the ContextShunt reader keeps its single verified `0.76.1`, so the
|
|
10
|
+
reader limit does not widen. Everything else in the launch check is unchanged: exact profile
|
|
11
|
+
projection and digest shape, exact model and thinking, host session binding, empty tools and
|
|
12
|
+
extensions, the pinned `@gotgenes/pi-permission-system` `33.0.3` runtime, and the terminal digest
|
|
13
|
+
binding. A build outside the list still fails closed before any request is sent.
|
|
14
|
+
|
|
15
|
+
The two contracts were compared from their real preflight payloads: they differ only in the package
|
|
16
|
+
version, the install path of the runtime extension and the digests derived from that path, and the
|
|
17
|
+
public fork wrapper is byte-identical. Admission and terminal binding were exercised in an isolated
|
|
18
|
+
host that answered with each contract's own digest. That does not cover provider transport, real
|
|
19
|
+
child execution or a real consultation, which remain unverified, and it does not explain the
|
|
20
|
+
Advisor failure reported on a forked session or the menu/status discrepancy; both stay open.
|
|
21
|
+
|
|
22
|
+
## 0.22.1 - 2026-10-22
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- The footer no longer keeps a stale `D:ERR` from session start when an ordinary model becomes
|
|
27
|
+
available only after this extension's `session_start` handler. Another extension may fill the model
|
|
28
|
+
catalog in its own start handler, and the host then emits `resources_discover`; a read-only runtime
|
|
29
|
+
refresh there repaints the footer with the existing validation. This adds one configuration/branch
|
|
30
|
+
read and footer refresh per session bind or reload, returns no resource paths, makes no network
|
|
31
|
+
call, and leaves the configuration-change notice reference alone, so a pending change is not lost.
|
|
32
|
+
A model that is genuinely missing or unusable still reports `D:ERR`. The fix relies on the public
|
|
33
|
+
post-start discovery order, verified in Pi `0.87.1` and `1.1.0`; availability changes after that
|
|
34
|
+
event still refresh on the next request or menu action.
|
|
35
|
+
|
|
3
36
|
## 0.22.0 - 2026-10-21
|
|
4
37
|
|
|
5
38
|
### Added
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ general subagent runner. Only explicit tools can request reader work or Advisor
|
|
|
6
6
|
the authorized host executor; hooks never launch children.
|
|
7
7
|
|
|
8
8
|
> **Docs:** [yivas.github.io/pi-delegation-policy](https://yivas.github.io/pi-delegation-policy/).
|
|
9
|
-
> Version **0.22.
|
|
9
|
+
> Version **0.22.2** requires Pi `0.87.1` or later (`>=0.87.1`); it re-applies its marked policy block in the final provider payload.
|
|
10
10
|
> Version `0.14.1` supports Pi `0.84.3` or later (`>=0.84.3`).
|
|
11
11
|
>
|
|
12
12
|
> Independent Advisor mode and its companion file are available from version `0.17.0`.
|
|
@@ -15,7 +15,7 @@ the authorized host executor; hooks never launch children.
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
pi install npm:pi-delegation-policy@0.22.
|
|
18
|
+
pi install npm:pi-delegation-policy@0.22.2
|
|
19
19
|
# restart Pi, or run /reload
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -77,8 +77,10 @@ same question. Weigh disagreements; agreement is not proof. The packaged no-tool
|
|
|
77
77
|
- `role`: the main agent launches every valid advisor in one background subagent call, with exact
|
|
78
78
|
models and thinking. The extension observes matching attempts but does not launch them.
|
|
79
79
|
- `tool`: the always-registered `consult_advisor({ question, brief? })` launches one child per valid
|
|
80
|
-
advisor in parallel through the public `pi-subagents` delegation API,
|
|
81
|
-
|
|
80
|
+
advisor in parallel through the public `pi-subagents` delegation API, admitted only for the exact
|
|
81
|
+
builds whose launch contract was verified (`0.76.1` and `0.83.1`). Any other build fails closed
|
|
82
|
+
before a request is sent. Otherwise it returns unavailable text. No model, provider or executor
|
|
83
|
+
fallback is added.
|
|
82
84
|
|
|
83
85
|
Both modes ask for consultation after orientation before substantive work, when stuck, before changing
|
|
84
86
|
approach, and before declaring a multi-step task done (ask for remaining risks, not approval). Short
|
|
@@ -190,6 +192,10 @@ example `advisor-mode=with-delegation (global); A:OFF` and `thinking-advisor=uns
|
|
|
190
192
|
`D:OFF`, `D:NORM`, `D:AGG`, and `D:ORCH` describe delegation; `A:OFF`, `A:ON`, `A:PART`, and `A:ERR` describe
|
|
191
193
|
Advisor. None of them proves that a launch happened or that another system followed the guidance.
|
|
192
194
|
|
|
195
|
+
The footer also revalidates after all session-start handlers finish. If another extension makes a
|
|
196
|
+
configured model available later in startup, the earlier `D:ERR` is replaced with the current status
|
|
197
|
+
without waiting for a message or menu action. A model that remains invalid still reports `D:ERR`.
|
|
198
|
+
|
|
193
199
|
### Configuration change notice
|
|
194
200
|
|
|
195
201
|
Available from `0.22.0`. The declared Pi peer remains
|
package/SECURITY.md
CHANGED
|
@@ -15,9 +15,10 @@ mode with an enabled valid advisor, never from hooks. Model input cannot choose
|
|
|
15
15
|
path, tools or extensions. Fork sends the conversation to each advisor provider; fresh sends the
|
|
16
16
|
question and brief. Disable Advisor when session content must not reach those providers.
|
|
17
17
|
|
|
18
|
-
The tool reuses strict public preflight and terminal binding
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
The tool reuses strict public preflight and terminal binding admitted only for the exact `pi-subagents`
|
|
19
|
+
builds whose contract was verified (`0.76.1` and `0.83.1`), exact models/thinking, the packaged
|
|
20
|
+
no-tools profile, replace prompt, no project resources, and the reader's prompt-only or pinned
|
|
21
|
+
permission-runtime checks. Host rules remain host-owned. Forked conversation is
|
|
21
22
|
untrusted data, not authority. Preflight binds the tool session identity; the public REQUEST API cannot
|
|
22
23
|
prove that the live executor session is the same. Terminal mismatch rejection happens only after
|
|
23
24
|
context exposure. The executor/runtime is trusted host code; digests are not signatures or a sandbox.
|
|
@@ -52,4 +53,4 @@ Include the affected version or commit, operating system, Pi version, reproducti
|
|
|
52
53
|
|
|
53
54
|
## Supported versions
|
|
54
55
|
|
|
55
|
-
Only the latest published version is supported. Version `0.
|
|
56
|
+
Only the latest published version is supported. Version `0.22.2` requires Pi `0.87.1` or later; version `0.14.1` requires Pi `0.84.3` or later.
|
package/package.json
CHANGED
package/src/advisor-executor.ts
CHANGED
|
@@ -18,6 +18,13 @@ import type { AdvisorContext } from "./prompt.ts";
|
|
|
18
18
|
import type { AdvisorSetting, ThinkingLevelName } from "./types.ts";
|
|
19
19
|
import type { ConsultationAttempt } from "./advisor-log.ts";
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* `pi-subagents` builds whose launch contract was checked against this profile: the original pin and
|
|
23
|
+
* the build that only changed its own package version (same contract version, profile projection,
|
|
24
|
+
* tool plan, runtime lists and fork wrapper). A different build is rejected before any request.
|
|
25
|
+
*/
|
|
26
|
+
const ADMITTED_SUBAGENTS_VERSIONS: readonly string[] = ["0.76.1", "0.83.1"];
|
|
27
|
+
|
|
21
28
|
export const ADVISOR_AGENT_NAME = "pi-delegation-policy.advisor";
|
|
22
29
|
export type AdvisorRequest = AgentLaunchRequest & {
|
|
23
30
|
question: string;
|
|
@@ -34,7 +41,7 @@ const DEFINITION: AgentLaunchDefinition<AdvisorRequest, string> = {
|
|
|
34
41
|
agentPath: resolve(
|
|
35
42
|
fileURLToPath(new URL("../agents/pi-delegation-policy.advisor.md", import.meta.url)),
|
|
36
43
|
),
|
|
37
|
-
|
|
44
|
+
admittedProtocolVersions: ADMITTED_SUBAGENTS_VERSIONS,
|
|
38
45
|
allowFork: true,
|
|
39
46
|
internalTools: [],
|
|
40
47
|
buildTask: (request) =>
|
|
@@ -84,9 +91,9 @@ function hostStatusText(status: AgentLaunchTerminalStatus | undefined): string {
|
|
|
84
91
|
case "tool_budget_exhausted":
|
|
85
92
|
return "The host ended the Advisor run at its tool limit before answering. Retry once with a narrower question.";
|
|
86
93
|
case "structured_output_failed":
|
|
87
|
-
return "The host ended the Advisor run while collecting its structured result. Retry once; if it repeats, inspect host diagnostics and check
|
|
94
|
+
return "The host ended the Advisor run while collecting its structured result. Retry once; if it repeats, inspect host diagnostics and check that the installed pi-delegation-policy and pi-subagents builds are compatible.";
|
|
88
95
|
case "acceptance_failed":
|
|
89
|
-
return "The host ended the Advisor run at its acceptance check. Retry once; if it repeats, inspect host diagnostics and check
|
|
96
|
+
return "The host ended the Advisor run at its acceptance check. Retry once; if it repeats, inspect host diagnostics and check that the installed pi-delegation-policy and pi-subagents builds are compatible.";
|
|
90
97
|
case "failed":
|
|
91
98
|
return "The host ended the Advisor run with status failed and supplied no safe detail. Retry once; if it repeats, check the installed pi-subagents version.";
|
|
92
99
|
default:
|
|
@@ -98,11 +105,11 @@ function unavailableFailureText(reason: AgentLaunchFailure | undefined): string
|
|
|
98
105
|
const preflightSeconds = LAUNCH_PREFLIGHT_TIMEOUT_MS / 1000;
|
|
99
106
|
switch (reason?.code) {
|
|
100
107
|
case "fork-task-normalizer-unavailable":
|
|
101
|
-
return "Fork launch is unavailable: the installed pi-subagents does not export wrapForkTask, so a fork task cannot be bound to the child. Retrying or supplying a brief will not switch this session to fresh; install
|
|
108
|
+
return "Fork launch is unavailable: the installed pi-subagents does not export wrapForkTask, so a fork task cannot be bound to the child. Retrying or supplying a brief will not switch this session to fresh; install an admitted pi-subagents build and reload the session.";
|
|
102
109
|
case "modules-unavailable":
|
|
103
|
-
return "Advisor launch is unavailable: the pi-subagents
|
|
110
|
+
return "Advisor launch is unavailable: the pi-subagents exports this extension requires were not found. Install an admitted pi-subagents build, then reload the session.";
|
|
104
111
|
case "preflight-unavailable":
|
|
105
|
-
return "Advisor preflight returned no launch contract. Retry once; if it repeats, check the
|
|
112
|
+
return "Advisor preflight returned no launch contract. Retry once; if it repeats, check the installed pi-subagents build and the packaged Advisor profile.";
|
|
106
113
|
case "preflight-timeout":
|
|
107
114
|
return `Advisor preflight did not finish within ${preflightSeconds} seconds. Retry once; if it repeats, check the installed pi-subagents version.`;
|
|
108
115
|
case "contract-rejected":
|
|
@@ -110,7 +117,7 @@ function unavailableFailureText(reason: AgentLaunchFailure | undefined): string
|
|
|
110
117
|
case "request-start-timeout":
|
|
111
118
|
return `The host did not start the Advisor within ${preflightSeconds} seconds. Retry once; if it repeats, check the installed pi-subagents version.`;
|
|
112
119
|
case "request-emit-failed":
|
|
113
|
-
return "The host could not set up or send the Advisor launch event. Reload the session, then retry; if it repeats, check the installed extension against
|
|
120
|
+
return "The host could not set up or send the Advisor launch event. Reload the session, then retry; if it repeats, check the installed extension against an admitted pi-subagents build.";
|
|
114
121
|
case "host-session-missing":
|
|
115
122
|
return "Advisor unavailable: the host supplied no session identity.";
|
|
116
123
|
case "fork-not-allowed":
|
|
@@ -131,7 +138,7 @@ function failedFailureText(reason: AgentLaunchFailure | undefined): string {
|
|
|
131
138
|
case "terminal-metadata-mismatch":
|
|
132
139
|
return `The host returned an Advisor reply whose ${terminalFieldText(reason.field)} did not match the preflight contract, so the reply was discarded. Retry once; if it repeats, report the mismatch.`;
|
|
133
140
|
case "terminal-result-invalid":
|
|
134
|
-
return "The host reported completion without a usable text answer, so the result was discarded. Retry once; if it repeats, inspect host diagnostics and check the compatibility of the extension with the installed pi-subagents
|
|
141
|
+
return "The host reported completion without a usable text answer, so the result was discarded. Retry once; if it repeats, inspect host diagnostics and check the compatibility of the extension with the installed pi-subagents build.";
|
|
135
142
|
case "host-terminal-status":
|
|
136
143
|
return hostStatusText(reason.status);
|
|
137
144
|
case "host-status-unrecognized":
|
package/src/agent-launch.ts
CHANGED
|
@@ -148,7 +148,12 @@ export type AgentLaunchDefinition<Request extends AgentLaunchRequest, Value> = R
|
|
|
148
148
|
agentPath: string;
|
|
149
149
|
/** Only the advisor may send a fork; reader requests remain fresh-only. */
|
|
150
150
|
allowFork?: boolean;
|
|
151
|
-
|
|
151
|
+
/**
|
|
152
|
+
* The `pi-subagents` package versions whose launch contract this profile was verified against.
|
|
153
|
+
* An exact, per-profile list: no range, wildcard or fallback, so a new build is rejected until
|
|
154
|
+
* its contract is checked.
|
|
155
|
+
*/
|
|
156
|
+
admittedProtocolVersions: readonly string[];
|
|
152
157
|
/**
|
|
153
158
|
* Builtin tools the child must expose. A profile that declares no tools and no
|
|
154
159
|
* extensions exposes exactly these, so the contract must report the same list
|
|
@@ -415,7 +420,8 @@ function validateLaunchContract<Request extends AgentLaunchRequest, Value>(
|
|
|
415
420
|
contract.version !== LAUNCH_CONTRACT_VERSION ||
|
|
416
421
|
!isRecord(contract.protocol) ||
|
|
417
422
|
contract.protocol.lifecycleArtifactVersion !== 3 ||
|
|
418
|
-
contract.protocol.packageVersion !==
|
|
423
|
+
typeof contract.protocol.packageVersion !== "string" ||
|
|
424
|
+
!definition.admittedProtocolVersions.includes(contract.protocol.packageVersion) ||
|
|
419
425
|
contract.runId !== active.requestId ||
|
|
420
426
|
!isLowerHexDigest(contract.digest)
|
|
421
427
|
)
|
|
@@ -109,7 +109,7 @@ function isReaderAnswer(value: unknown): value is ReaderAnswer {
|
|
|
109
109
|
const READER_LAUNCH = {
|
|
110
110
|
agentName: CONTEXT_SHUNT_READER_AGENT_NAME,
|
|
111
111
|
agentPath: CONTEXT_SHUNT_READER_AGENT_PATH,
|
|
112
|
-
|
|
112
|
+
admittedProtocolVersions: [CONTEXT_SHUNT_READER_PROTOCOL_VERSION],
|
|
113
113
|
internalTools: ["structured_output"],
|
|
114
114
|
buildTask: buildReaderTask,
|
|
115
115
|
result: {
|
package/src/index.ts
CHANGED
|
@@ -896,6 +896,14 @@ export function createPiDelegationPolicy(options: PiDelegationPolicyOptions = {}
|
|
|
896
896
|
advisorContext = undefined;
|
|
897
897
|
startConfigBaseline(await refreshRuntime(ctx));
|
|
898
898
|
});
|
|
899
|
+
// The host emits this after every `session_start` handler has run, so a model catalog another
|
|
900
|
+
// extension fills during its own start handler is visible here and the footer stops reporting an
|
|
901
|
+
// error that no longer applies. It only re-reads the runtime and repaints: no resource paths, no
|
|
902
|
+
// network, no new validation rules, and the notice reference stays as the start left it, so a pending
|
|
903
|
+
// change is not lost.
|
|
904
|
+
pi.on("resources_discover", async (_event, ctx) => {
|
|
905
|
+
await refreshRuntime(ctx);
|
|
906
|
+
});
|
|
899
907
|
pi.on("input", async (event) => {
|
|
900
908
|
// The host emits this for every submitted input immediately before the prompt it belongs to,
|
|
901
909
|
// and `before_agent_start` follows only for a fresh prompt. Attribution therefore depends on
|