pi-goal-list-loop-audit 0.28.26 → 0.28.28
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 +1 -0
- package/extensions/goal-loop-core.ts +6 -2
- package/extensions/loops/goal.ts +123 -17
- package/package.json +1 -1
- package/schemas/goal.schema.json +1 -0
package/README.md
CHANGED
|
@@ -39,6 +39,7 @@ Five top-level commands — `/goal`, `/list`, `/loop`, `/glla`, `/review`:
|
|
|
39
39
|
/goal resume # resume
|
|
40
40
|
/goal cancel # abort
|
|
41
41
|
/goal decide # re-open the decision picker (v0.28.23)
|
|
42
|
+
/goal audit # run the isolated auditor on the current goal now — no agent turn (v0.28.27)
|
|
42
43
|
/goal tweak "<new objective>" # edit in place (Confirm dialog)
|
|
43
44
|
/goal archive # archived goals, newest first
|
|
44
45
|
/glla # settings UI table · /glla key=value · /glla stats · /glla audits [N|full] · /glla postaudit · /glla autoaccept=on
|
|
@@ -185,6 +185,10 @@ export interface Goal {
|
|
|
185
185
|
* the retry resolves. Only consumed while paused with an "auditor quota:"
|
|
186
186
|
* reason, so a stale value is unreachable by construction. */
|
|
187
187
|
pendingCompletion?: { completionSummary?: string; verificationSummary?: string; at: string };
|
|
188
|
+
/** v0.28.28: provenance — who created this goal ("user", "list-cascade",
|
|
189
|
+
* "draft-confirmed", "draft-autoaccepted"). Ledgered on goal_created so
|
|
190
|
+
* "where did this come from" is answerable after the fact. */
|
|
191
|
+
createdVia?: string;
|
|
188
192
|
/** v0.25.0 (contract item 22): auditor objections extracted as TODOs when
|
|
189
193
|
* aggressiveMode keeps the goal active past the disapproval cap. Rendered
|
|
190
194
|
* into every continuation prompt until the next audit clears them. */
|
|
@@ -212,9 +216,9 @@ export interface Goal {
|
|
|
212
216
|
export type GoalRoute =
|
|
213
217
|
| { kind: "draft" }
|
|
214
218
|
| { kind: "set"; text: string }
|
|
215
|
-
| { kind: "sub"; name: "status" | "pause" | "resume" | "cancel" | "decide" | "tweak" | "archive" | "start"; rest: string };
|
|
219
|
+
| { kind: "sub"; name: "status" | "pause" | "resume" | "cancel" | "decide" | "audit" | "tweak" | "archive" | "start"; rest: string };
|
|
216
220
|
|
|
217
|
-
const GOAL_EXACT_SUBS = new Set(["status", "pause", "resume", "cancel", "decide"]);
|
|
221
|
+
const GOAL_EXACT_SUBS = new Set(["status", "pause", "resume", "cancel", "decide", "audit"]);
|
|
218
222
|
const GOAL_ARG_SUBS = new Set(["tweak", "archive", "start"]);
|
|
219
223
|
|
|
220
224
|
export function routeGoalArgs(raw: string): GoalRoute {
|
package/extensions/loops/goal.ts
CHANGED
|
@@ -568,6 +568,12 @@ function heartbeatTick(): void {
|
|
|
568
568
|
// machinery below stays quiet for 3 minutes while the replaced session
|
|
569
569
|
// settles (latch watchdog, wedge alert, refire counting all resume after).
|
|
570
570
|
if (Date.now() < compactionGraceUntil) return;
|
|
571
|
+
// v0.28.27: a stale (session-replaced) handle can never land a send —
|
|
572
|
+
// the terminal warning already fired once. ALL stall machinery stays
|
|
573
|
+
// quiet from here on: refiring into a dead process is misleading, and
|
|
574
|
+
// worse, the stall escalation would PAUSE the goal — silently cancelling
|
|
575
|
+
// the interruptedAt → auto-resume-on-restart promise the footer shows.
|
|
576
|
+
if (extensionApiStale) return;
|
|
571
577
|
// v0.26.5: pending-latch watchdog — a queued continuation whose turn
|
|
572
578
|
// trigger was dropped (field-observed post-compaction: continuation
|
|
573
579
|
// ACCEPTED at compact+0s, then 22 minutes of silence). The stuck latch
|
|
@@ -889,18 +895,19 @@ function notifyPersistenceState(ctx: ExtensionContext): void {
|
|
|
889
895
|
}
|
|
890
896
|
}
|
|
891
897
|
|
|
892
|
-
function setGoal(goal: Goal, ctx: ExtensionContext): void {
|
|
898
|
+
function setGoal(goal: Goal, ctx: ExtensionContext, via = "user"): void {
|
|
893
899
|
// v0.28.14: never silently orphan a live goal — a paused/active goal
|
|
894
900
|
// being replaced is archived honestly first (the old behavior left it in
|
|
895
901
|
// goals/ but untracked: "older goals lying around leading to confusion").
|
|
896
902
|
if (state.goal && state.goal.id !== goal.id && (state.goal.status === "active" || state.goal.status === "paused")) {
|
|
897
903
|
archiveCurrentGoal(ctx, "aborted", `replaced by goal ${goal.id}`);
|
|
898
904
|
}
|
|
905
|
+
goal.createdVia = via; // v0.28.28: provenance — answerable from the ledger + /glla log
|
|
899
906
|
state = { ...state, goal }; // preserve list AND loop (v0.28.14: the bare reconstruction used to nuke a held/active loop whenever a goal was set)
|
|
900
907
|
const file = writeGoalMd(ctx.cwd, goal);
|
|
901
908
|
state.goal!.activePath = path.relative(ctx.cwd, file) || file;
|
|
902
909
|
persistState(ctx);
|
|
903
|
-
appendLedger(ctx.cwd, "goal_created", { goalId: goal.id, objective: goal.objective, policy: goal.policy });
|
|
910
|
+
appendLedger(ctx.cwd, "goal_created", { goalId: goal.id, objective: goal.objective, policy: goal.policy, via });
|
|
904
911
|
}
|
|
905
912
|
|
|
906
913
|
function updateGoal(patch: Partial<Goal>, ctx: ExtensionContext): void {
|
|
@@ -963,15 +970,17 @@ function archiveCurrentGoal(ctx: ExtensionContext, status: Status, stopReason?:
|
|
|
963
970
|
* infra) → hand back to the agent: resume active + continuation, verdict
|
|
964
971
|
* durable in auditHistory.
|
|
965
972
|
*/
|
|
966
|
-
async function retryStoredCompletionAudit(ctx: ExtensionContext): Promise<void> {
|
|
973
|
+
async function retryStoredCompletionAudit(ctx: ExtensionContext, origin: "quota-retry" | "manual" = "quota-retry"): Promise<void> {
|
|
967
974
|
const goal = state.goal;
|
|
968
975
|
if (!goal?.pendingCompletion) return;
|
|
969
976
|
if (completionAuditInFlight) return;
|
|
970
977
|
const liveCtx = freshCtx() ?? ctx;
|
|
971
978
|
const claim = goal.pendingCompletion;
|
|
972
979
|
updateGoal({ status: "auditing" }, liveCtx);
|
|
973
|
-
appendLedger(liveCtx.cwd, "goal_resumed", { via: "quota-retry-direct-audit" });
|
|
974
|
-
liveCtx.ui.notify(
|
|
980
|
+
appendLedger(liveCtx.cwd, "goal_resumed", { via: origin === "manual" ? "manual-audit" : "quota-retry-direct-audit" });
|
|
981
|
+
liveCtx.ui.notify(origin === "manual"
|
|
982
|
+
? "Manual /goal audit — running the isolated auditor now (no agent turn needed)."
|
|
983
|
+
: "Auditor quota window elapsed — retrying the audit with your stored completion claim (no agent turn needed).", "info");
|
|
975
984
|
const settings = loadSettings(liveCtx.cwd);
|
|
976
985
|
const { model: auditorModel, error: modelError, via } = resolveAuditorModel(liveCtx, settings.auditorModel);
|
|
977
986
|
if (modelError) liveCtx.ui.notify(`Auditor model issue: ${modelError}`, "warning");
|
|
@@ -1027,9 +1036,9 @@ async function retryStoredCompletionAudit(ctx: ExtensionContext): Promise<void>
|
|
|
1027
1036
|
if (result.approved) {
|
|
1028
1037
|
updateGoal({ auditHistory: history, pendingCompletion: undefined }, liveCtx);
|
|
1029
1038
|
const objective = state.goal.objective;
|
|
1030
|
-
archiveCurrentGoal(liveCtx, "complete", `auditor ${result.model} approved (
|
|
1031
|
-
liveCtx.ui.notify(`Goal complete — auditor ${result.model} approved on the quota retry.`, "info");
|
|
1032
|
-
notifyExternal(liveCtx, `Goal complete (auditor approved
|
|
1039
|
+
archiveCurrentGoal(liveCtx, "complete", `auditor ${result.model} approved (${origin})`);
|
|
1040
|
+
liveCtx.ui.notify(`Goal complete — auditor ${result.model} approved${origin === "manual" ? " on /goal audit" : " on the quota retry"}.`, "info");
|
|
1041
|
+
notifyExternal(liveCtx, `Goal complete (auditor approved, ${origin}): ${objective.slice(0, 120)}`);
|
|
1033
1042
|
return;
|
|
1034
1043
|
}
|
|
1035
1044
|
|
|
@@ -1051,7 +1060,7 @@ async function retryStoredCompletionAudit(ctx: ExtensionContext): Promise<void>
|
|
|
1051
1060
|
liveCtx.ui.notify(`Auditor still quota-limited — next auto-retry in ${retryMin}m (your completion claim is stored; no action needed).`, "warning");
|
|
1052
1061
|
scheduleQuotaRetry(liveCtx, quota.retryAfterSec, result.error, () => {
|
|
1053
1062
|
if (state.goal && state.goal.status === "paused" && (state.goal.pauseReason ?? "").startsWith("auditor quota:") && state.goal.pendingCompletion) {
|
|
1054
|
-
void retryStoredCompletionAudit(liveCtx);
|
|
1063
|
+
void retryStoredCompletionAudit(liveCtx, origin);
|
|
1055
1064
|
}
|
|
1056
1065
|
});
|
|
1057
1066
|
return;
|
|
@@ -1072,10 +1081,10 @@ async function retryStoredCompletionAudit(ctx: ExtensionContext): Promise<void>
|
|
|
1072
1081
|
}, liveCtx);
|
|
1073
1082
|
liveCtx.ui.notify(
|
|
1074
1083
|
result.disapproved
|
|
1075
|
-
? `Auditor (
|
|
1084
|
+
? `Auditor (${origin}) DISAPPROVED — resuming; the report is in /goal status.`
|
|
1076
1085
|
: result.impossible
|
|
1077
|
-
? `Auditor (
|
|
1078
|
-
: `Auditor (
|
|
1086
|
+
? `Auditor (${origin}): goal IMPOSSIBLE — ${(result.impossibleReason ?? "").slice(0, 100)}. Resuming; consider /goal tweak.`
|
|
1087
|
+
: `Auditor (${origin}) hit an infrastructure error — resuming; re-call complete_goal when ready.`,
|
|
1079
1088
|
"warning",
|
|
1080
1089
|
);
|
|
1081
1090
|
appendLedger(liveCtx.cwd, "quota_retry_audit_verdict", {
|
|
@@ -1134,7 +1143,7 @@ function fireReviewer(
|
|
|
1134
1143
|
manual: opts.manual,
|
|
1135
1144
|
ledgerEntries,
|
|
1136
1145
|
sources,
|
|
1137
|
-
enqueueListItems: (objectives) => enqueueItems(ctx, objectives, "reviewer"),
|
|
1146
|
+
enqueueListItems: (objectives) => enqueueItems(ctx, objectives, "reviewer", { autoActivate: loadSettings(ctx.cwd).autoResume === true }),
|
|
1138
1147
|
proposeGoal: (objective, reason) => {
|
|
1139
1148
|
try {
|
|
1140
1149
|
extensionApi?.sendUserMessage(
|
|
@@ -1204,7 +1213,7 @@ function activateNextListItem(ctx: ExtensionContext, n = 1): boolean {
|
|
|
1204
1213
|
state = { ...state, list: rest };
|
|
1205
1214
|
const goal = createGoal(next.objective, ctx, "list");
|
|
1206
1215
|
if (next.verificationContract) goal.verificationContract = next.verificationContract;
|
|
1207
|
-
setGoal(goal, ctx);
|
|
1216
|
+
setGoal(goal, ctx, "list-cascade");
|
|
1208
1217
|
iterationCounter = 0;
|
|
1209
1218
|
consecutiveErrorIterations = 0;
|
|
1210
1219
|
consecutiveAbortIterations = 0;
|
|
@@ -1309,6 +1318,30 @@ async function cmdGoal(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
1309
1318
|
if (!shown) ctx.ui.notify("No pending decision — the goal isn't paused on a choice (or no UI).", "info");
|
|
1310
1319
|
return;
|
|
1311
1320
|
}
|
|
1321
|
+
// v0.28.27: /goal audit — run the isolated auditor on the current goal
|
|
1322
|
+
// RIGHT NOW, without engaging the agent. The user's "the work looks
|
|
1323
|
+
// done — just verify it" handle (and the manual counterpart of the
|
|
1324
|
+
// v0.28.26 stored-claim quota retry). Seeds a synthesized claim so a
|
|
1325
|
+
// quota block falls into the same pendingCompletion retry machinery.
|
|
1326
|
+
if (route.name === "audit") {
|
|
1327
|
+
if (!state.goal) {
|
|
1328
|
+
ctx.ui.notify("No active goal — /goal audit needs a goal to verify.", "warning");
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
if (completionAuditInFlight) {
|
|
1332
|
+
ctx.ui.notify("An audit is already running…", "info");
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
updateGoal({
|
|
1336
|
+
pendingCompletion: {
|
|
1337
|
+
completionSummary: "Manual audit requested by the user via /goal audit (no agent completion claim). Verify the objective against the repo directly.",
|
|
1338
|
+
at: nowIso(),
|
|
1339
|
+
},
|
|
1340
|
+
}, ctx);
|
|
1341
|
+
appendLedger(ctx.cwd, "manual_audit_requested", { goalId: state.goal.id });
|
|
1342
|
+
void retryStoredCompletionAudit(ctx, "manual");
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1312
1345
|
if (route.name === "tweak") return cmdTweak(route.rest, ctx);
|
|
1313
1346
|
if (route.name === "archive") return cmdGoals(ctx);
|
|
1314
1347
|
// v0.16.0: /goal start <objective> — explicit skip-draft. Activates
|
|
@@ -1599,7 +1632,7 @@ async function cmdTweak(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
1599
1632
|
* contract extraction) → appended to the queue → persisted → first item
|
|
1600
1633
|
* activated when nothing is running. Returns the count enqueued.
|
|
1601
1634
|
*/
|
|
1602
|
-
function enqueueItems(ctx: ExtensionContext, texts: string[], source: string): number {
|
|
1635
|
+
function enqueueItems(ctx: ExtensionContext, texts: string[], source: string, opts?: { autoActivate?: boolean }): number {
|
|
1603
1636
|
const items = texts.map((text) => {
|
|
1604
1637
|
const extracted = extractVerificationContract(text);
|
|
1605
1638
|
return { id: newGoalId(), objective: extracted.objective, verificationContract: extracted.verificationContract || undefined, addedAt: nowIso() };
|
|
@@ -1608,7 +1641,16 @@ function enqueueItems(ctx: ExtensionContext, texts: string[], source: string): n
|
|
|
1608
1641
|
persistState(ctx);
|
|
1609
1642
|
appendLedger(ctx.cwd, "list_imported", { source, count: items.length });
|
|
1610
1643
|
if (!state.goal || state.goal.status === "complete" || state.goal.status === "aborted") {
|
|
1611
|
-
|
|
1644
|
+
// v0.28.28: unsolicited sources (the reviewer) do NOT auto-start the
|
|
1645
|
+
// head unless autoResume is on — "I cancelled a goal and the next one
|
|
1646
|
+
// started itself" was the field complaint. User-driven imports keep
|
|
1647
|
+
// the immediate-start behavior (opts default true).
|
|
1648
|
+
if (opts?.autoActivate === false) {
|
|
1649
|
+
ctx.ui.notify(`Queued ${items.length} item(s) from ${source} — /list next when ready (auto-start is opt-in: /glla autoresume=on).`, "info");
|
|
1650
|
+
appendLedger(ctx.cwd, "list_autoactivation_held", { source, count: items.length });
|
|
1651
|
+
} else {
|
|
1652
|
+
activateNextListItem(ctx);
|
|
1653
|
+
}
|
|
1612
1654
|
}
|
|
1613
1655
|
return items.length;
|
|
1614
1656
|
}
|
|
@@ -3135,13 +3177,34 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
|
|
|
3135
3177
|
persistState(liveCtx);
|
|
3136
3178
|
appendLedger(liveCtx.cwd, "list_added", { id: item.id, objective: item.objective, drafted: true });
|
|
3137
3179
|
if (!state.goal || state.goal.status === "complete" || state.goal.status === "aborted") {
|
|
3180
|
+
// v0.28.28: an AUTO-ACCEPTED draft does not auto-start unless
|
|
3181
|
+
// autoResume is on — accepting a draft is not consent to start.
|
|
3182
|
+
if (autoAccept && loadSettings(liveCtx.cwd).autoResume !== true) {
|
|
3183
|
+
liveCtx.ui.notify(`Auto-accepted and QUEUED (autoResume off — not auto-started): ${extracted.objective.slice(0, 80)} — /list next when ready.`, "info");
|
|
3184
|
+
appendLedger(liveCtx.cwd, "list_autoactivation_held", { source: "draft-autoaccepted", count: 1 });
|
|
3185
|
+
return { content: [{ type: "text", text: "Draft accepted and added to the list, but NOT started (the user's autoResume setting is off — auto-accepted drafts queue, they don't auto-start). Do NOT begin work. Tell the user: /list next starts it." }], details: {} };
|
|
3186
|
+
}
|
|
3138
3187
|
activateNextListItem(liveCtx);
|
|
3139
3188
|
return { content: [{ type: "text", text: "Confirmed and activated (list was empty). Begin work now." }], details: {} };
|
|
3140
3189
|
}
|
|
3141
3190
|
return { content: [{ type: "text", text: `Confirmed and added to the list (${listQueue().length} waiting). It activates when the current goal completes.` }], details: {} };
|
|
3142
3191
|
}
|
|
3143
3192
|
const goal = createGoal(full, liveCtx);
|
|
3144
|
-
setGoal(goal, liveCtx);
|
|
3193
|
+
setGoal(goal, liveCtx, autoAccept ? "draft-autoaccepted" : "draft-confirmed");
|
|
3194
|
+
// v0.28.28: auto-accepted goal drafts are created HELD when autoResume
|
|
3195
|
+
// is off — auto-accept delegates the Confirm click, not the decision
|
|
3196
|
+
// to start. Explicit user-confirmed drafts still start immediately.
|
|
3197
|
+
if (autoAccept && loadSettings(liveCtx.cwd).autoResume !== true) {
|
|
3198
|
+
updateGoal({
|
|
3199
|
+
status: "paused",
|
|
3200
|
+
pauseKind: "blocked",
|
|
3201
|
+
pauseReason: "auto-accepted draft — held for the user's go-ahead (autoResume off)",
|
|
3202
|
+
pauseSuggestedAction: "/goal resume to start · /goal cancel to drop · /glla autoresume=on starts auto-accepted drafts automatically",
|
|
3203
|
+
}, liveCtx);
|
|
3204
|
+
appendLedger(liveCtx.cwd, "draft_held", { goalId: goal.id, reason: "autoaccept-autoresume-off" });
|
|
3205
|
+
liveCtx.ui.notify(`Draft auto-accepted and HELD (autoResume off): ${goal.objective.slice(0, 80)} — /goal resume to start, /goal cancel to drop.`, "info");
|
|
3206
|
+
return { content: [{ type: "text", text: "Goal accepted but HELD (the user's autoResume setting is off — auto-accepted drafts do not auto-start). Do NOT begin work. Tell the user: /goal resume starts it, /goal cancel drops it." }], details: {} };
|
|
3207
|
+
}
|
|
3145
3208
|
iterationCounter = 0;
|
|
3146
3209
|
consecutiveErrorIterations = 0;
|
|
3147
3210
|
consecutiveAbortIterations = 0;
|
|
@@ -4053,6 +4116,42 @@ function cmdStats(args: string, ctx: ExtensionContext): void {
|
|
|
4053
4116
|
* log (.pi-glla/audits.jsonl). Default: last 10 verdicts, one line each.
|
|
4054
4117
|
* "full" prints the latest report in full.
|
|
4055
4118
|
*/
|
|
4119
|
+
/**
|
|
4120
|
+
* v0.28.28: /glla log [N] — human-readable tail of the event ledger (the
|
|
4121
|
+
* forensic trail: who created/resumed/paused goals, from where). Skips the
|
|
4122
|
+
* high-frequency noise entries (state snapshots, re-arm internals) unless
|
|
4123
|
+
* "all" is passed. N defaults to 15.
|
|
4124
|
+
*/
|
|
4125
|
+
const LOG_NOISE = new Set(["state", "send_rearm_start", "heartbeat_suppressed_tick"]);
|
|
4126
|
+
function cmdLog(args: string, ctx: ExtensionContext): void {
|
|
4127
|
+
const all = /\ball\b/.test(args);
|
|
4128
|
+
const nMatch = args.match(/\b(\d+)\b/);
|
|
4129
|
+
const n = Math.min(Math.max(parseInt(nMatch?.[1] ?? "15", 10) || 15, 1), 100);
|
|
4130
|
+
let entries: Array<{ type: string; at?: string; value?: any }> = [];
|
|
4131
|
+
try {
|
|
4132
|
+
entries = parseLedgerEntries(fs.readFileSync(ledgerPath(ctx.cwd), "utf-8"));
|
|
4133
|
+
} catch {
|
|
4134
|
+
ctx.ui.notify("No ledger yet — .pi-glla/active.jsonl doesn't exist.", "info");
|
|
4135
|
+
return;
|
|
4136
|
+
}
|
|
4137
|
+
const visible = all ? entries : entries.filter((e) => !LOG_NOISE.has(e.type));
|
|
4138
|
+
const tail = visible.slice(-n);
|
|
4139
|
+
if (tail.length === 0) {
|
|
4140
|
+
ctx.ui.notify("Ledger is empty (no non-noise events yet).", "info");
|
|
4141
|
+
return;
|
|
4142
|
+
}
|
|
4143
|
+
const lines = tail.map((e) => {
|
|
4144
|
+
const t = (e.at ?? "").slice(11, 19);
|
|
4145
|
+
const v = e.value ?? {};
|
|
4146
|
+
const detail = Object.entries(v)
|
|
4147
|
+
.filter(([k]) => k !== "goalId" && k !== "report")
|
|
4148
|
+
.map(([k, val]) => `${k}=${typeof val === "string" ? val.slice(0, 60) : JSON.stringify(val)?.slice(0, 60)}`)
|
|
4149
|
+
.join(" ");
|
|
4150
|
+
return `${t} ${e.type}${detail ? ` ${detail}` : ""}`;
|
|
4151
|
+
});
|
|
4152
|
+
ctx.ui.notify(`Ledger tail (last ${tail.length}${all ? "" : " non-noise"} events — /glla log <N> for more, /glla log all to include noise):\n${lines.join("\n")}`, "info");
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4056
4155
|
function cmdAudits(args: string, ctx: ExtensionContext): void {
|
|
4057
4156
|
const full = /\bfull\b/.test(args);
|
|
4058
4157
|
const all = /\b(?:all|global|log)\b/.test(args);
|
|
@@ -4104,6 +4203,12 @@ async function cmdSettings(args: string, ctx: ExtensionContext): Promise<void> {
|
|
|
4104
4203
|
cmdAudits(trimmed.slice("audits".length).trim(), ctx);
|
|
4105
4204
|
return;
|
|
4106
4205
|
}
|
|
4206
|
+
// v0.28.28: /glla log [N] — the raw event trail, human-readable. "Log it
|
|
4207
|
+
// so we can look back and see where we are doing things wrong."
|
|
4208
|
+
if (/^log\b/.test(trimmed)) {
|
|
4209
|
+
cmdLog(trimmed.slice("log".length).trim(), ctx);
|
|
4210
|
+
return;
|
|
4211
|
+
}
|
|
4107
4212
|
if (/^reviewer\b/.test(trimmed)) {
|
|
4108
4213
|
await cmdReviewerSettings(ctx);
|
|
4109
4214
|
return;
|
|
@@ -4494,6 +4599,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
4494
4599
|
["autoresume=", "default: hold when a session is loaded, auto-resume on reload/fork; on: always auto-resume; off: never"],
|
|
4495
4600
|
["decisionpopup=", "on|off: decision pauses pop the select() picker (default on; the widget card always lists the options, /goal decide reopens the picker)"],
|
|
4496
4601
|
["auditcap=", "N: pause goal after N consecutive auditor disapprovals (default 5, 0 = unlimited)"],
|
|
4602
|
+
["log", "event-trail tail: /glla log [N] — who created/resumed/paused what, from where (v0.28.28)"],
|
|
4497
4603
|
["auditfeedbackchars=", "cap on executor-visible disapproval report chars (0 = full report, the default)"],
|
|
4498
4604
|
["aggressivemode=", "on: keep-going defaults — autoResume, cap 10, stuck 10, wedge off, quota auto-retry, cap→TODOs"],
|
|
4499
4605
|
["quotaretryminutes=", "N: minutes before auto-retrying a quota-exhausted auditor (default 60)"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goal-list-loop-audit",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.28",
|
|
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",
|
package/schemas/goal.schema.json
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"interruptedReason": { "type": "string" },
|
|
55
55
|
"auditInfraStreak": { "type": "number" },
|
|
56
56
|
"pendingCompletion": { "type": "object" },
|
|
57
|
+
"createdVia": { "type": "string" },
|
|
57
58
|
"activePath": { "type": "string" },
|
|
58
59
|
"archivedPath": { "type": "string" },
|
|
59
60
|
"usage": {
|