@linimin/pi-letscook 0.1.67 → 0.1.69

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.
@@ -24,26 +24,6 @@ export type AdvisoryStartupBrief = {
24
24
  evaluation_profile?: string;
25
25
  };
26
26
 
27
- export type ApprovedStartupPlan = {
28
- artifact_type: "completion-startup-plan";
29
- schema_version: 1;
30
- status: "approved";
31
- source: AdvisoryStartupBrief["source"];
32
- captured_at: string;
33
- mission_anchor: string;
34
- goal_text: string;
35
- task_type?: string;
36
- evaluation_profile?: string;
37
- scope: string[];
38
- constraints: string[];
39
- acceptance: string[];
40
- risks: string[];
41
- notes: string[];
42
- planned_surfaces: string[];
43
- verification_intent: string[];
44
- sequencing_hints: string[];
45
- };
46
-
47
27
  export function buildCookHandoffBoundaryReminder(): string {
48
28
  return [
49
29
  "You are in ordinary main chat unless the user explicitly runs /cook.",
@@ -53,11 +33,10 @@ export function buildCookHandoffBoundaryReminder(): string {
53
33
  "In ordinary chat, do not load or follow completion-protocol, and do not call completion_role.",
54
34
  "If the user wants direct implementation now, stay in ordinary chat and help directly instead of blocking on /cook.",
55
35
  "If the user asks follow-up questions or wants to keep refining scope, continue helping naturally in ordinary chat.",
56
- "If the user explicitly runs /cook, the extension should call a primary-agent startup-plan synthesis step from the current task context, show Start/Cancel confirmation in the same /cook entry, and only write the approved plan into .agent after Start.",
57
- "Do not expect /cook to infer or guess startup intent from recent discussion alone; /cook should use primary-agent-authored startup-plan data, whether it already exists as preview intake or is synthesized in the same /cook entry.",
58
- "Only provide a preview startup plan or ```cook_handoff``` capsule in ordinary chat when the user explicitly asks for that preview behavior.",
36
+ "If the user explicitly runs /cook, the extension should call a primary-agent handoff synthesis step from the current task context, show Start/Cancel confirmation, and persist the confirmed startup brief into .agent/** without making the user rerun /cook.",
37
+ "Do not expect /cook to infer or guess startup intent from recent discussion alone; /cook should use explicit primary-agent handoff data, whether it already exists or is synthesized in the same /cook entry.",
38
+ "Only provide a preview startup brief or ```cook_handoff``` capsule in ordinary chat when the user explicitly asks for that preview behavior.",
59
39
  "Any preview capsule is startup intake for /cook only: do not present it as canonical .agent state, an active slice, or a persistent repo contract.",
60
- "When /cook starts, the approved startup plan should be written into .agent and then handed to completion-regrounder so canonical slices can be derived from repo truth.",
61
40
  "When you continue in ordinary chat, do not pretend /cook already started and do not silently rewrite discussion into canonical workflow state.",
62
41
  ].join(" ");
63
42
  }
@@ -109,27 +88,6 @@ function buildAdvisoryStartupBriefNotes(analysis: ContextProposalAnalysis): stri
109
88
  return notes.length > 0 ? notes : ["No additional operator notes were derived from recent discussion."];
110
89
  }
111
90
 
