@linimin/pi-letscook 0.1.31 → 0.1.33

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
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.33
4
+
5
+ ### Changed
6
+
7
+ - kept full mission text in `/cook` confirmation instead of truncating mission anchors during derivation
8
+ - refined `/cook` activity and completion-role text contrast by reducing overuse of `dim` styling in high-value status surfaces
9
+
10
+ ## 0.1.32
11
+
12
+ ### Changed
13
+
14
+ - made `/cook` auto-continue workflows from canonical state when `continuation_policy == continue`, so the primary driver re-queues the canonical resume prompt after intermediate role turns instead of parking silently on known mandatory steps
15
+ - added smoke coverage for the new auto-resume driver prompt behavior and a guarded parked-state warning path to avoid infinite requeue loops on an unchanged mandatory state
16
+
3
17
  ## 0.1.31
4
18
 
5
19
  ### Changed
@@ -203,7 +203,7 @@ class StartupAnalystOverlay extends Container {
203
203
 
204
204
  private updateDisplay(): void {
205
205
  this.title.setText(this.theme.fg("accent", this.theme.bold("/cook proposal analyst")));
206
- this.body.setText(this.theme.fg("dim", this.lines.join("\n")));
206
+ this.body.setText(formatInlineRunningText(this.theme, this.lines, { primaryAssistant: true }));
207
207
  this.footer.setText(this.theme.fg("muted", "Esc cancel • This analysis runs before /cook writes canonical workflow state"));
208
208
  }
209
209
 
@@ -225,6 +225,16 @@ const liveRoleActivityByRoot = new Map<string, LiveRoleActivity>();
225
225
  const LIVE_ROLE_WAITING_MS = 15_000;
226
226
  const LIVE_ROLE_STALLED_MS = 45_000;
227
227
  const LIVE_ROLE_HEARTBEAT_MS = 5_000;
228
+ const DRIVER_AUTO_CONTINUE_MAX_ATTEMPTS = 2;
229
+
230
+ type DriverContinuationTracker = {
231
+ fingerprint: string;
232
+ attempts: number;
233
+ inFlight: boolean;
234
+ warned: boolean;
235
+ };
236
+
237
+ const driverContinuationByRoot = new Map<string, DriverContinuationTracker>();
228
238
 
229
239
  function isRecord(value: unknown): value is JsonRecord {
230
240
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -529,6 +539,14 @@ function completionTestDriverPromptPath(): string | undefined {
529
539
  return asString(process.env.PI_COMPLETION_TEST_DRIVER_PROMPT_PATH);
530
540
  }
531
541
 
542
+ function completionTestAutoContinuePromptPath(): string | undefined {
543
+ return asString(process.env.PI_COMPLETION_TEST_AUTO_CONTINUE_PROMPT_PATH);
544
+ }
545
+
546
+ function shouldTestAutoContinueOnSessionStart(): boolean {
547
+ return process.env.PI_COMPLETION_TEST_AUTO_CONTINUE_ON_SESSION_START === "1";
548
+ }
549
+
532
550
  function completionTestSystemReminderPath(): string | undefined {
533
551
  return asString(process.env.PI_COMPLETION_TEST_SYSTEM_REMINDER_PATH);
534
552
  }
@@ -1641,6 +1659,128 @@ function currentEvaluationProfile(snapshot: CompletionStateSnapshot): string | u
1641
1659
  );
1642
1660
  }
1643
1661
 
