@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.
@@ -3,7 +3,6 @@ import { spawnSync } from "node:child_process";
3
3
  import { promises as fsp } from "node:fs";
4
4
  import * as os from "node:os";
5
5
  import * as path from "node:path";
6
- import { buildApprovedStartupPlanMarkdown } from "./prompt-surfaces";
7
6
  import type { CompletionStateSnapshot, JsonRecord } from "./types";
8
7
 
9
8
  const PROTOCOL_ID = "completion";
@@ -46,10 +45,9 @@ export function resolveFiles(root: string) {
46
45
  statePath: path.join(agentDir, "state.json"),
47
46
  planPath: path.join(agentDir, "plan.json"),
48
47
  activePath: path.join(agentDir, "active-slice.json"),
49
- startupPlanPath: path.join(agentDir, "startup-plan.json"),
50
- startupPlanMarkdownPath: path.join(agentDir, "startup-plan.md"),
51
48
  sliceHistoryPath: path.join(agentDir, "slice-history.jsonl"),
52
49
  stopHistoryPath: path.join(agentDir, "stop-check-history.jsonl"),
50
+ startupBriefPath: path.join(agentDir, "startup-brief.json"),
53
51
  verificationEvidencePath: path.join(agentDir, "verification-evidence.json"),
54
52
  compactionMarkerPath: path.join(tmpDir, "post-compaction-recovery.json"),
55
53
  };
@@ -144,7 +142,7 @@ export async function loadCompletionSnapshot(startCwd: string): Promise<Completi
144
142
  const state = await readJson(files.statePath);
145
143
  const plan = await readJson(files.planPath);
146
144
  const active = await readJson(files.activePath);
147
- const startupPlan = await readJson(files.startupPlanPath);
145
+ const startupBrief = await readJson(files.startupBriefPath);
148
146
  const verificationEvidence = await readJson(files.verificationEvidencePath);
149
147
  return {
150
148
  files,
@@ -152,7 +150,7 @@ export async function loadCompletionSnapshot(startCwd: string): Promise<Completi
152
150
  state,
153
151
  plan,
154
152
  active,
155
- startupPlan,
153
+ startupBrief,
156
154
  verificationEvidence,
157
155
  activeSlice: findActiveSlice(plan, active),
158
156
  };
@@ -233,15 +231,25 @@ export function buildProfileRecord(args: {
233
231
  };
234
232
  }
235
233
 
