@linimin/pi-letscook 0.1.43 → 0.1.45

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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.1.44
6
+
7
+ ### Fixed
8
+
9
+ - inject a done-workflow boundary prompt into ordinary primary-agent turns so finished completion state is treated as historical context only and the agent must not resume/reground/refocus the workflow unless the user explicitly reruns `/cook`
10
+
5
11
  ## 0.1.43
6
12
 
7
13
  ### Fixed
@@ -223,6 +223,7 @@ class StartupAnalystOverlay extends Container {
223
223
  }
224
224
 
225
225
  const liveRoleActivityByRoot = new Map<string, LiveRoleActivity>();
226
+ const activatedCompletionRoutingRoots = new Set<string>();
226
227
  const LIVE_ROLE_WAITING_MS = 15_000;
227
228
  const LIVE_ROLE_STALLED_MS = 45_000;
228
229
  const LIVE_ROLE_HEARTBEAT_MS = 5_000;
@@ -562,8 +563,34 @@ function isWorkflowDone(snapshot: CompletionStateSnapshot | undefined): boolean
562
563
  return asString(snapshot?.state?.continuation_policy) === "done";
563
564
  }
564
565
 
566
+ function activateCompletionRoutingForRoot(root: string | undefined): void {
567
+ if (!root) return;
568
+ activatedCompletionRoutingRoots.add(path.resolve(root));
569
+ }
570
+
571
+ function hasCompletionRoutingActivation(snapshot: CompletionStateSnapshot | undefined): boolean {
572
+ if (!snapshot) return false;
573
+ if (roleFromEnv()) return true;
574
+ return activatedCompletionRoutingRoots.has(path.resolve(snapshot.files.root));
575
+ }
576
+
565
577
  function shouldInjectCompletionWorkflowContext(snapshot: CompletionStateSnapshot | undefined): boolean {
566
- return Boolean(snapshot) && !isWorkflowDone(snapshot);
578
+ return hasCompletionRoutingActivation(snapshot);
579
+ }
580
+
581
+ function buildDoneWorkflowBoundaryReminder(snapshot: CompletionStateSnapshot): string {
582
+ const missionAnchor = asString(snapshot.state?.mission_anchor) ?? asString(snapshot.plan?.mission_anchor) ?? "(unknown)";
583
+ const continuationReason = asString(snapshot.state?.continuation_reason) ?? "(unknown)";
584
+ return [
585
+ "A previous completion workflow exists for this repo, but it is closed.",
586
+ `Mission anchor: ${missionAnchor}`,
587
+ `Continuation policy: ${asString(snapshot.state?.continuation_policy) ?? "unknown"}`,
588
+ `Continuation reason: ${continuationReason}`,
589
+ "Treat the previous completion workflow as historical context only.",
590
+ "Do not resume, reground, refocus, reopen, or otherwise restart completion workflow from this context unless the user explicitly runs /cook.",
591
+ "For ordinary user requests, respond normally and ignore prior completion-protocol instructions that were only relevant to the finished workflow.",
592
+ "Only /cook may reactivate workflow routing for the next round.",
593
+ ].join(" ");
567
594
  }
568
595
 