1662
+ function completionContinuationFingerprint(snapshot: CompletionStateSnapshot): string | undefined {
1663
+ if (asString(snapshot.state?.continuation_policy) !== "continue") return undefined;
1664
+ const nextMandatoryRole = asString(snapshot.state?.next_mandatory_role);
1665
+ if (!nextMandatoryRole) return undefined;
1666
+ return JSON.stringify({
1667
+ mission_anchor: asString(snapshot.state?.mission_anchor) ?? asString(snapshot.plan?.mission_anchor) ?? null,
1668
+ task_type: currentTaskType(snapshot) ?? null,
1669
+ evaluation_profile: currentEvaluationProfile(snapshot) ?? null,
1670
+ current_phase: asString(snapshot.state?.current_phase) ?? null,
1671
+ next_mandatory_role: nextMandatoryRole,
1672
+ next_mandatory_action: asString(snapshot.state?.next_mandatory_action) ?? null,
1673
+ active_status: asString(snapshot.active?.status) ?? null,
1674
+ active_slice_id: asString(snapshot.active?.slice_id) ?? asString(snapshot.activeSlice?.slice_id) ?? null,
1675
+ latest_completed_slice: asString(snapshot.state?.latest_completed_slice) ?? null,
1676
+ latest_verified_slice: asString(snapshot.state?.latest_verified_slice) ?? null,
1677
+ });
1678
+ }
1679
+
1680
+ function noteQueuedDriverPrompt(rootKey: string, fingerprint: string): void {
1681
+ const tracker = driverContinuationByRoot.get(rootKey);
1682
+ if (tracker && tracker.fingerprint === fingerprint) {
1683
+ tracker.attempts += 1;
1684
+ tracker.inFlight = false;
1685
+ tracker.warned = false;
1686
+ return;
1687
+ }
1688
+ driverContinuationByRoot.set(rootKey, {
1689
+ fingerprint,
1690
+ attempts: 1,
1691
+ inFlight: false,
1692
+ warned: false,
1693
+ });
1694
+ }
1695
+
1696
+ function markQueuedDriverPromptInFlight(rootKey: string, fingerprint: string): void {
1697
+ const tracker = driverContinuationByRoot.get(rootKey);
1698
+ if (!tracker || tracker.fingerprint !== fingerprint) return;
1699
+ tracker.inFlight = true;
1700
+ }
1701
+
1702
+ function clearDriverContinuationTracker(rootKey: string): void {
1703
+ driverContinuationByRoot.delete(rootKey);
1704
+ }
1705
+
1706
+ function hasRunningCompletionRole(rootKey: string): boolean {
1707
+ return liveRoleActivityByRoot.get(rootKey)?.status === "running";
1708
+ }
1709
+
1710
+ function isWorkflowDriverActive(snapshot: CompletionStateSnapshot | undefined): boolean {
1711
+ return Boolean(snapshot) && asString(snapshot?.state?.continuation_policy) === "continue";
1712
+ }
1713
+
1714
+ function isDriverContinuationStateParked(rootKey: string, fingerprint: string): boolean {
1715
+ const tracker = driverContinuationByRoot.get(rootKey);
1716
+ if (!tracker || tracker.fingerprint !== fingerprint) return false;
1717
+ return tracker.warned;
1718
+ }
1719
+
1720
+ function rememberParkedDriverContinuation(rootKey: string, fingerprint: string): void {
1721
+ const tracker = driverContinuationByRoot.get(rootKey);
1722
+ if (!tracker || tracker.fingerprint !== fingerprint) return;
1723
+ tracker.warned = true;
1724
+ tracker.inFlight = false;
1725
+ }
1726
+
1727
+ async function queueCompletionDriverPrompt(
1728
+ pi: ExtensionAPI,
1729
+ ctx: { cwd: string; hasUI: boolean; ui: any },
1730
+ rootKey: string,
1731
+ fingerprint: string,
1732
+ prompt: string,
1733
+ kind: "kickoff" | "resume" | "auto-resume",
1734
+ ): Promise<boolean> {
1735
+ const snapshotPath = kind === "auto-resume" ? completionTestAutoContinuePromptPath() : completionTestDriverPromptPath();
1736
+ maybeWriteTestSnapshot(snapshotPath, `${prompt}\n`);
1737
+ noteQueuedDriverPrompt(rootKey, fingerprint);
1738
+ if (shouldSkipDriverKickoffForTests()) {
1739
+ emitCommandText(ctx, `Skipped completion workflow ${kind} prompt (test mode)`, "info");
1740
+ return false;
1741
+ }
1742
+ pi.sendUserMessage(prompt);
1743
+ emitCommandText(ctx, `Queued completion workflow ${kind}`, "info");
1744
+ return true;
1745
+ }
1746
+
1747
+ async function autoContinueWorkflowIfNeeded(pi: ExtensionAPI, ctx: { cwd: string; hasUI: boolean; ui: any }): Promise<void> {
1748
+ if (roleFromEnv()) return;
1749
+ const snapshot = await loadCompletionSnapshot(getCtxCwd(ctx));
1750
+ const rootKey = completionRootKey(snapshot, getCtxCwd(ctx));
1751
+ if (!snapshot) {
1752
+ clearDriverContinuationTracker(rootKey);
1753
+ return;
1754
+ }
1755
+ const fingerprint = completionContinuationFingerprint(snapshot);
1756
+ if (!fingerprint) {
1757
+ clearDriverContinuationTracker(rootKey);
1758
+ return;
1759
+ }
1760
+ if (!isWorkflowDriverActive(snapshot) || hasRunningCompletionRole(rootKey)) return;
1761
+ const tracker = driverContinuationByRoot.get(rootKey);
1762
+ if (tracker && tracker.fingerprint === fingerprint) {
1763
+ if (tracker.inFlight) {
1764
+ tracker.inFlight = false;
1765
+ if (tracker.attempts >= DRIVER_AUTO_CONTINUE_MAX_ATTEMPTS) {
1766
+ if (!isDriverContinuationStateParked(rootKey, fingerprint)) {
1767
+ rememberParkedDriverContinuation(rootKey, fingerprint);
1768
+ emitCommandText(
1769
+ ctx,
1770
+ `Completion workflow is parked before mandatory role dispatch: ${asString(snapshot.state?.next_mandatory_role) ?? "(unknown)"}. Rerun /cook to continue from canonical state.`,
1771
+ "warning",
1772
+ );
1773
+ }
1774
+ return;
1775
+ }
1776
+ } else {
1777
+ return;
1778
+ }
1779
+ }
1780
+ const resumePrompt = completionResumePrompt(currentTaskType(snapshot) ?? "(missing)", currentEvaluationProfile(snapshot) ?? "(missing)");
1781
+ await queueCompletionDriverPrompt(pi, ctx, rootKey, fingerprint, resumePrompt, "auto-resume");
1782
+ }
1783
+
1644
1784
  function isRubricEvaluationRole(role: string | undefined): role is RubricEvaluationRole {
1645
1785
  return RUBRIC_EVALUATION_ROLES.includes(role as RubricEvaluationRole);
1646
1786
  }
