pi-goal-list-loop-audit 0.19.0 → 0.19.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.
@@ -202,7 +202,7 @@ export function parseListImport(content: string): string[] {
202
202
  }
203
203
 
204
204
  /**
205
- * During a LIST drafting session the agent must not queue items one by one
205
+ * During a LIST drafting session the agent must not add items one by one
206
206
  * with list_add/list_activate — that bypasses the user's Confirm gate
207
207
  * (observed in the wild: the agent decomposed a dump and ACTIVATED the first
208
208
  * item with zero confirmation). The batch path is propose_goal_draft's
@@ -214,7 +214,7 @@ export function listMutationBlocked(draftingTarget: string | null): boolean {
214
214
  }
215
215
 
216
216
  export const LIST_DRAFTING_BLOCK_MESSAGE =
217
- "LIST DRAFTING IN PROGRESS — do not queue items one by one. Decompose the request into an items[] array and call propose_goal_draft ONCE: the user confirms the whole batch in a single dialog. list_add / list_activate work again after the drafting session ends.";
217
+ "LIST DRAFTING IN PROGRESS — do not add items one by one. Decompose the request into an items[] array and call propose_goal_draft ONCE: the user confirms the whole batch in a single dialog. list_add / list_activate work again after the drafting session ends.";
218
218
 
219
219
  /**
220
220
  * Route natural-language text handed to `/list` with no subcommand verb
@@ -67,7 +67,7 @@ export function buildStatusText(state: State, audit?: AuditDisplayProgress | nul
67
67
  if (g.status === "active") {
68
68
  const queue = state.list?.length ? ` · list ${state.list.length}` : "";
69
69
  const tasks = g.taskList ? ` ${countDone(g)}/${countTotal(g)} tasks ·` : "";
70
- return `glla: goal ●${tasks} ${fmtElapsed(now - Date.parse(g.createdAt))}${queue}`;
70
+ return `glla: ${g.policy} ●${tasks} ${fmtElapsed(now - Date.parse(g.createdAt))}${queue}`;
71
71
  }
72
72
  return undefined; // complete/aborted → clear
73
73
  }
@@ -431,7 +431,7 @@ async function startDrafting(ctx: ExtensionContext, target: "goal" | "list" | "l
431
431
  draftingTarget = target;
432
432
  const prompts: Record<string, [string, string, string]> = {
433
433
  goal: ["goal-loop-draft.md", "Goal drafting", "propose_goal_draft"],
434
- list: ["goal-loop-draft.md", "Goal drafting (for the queue)", "propose_goal_draft"],
434
+ list: ["goal-loop-draft.md", "Goal drafting (for the list)", "propose_goal_draft"],
435
435
  loop: ["goal-loop-forever-draft.md", "Loop drafting", "propose_loop_draft"],
436
436
  };
437
437
  const [file, label, tool] = prompts[target]!;
@@ -729,7 +729,7 @@ async function cmdList(args: string, ctx: ExtensionContext): Promise<void> {
729
729
  if (queue.length === 0) {
730
730
  lines.push("List: empty. /list <describe your tasks, or a plan file> — the agent shapes dumps into items, files import directly.");
731
731
  } else {
732
- lines.push(`Queue (${queue.length}):`);
732
+ lines.push(`List (${queue.length}):`);
733
733
  const PAGE = 15;
734
734
  queue.slice(0, PAGE).forEach((item, i) => lines.push(` ${i + 1}. ${item.objective.slice(0, 90)}`));
735
735
  if (queue.length > PAGE) {
@@ -1491,7 +1491,7 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1491
1491
  const wasIdle = !state.goal || state.goal.status === "complete" || state.goal.status === "aborted";
1492
1492
  const n = enqueueItems(liveCtx, p.items, "drafted batch");
1493
1493
  if (wasIdle) {
1494
- return { content: [{ type: "text", text: `${n} items confirmed; first activated (queue was empty). Begin work now.` }], details: {} };
1494
+ return { content: [{ type: "text", text: `${n} items confirmed; first activated (list was empty). Begin work now.` }], details: {} };
1495
1495
  }
1496
1496
  return { content: [{ type: "text", text: `${n} items confirmed and queued (${listQueue().length} waiting).` }], details: {} };
1497
1497
  }
@@ -1522,7 +1522,7 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1522
1522
  appendLedger(liveCtx.cwd, "list_added", { id: item.id, objective: item.objective, drafted: true });
1523
1523
  if (!state.goal || state.goal.status === "complete" || state.goal.status === "aborted") {
1524
1524
  activateNextListItem(liveCtx);
1525
- return { content: [{ type: "text", text: "Confirmed and activated (queue was empty). Begin work now." }], details: {} };
1525
+ return { content: [{ type: "text", text: "Confirmed and activated (list was empty). Begin work now." }], details: {} };
1526
1526
  }
1527
1527
  return { content: [{ type: "text", text: `Confirmed and queued (${listQueue().length} waiting). It activates when the current goal completes.` }], details: {} };
1528
1528
  }
@@ -1701,9 +1701,9 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1701
1701
  pi.registerTool(defineTool({
1702
1702
  name: "list_add",
1703
1703
  label: "Add to queue",
1704
- description: "Add one or many objectives to the /list list (loop 2). Use when the user asks to queue work — 'add these to my list', 'queue these 10 things', 'put this on the backlog'. Each item becomes an audited goal; per-item 'Done when:' clauses are honored. The first queued item activates automatically when nothing is running.",
1704
+ description: "Add one or many objectives to the /list list (loop 2). Use when the user asks to queue work — 'add these to my list', 'queue these 10 things', 'put this on the backlog'. Each item becomes an audited goal; per-item 'Done when:' clauses are honored. The first queued item activates automatically when nothing is running. The list is UNBOUNDED — hundreds of small items are fine; propose them all.",
1705
1705
  parameters: Type.Object({
1706
- items: Type.Array(Type.String(), { description: "Objectives to enqueue (1-100). Each may include its own 'Done when:' clause." }),
1706
+ items: Type.Array(Type.String(), { description: "Objectives to enqueue no count limit; large plans belong in ONE call." }),
1707
1707
  }),
1708
1708
  async execute(_id, params, _signal, _onUpdate, execCtx) {
1709
1709
  const p = params as { items: string[] };
@@ -1713,9 +1713,6 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1713
1713
  if (!Array.isArray(p.items) || p.items.length === 0) {
1714
1714
  return { content: [{ type: "text", text: "No items given." }], details: {} };
1715
1715
  }
1716
- if (p.items.length > 100) {
1717
- return { content: [{ type: "text", text: `Too many items at once (${p.items.length}); max 100 per call — batch larger plans across calls.` }], details: {} };
1718
- }
1719
1716
  const clean = p.items.map((t) => t.trim()).filter((t) => t.length > 0);
1720
1717
  const liveCtx = (execCtx as ExtensionContext | undefined) ?? ctx;
1721
1718
  const wasIdle = !state.goal || state.goal.status === "complete" || state.goal.status === "aborted";
@@ -1775,7 +1772,7 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1775
1772
  if (queue.length === 0) {
1776
1773
  lines.push("List: empty.");
1777
1774
  } else {
1778
- lines.push(`Queue (${queue.length}):`);
1775
+ lines.push(`List (${queue.length}):`);
1779
1776
  queue.slice(0, 20).forEach((item, i) => lines.push(`${i + 1}. ${item.objective}`));
1780
1777
  if (queue.length > 20) lines.push(`… and ${queue.length - 20} more`);
1781
1778
  }
@@ -1955,20 +1952,20 @@ function resolveAuditorModel(ctx: ExtensionContext, ref?: string): { model: any;
1955
1952
  }
1956
1953
  const sessionModel = ctx.model as any;
1957
1954
  if (sessionModel) return { model: sessionModel, via: "session" };
1958
- return { model: undefined, error: "no session model and no auditorModel configured — set one with /gla model=provider/id" };
1955
+ return { model: undefined, error: "no session model and no auditorModel configured — set one with /glla model=provider/id" };
1959
1956
  }
1960
1957
 
1961
1958
  // (v0.9.12) The auto-fallback apparatus was REMOVED: no tier ranking, no
1962
1959
  // candidate chains, no dead-model caches. The plugin never picks a model —
1963
- // you select it in pi (session model) or in /gla (explicit override). When
1960
+ // you select it in pi (session model) or in /glla (explicit override). When
1964
1961
  // neither works, the failure surfaces plainly (see the three-way split in
1965
1962
  // the complete_goal handler) with the exact fix; nothing is substituted
1966
1963
  // silently.
1967
1964
 
1968
1965
  /**
1969
- * The /gla interactive settings UI (v0.8.0): a menu loop over pi's dialog
1966
+ * The /glla interactive settings UI (v0.8.0): a menu loop over pi's dialog
1970
1967
  * primitives. Pick a setting → edit it → saved to GLOBAL → back to the menu.
1971
- * Done/Esc exits. Rarely opened by design; scriptable /gla key=value remains
1968
+ * Done/Esc exits. Rarely opened by design; scriptable /glla key=value remains
1972
1969
  * for tmux/headless.
1973
1970
  */
