@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
|
|
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
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
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 ||
|
|
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.
|
|
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
|
-
|
|
389
|
-
assert '
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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"
|
package/scripts/smoke-test.sh
CHANGED
|
@@ -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" \
|