234
+ function buildWorkflowSessionId(): string {
235
+ return `wf-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
236
+ }
237
+
236
238
  export function defaultState(
237
239
  missionAnchor: string,
238
240
  routing?: { taskType?: string; evaluationProfile?: string; continuationReason?: string },
239
241
  advisoryStartupBrief?: JsonRecord,
240
242
  ): JsonRecord {
243
+ const confirmedAt = asString(advisoryStartupBrief?.captured_at) ?? new Date().toISOString();
241
244
  return {
242
245
  schema_version: 1,
243
246
  mission_anchor: missionAnchor,
244
247
  advisory_startup_brief: advisoryStartupBrief ?? null,
248
+ workflow_entry_status: "active",
249
+ workflow_entry_source: "/cook",
250
+ workflow_entry_confirmed_at: confirmedAt,
251
+ workflow_session_id: buildWorkflowSessionId(),
252
+ startup_brief_path: ".agent/startup-brief.json",
245
253
  current_phase: "reground",
246
254
  continuation_policy: "continue",
247
255
  continuation_reason: routing?.continuationReason ?? "Fresh completion bootstrap requires canonical re-ground",
@@ -280,32 +288,6 @@ export function defaultPlan(
280
288
  };
281
289
  }
282
290
 
283
- export function defaultStartupPlan(
284
- missionAnchor: string,
285
- routing?: { taskType?: string; evaluationProfile?: string },
286
- approvedStartupPlan?: JsonRecord,
287
- ): JsonRecord {
288
- return approvedStartupPlan ?? {
289
- schema_version: 1,
290
- artifact_type: "completion-startup-plan",
291
- status: "approved",
292
- source: "recent_discussion",
293
- captured_at: null,
294
- mission_anchor: missionAnchor,
295
- goal_text: `Mission: ${missionAnchor}`,
296
- task_type: routing?.taskType ?? DEFAULT_TASK_TYPE,
297
- evaluation_profile: routing?.evaluationProfile ?? DEFAULT_EVALUATION_PROFILE,
298
- scope: [],
299
- constraints: [],
300
- acceptance: [],
301
- risks: [],
302
- notes: ["No approved startup plan has been recorded yet."],
303
- planned_surfaces: [],
304
- verification_intent: [],
305
- sequencing_hints: [],
306
- };
307
- }
308
-
309
291
  export function defaultActiveSlice(
310
292
  missionAnchor: string,
311
293
  routing?: { taskType?: string; evaluationProfile?: string },
@@ -334,6 +316,32 @@ export function defaultActiveSlice(
334
316
  };
335
317
  }
336
318
 
319
+ export function defaultStartupBrief(
320
+ missionAnchor: string,
321
+ routing?: { taskType?: string; evaluationProfile?: string },
322
+ advisoryStartupBrief?: JsonRecord,
323
+ ): JsonRecord {
324
+ return {
325
+ schema_version: 1,
326
+ artifact_type: "completion-startup-brief",
327
+ source: asString(advisoryStartupBrief?.source) ?? "primary_agent",
328
+ confirmed: true,
329
+ confirmed_at: asString(advisoryStartupBrief?.captured_at) ?? new Date().toISOString(),
330
+ mission: asString(advisoryStartupBrief?.mission) ?? missionAnchor,
331
+ goal_text: asString(advisoryStartupBrief?.goal_text) ?? `Mission: ${missionAnchor}`,
332
+ scope: asStringArray(advisoryStartupBrief?.scope),
333
+ constraints: asStringArray(advisoryStartupBrief?.constraints),
334
+ acceptance: asStringArray(advisoryStartupBrief?.acceptance),
335
+ risks: asStringArray(advisoryStartupBrief?.risks),
336
+ notes:
337
+ asStringArray(advisoryStartupBrief?.notes).length > 0
338
+ ? asStringArray(advisoryStartupBrief?.notes)
339
+ : ["No additional startup notes were preserved for this workflow entry."],
340
+ task_type: asString(advisoryStartupBrief?.task_type) ?? routing?.taskType ?? DEFAULT_TASK_TYPE,
341
+ evaluation_profile: asString(advisoryStartupBrief?.evaluation_profile) ?? routing?.evaluationProfile ?? DEFAULT_EVALUATION_PROFILE,
342
+ };
343
+ }
344
+
337
345
  export function defaultVerificationEvidence(): JsonRecord {
338
346
  return {
339
347
  schema_version: 1,
@@ -352,7 +360,7 @@ export function defaultVerificationEvidence(): JsonRecord {
352
360
  }
353
361
 
354
362
  export function buildAgentReadme(projectName: string): string {
355
- return `# Completion Control Plane\n\nThis repository uses the \`completion\` workflow for long-running coding tasks.\n\n## Canonical tracked contract files\n\n- \`.agent/README.md\`\n- \`.agent/mission.md\`\n- \`.agent/profile.json\`\n- \`.agent/verify_completion_stop.sh\`\n- \`.agent/verify_completion_control_plane.sh\`\n\n## Ignored canonical execution state\n\n- \`.agent/state.json\`\n- \`.agent/startup-plan.json\`\n- \`.agent/startup-plan.md\`\n- \`.agent/plan.json\`\n- \`.agent/active-slice.json\`\n- \`.agent/slice-history.jsonl\`\n- \`.agent/stop-check-history.jsonl\`\n- \`.agent/verification-evidence.json\`\n- \`.agent/*.log\`\n- \`.agent/tmp/\`\n\n\`.agent/startup-plan.json\` plus \`.agent/startup-plan.md\` preserve the approved workflow startup plan captured at \`/cook\`. \`completion-regrounder\` consumes that plan as planning input, then derives canonical slices in \`.agent/plan.json\` from current repo truth.\n\n\`.agent/verification-evidence.json\` is the durable canonical record of deterministic verification for the selected slice or current HEAD. Recovery, review, audit, and stop-check reminder surfaces consume it instead of temp-only artifacts or conversational summaries when it is populated.\n\nThe source of truth for long-running completion work is canonical \`.agent/**\` state plus current repo truth.\n\nProject: ${projectName}\n`;
363
+ return `# Completion Control Plane\n\nThis repository uses the \`completion\` workflow for long-running coding tasks.\n\n## Canonical tracked contract files\n\n- \`.agent/README.md\`\n- \`.agent/mission.md\`\n- \`.agent/profile.json\`\n- \`.agent/verify_completion_stop.sh\`\n- \`.agent/verify_completion_control_plane.sh\`\n\n## Ignored canonical execution state\n\n- \`.agent/state.json\`\n- \`.agent/startup-brief.json\`\n- \`.agent/plan.json\`\n- \`.agent/active-slice.json\`\n- \`.agent/slice-history.jsonl\`\n- \`.agent/stop-check-history.jsonl\`\n- \`.agent/verification-evidence.json\`\n- \`.agent/*.log\`\n- \`.agent/tmp/\`\n\n\`.agent/startup-brief.json\` preserves the confirmed \`/cook\` startup intent as canonical intake for re-grounding. It does not replace \`.agent/plan.json\` or \`.agent/active-slice.json\`, which remain under regrounder authority.\n\n\`.agent/verification-evidence.json\` is the durable canonical record of deterministic verification for the selected slice or current HEAD. Recovery, review, audit, and stop-check reminder surfaces consume it instead of temp-only artifacts or conversational summaries when it is populated.\n\nThe source of truth for long-running completion work is canonical \`.agent/**\` state plus current repo truth.\n\nProject: ${projectName}\n`;
356
364
  }
