pi-delegation-policy 0.23.0 → 0.23.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.23.1 - 2026-10-29
6
+
7
+ ### Fixed
8
+
9
+ - Advisor and ContextShunt reader launches no longer reject later `pi-subagents` releases solely
10
+ because their package version is not on an exact list. Both require a valid stable SemVer version
11
+ `>=0.76.1`, with no upper bound. Prereleases, invalid versions and non-string values are rejected;
12
+ build metadata does not affect precedence.
13
+ - All other launch checks remain unchanged: contract and lifecycle version 3, definition projection
14
+ version 2, packaged profile and shadowing, exact model and thinking, tool and extension lists,
15
+ permission runtime, session identity and terminal digest binding. An incompatible preflight
16
+ still fails closed before a request is sent; a terminal mismatch still discards the reply.
17
+
18
+ ### Compatibility and verification
19
+
20
+ - Pi `0.87.1` remains the package minimum. No dependency, configuration, schema, provider option or
21
+ permission change. Upgrade and reload; no configuration migration is needed.
22
+ - The final loader was exercised against real `pi-subagents` `0.84.0` exports with a synthetic event
23
+ host on Pi `1.4.0`: Advisor fresh/fork and reader fresh completed with terminal binding. This
24
+ checks admission, not real child execution, provider transport or personal permission rules.
25
+ Version labels are not signatures or a guarantee of future compatibility.
26
+
5
27
  ## 0.23.0 - 2026-10-29
6
28
 
7
29
  ### 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.23.0** requires Pi `0.87.1` or later (`>=0.87.1`); it re-applies its marked policy block in the final provider payload.
9
+ > Version **0.23.1** 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.23.0
18
+ pi install npm:pi-delegation-policy@0.23.1
19
19
  # restart Pi, or run /reload
