pi-goal-list-loop-audit 0.18.1 → 0.19.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/README.md +10 -10
- package/extensions/loops/goal.ts +26 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,11 +41,11 @@ Four top-level commands, that's all:
|
|
|
41
41
|
/goal tweak "<new objective>" # edit in place (Confirm dialog)
|
|
42
42
|
/goal archive # archived goals, newest first
|
|
43
43
|
/glla # open the settings UI (or /glla key=value)
|
|
44
|
-
/list fix the login bug, add dark mode, write docs # dump it — the agent
|
|
45
|
-
/list
|
|
46
|
-
/list
|
|
47
|
-
/list
|
|
48
|
-
/list add
|
|
44
|
+
/list fix the login bug, add dark mode, write docs # dump it — the agent shapes it into items, one Confirm
|
|
45
|
+
/list plan.md # file detected → bulk import, one Confirm (sisyphus/Ralph style)
|
|
46
|
+
/list <paste a checklist> # multi-line paste → same batch flow
|
|
47
|
+
/list "fix the flaky test. Done when: npm test green" # explicit contract → queues directly, no interview
|
|
48
|
+
/list # show the list (add/import are optional no-op aliases — detection routes everything)
|
|
49
49
|
|
|
50
50
|
(Or just say it: "queue these 10 things…" — the agent manages the list too.)
|
|
51
51
|
|
|
@@ -82,9 +82,9 @@ ONE confirmed batch, not 50 dialogs.
|
|
|
82
82
|
Note: every queue item is audited individually, so at hundreds of items the
|
|
83
83
|
audit cost per item is the thing to think about.
|
|
84
84
|
|
|
85
|
-
**Drafting is the default for long-running things.** `/goal
|
|
86
|
-
`/loop` with no arguments
|
|
87
|
-
dialog. For `/loop` specifically, the orchestrator **test-runs the proposed
|
|
85
|
+
**Drafting is the default for long-running things.** `/goal` and
|
|
86
|
+
`/loop` with no arguments — and any vague `/list` dump — all start a
|
|
87
|
+
grilling turn that ends in a Confirm dialog. For `/loop` specifically, the orchestrator **test-runs the proposed
|
|
88
88
|
measure command once** and shows the real number in the dialog — you validate
|
|
89
89
|
the metric before a single iteration burns tokens.
|
|
90
90
|
|
|
@@ -132,8 +132,8 @@ redirect you to `/goal`.
|
|
|
132
132
|
| Loop | Command | Status |
|
|
133
133
|
|---|---|---|
|
|
134
134
|
| 1. Single ordered goal | `/goal "<objective>"` | **shipped v0.1.0** |
|
|
135
|
-
| 2. Queue of goals | `/list
|
|
136
|
-
| 3.
|
|
135
|
+
| 2. Queue of goals | `/list [show\|next\|remove\|clear]` | **shipped v0.2.0** |
|
|
136
|
+
| 3. Metric-driven process loop | `/loop start\|status\|stop` | **shipped v0.3.0** |
|
|
137
137
|
|
|
138
138
|
Each loop is a different policy class on the same status machine.
|
|
139
139
|
|
package/extensions/loops/goal.ts
CHANGED
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
DEFAULT_TOKEN_LIMIT,
|
|
34
34
|
mergeSettings,
|
|
35
35
|
parseListImport,
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
routeGoalArgs,
|
|
38
38
|
routeListText,
|
|
39
39
|
listMutationBlocked,
|
|
@@ -437,7 +437,7 @@ async function startDrafting(ctx: ExtensionContext, target: "goal" | "list" | "l
|
|
|
437
437
|
const [file, label, tool] = prompts[target]!;
|
|
438
438
|
ctx.ui.notify(
|
|
439
439
|
seed
|
|
440
|
-
? `${label}: the objective has no "Done when:" clause — the agent will grill you about it first (nothing activates until you confirm).
|
|
440
|
+
? `${label}: the objective has no "Done when:" clause — the agent will grill you about it first (nothing activates until you confirm). ${target === "list" ? "Add directly instead: include a \"Done when:\" clause." : "Skip the interview entirely: /goal start <objective>."}`
|
|
441
441
|
: `${label} started. The agent will grill until the contract is concrete, then ${tool} opens a Confirm dialog. No work begins before confirmation.`,
|
|
442
442
|
"info",
|
|
443
443
|
);
|
|
@@ -727,7 +727,7 @@ async function cmdList(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
727
727
|
lines.push("Active: (none)");
|
|
728
728
|
}
|
|
729
729
|
if (queue.length === 0) {
|
|
730
|
-
lines.push("List: empty. /list <describe your tasks>
|
|
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
732
|
lines.push(`Queue (${queue.length}):`);
|
|
733
733
|
const PAGE = 15;
|
|
@@ -741,43 +741,33 @@ async function cmdList(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
741
741
|
}
|
|
742
742
|
|
|
743
743
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
744
|
+
// v0.19.0: `add` and `import` are pure no-op aliases — the verb changes
|
|
745
|
+
// nothing, detection routes everything. `/list plan.md` and
|
|
746
|
+
// `/list add plan.md` both import; `/list fix x, do y` and
|
|
747
|
+
// `/list add fix x, do y` both draft. Rationale: a list item activates
|
|
748
|
+
// RAW when it reaches the head, so the drafting interview is the only
|
|
749
|
+
// quality gate an item ever gets — a verb whose only job was skipping
|
|
750
|
+
// that gate was a leak, not an escape hatch. The direct path is an
|
|
751
|
+
// explicit "Done when:" clause (user already did the contract work).
|
|
752
|
+
if (sub === "add" || sub === "import") {
|
|
753
|
+
if (!rest) {
|
|
754
|
+
await startDrafting(ctx, "list");
|
|
749
755
|
return;
|
|
750
756
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
if (sub === "add") {
|
|
756
|
-
let raw = rest;
|
|
757
|
-
if (raw.length >= 2 && ((raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'")))) {
|
|
758
|
-
raw = raw.slice(1, -1).trim();
|
|
759
|
-
}
|
|
760
|
-
if (!raw) {
|
|
761
|
-
// /list add with no args → draft a confirmed contract INTO THE QUEUE.
|
|
762
|
-
await startDrafting(ctx, "list");
|
|
757
|
+
const aliased = routeListText(ctx.cwd, rest.replace(/^["']|["']$/g, ""));
|
|
758
|
+
if (aliased.kind === "file") {
|
|
759
|
+
await bulkAddFromFile(ctx, aliased.path);
|
|
763
760
|
return;
|
|
764
761
|
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
// ITEM — no interview. The conversational path is bare /list <text>.
|
|
768
|
-
const importFile = resolveImportFile(ctx.cwd, raw);
|
|
769
|
-
if (importFile) {
|
|
770
|
-
await bulkAddFromFile(ctx, importFile);
|
|
762
|
+
if (aliased.kind === "batch") {
|
|
763
|
+
await bulkAddItems(ctx, aliased.items, "pasted text");
|
|
771
764
|
return;
|
|
772
765
|
}
|
|
773
|
-
if (
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
await bulkAddItems(ctx, pasted, "pasted text");
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
766
|
+
if (aliased.kind === "direct") {
|
|
767
|
+
addSingleItem(ctx, aliased.text);
|
|
768
|
+
return;
|
|
779
769
|
}
|
|
780
|
-
|
|
770
|
+
await startDrafting(ctx, "list", aliased.seed);
|
|
781
771
|
return;
|
|
782
772
|
}
|
|
783
773
|
|
|
@@ -1711,9 +1701,9 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
|
|
|
1711
1701
|
pi.registerTool(defineTool({
|
|
1712
1702
|
name: "list_add",
|
|
1713
1703
|
label: "Add to queue",
|
|
1714
|
-
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.",
|
|
1715
1705
|
parameters: Type.Object({
|
|
1716
|
-
items: Type.Array(Type.String(), { description: "Objectives to enqueue
|
|
1706
|
+
items: Type.Array(Type.String(), { description: "Objectives to enqueue — no count limit; large plans belong in ONE call." }),
|
|
1717
1707
|
}),
|
|
1718
1708
|
async execute(_id, params, _signal, _onUpdate, execCtx) {
|
|
1719
1709
|
const p = params as { items: string[] };
|
|
@@ -1723,9 +1713,6 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
|
|
|
1723
1713
|
if (!Array.isArray(p.items) || p.items.length === 0) {
|
|
1724
1714
|
return { content: [{ type: "text", text: "No items given." }], details: {} };
|
|
1725
1715
|
}
|
|
1726
|
-
if (p.items.length > 100) {
|
|
1727
|
-
return { content: [{ type: "text", text: `Too many items at once (${p.items.length}); max 100 per call — batch larger plans across calls.` }], details: {} };
|
|
1728
|
-
}
|
|
1729
1716
|
const clean = p.items.map((t) => t.trim()).filter((t) => t.length > 0);
|
|
1730
1717
|
const liveCtx = (execCtx as ExtensionContext | undefined) ?? ctx;
|
|
1731
1718
|
const wasIdle = !state.goal || state.goal.status === "complete" || state.goal.status === "aborted";
|
|
@@ -2206,7 +2193,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
2206
2193
|
handler: settingsHandler,
|
|
2207
2194
|
});
|
|
2208
2195
|
pi.registerCommand("list", {
|
|
2209
|
-
description: "Loop 2: the list of audited goals — order is the default, not the law. /list <describe
|
|
2196
|
+
description: "Loop 2: the list of audited goals — order is the default, not the law. /list <describe tasks or name a plan file> (dumps get shaped into items, files import, 'Done when:' adds directly) | /list show | /list next [n] | /list remove <n> | /list clear",
|
|
2210
2197
|
handler: (args: string, ctx: ExtensionContext) => { rememberCtx(ctx); return cmdList(args, ctx); },
|
|
2211
2198
|
});
|
|
2212
2199
|
pi.registerCommand("loop", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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",
|