pi-goal-list-loop-audit 0.26.8 → 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/README.md +1 -1
- package/extensions/goal-loop-core.ts +15 -10
- package/extensions/loops/goal.ts +107 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -199,7 +199,7 @@ No external watchdog plugin needed.
|
|
|
199
199
|
/glla tokenlimit=10000000 # per-goal token budget (default: off) → GLOBAL
|
|
200
200
|
/glla tokenlimit=0 # explicitly no cap (the default)
|
|
201
201
|
/glla wedgealert=30 # hung-command alert minutes (default: 30, 0 = off)
|
|
202
|
-
/glla autoresume=on #
|
|
202
|
+
/glla autoresume=on # auto-resume goals/loops on session LOAD too (default: hold on load, auto-resume on reload/fork; off: never)
|
|
203
203
|
/glla auditcap=5 # pause the goal after N consecutive auditor disapprovals (default 5, 0 = unlimited)
|
|
204
204
|
/glla aggressivemode=on # keep-going defaults: autoResume, cap 10, stuck 10, wedge off, quota auto-retry, cap→TODOs
|
|
205
205
|
/glla quotaretryminutes=60 # minutes before auto-retrying a quota-exhausted auditor
|
|
@@ -660,16 +660,21 @@ export function cloneGoal(goal: Goal): Goal {
|
|
|
660
660
|
* setting for unattended restarts). One mechanical predicate; no heuristics.
|
|
661
661
|
*/
|
|
662
662
|
export function shouldAutoResumeOnSessionStart(reason: string | undefined, autoResume: boolean | undefined): boolean {
|
|
663
|
-
// v0.26.
|
|
664
|
-
//
|
|
665
|
-
//
|
|
666
|
-
//
|
|
667
|
-
//
|
|
668
|
-
//
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
663
|
+
// v0.26.9 tri-state:
|
|
664
|
+
// true → auto-resume on EVERY session start (unattended rigs).
|
|
665
|
+
// false → never auto-resume; always hold for an explicit resume.
|
|
666
|
+
// undefined → DEFAULT: a human LOADING a session ("startup"/"new"/
|
|
667
|
+
// "resume", or old pi reporting no reason) must not trigger
|
|
668
|
+
// work — show the held popup, they resume explicitly.
|
|
669
|
+
// In-session MACHINERY ("reload"/"fork") auto-resumes so an
|
|
670
|
+
// extension reload or session fork never strands work.
|
|
671
|
+
// Mid-session continuation (agent_end chains, heartbeat refires,
|
|
672
|
+
// post-compaction, list/loop transitions) is not gated here at all — it
|
|
673
|
+
// auto-continues forever unless a super-stuck brake (stall escalation,
|
|
674
|
+
// stale-api terminal, pending-latch watchdog) stops it loudly.
|
|
675
|
+
if (autoResume === true) return true;
|
|
676
|
+
if (autoResume === false) return false;
|
|
677
|
+
return reason === "reload" || reason === "fork";
|
|
673
678
|
}
|
|
674
679
|
|
|
675
680
|
/**
|
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)}`,
|
|
@@ -3329,7 +3378,7 @@ async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
3329
3378
|
saveSettings(scope, ctx.cwd, patch);
|
|
3330
3379
|
const effective = loadSettings(ctx.cwd);
|
|
3331
3380
|
ctx.ui.notify(
|
|
3332
|
-
`Saved to ${scope} config. Effective now: model=${effective.auditorModel ?? "(session model)"} thinking=${effective.auditorThinkingLevel ?? "(session)"} notify=${effective.notifyCmd ?? "(off)"} tokenLimit=${effective.tokenLimit ?? 0}${(effective.tokenLimit ?? 0) > 0 ? "" : " (off)"} autoResume=${effective.autoResume === false ? "off" : "on
|
|
3381
|
+
`Saved to ${scope} config. Effective now: model=${effective.auditorModel ?? "(session model)"} thinking=${effective.auditorThinkingLevel ?? "(session)"} notify=${effective.notifyCmd ?? "(off)"} tokenLimit=${effective.tokenLimit ?? 0}${(effective.tokenLimit ?? 0) > 0 ? "" : " (off)"} autoResume=${effective.autoResume === true ? "on" : effective.autoResume === false ? "off" : "default (hold on load)"} auditFeedbackChars=${effective.auditFeedbackChars ?? DEFAULT_AUDIT_FEEDBACK_CHARS}${(effective.auditFeedbackChars ?? DEFAULT_AUDIT_FEEDBACK_CHARS) === 0 ? " (full report)" : ""}\n` +
|
|
3333
3382
|
`Note: the auditor runs without extensions — it must be a built-in provider, not an extension-registered one.`,
|
|
3334
3383
|
"info",
|
|
3335
3384
|
);
|
|
@@ -3444,7 +3493,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
3444
3493
|
["thinking=", "auditor thinking level: /glla thinking=high"],
|
|
3445
3494
|
["notify=", "desktop push command: /glla notify='notify-send pi \"$1\"'"],
|
|
3446
3495
|
["tokenlimit=", "per-goal token budget (0 = off): /glla tokenlimit=2000000"],
|
|
3447
|
-
["autoresume=", "
|
|
3496
|
+
["autoresume=", "default: hold when a session is loaded, auto-resume on reload/fork; on: always auto-resume; off: never"],
|
|
3448
3497
|
["auditcap=", "N: pause goal after N consecutive auditor disapprovals (default 5, 0 = unlimited)"],
|
|
3449
3498
|
["auditfeedbackchars=", "cap on executor-visible disapproval report chars (0 = full report, the default)"],
|
|
3450
3499
|
["aggressivemode=", "on: keep-going defaults — autoResume, cap 10, stuck 10, wedge off, quota auto-retry, cap→TODOs"],
|
|
@@ -3641,12 +3690,14 @@ export default function (pi: ExtensionAPI): void {
|
|
|
3641
3690
|
} catch (err) {
|
|
3642
3691
|
ctx.ui.notify(`glla subagent override sync failed: ${err instanceof Error ? err.message : String(err)}`, "warning");
|
|
3643
3692
|
}
|
|
3644
|
-
// Restore gate (v0.
|
|
3645
|
-
//
|
|
3646
|
-
//
|
|
3647
|
-
// /glla autoresume=
|
|
3648
|
-
//
|
|
3649
|
-
//
|
|
3693
|
+
// Restore gate (v0.26.9 tri-state): a human LOADING a session
|
|
3694
|
+
// ("startup"/"new"/"resume", or no reason) HOLDS — the popup shows what
|
|
3695
|
+
// is waiting and nothing starts until they resume explicitly. In-session
|
|
3696
|
+
// machinery ("reload"/"fork") auto-resumes. /glla autoresume=on opts a
|
|
3697
|
+
// project into auto-resume everywhere (unattended rigs); autoresume=off
|
|
3698
|
+
// never auto-resumes. Once running, the chain auto-continues forever
|
|
3699
|
+
// unless a super-stuck brake (stall escalation / stale-api / latch)
|
|
3700
|
+
// stops it loudly.
|
|
3650
3701
|
const autoResume = shouldAutoResumeOnSessionStart(event?.reason, resolveEffectiveAggressiveSettings(loadSettings(ctx.cwd)).autoResume);
|
|
3651
3702
|
// v0.25.0 (contract item 6): aggressiveMode announces every auto-event.
|
|
3652
3703
|
if (
|
|
@@ -3668,7 +3719,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
3668
3719
|
state.loop = { ...l, active: false, stopReason: HELD_ON_RESTORE };
|
|
3669
3720
|
persistState(ctx);
|
|
3670
3721
|
ctx.ui.notify(
|
|
3671
|
-
`Loop held on restore
|
|
3722
|
+
`Loop held on restore: ${l.target.slice(0, 60)} — /loop to resume, /glla autoresume=on to auto-resume on session load in this project.`,
|
|
3672
3723
|
"info",
|
|
3673
3724
|
);
|
|
3674
3725
|
}
|
|
@@ -3687,7 +3738,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
3687
3738
|
const resumeHint = `${resumeCmd} to continue${queued > 0 ? ` (+${queued} waiting in the list)` : ""} · /glla autoresume=on to auto-resume in this project`;
|
|
3688
3739
|
updateGoal({
|
|
3689
3740
|
status: "paused",
|
|
3690
|
-
pauseReason: "restored
|
|
3741
|
+
pauseReason: "restored on session load — held for explicit resume",
|
|
3691
3742
|
pauseSuggestedAction: resumeHint,
|
|
3692
3743
|
}, ctx);
|
|
3693
3744
|
ctx.ui.notify(
|
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",
|