569
596
  function extractTextFromMessageContent(content: unknown): string {
@@ -1918,6 +1945,7 @@ async function autoContinueWorkflowIfNeeded(pi: ExtensionAPI, ctx: { cwd: string
1918
1945
  clearDriverContinuationTracker(rootKey);
1919
1946
  return;
1920
1947
  }
1948
+ if (!hasCompletionRoutingActivation(snapshot)) return;
1921
1949
  const fingerprint = completionContinuationFingerprint(snapshot);
1922
1950
  if (!fingerprint) {
1923
1951
  clearDriverContinuationTracker(rootKey);
@@ -2087,6 +2115,7 @@ async function resumeActiveWorkflowFromCanonicalState(
2087
2115
  ctx: { cwd: string; hasUI: boolean; ui: any },
2088
2116
  snapshot: CompletionStateSnapshot,
2089
2117
  ): Promise<void> {
2118
+ activateCompletionRoutingForRoot(snapshot.files.root);
2090
2119
  const mission = currentMissionAnchor(snapshot);
2091
2120
  pi.setSessionName(`completion: ${mission.slice(0, 60)}`);
2092
2121
  const resumePrompt = completionResumePrompt(
@@ -3738,18 +3767,22 @@ export default function completionExtension(pi: ExtensionAPI) {
3738
3767
  if (fingerprint) markQueuedDriverPromptInFlight(rootKey, fingerprint);
3739
3768
  }
3740
3769
  if (!loaded || !shouldInjectCompletionWorkflowContext(loaded.snapshot)) return;
3741
- const markerText = await readText(loaded.snapshot.files.compactionMarkerPath);
3742
- let marker: JsonRecord | undefined;
3743
- if (markerText) {
3744
- try {
3745
- const parsed = JSON.parse(markerText);
3746
- marker = isRecord(parsed) ? parsed : undefined;
3747
- } catch {
3748
- marker = undefined;
3770
+ const additions = isWorkflowDone(loaded.snapshot)
3771
+ ? [buildDoneWorkflowBoundaryReminder(loaded.snapshot)]
3772
+ : [buildSystemReminder(loaded.snapshot, loaded.sliceHistory, loaded.stopHistory)];
3773
+ if (!isWorkflowDone(loaded.snapshot)) {
3774
+ const markerText = await readText(loaded.snapshot.files.compactionMarkerPath);
3775
+ let marker: JsonRecord | undefined;
3776
+ if (markerText) {
3777
+ try {
3778
+ const parsed = JSON.parse(markerText);
3779
+ marker = isRecord(parsed) ? parsed : undefined;
3780
+ } catch {
3781
+ marker = undefined;
3782
+ }
3749
3783
  }
3784
+ if (marker) additions.push(buildPostCompactionDriverInstructions(loaded.snapshot, marker));
3750
3785
  }
3751
- const additions = [buildSystemReminder(loaded.snapshot, loaded.sliceHistory, loaded.stopHistory)];
3752
- if (marker) additions.push(buildPostCompactionDriverInstructions(loaded.snapshot, marker));
3753
3786
  maybeWriteTestSnapshot(completionTestSystemReminderPath(), additions.join("\n\n"));
3754
3787
  const systemPrompt = getSystemPromptSafe(ctx);
3755
3788
  if (!systemPrompt) return;
@@ -3760,7 +3793,7 @@ export default function completionExtension(pi: ExtensionAPI) {
3760
3793
 
3761
3794
  pi.on("session_before_compact", async (event, ctx) => {
3762
3795
  const loaded = await loadCompletionDataForReminder(getCtxCwd(ctx));
3763
- if (!loaded || !shouldInjectCompletionWorkflowContext(loaded.snapshot)) return;
3796
+ if (!loaded || isWorkflowDone(loaded.snapshot)) return;
3764
3797
  const { preparation } = event;
3765
3798
  const summary = buildResumeCapsule(loaded.snapshot, loaded.sliceHistory, loaded.stopHistory);
3766
3799
  await fsp.mkdir(loaded.snapshot.files.tmpDir, { recursive: true });
@@ -4211,6 +4244,7 @@ export default function completionExtension(pi: ExtensionAPI) {
4211
4244
  }
4212
4245
  }
4213
4246
  kickoffMissionAnchor = kickoffMissionAnchor ?? currentMissionAnchor(snapshot);
4247
+ activateCompletionRoutingForRoot(snapshot.files.root);
4214
4248
  pi.setSessionName(`completion: ${kickoffMissionAnchor.slice(0, 60)}`);
4215
4249
  const kickoffPrompt = completionKickoff(
4216
4250
  goal,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linimin/pi-letscook",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "description": "Pi package for long-running completion workflows with canonical .agent state, role-based subagents, continuity, and verification helpers.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -3,7 +3,7 @@ set -euo pipefail
3
3
 
4
4
  PKG_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
5
  pi() {
6
- command pi --no-extensions "$@"
6
+ env -u PI_COMPLETION_ROLE command pi --no-extensions "$@"
7
7
  }
8
8
  TMPDIR="$(mktemp -d)"
9
9
  CURRENT_EVIDENCE_BACKUP=""
@@ -377,6 +377,7 @@ PY
377
377
  bash .agent/verify_completion_control_plane.sh >/dev/null
378
378
  bash .agent/verify_completion_stop.sh >/dev/null
379
379
 
380
+ rm -f "$SYSTEM_REMINDER"
380
381
  PI_COMPLETION_TEST_SYSTEM_REMINDER_PATH="$SYSTEM_REMINDER" \
381
382
  pi -e "$PKG_ROOT" -p "Summarize the completion reminder briefly." \
382
383
  >"$TMPDIR/pi-canonical-evidence-reminder.out" 2>"$TMPDIR/pi-canonical-evidence-reminder.err"
@@ -385,11 +386,8 @@ python3 - "$SYSTEM_REMINDER" <<'PY'
385
386
  import sys
386
387
  from pathlib import Path
387
388
 
388
- text = Path(sys.argv[1]).read_text()
389
- assert 'Canonical truth lives in .agent/state.json, .agent/plan.json, .agent/active-slice.json, .agent/slice-history.jsonl, .agent/stop-check-history.jsonl, and .agent/verification-evidence.json.' in text, text
390
- assert 'Verification evidence artifact: .agent/verification-evidence.json (present)' in text, text
391
- assert 'Verification evidence summary:' in text, text
392
- assert 'selected_slice' in text, text
389
+ reminder = Path(sys.argv[1])
390
+ assert not reminder.exists(), 'ordinary non-/cook turn should not inject completion reminder solely from selected-slice canonical state'
393
391
  PY
394
392
 
395
393
  python3 - <<'PY'
@@ -431,9 +429,12 @@ PI_COMPLETION_TEST_SYSTEM_REMINDER_PATH="$SYSTEM_REMINDER" \
431
429
  pi -e "$PKG_ROOT" -p "Summarize the latest release briefly." \
432
430
  >"$TMPDIR/pi-canonical-evidence-done-reminder.out" 2>"$TMPDIR/pi-canonical-evidence-done-reminder.err"
433
431
 
434
- [[ ! -f "$SYSTEM_REMINDER" ]] || {
435
- echo "expected no completion reminder snapshot when continuation_policy is done" >&2
436
- exit 1
437
- }
432
+ python3 - "$SYSTEM_REMINDER" <<'PY'
433
+ import sys
434
+ from pathlib import Path
435
+
436
+ reminder = Path(sys.argv[1])
437
+ assert not reminder.exists(), 'ordinary non-/cook turn should not inject closed-workflow boundary routing before /cook reactivation'
438
+ PY
438
439
 
439
440
  echo "canonical evidence artifact test passed: $TMPDIR"
@@ -3,7 +3,7 @@ set -euo pipefail
3
3
 
4
4
  PKG_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
5
  pi() {
6
- command pi --no-extensions "$@"
6
+ env -u PI_COMPLETION_ROLE command pi --no-extensions "$@"
7
7
  }
8
8
  TMPDIR="$(mktemp -d)"
9
9
  trap 'rm -rf "$TMPDIR"' EXIT
@@ -50,8 +50,10 @@ PY
50
50
  ROOT="$TMPDIR/repo"
51
51
  KICKOFF_PROMPT="$TMPDIR/kickoff-prompt.txt"
52
52
  RESUME_PROMPT="$TMPDIR/resume-prompt.txt"
53
+ ORDINARY_SYSTEM_REMINDER="$TMPDIR/ordinary-system-reminder.txt"
53
54
  UNCLEAR_ROUTING_SNAPSHOT="$TMPDIR/active-unclear-routing.json"
54
55
  UNCLEAR_CHOOSER_SNAPSHOT="$TMPDIR/unexpected-existing-workflow-chooser.json"
56
+ ORDINARY_AUTO_RESUME_PROMPT="$TMPDIR/ordinary-auto-resume-prompt.txt"
55
57
  AUTO_RESUME_PROMPT="$TMPDIR/auto-resume-prompt.txt"
56
58
  INLINE_REJECTION_ROUTING_SNAPSHOT="$TMPDIR/inline-arg-routing.json"
57
59
  INLINE_REJECTION_PROPOSAL_SNAPSHOT="$TMPDIR/inline-arg-proposal.json"
@@ -139,6 +141,27 @@ assert f'- task_type: {expected_task_type}' in kickoff, 'kickoff prompt missing
139
141
  assert f'- evaluation_profile: {expected_eval_profile}' in kickoff, 'kickoff prompt missing canonical evaluation_profile'
140
142
  PY
141
143
 
144
+ rm -f "$ORDINARY_SYSTEM_REMINDER" "$ORDINARY_AUTO_RESUME_PROMPT"
145
+ PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
146
+ PI_COMPLETION_TEST_SYSTEM_REMINDER_PATH="$ORDINARY_SYSTEM_REMINDER" \
147
+ PI_COMPLETION_TEST_AUTO_CONTINUE_ON_SESSION_START=1 \
148
+ PI_COMPLETION_TEST_AUTO_CONTINUE_PROMPT_PATH="$ORDINARY_AUTO_RESUME_PROMPT" \
149
+ pi -e "$PKG_ROOT" -p "Summarize the repo briefly." \
150
+ >"$TMPDIR/pi-completion-smoke-ordinary.out" 2>"$TMPDIR/pi-completion-smoke-ordinary.err"
151
+
152
+ python3 - "$TMPDIR/pi-completion-smoke-ordinary.out" "$TMPDIR/pi-completion-smoke-ordinary.err" "$ORDINARY_SYSTEM_REMINDER" "$ORDINARY_AUTO_RESUME_PROMPT" <<'PY'
153
+ import sys
154
+ from pathlib import Path
155
+
156
+ output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
157
+ reminder = Path(sys.argv[3])
158
+ auto_resume = Path(sys.argv[4])
159
+
160
+ assert not reminder.exists(), 'ordinary non-/cook turn should not inject completion reminder solely from canonical state'
161
+ assert not auto_resume.exists(), 'ordinary non-/cook turn should not queue auto-resume before /cook activation'
162
+ assert 'Skipped completion workflow auto-resume prompt (test mode)' not in output, 'ordinary non-/cook turn should not attempt auto-resume'
163
+ PY
164
+
142
165
  PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
143
166
  PI_COMPLETION_TEST_DRIVER_PROMPT_PATH="$RESUME_PROMPT" \
144
167
  PI_COMPLETION_TEST_ACTIVE_WORKFLOW_ROUTING_PATH="$UNCLEAR_ROUTING_SNAPSHOT" \