pi-goal-list-loop-audit 0.28.6 → 0.28.7

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.
@@ -897,7 +897,12 @@ export interface EffectiveAggressiveSettings {
897
897
  stuckMaxInterventions: number;
898
898
  /** 0 = wedge alerts off. */
899
899
  wedgeAlertMinutes: number;
900
- autoResume: boolean;
900
+ /** Tri-state: true = always auto-resume; false = never; undefined =
901
+ * DEFAULT (hold on human session loads, resume on reload/fork).
902
+ * v0.28.7: must stay tri-state here — coercing unset→false broke the
903
+ * restore gate's default branch (the 0.28.3 regression the behavioral
904
+ * harness caught). */
905
+ autoResume: boolean | undefined;
901
906
  aggressiveMode: boolean;
902
907
  }
903
908
 
@@ -918,7 +923,7 @@ export function resolveEffectiveAggressiveSettings(s: {
918
923
  stuckMaxInterventions:
919
924
  s.stuckMaxInterventions ?? (aggressiveMode ? AGGRESSIVE_STUCK_MAX_INTERVENTIONS : BASE_STUCK_MAX_INTERVENTIONS),
920
925
  wedgeAlertMinutes: s.wedgeAlertMinutes ?? (aggressiveMode ? 0 : 30),
921
- autoResume: s.autoResume ?? aggressiveMode,
926
+ autoResume: s.autoResume ?? (aggressiveMode ? true : undefined),
922
927
  };
923
928
  }
924
929
 
@@ -224,6 +224,13 @@ function goStaleTerminal(ctx: ExtensionContext, where: string): void {
224
224
  notifyExternal(ctx, `glla: extension api stale — restart pi. (${where})`);
225
225
  }
226
226
 
227
+ /** TEST-ONLY hook (tests/harness): the stale flag is process-terminal in
228
+ * production — only a pi restart clears it — so behavioral tests reset it
229
+ * between stale scenarios. Never called by production code. */
230
+ export function __testOnlyResetStaleFlag(): void {
231
+ extensionApiStale = false;
232
+ }
233
+
227
234
  /** v0.28.1 (S3): side-effect-free staleness probe — getSessionName()
228
235
  * routes through pi's assertActive() and throws the stale signature iff
229
236
  * pi invalidated this factory handle (session replacement). A positive
@@ -2523,11 +2530,12 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
2523
2530
  pi.registerTool(defineTool({
2524
2531
  name: "complete_task",
2525
2532
  label: "Complete task",
2526
- description: "Mark a task in the active goal's task list as complete (does not stop the turn).",
2527
- parameters: Type.Object({
2533
+ description: "Mark a task in the active goal's task list as complete (does not stop the turn).", parameters: Type.Object({
2528
2534
  id: Type.String({ description: "Task id to complete" }),
2529
2535
  }),
2530
- async execute(_id, params) {
2536
+ async execute(_id, params, _signal, _onUpdate, execCtx) {
2537
+ const foreign7 = foreignToolGuard(execCtx);
2538
+ if (foreign7) return { content: [{ type: "text", text: foreign7 }], details: {} };
2531
2539
  const p = params as { id: string };
2532
2540
  if (!state.goal || !state.goal.taskList) {
2533
2541
  return { content: [{ type: "text", text: "No task list in this goal." }], details: {} };
@@ -2555,7 +2563,9 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
2555
2563
  id: Type.String(),
2556
2564
  status: Type.Union([Type.Literal("pending"), Type.Literal("in_progress"), Type.Literal("complete")]),
2557
2565
  }),
2558
- async execute(_id, params) {
2566
+ async execute(_id, params, _signal, _onUpdate, execCtx) {
2567
+ const foreign8 = foreignToolGuard(execCtx);
2568
+ if (foreign8) return { content: [{ type: "text", text: foreign8 }], details: {} };
2559
2569
  const p = params as { id: string; status: "pending" | "in_progress" | "complete" };
2560
2570
  if (!state.goal || !state.goal.taskList) {
2561
2571
  return { content: [{ type: "text", text: "No task list in this goal." }], details: {} };
@@ -3012,6 +3022,8 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
3012
3022
  })),
3013
3023
  }),
3014
3024
  async execute(_id, params, _signal, _onUpdate, execCtx) {
3025
+ const foreign9 = foreignToolGuard(execCtx);
3026
+ if (foreign9) return { content: [{ type: "text", text: foreign9 }], details: {} };
3015
3027
  if (!state.goal || state.goal.status !== "active") {
3016
3028
  return { content: [{ type: "text", text: "No active goal to break down." }], details: {} };
3017
3029
  }
@@ -3179,7 +3191,9 @@ async function promptSettingsMenu(
3179
3191
  * Same handlers as v0.27.0's if/else chain — only the trigger changed from
3180
3192
  * `startsWith(label)` strings to stable ids.
3181
3193
  */
3182
- async function handleSettingChoice(id: string, ctx: ExtensionContext): Promise<void> {
3194
+ // v0.28.7 (T4): exported for the behavioral settings-editor tests
3195
+ // (tests/settings-editors.test.ts drives each editor class end-to-end).
3196
+ export async function handleSettingChoice(id: string, ctx: ExtensionContext): Promise<void> {
3183
3197
  switch (id) {
3184
3198
  case "autoResume": {
3185
3199
  const v = await ctx.ui.select("Auto-resume goals/loops on session start", [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.28.6",
3
+ "version": "0.28.7",
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",