pi-goal-list-loop-audit 0.23.4 → 0.23.5

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.
@@ -593,3 +593,37 @@ export function shouldAutoResumeOnSessionStart(reason: string | undefined, autoR
593
593
  if (autoResume === true) return true;
594
594
  return reason === "resume" || reason === "reload" || reason === "fork";
595
595
  }
596
+
597
+ /**
598
+ * v0.23.5: normalize a drafter-supplied verification contract for the
599
+ * Confirm dialog AND for storage. Three cleanups, all mechanical:
600
+ * 1. Drop bare introducer lines ("Done when:", "Done when ALL of the
601
+ * following are true:") — the dialog adds its own "Done when" header;
602
+ * a model-supplied one renders doubled (field-observed) and pollutes
603
+ * the shield's item list.
604
+ * 2. Strip a glued "Done when: " prefix on a content line.
605
+ * 3. Renumber bullet/numbered lines sequentially ("1.", "2.", ...) so the
606
+ * dialog reads as a checklist and reject-feedback can cite item
607
+ * numbers. Non-bullet prose lines pass through untouched.
608
+ */
609
+ export function normalizeDraftContract(raw: string): string {
610
+ const lines = raw
611
+ .trim()
612
+ .split("\n")
613
+ .map((l) => l.trim())
614
+ .filter((l) => !/^(?:done when|verified when|verify|verification)\b[^:]*:\s*$/i.test(l))
615
+ .map((l) => l.replace(/^(?:done when|verified when)\s*:\s+/i, ""))
616
+ .filter((l) => l.length > 0);
617
+ let n = 0;
618
+ return lines
619
+ .map((l) => {
620
+ const m = l.match(/^(?:[-*•]\s+|\d+[.)]\s+)(.+)$/);
621
+ return m ? `${++n}. ${m[1]}` : l;
622
+ })
623
+ .join("\n");
624
+ }
625
+
626
+ /** Count the numbered checklist items in a normalized contract. */
627
+ export function draftContractItemCount(normalized: string): number {
628
+ return normalized.split("\n").filter((l) => /^\d+\.\s/.test(l)).length;
629
+ }
@@ -53,6 +53,8 @@ import {
53
53
  newGoalId,
54
54
  nowIso,
55
55
  piGlaDir,
56
+ normalizeDraftContract,
57
+ draftContractItemCount,
56
58
  readState,
57
59
  renderGoalMarkdown,
58
60
  shouldAutoResumeOnSessionStart,
@@ -1630,8 +1632,10 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1630
1632
  }
1631
1633
  return { content: [{ type: "text", text: `${n} items confirmed and queued (${listQueue().length} waiting).` }], details: {} };
1632
1634
  }
1633
- const contractBlock = p.verificationContract?.trim()
1634
- ? `\n\nDone when:\n${p.verificationContract.trim()}`
1635
+ const normContract = p.verificationContract?.trim() ? normalizeDraftContract(p.verificationContract) : "";
1636
+ const checkCount = normContract ? draftContractItemCount(normContract) : 0;
1637
+ const contractBlock = normContract
1638
+ ? `\n\nDone when${checkCount > 0 ? ` — ${checkCount} check${checkCount === 1 ? "" : "s"}` : ""}:\n${normContract}`
1635
1639
  : "\n\n(No verification contract — the auditor will infer done-criteria from the objective. Consider adding one.)";
1636
1640
  // v0.22.6: a list draft that will activate immediately must SAY so in
1637
1641
  // the Confirm dialog — "I started a list and ended up with a running
@@ -1657,7 +1661,7 @@ function registerAgentTools(pi: any, ctx: ExtensionContext): void {
1657
1661
  }
1658
1662
  const confirmedTarget = draftingTarget;
1659
1663
  draftingTarget = null;
1660
- const full = p.objective.trim() + (p.verificationContract?.trim() ? `\nDone when:\n${p.verificationContract.trim()}` : "");
1664
+ const full = p.objective.trim() + (normContract ? `\nDone when:\n${normContract}` : "");
1661
1665
  // List drafting: the confirmed contract goes into the QUEUE, not active.
1662
1666
  if (confirmedTarget === "list") {
1663
1667
  const extracted = extractVerificationContract(full);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goal-list-loop-audit",
3
- "version": "0.23.4",
3
+ "version": "0.23.5",
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",
@@ -19,6 +19,13 @@ request into a **confirmed goal contract**. Do NOT start substantive work yet.
19
19
  - **verification contract** — how an independent auditor can tell it is
20
20
  done, as checkable items (commands, file states, test outcomes).
21
21
  Strongly recommended; without it the auditor infers from the objective.
22
+ Write 3–8 mechanical checks, one per line, each verifiable with ONE
23
+ command or file check. The auditor must quote raw evidence for EVERY
24
+ item — a 17-item contract means a slow, expensive audit and more
25
+ regression-shield friction. Verify the artifact's integrity (the doc
26
+ exists, the table has N rows, the gates pass), not every sub-part.
27
+ Do NOT prefix the contract with "Done when:" — the Confirm dialog
28
+ adds that header itself.
22
29
  - **boundaries** — what is explicitly out of scope (fold into the
23
30
  objective text).
24
31
  4. Keep grilling until the objective and success criteria are concrete