pi-goal-list-loop-audit 0.31.1 → 0.31.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -112,9 +112,10 @@ export interface Settings {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
export const DEFAULT_SETTINGS: Settings = {
|
|
115
|
-
// Unset =
|
|
116
|
-
//
|
|
117
|
-
//
|
|
115
|
+
// Unset = "high" at the call site (v0.31.2). The auditor is the
|
|
116
|
+
// verification gate: its depth must NOT ride the session's coding-speed
|
|
117
|
+
// thinking dial (user 2026-07-31: "we should also select its thinking
|
|
118
|
+
// level — we don't keep switching it"). /glla thinking= overrides.
|
|
118
119
|
auditorThinkingLevel: undefined,
|
|
119
120
|
// v0.24.6: subagents inherit the session model by default — one quota
|
|
120
121
|
// pool, no surprise 403s from a pinned default agent's provider.
|
package/extensions/loops/goal.ts
CHANGED
|
@@ -154,6 +154,7 @@ import {
|
|
|
154
154
|
} from "../settings-menu.js";
|
|
155
155
|
import {
|
|
156
156
|
buildModelPickItems,
|
|
157
|
+
pickDiverseAuditorModel,
|
|
157
158
|
ModelPickerComponent,
|
|
158
159
|
type ModelPickItem,
|
|
159
160
|
} from "../model-picker.js";
|
|
@@ -1380,7 +1381,7 @@ async function retryStoredCompletionAudit(ctx: ExtensionContext, origin: "quota-
|
|
|
1380
1381
|
completionSummary: claim.completionSummary,
|
|
1381
1382
|
verificationSummary: claim.verificationSummary,
|
|
1382
1383
|
model: auditorModel,
|
|
1383
|
-
thinkingLevel: settings.auditorThinkingLevel ??
|
|
1384
|
+
thinkingLevel: settings.auditorThinkingLevel ?? "high",
|
|
1384
1385
|
onProgress: (progress) => {
|
|
1385
1386
|
latestAuditProgress = { currentTool: progress.currentTool, label: progress.label, elapsedMs: progress.elapsedMs, lastEventAt: Date.now() };
|
|
1386
1387
|
refreshUI(liveCtx);
|
|
@@ -3188,7 +3189,7 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
|
|
|
3188
3189
|
completionSummary: p.completionSummary,
|
|
3189
3190
|
verificationSummary: p.verificationSummary,
|
|
3190
3191
|
model: auditorModel,
|
|
3191
|
-
thinkingLevel: settings.auditorThinkingLevel ??
|
|
3192
|
+
thinkingLevel: settings.auditorThinkingLevel ?? "high",
|
|
3192
3193
|
signal: signal ?? undefined,
|
|
3193
3194
|
onProgress: (progress) => {
|
|
3194
3195
|
latestAuditProgress = {
|
|
@@ -4207,18 +4208,6 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
|
|
|
4207
4208
|
* the thinking level the user selected in pi; if none is set, audits run at
|
|
4208
4209
|
* "high" — the auditor is the verification gate, depth beats speed there.
|
|
4209
4210
|
*/
|
|
4210
|
-
function getSessionThinkingLevel(): "off" | "minimal" | "low" | "medium" | "high" | "xhigh" {
|
|
4211
|
-
try {
|
|
4212
|
-
const level = extensionApi?.getThinkingLevel?.();
|
|
4213
|
-
if (level && ["off", "minimal", "low", "medium", "high", "xhigh"].includes(level)) {
|
|
4214
|
-
return level as "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
4215
|
-
}
|
|
4216
|
-
} catch {
|
|
4217
|
-
// fall through to the floor
|
|
4218
|
-
}
|
|
4219
|
-
return "high";
|
|
4220
|
-
}
|
|
4221
|
-
|
|
4222
4211
|
/**
|
|
4223
4212
|
* Resolve the auditor model (v0.6.2). The principle: **the user selects the
|
|
4224
4213
|
* model in pi; the auditor uses it.** The plugin never picks a model itself.
|
|
@@ -4235,6 +4224,24 @@ function getSessionThinkingLevel(): "off" | "minimal" | "low" | "medium" | "high
|
|
|
4235
4224
|
function resolveAuditorModel(ctx: ExtensionContext, ref?: string): { model: any; error?: string; via?: string } {
|
|
4236
4225
|
if (ref && ref.trim()) {
|
|
4237
4226
|
const trimmed = ref.trim();
|
|
4227
|
+
// v0.31.2: "diverse" — the cross-vendor auditor (user design 2026-07-31:
|
|
4228
|
+
// "there is benefit to have a different auditor"). Independent blind
|
|
4229
|
+
// spots + a separate quota pool; the fresh auditor session shares no
|
|
4230
|
+
// prompt cache anyway, so cross-vendor costs nothing extra.
|
|
4231
|
+
if (trimmed.toLowerCase() === "diverse") {
|
|
4232
|
+
const sessionModel = ctx.model as any;
|
|
4233
|
+
const available = ctx.modelRegistry
|
|
4234
|
+
.getAvailable()
|
|
4235
|
+
.filter((m: any) => ctx.modelRegistry.hasConfiguredAuth(m));
|
|
4236
|
+
const pick = pickDiverseAuditorModel(available, sessionModel?.provider);
|
|
4237
|
+
if (pick) return { model: pick, via: "diverse" };
|
|
4238
|
+
if (sessionModel) {
|
|
4239
|
+
appendLedger(ctx.cwd, "auditor_model_fallback", { configured: "diverse", reason: "no configured-auth model outside the session's provider" });
|
|
4240
|
+
ctx.ui.notify("Auditor model \"diverse\" found no model outside the session's provider — falling back to the session model (LOUD fallback; pin one via /glla → Auditor model).", "warning");
|
|
4241
|
+
return { model: sessionModel, via: "session-fallback" };
|
|
4242
|
+
}
|
|
4243
|
+
return { model: undefined, error: "auditorModel \"diverse\": no configured-auth model at all" };
|
|
4244
|
+
}
|
|
4238
4245
|
// v0.29.17: an unavailable configured model (unknown id, or a provider
|
|
4239
4246
|
// with no configured auth) falls back LOUDLY to the session model —
|
|
4240
4247
|
// user request: "fall back to the session if unavailable". The v0.9.12
|
|
@@ -4355,6 +4362,7 @@ async function promptModelRef(
|
|
|
4355
4362
|
ctx: ExtensionContext,
|
|
4356
4363
|
title: string,
|
|
4357
4364
|
emptyLabel: string,
|
|
4365
|
+
extraTop: ModelPickItem[] = [],
|
|
4358
4366
|
): Promise<{ kind: "session" } | { kind: "ref"; ref: string } | undefined> {
|
|
4359
4367
|
if (typeof (ctx.ui as { custom?: unknown }).custom !== "function" || !ctx.modelRegistry) {
|
|
4360
4368
|
const v = await ctx.ui.input(title, "provider/model-id — empty keeps the default");
|
|
@@ -4366,7 +4374,7 @@ async function promptModelRef(
|
|
|
4366
4374
|
const models = ctx.modelRegistry
|
|
4367
4375
|
.getAvailable()
|
|
4368
4376
|
.filter((m: any) => ctx.modelRegistry.hasConfiguredAuth(m));
|
|
4369
|
-
const items = buildModelPickItems(models, sessionLabel);
|
|
4377
|
+
const items = buildModelPickItems(models, sessionLabel, extraTop);
|
|
4370
4378
|
const pick = await ctx.ui.custom<ModelPickItem | undefined>((tui, theme, keybindings, done) => {
|
|
4371
4379
|
return new ModelPickerComponent({ title, items }, () => tui.requestRender(), theme, keybindings, done);
|
|
4372
4380
|
});
|
|
@@ -4418,10 +4426,21 @@ export async function handleSettingChoice(id: string, ctx: ExtensionContext): Pr
|
|
|
4418
4426
|
return;
|
|
4419
4427
|
}
|
|
4420
4428
|
case "auditorModel": {
|
|
4421
|
-
|
|
4429
|
+
// v0.31.2: "diverse" sits at the top — the cross-vendor auditor
|
|
4430
|
+
// (independent blind spots + a separate quota pool from the coding
|
|
4431
|
+
// session). Picked like a model; resolution happens per-audit so
|
|
4432
|
+
// provider availability is re-checked every time.
|
|
4433
|
+
const diverseItem: ModelPickItem = {
|
|
4434
|
+
kind: "model",
|
|
4435
|
+
ref: "diverse",
|
|
4436
|
+
label: "diverse — cross-vendor auditor: a different provider than the session, picked fresh per audit (Recommended)",
|
|
4437
|
+
searchText: "diverse cross vendor independent different provider quota strategy recommended",
|
|
4438
|
+
};
|
|
4439
|
+
const pick = await promptModelRef(ctx, "Auditor model override", "provider/model-id — empty keeps the pi session model", [diverseItem]);
|
|
4422
4440
|
if (pick === undefined) return;
|
|
4423
4441
|
saveSettings("global", ctx.cwd, { auditorModel: pick.kind === "session" ? undefined : pick.ref });
|
|
4424
4442
|
if (pick.kind === "session") ctx.ui.notify("Auditor model override cleared — the auditor follows the pi session model.", "info");
|
|
4443
|
+
if (pick.kind === "ref" && pick.ref === "diverse") ctx.ui.notify("Auditor model: DIVERSE — each audit picks a configured model outside the session's provider (deepseek ↔ MiniMax first).", "info");
|
|
4425
4444
|
return;
|
|
4426
4445
|
}
|
|
4427
4446
|
case "auditorThinkingLevel": {
|
|
@@ -41,7 +41,7 @@ export interface RegistryModelLike {
|
|
|
41
41
|
/** Build the picker's static item list from registry models (already
|
|
42
42
|
* filtered to configured-auth providers by the caller). Session row first,
|
|
43
43
|
* manual-entry row last; models sorted by provider then id. */
|
|
44
|
-
export function buildModelPickItems(models: RegistryModelLike[], sessionLabel: string): ModelPickItem[] {
|
|
44
|
+
export function buildModelPickItems(models: RegistryModelLike[], sessionLabel: string, extraTop: ModelPickItem[] = []): ModelPickItem[] {
|
|
45
45
|
const sorted = [...models].sort((a, b) =>
|
|
46
46
|
a.provider === b.provider ? a.id.localeCompare(b.id) : a.provider.localeCompare(b.provider),
|
|
47
47
|
);
|
|
@@ -51,6 +51,7 @@ export function buildModelPickItems(models: RegistryModelLike[], sessionLabel: s
|
|
|
51
51
|
label: `session model (${sessionLabel}) — clear the override`,
|
|
52
52
|
searchText: "session model default clear override follow",
|
|
53
53
|
},
|
|
54
|
+
...extraTop,
|
|
54
55
|
...sorted.map((m) => {
|
|
55
56
|
const ref = `${m.provider}/${m.id}`;
|
|
56
57
|
return {
|
|
@@ -206,3 +207,47 @@ export class ModelPickerComponent {
|
|
|
206
207
|
|
|
207
208
|
// Re-export for callers that only need the width helper's type signature.
|
|
208
209
|
export { visibleWidth };
|
|
210
|
+
|
|
211
|
+
/** v0.31.2: provider preference for the "diverse" auditor strategy (user
|
|
212
|
+
* design 2026-07-31: "there is benefit to have a different auditor — M3's
|
|
213
|
+
* auditor could be deepseek and vice versa"). A cross-vendor auditor reads
|
|
214
|
+
* the executor's claims with INDEPENDENT blind spots (same-family models
|
|
215
|
+
* share failure modes), and it spends a DIFFERENT provider's quota pool —
|
|
216
|
+
* audits stop eating the coding session's MiniMax window. The auditor is
|
|
217
|
+
* already a fresh session (no prompt-cache sharing), so cross-vendor costs
|
|
218
|
+
* nothing in cache terms.
|
|
219
|
+
*
|
|
220
|
+
* Order: deepseek-via-openrouter first, MiniMax second, then the other
|
|
221
|
+
* providers seen on this rig. The session's own provider is EXCLUDED
|
|
222
|
+
* entirely (openrouter hosts everything — family-level reasoning about its
|
|
223
|
+
* catalogue isn't reliable, so exclusion is at provider granularity).
|
|
224
|
+
*/
|
|
225
|
+
export const DIVERSE_AUDITOR_PREFERENCE: Array<{ provider: string; match?: string }> = [
|
|
226
|
+
{ provider: "openrouter", match: "deepseek/deepseek-chat" },
|
|
227
|
+
{ provider: "openrouter", match: "deepseek" },
|
|
228
|
+
{ provider: "minimax", match: "MiniMax-M3" },
|
|
229
|
+
{ provider: "minimax" },
|
|
230
|
+
{ provider: "kimi-coding" },
|
|
231
|
+
{ provider: "kimi" },
|
|
232
|
+
{ provider: "xai-auth" },
|
|
233
|
+
{ provider: "opencode" },
|
|
234
|
+
{ provider: "zenmux" },
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
/** Pure selection: the first preference entry (outside the session's
|
|
238
|
+
* provider) with at least one available model wins; within an entry the
|
|
239
|
+
* models arrive pre-filtered (auth checked by the caller) and sorted.
|
|
240
|
+
* Returns undefined when nothing outside the session provider is available
|
|
241
|
+
* — the caller falls back LOUDLY to the session model.
|
|
242
|
+
*/
|
|
243
|
+
export function pickDiverseAuditorModel(
|
|
244
|
+
models: RegistryModelLike[],
|
|
245
|
+
sessionProvider: string | undefined,
|
|
246
|
+
): RegistryModelLike | undefined {
|
|
247
|
+
for (const pref of DIVERSE_AUDITOR_PREFERENCE) {
|
|
248
|
+
if (pref.provider === sessionProvider) continue;
|
|
249
|
+
const hit = models.find((m) => m.provider === pref.provider && (!pref.match || m.id.includes(pref.match)));
|
|
250
|
+
if (hit) return hit;
|
|
251
|
+
}
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
@@ -173,9 +173,9 @@ export function buildSettingsRows(
|
|
|
173
173
|
id: "auditorThinkingLevel",
|
|
174
174
|
section: "auditor",
|
|
175
175
|
label: "Auditor thinking",
|
|
176
|
-
valueText: show("auditorThinkingLevel", "session
|
|
176
|
+
valueText: show("auditorThinkingLevel", "high (fixed — never the session coding dial)"),
|
|
177
177
|
sourceText: src("auditorThinkingLevel"),
|
|
178
|
-
description: "thinking level for the auditor session",
|
|
178
|
+
description: "thinking level for the auditor session — unset = high (the verification gate does not ride the session thinking dial)",
|
|
179
179
|
},
|
|
180
180
|
{
|
|
181
181
|
id: "auditCap",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.2",
|
|
4
4
|
"description": "Goal. Loop. Audit. Done. \u2014 a pi-coding-agent extension that supervises long-running work, with isolated auditor on each completion. Beat bamboozling by design: the auditor runs in a fresh session with no extensions, no skills, no editor \u2014 only the read tools needed to verify your goal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "dracon",
|