pi-goal-list-loop-audit 0.15.0 → 0.15.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.
- package/extensions/goal-loop-core.ts +22 -2
- package/extensions/loops/goal.ts +17 -2
- package/package.json +1 -1
|
@@ -275,9 +275,29 @@ export function buildSeedGrillMessage(tmpl: string, seed: string, tool: string):
|
|
|
275
275
|
* mechanism guarantees an interview HAPPENED; question quality is the
|
|
276
276
|
* model's job (shaped by buildSeedGrillMessage).
|
|
277
277
|
*/
|
|
278
|
-
export function draftProposalBlock(userReplies: number): string | null {
|
|
278
|
+
export function draftProposalBlock(userReplies: number, blockedAttempts = 0): string | null {
|
|
279
279
|
if (userReplies > 0) return null;
|
|
280
|
-
|
|
280
|
+
const base = "INTERVIEW FIRST — you have not received a single user reply since drafting started. Ask the user ONE sharp question about their objective (seed-specific, with a recommended default; challenge non-answers by offering concrete options), wait for the answer, and only then call the propose tool again. The Confirm dialog stays closed until the user has actually been heard.";
|
|
281
|
+
// v0.15.1 escape hatch: typed chat replies AND answered ask_user_question
|
|
282
|
+
// dialogs both count. If we have blocked 3+ proposals, the replies are
|
|
283
|
+
// arriving through a path this plugin cannot see — hand the user a manual
|
|
284
|
+
// unlock instead of manufacturing yet another interview round.
|
|
285
|
+
if (blockedAttempts >= 3) {
|
|
286
|
+
return base + " NOTE: proposals have been blocked repeatedly despite interviewing — the reply counter may not see your channel. Tell the user plainly: 'type any chat message (e.g. \"go on\") to unlock the Confirm dialog', wait for it, then propose again. Do NOT ask another interview question first.";
|
|
287
|
+
}
|
|
288
|
+
return base;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* v0.15.1: an ask_user_question tool result counts as a user reply during
|
|
293
|
+
* drafting — dialog answers arrive as tool results, not chat messages.
|
|
294
|
+
* Answered = not cancelled (Esc) with at least one answer recorded.
|
|
295
|
+
*/
|
|
296
|
+
export function askUserQuestionAnswered(toolName: string, details: unknown): boolean {
|
|
297
|
+
if (toolName !== "ask_user_question") return false;
|
|
298
|
+
if (!details || typeof details !== "object") return false;
|
|
299
|
+
const d = details as { answers?: unknown; cancelled?: unknown };
|
|
300
|
+
return d.cancelled === false && Array.isArray(d.answers) && d.answers.length > 0;
|
|
281
301
|
}
|
|
282
302
|
|
|
283
303
|
/**
|
package/extensions/loops/goal.ts
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
takeAt,
|
|
40
40
|
goalArgsNeedDrafting,
|
|
41
41
|
buildSeedGrillMessage,
|
|
42
|
+
askUserQuestionAnswered,
|
|
42
43
|
draftProposalBlock,
|
|
43
44
|
type TaskProposal,
|
|
44
45
|
validateTaskProposal,
|
|
@@ -110,6 +111,7 @@ let draftingTarget: "goal" | "list" | "loop" | null = null;
|
|
|
110
111
|
// v0.14.0 drafting floor: user replies counted while drafting; the injected
|
|
111
112
|
// seed prompt itself arrives as a user message — skip exactly that one.
|
|
112
113
|
let draftingUserReplies = 0;
|
|
114
|
+
let draftingBlockedProposals = 0; // v0.15.1: stuck-gate escape hatch
|
|
113
115
|
let draftingSeedInFlight = false;
|
|
114
116
|
|
|
115
117
|
// Dedup set for token accounting (agent_end may replay seen messages).
|
|
@@ -458,6 +460,7 @@ async function startDrafting(ctx: ExtensionContext, target: "goal" | "list" | "l
|
|
|
458
460
|
try {
|
|
459
461
|
extensionApi?.sendUserMessage(tmpl, { deliverAs: ctx.isIdle() ? "followUp" : "steer" });
|
|
460
462
|
draftingUserReplies = 0;
|
|
463
|
+
draftingBlockedProposals = 0;
|
|
461
464
|
draftingSeedInFlight = true; // our injected prompt also arrives as a user message — don't count it
|
|
462
465
|
} catch {
|
|
463
466
|
draftingTarget = null;
|
|
@@ -1420,7 +1423,9 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
|
|
|
1420
1423
|
};
|
|
1421
1424
|
}
|
|
1422
1425
|
// v0.14.0: the interview floor — no Confirm until the user replied.
|
|
1423
|
-
|
|
1426
|
+
// v0.14.0: the interview floor — no Confirm until the user replied.
|
|
1427
|
+
if (draftingUserReplies === 0) draftingBlockedProposals++;
|
|
1428
|
+
const block = draftProposalBlock(draftingUserReplies, draftingBlockedProposals);
|
|
1424
1429
|
if (block) {
|
|
1425
1430
|
return { content: [{ type: "text", text: block }], details: {} };
|
|
1426
1431
|
}
|
|
@@ -1525,7 +1530,8 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
|
|
|
1525
1530
|
};
|
|
1526
1531
|
}
|
|
1527
1532
|
// v0.14.0: the interview floor — no Confirm until the user replied.
|
|
1528
|
-
|
|
1533
|
+
if (draftingUserReplies === 0) draftingBlockedProposals++;
|
|
1534
|
+
const loopBlock = draftProposalBlock(draftingUserReplies, draftingBlockedProposals);
|
|
1529
1535
|
if (loopBlock) {
|
|
1530
1536
|
return { content: [{ type: "text", text: loopBlock }], details: {} };
|
|
1531
1537
|
}
|
|
@@ -2188,6 +2194,15 @@ export default function (pi: ExtensionAPI): void {
|
|
|
2188
2194
|
draftingUserReplies++;
|
|
2189
2195
|
});
|
|
2190
2196
|
|
|
2197
|
+
// v0.15.1: ask_user_question answers arrive as tool results, not chat
|
|
2198
|
+
// messages — count answered (non-cancelled) questionnaires as replies too.
|
|
2199
|
+
pi.on("tool_result", async (event: any) => {
|
|
2200
|
+
if (draftingTarget === null) return;
|
|
2201
|
+
if (askUserQuestionAnswered(String(event?.toolName ?? ""), event?.details)) {
|
|
2202
|
+
draftingUserReplies++;
|
|
2203
|
+
}
|
|
2204
|
+
});
|
|
2205
|
+
|
|
2191
2206
|
pi.on("session_start", async (_event: any, ctx: ExtensionContext) => {
|
|
2192
2207
|
rememberCtx(ctx);
|
|
2193
2208
|
state = readState(ctx.cwd);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.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",
|