pi-goal-list-loop-audit 0.18.0 → 0.18.1

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.
@@ -201,6 +201,21 @@ export function parseListImport(content: string): string[] {
201
201
  return items;
202
202
  }
203
203
 
204
+ /**
205
+ * During a LIST drafting session the agent must not queue items one by one
206
+ * with list_add/list_activate — that bypasses the user's Confirm gate
207
+ * (observed in the wild: the agent decomposed a dump and ACTIVATED the first
208
+ * item with zero confirmation). The batch path is propose_goal_draft's
209
+ * items[]: one Confirm for the whole list. User commands (/list add) are
210
+ * unaffected — only the agent tools are gated.
211
+ */
212
+ export function listMutationBlocked(draftingTarget: string | null): boolean {
213
+ return draftingTarget === "list";
214
+ }
215
+
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.";
218
+
204
219
  /**
205
220
  * Route natural-language text handed to `/list` with no subcommand verb
206
221
  * (v0.18.0). The user typed a dump — "fix x, do y, write docs" — not a
@@ -36,6 +36,8 @@ import {
36
36
  resolveImportFile,
37
37
  routeGoalArgs,
38
38
  routeListText,
39
+ listMutationBlocked,
40
+ LIST_DRAFTING_BLOCK_MESSAGE,
39
41
  sumNewAssistantTokens,
40
42
  takeAt,
41
43
  goalArgsNeedDrafting,
@@ -1715,6 +1717,9 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1715
1717
  }),
1716
1718
  async execute(_id, params, _signal, _onUpdate, execCtx) {
1717
1719
  const p = params as { items: string[] };
1720
+ if (listMutationBlocked(draftingTarget)) {
1721
+ return { content: [{ type: "text", text: LIST_DRAFTING_BLOCK_MESSAGE }], details: {} };
1722
+ }
1718
1723
  if (!Array.isArray(p.items) || p.items.length === 0) {
1719
1724
  return { content: [{ type: "text", text: "No items given." }], details: {} };
1720
1725
  }
@@ -1746,6 +1751,9 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1746
1751
  }),
1747
1752
  async execute(_id, params, _signal, _onUpdate, execCtx) {
1748
1753
  const p = params as { n: number };
1754
+ if (listMutationBlocked(draftingTarget)) {
1755
+ return { content: [{ type: "text", text: LIST_DRAFTING_BLOCK_MESSAGE }], details: {} };
1756
+ }
1749
1757
  const n = Math.floor(p.n);
1750
1758
  if (!Number.isInteger(n) || n < 1) {
1751
1759
  return { content: [{ type: "text", text: "n must be a positive integer (1-based position)." }], details: {} };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
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",