@linimin/pi-letscook 0.1.68 → 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.68",
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,
@@ -242,6 +242,11 @@ acceptance = [
242
242
  state = {
243
243
  'schema_version': 1,
244
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',
245
250
  'current_phase': 'implement',
246
251
  'continuation_policy': 'continue',
247
252
  'continuation_reason': 'Fixture for active-slice contract regression coverage.',
@@ -316,6 +321,22 @@ active = {
316
321
  }
317
322
 
318
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')
319
340
  Path('.agent/plan.json').write_text(json.dumps(plan, indent=2) + '\n')
320
341
  Path('.agent/active-slice.json').write_text(json.dumps(active, indent=2) + '\n')
321
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
@@ -182,26 +191,27 @@ bash .agent/verify_completion_control_plane.sh >/dev/null
182
191
  ROOT="$TMPDIR/repo"
183
192
  SYSTEM_REMINDER="$TMPDIR/system-reminder.txt"
184
193
  BOOTSTRAP_SESSION="$TMPDIR/session-canonical-evidence-bootstrap.jsonl"
185
- BOOTSTRAP_DISCUSSION=$'Prepare the canonical evidence bootstrap fixture and tell me when it is ready for /cook.'
186
- GENERATED_HANDOFF="$(python3 - <<'PY'
194
+ BOOTSTRAP_MESSAGES="$(python3 - <<'PY'
187
195
  import json
188
196
  capsule = {
189
197
  "kind": "cook_handoff",
190
198
  "source": "primary_agent",
199
+ "captured_at": "2026-01-01T00:00:02.000Z",
200
+ "source_turn_id": "m0002",
191
201
  "mission": "Exercise canonical evidence fixture bootstrap.",
192
202
  "scope": [
193
203
  "Materialize canonical completion files for the evidence artifact fixture.",
194
- "Keep the verification-evidence bootstrap on the supported same-entry synthesis startup path."
204
+ "Keep the verification-evidence bootstrap on the supported explicit-handoff startup path."
195
205
  ],
196
206
  "constraints": [
197
207
  "Use supported bare /cook startup only."
198
208
  ],
199
209
  "acceptance": [
200
- "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.",
201
211
  "Keep scripts/canonical-evidence-artifact-test.sh aligned with packaged bootstrap behavior."
202
212
  ],
203
213
  "risks": [
204
- "Evidence-artifact bootstrap must stay anchored to same-entry primary-agent startup-plan synthesis."
214
+ "Evidence-artifact bootstrap must stay anchored to the fresh explicit handoff."
205
215
  ],
206
216
  "notes": [
207
217
  "This fixture exists only to scaffold canonical files before rewriting them for evidence parity coverage."
@@ -223,26 +233,30 @@ capsule = {
223
233
  "evaluation_profile": "completion-rubric-v1",
224
234
  "why_cook_now": "The fixture bootstrap is concrete enough to create canonical control-plane files."
225
235
  }
226
- print("```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```")
236
+ messages = [
237
+ {"role": "user", "content": "Prepare the canonical evidence bootstrap fixture and tell me when it is ready for /cook."},
238
+ {"role": "assistant", "content": "The canonical evidence 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```"},
239
+ ]
240
+ print(json.dumps(messages, ensure_ascii=False))
227
241
  PY
228
242
  )"
229
243
  mkdir -p "$ROOT"
230
244
  cd "$ROOT"
231
245
  git init -q
232
- write_session "$BOOTSTRAP_SESSION" "$ROOT" "$BOOTSTRAP_DISCUSSION"
246
+ write_session_messages "$BOOTSTRAP_SESSION" "$ROOT" "$BOOTSTRAP_MESSAGES"
233
247
 
234
248
  PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=accept \
235
- PI_COMPLETION_PRIMARY_HANDOFF_OUTPUT="$GENERATED_HANDOFF" \
249
+ PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
236
250
  PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
237
251
  pi --session "$BOOTSTRAP_SESSION" -e "$PKG_ROOT" -p "/cook" \
238
252
  >"$TMPDIR/pi-canonical-evidence-bootstrap.out" 2>"$TMPDIR/pi-canonical-evidence-bootstrap.err"
239
253
 
240
- 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
241
255
  [[ -f "$file" ]] || { echo "missing canonical bootstrap file: $file" >&2; exit 1; }
242
256
  done
243
257
 
244
258
  bash .agent/verify_completion_control_plane.sh >/dev/null
245
- bash .agent/verify_completion_stop.sh >/dev/null
259
+ PI_COMPLETION_RUNNING_RELEASE_CHECK=1 bash .agent/verify_completion_stop.sh >/dev/null
246
260
 
247
261
  python3 - <<'PY'
248
262
  import json
@@ -283,39 +297,14 @@ acceptance = [
283
297
  'Canonical verification evidence is recorded for the selected slice.',
284
298
  'Fail-closed verification rejects missing or stale evidence.',
285
299
  ]
286
- startup_plan = {
287
- 'schema_version': 1,
288
- 'artifact_type': 'completion-startup-plan',
289
- 'status': 'approved',
290
- 'source': 'deferred_primary_agent_handoff',
291
- 'captured_at': '2026-05-03T00:00:00Z',
292
- 'mission_anchor': mission,
293
- '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.',
294
- 'task_type': task_type,
295
- 'evaluation_profile': evaluation_profile,
296
- 'scope': [
297
- 'Persist canonical verification evidence for the selected slice.',
298
- 'Keep the verifier fail-closed on stale or missing evidence.',
299
- ],
300
- 'constraints': [
301
- 'Keep the fixture scoped to canonical verification evidence parity.',
302
- ],
303
- 'acceptance': acceptance,
304
- 'risks': [
305
- 'Stale startup-plan parity could mask canonical evidence regressions.',
306
- ],
307
- 'notes': [
308
- 'Use startup-plan parity to prove the verifier reads the approved startup plan alongside other canonical state.',
309
- ],
310
- 'planned_surfaces': implementation_surfaces,
311
- 'verification_intent': verification_commands,
312
- 'sequencing_hints': [
313
- 'First slice goal: Persist canonical verification evidence for the selected slice.',
314
- ],
315
- }
316
300
  state = {
317
301
  'schema_version': 1,
318
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',
319
308
  'current_phase': 'implement',
320
309
  'continuation_policy': 'continue',
321
310
  'continuation_reason': 'Fixture for canonical evidence artifact regression coverage.',
@@ -389,22 +378,25 @@ active = {
389
378
  'why_now': 'Exercise fail-closed evidence parity.',
390
379
  }
391
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
+
392
398
  Path('.agent/state.json').write_text(json.dumps(state, indent=2) + '\n')
393
- Path('.agent/startup-plan.json').write_text(json.dumps(startup_plan, indent=2) + '\n')
394
- Path('.agent/startup-plan.md').write_text(
395
- '# Approved Startup Plan\n\n'
396
- f'Mission anchor: {mission}\n'
397
- 'Source: deferred_primary_agent_handoff\n'
398
- 'Captured at: 2026-05-03T00:00:00Z\n'
399
- f'Task type: {task_type}\n'
400
- f'Evaluation profile: {evaluation_profile}\n\n'
401
- '## Goal\n\n'
402
- f"{startup_plan['goal_text']}\n\n"
403
- '## Planned surfaces\n\n'
404
- + ''.join(f'- {item}\n' for item in startup_plan['planned_surfaces'])
405
- + '\n## Verification intent\n\n'
406
- + ''.join(f'- {item}\n' for item in startup_plan['verification_intent'])
407
- )
399
+ Path('.agent/startup-brief.json').write_text(json.dumps(startup_brief, indent=2) + '\n')
408
400
  Path('.agent/plan.json').write_text(json.dumps(plan, indent=2) + '\n')
409
401
  Path('.agent/active-slice.json').write_text(json.dumps(active, indent=2) + '\n')
410
402
  PY
@@ -506,7 +498,7 @@ Path('.agent/verification-evidence.json').write_text(json.dumps(valid, indent=2)
506
498
  PY
507
499
 
508
500
  bash .agent/verify_completion_control_plane.sh >/dev/null
509
- bash .agent/verify_completion_stop.sh >/dev/null
501
+ PI_COMPLETION_RUNNING_RELEASE_CHECK=1 bash .agent/verify_completion_stop.sh >/dev/null
510
502
 
511
503
  rm -f "$SYSTEM_REMINDER"
512
504
  PI_COMPLETION_TEST_SYSTEM_REMINDER_PATH="$SYSTEM_REMINDER" \