pi-delegation-policy 0.6.0 → 0.8.0

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,19 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.8.0 - 2026-09-07
6
+
7
+ ### Changed
8
+
9
+ - Tighten `orchestrator` guidance to require delegation before all transferable execution, including detailed review and integration mechanics; require waiting for and consuming pending results, concrete gap-only reinspection, and a brief exception before minimum direct work. Size, triviality, convenience, economics, transfer cost, and final-review or integration labels are not bypasses. The published `0.7.0` policy remains unchanged.
10
+
11
+ ## 0.7.0 - 2026-09-06
12
+
13
+ ### Added
14
+
15
+ - Add the `orchestrator` intensity with `/delegate orchestrator` and `D:ORCH`. It delegates transferable research, detailed planning, implementation, testing, writing, review, and integration mechanics while keeping objectives, critical decisions, coordination, evidence, and final acceptance with the main agent.
16
+ - Add orchestrator guidance for batching small work, concise briefs and results with file references, and avoiding duplicate inspection without a concrete gap or risk.
17
+
5
18
  ## 0.6.0 - 2026-08-29
6
19
 
7
20
  ### Added
package/README.md CHANGED
@@ -2,24 +2,24 @@
2
2
 
3
3
  A local Pi extension that helps the main agent decide **when delegation is worth it** and which exact models to use for Small, Medium, Large, and optional Visual Design. It provides guidance; it is not a subagent runner.
4
4
 
5
- > **Status:** Version **0.6.0** is the latest published package. The package requires Pi `>=0.84.3`; Pi `0.84.3` is the explicitly checked baseline.
5
+ > **Status:** Version **0.8.0** is the latest published package and supports `off`, `normal`, `aggressive`, and `orchestrator`. The package requires Pi `>=0.84.3`; Pi `0.84.3` is the explicitly checked baseline.
6
6
  >