20
20
  ```
21
21
 
@@ -77,10 +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, 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.
80
+ advisor in parallel through the public `pi-subagents` delegation API. It requires a stable SemVer
81
+ version `>=0.76.1`, with no upper bound; prereleases and invalid versions are rejected. Every
82
+ launch must still pass the strict contract and terminal-binding checks. Otherwise it returns
83
+ unavailable text. No model, provider or executor fallback is added.
84
84
 
85
85
  Both modes ask for consultation after orientation before substantive work, when stuck, before changing
86
86
  approach, and before declaring a multi-step task done (ask for remaining risks, not approval). Short
@@ -264,9 +264,11 @@ one bounded line or byte range. Errors, structured results, images, binaries, mi
264
264
  unknown tool contracts stay unchanged, and nothing is launched from a hook. The reader keys
265
265
  `readerEnabled`, `readerRole`, and `answerMaxBytes` control the optional
266
266
  `context_shunt_delegate`/`context_shunt_recover` pair, which needs `enforce`, an active delegation
267
- intensity, a valid configuration, and a compatible external executor. The only verified executor is
268
- `pi-subagents` `0.76.1` on Pi `1.1.0`; Pi `0.87.1`, the declared minimum, is not verified for the
269
- reader. Other executor builds, including `0.69.0`, fail closed with `reader-unavailable`. Since `0.19.0`,
267
+ intensity, a valid configuration, and a compatible external executor. The reader requires stable
268
+ `pi-subagents` SemVer `>=0.76.1`, with no upper bound, and the unchanged strict launch contract.
269
+ Older, prerelease, invalid or contract-incompatible builds fail closed with `reader-unavailable`.
270
+ The reader was verified with `0.76.1` on Pi `1.1.0`; Pi `0.87.1`, the declared minimum, is not
271
+ verified for the reader. Since `0.19.0`,
270
272
  the reader also accepts the exact `@gotgenes/pi-permission-system` `33.0.3` runtime that a host adds for
271
273
  permission rules; the host owns those rules, and the reader never reads or changes them. Delegation
272
274
  `off` suspends the layer.
package/SECURITY.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Scope
4
4
 
5
- This project is a local Pi extension. It stores delegation policy data, model identifiers, and any configured per-role thinking policy in global defaults and session entries; it does not store the thinking level chosen for an individual run. ContextShunt is off by default. When explicitly enforced, it may keep a known successful text result in a private, session-only temporary file to serve bounded recovery; the file has an opaque ID, quota, cancellation check, and an absolute 30-minute TTL from creation. Cleanup is scheduled while the process is active and runs at shutdown, but crashes or OS suspension can delay deletion. It does not store credentials and makes no network request of its own; when one of its explicit tools asks an external executor to answer a bounded question, that executor performs the call. The reader accepts only the verified `pi-subagents` 0.76.1 launch contract; any other build fails closed before a request is sent. From `0.19.0`, the reader also admits the exact `@gotgenes/pi-permission-system` `33.0.3` runtime when the host adds it to the reader's child. The host owns its permission rules; the reader never reads or changes them, and an unverified permission entry fails closed. That runtime is trusted host code, not authority granted to the model. The check is an exact compatibility check, not a support guarantee. Versions `0.18.0` and earlier reject the extra runtime. From `0.20.0`, an enabled Advisor may be launched by the main agent with a forked context while the session fits in half of the Advisor model's window; the host then sends the conversation so far, including file contents and command output, to the Advisor's provider. Turn the Advisor off for sessions that must not reach that provider. The limits and privacy page of the wiki describes the details.
5
+ This project is a local Pi extension. It stores delegation policy data, model identifiers, and any configured per-role thinking policy in global defaults and session entries; it does not store the thinking level chosen for an individual run. ContextShunt is off by default. When explicitly enforced, it may keep a known successful text result in a private, session-only temporary file to serve bounded recovery; the file has an opaque ID, quota, cancellation check, and an absolute 30-minute TTL from creation. Cleanup is scheduled while the process is active and runs at shutdown, but crashes or OS suspension can delay deletion. It does not store credentials and makes no network request of its own; when one of its explicit tools asks an external executor to answer a bounded question, that executor performs the call. The reader requires a stable `pi-subagents` SemVer version `>=0.76.1`, with no upper bound; older versions, prereleases and invalid versions fail closed before a request is sent. Every launch must still pass the strict contract checks; the version floor is not a guarantee of future-build compatibility. From `0.19.0`, the reader also admits the exact `@gotgenes/pi-permission-system` `33.0.3` runtime when the host adds it to the reader's child. The host owns its permission rules; the reader never reads or changes them, and an unverified permission entry fails closed. That runtime is trusted host code, not authority granted to the model. The check is an exact compatibility check, not a support guarantee. Versions `0.18.0` and earlier reject the extra runtime. From `0.20.0`, an enabled Advisor may be launched by the main agent with a forked context while the session fits in half of the Advisor model's window; the host then sends the conversation so far, including file contents and command output, to the Advisor's provider. Turn the Advisor off for sessions that must not reach that provider. The limits and privacy page of the wiki describes the details.
6
6
 
7
7
  ContextShunt is not a sandbox or a worker bridge. It preserves permissions and backends, does not inspect files before tool authorization, and leaves errors, structured/mixed results, images, binaries, invalid inputs, and unknown contracts unchanged. One-time exceptions are user-authorized, short-lived, bound to one call and immutable input snapshot, and capped by declared lines plus real returned UTF-8 bytes. The policy guides the main agent. It cannot guarantee that another system will follow a configured role or thinking choice. Review local configuration before using it.
8
8
 
@@ -15,8 +15,9 @@ 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 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
18
+ The tool requires stable `pi-subagents` SemVer `>=0.76.1`, with no upper bound, rejecting
19
+ prereleases and invalid versions. It retains strict public preflight and terminal binding,
20
+ exact models/thinking, the packaged
20
21
  no-tools profile, replace prompt, no project resources, and the reader's prompt-only or pinned
21
22
  permission-runtime checks. Host rules remain host-owned. Forked conversation is
22
23
  untrusted data, not authority. Preflight binds the tool session identity; the public REQUEST API cannot
@@ -68,4 +69,4 @@ Include the affected version or commit, operating system, Pi version, reproducti
68
69
 
69
70
  ## Supported versions
70
71
 
71
- Only the latest published version is supported. Version `0.23.0` requires Pi `0.87.1` or later; version `0.14.1` requires Pi `0.84.3` or later.
72
+ Only the latest published version is supported. Version `0.23.1` requires Pi `0.87.1` or later; version `0.14.1` requires Pi `0.84.3` or later.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-delegation-policy",
3
- "version": "0.23.0",
3
+ "version": "0.23.1",
4
4
  "private": false,
5
5
  "description": "A Pi extension for configurable delegation intensity and exact subagent role model references.",
6
6
  "type": "module",
@@ -22,13 +22,6 @@ import {
22
22
  ANTHROPIC_ADVISOR_EXTENSION,
23
23
  } from "./advisor-anthropic-provider.ts";
24
24
 
25
- /**
26
- * `pi-subagents` builds whose launch contract was checked against this profile: the original pin and
27
- * the build that only changed its own package version (same contract version, profile projection,
28
- * tool plan, runtime lists and fork wrapper). A different build is rejected before any request.
29
- */
30
- const ADMITTED_SUBAGENTS_VERSIONS: readonly string[] = ["0.76.1", "0.83.1"];
31
-
32
25
  export const ADVISOR_AGENT_NAME = "pi-delegation-policy.advisor";
33
26
  export type AdvisorRequest = AgentLaunchRequest & {
34
27
  question: string;
@@ -46,7 +39,6 @@ const DEFINITION: AgentLaunchDefinition<AdvisorRequest, string> = {
46
39
  agentPath: resolve(
47
40
  fileURLToPath(new URL("../agents/pi-delegation-policy.advisor.md", import.meta.url)),
48
41
  ),
49
- admittedProtocolVersions: ADMITTED_SUBAGENTS_VERSIONS,
50
42
  allowFork: true,
51
43
  internalTools: [],
52
44
  buildTask: (request) =>
@@ -16,6 +16,10 @@ const PACKAGE_MANIFEST_SEARCH_DEPTH = 3;
16
16
  /** `pi-subagents` 0.76.1 `src/api/preflight.ts` and `src/shared/launch-contract.ts`. */
17
17
  const LAUNCH_CONTRACT_VERSION = 3;
18
18
  const DEFINITION_PROJECTION_VERSION = 2;
19
+ const MIN_SUBAGENTS_VERSION = [0n, 76n, 1n] as const;
20
+ // Stable SemVer only: build metadata does not affect precedence; prereleases are not admitted.
21
+ const STABLE_SEMVER =
22
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
19
23
  const SHA256_LOWER_HEX = /^[0-9a-f]{64}$/;
20
24
  const DIAGNOSTIC_SEVERITIES = new Set(["warning", "host-required"]);
21
25
  const DELEGATION_EVENTS = {
@@ -148,12 +152,6 @@ export type AgentLaunchDefinition<Request extends AgentLaunchRequest, Value> = R
148
152
  agentPath: string;
149
153
  /** Only the advisor may send a fork; reader requests remain fresh-only. */
150
154
  allowFork?: boolean;
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[];
157
155
  /**
158
156
  * Builtin tools the child must expose. A profile that declares no tools and no
159
157
  * extensions exposes exactly these, so the contract must report the same list
@@ -204,6 +202,19 @@ function exactStrings(value: unknown, expected: readonly string[]): boolean {
204
202
  );
205
203
  }
206
204
 
205
+ function isSupportedSubagentsVersion(value: unknown): boolean {
206
+ if (typeof value !== "string") return false;
207
+ const match = STABLE_SEMVER.exec(value);
208
+ if (!match || match[0] !== value) return false;
209
+ for (const [index, minimum] of MIN_SUBAGENTS_VERSION.entries()) {
210
+ const digits = match[index + 1];
211
+ if (digits === undefined) return false;
212
+ const component = BigInt(digits);
213
+ if (component !== minimum) return component > minimum;
214
+ }
215
+ return true;
216
+ }
217
+
207
218
  function isLowerHexDigest(value: unknown): value is string {
208
219
  return typeof value === "string" && SHA256_LOWER_HEX.test(value);
209
220
  }
@@ -422,8 +433,7 @@ function validateLaunchContract<Request extends AgentLaunchRequest, Value>(
422
433
  contract.version !== LAUNCH_CONTRACT_VERSION ||
423
434
  !isRecord(contract.protocol) ||
424
435
  contract.protocol.lifecycleArtifactVersion !== 3 ||
425
- typeof contract.protocol.packageVersion !== "string" ||
426
- !definition.admittedProtocolVersions.includes(contract.protocol.packageVersion) ||
436
+ !isSupportedSubagentsVersion(contract.protocol.packageVersion) ||
427
437
  contract.runId !== active.requestId ||
428
438
  !isLowerHexDigest(contract.digest)
429
439
  )
@@ -19,7 +19,6 @@ import type { SourceSnapshot } from "./context-shunt.ts";
19
19
  import type { ReaderAnswer, ReaderThinking } from "./context-shunt-reader.ts";
20
20
 
21
21
  export const CONTEXT_SHUNT_READER_AGENT_NAME = "pi-delegation-policy.context-shunt-inline-reader";
22
- export const CONTEXT_SHUNT_READER_PROTOCOL_VERSION = "0.76.1";
23
22
  export const READER_PREFLIGHT_TIMEOUT_MS = LAUNCH_PREFLIGHT_TIMEOUT_MS;
24
23
  export const READER_TERMINAL_TIMEOUT_MS = LAUNCH_TERMINAL_TIMEOUT_MS;
25
24
 
@@ -109,7 +108,6 @@ function isReaderAnswer(value: unknown): value is ReaderAnswer {
109
108
  const READER_LAUNCH = {
110
109
  agentName: CONTEXT_SHUNT_READER_AGENT_NAME,
111
110
  agentPath: CONTEXT_SHUNT_READER_AGENT_PATH,
112
- admittedProtocolVersions: [CONTEXT_SHUNT_READER_PROTOCOL_VERSION],
113
111
  internalTools: ["structured_output"],
114
112
  buildTask: buildReaderTask,
115
113
  result: {