ytdb-slate 0.12.0 → 0.13.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.
@@ -71,7 +71,7 @@ The project must be trusted before Slate reads this file. Start a new session af
71
71
  | `doctrineExtraPath` | string | — | Markdown whose **content** is appended to the orchestrator doctrine (project-specific workflow additions). |
72
72
  | `reviewPerspectivesPath` | string | — | Review charters, each declaring its own finding-ID prefix. The doctrine references this **path**; the orchestrator reads the file alongside the shipped review rules. |
73
73
  | `router.models` | object | shipped six-model pool | Ordinary membership and definitions. `include` replaces the starting membership, including with an empty list. `add` accepts complete new definitions. `replace` changes selected fields. `exclude` applies last. Within each model definition, lists and provider maps replace shipped fields. The home and project configuration files merge first. |
74
- | `router.compressor.models` | array of `{ model, effort }` | `[{"model":"claude-sonnet-5","effort":"medium"}]` | Independent ordered compressor list. An explicit empty list blocks work. |
74
+ | `router.compressor.models` | array of `{ model, effort }` | `[{"model":"claude-sonnet-5.5","effort":"medium"}]` | Independent ordered compressor list. An explicit empty list blocks work. |
75
75
 
76
76
  ## Extended example
77
77
 
@@ -91,7 +91,7 @@ The `docs/agents/...` values below are placeholders. Point them at Markdown file
91
91
  "reviewPerspectivesPath": "docs/agents/review-perspectives.md",
92
92
  "router": {
93
93
  "models": { "include": ["luna-6", "claude-opus-5.5"] },
94
- "compressor": { "models": [{ "model": "claude-sonnet-5", "effort": "medium" }] }
94
+ "compressor": { "models": [{ "model": "claude-sonnet-5.5", "effort": "medium" }] }
95
95
  }
96
96
  }