@@ -1806,10 +1946,6 @@ function deriveMissionAnchor(rawGoal: string, projectName: string): string {
1806
1946
  .replace(/\bwith docs\b/gi, "with docs parity")
1807
1947
  .trim();
1808
1948
 
1809
- if (mission.length > 120) {
1810
- mission = `${mission.slice(0, 117).trimEnd()}...`;
1811
- }
1812
-
1813
1949
  if (!/[.!?。!?]$/u.test(mission)) mission += ".";
1814
1950
  return mission;
1815
1951
  }
@@ -2798,6 +2934,53 @@ function collapseRecentActivity(items: string[], maxItems = 4): string[] {
2798
2934
  return collapsed.slice(-maxItems);
2799
2935
  }
2800
2936
 
2937
+ function formatInlineRunningText(theme: any, lines: string[], options?: { primaryAssistant?: boolean }): string {
2938
+ let text = "";
2939
+ for (const [index, line] of lines.entries()) {
2940
+ if (index > 0) text += "\n";
2941
+ if (index === 0) {
2942
+ const [prefix, ...rest] = line.split(" ");
2943
+ text += theme.fg("warning", prefix);
2944
+ if (rest.length > 0) text += ` ${theme.fg("accent", rest.join(" "))}`;
2945
+ continue;
2946
+ }
2947
+ if (line.startsWith("tool:") || line.startsWith("progress:")) {
2948
+ text += theme.fg("toolOutput", line);
2949
+ continue;
2950
+ }
2951
+ if (line.startsWith("activity:")) {
2952
+ text += theme.fg(line.includes("stalled") ? "warning" : "dim", line);
2953
+ continue;
2954
+ }
2955
+ if (line === "recent tools:") {
2956
+ text += theme.fg("muted", line);
2957
+ continue;
2958
+ }
2959
+ if (line.startsWith("- ")) {
2960
+ text += `${theme.fg("muted", "- ")}${theme.fg("muted", line.slice(2))}`;
2961
+ continue;
2962
+ }
2963
+ if (line.startsWith("elapsed:")) {
2964
+ text += theme.fg("dim", line);
2965
+ continue;
2966
+ }
2967
+ if (line.startsWith("assistant:")) {
2968
+ text += options?.primaryAssistant ? line : theme.fg("muted", line);
2969
+ continue;
2970
+ }
2971
+ if (line.startsWith("next:") || line.startsWith("verifying:")) {
2972
+ text += theme.fg("muted", line);
2973
+ continue;
2974
+ }
2975
+ if (line.startsWith("rationale:") || line.startsWith("state-delta:")) {
2976
+ text += theme.fg("dim", line);
2977
+ continue;
2978
+ }
2979
+ text += theme.fg("muted", line);
2980
+ }
2981
+ return text;
2982
+ }
2983
+
2801
2984
  function buildInlineRunningLines(details: {
2802
2985
  role?: string;
2803
2986
  startedAt?: number;
@@ -3020,6 +3203,9 @@ function completionResumePrompt(taskType: string, evaluationProfile: string): st
3020
3203
  export default function completionExtension(pi: ExtensionAPI) {
3021
3204
  pi.on("session_start", async (_event, ctx) => {
3022
3205
  await refreshStatus(ctx);
3206
+ if (shouldTestAutoContinueOnSessionStart()) {
3207
+ await autoContinueWorkflowIfNeeded(pi, ctx);
3208
+ }
3023
3209
  });
3024
3210
 
3025
3211
  pi.on("turn_end", async (_event, ctx) => {
@@ -3032,10 +3218,16 @@ export default function completionExtension(pi: ExtensionAPI) {
3032
3218
  await fsp.rm(snapshot.files.compactionMarkerPath, { force: true });
3033
3219
  }
3034
3220
  await refreshStatus(ctx);
3221
+ await autoContinueWorkflowIfNeeded(pi, ctx);
3035
3222
  });
3036
3223
 
3037
3224
  pi.on("before_agent_start", async (_event, ctx) => {
3038
3225
  const loaded = await loadCompletionDataForReminder(getCtxCwd(ctx));
3226
+ if (loaded) {
3227
+ const rootKey = completionRootKey(loaded.snapshot, getCtxCwd(ctx));
3228
+ const fingerprint = completionContinuationFingerprint(loaded.snapshot);
3229
+ if (fingerprint) markQueuedDriverPromptInFlight(rootKey, fingerprint);
3230
+ }
3039
3231
  if (!loaded) return;
3040
3232
  const markerText = await readText(loaded.snapshot.files.compactionMarkerPath);
3041
3233
  let marker: JsonRecord | undefined;
@@ -3324,7 +3516,7 @@ export default function completionExtension(pi: ExtensionAPI) {
3324
3516
  const task = typeof args.task === "string" ? args.task.trim() : "";
3325
3517
  let text = theme.fg("toolTitle", theme.bold("completion_role ")) + theme.fg("accent", role);
3326
3518
  if (task) {
3327
- text += `\n${theme.fg("dim", task)}`;
3519
+ text += `\n${theme.fg("muted", task)}`;
3328
3520
  }
3329
3521
  return new Text(text, 0, 0);
3330
3522
  },
@@ -3352,53 +3544,26 @@ export default function completionExtension(pi: ExtensionAPI) {
3352
3544
  };
3353
3545
  if (isPartial) {
3354
3546
  const lines = buildInlineRunningLines(details);
3355
- let text = "";
3356
- for (const [index, line] of lines.entries()) {
3357
- if (index > 0) text += "\n";
3358
- if (index === 0) {
3359
- const [prefix, ...rest] = line.split(" ");
3360
- text += theme.fg("warning", prefix);
3361
- if (rest.length > 0) text += ` ${theme.fg("accent", rest.join(" "))}`;
3362
- continue;
3363
- }
3364
- if (line.startsWith("tool:") || line.startsWith("progress:")) {
3365
- text += theme.fg("toolOutput", line);
3366
- continue;
3367
- }
3368
- if (line.startsWith("activity:")) {
3369
- text += theme.fg(line.includes("stalled") ? "warning" : "dim", line);
3370
- continue;
3371
- }
3372
- if (line === "recent tools:") {
3373
- text += theme.fg("dim", line);
3374
- continue;
3375
- }
3376
- if (line.startsWith("- ")) {
3377
- text += `${theme.fg("muted", "- ")}${theme.fg("dim", line.slice(2))}`;
3378
- continue;
3379
- }
3380
- text += theme.fg("dim", line);
3381
- }
3382
- return new Text(text, 0, 0);
3547
+ return new Text(formatInlineRunningText(theme, lines), 0, 0);
3383
3548
  }
3384
3549
  const role = details.role ?? "completion-role";
3385
3550
  const ok = details.status === "ok" && !result.isError;
3386
3551
  let text = `${theme.fg(ok ? "success" : "error", ok ? "done" : "error")} ${theme.fg("toolTitle", theme.bold(role))}`;
3387
- if (details.startedAt !== undefined) text += `\n${theme.fg("dim", `elapsed: ${formatElapsed(nowMs() - details.startedAt)}`)}`;
3552
+ if (details.startedAt !== undefined) text += `\n${theme.fg("muted", `elapsed: ${formatElapsed(nowMs() - details.startedAt)}`)}`;
3388
3553
  if (details.toolActivity) text += `\n${theme.fg("toolOutput", `tool: ${details.toolActivity}`)}`;
3389
3554
  if (details.progress) text += `\n${theme.fg("toolOutput", `progress: ${details.progress}`)}`;
3390
- else if (details.assistantSummary) text += `\n${theme.fg("dim", `assistant: ${details.assistantSummary}`)}`;
3391
- if (details.rationale) text += `\n${theme.fg("dim", `rationale: ${details.rationale}`)}`;
3392
- if (details.nextStep) text += `\n${theme.fg("dim", `next: ${details.nextStep}`)}`;
3393
- if (details.verifying) text += `\n${theme.fg("dim", `verifying: ${details.verifying}`)}`;
3555
+ else if (details.assistantSummary) text += `\nassistant: ${details.assistantSummary}`;
3556
+ if (details.rationale) text += `\n${theme.fg("muted", `rationale: ${details.rationale}`)}`;
3557
+ if (details.nextStep) text += `\n${theme.fg("muted", `next: ${details.nextStep}`)}`;
3558
+ if (details.verifying) text += `\n${theme.fg("muted", `verifying: ${details.verifying}`)}`;
3394
3559
  if (details.stateDeltas?.length) {
3395
- for (const delta of details.stateDeltas.slice(-4)) text += `\n${theme.fg("dim", `state-delta: ${delta}`)}`;
3560
+ for (const delta of details.stateDeltas.slice(-4)) text += `\n${theme.fg("muted", `state-delta: ${delta}`)}`;
3396
3561
  }
3397
3562
  if (details.transcription?.appended?.length) {
3398
3563
  text += `\n${theme.fg("success", `transcribed: ${details.transcription.appended.join(", ")}`)}`;
3399
3564
  }
3400
3565
  if (details.transcription?.skipped?.length && expanded) {
3401
- text += `\n${theme.fg("dim", `skipped: ${details.transcription.skipped.join(" | ")}`)}`;
3566
+ text += `\n${theme.fg("muted", `skipped: ${details.transcription.skipped.join(" | ")}`)}`;
3402
3567
  }
3403
3568
  if (details.transcription?.errors?.length) {
3404
3569
  text += `\n${theme.fg("warning", `warnings: ${details.transcription.errors.join(" | ")}`)}`;
@@ -3416,14 +3581,14 @@ export default function completionExtension(pi: ExtensionAPI) {
3416
3581
  for (const key of summaryKeys) {
3417
3582
  const value = reportFields[key];
3418
3583
  if (!value) continue;
3419
- text += `\n${theme.fg("dim", `${key}: `)}${value}`;
3584
+ text += `\n${theme.fg("muted", `${key}: `)}${value}`;
3420
3585
  }
3421
3586
  const body = result.content.find((item) => item.type === "text");
3422
3587
  if (expanded && body?.type === "text") {
3423
3588
  text += `\n\n${body.text}`;
3424
3589
  } else if (!expanded && body?.type === "text") {
3425
3590
  const preview = body.text.split("\n").slice(0, 4).join("\n");
3426
- text += `\n${theme.fg("dim", preview)}`;
3591
+ text += `\n${theme.fg("muted", preview)}`;
3427
3592
  }
3428
3593
  if (details.stderr && expanded) text += `\n${theme.fg("error", details.stderr)}`;
3429
3594
  return new Text(text, 0, 0);
@@ -3538,13 +3703,14 @@ export default function completionExtension(pi: ExtensionAPI) {
3538
3703
  currentTaskType(snapshot) ?? "(missing)",
3539
3704
  currentEvaluationProfile(snapshot) ?? "(missing)",
3540
3705
  );
3541
- maybeWriteTestSnapshot(completionTestDriverPromptPath(), `${resumePrompt}\n`);
3542
- if (shouldSkipDriverKickoffForTests()) {
3543
- emitCommandText(ctx, "Skipped completion workflow resume kickoff (test mode)", "info");
3544
- return;
3545
- }
3546
- pi.sendUserMessage(resumePrompt);
3547
- emitCommandText(ctx, "Queued completion workflow resume", "info");
3706
+ const rootKey = completionRootKey(snapshot, getCtxCwd(ctx));
3707
+ const fingerprint = completionContinuationFingerprint(snapshot) ?? JSON.stringify({
3708
+ kind: "resume",
3709
+ mission_anchor: currentMissionAnchor(snapshot),
3710
+ current_phase: asString(snapshot.state?.current_phase) ?? null,
3711
+ next_mandatory_role: asString(snapshot.state?.next_mandatory_role) ?? null,
3712
+ });
3713
+ await queueCompletionDriverPrompt(pi, ctx, rootKey, fingerprint, resumePrompt, "resume");
3548
3714
  return;
3549
3715
  }
3550
3716
  }
@@ -3613,13 +3779,16 @@ export default function completionExtension(pi: ExtensionAPI) {
3613
3779
  kickoffIntent,
3614
3780
  kickoffMissionAnchor,
3615
3781
  );
3616
- maybeWriteTestSnapshot(completionTestDriverPromptPath(), `${kickoffPrompt}\n`);
3617
- if (shouldSkipDriverKickoffForTests()) {
3618
- emitCommandText(ctx, "Skipped completion workflow kickoff (test mode)", "info");
3619
- return;
3620
- }
3621
- pi.sendUserMessage(kickoffPrompt);
3622
- emitCommandText(ctx, "Queued completion workflow kickoff", "info");
3782
+ const rootKey = completionRootKey(snapshot, getCtxCwd(ctx));
3783
+ const fingerprint = completionContinuationFingerprint(snapshot) ?? JSON.stringify({
3784
+ kind: "kickoff",
3785
+ mission_anchor: kickoffMissionAnchor,
3786
+ goal,
3787
+ intent: kickoffIntent,
3788
+ task_type: currentTaskType(snapshot) ?? "(missing)",
3789
+ evaluation_profile: currentEvaluationProfile(snapshot) ?? "(missing)",
3790
+ });
3791
+ await queueCompletionDriverPrompt(pi, ctx, rootKey, fingerprint, kickoffPrompt, "kickoff");
3623
3792
  },
3624
3793
  });
3625
3794
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linimin/pi-letscook",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
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,
@@ -8,6 +8,7 @@ trap 'rm -rf "$TMPDIR"' EXIT
8
8
  ROOT="$TMPDIR/repo"
9
9
  KICKOFF_PROMPT="$TMPDIR/kickoff-prompt.txt"
10
10
  RESUME_PROMPT="$TMPDIR/resume-prompt.txt"
11
+ AUTO_RESUME_PROMPT="$TMPDIR/auto-resume-prompt.txt"
11
12
 
12
13
  mkdir -p "$ROOT"
13
14
  cd "$ROOT"
@@ -72,6 +73,26 @@ assert f'- task_type: {expected_task_type}' in resume, 'resume prompt missing ca
72
73
  assert f'- evaluation_profile: {expected_eval_profile}' in resume, 'resume prompt missing canonical evaluation_profile'
73
74
  PY
74
75
 
76
+ PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
77
+ PI_COMPLETION_TEST_AUTO_CONTINUE_ON_SESSION_START=1 \
78
+ PI_COMPLETION_TEST_AUTO_CONTINUE_PROMPT_PATH="$AUTO_RESUME_PROMPT" \
79
+ pi -e "$PKG_ROOT" -p "/cook" \
80
+ >"$TMPDIR/pi-completion-smoke-auto-resume.out" 2>"$TMPDIR/pi-completion-smoke-auto-resume.err"
81
+
82
+ python3 - "$AUTO_RESUME_PROMPT" <<'PY'
83
+ import sys
84
+ from pathlib import Path
85
+
86
+ expected_task_type = 'completion-workflow'
87
+ expected_eval_profile = 'completion-rubric-v1'
88
+ auto_resume = Path(sys.argv[1]).read_text()
89
+
90
+ assert 'Resume the completion workflow from canonical state.' in auto_resume, 'auto-resume prompt should use the canonical resume workflow prompt'
91
+ assert 'Canonical routing profile:' in auto_resume, 'auto-resume prompt should expose canonical routing profile'
92
+ assert f'- task_type: {expected_task_type}' in auto_resume, 'auto-resume prompt missing canonical task_type'
93
+ assert f'- evaluation_profile: {expected_eval_profile}' in auto_resume, 'auto-resume prompt missing canonical evaluation_profile'
94
+ PY
95
+
75
96
  python3 - <<'PY'
76
97
  import json
77
98
  from pathlib import Path