pi-goal-list-loop-audit 0.26.9 → 0.27.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/extensions/loops/goal.ts +95 -46
- package/package.json +1 -1
package/extensions/loops/goal.ts
CHANGED
|
@@ -2852,66 +2852,93 @@ async function openSettingsUI(ctx: ExtensionContext): Promise<void> {
|
|
|
2852
2852
|
const v = p.value === undefined ? fallback : String(p.value);
|
|
2853
2853
|
return `${v} [${p.source}]`;
|
|
2854
2854
|
};
|
|
2855
|
+
const settings = loadSettings(ctx.cwd);
|
|
2856
|
+
// v0.27.0: every option on ONE screen, grouped into sections, each row
|
|
2857
|
+
// carrying `label — value [provenance] — what it does` so the menu is
|
|
2858
|
+
// also the documentation. Header rows are no-ops when selected.
|
|
2859
|
+
const rows = [
|
|
2860
|
+
"── Keep-going ──",
|
|
2861
|
+
`Auto-resume on load — ${show("autoResume", "default")} — on: resume on session load too · off: never · default: hold on load, resume on reload/fork`,
|
|
2862
|
+
`Auto-accept drafts — ${show("autoAcceptDrafts", "(off)")} — on: goal/loop drafts activate without the Confirm dialog (unattended rigs)`,
|
|
2863
|
+
`Aggressive mode — ${show("aggressiveMode", "(off)")} — flips DEFAULTS toward keep-going (autoResume, cap 10, stuck 10, wedge off, quota auto-retry, cap→TODOs); explicit per-key settings still win`,
|
|
2864
|
+
"── Auditor ──",
|
|
2865
|
+
`Auditor model — ${show("auditorModel", "(pi session model)")} — provider/model override for the isolated auditor`,
|
|
2866
|
+
`Auditor thinking — ${show("auditorThinkingLevel", "(session, floor high)")} — thinking level for the auditor session`,
|
|
2867
|
+
`Audit cap — ${show("auditCap", "(5)")} — pause the goal after N consecutive disapprovals (0 = unlimited)`,
|
|
2868
|
+
`Audit feedback chars — ${show("auditFeedbackChars", "(full report)")} — cap the executor-visible disapproval report (0 = full report)`,
|
|
2869
|
+
`Quota retry minutes — ${show("quotaRetryMinutes", `(${DEFAULT_QUOTA_RETRY_MINUTES})`)} — auto-retry a quota-exhausted auditor after N minutes`,
|
|
2870
|
+
"── Stall brakes ──",
|
|
2871
|
+
`Wedge alert minutes — ${show("wedgeAlertMinutes", `(${WEDGE_ALERT_DEFAULT_MINUTES})`)} — hung-command alert while the session is busy (0 = off)`,
|
|
2872
|
+
`Stuck max interventions — ${show("stuckMaxInterventions", "(5)")} — consecutive stuck interventions before a loop stops`,
|
|
2873
|
+
`Stall escalation refires — ${show("stallEscalationRefires", "(5)")} — heartbeat refires with no turn before the goal pauses / loop stops (0 = never)`,
|
|
2874
|
+
"── Subagents ──",
|
|
2875
|
+
`Subagent model strategy — ${show("subagentModelStrategy", "(inherit-parent)")} — inherit-parent shares your session model+quota; agent-default pins haiku for Explore`,
|
|
2876
|
+
`Subagent Explore pin — ${settings.subagentModelOverrides?.Explore ?? "(follows strategy)"} — provider/model pin; always wins over strategy`,
|
|
2877
|
+
`Subagent Plan pin — ${settings.subagentModelOverrides?.Plan ?? "(follows strategy)"} — provider/model pin; always wins over strategy`,
|
|
2878
|
+
`Subagent general-purpose pin — ${settings.subagentModelOverrides?.["general-purpose"] ?? "(follows strategy)"} — provider/model pin; always wins over strategy`,
|
|
2879
|
+
"── Other ──",
|
|
2880
|
+
`Notify command — ${show("notifyCmd", "(off)")} — desktop push command; the event message is passed as $1`,
|
|
2881
|
+
`Token limit per goal — ${show("tokenLimit", "(off)")} — per-goal token budget; pause when exceeded (0 = off)`,
|
|
2882
|
+
`Reviewer config… — open the reviewer menu (post-completion follow-up enqueuer: mode, triggers, cascade, caps)`,
|
|
2883
|
+
"Done",
|
|
2884
|
+
];
|
|
2855
2885
|
let choice: string | undefined;
|
|
2856
2886
|
try {
|
|
2857
2887
|
choice = await ctx.ui.select(
|
|
2858
2888
|
`pi-goal-list-loop-audit settings — global: ${globalSettingsPath()}`,
|
|
2859
|
-
|
|
2860
|
-
`Auditor model override — ${show("auditorModel", "(pi session model)")}`,
|
|
2861
|
-
`Auditor thinking — ${show("auditorThinkingLevel", "(session, floor high)")}`,
|
|
2862
|
-
`Notify command — ${show("notifyCmd", "(off)")}`,
|
|
2863
|
-
`Token limit per goal — ${show("tokenLimit", "(off)")}`,
|
|
2864
|
-
`Wedge alert minutes — ${show("wedgeAlertMinutes", `(${WEDGE_ALERT_DEFAULT_MINUTES}m default)`)}`,
|
|
2865
|
-
`Aggressive mode — ${show("aggressiveMode", "(off)")}`,
|
|
2866
|
-
`Quota retry minutes — ${show("quotaRetryMinutes", `(${DEFAULT_QUOTA_RETRY_MINUTES}m default)`)}`,
|
|
2867
|
-
`Stuck max interventions — ${show("stuckMaxInterventions", "(5 default)")}`,
|
|
2868
|
-
`Subagent model strategy — ${show("subagentModelStrategy", "(inherit-parent)")}`,
|
|
2869
|
-
`Subagent Explore model pin — ${loadSettings(ctx.cwd).subagentModelOverrides?.Explore ?? "(follows strategy)"}`,
|
|
2870
|
-
`Subagent Plan model pin — ${loadSettings(ctx.cwd).subagentModelOverrides?.Plan ?? "(follows strategy)"}`,
|
|
2871
|
-
`Subagent general-purpose model pin — ${loadSettings(ctx.cwd).subagentModelOverrides?.["general-purpose"] ?? "(follows strategy)"}`,
|
|
2872
|
-
`Audit feedback characters — ${show("auditFeedbackChars", "(full report)")}`,
|
|
2873
|
-
"Done",
|
|
2874
|
-
],
|
|
2889
|
+
rows,
|
|
2875
2890
|
);
|
|
2876
2891
|
} catch {
|
|
2877
2892
|
return;
|
|
2878
2893
|
}
|
|
2879
2894
|
if (!choice || choice === "Done") return;
|
|
2895
|
+
if (choice.startsWith("──")) continue; // section header — no-op
|
|
2880
2896
|
try {
|
|
2881
|
-
if (choice.startsWith("
|
|
2897
|
+
if (choice.startsWith("Auto-resume")) {
|
|
2898
|
+
const v = await ctx.ui.select("Auto-resume goals/loops on session start", [
|
|
2899
|
+
"default — HOLD when a session is loaded (popup shows what waits); auto-resume on reload/fork so machinery never strands work",
|
|
2900
|
+
"on — auto-resume on EVERY session start (unattended rigs)",
|
|
2901
|
+
"off — never auto-resume; always wait for an explicit resume",
|
|
2902
|
+
]);
|
|
2903
|
+
if (v) saveSettings("global", ctx.cwd, { autoResume: v.startsWith("on") ? true : v.startsWith("off") ? false : undefined });
|
|
2904
|
+
} else if (choice.startsWith("Auto-accept drafts")) {
|
|
2905
|
+
const v = await ctx.ui.select("Auto-accept goal/loop drafts", [
|
|
2906
|
+
"off — the Confirm dialog gates every draft",
|
|
2907
|
+
"on — drafts activate immediately, no Confirm (unattended rigs)",
|
|
2908
|
+
]);
|
|
2909
|
+
if (v) saveSettings("global", ctx.cwd, { autoAcceptDrafts: v.startsWith("on") ? true : undefined });
|
|
2910
|
+
} else if (choice.startsWith("Aggressive mode")) {
|
|
2911
|
+
const v = await ctx.ui.select("Aggressive mode (flips DEFAULTS toward keep-going — explicit per-key settings still win)", [
|
|
2912
|
+
"off — current behavior: pause at the audit cap, wedge alerts on, manual resume",
|
|
2913
|
+
"on — autoResume, audit cap 10, stuck max 10, wedge alerts off, quota auto-retry, cap disapprovals become a TODO list and the goal KEEPS GOING",
|
|
2914
|
+
]);
|
|
2915
|
+
if (v) {
|
|
2916
|
+
saveSettings("global", ctx.cwd, { aggressiveMode: v.startsWith("on") });
|
|
2917
|
+
ctx.ui.notify(`Aggressive mode ${v.startsWith("on") ? "ON — goals keep going past the audit cap; objections become TODOs" : "off"}.`, "info");
|
|
2918
|
+
}
|
|
2919
|
+
} else if (choice.startsWith("Auditor model")) {
|
|
2882
2920
|
const v = await ctx.ui.input("Auditor model override", "provider/model-id — empty keeps the pi session model");
|
|
2883
2921
|
if (v !== undefined) saveSettings("global", ctx.cwd, { auditorModel: v.trim() || undefined });
|
|
2884
2922
|
} else if (choice.startsWith("Auditor thinking")) {
|
|
2885
2923
|
const v = await ctx.ui.select("Auditor thinking level", ["off", "minimal", "low", "medium", "high", "xhigh"]);
|
|
2886
2924
|
if (v) saveSettings("global", ctx.cwd, { auditorThinkingLevel: v as Settings["auditorThinkingLevel"] });
|
|
2887
|
-
} else if (choice.startsWith("
|
|
2888
|
-
const v = await ctx.ui.input("
|
|
2889
|
-
if (v !== undefined) saveSettings("global", ctx.cwd, { notifyCmd: v.trim() || undefined });
|
|
2890
|
-
} else if (choice.startsWith("Token limit")) {
|
|
2891
|
-
const v = await ctx.ui.input("Per-goal token budget", "non-negative integer; 0 or empty = off (no cap)");
|
|
2925
|
+
} else if (choice.startsWith("Audit cap")) {
|
|
2926
|
+
const v = await ctx.ui.input("Consecutive auditor disapprovals before the goal pauses", "non-negative integer; 0 = unlimited, empty = default 5");
|
|
2892
2927
|
if (v !== undefined) {
|
|
2893
2928
|
const n = Number.parseInt(v.trim(), 10);
|
|
2894
|
-
if (Number.isFinite(n) && n >= 0) saveSettings("global", ctx.cwd, {
|
|
2895
|
-
else if (!v.trim()) saveSettings("global", ctx.cwd, {
|
|
2929
|
+
if (Number.isFinite(n) && n >= 0) saveSettings("global", ctx.cwd, { auditCap: n });
|
|
2930
|
+
else if (!v.trim()) saveSettings("global", ctx.cwd, { auditCap: undefined });
|
|
2896
2931
|
else ctx.ui.notify(`Not a non-negative integer: ${v}`, "warning");
|
|
2897
2932
|
}
|
|
2898
|
-
} else if (choice.startsWith("
|
|
2899
|
-
const v = await ctx.ui.input("
|
|
2933
|
+
} else if (choice.startsWith("Audit feedback")) {
|
|
2934
|
+
const v = await ctx.ui.input("Auditor feedback returned to the executor (characters)", "non-negative integer cap; 0 or empty = full report (default)");
|
|
2900
2935
|
if (v !== undefined) {
|
|
2901
|
-
const
|
|
2902
|
-
|
|
2903
|
-
|
|
2936
|
+
const raw = v.trim();
|
|
2937
|
+
const n = Number(raw);
|
|
2938
|
+
if (/^\d+$/.test(raw) && Number.isSafeInteger(n)) saveSettings("global", ctx.cwd, { auditFeedbackChars: n });
|
|
2939
|
+
else if (!v.trim()) saveSettings("global", ctx.cwd, { auditFeedbackChars: undefined });
|
|
2904
2940
|
else ctx.ui.notify(`Not a non-negative integer: ${v}`, "warning");
|
|
2905
2941
|
}
|
|
2906
|
-
} else if (choice.startsWith("Aggressive mode")) {
|
|
2907
|
-
const v = await ctx.ui.select("Aggressive mode (flips DEFAULTS toward keep-going — explicit per-key settings still win)", [
|
|
2908
|
-
"off — current behavior: pause at the audit cap, wedge alerts on, manual resume",
|
|
2909
|
-
"on — autoResume, audit cap 10, stuck max 10, wedge alerts off, quota auto-retry, cap disapprovals become a TODO list and the goal KEEPS GOING",
|
|
2910
|
-
]);
|
|
2911
|
-
if (v) {
|
|
2912
|
-
saveSettings("global", ctx.cwd, { aggressiveMode: v.startsWith("on") });
|
|
2913
|
-
ctx.ui.notify(`Aggressive mode ${v.startsWith("on") ? "ON — goals keep going past the audit cap; objections become TODOs" : "off"}.`, "info");
|
|
2914
|
-
}
|
|
2915
2942
|
} else if (choice.startsWith("Quota retry minutes")) {
|
|
2916
2943
|
const v = await ctx.ui.input("Minutes before auto-retrying a quota-exhausted auditor", `positive integer; empty = default ${DEFAULT_QUOTA_RETRY_MINUTES}`);
|
|
2917
2944
|
if (v !== undefined) {
|
|
@@ -2920,6 +2947,14 @@ async function openSettingsUI(ctx: ExtensionContext): Promise<void> {
|
|
|
2920
2947
|
else if (!v.trim()) saveSettings("global", ctx.cwd, { quotaRetryMinutes: undefined });
|
|
2921
2948
|
else ctx.ui.notify(`Not a positive integer: ${v}`, "warning");
|
|
2922
2949
|
}
|
|
2950
|
+
} else if (choice.startsWith("Wedge alert")) {
|
|
2951
|
+
const v = await ctx.ui.input("Wedge alert threshold (minutes)", "non-negative integer; 0 = off, empty = default 30");
|
|
2952
|
+
if (v !== undefined) {
|
|
2953
|
+
const n = Number.parseInt(v.trim(), 10);
|
|
2954
|
+
if (Number.isFinite(n) && n >= 0) saveSettings("global", ctx.cwd, { wedgeAlertMinutes: n });
|
|
2955
|
+
else if (!v.trim()) saveSettings("global", ctx.cwd, { wedgeAlertMinutes: undefined });
|
|
2956
|
+
else ctx.ui.notify(`Not a non-negative integer: ${v}`, "warning");
|
|
2957
|
+
}
|
|
2923
2958
|
} else if (choice.startsWith("Stuck max interventions")) {
|
|
2924
2959
|
const v = await ctx.ui.input("Consecutive stuck interventions before a loop stops", "positive integer; empty = default 5 (10 under aggressiveMode)");
|
|
2925
2960
|
if (v !== undefined) {
|
|
@@ -2928,6 +2963,14 @@ async function openSettingsUI(ctx: ExtensionContext): Promise<void> {
|
|
|
2928
2963
|
else if (!v.trim()) saveSettings("global", ctx.cwd, { stuckMaxInterventions: undefined });
|
|
2929
2964
|
else ctx.ui.notify(`Not a positive integer: ${v}`, "warning");
|
|
2930
2965
|
}
|
|
2966
|
+
} else if (choice.startsWith("Stall escalation")) {
|
|
2967
|
+
const v = await ctx.ui.input("Heartbeat refires without a turn before the goal pauses / loop stops", "non-negative integer; 0 = never escalate, empty = default 5");
|
|
2968
|
+
if (v !== undefined) {
|
|
2969
|
+
const n = Number.parseInt(v.trim(), 10);
|
|
2970
|
+
if (Number.isFinite(n) && n >= 0) saveSettings("global", ctx.cwd, { stallEscalationRefires: n });
|
|
2971
|
+
else if (!v.trim()) saveSettings("global", ctx.cwd, { stallEscalationRefires: undefined });
|
|
2972
|
+
else ctx.ui.notify(`Not a non-negative integer: ${v}`, "warning");
|
|
2973
|
+
}
|
|
2931
2974
|
} else if (choice.startsWith("Subagent model strategy")) {
|
|
2932
2975
|
const v = await ctx.ui.select("Subagent model (pi-subagents default agents)", [
|
|
2933
2976
|
"inherit-parent — subagents share your session model + its quota pool (fixes separate-provider 403s; search agents may run on a pricier model)",
|
|
@@ -2938,8 +2981,8 @@ async function openSettingsUI(ctx: ExtensionContext): Promise<void> {
|
|
|
2938
2981
|
saveSettings("global", ctx.cwd, { subagentModelStrategy: strategy });
|
|
2939
2982
|
ctx.ui.notify("Subagent model strategy saved — applies to NEW pi sessions (pi-subagents registers agents at session start).", "info");
|
|
2940
2983
|
}
|
|
2941
|
-
} else if (/^Subagent (Explore|Plan|general-purpose)
|
|
2942
|
-
const agentType = choice.match(/^Subagent (Explore|Plan|general-purpose)
|
|
2984
|
+
} else if (/^Subagent (Explore|Plan|general-purpose) pin/.test(choice)) {
|
|
2985
|
+
const agentType = choice.match(/^Subagent (Explore|Plan|general-purpose) pin/)![1]!;
|
|
2943
2986
|
const v = await ctx.ui.input(`Model pin for ${agentType} subagents`, "provider/model-id e.g. minimax/MiniMax-M3 — always wins over strategy; empty = follow strategy");
|
|
2944
2987
|
if (v !== undefined) {
|
|
2945
2988
|
const current = loadSettings(ctx.cwd).subagentModelOverrides ?? {};
|
|
@@ -2949,15 +2992,19 @@ async function openSettingsUI(ctx: ExtensionContext): Promise<void> {
|
|
|
2949
2992
|
saveSettings("global", ctx.cwd, { subagentModelOverrides: Object.keys(next).length > 0 ? next : undefined });
|
|
2950
2993
|
ctx.ui.notify(`${agentType} model pin saved — applies to NEW pi sessions.`, "info");
|
|
2951
2994
|
}
|
|
2952
|
-
} else if (choice.startsWith("
|
|
2953
|
-
const v = await ctx.ui.input("
|
|
2995
|
+
} else if (choice.startsWith("Notify command")) {
|
|
2996
|
+
const v = await ctx.ui.input("Notify command — the event message is passed as $1", "e.g. a desktop-notification or push command; empty = off");
|
|
2997
|
+
if (v !== undefined) saveSettings("global", ctx.cwd, { notifyCmd: v.trim() || undefined });
|
|
2998
|
+
} else if (choice.startsWith("Token limit")) {
|
|
2999
|
+
const v = await ctx.ui.input("Per-goal token budget", "non-negative integer; 0 or empty = off (no cap)");
|
|
2954
3000
|
if (v !== undefined) {
|
|
2955
|
-
const
|
|
2956
|
-
|
|
2957
|
-
if (
|
|
2958
|
-
else if (!v.trim()) saveSettings("global", ctx.cwd, { auditFeedbackChars: undefined });
|
|
3001
|
+
const n = Number.parseInt(v.trim(), 10);
|
|
3002
|
+
if (Number.isFinite(n) && n >= 0) saveSettings("global", ctx.cwd, { tokenLimit: n });
|
|
3003
|
+
else if (!v.trim()) saveSettings("global", ctx.cwd, { tokenLimit: undefined });
|
|
2959
3004
|
else ctx.ui.notify(`Not a non-negative integer: ${v}`, "warning");
|
|
2960
3005
|
}
|
|
3006
|
+
} else if (choice.startsWith("Reviewer config")) {
|
|
3007
|
+
await cmdReviewerSettings(ctx);
|
|
2961
3008
|
}
|
|
2962
3009
|
} catch {
|
|
2963
3010
|
return;
|
|
@@ -3161,6 +3208,8 @@ async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
3161
3208
|
fmt("aggressiveMode", "aggressiveMode"),
|
|
3162
3209
|
fmt("quotaRetryMinutes", "quotaRetryMinutes"),
|
|
3163
3210
|
fmt("stuckMaxInterventions", "stuckMaxInterventions"),
|
|
3211
|
+
fmt("stallEscalationRefires", "stallEscalation"),
|
|
3212
|
+
fmt("wedgeAlertMinutes", "wedgeAlert"),
|
|
3164
3213
|
// v0.25.6: effective per-type subagent model resolution.
|
|
3165
3214
|
...["Explore", "Plan", "general-purpose"].map(
|
|
3166
3215
|
(t) => `subagent ${t}: ${resolveEffectiveSubagentModel(t, loadSettings(ctx.cwd), (ctx.model as any)?.id ? `${(ctx.model as any).provider}/${(ctx.model as any).id}` : undefined)}`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Goal. Loop. Audit. Done. — 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 — only the read tools needed to verify your goal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "dracon",
|