97
97
  ```
@@ -170,9 +170,9 @@ Slate reports each refused prompt once. The orchestrator must use one state-save
170
170
  worker at a time. It must wait for the result and verify success. It must report
171
171
  incomplete preparation rather than claim that the research log was saved.
172
172
 
173
- Remote steer or follow-up, compaction-buffered input, and input accepted before
174
- the pause can bypass the hook. These are accepted limits of the pinned Pi input
175
- surface.
173
+ The remote procedure call (RPC) commands `steer` and `follow_up` pass through the Pi input hook.
174
+ Pi also applies the hook when it sends input buffered during compaction.
175
+ Input accepted before the pause can still reach the agent.
176
176
 
177
177
  ## What the always-loaded doctrine costs the budget
178
178
 
@@ -196,28 +196,28 @@ characters. Tool names use 64 characters. Descriptions use 140 characters.
196
196
 
197
197
  | fixture | paths | portable characters | lines |
198
198
  | --- | ---: | ---: | ---: |
199
- | shipped logical section | 0 | 3,892 | 11 |
200
- | trusted shipped-default doctrine | 5 | 8,764 | 88 |
199
+ | shipped logical section | 0 | 3,596 | 11 |
200
+ | trusted shipped-default doctrine | 5 | 8,468 | 88 |
201
201
  | untrusted doctrine without a home configuration file | 4 | 2,775 | 47 |
202
- | draft pull requests, shipped policy | 6 | 8,839 | 89 |
203
- | capped workers, shipped policy | 5 | 10,111 | 98 |
204
- | draft plus capped workers | 6 | 10,186 | 99 |
205
- | deferred issues plus capped workers | 5 | 10,185 | 99 |
206
- | routing recommendations plus capped workers | 5 | 10,208 | 99 |
207
- | draft plus deferred issues and capped workers | 6 | 10,260 | 100 |
208
- | draft plus routing recommendations and capped workers | 6 | 10,279 | 100 |
209
- | deferred issues plus routing recommendations and capped workers | 5 | 10,282 | 100 |
210
- | canonical maximal baseline with all workflow options | 6 | 10,353 | 101 |
211
- | maximal baseline with an open change | 6 | 10,551 | 102 |
212
- | maximal baseline with source and legacy root log | 6 | 10,781 | 104 |
213
- | dogfood `.pi/slate.json` and its two extension units | 6 | 9,478 | 100 |
202
+ | draft pull requests, shipped policy | 6 | 8,543 | 89 |
203
+ | capped workers, shipped policy | 5 | 9,815 | 98 |
204
+ | draft plus capped workers | 6 | 9,890 | 99 |
205
+ | deferred issues plus capped workers | 5 | 9,889 | 99 |
206
+ | routing recommendations plus capped workers | 5 | 9,912 | 99 |
207
+ | draft plus deferred issues and capped workers | 6 | 9,964 | 100 |
208
+ | draft plus routing recommendations and capped workers | 6 | 9,983 | 100 |
209
+ | deferred issues plus routing recommendations and capped workers | 5 | 9,986 | 100 |
210
+ | canonical maximal baseline with all workflow options | 6 | 10,057 | 101 |
211
+ | maximal baseline with an open change | 6 | 10,255 | 102 |
212
+ | maximal baseline with source and legacy root log | 6 | 10,485 | 104 |
213
+ | dogfood `.pi/slate.json` and its two extension units | 6 | 9,182 | 100 |
214
214
  | runtime boundary plus draft and capped workers, source and legacy log | 6 | 26,122 | 102 |
215
215
  | runtime boundary plus draft and deferred issues, source and legacy log | 6 | 26,196 | 103 |
216
216
  | runtime boundary plus routing recommendations, source and legacy log | 5 | 26,144 | 102 |
217
217
  | runtime boundary plus deferred issues and routing recommendations, source and legacy log | 5 | 26,218 | 103 |
218
218
  | runtime boundary plus draft and routing recommendations, source and legacy log | 6 | 26,215 | 103 |
219
219
  | same boundary composition plus deferred issues | 6 | 26,289 | 104 |
220
- | valid shipped policy plus 88 capped worker tools, source and legacy log | 6 | 28,455 | 187 |
220
+ | valid shipped policy plus 88 capped worker tools, source and legacy log | 6 | 28,159 | 187 |
221
221
 
222
222
  An untrusted session with an empty home `slate.json` receives the same doctrine
223
223
  as the trusted shipped-default fixture above. It includes routing and writing
@@ -228,7 +228,7 @@ project preferences can.
228
228
  The canonical maximal baseline uses all six shipped logical definitions, all
229
229
  three workflow options, and the fixed capped worker roster. Its largest variant
230
230
  has an open change, one direct source folder, and a legacy root log. Its
231
- five-percent requirement is `ceil(10,781 × 1.05) = 11,321`.
231
+ five-percent requirement is `ceil(10,485 × 1.05) = 11,010`.
232
232
  The 26,300 whole-doctrine ceiling exceeds it. The table pins all eight
233
233
  combinations of the three workflow options with the capped worker roster. The
234
234
  dogfood row reads the actual project configuration. A change to `.pi/slate.json` requires a fresh render.
@@ -245,8 +245,8 @@ the first value beyond the ceiling.
245
245
 
246
246
  The over-cap counterfactual uses a valid shipped logical policy and one supported
247
247
  worker-extension unit with 88 capped tools. It also includes an open change,
248
- its source, and the legacy root log. Its 28,455 portable characters exceed
249
- the whole-doctrine ceiling by 2,155. The check therefore detects whole-doctrine
248
+ its source, and the legacy root log. Its 28,159 portable characters exceed
249
+ the whole-doctrine ceiling by 1,859. The check therefore detects whole-doctrine
250
250
  growth without using a retired model-row shape or an assumed per-tool increment.
251
251
  Worker-extension doctrine has no runtime size cap, so the fixture reaches the
252
252
  whole-doctrine guard rather than failing logical-policy validation first.
@@ -301,9 +301,9 @@ the compact JSON form after pi converts the reminder to a provider request user
301
301
  message with one text part. It excludes the volatile timestamp.
302
302
 
303
303
  The 319-byte figure is one compact persisted `custom_message` record from pi
304
- 0.83.0, including its identifiers, timestamp, JSON framing, and final line-feed
305
- byte. These figures contain no installed path, so the portable and rendered
306
- counts are identical.
304
+ 1.0.0. It includes two eight-character identifiers, the timestamp, JSON framing
305
+ and the final line-feed byte. These figures contain no installed path, so the
306
+ portable and rendered counts are identical.
307
307
 
308
308
  Before automatic compaction, transcript storage grows in proportion to the number
309
309
  of turns. Cumulative request appearances grow with the square of the number of
@@ -69,11 +69,11 @@ forecasts. Membership changes do not rescale them.
69
69
  | logical model | ordinary effort | capability | cost | preferred provider | exact initial permission | guidance | cautions |
70
70
  | --- | --- | ---: | ---: | --- | --- | --- | --- |
71
71
  | `luna-6` | `max` | 45 | 5 | `openai` | `openai/gpt-6-luna` | Auxiliary tasks only, such as file location, check-result collection, or routine text management such as modifying research logs. Never primary research, implementation, design, or review. Consumer-contract work only when auxiliary. | scope and complex-text cautions below |
72
- | `claude-sonnet-5` | `high` | 40 | 90 | `anthropic` | `anthropic/claude-sonnet-5` | none | scope caution below |
73
- | `sol-6` | `high` | 58 | 20 | `openai` | `openai/gpt-6-sol` | Default thread choice. | blocked-action caution below |
72
+ | `claude-sonnet-5.5` | `high` | 45 | 54 | `anthropic` | `anthropic/claude-sonnet-5-5` | none | scope caution below |
73
+ | `sol-6.1` | `high` | 85 | 20 | `openai` | `openai/gpt-6.1-sol` | Default thread choice. | blocked-action caution below |
74
74
  | `gemini-3.8-flash` | `medium` | 55 | 30 | `google-vertex` | `google-vertex/gemini-3.8-flash` | Default thread choice. Generally prefer over Luna when available. A more specific active guideline overrides this general Flash preference. | reviewer and evidence caution below |
75
- | `claude-opus-5.5` | `high` | 90 | 65 | `anthropic` | `anthropic/claude-opus-5-5` | Concurrency, data-loss, and performance work. Prefer over Astra for code reviews of focus areas that require high-level design, except non-local logic. Do not select Opus 5.5 as the default implementer. If a lower-capability model repeatedly fails at implementation, first ask Opus 5.5 to investigate and provide detailed repair instructions. Let the implementer try those instructions. Use Opus 5.5 as the implementer only if that guided attempt also fails. Treat that use as an exception. Select another suitable model for later implementation work. Existing approval requirements and repair limits still apply. | scope caution below |
76
- | `gpt-6-astra` | `medium` | 86 | 60 | `openai` | `openai/gpt-6-astra` | Prefer when available for design reviews of all focus areas that require high-level design. Prefer for code reviews of non-local logic defects. Security and performance work. Do not select Astra as the default implementer. Use Astra for review only when assigned to a specific focus area. Use Astra for research when appropriate. | none |
75
+ | `claude-opus-5.5` | `high` | 90 | 65 | `anthropic` | `anthropic/claude-opus-5-5` | Reviewer for each proved DESIGN-TRIGGERING focus area, in adversarial design review and in implementation area review. Do not select Opus 5.5 as the default implementer. If a lower-capability model repeatedly fails at implementation, first ask Opus 5.5 to investigate and provide detailed repair instructions. Let the implementer try those instructions. Use Opus 5.5 as the implementer only if that guided attempt also fails. Treat that use as an exception. Select another suitable model for later implementation work. Existing approval requirements and repair limits still apply. | scope caution below |
76
+ | `gpt-6-astra` | `medium` | 86 | 60 | `openai` | `openai/gpt-6-astra` | Do not select Astra as the default implementer. Prefer Sol 6.1 over Astra. | none |
77
77
 
78
78
  Sonnet and Opus use this caution: `May exceed explicit scope or infer permission