357
365
 
358
366
  export function buildMission(projectName: string, missionAnchor: string): string {
@@ -455,23 +463,15 @@ function trackedDiffFiles(fromCommit, toCommit) {
455
463
 
456
464
  const profile = readJson('.agent/profile.json');
457
465
  const state = readJson('.agent/state.json');
458
- const startupPlan = readJson('.agent/startup-plan.json');
459
466
  const plan = readJson('.agent/plan.json');
460
467
  const active = readJson('.agent/active-slice.json');
461
468
  const evidence = readJson('.agent/verification-evidence.json');
462
- let startupPlanMarkdown = '';
463
- try {
464
- startupPlanMarkdown = fs.readFileSync('.agent/startup-plan.md', 'utf8');
465
- } catch (error) {
466
- fail('.agent/startup-plan.md must be present and readable: ' + error.message);
467
- }
468
469
 
469
470
  ensureTrackedContractFiles();
470
471
 
471
472
  for (const [file, record] of [
472
473
  ['.agent/profile.json', profile],
473
474
  ['.agent/state.json', state],
474
- ['.agent/startup-plan.json', startupPlan],
475
475
  ['.agent/plan.json', plan],
476
476
  ['.agent/active-slice.json', active],
477
477
  ]) {
@@ -482,38 +482,12 @@ for (const [file, record] of [
482
482
  const taskType = asString(profile.task_type);
483
483
  const evaluationProfile = asString(profile.evaluation_profile);
484
484
  if (asString(state.task_type) !== taskType) fail('.agent/state.json task_type must match .agent/profile.json task_type');
485
- if (asString(startupPlan.task_type) !== taskType) fail('.agent/startup-plan.json task_type must match .agent/profile.json task_type');
486
485
  if (asString(plan.task_type) !== taskType) fail('.agent/plan.json task_type must match .agent/profile.json task_type');
487
486
  if (asString(active.task_type) !== taskType) fail('.agent/active-slice.json task_type must match .agent/profile.json task_type');
488
487
  if (asString(state.evaluation_profile) !== evaluationProfile) fail('.agent/state.json evaluation_profile must match .agent/profile.json evaluation_profile');
489
- if (asString(startupPlan.evaluation_profile) !== evaluationProfile) fail('.agent/startup-plan.json evaluation_profile must match .agent/profile.json evaluation_profile');
490
488
  if (asString(plan.evaluation_profile) !== evaluationProfile) fail('.agent/plan.json evaluation_profile must match .agent/profile.json evaluation_profile');
491
489
  if (asString(active.evaluation_profile) !== evaluationProfile) fail('.agent/active-slice.json evaluation_profile must match .agent/profile.json evaluation_profile');
492
490
 
493
- if (asString(startupPlan.artifact_type) !== 'completion-startup-plan') {
494
- fail('.agent/startup-plan.json artifact_type must be completion-startup-plan');
495
- }
496
- if (asString(startupPlan.status) !== 'approved') {
497
- fail('.agent/startup-plan.json status must be approved');
498
- }
499
- const startupPlanMissionAnchor = asString(startupPlan.mission_anchor);
500
- if (!startupPlanMissionAnchor) fail('.agent/startup-plan.json mission_anchor must be present');
501
- if (startupPlanMissionAnchor !== asString(state.mission_anchor)) fail('.agent/startup-plan.json mission_anchor must match .agent/state.json mission_anchor');
502
- if (startupPlanMissionAnchor !== asString(plan.mission_anchor)) fail('.agent/startup-plan.json mission_anchor must match .agent/plan.json mission_anchor');
503
- if (startupPlanMissionAnchor !== asString(active.mission_anchor)) fail('.agent/startup-plan.json mission_anchor must match .agent/active-slice.json mission_anchor');
504
- if (!asString(startupPlan.goal_text)) fail('.agent/startup-plan.json goal_text must be present');
505
- for (const field of ['scope', 'constraints', 'acceptance', 'risks', 'notes', 'planned_surfaces', 'verification_intent', 'sequencing_hints']) {
506
- if (!Array.isArray(startupPlan[field])) fail('.agent/startup-plan.json is missing ' + field);
507
- }
508
- if (startupPlanMarkdown.trim().length === 0) fail('.agent/startup-plan.md must not be empty');
509
- if (startupPlanMissionAnchor && !startupPlanMarkdown.includes(startupPlanMissionAnchor)) {
510
- fail('.agent/startup-plan.md must mention the startup-plan mission_anchor');
511
- }
512
- const startupPlanGoalText = asString(startupPlan.goal_text);
513
- if (startupPlanGoalText && !startupPlanMarkdown.includes(startupPlanGoalText)) {
514
- fail('.agent/startup-plan.md must render the startup-plan goal_text');
515
- }
516
-
517
491
  if (asString(evidence.artifact_type) !== 'completion-verification-evidence') {
518
492
  fail('.agent/verification-evidence.json artifact_type must be completion-verification-evidence');
519
493
  }
@@ -660,12 +634,7 @@ export type ScaffoldResult = {
660
634
  export async function scaffoldCompletionFiles(
661
635
  root: string,
662
636
  missionAnchor: string,
663
- options?: {
664
- analysis?: { taskType?: string; evaluationProfile?: string };
665
- continuationReason?: string;
666
- advisoryStartupBrief?: JsonRecord;
667
- approvedStartupPlan?: JsonRecord;
668
- },
637
+ options?: { analysis?: { taskType?: string; evaluationProfile?: string }; continuationReason?: string; advisoryStartupBrief?: JsonRecord },
669
638
  ): Promise<ScaffoldResult> {
670
639
  const files = resolveFiles(root);
671
640
  const created: string[] = [];
@@ -675,10 +644,6 @@ export async function scaffoldCompletionFiles(
675
644
  const projectName = path.basename(root);
676
645
  const docsSurfaces = await detectDocsSurfaces(root);
677
646
  const verifierCommand = await detectVerifierCommand(root);
678
- const startupPlanRecord =
679
- options?.approvedStartupPlan ??
680
- (await readJson(files.startupPlanPath)) ??
681
- defaultStartupPlan(missionAnchor, { taskType: options?.analysis?.taskType, evaluationProfile: options?.analysis?.evaluationProfile });
682
647
  const trackedFiles: Array<{ path: string; content: string; executable?: boolean }> = [
683
648
  { path: path.join(files.agentDir, "README.md"), content: buildAgentReadme(projectName) },
684
649
  { path: path.join(files.agentDir, "mission.md"), content: buildMission(projectName, missionAnchor) },
@@ -693,12 +658,8 @@ export async function scaffoldCompletionFiles(
693
658
  content: `${JSON.stringify(defaultState(missionAnchor, { taskType: options?.analysis?.taskType, evaluationProfile: options?.analysis?.evaluationProfile, continuationReason: options?.continuationReason }, options?.advisoryStartupBrief), null, 2)}\n`,
694
659
  },
695
660
  {
696
- path: files.startupPlanPath,
697
- content: `${JSON.stringify(startupPlanRecord, null, 2)}\n`,
698
- },
699
- {
700
- path: files.startupPlanMarkdownPath,
701
- content: buildApprovedStartupPlanMarkdown(startupPlanRecord as any),
661
+ path: files.startupBriefPath,
662
+ content: `${JSON.stringify(defaultStartupBrief(missionAnchor, { taskType: options?.analysis?.taskType, evaluationProfile: options?.analysis?.evaluationProfile }, options?.advisoryStartupBrief), null, 2)}\n`,
702
663
  },
703
664
  { path: files.planPath, content: `${JSON.stringify(defaultPlan(missionAnchor, { taskType: options?.analysis?.taskType, evaluationProfile: options?.analysis?.evaluationProfile }), null, 2)}\n` },
704
665
  { path: files.activePath, content: `${JSON.stringify(defaultActiveSlice(missionAnchor, { taskType: options?.analysis?.taskType, evaluationProfile: options?.analysis?.evaluationProfile }), null, 2)}\n` },
@@ -721,7 +682,6 @@ export function currentTaskType(snapshot: CompletionStateSnapshot): string | und
721
682
  return (
722
683
  asString(snapshot.active?.task_type) ??
723
684
  asString(snapshot.state?.task_type) ??
724
- asString(snapshot.startupPlan?.task_type) ??
725
685
  asString(snapshot.plan?.task_type) ??
726
686
  asString(snapshot.profile?.task_type)
727
687
  );
@@ -731,7 +691,6 @@ export function currentEvaluationProfile(snapshot: CompletionStateSnapshot): str
731
691
  return (
732
692
  asString(snapshot.active?.evaluation_profile) ??
733
693
  asString(snapshot.state?.evaluation_profile) ??
734
- asString(snapshot.startupPlan?.evaluation_profile) ??
735
694
  asString(snapshot.plan?.evaluation_profile) ??
736
695
  asString(snapshot.profile?.evaluation_profile)
737
696
  );
@@ -740,7 +699,6 @@ export function currentEvaluationProfile(snapshot: CompletionStateSnapshot): str
740
699
  export function currentMissionAnchor(snapshot: CompletionStateSnapshot): string {
741
700
  return (
742
701
  asString(snapshot.state?.mission_anchor) ??
743
- asString(snapshot.startupPlan?.mission_anchor) ??
744
702
  asString(snapshot.plan?.mission_anchor) ??
745
703
  asString(snapshot.active?.mission_anchor) ??
746
704
  path.basename(snapshot.files.root)
@@ -18,10 +18,9 @@ export type CompletionFiles = {
18
18
  statePath: string;
19
19
  planPath: string;
20
20
  activePath: string;
21
- startupPlanPath: string;
22
- startupPlanMarkdownPath: string;
23
21
  sliceHistoryPath: string;
24
22
  stopHistoryPath: string;
23
+ startupBriefPath: string;
25
24
  verificationEvidencePath: string;
26
25
  compactionMarkerPath: string;
27
26
  };
@@ -32,7 +31,7 @@ export type CompletionStateSnapshot = {
32
31
  state?: JsonRecord;
33
32
  plan?: JsonRecord;
34
33
  active?: JsonRecord;
35
- startupPlan?: JsonRecord;
34
+ startupBrief?: JsonRecord;
36
35
  verificationEvidence?: JsonRecord;
37
36
  activeSlice?: JsonRecord;
38
37
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linimin/pi-letscook",
3
- "version": "0.1.67",
3
+ "version": "0.1.69",
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,
@@ -137,17 +137,16 @@ NODE
137
137
  ROOT="$TMPDIR/repo"
138
138
  PROMPT="$TMPDIR/resume-prompt.txt"
139
139
  BOOTSTRAP_SESSION="$TMPDIR/session-active-slice-bootstrap.jsonl"
140
- BOOTSTRAP_MESSAGES="$(python3 - <<'PY'
140
+ BOOTSTRAP_DISCUSSION=$'Prepare the active-slice contract bootstrap fixture and tell me when it is ready for /cook.'
141
+ GENERATED_HANDOFF="$(python3 - <<'PY'
141
142
  import json
142
143
  capsule = {
143
144
  "kind": "cook_handoff",
144
145
  "source": "primary_agent",
145
- "captured_at": "2026-01-01T00:00:02.000Z",
146
- "source_turn_id": "m0002",
147
146
  "mission": "Exercise active-slice contract parity.",
148
147
  "scope": [
149
148
  "Bootstrap canonical completion files for the active-slice contract fixture.",
150
- "Keep the fixture on the shipped explicit-handoff startup path."
149
+ "Keep the fixture on the shipped same-entry synthesis startup path."
151
150
  ],
152
151
  "constraints": [
153
152
  "Use supported bare /cook startup only."
@@ -157,7 +156,7 @@ capsule = {
157
156
  "Keep scripts/active-slice-contract-test.sh aligned with the packaged startup contract."
158
157
  ],
159
158
  "risks": [
160
- "Active-slice fixture bootstrap must stay anchored to the fresh explicit startup-plan preview."
159
+ "Active-slice fixture bootstrap must stay anchored to same-entry primary-agent startup-plan synthesis."
161
160
  ],
162
161
  "notes": [
163
162
  "This handoff exists only to scaffold canonical files before the fixture rewrites them for contract parity coverage."
@@ -179,20 +178,16 @@ capsule = {
179
178
  "evaluation_profile": "completion-rubric-v1",
180
179
  "why_cook_now": "The fixture bootstrap is concrete enough to scaffold canonical control-plane files."
181
180
  }
182
- messages = [
183
- {"role": "user", "content": "Prepare the active-slice contract bootstrap fixture and tell me when it is ready for /cook."},
184
- {"role": "assistant", "content": "The active-slice contract bootstrap fixture is ready for /cook. Run /cook to confirm it.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
185
- ]
186
- print(json.dumps(messages, ensure_ascii=False))
181
+ print("```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```")
187
182
  PY
188
183
  )"
189
184
  mkdir -p "$ROOT"
190
185
  cd "$ROOT"
191
186
  git init -q
192
- write_session_messages "$BOOTSTRAP_SESSION" "$ROOT" "$BOOTSTRAP_MESSAGES"
187
+ write_session "$BOOTSTRAP_SESSION" "$ROOT" "$BOOTSTRAP_DISCUSSION"
193
188
 
194
189
  PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=accept \
195
- PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
190
+ PI_COMPLETION_PRIMARY_HANDOFF_OUTPUT="$GENERATED_HANDOFF" \
196
191
  PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
197
192
  pi --session "$BOOTSTRAP_SESSION" -e "$PKG_ROOT" -p "/cook" \
198
193
  >"$TMPDIR/pi-active-slice-bootstrap.out" 2>"$TMPDIR/pi-active-slice-bootstrap.err"
@@ -247,6 +242,11 @@ acceptance = [
247
242
  state = {
248
243
  'schema_version': 1,
249
244
  'mission_anchor': mission,
245
+ 'workflow_entry_status': 'active',
246
+ 'workflow_entry_source': '/cook',
247
+ 'workflow_entry_confirmed_at': '2026-05-03T00:00:00Z',
248
+ 'workflow_session_id': 'active-slice-fixture-session',
249
+ 'startup_brief_path': '.agent/startup-brief.json',
250
250
  'current_phase': 'implement',
251
251
  'continuation_policy': 'continue',
252
252
  'continuation_reason': 'Fixture for active-slice contract regression coverage.',
@@ -321,6 +321,22 @@ active = {
321
321
  }
322
322
 
323
323
  Path('.agent/state.json').write_text(json.dumps(state, indent=2) + '\n')
324
+ Path('.agent/startup-brief.json').write_text(json.dumps({
325
+ 'schema_version': 1,
326
+ 'artifact_type': 'completion-startup-brief',
327
+ 'source': 'primary_agent',
328
+ 'confirmed': True,
329
+ 'confirmed_at': '2026-05-03T00:00:00Z',
330
+ 'mission': mission,
331
+ 'goal_text': f'Mission: {mission}',
332
+ 'scope': ['Exercise active-slice contract parity.'],
333
+ 'constraints': ['Keep the fixture scoped to active-slice contract coverage.'],
334
+ 'acceptance': acceptance,
335
+ 'risks': ['Fixture drift can hide active-slice contract regressions.'],
336
+ 'notes': ['Fixture startup brief for active-slice contract regression coverage.'],
337
+ 'task_type': task_type,
338
+ 'evaluation_profile': evaluation_profile,
339
+ }, indent=2) + '\n')
324
340
  Path('.agent/plan.json').write_text(json.dumps(plan, indent=2) + '\n')
325
341
  Path('.agent/active-slice.json').write_text(json.dumps(active, indent=2) + '\n')
326
342
  Path('.agent/verification-evidence.json').write_text(json.dumps({
@@ -134,11 +134,11 @@ assertIncludes('.agent/README.md', 'durable canonical record of deterministic ve
134
134
  assertSectionIncludes('skills/completion-protocol/SKILL.md', '## Canonical Files', '- `.agent/verification-evidence.json`');
135
135
  assertSectionIncludes('skills/completion-protocol/SKILL.md', '## Canonical Inputs', '- `.agent/verification-evidence.json`');
136
136
  assertSectionIncludes('skills/completion-protocol/SKILL.md', '## Compaction And Recovery', '- `.agent/verification-evidence.json`');
137
- assertSectionIncludes('skills/completion-protocol/SKILL.md', '## Compaction And Recovery', '`completion-implementer` must also re-read canonical `.agent/state.json`, `.agent/startup-plan.json`, `.agent/plan.json`, `.agent/active-slice.json`, and `.agent/verification-evidence.json` before resuming work.');
137
+ assertSectionIncludes('skills/completion-protocol/SKILL.md', '## Compaction And Recovery', '`completion-implementer` must also re-read canonical `.agent/state.json`, `.agent/plan.json`, `.agent/active-slice.json`, and `.agent/verification-evidence.json` before resuming work.');
138
138
  assertSectionIncludes('skills/completion-protocol/references/completion.md', '## Ignored Canonical Execution State', '- `.agent/verification-evidence.json`');
139
139
  assertSectionIncludes('skills/completion-protocol/references/completion.md', '## Canonical Inputs', '- `.agent/verification-evidence.json`');
140
140
  assertSectionIncludes('skills/completion-protocol/references/completion.md', '## Compaction And Recovery', '- `.agent/verification-evidence.json`');
141
- assertSectionIncludes('skills/completion-protocol/references/completion.md', '## Compaction And Recovery', '`completion-implementer` must also re-read canonical `.agent/state.json`, `.agent/startup-plan.json`, `.agent/plan.json`, `.agent/active-slice.json`, and `.agent/verification-evidence.json` before resuming work.');
141
+ assertSectionIncludes('skills/completion-protocol/references/completion.md', '## Compaction And Recovery', '`completion-implementer` must also re-read canonical `.agent/state.json`, `.agent/plan.json`, `.agent/active-slice.json`, and `.agent/verification-evidence.json` before resuming work.');
142
142
  assertIncludes('extensions/completion/prompt-surfaces.ts', 'Verification evidence artifact: ${args.evidence.path} (${args.evidence.status})');
143
143
  assertIncludes('extensions/completion/prompt-surfaces.ts', 'Verification evidence summary: ${args.evidence.summary}');
144
144
  assertIncludes('extensions/completion/index.ts', 'Canonical verification evidence artifact is currently: ${evidence.path} (${evidence.status})');
@@ -157,6 +157,13 @@ bash .agent/verify_completion_control_plane.sh >/dev/null
157
157
  CURRENT_EVIDENCE_BACKUP="$TMPDIR/current-verification-evidence.json"
158
158
  cp .agent/verification-evidence.json "$CURRENT_EVIDENCE_BACKUP"
159
159
 
160
+ CURRENT_EVIDENCE_SUBJECT_TYPE="$(python3 - <<'PY'
161
+ import json
162
+ from pathlib import Path
163
+ print(json.loads(Path('.agent/verification-evidence.json').read_text()).get('subject_type', ''))
164
+ PY
165
+ )"
166
+
160
167
  python3 - <<'PY'
161
168
  import json
162
169
  from pathlib import Path
@@ -166,14 +173,16 @@ evidence['head_sha'] = 'stale-head'
166
173
  path.write_text(json.dumps(evidence, indent=2) + '\n')
167
174
  PY
168
175
 
169
- if bash ./scripts/release-check.sh >/dev/null 2>&1; then
170
- echo "expected release-check to fail when current repo verification-evidence.json is stale" >&2
171
- exit 1
172
- fi
176
+ if [[ "$CURRENT_EVIDENCE_SUBJECT_TYPE" == "selected_slice" ]]; then
177
+ if bash ./scripts/release-check.sh >/dev/null 2>&1; then
178
+ echo "expected release-check to fail when current repo verification-evidence.json is stale" >&2
179
+ exit 1
180
+ fi
173
181
 
174
- if bash .agent/verify_completion_stop.sh >/dev/null 2>&1; then
175
- echo "expected verify_completion_stop.sh to fail when current repo verification-evidence.json is stale" >&2
176
- exit 1
182
+ if bash .agent/verify_completion_stop.sh >/dev/null 2>&1; then
183
+ echo "expected verify_completion_stop.sh to fail when current repo verification-evidence.json is stale" >&2
184
+ exit 1
185
+ fi
177
186
  fi
178
187
 
179
188
  cp "$CURRENT_EVIDENCE_BACKUP" .agent/verification-evidence.json
@@ -198,11 +207,11 @@ capsule = {
198
207
  "Use supported bare /cook startup only."
199
208
  ],
200
209
  "acceptance": [
201
- "Scaffold .agent/profile.json, .agent/state.json, .agent/plan.json, .agent/active-slice.json, and .agent/verification-evidence.json before the fixture rewrites them.",
210
+ "Write the workflow control-plane files under .agent, including profile.json, state.json, active-slice.json, verification-evidence.json, and the slice backlog file, before the fixture rewrites them.",
202
211
  "Keep scripts/canonical-evidence-artifact-test.sh aligned with packaged bootstrap behavior."
203
212
  ],
204
213
  "risks": [
205
- "Evidence-artifact bootstrap must stay anchored to the fresh explicit startup-plan preview."
214
+ "Evidence-artifact bootstrap must stay anchored to the fresh explicit handoff."
206
215
  ],
207
216
  "notes": [
208
217
  "This fixture exists only to scaffold canonical files before rewriting them for evidence parity coverage."
@@ -242,12 +251,12 @@ PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
242
251
  pi --session "$BOOTSTRAP_SESSION" -e "$PKG_ROOT" -p "/cook" \
243
252
  >"$TMPDIR/pi-canonical-evidence-bootstrap.out" 2>"$TMPDIR/pi-canonical-evidence-bootstrap.err"
244
253
 
245
- for file in .agent/profile.json .agent/state.json .agent/startup-plan.json .agent/startup-plan.md .agent/plan.json .agent/active-slice.json .agent/verification-evidence.json; do
254
+ for file in .agent/profile.json .agent/state.json .agent/plan.json .agent/active-slice.json .agent/verification-evidence.json; do
246
255
  [[ -f "$file" ]] || { echo "missing canonical bootstrap file: $file" >&2; exit 1; }
247
256
  done
248
257
 
249
258
  bash .agent/verify_completion_control_plane.sh >/dev/null
250
- bash .agent/verify_completion_stop.sh >/dev/null
259
+ PI_COMPLETION_RUNNING_RELEASE_CHECK=1 bash .agent/verify_completion_stop.sh >/dev/null
251
260
 
252
261
  python3 - <<'PY'
253
262
  import json
@@ -288,39 +297,14 @@ acceptance = [
288
297
  'Canonical verification evidence is recorded for the selected slice.',
289
298
  'Fail-closed verification rejects missing or stale evidence.',
290
299
  ]
291
- startup_plan = {
292
- 'schema_version': 1,
293
- 'artifact_type': 'completion-startup-plan',
294
- 'status': 'approved',
295
- 'source': 'primary_agent_handoff',
296
- 'captured_at': '2026-05-03T00:00:00Z',
297
- 'mission_anchor': mission,
298
- 'goal_text': 'Mission: Exercise canonical verification evidence parity.\n\nScope:\n- Persist canonical verification evidence for the selected slice.\n- Keep the verifier fail-closed on stale or missing evidence.\n\nAcceptance:\n- Canonical verification evidence is recorded for the selected slice.\n- Fail-closed verification rejects missing or stale evidence.',
299
- 'task_type': task_type,
300
- 'evaluation_profile': evaluation_profile,
301
- 'scope': [
302
- 'Persist canonical verification evidence for the selected slice.',
303
- 'Keep the verifier fail-closed on stale or missing evidence.',
304
- ],
305
- 'constraints': [
306
- 'Keep the fixture scoped to canonical verification evidence parity.',
307
- ],
308
- 'acceptance': acceptance,
309
- 'risks': [
310
- 'Stale startup-plan parity could mask canonical evidence regressions.',
311
- ],
312
- 'notes': [
313
- 'Use startup-plan parity to prove the verifier reads the approved startup plan alongside other canonical state.',
314
- ],
315
- 'planned_surfaces': implementation_surfaces,
316
- 'verification_intent': verification_commands,
317
- 'sequencing_hints': [
318
- 'First slice goal: Persist canonical verification evidence for the selected slice.',
319
- ],
320
- }
321
300
  state = {
322
301
  'schema_version': 1,
323
302
  'mission_anchor': mission,
303
+ 'workflow_entry_status': 'active',
304
+ 'workflow_entry_source': '/cook',
305
+ 'workflow_entry_confirmed_at': '2026-05-03T00:00:00Z',
306
+ 'workflow_session_id': 'evidence-fixture-session',
307
+ 'startup_brief_path': '.agent/startup-brief.json',
324
308
  'current_phase': 'implement',
325
309
  'continuation_policy': 'continue',
326
310
  'continuation_reason': 'Fixture for canonical evidence artifact regression coverage.',
@@ -394,22 +378,25 @@ active = {
394
378
  'why_now': 'Exercise fail-closed evidence parity.',
395
379
  }
396
380
 
381
+ startup_brief = {
382
+ 'schema_version': 1,
383
+ 'artifact_type': 'completion-startup-brief',
384
+ 'source': 'primary_agent',
385
+ 'confirmed': True,
386
+ 'confirmed_at': '2026-05-03T00:00:00Z',
387
+ 'mission': mission,
388
+ 'goal_text': f'Mission: {mission}',
389
+ 'scope': ['Exercise canonical verification evidence artifact parity.'],
390
+ 'constraints': ['Keep the fixture scoped to verification evidence coverage.'],
391
+ 'acceptance': acceptance,
392
+ 'risks': ['Fixture drift can hide evidence-parity regressions.'],
393
+ 'notes': ['Fixture startup brief for canonical evidence artifact regression coverage.'],
394
+ 'task_type': task_type,
395
+ 'evaluation_profile': evaluation_profile,
396
+ }
397
+
397
398
  Path('.agent/state.json').write_text(json.dumps(state, indent=2) + '\n')
398
- Path('.agent/startup-plan.json').write_text(json.dumps(startup_plan, indent=2) + '\n')
399
- Path('.agent/startup-plan.md').write_text(
400
- '# Approved Startup Plan\n\n'
401
- f'Mission anchor: {mission}\n'
402
- 'Source: primary_agent_handoff\n'
403
- 'Captured at: 2026-05-03T00:00:00Z\n'
404
- f'Task type: {task_type}\n'
405
- f'Evaluation profile: {evaluation_profile}\n\n'
406
- '## Goal\n\n'
407
- f"{startup_plan['goal_text']}\n\n"
408
- '## Planned surfaces\n\n'
409
- + ''.join(f'- {item}\n' for item in startup_plan['planned_surfaces'])
410
- + '\n## Verification intent\n\n'
411
- + ''.join(f'- {item}\n' for item in startup_plan['verification_intent'])
412
- )
399
+ Path('.agent/startup-brief.json').write_text(json.dumps(startup_brief, indent=2) + '\n')
413
400
  Path('.agent/plan.json').write_text(json.dumps(plan, indent=2) + '\n')
414
401
  Path('.agent/active-slice.json').write_text(json.dumps(active, indent=2) + '\n')
415
402
  PY
@@ -511,7 +498,7 @@ Path('.agent/verification-evidence.json').write_text(json.dumps(valid, indent=2)
511
498
  PY
512
499
 
513
500
  bash .agent/verify_completion_control_plane.sh >/dev/null
514
- bash .agent/verify_completion_stop.sh >/dev/null
501
+ PI_COMPLETION_RUNNING_RELEASE_CHECK=1 bash .agent/verify_completion_stop.sh >/dev/null
515
502
 
516
503
  rm -f "$SYSTEM_REMINDER"
517
504
  PI_COMPLETION_TEST_SYSTEM_REMINDER_PATH="$SYSTEM_REMINDER" \