7
7
  > **Docs:** [Read the documentation site](https://yivas.github.io/pi-delegation-policy/).
8
8
 
9
9
  ## Value and boundary
10
10
 
11
- - Choose `off`, `normal`, or `aggressive` globally or for the current session branch.
11
+ - Choose `off`, `normal`, `aggressive`, or `orchestrator` globally or for the current session branch.
12
12
  - Configure an exact provider/model reference or explicitly disable each ordinary role.
13
13
  - Keep global defaults and session-branch overrides across reload, resume, and tree navigation.
14
14
  - Validate active configurations before injecting one policy block through Pi's public `before_agent_start` event.
15
15
 
16
- The extension guides the main agent. It never creates, launches, routes, supervises, or blocks subagents; changes Pi's main model or thinking; stores credentials; intercepts tools; or makes its own network requests. It has no model fallback, telemetry, project configuration, presets, or external skill loading.
16
+ The extension guides the main agent. It never creates, launches, routes, supervises, or blocks subagents; changes Pi's main model or thinking; stores credentials; intercepts tools; or makes its own network requests. In `0.8.0` `orchestrator`, an enabled capable role and authorized launcher require delegation of all transferable execution before it begins, regardless of size: small lookups, code reading, detailed planning, edits, tests, writing, detailed review, and integration mechanics. Bootstrap is limited to mandatory instructions, tool discovery, and a narrow assignment scope; after assigning, the main agent coordinates only disjoint work, waits through the host, and consumes results before dependencies or finalizing. It retains strategy, critical user decisions, coordination, safety, evidence evaluation, final acceptance, and concise synthesis, not permission to perform transferable review or integration. Direct work requires a briefly stated concrete exception: genuinely non-transferable work, no enabled capable role, a confirmed unavailable authorized launcher, or an explicit user or higher-priority requirement. It reinspects only a concrete gap, risk, or contradiction and delegates transferable fixes or rechecks. A final-review or integration label, size, triviality, convenience, economics, transfer cost, or familiarity never justifies doing the whole task personally. Published `0.7.0` retains its original policy; `0.8.0` contains this stricter guidance. It has no model fallback, telemetry, project configuration, presets, or external skill loading.
17
17
 
18
18
  A valid active policy requires an explicit decision for Small, Medium, and Large: an exact model reference or disabled. At least one ordinary role must remain enabled. A disabled role is not validated. An absent role, an invalid enabled reference, or no enabled ordinary role produces `D:ERR` and injects no policy. `off` always produces `D:OFF` without injection.
19
19
 
20
20
  The policy considers only enabled ordinary roles, chooses the least costly role that can satisfy the task's acceptance criteria and evidence, and keeps work with the main agent when none can. It never invents a model or role. `efficient` and `intensive` are tie-breaks only when both Small and Medium are enabled; otherwise their bias is inactive.
21
21
 
22
- Visual Design is an independent optional specialist for direction, assets, bounded presentation-layer implementation, and visual review. Use it only when behavior and data contracts are already defined and unchanged, the affected surface is bounded, and visual quality or user experience is the primary acceptance criterion. It does not count as an ordinary role or replace one. Route business logic, data, APIs, routes, application architecture, tooling, interaction behavior, and cross-system integration to an enabled ordinary role by task fit. The main agent retains final integration and acceptance.
22
+ Visual Design is an independent optional specialist for direction, assets, bounded presentation-layer implementation, and visual review. Use it only when behavior and data contracts are already defined and unchanged, the affected surface is bounded, and visual quality or user experience is the primary acceptance criterion. It does not count as an ordinary role or replace one. In published `0.7.0` and `normal` or `aggressive`, route business logic, data, APIs, routes, application architecture, tooling, interaction behavior, and cross-system integration to an enabled ordinary role by task fit; the main agent retains final integration and acceptance. In `0.8.0` `orchestrator`, the main agent instead retains integration responsibility, coordination, and final acceptance while a capable ordinary role performs transferable integration mechanics and detailed review unless a named direct-work exception applies.
23
23
 
24
24
  ## Install and start
25
25
 
@@ -30,11 +30,13 @@ pi install npm:pi-delegation-policy
30
30
 
31
31
  1. Open `/delegate` (or press `Alt+G` in Pi's TUI).
32
32
  2. For Small, Medium, and Large, select an exact authenticated provider/model or **Disable for this session**. Keep at least one enabled.
33
- 3. Select `normal` or `aggressive`, then choose **Apply changes**.
33
+ 3. Select `normal`, `aggressive`, or `orchestrator`, then choose **Apply changes**.
34
34
  4. Run `/delegate status`. `disabled`, `not configured`, and exact references remain distinct. `D:ERR` means no policy is injected.
35
35
  5. The applied state affects the **next** agent run.
36
36
 
37
- Global defaults are stored at `~/.pi/agent/delegation-policy.json` and use schema version 3. Schema 2 defaults and session entries are read and normalized in memory; they are not rewritten on read. Schema 3 stores `null` for an explicitly disabled ordinary role. Session changes write a schema 2 `off` guard before the schema 3 state so older versions restore off. Saving global defaults is global-only: before downgrading after that action or manually writing schema 3, run `/delegate off` in every active branch, restore schema 2 references manually, then install the older package.
37
+ Global defaults are stored at `~/.pi/agent/delegation-policy.json` and use schema version 3. Schema 2 defaults and session entries are read and normalized in memory without rewriting them. Schema 3 stores `null` for an explicitly disabled ordinary role. Session changes write a schema 2 `off` guard before the schema 3 state; saving defaults changes only the global file.
38
+
39
+ Before downgrading to `0.6.0`, change the global intensity to `off`, `normal`, or `aggressive` and run `/delegate off` in every active branch. For `<=0.5.0`, also convert global defaults to schema 2 and replace ordinary `null` values with exact model references. Schema 2 never accepts `orchestrator`. See the configuration reference for details.
38
40
 
39
41
  See the [getting-started guide](https://yivas.github.io/pi-delegation-policy/getting-started/) and [configuration reference](https://yivas.github.io/pi-delegation-policy/configuration/).
40
42
 
@@ -45,6 +47,7 @@ See the [getting-started guide](https://yivas.github.io/pi-delegation-policy/get
45
47
  /delegate off Disable policy for this session branch
46
48
  /delegate normal Enable balanced delegation guidance
47
49
  /delegate aggressive Enable delegation-first guidance
50
+ /delegate orchestrator Minimize main-agent execution and narration
48
51
  /delegate status Show effective session state
49
52
  /delegate reset Reset this branch to off and other fields to global defaults
50
53
  ```
package/SECURITY.md CHANGED
@@ -14,4 +14,4 @@ Include the affected version or commit, operating system, Pi version, reproducti
14
14
 
15
15
  ## Supported versions
16
16
 
17
- Only the latest published version is supported. Version 0.6.0 is the current supported release.
17
+ Only the latest published version is supported. Version 0.8.0 is the current supported release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-delegation-policy",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "private": false,
5
5
  "description": "A Pi extension for configurable delegation intensity and exact subagent role model references.",
6
6
  "type": "module",
@@ -44,10 +44,10 @@
44
44
  "@earendil-works/pi-ai": "0.84.3",
45
45
  "@earendil-works/pi-coding-agent": "0.84.3",
46
46
  "@earendil-works/pi-tui": "0.84.3",
47
- "@eslint/js": "^9.39.5",
48
- "@types/node": "^22.0.0",
47
+ "@eslint/js": "^10.0.1",
48
+ "@types/node": "^26.2.0",
49
49
  "ajv": "^8.20.0",
50
- "eslint": "^9.0.0",
50
+ "eslint": "^10.9.1",
51
51
  "prettier": "^3.0.0",
52
52
  "typescript": "^5.7.0",
53
53
  "typescript-eslint": "^8.68.0"
@@ -6,7 +6,7 @@
6
6
  "required": ["schemaVersion"],
7
7
  "properties": {
8
8
  "schemaVersion": { "const": 3 },
9
- "intensity": { "enum": ["off", "normal", "aggressive"] },
9
+ "intensity": { "enum": ["off", "normal", "aggressive", "orchestrator"] },
10
10
  "preference": { "enum": ["efficient", "standard", "intensive"] },
11
11
  "small": { "$ref": "#/$defs/ordinaryRole" },
12
12
  "medium": { "$ref": "#/$defs/ordinaryRole" },
package/src/config.ts CHANGED
@@ -3,6 +3,7 @@ import { homedir } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
4
  import {
5
5
  CURRENT_SCHEMA_VERSION,
6
+ INTENSITIES,
6
7
  emptyGlobalDefaults,
7
8
  emptySessionState,
8
9
  type EffectiveDelegateState,
@@ -56,7 +57,7 @@ export type GuardedAppendResult = "success" | "guard-failed" | "state-failed";
56
57
 
57
58
  type Schema2GlobalDefaults = {
58
59
  schemaVersion: 2;
59
- intensity?: Intensity;
60
+ intensity?: LegacyIntensity;
60
61
  preference?: Preference;
61
62
  small?: ModelRef;
62
63
  medium?: ModelRef;
@@ -75,7 +76,14 @@ function hasOnlyKeys(value: Record<string, unknown>, allowedKeys: readonly strin
75
76
  }
76
77
 
77
78
  function isIntensity(value: unknown): value is Intensity {
78
- return value === "off" || value === "normal" || value === "aggressive";
79
+ return INTENSITIES.some((intensity) => intensity === value);
80
+ }
81
+
82
+ const LEGACY_INTENSITIES = ["off", "normal", "aggressive"] as const;
83
+ type LegacyIntensity = (typeof LEGACY_INTENSITIES)[number];
84
+
85
+ function isLegacyIntensity(value: unknown): value is LegacyIntensity {
86
+ return LEGACY_INTENSITIES.some((intensity) => intensity === value);
79
87
  }
80
88
 
81
89
  function isPreference(value: unknown): value is Preference {
@@ -99,12 +107,16 @@ function copyRoleSetting(value: OrdinaryRoleSetting | undefined): OrdinaryRoleSe
99
107
  return value === null ? null : value ? { ...value } : undefined;
100
108
  }
101
109
 
102
- function hasValidEnvelope(value: unknown, schemaVersion: 2 | 3): value is Record<string, unknown> {
110
+ function hasValidEnvelope(
111
+ value: unknown,
112
+ schemaVersion: 2 | 3,
113
+ intensityValidator: (value: unknown) => boolean = isIntensity,
114
+ ): value is Record<string, unknown> {
103
115
  return (
104
116
  isRecord(value) &&
105
117
  hasOnlyKeys(value, CONFIG_KEYS) &&
106
118
  value.schemaVersion === schemaVersion &&
107
- (value.intensity === undefined || isIntensity(value.intensity)) &&
119
+ (value.intensity === undefined || intensityValidator(value.intensity)) &&
108
120
  (value.preference === undefined || isPreference(value.preference))
109
121
  );
110
122
  }
@@ -132,12 +144,14 @@ function parseSchema2Roles(
132
144
  }
133
145
 
134
146
  export function parseSchema2Config(value: unknown): Schema2GlobalDefaults | undefined {
135
- if (!hasValidEnvelope(value, 2)) return undefined;
147
+ if (!hasValidEnvelope(value, 2, isLegacyIntensity)) return undefined;
148
+ const intensity = value.intensity;
149
+ if (intensity !== undefined && !isLegacyIntensity(intensity)) return undefined;
136
150
  const roles = parseSchema2Roles(value);
137
151
  if (!roles) return undefined;
138
152
  return {
139
153
  schemaVersion: 2,
140
- ...(value.intensity ? { intensity: value.intensity as Intensity } : {}),
154
+ ...(intensity ? { intensity } : {}),
141
155
  ...(value.preference ? { preference: value.preference as Preference } : {}),
142
156
  ...roles,
143
157
  };
@@ -145,6 +159,8 @@ export function parseSchema2Config(value: unknown): Schema2GlobalDefaults | unde
145
159
 
146
160
  export function parseSchema3Config(value: unknown): GlobalDefaults | undefined {
147
161
  if (!hasValidEnvelope(value, CURRENT_SCHEMA_VERSION)) return undefined;
162
+ const intensity = value.intensity;
163
+ if (intensity !== undefined && !isIntensity(intensity)) return undefined;
148
164
  const parseOrdinary = (setting: unknown): OrdinaryRoleSetting | undefined =>
149
165
  setting === null ? null : parseModelRef(setting);
150
166
  const small = value.small === undefined ? undefined : parseOrdinary(value.small);
@@ -160,7 +176,7 @@ export function parseSchema3Config(value: unknown): GlobalDefaults | undefined {
160
176
  return undefined;
161
177
  return {
162
178
  schemaVersion: CURRENT_SCHEMA_VERSION,
163
- ...(value.intensity ? { intensity: value.intensity as Intensity } : {}),
179
+ ...(intensity ? { intensity } : {}),
164
180
  ...(value.preference ? { preference: value.preference as Preference } : {}),
165
181
  ...(small !== undefined ? { small } : {}),
166
182
  ...(medium !== undefined ? { medium } : {}),
@@ -172,7 +188,7 @@ export function parseSchema3Config(value: unknown): GlobalDefaults | undefined {
172
188
  function migrateSchema2Config(value: Schema2GlobalDefaults): GlobalDefaults {
173
189
  return {
174
190
  schemaVersion: CURRENT_SCHEMA_VERSION,
175
- ...(value.intensity ? { intensity: value.intensity as Intensity } : {}),
191
+ ...(value.intensity ? { intensity: value.intensity } : {}),
176
192
  ...(value.preference ? { preference: value.preference as Preference } : {}),
177
193
  ...(value.small ? { small: { ...value.small } } : {}),
178
194
  ...(value.medium ? { medium: { ...value.medium } } : {}),
@@ -192,7 +208,9 @@ export function parseConfig(value: unknown): GlobalDefaults | undefined {
192
208
  }
193
209
 
194
210
  function parseSchema2SessionState(value: unknown): Schema2SessionState | undefined {
195
- if (!hasValidEnvelope(value, 2)) return undefined;
211
+ if (!hasValidEnvelope(value, 2, isLegacyIntensity)) return undefined;
212
+ const intensity = value.intensity;
213
+ if (intensity !== undefined && !isLegacyIntensity(intensity)) return undefined;
196
214
  const uiDesign =
197
215
  value.uiDesign === undefined || value.uiDesign === null
198
216
  ? value.uiDesign
@@ -202,7 +220,7 @@ function parseSchema2SessionState(value: unknown): Schema2SessionState | undefin
202
220
  return undefined;
203
221
  return {
204
222
  schemaVersion: 2,
205
- ...(value.intensity ? { intensity: value.intensity as Intensity } : {}),
223
+ ...(intensity ? { intensity } : {}),
206
224
  ...(value.preference ? { preference: value.preference as Preference } : {}),
207
225
  ...roles,
208
226
  ...(uiDesign === null ? { uiDesign: null } : uiDesign ? { uiDesign } : {}),
@@ -211,6 +229,8 @@ function parseSchema2SessionState(value: unknown): Schema2SessionState | undefin
211
229
 
212
230
  function parseSchema3SessionState(value: unknown): SessionDelegateState | undefined {
213
231
  if (!hasValidEnvelope(value, CURRENT_SCHEMA_VERSION)) return undefined;
232
+ const intensity = value.intensity;
233
+ if (intensity !== undefined && !isIntensity(intensity)) return undefined;
214
234
  const parseOrdinary = (setting: unknown): OrdinaryRoleSetting | undefined =>
215
235
  setting === null ? null : parseModelRef(setting);
216
236
  const small = value.small === undefined ? undefined : parseOrdinary(value.small);
@@ -229,7 +249,7 @@ function parseSchema3SessionState(value: unknown): SessionDelegateState | undefi
229
249
  return undefined;
230
250
  return {
231
251
  schemaVersion: CURRENT_SCHEMA_VERSION,
232
- ...(value.intensity ? { intensity: value.intensity as Intensity } : {}),
252
+ ...(intensity ? { intensity } : {}),
233
253
  ...(value.preference ? { preference: value.preference as Preference } : {}),
234
254
  ...(small !== undefined ? { small } : {}),
235
255
  ...(medium !== undefined ? { medium } : {}),
@@ -241,7 +261,7 @@ function parseSchema3SessionState(value: unknown): SessionDelegateState | undefi
241
261
  function migrateSchema2SessionState(value: Schema2SessionState): SessionDelegateState {
242
262
  return {
243
263
  schemaVersion: CURRENT_SCHEMA_VERSION,
244
- ...(value.intensity ? { intensity: value.intensity as Intensity } : {}),
264
+ ...(value.intensity ? { intensity: value.intensity } : {}),
245
265
  ...(value.preference ? { preference: value.preference as Preference } : {}),
246
266
  ...(value.small ? { small: { ...value.small } } : {}),
247
267
  ...(value.medium ? { medium: { ...value.medium } } : {}),
@@ -445,7 +445,8 @@ export class DelegatePanel implements Component, Focusable {
445
445
  effective.intensity !== "off" && this.hasRuntimeError
446
446
  ? ["D:ERR · policy unavailable; fix the reported role diagnostics"]
447
447
  : buildPolicyPreview(effective);
448
- const maximum = width >= 60 && budget >= 8 ? 4 : 2;
448
+ const maximum =
449
+ width >= 60 && budget >= 8 ? (effective.intensity === "orchestrator" ? 5 : 4) : 2;
449
450
  return ["Effective policy preview", ...lines]
450
451
  .slice(0, maximum)
451
452
  .map((line) => truncateToWidth(this.theme.fg("dim", line), width, ""));
@@ -492,6 +493,7 @@ export class DelegatePanel implements Component, Focusable {
492
493
  off: "No policy is injected.",
493
494
  normal: "Delegate when the expected benefit clearly outweighs overhead.",
494
495
  aggressive: "Delegate suitable substantial work by default.",
496
+ orchestrator: "Delegate transferable detail and keep ownership with the main agent.",
495
497
  }
496
498
  : {
497
499
  efficient: "Tie-break comparable fits toward Small.",
package/src/index.ts CHANGED
@@ -136,7 +136,10 @@ export default function piDelegationPolicy(pi: ExtensionAPI): void {
136
136
  await setSessionIntensity(pi, ctx, action.intensity);
137
137
  return;
138
138
  }
139
- ctx.ui.notify("Usage: /delegate, /delegate off|normal|aggressive|status|reset", "error");
139
+ ctx.ui.notify(
140
+ "Usage: /delegate, /delegate off|normal|aggressive|orchestrator|status|reset",
141
+ "error",
142
+ );
140
143
  },
141
144
  });
142
145
 
package/src/prompt.ts CHANGED
@@ -10,6 +10,8 @@ const NORMAL_POLICY =
10
10
  "Delegate substantial, separable work only when the expected benefit clearly outweighs briefing, supervision, review, and integration cost. Count parallelism as a benefit only when valuable work can advance now or elapsed time matters. A merely possible fresh perspective is not enough by itself. Keep borderline work with the main agent.";
11
11
  const AGGRESSIVE_POLICY =
12
12
  "Default to delegating substantial, separable, independently checkable work with a clear objective and acceptance criteria. Delegate when the benefit is plausible even if not proven, including a useful independent perspective. Keep work with the main agent when it is poorly bounded, tightly coupled, dominated by integration or final accountability, or has clearly prohibitive delegation overhead.";
13
+ const ORCHESTRATOR_POLICY =
14
+ "Delegate all transferable execution before performing it whenever an enabled capable role and authorized launcher are available, regardless of size. This includes small lookups, code reading, detailed planning, implementation, tests, writing, detailed review, and integration mechanics. Perform only minimal bootstrap: mandatory instructions, tool discovery, and narrow assignment scope; do not pre-solve or broadly inspect the repository. Batch small tasks without forcing recursive fanout. After assigning a task, do not take it over or run an equivalent worker while it is pending; coordinate only disjoint work, use the host wait/completion mechanism, and consume its result before dependent work or finalizing. Retain strategy, objectives, critical user decisions, coordination, safety, evidence evaluation, final acceptance, and concise synthesis; final responsibility does not permit personally completing review or integration mechanics. Reinspect returned work only for a concrete gap, risk, or contradiction; delegate transferable fixes or rechecks. Direct execution is allowed only for genuinely non-transferable work, no enabled capable role, a confirmed unavailable authorized launcher, or an explicit user or higher-priority requirement. Before direct work, state the concrete exception briefly, do only the minimum, do not repeat it while unchanged, and resume delegation when it ends. Never use a final-review or integration label to do the whole task personally. Triviality, convenience, economics, transfer cost, size, or familiarity do not justify direct execution. Keep narration concise, but never omit requested detail, risks, evidence, or safety information. Do not promise savings.";
13
15
 
14
16
  const ROLE_SELECTION_POLICY = `Choose the role by task fit before considering model preference:
15
17
  - demand: execute, search, plan, decide, coordinate, or unblock;
@@ -24,9 +26,12 @@ Use Medium directly when the combined task fit materially requires planning, red
24
26
 
25
27
  When Small and Medium are enabled alternatives, use Large only to unblock genuinely stuck work: persistent failures, severe framework conflicts, contradictory hypotheses, or reliable prior evidence that ordinary roles have not produced a trustworthy answer. Do not require ceremonial failed attempts. Large remains exceptional in a complete ordinary-role configuration.
26
28
 
27
- A more capable enabled role may cover work normally suited to a disabled role only when it can satisfy the same acceptance and evidence. Never choose a less capable role merely because it is the only enabled role. Large quantities of repetitive, independent work favor multiple Small delegations; volume alone does not justify Medium or Large. Agent type does not determine the model role. Apply preference only when Small and Medium are comparably credible fits. That tie-break applies only when both are enabled.
29
+ A more capable enabled role may cover work normally suited to a disabled role only when it can satisfy the same acceptance and evidence. Never choose a less capable role merely because it is the only enabled role. Large quantities of repetitive, independent work favor multiple Small delegations; volume alone does not justify Medium or Large. Agent type does not determine the model role. Apply preference only when Small and Medium are comparably credible fits. That tie-break applies only when both are enabled.`;
28
30
 
29
- In every intensity, keep global strategy, coordination, integration, final review, and work whose essential context is too costly or risky to transfer with the main agent.`;
31
+ const LEGACY_OWNERSHIP_POLICY =
32
+ "In every intensity, keep global strategy, coordination, integration, final review, and work whose essential context is too costly or risky to transfer with the main agent.";
33
+ const ORCHESTRATOR_OWNERSHIP_POLICY =
34
+ "In orchestrator, keep global strategy, objectives, critical decisions, coordination, safety, evidence evaluation, final acceptance, and concise synthesis with the main agent. The main agent MUST delegate transferable detailed review and integration mechanics; final responsibility does not permit personal execution except under the named direct-work exceptions.";
30
35
 
31
36
  const VISUAL_DESIGN_POLICY = `Visual Design is an optional specialist role. Use it only when all four conditions hold:
32
37
  1. the primary acceptance criterion is a visual or user-experience result;
@@ -34,9 +39,11 @@ const VISUAL_DESIGN_POLICY = `Visual Design is an optional specialist role. Use
34
39
  3. the patch is bounded to an identifiable surface, component, or set of assets;
35
40
  4. it requires no business logic, data flow, APIs, routes, application architecture, tooling, or cross-system coordination.
36
41
 
37
- When eligible, Visual Design may design, create, implement, and review scoped presentation code and visual assets, including layout, styles, responsive presentation, typography, images, icons, logos, SVGs, diagrams, and documentation visuals. It may address visual accessibility such as contrast and focus visibility. It must run and report the relevant existing checks for its patch.
38
-
39
- Route interaction behavior, state, validation, semantic HTML changes, keyboard mechanics, ARIA behavior, authentication, permissions, persistence, test infrastructure, and behavior-test ownership to an enabled ordinary role that fits, or keep it with the main agent. If any eligibility condition fails, use an enabled ordinary role or split the visual portion from the broader task. The main agent retains cross-domain integration and final acceptance.`;
42
+ When eligible, Visual Design may design, create, implement, and review scoped presentation code and visual assets, including layout, styles, responsive presentation, typography, images, icons, logos, SVGs, diagrams, and documentation visuals. It may address visual accessibility such as contrast and focus visibility. It must run and report the relevant existing checks for its patch.`;
43
+ const LEGACY_VISUAL_DESIGN_ROUTING_POLICY =
44
+ "Route interaction behavior, state, validation, semantic HTML changes, keyboard mechanics, ARIA behavior, authentication, permissions, persistence, test infrastructure, and behavior-test ownership to an enabled ordinary role that fits, or keep it with the main agent. If any eligibility condition fails, use an enabled ordinary role or split the visual portion from the broader task. The main agent retains cross-domain integration and final acceptance.";
45
+ const ORCHESTRATOR_VISUAL_DESIGN_ROUTING_POLICY =
46
+ "In orchestrator, route interaction behavior, state, validation, semantic HTML changes, keyboard mechanics, ARIA behavior, authentication, permissions, persistence, test infrastructure, and behavior-test ownership to an enabled ordinary role that fits. If any eligibility condition fails, use an enabled ordinary role or split the visual portion from the broader task. The main agent retains cross-domain integration responsibility, coordination, and final acceptance, but MUST delegate transferable integration mechanics and detailed review to a capable enabled ordinary role unless a named direct-work exception applies.";
40
47
 
41
48
  function hasSmallMedium(enabled: readonly ModelRole[]): boolean {
42
49
  return enabled.includes("small") && enabled.includes("medium");
@@ -118,6 +125,9 @@ export function buildPolicyPreview(effective: EffectiveDelegateState): string[]
118
125
  `${effective.intensity} · task fit first · ${preferencePreview(effective.preference, enabled)}`,
119
126
  `Enabled: ${enabled.map(roleName).join(", ")}${disabled.length ? ` · Disabled: ${disabled.map(roleName).join(", ")}` : ""}`,
120
127
  `${references} · exact model plus per-task thinking required; neither uses an ambient default.`,
128
+ ...(effective.intensity === "orchestrator"
129
+ ? ["Delegate all transferable work; main agent keeps final acceptance."]
130
+ : []),
121
131
  ];
122
132
  }
123
133
 
@@ -128,10 +138,23 @@ export function buildDelegationPolicy(state: RuntimeState): string | undefined {
128
138
  const { enabled, disabled } = rolesByState(effective);
129
139
  if (enabled.length === 0) return undefined;
130
140
 
131
- const intensityPolicy = effective.intensity === "normal" ? NORMAL_POLICY : AGGRESSIVE_POLICY;
141
+ const intensityPolicy =
142
+ effective.intensity === "normal"
143
+ ? NORMAL_POLICY
144
+ : effective.intensity === "aggressive"
145
+ ? AGGRESSIVE_POLICY
146
+ : ORCHESTRATOR_POLICY;
147
+ const ownershipPolicy =
148
+ effective.intensity === "orchestrator"
149
+ ? ORCHESTRATOR_OWNERSHIP_POLICY
150
+ : LEGACY_OWNERSHIP_POLICY;
132
151
  const uiDesign = effective.uiDesign
133
152
  ? `\n- Visual Design: ${formatReference(effective.uiDesign)}; exact model base: ${formatLaunchModel(effective.uiDesign)}; pi-subagents form: ${formatThinkingLaunchModel(effective.uiDesign)}`
134
153
  : "";
154
+ const visualDesignPolicy =
155
+ effective.intensity === "orchestrator"
156
+ ? `${VISUAL_DESIGN_POLICY}\n\n${ORCHESTRATOR_VISUAL_DESIGN_ROUTING_POLICY}`
157
+ : `${VISUAL_DESIGN_POLICY}\n\n${LEGACY_VISUAL_DESIGN_ROUTING_POLICY}`;
135
158
  const roleLines = enabled
136
159
  .map((role) => {
137
160
  const reference = effective[role] as ModelRef;
@@ -145,6 +168,8 @@ ${intensityPolicy}
145
168
 
146
169
  ${ROLE_SELECTION_POLICY}
147
170
 
171
+ ${ownershipPolicy}
172
+
148
173
  Enabled ordinary roles: ${enabled.map(roleName).join(", ")}.${disabled.length ? `\nDisabled ordinary roles: ${disabled.map(roleName).join(", ")}.` : ""}
149
174
 
150
175
  Model preference: ${effective.preference}. ${preferenceGuidance(effective.preference, enabled)}
@@ -153,7 +178,7 @@ Before every delegated launch, name the selected role and take its exact combine
153
178
 
154
179
  Roles:
155
180
  ${roleLines}${uiDesign}
156
- ${effective.uiDesign ? `\n${VISUAL_DESIGN_POLICY}\n` : ""}
181
+ ${effective.uiDesign ? `\n${visualDesignPolicy}\n` : ""}
157
182
  This is guidance for the main agent. It does not create, execute, route, supervise, or enforce delegated work.
158
183
  </delegation_policy>`;
159
184
  }
package/src/runtime.ts CHANGED
@@ -160,7 +160,12 @@ export function hasRuntimeError(state: RuntimeState): boolean {
160
160
  export function statusLabel(state: RuntimeState): string {
161
161
  if (state.effective.intensity === "off") return "D:OFF";
162
162
  if (hasRuntimeError(state)) return "D:ERR";
163
- return state.effective.intensity === "normal" ? "D:NORM" : "D:AGG";
163
+ const labels = {
164
+ normal: "D:NORM",
165
+ aggressive: "D:AGG",
166
+ orchestrator: "D:ORCH",
167
+ } as const;
168
+ return labels[state.effective.intensity];
164
169
  }
165
170
 
166
171
  export function formatModelRef(reference: ModelRef | null | undefined): string {
package/src/types.ts CHANGED
@@ -2,7 +2,7 @@ import type { Api, Model } from "@earendil-works/pi-ai";
2
2
 
3
3
  export const CURRENT_SCHEMA_VERSION = 3 as const;
4
4
 
5
- export const INTENSITIES = ["off", "normal", "aggressive"] as const;
5
+ export const INTENSITIES = ["off", "normal", "aggressive", "orchestrator"] as const;
6
6
  export type Intensity = (typeof INTENSITIES)[number];
7
7
 
8
8
  export const PREFERENCES = ["efficient", "standard", "intensive"] as const;
package/src/ui.ts CHANGED
@@ -13,7 +13,7 @@ export async function openDelegateEditor(ctx: ExtensionContext, pi: ExtensionAPI
13
13
  if (!ctx.hasUI) return;
14
14
  if (ctx.mode !== "tui") {
15
15
  ctx.ui.notify(
16
- "The delegation editor requires TUI mode. Use /delegate off, normal, aggressive, status, or reset here.",
16
+ "The delegation editor requires TUI mode. Use /delegate off, normal, aggressive, orchestrator, status, or reset here.",
17
17
  "warning",
18
18
  );
19
19
  return;