79
79
  from earlier requests. Check changes against stated exclusions and approval
@@ -89,14 +89,15 @@ behavior.` Fable is not active because it has no complete
89
89
  approved definition.
90
90
 
91
91
  The independent shipped compressor list contains one entry. It is
92
- `claude-sonnet-5` at `medium`. Ordinary Sonnet remains at `high`.
92
+ `claude-sonnet-5.5` at `medium`. Ordinary Sonnet remains at `high`.
93
93
 
94
- The ratings are project judgments informed by DeepSWE v1.1 by DataCurve and
95
- reviewed supporting evidence. The live source is
94
+ The Sol 6.1 and Sonnet 5.5 capability and cost ratings are project judgments
95
+ set on 2026-09-30 without new benchmark evidence. Other ratings are project
96
+ judgments informed by DeepSWE v1.1 by DataCurve and reviewed supporting evidence.
97
+ The source for those other ratings is
96
98
  <https://deepswe.datacurve.ai/artifacts/v1.1/leaderboard-live.json>. The project
97
- retrieved it on 2026-09-11. The 2026-09-18 rating decision reused that evidence
98
- without a refresh. The live source has no confirmed licence bridge for every
99
- newer result. Slate publishes no raw task, trajectory, leaderboard row, copied
99
+ retrieved it on 2026-09-11. Those ratings use that evidence without a later
100
+ refresh. The live source has no confirmed licence bridge for every newer result. Slate publishes no raw task, trajectory, leaderboard row, copied
100
101
  publisher prose, or copied table structure. This attribution is not a new
101
102
  licence grant.
102
103
 
@@ -121,13 +122,13 @@ new session.
121
122
  {
122
123
  "router": {
123
124
  "models": {
124
- "include": ["luna-6", "claude-sonnet-5", "gpt-6-astra"],
125
+ "include": ["luna-6", "claude-sonnet-5.5", "gpt-6-astra"],
125
126
  "add": [],
126
127
  "replace": [],
127
128
  "exclude": []
128
129
  },
129
130
  "compressor": {
130
- "models": [{ "model": "claude-sonnet-5", "effort": "medium" }]
131
+ "models": [{ "model": "claude-sonnet-5.5", "effort": "medium" }]
131
132
  }
132
133
  }
133
134
  }
@@ -198,12 +199,12 @@ Complete `replace` example:
198
199
  "models": {
199
200
  "replace": [
200
201
  {
201
- "model": "sol-6",
202
+ "model": "sol-6.1",
202
203
  "effort": "max",
203
- "capabilityRating": 58,
204
+ "capabilityRating": 85,
204
205
  "costRating": 20,
205
206
  "preferredProvider": "gateway",
206
- "providers": { "gateway": "openai/gpt-6-sol" },
207
+ "providers": { "gateway": "openai/gpt-6.1-sol" },
207
208
  "guidelines": ["repository-wide implementation"],
208
209
  "cautions": []
209
210
  }
@@ -226,9 +227,11 @@ block logical work before dispatch. Slate reports each critical error. Legacy
226
227
  `router.allowUnmeasuredEffort`, and `router.showWarnings` values are named and
227
228
  ignored. Slate performs no automatic migration.
228
229
 
229
- The shipped names `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, and
230
- `claude-opus-5` are withdrawn. Use `luna-6`, `sol-6`, and
231
- `claude-opus-5.5` in `include`, `replace`, `exclude`, and compressor entries.
230
+ The shipped names `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`,
231
+ `claude-opus-5`, `sol-6`, and `claude-sonnet-5` are withdrawn. Use `luna-6`
232
+ for `gpt-5.6-luna`. Use `sol-6.1` for `gpt-5.6-sol` and `sol-6`. Use
233
+ `claude-opus-5.5` for `claude-opus-5` and `claude-sonnet-5.5` for
234
+ `claude-sonnet-5` in `include`, `replace`, `exclude`, and compressor entries.
232
235
  Terra has no replacement. Slate provides no automatic alias. A withdrawn name