112
- function startupPlanSourceForProposal(source: ContextProposal["source"]): AdvisoryStartupBrief["source"] {
113
- return source === "handoff_capsule"
114
- ? "primary_agent_handoff"
115
- : source === "deferred_primary_agent_handoff"
116
- ? "deferred_primary_agent_handoff"
117
- : "recent_discussion";
118
- }
119
-
120
- function extractDelimitedNoteValues(notes: string[], prefix: string): string[] {
121
- return notes.flatMap((note) => {
122
- if (!note.startsWith(prefix)) return [];
123
- return note.slice(prefix.length).split("|").map((item) => item.trim()).filter(Boolean);
124
- });
125
- }
126
-
127
- function extractSequencingHints(notes: string[]): string[] {
128
- return notes.filter((note) =>
129
- note.startsWith("First slice goal:") || note.startsWith("First slice non-goals:") || note.startsWith("Why this slice first:"),
130
- );
131
- }
132
-
133
91
  export function buildAdvisoryStartupBrief(args: {
134
92
  proposal: Pick<ContextProposal, "goalText" | "mission" | "scope" | "constraints" | "acceptance" | "source">;
135
93
  analysis: ContextProposalAnalysis;
@@ -137,7 +95,12 @@ export function buildAdvisoryStartupBrief(args: {
137
95
  }): AdvisoryStartupBrief {
138
96
  return {
139
97
  kind: "startup_brief",
140
- source: startupPlanSourceForProposal(args.proposal.source),
98
+ source:
99
+ args.proposal.source === "handoff_capsule"
100
+ ? "primary_agent_handoff"
101
+ : args.proposal.source === "deferred_primary_agent_handoff"
102
+ ? "deferred_primary_agent_handoff"
103
+ : "recent_discussion",
141
104
  confirmed: true,
142
105
  captured_at: args.capturedAt ?? new Date().toISOString(),
143
106
  goal_text: args.proposal.goalText,
@@ -152,81 +115,6 @@ export function buildAdvisoryStartupBrief(args: {
152
115
  };
153
116
  }
154
117
 
155
- export function buildApprovedStartupPlan(args: {
156
- proposal: Pick<ContextProposal, "goalText" | "mission" | "scope" | "constraints" | "acceptance" | "source">;
157
- analysis: ContextProposalAnalysis;
158
- missionAnchor?: string;
159
- capturedAt?: string;
160
- }): ApprovedStartupPlan {
161
- const capturedAt = args.capturedAt ?? new Date().toISOString();
162
- const notes = buildAdvisoryStartupBriefNotes(args.analysis);
163
- return {
164
- artifact_type: "completion-startup-plan",
165
- schema_version: 1,
166
- status: "approved",
167
- source: startupPlanSourceForProposal(args.proposal.source),
168
- captured_at: capturedAt,
169
- mission_anchor: args.missionAnchor ?? args.proposal.mission,
170
- goal_text: args.proposal.goalText,
171
- task_type: args.analysis.taskType,
172
- evaluation_profile: args.analysis.evaluationProfile,
173
- scope: [...args.proposal.scope],
174
- constraints: [...args.proposal.constraints],
175
- acceptance: [...args.proposal.acceptance],
176
- risks: [...args.analysis.risks],
177
- notes: [...notes],
178
- planned_surfaces: extractDelimitedNoteValues(notes, "Implementation surfaces:"),
179
- verification_intent: extractDelimitedNoteValues(notes, "Verification commands:"),
180
- sequencing_hints: extractSequencingHints(notes),
181
- };
182
- }
183
-
184
- export function buildApprovedStartupPlanMarkdown(plan: ApprovedStartupPlan): string {
185
- const lines = [
186
- "# Approved Startup Plan",
187
- "",
188
- `Mission anchor: ${plan.mission_anchor}`,
189
- `Source: ${plan.source}`,
190
- `Captured at: ${plan.captured_at}`,
191
- ];
192
- if (plan.task_type) lines.push(`Task type: ${plan.task_type}`);
193
- if (plan.evaluation_profile) lines.push(`Evaluation profile: ${plan.evaluation_profile}`);
194
- lines.push("", "## Goal", "", plan.goal_text);
195
- if (plan.scope.length > 0) {
196
- lines.push("", "## Scope", "");
197
- for (const item of plan.scope) lines.push(`- ${item}`);
198
- }
199
- if (plan.constraints.length > 0) {
200
- lines.push("", "## Constraints", "");
201
- for (const item of plan.constraints) lines.push(`- ${item}`);
202
- }
203
- if (plan.acceptance.length > 0) {
204
- lines.push("", "## Acceptance", "");
205
- for (const item of plan.acceptance) lines.push(`- ${item}`);
206
- }
207
- if (plan.risks.length > 0) {
208
- lines.push("", "## Risks", "");
209
- for (const item of plan.risks) lines.push(`- ${item}`);
210
- }
211
- if (plan.planned_surfaces.length > 0) {
212
- lines.push("", "## Planned surfaces", "");
213
- for (const item of plan.planned_surfaces) lines.push(`- ${item}`);
214
- }
215
- if (plan.verification_intent.length > 0) {
216
- lines.push("", "## Verification intent", "");
217
- for (const item of plan.verification_intent) lines.push(`- ${item}`);
218
- }
219
- if (plan.sequencing_hints.length > 0) {
220
- lines.push("", "## Sequencing hints", "");
221
- for (const item of plan.sequencing_hints) lines.push(`- ${item}`);
222
- }
223
- if (plan.notes.length > 0) {
224
- lines.push("", "## Notes", "");
225
- for (const item of plan.notes) lines.push(`- ${item}`);
226
- }
227
- return `${lines.join("\n")}\n`;
228
- }
229
-
230
118
  export function buildContextProposalCritiqueText(analysis: ContextProposalAnalysis): string {
231
119
  const lines: string[] = [];
232
120
  if (analysis.critique.length > 0) {
@@ -259,7 +147,7 @@ export function buildContextProposalCritiqueText(analysis: ContextProposalAnalys
259
147
  for (const item of analysis.suppressedNegatedTopics) lines.push(`- ${item}`);
260
148
  }
261
149
  if (lines.length === 0) {
262
- return "No additional operator notes or risks were derived for this startup plan.";
150
+ return "No additional operator notes or risks were derived for this startup brief.";
263
151
  }
264
152
  return lines.join("\n");
265
153
  }
@@ -308,7 +196,7 @@ export function buildContextProposalConfirmationActions(mainChatRerunGuidance: s
308
196
  {
309
197
  id: "start",
310
198
  label: "Start",
311
- description: "Accept this startup plan and let /cook write or refocus canonical workflow state.",
199
+ description: "Accept this startup brief and let /cook write or refocus canonical workflow state.",
312
200
  },
313
201
  {
314
202
  id: "cancel",
@@ -328,8 +216,8 @@ export function buildContextProposalConfirmationLayout(args: {
328
216
  }): ContextProposalConfirmationLayout {
329
217
  return {
330
218
  title: args.title,
331
- intro: "Review the startup plan (mission, scope, constraints, acceptance, and notes/risks) plus the routing details before /cook writes canonical workflow state. This gate is approval-only: either Start it as-is or Cancel, discuss changes in the main chat, and rerun /cook.",
332
- proposalHeading: "Startup plan",
219
+ intro: "Review the startup brief (mission, scope, constraints, acceptance, and notes/risks) plus the routing details before /cook writes canonical workflow state. This gate is approval-only: either Start it as-is or Cancel, discuss changes in the main chat, and rerun /cook.",
220
+ proposalHeading: "Startup brief",
333
221
  proposalBody: buildContextProposalDisplayText(args.proposal),
334
222
  critiqueHeading: "Notes and risks",
335
223
  critiqueBody: buildContextProposalCritiqueText(args.analysis),
@@ -529,15 +417,6 @@ type CompletionVerificationEvidenceSummary = {
529
417
  summary: string;
530
418
  };
531
419
 
532
- type CompletionStartupPlanSummary = {
533
- path: string;
534
- status: string;
535
- source?: string;
536
- plannedSurfaces: string[];
537
- verificationIntent: string[];
538
- summary: string;
539
- };
540
-
541
420
  export function buildSystemReminder(args: {
542
421
  missionAnchor?: string;
543
422
  taskType?: string;
@@ -561,12 +440,11 @@ export function buildSystemReminder(args: {
561
440
  implementationSurfacesLine?: string;
562
441
  verificationCommandsLine?: string;
563
442
  evidence: CompletionVerificationEvidenceSummary;
564
- startupPlan: CompletionStartupPlanSummary;
565
443
  evaluationRoleReminderText?: string;
566
444
  }): string {
567
445
  const lines = [
568
446
  "Completion workflow detected.",
569
- "Canonical truth lives in .agent/state.json, .agent/startup-plan.json, .agent/plan.json, .agent/active-slice.json, .agent/slice-history.jsonl, .agent/stop-check-history.jsonl, and .agent/verification-evidence.json.",
447
+ "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.",
570
448
  `Mission anchor: ${args.missionAnchor ?? "(unknown)"}`,
571
449
  `Task type: ${args.taskType ?? "(missing)"}`,
572
450
  `Evaluation profile: ${args.evaluationProfile ?? "(missing)"}`,
@@ -583,7 +461,6 @@ export function buildSystemReminder(args: {
583
461
  "Only stop for the user when continuation_policy is await_user_input, blocked, paused, or done.",
584
462
  "If canonical state is stale, invalid, ambiguous, or missing, route to completion-regrounder.",
585
463
  "When recovering from compaction, prefer a deterministic restart from canonical files over conversational inference.",
586
- `Approved startup plan: ${args.startupPlan.path} (${args.startupPlan.status})`,
587
464
  ];
588
465
  if (args.exactActiveContract) {
589
466
  lines.push("Selected/in-progress/committed/done .agent/active-slice.json is the canonical implementation contract.");
@@ -597,14 +474,6 @@ export function buildSystemReminder(args: {
597
474
  else if (args.implementationSurfaces.length > 0) lines.push(`Active implementation surfaces: ${args.implementationSurfaces.join(", ")}`);
598
475
  if (args.verificationCommandsLine) lines.push(args.verificationCommandsLine);
599
476
  else if (args.verificationCommands.length > 0) lines.push(`Active verification commands: ${args.verificationCommands.join(" | ")}`);
600
- if (args.startupPlan.source) lines.push(`Approved startup plan source: ${args.startupPlan.source}`);
601
- if (args.startupPlan.plannedSurfaces.length > 0) {
602
- lines.push(`Approved startup plan surfaces: ${args.startupPlan.plannedSurfaces.join(" | ")}`);
603
- }
604
- if (args.startupPlan.verificationIntent.length > 0) {
605
- lines.push(`Approved startup plan verification intent: ${args.startupPlan.verificationIntent.join(" | ")}`);
606
- }
607
- lines.push(`Approved startup plan summary: ${args.startupPlan.summary}`);
608
477
  lines.push(`Verification evidence artifact: ${args.evidence.path} (${args.evidence.status})`);
609
478
  if (args.evidence.subjectType) lines.push(`Verification evidence subject: ${args.evidence.subjectType}`);
610
479
  if (args.evidence.outcome) lines.push(`Verification evidence outcome: ${args.evidence.outcome}`);
@@ -633,7 +502,6 @@ export function buildResumeCapsule(args: {
633
502
  activeSliceMatchesPlan: "yes" | "no" | "unknown";
634
503
  activeSliceContractDrift: string;
635
504
  implementerHandoffSnapshot: "present" | "missing_or_unclear";
636
- startupPlan: CompletionStartupPlanSummary;
637
505
  evidence: CompletionVerificationEvidenceSummary;
638
506
  activeSlice: {
639
507
  sliceId?: string;
@@ -676,14 +544,6 @@ export function buildResumeCapsule(args: {
676
544
  `implementer_handoff_snapshot: ${args.implementerHandoffSnapshot}`,
677
545
  `history_counts: reviewed=${args.history.reviewed}, audited=${args.history.audited}, accepted=${args.history.accepted}, reopened=${args.history.reopened}, judgments=${args.history.judgments}`,
678
546
  "",
679
- "startup_plan:",
680
- `- path: ${args.startupPlan.path}`,
681
- `- status: ${args.startupPlan.status}`,
682
- `- source: ${args.startupPlan.source ?? "(missing)"}`,
683
- `- planned_surfaces: ${args.startupPlan.plannedSurfaces.length > 0 ? args.startupPlan.plannedSurfaces.join(" | ") : "(none)"}`,
684
- `- verification_intent: ${args.startupPlan.verificationIntent.length > 0 ? args.startupPlan.verificationIntent.join(" | ") : "(none)"}`,
685
- `- summary: ${args.startupPlan.summary}`,
686
- "",
687
547
  "verification_evidence:",
688
548
  `- path: ${args.evidence.path}`,
689
549
  `- status: ${args.evidence.status}`,
@@ -731,9 +591,8 @@ export function buildResumeCapsule(args: {
731
591
  "- Treat this block as continuity support derived from canonical .agent state.",
732
592
  "- For selected/in-progress/committed/done slices, .agent/active-slice.json is the canonical implementation contract and the selected plan slice must mirror it exactly.",
733
593
  "- Preserve exact slice_id, goal, contract_ids, acceptance criteria, blocked_on, priority, why_now, implementation surfaces, verification commands, locked notes, must-fix findings, basis_commit, and before-slice counters where still true.",
734
- "- .agent/startup-plan.json is the approved workflow plan captured at /cook entry. completion-regrounder must treat it as planning input, then reconcile canonical slices against repo truth instead of copying it blindly into plan.json.",
735
594
  "- When populated, .agent/verification-evidence.json is the durable canonical verification record for the selected slice or current HEAD and should be consumed instead of temp-only artifacts or conversational summaries.",
736
- "- After compaction, re-read .agent/state.json, .agent/startup-plan.json, .agent/plan.json, .agent/active-slice.json, .agent/slice-history.jsonl, .agent/stop-check-history.jsonl, and .agent/verification-evidence.json before resuming long-running completion work.",
595
+ "- After compaction, re-read .agent/state.json, .agent/plan.json, .agent/active-slice.json, .agent/slice-history.jsonl, .agent/stop-check-history.jsonl, and .agent/verification-evidence.json before resuming long-running completion work.",
737
596
  "- Invoke completion-regrounder before continuing when requires_reground is true or unknown.",
738
597
  "- Invoke completion-regrounder before continuing when next_mandatory_role or next_mandatory_action is unknown or ambiguous.",
739
598
  "- Invoke completion-regrounder before continuing when active_slice_matches_plan is no, active_slice_contract_drift_fields is not none, or implementer_handoff_snapshot is missing_or_unclear.",
@@ -60,11 +60,11 @@ export type CookHandoffCapsule = {
60
60
  risks: string[];
61
61
  notes: string[];
62
62
  handoff_kind: "implementation_workflow_handoff";
63
- first_slice_goal?: string;
63
+ first_slice_goal: string;
64
64
  first_slice_non_goals: string[];
65
65
  implementation_surfaces: string[];
66
66
  verification_commands: string[];
67
- why_this_slice_first?: string;
67
+ why_this_slice_first: string;
68
68
  task_type?: string;
69
69
  evaluation_profile?: string;
70
70
  why_cook_now?: string;
@@ -1279,7 +1279,7 @@ function parseCookHandoffCapsulesFromText(
1279
1279
  const mission = deps.asString(parsed.mission);
1280
1280
  const firstSliceGoal = deps.asString(parsed.first_slice_goal ?? parsed.firstSliceGoal);
1281
1281
  const whyThisSliceFirst = deps.asString(parsed.why_this_slice_first ?? parsed.whyThisSliceFirst);
1282
- if (!mission) continue;
1282
+ if (!mission || !firstSliceGoal || !whyThisSliceFirst) continue;
1283
1283
  const scope = deps.asStringArray(parsed.scope);
1284
1284
  const constraints = deps.asStringArray(parsed.constraints);
1285
1285
  const nonGoals = deps.asStringArray(parsed.non_goals ?? parsed.nonGoals);
@@ -1325,12 +1325,12 @@ function buildCookHandoffBasisPreview(capsule: CookHandoffCapsule): string {
1325
1325
  ...capsule.constraints,
1326
1326
  ...capsule.non_goals,
1327
1327
  ...capsule.acceptance,
1328
+ `first_slice_goal: ${capsule.first_slice_goal}`,
1329
+ ...capsule.first_slice_non_goals.map((item) => `first_slice_non_goals: ${item}`),
1330
+ ...capsule.implementation_surfaces.map((item) => `implementation_surfaces: ${item}`),
1331
+ ...capsule.verification_commands.map((item) => `verification_commands: ${item}`),
1332
+ `why_this_slice_first: ${capsule.why_this_slice_first}`,
1328
1333
  ];
1329
- if (capsule.first_slice_goal) parts.push(`first_slice_goal: ${capsule.first_slice_goal}`);
1330
- parts.push(...capsule.first_slice_non_goals.map((item) => `first_slice_non_goals: ${item}`));
1331
- parts.push(...capsule.implementation_surfaces.map((item) => `implementation_surfaces: ${item}`));
1332
- parts.push(...capsule.verification_commands.map((item) => `verification_commands: ${item}`));
1333
- if (capsule.why_this_slice_first) parts.push(`why_this_slice_first: ${capsule.why_this_slice_first}`);
1334
1334
  if (capsule.why_cook_now) parts.push(`why_cook_now: ${capsule.why_cook_now}`);
1335
1335
  return parts.join("\n").trim();
1336
1336
  }
@@ -1363,21 +1363,21 @@ function cookHandoffStartabilityFailures(
1363
1363
  else if (!cookHandoffAcceptanceIsRepoChangeOriented(capsule)) {
1364
1364
  failures.push("acceptance is not anchored to concrete repo changes or verification");
1365
1365
  }
1366
- if (capsule.first_slice_goal) {
1367
- const firstSliceGoal = deps.normalizeMissionAnchorText(capsule.first_slice_goal);
1368
- if (!firstSliceGoal || deps.isWeakMissionAnchor(firstSliceGoal) || COOK_HANDOFF_NEGATIVE_MISSION_REGEX.test(firstSliceGoal)) {
1369
- failures.push("first_slice_goal is not a useful sequencing hint");
1370
- } else if (hasExplicitPlanningOnlyDeliverable([capsule.first_slice_goal]) || hasClearNoImplementationSignal([capsule.first_slice_goal])) {
1371
- failures.push("first_slice_goal is planning-only instead of a repo-change sequencing hint");
1372
- }
1366
+ const firstSliceGoal = deps.normalizeMissionAnchorText(capsule.first_slice_goal);
1367
+ if (!firstSliceGoal || deps.isWeakMissionAnchor(firstSliceGoal) || COOK_HANDOFF_NEGATIVE_MISSION_REGEX.test(firstSliceGoal)) {
1368
+ failures.push("first_slice_goal is not a bounded implementation slice");
1369
+ } else if (hasExplicitPlanningOnlyDeliverable([capsule.first_slice_goal]) || hasClearNoImplementationSignal([capsule.first_slice_goal])) {
1370
+ failures.push("first_slice_goal is planning-only instead of a repo-change slice");
1373
1371
  }
1372
+ if (capsule.implementation_surfaces.length === 0) failures.push("implementation_surfaces is empty");
1373
+ if (capsule.verification_commands.length === 0) failures.push("verification_commands is empty");
1374
1374
  return failures;
1375
1375
  }
1376
1376
 
1377
1377
  function buildNonStartableCookHandoffMessage(failures: string[]): string {
1378
1378
  return [
1379
- "/cook failed closed because a fresh explicit primary-agent startup plan exists, but it is not concrete enough to seed workflow planning yet.",
1380
- "Tighten the startup plan in the main chat so it captures a concrete mission, repo-change-oriented acceptance, and truthful verification intent, then rerun /cook.",
1379
+ "/cook failed closed because a fresh explicit primary-agent handoff exists, but it is not concrete enough to start implementation workflow yet.",
1380
+ "Tighten the handoff in the main chat so it names a bounded first implementation slice, repo-change-oriented acceptance, implementation_surfaces, and verification_commands, then rerun /cook.",
1381
1381
  `Blocking details: ${failures.join("; ")}.`,
1382
1382
  ].join(" ");
1383
1383
  }
@@ -1435,11 +1435,11 @@ function buildContextProposalFromCookHandoffCapsule(
1435
1435
  evaluationProfile: capsule.evaluation_profile,
1436
1436
  critique: [
1437
1437
  ...capsule.notes,
1438
- ...(capsule.first_slice_goal ? [`First slice goal: ${capsule.first_slice_goal}`] : []),
1438
+ `First slice goal: ${capsule.first_slice_goal}`,
1439
1439
  ...(capsule.first_slice_non_goals.length > 0 ? [`First slice non-goals: ${capsule.first_slice_non_goals.join(" | ")}`] : []),
1440
1440
  ...(capsule.implementation_surfaces.length > 0 ? [`Implementation surfaces: ${capsule.implementation_surfaces.join(" | ")}`] : []),
1441
1441
  ...(capsule.verification_commands.length > 0 ? [`Verification commands: ${capsule.verification_commands.join(" | ")}`] : []),
1442
- ...(capsule.why_this_slice_first ? [`Why this slice first: ${capsule.why_this_slice_first}`] : []),
1442
+ `Why this slice first: ${capsule.why_this_slice_first}`,
1443
1443
  ...(capsule.why_cook_now ? [`Primary-agent /cook handoff rationale: ${capsule.why_cook_now}`] : []),
1444
1444
  ],
1445
1445
  risks: capsule.risks,
@@ -1455,11 +1455,11 @@ function buildContextProposalFromCookHandoffCapsule(
1455
1455
  ...capsule.scope,
1456
1456
  ...constraints,
1457
1457
  ...capsule.acceptance,
1458
- ...(capsule.first_slice_goal ? [capsule.first_slice_goal] : []),
1458
+ capsule.first_slice_goal,
1459
1459
  ...capsule.first_slice_non_goals,
1460
1460
  ...capsule.implementation_surfaces,
1461
1461
  ...capsule.verification_commands,
1462
- ...(capsule.why_this_slice_first ? [capsule.why_this_slice_first] : []),
1462
+ capsule.why_this_slice_first,
1463
1463
  ],
1464
1464
  ),
1465
1465
  goalText,
@@ -97,15 +97,14 @@ const STARTUP_ANALYST_ROLE = "cook-proposal-analyst";
97
97
  const ANALYST_HEARTBEAT_MS = 5_000;
98
98
 
99
99
  const PRIMARY_AGENT_HANDOFF_SYSTEM_PROMPT = [
100
- "You are the primary agent preparing an explicit /cook startup plan after the user already chose workflow mode.",
101
- "Return either exactly one fenced ```cook_handoff JSON block or one brief plain sentence explaining why no concrete startup plan can be prepared.",
102
- "If you can prepare a plan, the JSON must use kind cook_handoff, source primary_agent, and handoff_kind implementation_workflow_handoff.",
103
- "Author the approved workflow startup plan now from the primary-agent view of the task so /cook can persist it under .agent before completion-regrounder derives canonical slices.",
104
- "Capture the agreed mission, scope, constraints or non_goals, acceptance, risks, notes, and any concrete planning hints that will help completion-regrounder split slices later.",
105
- "If a bounded first slice, likely implementation surfaces, or likely verification commands are already obvious, include first_slice_goal, first_slice_non_goals, implementation_surfaces, verification_commands, and why_this_slice_first as optional hints only. They are not required when the overall startup plan is already concrete enough to begin workflow planning.",
106
- "Do not make /cook infer or rediscover the mission from recent discussion later; author the startup plan now from the primary-agent view of the task.",
100
+ "You are the primary agent preparing an explicit /cook handoff after the user already chose workflow mode.",
101
+ "Return either exactly one fenced ```cook_handoff JSON block or one brief plain sentence explaining why no concrete handoff can be prepared.",
102
+ "If you can prepare a handoff, the JSON must use kind cook_handoff, source primary_agent, and handoff_kind implementation_workflow_handoff.",
103
+ "When the user has clearly accepted a concrete assistant-proposed slice, carry that slice forward into the handoff instead of broadening or re-guessing the mission.",
104
+ "Do not make /cook infer or rediscover the mission from recent discussion later; author the handoff now from the primary-agent view of the task.",
107
105
  "Do not emit markdown commentary before or after the capsule.",
108
- "If the task is not concrete enough for workflow startup, do not invent missing detail.",
106
+ "If the task is not concrete enough for implementation workflow, do not invent the slice.",
107
+ "A valid implementation-ready handoff must include mission, scope, constraints or non_goals, acceptance, risks, notes, first_slice_goal, first_slice_non_goals, implementation_surfaces, verification_commands, and why_this_slice_first.",
109
108
  ].join(" ");
110
109
  const PRIMARY_AGENT_HANDOFF_ROLE = "cook-primary-agent-handoff";
111
110
 
@@ -343,7 +342,7 @@ function buildPrimaryAgentHandoffPrompt(projectName: string, recentEntries: Rece
343
342
  lines.push(
344
343
  "",
345
344
  "Task:",
346
- "The user explicitly invoked /cook. Prepare the primary-agent startup plan that /cook should consume immediately for Start/Cancel confirmation, persistence under .agent, and later slice derivation by completion-regrounder.",
345
+ "The user explicitly invoked /cook. Prepare the primary-agent handoff that /cook should consume immediately for Start/Cancel confirmation.",
347
346
  );
348
347
  return lines.join("\n");
349
348
  }
@@ -360,7 +359,7 @@ async function runPrimaryAgentHandoffSubprocess(params: GenerateCookHandoffWithA
360
359
  const invocation = getPiInvocation(args);
361
360
  const liveActivity = createLiveRoleActivity(PRIMARY_AGENT_HANDOFF_ROLE);
362
361
  liveActivity.progress = "Preparing primary-agent /cook handoff";
363
- liveActivity.currentAction = "Authoring explicit startup plan from current task context";
362
+ liveActivity.currentAction = "Authoring explicit startup handoff from current task context";
364
363
  liveActivity.assistantSummary = liveActivity.progress;
365
364
  try {
366
365
  const output = await new Promise<string | undefined>((resolve) => {
@@ -410,7 +409,7 @@ export async function generateCookHandoffWithAgent(params: GenerateCookHandoffWi
410
409
  try {
411
410
  return await runPrimaryAgentHandoffSubprocess(params);
412
411
  } catch (error) {
413
- console.warn("[completion] primary-agent startup-plan generation failed", error);
412
+ console.warn("[completion] primary-agent handoff generation failed", error);
414
413
  return undefined;
415
414
  }
416
415
  }