1974
1971
  async function openSettingsUI(ctx: ExtensionContext): Promise<void> {
@@ -2022,13 +2019,13 @@ async function openSettingsUI(ctx: ExtensionContext): Promise<void> {
2022
2019
 
2023
2020
  async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
2024
2021
  // The plugin's ONE config surface — global by default, rarely opened.
2025
- // /gla show effective values + where each comes from
2026
- // /gla model=provider/id write to GLOBAL config
2027
- // /gla thinking=high write to GLOBAL config
2028
- // /gla notify='cmd $1' write to GLOBAL config
2029
- // /gla tokenlimit=2000000 write to GLOBAL config
2030
- // /gla project model=... write to PROJECT override (rare)
2031
- // /gla model=unset remove key (from global; project model=unset for project)
2022
+ // /glla show effective values + where each comes from
2023
+ // /glla model=provider/id write to GLOBAL config
2024
+ // /glla thinking=high write to GLOBAL config
2025
+ // /glla notify='cmd $1' write to GLOBAL config
2026
+ // /glla tokenlimit=2000000 write to GLOBAL config
2027
+ // /glla project model=... write to PROJECT override (rare)
2028
+ // /glla model=unset remove key (from global; project model=unset for project)
2032
2029
  const trimmed = args.trim();
2033
2030
  if (!trimmed) {
2034
2031
  if (ctx.hasUI) {
@@ -2050,7 +2047,7 @@ async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
2050
2047
  fmt("tokenLimit", "tokenLimit"),
2051
2048
  `\nglobal: ${globalSettingsPath()}`,
2052
2049
  `project: ${projectSettingsPath(ctx.cwd)}`,
2053
- `Set with: /gla key=value (global) · /gla project key=value (project override)`,
2050
+ `Set with: /glla key=value (global) · /glla project key=value (project override)`,
2054
2051
  ].join("\n"),
2055
2052
  "info",
2056
2053
  );
@@ -2140,7 +2137,7 @@ function warnIfAuditorProviderRisky(ctx: ExtensionContext): void {
2140
2137
  const provider = (ctx.model as any)?.provider as string | undefined;
2141
2138
  if (!provider || KNOWN_BUILTIN_PROVIDERS.has(provider)) return;
2142
2139
  ctx.ui.notify(
2143
- `pi-goal-list-loop-audit: session provider "${provider}" is extension-registered — the auditor (extension-less session) will fail auth with it. If audits error, set a built-in override once: /gla model=provider/id`,
2140
+ `pi-goal-list-loop-audit: session provider "${provider}" is extension-registered — the auditor (extension-less session) will fail auth with it. If audits error, set a built-in override once: /glla model=provider/id`,
2144
2141
  "info",
2145
2142
  );
2146
2143
  } catch {
@@ -2185,7 +2182,7 @@ export default function (pi: ExtensionAPI): void {
2185
2182
  // /goal — set/draft + status|pause|resume|cancel|tweak|archive subcommands
2186
2183
  // /list — the list (add|show|next|remove|clear)
2187
2184
  // /loop — the metric loop (draft|start|status|stop)
2188
- // /gla — the settings UI (+ scriptable key=value)
2185
+ // /glla — the settings UI (+ scriptable key=value)
2189
2186
  pi.registerCommand("goal", {
2190
2187
  description: "Set/draft a goal, or /goal status|pause|resume|cancel|tweak <text>|archive|start <objective>. Objectives without a 'Done when:' clause are grilled into a contract first; include the clause or use /goal start to skip the interview and activate instantly.",
2191
2188
  handler: (args: string, ctx: ExtensionContext) => { rememberCtx(ctx); return cmdGoal(args, ctx); },
@@ -2314,7 +2311,7 @@ export default function (pi: ExtensionAPI): void {
2314
2311
 
2315
2312
  // Token accounting + cost guard: accumulate this turn's assistant tokens
2316
2313
  // (deduped — agent_end may replay seen messages). Crossing the goal's
2317
- // token limit pauses it; /gla tokenlimit=<n> to raise.
2314
+ // token limit pauses it; /glla tokenlimit=<n> to raise.
2318
2315
  const newTokens = sumNewAssistantTokens(event.messages as unknown[], countedTokenMessages);
2319
2316
  if (newTokens > 0) {
2320
2317
  const used = (state.goal.usage?.tokensUsed ?? 0) + newTokens;
@@ -2325,9 +2322,9 @@ export default function (pi: ExtensionAPI): void {
2325
2322
  usage: { tokensUsed: used, tokensLimit: limit },
2326
2323
  status: "paused",
2327
2324
  pauseReason: `token limit exceeded (${used.toLocaleString()} > ${limit.toLocaleString()})`,
2328
- pauseSuggestedAction: "/gla tokenlimit=<n> to raise the cap (or 0 to disable), then /goal resume",
2325
+ pauseSuggestedAction: "/glla tokenlimit=<n> to raise the cap (or 0 to disable), then /goal resume",
2329
2326
  }, ctx);
2330
- ctx.ui.notify(`Goal paused: token limit exceeded (${used.toLocaleString()} > ${limit.toLocaleString()}). /gla tokenlimit=<n> to raise, 0 to disable.`, "warning");
2327
+ ctx.ui.notify(`Goal paused: token limit exceeded (${used.toLocaleString()} > ${limit.toLocaleString()}). /glla tokenlimit=<n> to raise, 0 to disable.`, "warning");
2331
2328
  notifyExternal(ctx, `Goal paused: token limit exceeded (${used} > ${limit}).`);
2332
2329
  return;
2333
2330
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.19.0",
3
+ "version": "0.19.2",
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",