233
236
  in one of those reference positions produces that position's explicit unknown-model
234
237
  error and blocks routing. A project can still define a withdrawn spelling as a
@@ -331,11 +334,11 @@ for an unknown or ambiguous route. Main recovery stays available during handoff
331
334
  pause. An unresolved stop keeps worker dispatch paused while brief writing waits
332
335
  for the user choice.
333
336
 
334
- Pi 0.85.1 model and effort switches are session-only unless the caller explicitly
337
+ Pi 1.0.0 model and effort switches are session-only unless the caller explicitly
335
338
  requests persistence. Slate retains shared saved-default ownership and its
336
- compatibility restoration guard. The guard still protects explicit persistence
337
- and older behavior. A restoration failure is visible and can leave the changed
338
- default in place.
339
+ compatibility restoration guard. The guard covers explicit persistence and
340
+ hosts that persist switches. A restoration failure is visible and can leave the
341
+ changed default in place.
339
342
 
340
343
  ## Package reliance boundary
341
344
 
@@ -556,18 +556,18 @@ export function registerSlateHandoff(
556
556
  let adopted = false;
557
557
  try {
558
558
  // Keep the whole adoption block inside the compatibility restore guard.
559
- // Pi 0.85.1 extension setters are session-only, so this is normally a
560
- // zero-write no-op. The guard still covers older or explicitly persistent
561
- // host behavior, including a thinking-level-only write.
559
+ // Pi 1.0.0 extension setters are session-only, so this is normally a
560
+ // zero-write no-op. The guard covers hosts that persist switches,
561
+ // including a thinking-level-only write.
562
562
  await withGlobalModelDefaultRestored(
563
563
  pi,
564
564
  ctx,
565
565
  getConfig(),
566
566
  { provider, id },
567
567
  async () => {
568
- // True once a Pi setter has been called. Pi 0.85.1 does not persist
569
- // this call, but the compatibility guard must conservatively cover hosts
570
- // where the same call can write a default.
568
+ // True once a Pi setter has been called. Pi 1.0.0 does not persist
569
+ // this call. The compatibility guard also covers hosts where the call
570
+ // can write a default.
571
571
  let calledSetter = false;
572
572
  try {
573
573
  // Equality guard: avoid a recorded session switch when the fresh
@@ -1,12 +1,16 @@
1
1
  export const LOGICAL_MODEL_EFFORTS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;
2
2
  export type LogicalModelEffort = (typeof LOGICAL_MODEL_EFFORTS)[number];
3
3
 
4
- export interface LogicalFieldSource {
4
+ export type LogicalFieldSource = {
5
5
  publisher: "DeepSWE/DataCurve";
6
6
  retrieved: "2026-09-11";
7
7
  sourceUrl: "https://deepswe.datacurve.ai/artifacts/v1.1/leaderboard-live.json";
8
8
  basis: "Project judgment informed by DeepSWE v1.1 and reviewed supporting evidence";
9
- }
9
+ } | {
10
+ publisher: "Slate project";
11
+ decided: "2026-09-30";
12
+ basis: "Project judgment set on 2026-09-30 without new benchmark evidence";
13
+ };
10
14
 
11
15
  export interface LogicalModelSource {
12
16
  capabilityRating?: Readonly<LogicalFieldSource>;
@@ -66,8 +70,11 @@ function fieldSource(): LogicalFieldSource {
66
70
  };
67
71
  }
68
72
 
69
- function source(): LogicalModelSource {
70
- return { capabilityRating: fieldSource(), costRating: fieldSource(), guidelines: fieldSource() };
73
+ function source(projectRatings = false): LogicalModelSource {
74
+ const ratingSource: LogicalFieldSource = projectRatings
75
+ ? { publisher: "Slate project", decided: "2026-09-30", basis: "Project judgment set on 2026-09-30 without new benchmark evidence" }
76
+ : fieldSource();
77
+ return { capabilityRating: ratingSource, costRating: ratingSource, guidelines: fieldSource() };
71
78
  }
72
79
 
73
80
  const SHIPPED_DEFINITIONS: LogicalModelDefinition[] = [
@@ -78,14 +85,14 @@ const SHIPPED_DEFINITIONS: LogicalModelDefinition[] = [
78
85
  cautions: [LUNA_CAUTION, "Do not use Luna to handle complex texts."], source: source(),
79
86
  },
80
87
  {
81
- model: "claude-sonnet-5", capabilityRating: 40, effort: "high", costRating: 90,
82
- preferredProvider: "anthropic", providers: providers("anthropic", "claude-sonnet-5"),
83
- guidelines: [], cautions: [SONNET_OPUS_CAUTION], source: source(),
88
+ model: "claude-sonnet-5.5", capabilityRating: 45, effort: "high", costRating: 54,
89
+ preferredProvider: "anthropic", providers: providers("anthropic", "claude-sonnet-5-5"),
90
+ guidelines: [], cautions: [SONNET_OPUS_CAUTION], source: source(true),
84
91
  },
85
92
  {
86
- model: "sol-6", capabilityRating: 58, effort: "high", costRating: 20,
87
- preferredProvider: "openai", providers: providers("openai", "gpt-6-sol"),
88
- guidelines: ["default thread choice"], cautions: [SOL_CAUTION], source: source(),
93
+ model: "sol-6.1", capabilityRating: 85, effort: "high", costRating: 20,
94
+ preferredProvider: "openai", providers: providers("openai", "gpt-6.1-sol"),
95
+ guidelines: ["default thread choice"], cautions: [SOL_CAUTION], source: source(true),
89
96
  },
90
97
  {
91
98
  model: "gemini-3.8-flash", capabilityRating: 55, effort: "medium", costRating: 30,
@@ -96,12 +103,12 @@ const SHIPPED_DEFINITIONS: LogicalModelDefinition[] = [
96
103
  {
97
104
  model: "claude-opus-5.5", capabilityRating: 90, effort: "high", costRating: 65,
98
105
  preferredProvider: "anthropic", providers: providers("anthropic", "claude-opus-5-5"),
99
- guidelines: ["concurrency work", "data-loss work", "performance work", "prefer over Astra for code reviews of focus areas that require high-level design, except non-local logic", "Do not select Opus 5.5 as the default implementer. If a lower-capability model repeatedly fails at implementation, first ask Opus 5.5 to investigate and provide detailed repair instructions. Let the implementer try those instructions. Use Opus 5.5 as the implementer only if that guided attempt also fails. Treat that use as an exception. Select another suitable model for later implementation work. Existing approval requirements and repair limits still apply."], cautions: [SONNET_OPUS_CAUTION], source: source(),
106
+ guidelines: ["Reviewer for each proved DESIGN-TRIGGERING focus area, in adversarial design review and in implementation area review.", "Do not select Opus 5.5 as the default implementer. If a lower-capability model repeatedly fails at implementation, first ask Opus 5.5 to investigate and provide detailed repair instructions. Let the implementer try those instructions. Use Opus 5.5 as the implementer only if that guided attempt also fails. Treat that use as an exception. Select another suitable model for later implementation work. Existing approval requirements and repair limits still apply."], cautions: [SONNET_OPUS_CAUTION], source: source(),
100
107
  },
101
108
  {
102
109
  model: "gpt-6-astra", capabilityRating: 86, effort: "medium", costRating: 60,
103
110
  preferredProvider: "openai", providers: providers("openai", "gpt-6-astra"),
104
- guidelines: ["prefer when available for design reviews of all focus areas that require high-level design", "prefer for code reviews of non-local logic defects", "security work", "performance work", "Do not select Astra as the default implementer. Use Astra for review only when assigned to a specific focus area. Use Astra for research when appropriate."],
111
+ guidelines: ["Do not select Astra as the default implementer.", "Prefer Sol 6.1 over Astra."],
105
112
  cautions: [], source: source(),
106
113
  },
107
114
  ];
@@ -109,11 +116,11 @@ const SHIPPED_DEFINITIONS: LogicalModelDefinition[] = [
109
116
  export const SHIPPED_LOGICAL_MODELS: readonly LogicalModelDefinition[] = deepFreeze(SHIPPED_DEFINITIONS);
110
117
 
111
118
  export const SHIPPED_COMPRESSOR_MODELS: readonly LogicalCompressorEntry[] = deepFreeze([
112
- { model: "claude-sonnet-5", effort: "medium" },
119
+ { model: "claude-sonnet-5.5", effort: "medium" },
113
120
  ]);
114
121
 
115
122
  export const LOGICAL_MODEL_SOURCE_NOTES = deepFreeze({
116
- ratings: "Fixed project judgments informed by DeepSWE v1.1 by DataCurve and reviewed supporting evidence",
123
+ ratings: "Fixed project judgments. Sol 6.1 and Sonnet 5.5 ratings were set on 2026-09-30 without new benchmark evidence. Other ratings are informed by DeepSWE v1.1 by DataCurve and reviewed supporting evidence",
117
124
  guidance: "Project-authored advisory guidance informed by DeepSWE v1.1 focus analysis and approved project inference",
118
125
  source: "https://deepswe.datacurve.ai/artifacts/v1.1/leaderboard-live.json",
119
126
  retrieved: "2026-09-11",
package/extension/mode.ts CHANGED
@@ -598,14 +598,13 @@ export function registerSlateMode(
598
598
  if (store.orchestratorMode && choice.enabled) displaySummary(ctx);
599
599
  };
600
600
 
601
- // pi runs a REGISTERED extension command before it emits the input event: in
602
- // the pinned pi 0.83.0, AgentSession.prompt() calls
603
- // _tryExecuteExtensionCommand(text) first and returns when a command claims
604
- // the text, and it emits the input event only for text that no command
605
- // claimed. /slate resume and /slate handoff therefore never reach this
606
- // handler, so it needs no command exemption. Text that only LOOKS like a
607
- // command — a different letter case, or a sendUserMessage() call, which skips
608
- // command handling — is ordinary user input and is refused like any other.
601
+ // In pinned pi 1.0.0, AgentSession.prompt() handles registered extension
602
+ // commands before the input event. It returns when a command claims the text.
603
+ // /slate resume and /slate handoff therefore never reach this handler.
604
+ // Command matching is exact and case-sensitive. sendUserMessage() skips
605
+ // command handling by default. Setting expandPromptTemplates to true enables
606
+ // command handling. A command-looking string that reaches this handler is
607
+ // ordinary user input and receives the same pause rule.
609
608
  pi.on("input", async (event, ctx) => {
610
609
  if (store.orchestratorMode && store.paused) {
611
610
  reportPausedInput(ctx);
@@ -2,12 +2,11 @@
2
2
  * Global model-default restore: put the user's GLOBAL pi defaults back after a
3
3
  * slate-initiated model switch.
4
4
  *
5
- * Pi 0.85.1 keeps ordinary extension model and thinking-level switches inside
6
- * the current session. It changes global defaults only when a lower-level caller
5
+ * Pi 1.0.0 keeps ordinary extension model and thinking-level switches inside
6
+ * the current session. AgentSession changes global defaults only when a caller
7
7
  * explicitly requests persistence. Slate requests no persistence. This guard
8
- * remains for compatibility with explicit persistence fixtures and older host
9
- * behavior. If a switch does write global defaults, the guard restores exactly
10
- * the residue that the switch produced.
8
+ * covers explicit persistence fixtures and hosts that persist switches. If a
9
+ * switch writes global defaults, the guard restores exactly its matching residue.
11
10
  *
12
11
  * TWO INDEPENDENT DECISIONS, NEVER ONE PER SWITCH AND NEVER ONE PER KEY:
13
12
  * - the defaultProvider + defaultModel PAIR, decided and written as ONE UNIT;
@@ -15,23 +14,20 @@
15
14
  * Each is judged from two fresh disk reads taken immediately before and after
16
15
  * the switch: restore only what CHANGED, and only when what it changed to is
17
16
  * exactly what slate's own switch should have produced. Anything unchanged is
18
- * never touched (which also makes this a zero-write no-op in EVERY state on a
19
- * future pi that stops persisting switches — upstream #5263); anything holding
20
- * a different value belongs to somebody else and is left alone.
17
+ * never touched, so session-only switches make this a zero-write no-op.
18
+ * A different value belongs to another caller and stays unchanged.
21
19
  *
22
- * Why the pair is ONE unit while the thinking level is separate: pi's ONLY
23
- * writer of those two keys is setDefaultModelAndProvider, which writes them
24
- * together, so any combination other than a pair that actually existed is a
25
- * state pi cannot produce and no consumer expects (a provider that does not own
26
- * the model, or a model with no provider at all). Deciding the halves
27
- * separately would manufacture exactly that: pre-switch provider + a third
28
- * party's model. So the pair is restored only when EVERY half that changed
29
- * matches the switch's expectation, and then the pre-switch pair is written
30
- * back EXACTLY, both halves, absence included — a state that demonstrably
31
- * existed a moment ago. The thinking level is not part of that pair and stays
32
- * independent, because the model setter's cascade can write it even when
33
- * provider and model already name the target, and handoff adoption can write it
34
- * ALONE when its equality guard skips the model setter.
20
+ * Restore provider and model as one pair. AgentSession persists that pair with
21
+ * setDefaultModelAndProvider. SettingsManager also exposes separate setters,
22
+ * so other callers can change either key. Restoring halves separately could
23
+ * combine Slate's saved provider with another caller's model. Restore the pair
24
+ * only when every changed half matches the switch expectation. Restore both
25
+ * saved halves, including absence.
26
+ *
27
+ * Restore the thinking level independently. AgentSession.setModel does not
28
+ * persist the thinking level by itself. An explicitly persistent thinking
29
+ * setter or a persistence fixture can write it separately. Handoff can call
30
+ * only the thinking setter when its model equality guard skips the model switch.
35
31
  *
36
32
  * Invariants baked in here, each one a defect this shape had to reverse:
37
33
  * - NO STATE OUTLIVES A SINGLE SWITCH. Everything consulted is read during the
@@ -67,7 +63,7 @@
67
63
  *
68
64
  * Residue, stated honestly: a restore that exhausts its retry budget is
69
65
  * ABANDONED with a loud console warning and never repaired — the switched value
70
- * then persists globally exactly as it does today.
66
+ * remains in the global file when the switch requested persistence.
71
67
  */
72
68
 
73
69
  import { existsSync, statSync } from "node:fs";
@@ -90,8 +86,8 @@ type ThinkingLevel = ReturnType<ExtensionAPI["getThinkingLevel"]>;
90
86
  * busy-waits SYNCHRONOUSLY, so an attempt's cost is set by contention, not by
91
87
  * slate — a count-based bound would leave the stall unbounded.
92
88
  *
93
- * WORST-CASE STALL, derived from this file as written (pi 0.82.1: a contended
94
- * acquisition spins 10 × 20 ms ≈ 180 ms before it succeeds or throws):
89
+ * WORST-CASE STALL, derived from this file as written (pi 1.0.0: a contended
90
+ * acquisition makes ten attempts with nine 20 ms waits, about 180 ms):
95
91
  * five lock acquisitions per attempt — post-switch read (construction IS a
96
92
  * read), write-manager construction, the pair write, the separate
97
93
  * thinking-level write, and the verifying read — so a fully contended attempt
@@ -124,7 +120,7 @@ const REPORT_MAX_CHARS = 500;
124
120
  /** Explicit end-marker for a truncated report line. */
125
121
  const REPORT_TRUNCATION_MARK = " […truncated]";
126
122
 
127
- /** The three global keys pi's model setter can write. */
123
+ /** The three global defaults covered by the restore guard. */
128
124
  interface GlobalDefaults {
129
125
  provider: string | undefined;
130
126
  model: string | undefined;
@@ -322,9 +318,8 @@ function readGlobalDefaults(cwd: string): ReadResult {
322
318
  * module header for why a per-half decision is unsafe). Returns the exact
323
319
  * pre-switch pair to write back, or undefined to leave BOTH keys alone.
324
320
  *
325
- * Do not re-split this into two decisions: pi's only writer of these keys
326
- * writes them together, so a pair mixing a pre-switch half with a post-switch
327
- * half is a state pi can never produce.
321
+ * Keep the restore decision atomic for the provider and model pair. Restoring
322
+ * only one half could combine the saved value with another caller's value.
328
323
  */
329
324
  function planPairRestore(
330
325
  pre: GlobalDefaults,
@@ -518,16 +513,19 @@ function switchMayHavePersisted<T>(predicate: ((result: T) => boolean) | undefin
518
513
  }
519
514
 
520
515
  /**
521
- * Wrap ONE slate-initiated model switch so the user's global model defaults are
522
- * left as slate found them. `performSwitch` must contain every setter call of
523
- * that switch — the post-switch read has to follow the LAST write, since
524
- * adoption can persist the thinking-level key alone.
516
+ * Wrap one slate-initiated model switch to preserve the user's global defaults.
517
+ * `performSwitch` must contain every setter call for that switch.
518
+ * The post-switch read must follow the last write.
519
+ * Explicit persistence or a host that persists switches can write the thinking
520
+ * default alone during handoff adoption. Ordinary pi 1.0.0 switches write no
521
+ * global defaults.
525
522
  *
526
- * The restore runs even when `performSwitch` THROWS (pi's model setter persists
527
- * the pair before the cascade and the model-select emission that can throw, so
528
- * a throw can still leave residue); the original rejection is then re-thrown
529
- * unchanged. Apart from that, the wrapper never throws and never alters what
530
- * `performSwitch` returns: a restore failure is reported, not propagated.
523
+ * The restore runs even when `performSwitch` throws.
524
+ * With persist:true, pi's model setter writes the pair before updating thinking
525
+ * and emitting model_select. That emission can throw after the write.
526
+ * The wrapper rethrows the original rejection unchanged.
527
+ * Otherwise, the wrapper never throws or changes what `performSwitch` returns.
528
+ * It reports a restore failure without propagating it.
531
529
  *
532
530
  * `mayHavePersisted` is an optional escape hatch for the opposite case: return
533
531
  * false to state that the callback provably called NO pi setter, so nothing can
@@ -78,7 +78,7 @@ export function isJudgementThreadType(type: unknown): type is (typeof JUDGEMENT_
78
78
  return (JUDGEMENT_THREAD_TYPES as readonly unknown[]).includes(type);
79
79
  }
80
80
 
81
- // pi-ai 0.85.1 declares this value in
81
+ // pi-ai 1.0.0 declares this value in
82
82
  // @earendil-works/pi-ai/dist/api/openai-prompt-cache.js. pi's extension loader
83
83
  // aliases the package root to the compat.js FILE, so an extension cannot safely
84
84
  // import that deep subpath. The node test pins this copy to pi-ai's declaration.
@@ -162,7 +162,7 @@ function installPromptCacheKey(session: WorkerSession, promptCacheKey?: string):
162
162
  }
163
163
 
164
164
  try {
165
- // pi-ai 0.85.1's api/openai-responses.js buildParams always creates
165
+ // pi-ai 1.0.0 api/openai-responses.js buildParams always creates
166
166
  // prompt_cache_key and assigns undefined when resolved cacheRetention is
167
167
  // "none". Own-property presence therefore distinguishes that deliberate
168
168
  // opt-out from a payload shape that never considered this field.
@@ -295,15 +295,11 @@ export function createWorkerRequestContract(): WorkerRequestContract {
295
295
  * · the wait happens BEFORE the SDK converts the conversation into a provider
296
296
  * payload, so a waiting request holds no converted copy (PF5).
297
297
  *
298
- * THE AUTHENTICATION CONTRACT IS UNCHANGED by this wrapper.
299
- * `AgentSession._getSummarizationRequestAuth` (agent-session.js:195) takes its
300
- * STRICT branch only while `agent.streamFunction === streamSimple`. A session
301
- * built by `createAgentSession` never satisfies that test: the SDK installs its
302
- * own stream function on the Agent (dist/core/sdk.js, `streamFn:` in the agent
303
- * runtime options), so the lenient branch is already the branch every slate
304
- * worker session used before this wrapper existed. A measured probe on the
305
- * pinned pi 0.85.1 confirmed `streamFunction === streamSimple` is false for a
306
- * fresh worker session, and test/request-throttle-worker.test.ts pins it.
298
+ * The wrapper preserves the software development kit (SDK) authentication branch.
299
+ * AgentSession._getSummarizationRequestAuth takes its strict branch only when
300
+ * agent.streamFunction === streamSimple. In pinned pi 1.0.0, createAgentSession
301
+ * installs its own stream function, so fresh worker sessions take the lenient
302
+ * branch. test/request-throttle-worker.test.ts checks that identity.
307
303
  *
308
304
  * A THROWN admission error is NOT swallowed. A cancelled wait rejects, pi turns
309
305
  * the rejection into the same aborted or errored assistant outcome it produces
@@ -455,24 +451,24 @@ export async function openWorkerSession(opts: {
455
451
  // user has NOT trusted. Carry the host session's actual trust decision into
456
452
  // both the resource loader and the session.
457
453
  //
458
- // READ-ONLY view (AF8/AF9): model failover may call session.setModel on a
459
- // live worker, and setModel persists the new model as the default via
460
- // SettingsManager (setThinkingLevel likewise). A file-backed manager would
461
- // write a worker's failover model into the USER'S global settings.json.
462
- // Instead, snapshot the settings once here and serve them through a custom
463
- // SettingsStorage whose withLock discards the callback's return value —
464
- // the supported no-op write path (persistScopedSettings only hands the new
465
- // JSON back as that return value; there is no error path). Reads, merge
466
- // semantics, and trust gating are identical to a file-backed manager.
454
+ // READ-ONLY view (AF8/AF9): pi 1.0.0 keeps ordinary session.setModel and
455
+ // setThinkingLevel calls inside the session. Slate requests no persistence.
456
+ // This storage protects global settings from calls with persist:true and
457
+ // from hosts that persist switches. A file-backed manager would save those
458
+ // explicit writes as global defaults, including a worker's failover choice.
459
+ // Snapshot the settings once and serve them through a custom SettingsStorage.
460
+ // Its withLock discards the callback's return value, which drops writes.
461
+ // persistScopedSettings returns the new JSON through that callback.
462
+ // Reads, merge semantics and trust gating match a file-backed manager.
467
463
  //
468
- // CN4: the snapshot is taken via a throwaway file-backed SettingsManager,
469
- // NOT a raw readFileSync — pi's settings writer holds a lockfile during
470
- // its non-atomic writes (e.g. the orchestrator's own failover setModel
471
- // persisting a new global default), so an unlocked read could tear. The
472
- // throwaway does the locked, error-tolerant read; its per-scope snapshots
473
- // are re-serialized for the storage below (fromStorage re-parses and
474
- // re-migrates them — idempotent), and it never writes: no setter is ever
475
- // called on it.
464
+ // CN4: a throwaway file-backed SettingsManager takes the snapshot under pi's
465
+ // settings lock. Pi holds that lock during its non-atomic settings writes.
466
+ // A call with persist:true or a direct SettingsManager setter can write
467
+ // global defaults. An unlocked read could capture an incomplete write.
468
+ // The throwaway manager reads under the lock and handles read errors.
469
+ // Its per-scope snapshots become JSON for the storage below.
470
+ // fromStorage parses and migrates that JSON again without changing it.
471
+ // The throwaway manager never writes because no caller invokes its setters.
476
472
  const trusted = ctx.isProjectTrusted();
477
473
  const snapshot = SettingsManager.create(ctx.cwd, agentDir, { projectTrusted: trusted });
478
474
  // Pi's background warmer bypasses agent.streamFunction and therefore Slate's
@@ -597,13 +593,11 @@ export async function openWorkerSession(opts: {
597
593
  ? SessionManager.open(opts.sessionFile)
598
594
  : SessionManager.create(ctx.cwd, ensureRuntimeDirectory(ctx.cwd, opts.runtimeFolder ?? defaultArtifactFolder(), "threads"));
599
595
 
600
- // No modelRuntime passed: createAgentSession (pi >= 0.80.8) defaults to a
601
- // ModelRuntime replacing the AuthStorage + ModelRegistry setup this code
602
- // hand-built before those SDK options were removed. Credential/config
603
- // sources are unchanged — global agentDir auth.json + models.json, never
604
- // project-local — but the default is a superset: it also reads/writes
605
- // agentDir/models-store.json and may run a throttled (~4h-cached)
606
- // create-time network catalog refresh (disabled by PI_OFFLINE).
596
+ // In pi 1.0.0, createAgentSession creates a ModelRuntime when none is passed.
597
+ // It uses auth.json, models.json and models-store.json under agentDir.
598
+ // SDK creation enables network catalog refresh only with allowModelNetwork.
599
+ // This call supplies no runtime option, so creation uses no network catalog
600
+ // refresh. PI_OFFLINE also disables model-network access.
607
601
  const { session } = await createAgentSession({
608
602
  cwd: ctx.cwd,
609
603
  agentDir,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ytdb-slate",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Multi-agent orchestration extension for the pi coding agent: bounded worker sessions, structured episode summaries, and a risk-based review workflow.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -36,9 +36,9 @@
36
36
  "typebox": "*"
37
37
  },
38
38
  "devDependencies": {
39
- "@earendil-works/pi-ai": "0.87.1",
40
- "@earendil-works/pi-coding-agent": "0.87.1",
41
- "@earendil-works/pi-tui": "0.87.1",
39
+ "@earendil-works/pi-ai": "1.0.0",
40
+ "@earendil-works/pi-coding-agent": "1.0.0",
41
+ "@earendil-works/pi-tui": "1.0.0",
42
42
  "@types/node": "24.13.3",
43
43
  "typebox": "1.3.27",
44
44
  "typescript": "5.9.3"