pi-gauntlet 7.18.0 → 7.18.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
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v7.18.1 - 2026-10-19
4
+
5
+ ### Removed
6
+
7
+ - **`start implement` no longer warns about a missing `promptCache` lifetime.** The warning fired on every non-Anthropic model (pi's catalog declares `promptCache` only for direct `anthropic` Claude entries) and read as an instruction to edit `models.json`, which stalled auto-chaining into implement until the user typed "continue"; the per-call cache telemetry from #67 stays and is the real signal for cache hits.
8
+
3
9
  ## v7.18.0 - 2026-10-19
4
10
 
5
11
  ### Changed
@@ -69,7 +69,7 @@ const resumedBranch = (rest: Partial<Record<Phase, Status>>) => [
69
69
  phaseResult("complete", phases({ brainstorm: "skipped", ...rest })),
70
70
  ];
71
71
 
72
- type TestModel = { provider: string; id: string; promptCache?: { short?: number; long?: number } };
72
+ type TestModel = { provider: string; id: string };
73
73
 
74
74
  function harness(options: { cwd?: string; branch?: unknown[]; idle?: boolean; beforeSettled?: (setIdle: (idle: boolean) => void) => void; sendThrows?: boolean; model?: TestModel; thinkingLevel?: string; registry?: Record<string, TestModel>; setModelResult?: boolean | Error } = {}) {
75
75
  const handlers = new Map<string, ((event: unknown, ctx: unknown) => unknown)[]>();
@@ -136,7 +136,7 @@ const startPhase = async (h: ReturnType<typeof harness>, phase: string) => {
136
136
  return { text: r.content.map((c) => c.text).join("\n"), status: r.details.phases[phase].status };
137
137
  };
138
138
 
139
- const M = (id: string, promptCache?: { short?: number; long?: number }) => ({ provider: "p", id, promptCache });
139
+ const M = (id: string) => ({ provider: "p", id });
140
140
 
141
141
  const preparePhase = async (h: ReturnType<typeof harness>, phase = "plan") => {
142
142
  await settle(h);
@@ -223,46 +223,6 @@ test("phaseModels: resolver warnings appear only for their phase", async () => {
223
223
  assert.deepEqual(h.pi.thinkingCalls, []);
224
224
  });
225
225
 
226
- for (const row of [
227
- { name: "missing short", phase: "implement", cache: undefined, retention: undefined, tier: "short" },
228
- { name: "declared short", phase: "implement", cache: { short: 300 }, retention: undefined, tier: undefined },
229
- { name: "missing long", phase: "implement", cache: { short: 300 }, retention: "long", tier: "long" },
230
- { name: "plan ignores cache", phase: "plan", cache: undefined, retention: undefined, tier: undefined },
231
- ]) {
232
- test(`phaseModels: cache warning ${row.name}`, async () => {
233
- const retention = process.env.PI_CACHE_RETENTION;
234
- if (row.retention === undefined) delete process.env.PI_CACHE_RETENTION;
235
- else process.env.PI_CACHE_RETENTION = row.retention;
236
- try {
237
- const h = harness({ cwd: tempCwd({ piGauntlet: { flowGuards: { enforce: false } } }), model: M("m", row.cache) });
238
- await preparePhase(h, row.phase);
239
- const r = await startPhase(h, row.phase);
240
- if (row.tier) {
241
- assert.ok(r.text.includes(`p/m declares no promptCache.${row.tier} lifetime, so pi's cache warmer skips it`));
242
- assert.ok(r.text.includes("providers.p.modelOverrides.m.promptCache"));
243
- assert.ok(r.text.includes("providers.p.models[].promptCache"));
244
- } else assert.doesNotMatch(r.text, /cache warmer/);
245
- assert.deepEqual(h.pi.setModelCalls, []);
246
- assert.deepEqual(h.pi.thinkingCalls, []);
247
- assert.equal(r.status, "in_progress");
248
- } finally {
249
- if (retention === undefined) delete process.env.PI_CACHE_RETENTION;
250
- else process.env.PI_CACHE_RETENTION = retention;
251
- }
252
- });
253
- }
254
-
255
- test("phaseModels: cache warning checks the switched model", async () => {
256
- const h = harness({ cwd: tempCwd({ piGauntlet: { flowGuards: { enforce: false }, phaseModels: { implement: "p/warm" } } }), model: M("old"), registry: { "p/warm": M("warm", { short: 300, long: 3600 }) } });
257
- await preparePhase(h, "implement");
258
- const r = await startPhase(h, "implement");
259
- assert.equal(h.pi.setModelCalls.length, 1);
260
- assert.deepEqual(h.pi.thinkingCalls, []);
261
- assert.equal(h.ctx.model?.id, "warm");
262
- assert.doesNotMatch(r.text, /cache warmer/);
263
- assert.equal(r.status, "in_progress");
264
- });
265
-
266
226
  test("agent_settled nudges each exact edge with persisted details", async () => {
267
227
  for (const [state, edge, skill] of [
268
228
  [phases({ brainstorm: "complete", plan: "complete" }), "plan-implement", "/skill:subagent-driven-development"],
@@ -1031,17 +1031,6 @@ export default function (pi: ExtensionAPI) {
1031
1031
  for (const w of resolved.warning?.split("; ") ?? []) if (w.includes(`phaseModels.${phase} `)) startLines.push(`\u26a0\ufe0f ${w}`);
1032
1032
  const target = resolved.phaseModels[phase];
1033
1033
  if (target) startLines.push(...(await applyPhaseModel(pi, ctx, phase, target)));
1034
- if (phase === "implement") {
1035
- const tier = process.env.PI_CACHE_RETENTION === "long" ? "long" : "short";
1036
- const m = ctx.model;
1037
- if (m && m.promptCache?.[tier] === undefined) {
1038
- startLines.push(
1039
- `\u26a0\ufe0f ${m.provider}/${m.id} declares no promptCache.${tier} lifetime, so pi's cache warmer skips it. ` +
1040
- `Declare it in <agent-dir>/models.json (default ~/.pi/agent): providers.${m.provider}.modelOverrides.${m.id}.promptCache for a built-in model, ` +
1041
- `or providers.${m.provider}.models[].promptCache for a custom one; the lifetime is required by the warmer but not sufficient - see doc/configuration.md#phase-models.`,
1042
- );
1043
- }
1044
- }
1045
1034
  }
1046
1035
  phases = { ...phases, [params.phase]: transitionPhaseState("in_progress") as PhaseState };
1047
1036
  // A rewind must not inherit the prior verify's conformance latch.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "7.18.0",
3
+ "version": "7.18.1",
4
4
  "description": "Opinionated, gated workflow skills, subagent personas, and runtime extensions for the pi coding agent.",
5
5
  "author": "Jacek Juraszek",
6
6
  "type": "module",