@linimin/pi-letscook 0.1.56 → 0.1.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -1
- package/README.md +18 -8
- package/extensions/completion/driver.ts +43 -7
- package/extensions/completion/index.ts +65 -32
- package/extensions/completion/prompt-surfaces.ts +9 -4
- package/extensions/completion/proposal.ts +339 -13
- package/package.json +1 -1
- package/scripts/context-proposal-test.sh +482 -0
- package/scripts/release-check.sh +15 -7
- package/scripts/smoke-test.sh +4 -0
- package/skills/cook-handoff-boundary/SKILL.md +40 -2
|
@@ -47,6 +47,49 @@ with session_path.open('w', encoding='utf-8') as fh:
|
|
|
47
47
|
PY
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
write_session_messages() {
|
|
51
|
+
local session_path="$1"
|
|
52
|
+
local cwd="$2"
|
|
53
|
+
local messages_json="$3"
|
|
54
|
+
python3 - "$session_path" "$cwd" "$messages_json" <<'PY'
|
|
55
|
+
import json
|
|
56
|
+
import sys
|
|
57
|
+
from pathlib import Path
|
|
58
|
+
|
|
59
|
+
session_path = Path(sys.argv[1])
|
|
60
|
+
cwd = sys.argv[2]
|
|
61
|
+
messages = json.loads(sys.argv[3])
|
|
62
|
+
session_path.parent.mkdir(parents=True, exist_ok=True)
|
|
63
|
+
entries = [
|
|
64
|
+
{
|
|
65
|
+
"type": "session",
|
|
66
|
+
"version": 3,
|
|
67
|
+
"id": "11111111-1111-4111-8111-111111111111",
|
|
68
|
+
"timestamp": "2026-01-01T00:00:00.000Z",
|
|
69
|
+
"cwd": cwd,
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
parent_id = None
|
|
73
|
+
for index, message in enumerate(messages, start=1):
|
|
74
|
+
entry_id = f"m{index:04d}"
|
|
75
|
+
entries.append({
|
|
76
|
+
"type": "message",
|
|
77
|
+
"id": entry_id,
|
|
78
|
+
"parentId": parent_id,
|
|
79
|
+
"timestamp": f"2026-01-01T00:00:{index:02d}.000Z",
|
|
80
|
+
"message": {
|
|
81
|
+
"role": message["role"],
|
|
82
|
+
"content": message["content"],
|
|
83
|
+
"timestamp": 1767225600000 + index * 1000,
|
|
84
|
+
},
|
|
85
|
+
})
|
|
86
|
+
parent_id = entry_id
|
|
87
|
+
with session_path.open('w', encoding='utf-8') as fh:
|
|
88
|
+
for entry in entries:
|
|
89
|
+
fh.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
|
90
|
+
PY
|
|
91
|
+
}
|
|
92
|
+
|
|
50
93
|
mark_done() {
|
|
51
94
|
python3 - <<'PY'
|
|
52
95
|
import json
|
|
@@ -1358,7 +1401,446 @@ assert 'Discuss changes in the main chat and rerun /cook.' in output, 'cancel co
|
|
|
1358
1401
|
assert not Path('.agent').exists(), 'cancel action should not write canonical workflow state'
|
|
1359
1402
|
PY
|
|
1360
1403
|
|
|
1404
|
+
# Explicit primary-agent handoff: /cook should prefer the structured handoff capsule over broad context re-inference.
|
|
1405
|
+
HANDOFF_ROOT_START="$TMPDIR/handoff-root-start"
|
|
1406
|
+
mkdir -p "$HANDOFF_ROOT_START"
|
|
1407
|
+
cd "$HANDOFF_ROOT_START"
|
|
1408
|
+
git init -q
|
|
1409
|
+
|
|
1410
|
+
HANDOFF_SESSION_START="$TMPDIR/handoff-session-start.jsonl"
|
|
1411
|
+
HANDOFF_SNAPSHOT_START="$TMPDIR/handoff-proposal-start.json"
|
|
1412
|
+
HANDOFF_MESSAGES_START="$(python3 - <<'PY'
|
|
1413
|
+
import json
|
|
1414
|
+
capsule = {
|
|
1415
|
+
"kind": "cook_handoff",
|
|
1416
|
+
"source": "primary_agent",
|
|
1417
|
+
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
1418
|
+
"source_turn_id": "m0002",
|
|
1419
|
+
"mission": "Fix login redirect callback behavior.",
|
|
1420
|
+
"scope": [
|
|
1421
|
+
"Update the callback redirect decision logic.",
|
|
1422
|
+
"Preserve the broader auth flow."
|
|
1423
|
+
],
|
|
1424
|
+
"constraints": [
|
|
1425
|
+
"Do not refactor the broader auth flow."
|
|
1426
|
+
],
|
|
1427
|
+
"acceptance": [
|
|
1428
|
+
"Add a regression test for returning to the requested page."
|
|
1429
|
+
],
|
|
1430
|
+
"risks": [
|
|
1431
|
+
"Stale auth discussion could broaden the startup brief if the handoff is ignored."
|
|
1432
|
+
],
|
|
1433
|
+
"notes": [
|
|
1434
|
+
"Keep the startup brief aligned with the explicit primary-agent plan."
|
|
1435
|
+
],
|
|
1436
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
1437
|
+
"first_slice_goal": "Land the redirect callback fix and its regression coverage.",
|
|
1438
|
+
"first_slice_non_goals": [
|
|
1439
|
+
"Do not refactor the broader auth flow."
|
|
1440
|
+
],
|
|
1441
|
+
"implementation_surfaces": [
|
|
1442
|
+
"src/auth/redirect.ts",
|
|
1443
|
+
"tests/auth/redirect.spec.ts"
|
|
1444
|
+
],
|
|
1445
|
+
"verification_commands": [
|
|
1446
|
+
"npm test -- redirect.spec.ts"
|
|
1447
|
+
],
|
|
1448
|
+
"why_this_slice_first": "The redirect callback bug is already bounded enough to start implementation safely.",
|
|
1449
|
+
"task_type": "completion-workflow",
|
|
1450
|
+
"evaluation_profile": "completion-rubric-v1",
|
|
1451
|
+
"why_cook_now": "The implementation plan is concrete and ready for repo changes."
|
|
1452
|
+
}
|
|
1453
|
+
messages = [
|
|
1454
|
+
{"role": "user", "content": "Please think through the login redirect fix and tell me when it is ready for /cook."},
|
|
1455
|
+
{"role": "assistant", "content": "This task is now ready for /cook. Run /cook to confirm the startup brief.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
1456
|
+
]
|
|
1457
|
+
print(json.dumps(messages, ensure_ascii=False))
|
|
1458
|
+
PY
|
|
1459
|
+
)"
|
|
1460
|
+
write_session_messages "$HANDOFF_SESSION_START" "$HANDOFF_ROOT_START" "$HANDOFF_MESSAGES_START"
|
|
1461
|
+
|
|
1462
|
+
PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=accept \
|
|
1463
|
+
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$HANDOFF_SNAPSHOT_START" \
|
|
1464
|
+
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
1465
|
+
pi --session "$HANDOFF_SESSION_START" -e "$PKG_ROOT" -p "/cook" >"$TMPDIR/pi-completion-handoff-start.out" 2>"$TMPDIR/pi-completion-handoff-start.err"
|
|
1466
|
+
|
|
1467
|
+
python3 - "$HANDOFF_SNAPSHOT_START" <<'PY'
|
|
1468
|
+
import json
|
|
1469
|
+
import sys
|
|
1470
|
+
from pathlib import Path
|
|
1471
|
+
|
|
1472
|
+
snapshot = json.loads(Path(sys.argv[1]).read_text())
|
|
1473
|
+
state = json.loads(Path('.agent/state.json').read_text())
|
|
1474
|
+
|
|
1475
|
+
assert snapshot['source'] == 'handoff_capsule', 'explicit handoff startup should snapshot the handoff capsule as the proposal source'
|
|
1476
|
+
assert snapshot['mission'] == 'Fix login redirect callback behavior.', 'explicit handoff startup should preserve the primary-agent mission'
|
|
1477
|
+
assert state['mission_anchor'] == 'Fix login redirect callback behavior.', 'explicit handoff startup should use the handoff mission as canonical mission_anchor'
|
|
1478
|
+
assert state['advisory_startup_brief']['source'] == 'primary_agent_handoff', 'explicit handoff startup should preserve the advisory intake source'
|
|
1479
|
+
assert state['advisory_startup_brief']['risks'] == ['Stale auth discussion could broaden the startup brief if the handoff is ignored.'], 'explicit handoff startup should preserve handoff risks'
|
|
1480
|
+
assert 'First slice goal: Land the redirect callback fix and its regression coverage.' in state['advisory_startup_brief']['notes'], 'explicit handoff startup should preserve first_slice_goal in advisory notes'
|
|
1481
|
+
assert 'First slice non-goals: Do not refactor the broader auth flow.' in state['advisory_startup_brief']['notes'], 'explicit handoff startup should preserve first_slice_non_goals in advisory notes'
|
|
1482
|
+
assert 'Implementation surfaces: src/auth/redirect.ts | tests/auth/redirect.spec.ts' in state['advisory_startup_brief']['notes'], 'explicit handoff startup should preserve implementation_surfaces in advisory notes'
|
|
1483
|
+
assert 'Verification commands: npm test -- redirect.spec.ts' in state['advisory_startup_brief']['notes'], 'explicit handoff startup should preserve verification_commands in advisory notes'
|
|
1484
|
+
assert 'Why this slice first: The redirect callback bug is already bounded enough to start implementation safely.' in state['advisory_startup_brief']['notes'], 'explicit handoff startup should preserve why_this_slice_first in advisory notes'
|
|
1485
|
+
assert 'Primary-agent /cook handoff rationale: The implementation plan is concrete and ready for repo changes.' in state['advisory_startup_brief']['notes'], 'explicit handoff startup should preserve why_cook_now as notes'
|
|
1486
|
+
PY
|
|
1487
|
+
|
|
1488
|
+
# Fresh but non-startable explicit handoff: /cook should fail closed instead of falling back
|
|
1489
|
+
# to a broad recent-discussion startup brief when the explicit capsule is still too vague.
|
|
1490
|
+
HANDOFF_ROOT_VAGUE="$TMPDIR/handoff-root-vague"
|
|
1491
|
+
mkdir -p "$HANDOFF_ROOT_VAGUE"
|
|
1492
|
+
cd "$HANDOFF_ROOT_VAGUE"
|
|
1493
|
+
git init -q
|
|
1494
|
+
|
|
1495
|
+
HANDOFF_SESSION_VAGUE="$TMPDIR/handoff-session-vague.jsonl"
|
|
1496
|
+
HANDOFF_SNAPSHOT_VAGUE="$TMPDIR/handoff-proposal-vague.json"
|
|
1497
|
+
HANDOFF_MESSAGES_VAGUE="$(python3 - <<'PY'
|
|
1498
|
+
import json
|
|
1499
|
+
capsule = {
|
|
1500
|
+
"kind": "cook_handoff",
|
|
1501
|
+
"source": "primary_agent",
|
|
1502
|
+
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
1503
|
+
"source_turn_id": "m0002",
|
|
1504
|
+
"mission": "Fix login redirect callback behavior.",
|
|
1505
|
+
"scope": [
|
|
1506
|
+
"Update the callback redirect decision logic."
|
|
1507
|
+
],
|
|
1508
|
+
"constraints": [
|
|
1509
|
+
"Do not refactor the broader auth flow."
|
|
1510
|
+
],
|
|
1511
|
+
"acceptance": [
|
|
1512
|
+
"Confirm the final implementation breakdown before coding."
|
|
1513
|
+
],
|
|
1514
|
+
"risks": [
|
|
1515
|
+
"Broad recent context could be reused if the vague explicit handoff is ignored."
|
|
1516
|
+
],
|
|
1517
|
+
"notes": [
|
|
1518
|
+
"This handoff is still too vague to start implementation directly."
|
|
1519
|
+
],
|
|
1520
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
1521
|
+
"first_slice_goal": "Patch the callback redirect decision logic.",
|
|
1522
|
+
"first_slice_non_goals": [
|
|
1523
|
+
"Do not refactor the broader auth flow."
|
|
1524
|
+
],
|
|
1525
|
+
"implementation_surfaces": [],
|
|
1526
|
+
"verification_commands": [],
|
|
1527
|
+
"why_this_slice_first": "The callback redirect path is the likely first slice, but the handoff still lacks execution detail.",
|
|
1528
|
+
"task_type": "completion-workflow",
|
|
1529
|
+
"evaluation_profile": "completion-rubric-v1",
|
|
1530
|
+
"why_cook_now": "The task is workflow-worthy, but the implementation slice is not concrete enough yet."
|
|
1531
|
+
}
|
|
1532
|
+
recent_discussion = "Mission: Fix login redirect callback behavior.\nScope:\n- Update the callback redirect decision logic.\nConstraints:\n- Do not refactor the broader auth flow.\nAcceptance:\n- Add a regression test for returning to the requested page."
|
|
1533
|
+
messages = [
|
|
1534
|
+
{"role": "user", "content": recent_discussion},
|
|
1535
|
+
{"role": "assistant", "content": "This follow-up might soon be ready for /cook.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
1536
|
+
]
|
|
1537
|
+
print(json.dumps(messages, ensure_ascii=False))
|
|
1538
|
+
PY
|
|
1539
|
+
)"
|
|
1540
|
+
write_session_messages "$HANDOFF_SESSION_VAGUE" "$HANDOFF_ROOT_VAGUE" "$HANDOFF_MESSAGES_VAGUE"
|
|
1541
|
+
|
|
1542
|
+
PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
|
|
1543
|
+
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$HANDOFF_SNAPSHOT_VAGUE" \
|
|
1544
|
+
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
1545
|
+
pi --session "$HANDOFF_SESSION_VAGUE" -e "$PKG_ROOT" -p "/cook" >"$TMPDIR/pi-completion-handoff-vague.out" 2>"$TMPDIR/pi-completion-handoff-vague.err"
|
|
1546
|
+
|
|
1547
|
+
python3 - "$HANDOFF_SNAPSHOT_VAGUE" "$TMPDIR/pi-completion-handoff-vague.out" "$TMPDIR/pi-completion-handoff-vague.err" <<'PY'
|
|
1548
|
+
import sys
|
|
1549
|
+
from pathlib import Path
|
|
1550
|
+
|
|
1551
|
+
snapshot = Path(sys.argv[1])
|
|
1552
|
+
output = Path(sys.argv[2]).read_text() + Path(sys.argv[3]).read_text()
|
|
1553
|
+
|
|
1554
|
+
assert not snapshot.exists(), 'fresh non-startable handoff should not emit a startup proposal snapshot'
|
|
1555
|
+
assert not Path('.agent').exists(), 'fresh non-startable handoff should fail closed without writing canonical state'
|
|
1556
|
+
assert 'fresh explicit primary-agent handoff exists' in output, 'fresh non-startable handoff should explain that the explicit capsule blocked startup'
|
|
1557
|
+
assert 'acceptance is not anchored to concrete repo changes or verification' in output, 'fresh non-startable handoff should explain the workflow-only acceptance failure'
|
|
1558
|
+
assert 'implementation_surfaces is empty' in output, 'fresh non-startable handoff should explain the missing implementation_surfaces requirement'
|
|
1559
|
+
assert 'verification_commands is empty' in output, 'fresh non-startable handoff should explain the missing verification_commands requirement'
|
|
1560
|
+
PY
|
|
1561
|
+
|
|
1562
|
+
# Fresh explicit handoff with complete first-slice fields but vague acceptance: /cook should still fail closed
|
|
1563
|
+
# with the dedicated explicit-handoff message instead of bootstrapping canonical state.
|
|
1564
|
+
HANDOFF_ROOT_VAGUE_ACCEPTANCE="$TMPDIR/handoff-root-vague-acceptance"
|
|
1565
|
+
mkdir -p "$HANDOFF_ROOT_VAGUE_ACCEPTANCE"
|
|
1566
|
+
cd "$HANDOFF_ROOT_VAGUE_ACCEPTANCE"
|
|
1567
|
+
git init -q
|
|
1568
|
+
|
|
1569
|
+
HANDOFF_SESSION_VAGUE_ACCEPTANCE="$TMPDIR/handoff-session-vague-acceptance.jsonl"
|
|
1570
|
+
HANDOFF_SNAPSHOT_VAGUE_ACCEPTANCE="$TMPDIR/handoff-proposal-vague-acceptance.json"
|
|
1571
|
+
HANDOFF_MESSAGES_VAGUE_ACCEPTANCE="$(python3 - <<'PY'
|
|
1572
|
+
import json
|
|
1573
|
+
capsule = {
|
|
1574
|
+
"kind": "cook_handoff",
|
|
1575
|
+
"source": "primary_agent",
|
|
1576
|
+
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
1577
|
+
"source_turn_id": "m0002",
|
|
1578
|
+
"mission": "Fix login redirect callback behavior.",
|
|
1579
|
+
"scope": [
|
|
1580
|
+
"Update the callback redirect decision logic.",
|
|
1581
|
+
"Preserve the broader auth flow."
|
|
1582
|
+
],
|
|
1583
|
+
"constraints": [
|
|
1584
|
+
"Do not refactor the broader auth flow."
|
|
1585
|
+
],
|
|
1586
|
+
"acceptance": [
|
|
1587
|
+
"Current behavior stays understandable."
|
|
1588
|
+
],
|
|
1589
|
+
"risks": [
|
|
1590
|
+
"Broad recent context could be reused if the vague explicit handoff is ignored."
|
|
1591
|
+
],
|
|
1592
|
+
"notes": [
|
|
1593
|
+
"This handoff includes first-slice fields but still lacks concrete acceptance."
|
|
1594
|
+
],
|
|
1595
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
1596
|
+
"first_slice_goal": "Land the redirect callback fix and its regression coverage.",
|
|
1597
|
+
"first_slice_non_goals": [
|
|
1598
|
+
"Do not refactor the broader auth flow."
|
|
1599
|
+
],
|
|
1600
|
+
"implementation_surfaces": [
|
|
1601
|
+
"src/auth/redirect.ts",
|
|
1602
|
+
"tests/auth/redirect.spec.ts"
|
|
1603
|
+
],
|
|
1604
|
+
"verification_commands": [
|
|
1605
|
+
"npm test -- redirect.spec.ts"
|
|
1606
|
+
],
|
|
1607
|
+
"why_this_slice_first": "The redirect callback bug is already bounded enough to start implementation safely once acceptance is concrete.",
|
|
1608
|
+
"task_type": "completion-workflow",
|
|
1609
|
+
"evaluation_profile": "completion-rubric-v1",
|
|
1610
|
+
"why_cook_now": "The task is workflow-worthy, but the acceptance still needs concrete repo-change detail."
|
|
1611
|
+
}
|
|
1612
|
+
recent_discussion = "Mission: Fix login redirect callback behavior.\nScope:\n- Update the callback redirect decision logic.\nConstraints:\n- Do not refactor the broader auth flow.\nAcceptance:\n- Add a regression test for returning to the requested page."
|
|
1613
|
+
messages = [
|
|
1614
|
+
{"role": "user", "content": recent_discussion},
|
|
1615
|
+
{"role": "assistant", "content": "This follow-up might soon be ready for /cook.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
1616
|
+
]
|
|
1617
|
+
print(json.dumps(messages, ensure_ascii=False))
|
|
1618
|
+
PY
|
|
1619
|
+
)"
|
|
1620
|
+
write_session_messages "$HANDOFF_SESSION_VAGUE_ACCEPTANCE" "$HANDOFF_ROOT_VAGUE_ACCEPTANCE" "$HANDOFF_MESSAGES_VAGUE_ACCEPTANCE"
|
|
1621
|
+
|
|
1622
|
+
PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
|
|
1623
|
+
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$HANDOFF_SNAPSHOT_VAGUE_ACCEPTANCE" \
|
|
1624
|
+
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
1625
|
+
pi --session "$HANDOFF_SESSION_VAGUE_ACCEPTANCE" -e "$PKG_ROOT" -p "/cook" >"$TMPDIR/pi-completion-handoff-vague-acceptance.out" 2>"$TMPDIR/pi-completion-handoff-vague-acceptance.err"
|
|
1626
|
+
|
|
1627
|
+
python3 - "$HANDOFF_SNAPSHOT_VAGUE_ACCEPTANCE" "$TMPDIR/pi-completion-handoff-vague-acceptance.out" "$TMPDIR/pi-completion-handoff-vague-acceptance.err" <<'PY'
|
|
1628
|
+
import sys
|
|
1629
|
+
from pathlib import Path
|
|
1630
|
+
|
|
1631
|
+
snapshot = Path(sys.argv[1])
|
|
1632
|
+
output = Path(sys.argv[2]).read_text() + Path(sys.argv[3]).read_text()
|
|
1633
|
+
|
|
1634
|
+
assert not snapshot.exists(), 'fresh explicit handoff with vague acceptance should not emit a startup proposal snapshot'
|
|
1635
|
+
assert not Path('.agent').exists(), 'fresh explicit handoff with vague acceptance should fail closed without writing canonical state'
|
|
1636
|
+
assert 'fresh explicit primary-agent handoff exists' in output, 'fresh explicit handoff with vague acceptance should use the dedicated explicit-handoff fail-closed message'
|
|
1637
|
+
assert 'acceptance is not anchored to concrete repo changes or verification' in output, 'fresh explicit handoff with vague acceptance should explain the vague acceptance failure'
|
|
1638
|
+
PY
|
|
1639
|
+
|
|
1640
|
+
# Done workflow + fresh handoff: the fresh explicit handoff should override done-state suppression and start the new round.
|
|
1641
|
+
HANDOFF_ROOT_DONE="$TMPDIR/handoff-root-done"
|
|
1642
|
+
mkdir -p "$HANDOFF_ROOT_DONE"
|
|
1643
|
+
cd "$HANDOFF_ROOT_DONE"
|
|
1644
|
+
git init -q
|
|
1645
|
+
|
|
1646
|
+
DONE_SEED_SESSION="$TMPDIR/handoff-done-seed-session.jsonl"
|
|
1647
|
+
DONE_SEED_DISCUSSION=$'Mission: Seed a finished workflow before testing fresh handoff priority.\nScope:\n- Create canonical workflow state.\nConstraints:\n- Keep the seed minimal.\nAcceptance:\n- Mark the workflow done before the next test step.'
|
|
1648
|
+
write_session "$DONE_SEED_SESSION" "$HANDOFF_ROOT_DONE" "$DONE_SEED_DISCUSSION"
|
|
1649
|
+
PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=accept \
|
|
1650
|
+
PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
|
|
1651
|
+
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
1652
|
+
pi --session "$DONE_SEED_SESSION" -e "$PKG_ROOT" -p "/cook" >"$TMPDIR/pi-completion-handoff-done-seed.out" 2>"$TMPDIR/pi-completion-handoff-done-seed.err"
|
|
1653
|
+
mark_done
|
|
1654
|
+
|
|
1655
|
+
HANDOFF_SESSION_DONE="$TMPDIR/handoff-session-done.jsonl"
|
|
1656
|
+
HANDOFF_SNAPSHOT_DONE="$TMPDIR/handoff-proposal-done.json"
|
|
1657
|
+
HANDOFF_MESSAGES_DONE="$(python3 - <<'PY'
|
|
1658
|
+
import json
|
|
1659
|
+
capsule = {
|
|
1660
|
+
"kind": "cook_handoff",
|
|
1661
|
+
"source": "primary_agent",
|
|
1662
|
+
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
1663
|
+
"source_turn_id": "m0002",
|
|
1664
|
+
"mission": "Reopen the login redirect work for the callback edge case.",
|
|
1665
|
+
"scope": [
|
|
1666
|
+
"Handle the callback edge case in the redirect logic.",
|
|
1667
|
+
"Keep the finished workflow as historical context only."
|
|
1668
|
+
],
|
|
1669
|
+
"constraints": [
|
|
1670
|
+
"Do not turn done-state suppression into the startup mission."
|
|
1671
|
+
],
|
|
1672
|
+
"acceptance": [
|
|
1673
|
+
"Add a regression test for the callback edge case."
|
|
1674
|
+
],
|
|
1675
|
+
"risks": [
|
|
1676
|
+
"Done-state context could override the new mission if the handoff is ignored."
|
|
1677
|
+
],
|
|
1678
|
+
"notes": [
|
|
1679
|
+
"This is a fresh implementation round, not a summary of the finished workflow."
|
|
1680
|
+
],
|
|
1681
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
1682
|
+
"first_slice_goal": "Patch the callback edge case and cover it with a focused regression test.",
|
|
1683
|
+
"first_slice_non_goals": [
|
|
1684
|
+
"Do not turn done-state suppression into the startup mission."
|
|
1685
|
+
],
|
|
1686
|
+
"implementation_surfaces": [
|
|
1687
|
+
"src/auth/redirect.ts",
|
|
1688
|
+
"tests/auth/redirect-edge.spec.ts"
|
|
1689
|
+
],
|
|
1690
|
+
"verification_commands": [
|
|
1691
|
+
"npm test -- redirect-edge.spec.ts"
|
|
1692
|
+
],
|
|
1693
|
+
"why_this_slice_first": "The new callback edge case is the smallest fresh implementation slice after the prior round closed.",
|
|
1694
|
+
"task_type": "completion-workflow",
|
|
1695
|
+
"evaluation_profile": "completion-rubric-v1",
|
|
1696
|
+
"why_cook_now": "A new implementation-ready edge case was identified after the previous round closed."
|
|
1697
|
+
}
|
|
1698
|
+
messages = [
|
|
1699
|
+
{"role": "user", "content": "The previous round is done, but there is a fresh callback edge case to implement."},
|
|
1700
|
+
{"role": "assistant", "content": "The next round is ready for /cook. Run /cook to confirm this fresh implementation mission.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
1701
|
+
]
|
|
1702
|
+
print(json.dumps(messages, ensure_ascii=False))
|
|
1703
|
+
PY
|
|
1704
|
+
)"
|
|
1705
|
+
write_session_messages "$HANDOFF_SESSION_DONE" "$HANDOFF_ROOT_DONE" "$HANDOFF_MESSAGES_DONE"
|
|
1706
|
+
|
|
1707
|
+
PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=accept \
|
|
1708
|
+
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$HANDOFF_SNAPSHOT_DONE" \
|
|
1709
|
+
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
1710
|
+
pi --session "$HANDOFF_SESSION_DONE" -e "$PKG_ROOT" -p "/cook" >"$TMPDIR/pi-completion-handoff-done.out" 2>"$TMPDIR/pi-completion-handoff-done.err"
|
|
1711
|
+
|
|
1712
|
+
python3 - "$HANDOFF_SNAPSHOT_DONE" <<'PY'
|
|
1713
|
+
import json
|
|
1714
|
+
import sys
|
|
1715
|
+
from pathlib import Path
|
|
1716
|
+
|
|
1717
|
+
snapshot = json.loads(Path(sys.argv[1]).read_text())
|
|
1718
|
+
state = json.loads(Path('.agent/state.json').read_text())
|
|
1719
|
+
|
|
1720
|
+
assert snapshot['source'] == 'handoff_capsule', 'done-workflow handoff should still use the explicit handoff capsule'
|
|
1721
|
+
assert snapshot['mission'] == 'Reopen the login redirect work for the callback edge case.', 'done-workflow handoff should preserve the fresh mission'
|
|
1722
|
+
assert state['mission_anchor'] == 'Reopen the login redirect work for the callback edge case.', 'done-workflow handoff should override done-state suppression with the fresh mission'
|
|
1723
|
+
assert state['continuation_policy'] == 'continue', 'done-workflow handoff should reopen canonical workflow state for the new round'
|
|
1724
|
+
assert state['advisory_startup_brief']['source'] == 'primary_agent_handoff', 'done-workflow handoff should preserve the handoff advisory source'
|
|
1725
|
+
assert 'First slice goal: Patch the callback edge case and cover it with a focused regression test.' in state['advisory_startup_brief']['notes'], 'done-workflow handoff should preserve first_slice_goal in advisory notes'
|
|
1726
|
+
assert 'Verification commands: npm test -- redirect-edge.spec.ts' in state['advisory_startup_brief']['notes'], 'done-workflow handoff should preserve verification_commands in advisory notes'
|
|
1727
|
+
PY
|
|
1728
|
+
|
|
1729
|
+
# Stale handoff: later discussion should invalidate the older handoff capsule and fall back to the newer discussion mission.
|
|
1730
|
+
HANDOFF_ROOT_STALE="$TMPDIR/handoff-root-stale"
|
|
1731
|
+
mkdir -p "$HANDOFF_ROOT_STALE"
|
|
1732
|
+
cd "$HANDOFF_ROOT_STALE"
|
|
1733
|
+
git init -q
|
|
1734
|
+
|
|
1735
|
+
HANDOFF_SESSION_STALE="$TMPDIR/handoff-session-stale.jsonl"
|
|
1736
|
+
HANDOFF_SNAPSHOT_STALE="$TMPDIR/handoff-proposal-stale.json"
|
|
1737
|
+
HANDOFF_MESSAGES_STALE="$(python3 - <<'PY'
|
|
1738
|
+
import json
|
|
1739
|
+
capsule = {
|
|
1740
|
+
"kind": "cook_handoff",
|
|
1741
|
+
"source": "primary_agent",
|
|
1742
|
+
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
1743
|
+
"source_turn_id": "m0002",
|
|
1744
|
+
"mission": "Fix the original login redirect callback behavior.",
|
|
1745
|
+
"scope": ["Update the original callback redirect logic."],
|
|
1746
|
+
"constraints": ["Do not refactor the auth stack."],
|
|
1747
|
+
"acceptance": ["Add the original callback regression test."],
|
|
1748
|
+
"risks": [],
|
|
1749
|
+
"notes": [],
|
|
1750
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
1751
|
+
"first_slice_goal": "Ship the original login callback follow-up.",
|
|
1752
|
+
"first_slice_non_goals": ["Do not refactor the auth stack."],
|
|
1753
|
+
"implementation_surfaces": ["src/auth/login-redirect.ts"],
|
|
1754
|
+
"verification_commands": ["npm test -- login-redirect.spec.ts"],
|
|
1755
|
+
"why_this_slice_first": "The original callback follow-up was the first bounded implementation slice before later discussion replaced it."
|
|
1756
|
+
}
|
|
1757
|
+
newer_discussion = "Mission: Ship logout redirect consistency instead.\nScope:\n- Update the logout redirect path.\nConstraints:\n- Leave the login callback flow unchanged.\nAcceptance:\n- Add a logout redirect regression test."
|
|
1758
|
+
messages = [
|
|
1759
|
+
{"role": "user", "content": "Please plan the login redirect follow-up."},
|
|
1760
|
+
{"role": "assistant", "content": "Run /cook if you want to start the original follow-up.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
1761
|
+
{"role": "user", "content": newer_discussion},
|
|
1762
|
+
]
|
|
1763
|
+
print(json.dumps(messages, ensure_ascii=False))
|
|
1764
|
+
PY
|
|
1765
|
+
)"
|
|
1766
|
+
write_session_messages "$HANDOFF_SESSION_STALE" "$HANDOFF_ROOT_STALE" "$HANDOFF_MESSAGES_STALE"
|
|
1767
|
+
|
|
1768
|
+
PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=accept \
|
|
1769
|
+
PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
|
|
1770
|
+
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$HANDOFF_SNAPSHOT_STALE" \
|
|
1771
|
+
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
1772
|
+
pi --session "$HANDOFF_SESSION_STALE" -e "$PKG_ROOT" -p "/cook" >"$TMPDIR/pi-completion-handoff-stale.out" 2>"$TMPDIR/pi-completion-handoff-stale.err"
|
|
1773
|
+
|
|
1774
|
+
python3 - "$HANDOFF_SNAPSHOT_STALE" <<'PY'
|
|
1775
|
+
import json
|
|
1776
|
+
import sys
|
|
1777
|
+
from pathlib import Path
|
|
1778
|
+
|
|
1779
|
+
snapshot = json.loads(Path(sys.argv[1]).read_text())
|
|
1780
|
+
state = json.loads(Path('.agent/state.json').read_text())
|
|
1781
|
+
|
|
1782
|
+
assert snapshot['source'] == 'session', 'stale handoff should fall back to the newer user discussion proposal'
|
|
1783
|
+
assert snapshot['mission'] == 'Ship logout redirect consistency instead.', 'stale handoff fallback should prefer the newer discussion mission'
|
|
1784
|
+
assert state['mission_anchor'] == 'Ship logout redirect consistency instead.', 'stale handoff fallback should not keep the older handoff mission'
|
|
1785
|
+
assert state['advisory_startup_brief']['source'] == 'recent_discussion', 'stale handoff fallback should preserve that the accepted startup came from discussion'
|
|
1786
|
+
PY
|
|
1787
|
+
|
|
1788
|
+
# Negative handoff rationale: a non-startable capsule must not become the startup mission.
|
|
1789
|
+
HANDOFF_ROOT_NEGATIVE="$TMPDIR/handoff-root-negative"
|
|
1790
|
+
mkdir -p "$HANDOFF_ROOT_NEGATIVE"
|
|
1791
|
+
cd "$HANDOFF_ROOT_NEGATIVE"
|
|
1792
|
+
git init -q
|
|
1793
|
+
|
|
1794
|
+
HANDOFF_SESSION_NEGATIVE="$TMPDIR/handoff-session-negative.jsonl"
|
|
1795
|
+
HANDOFF_SNAPSHOT_NEGATIVE="$TMPDIR/handoff-proposal-negative.json"
|
|
1796
|
+
HANDOFF_MESSAGES_NEGATIVE="$(python3 - <<'PY'
|
|
1797
|
+
import json
|
|
1798
|
+
capsule = {
|
|
1799
|
+
"kind": "cook_handoff",
|
|
1800
|
+
"source": "primary_agent",
|
|
1801
|
+
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
1802
|
+
"source_turn_id": "m0002",
|
|
1803
|
+
"mission": "Do not reopen implementation for the finished workflow.",
|
|
1804
|
+
"scope": ["Keep the old workflow closed."],
|
|
1805
|
+
"constraints": ["Do not start repo changes."],
|
|
1806
|
+
"acceptance": ["Explain that the finished workflow should stay closed."],
|
|
1807
|
+
"risks": [],
|
|
1808
|
+
"notes": [],
|
|
1809
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
1810
|
+
"first_slice_goal": "Keep the finished workflow closed.",
|
|
1811
|
+
"first_slice_non_goals": ["Do not start repo changes."],
|
|
1812
|
+
"implementation_surfaces": ["docs/workflow-status.md"],
|
|
1813
|
+
"verification_commands": ["npm test -- workflow-status"],
|
|
1814
|
+
"why_this_slice_first": "This is the only bounded next step being proposed, even though the mission itself is invalid."
|
|
1815
|
+
}
|
|
1816
|
+
messages = [
|
|
1817
|
+
{"role": "user", "content": "Should we reopen the finished workflow?"},
|
|
1818
|
+
{"role": "assistant", "content": "Do not reopen it directly.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
1819
|
+
]
|
|
1820
|
+
print(json.dumps(messages, ensure_ascii=False))
|
|
1821
|
+
PY
|
|
1822
|
+
)"
|
|
1823
|
+
write_session_messages "$HANDOFF_SESSION_NEGATIVE" "$HANDOFF_ROOT_NEGATIVE" "$HANDOFF_MESSAGES_NEGATIVE"
|
|
1824
|
+
|
|
1825
|
+
PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
|
|
1826
|
+
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$HANDOFF_SNAPSHOT_NEGATIVE" \
|
|
1827
|
+
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
1828
|
+
pi --session "$HANDOFF_SESSION_NEGATIVE" -e "$PKG_ROOT" -p "/cook" >"$TMPDIR/pi-completion-handoff-negative.out" 2>"$TMPDIR/pi-completion-handoff-negative.err"
|
|
1829
|
+
|
|
1830
|
+
python3 - "$HANDOFF_SNAPSHOT_NEGATIVE" "$TMPDIR/pi-completion-handoff-negative.out" "$TMPDIR/pi-completion-handoff-negative.err" <<'PY'
|
|
1831
|
+
import sys
|
|
1832
|
+
from pathlib import Path
|
|
1833
|
+
|
|
1834
|
+
snapshot = Path(sys.argv[1])
|
|
1835
|
+
output = Path(sys.argv[2]).read_text() + Path(sys.argv[3]).read_text()
|
|
1836
|
+
|
|
1837
|
+
assert not snapshot.exists(), 'negative handoff rationale should not emit a startup proposal snapshot'
|
|
1838
|
+
assert not Path('.agent').exists(), 'negative handoff rationale should fail closed without writing canonical state'
|
|
1839
|
+
assert '/cook failed closed' in output, 'negative handoff rationale should fail closed instead of becoming the startup mission'
|
|
1840
|
+
PY
|
|
1841
|
+
|
|
1361
1842
|
grep -q 'export async function deriveCookContextProposalFromRecentDiscussion' "$PKG_ROOT/extensions/completion/proposal.ts"
|
|
1843
|
+
grep -q 'export function extractLatestCookHandoffProposal' "$PKG_ROOT/extensions/completion/proposal.ts"
|
|
1362
1844
|
grep -q 'export function parseContextProposalAnalystOutput' "$PKG_ROOT/extensions/completion/proposal.ts"
|
|
1363
1845
|
grep -q 'export function buildContextProposalConfirmationLayout' "$PKG_ROOT/extensions/completion/prompt-surfaces.ts"
|
|
1364
1846
|
grep -q 'export function buildEvaluationRoleContextLines' "$PKG_ROOT/extensions/completion/prompt-surfaces.ts"
|
package/scripts/release-check.sh
CHANGED
|
@@ -3,6 +3,7 @@ set -euo pipefail
|
|
|
3
3
|
|
|
4
4
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
5
|
cd "$ROOT"
|
|
6
|
+
export PI_COMPLETION_RUNNING_RELEASE_CHECK=1
|
|
6
7
|
|
|
7
8
|
echo "[release-check] running control-plane validation, tracked .agent contract coverage, slice-surface parity, explicit-/cook parity, startup/refocus/context regressions, canonical evidence artifact, active-slice contract, observability, legacy cleanup, evaluator calibration, and rubric contract coverage"
|
|
8
9
|
bash .agent/verify_completion_control_plane.sh
|
|
@@ -18,19 +19,26 @@ checks = {
|
|
|
18
19
|
"`/cook` is the explicit workflow boundary for starting, continuing, refocusing, or beginning the next round of long-running repo work.",
|
|
19
20
|
"Only explicit `/cook` enters the workflow. Ordinary prompts stay in the main chat and go straight to the primary agent.",
|
|
20
21
|
"If a task has clearly matured into completion-workflow scope, the primary agent should hand you off to `/cook` instead of starting long-running implementation directly in ordinary chat.",
|
|
21
|
-
"`/cook`
|
|
22
|
-
"
|
|
23
|
-
"The
|
|
22
|
+
"That handoff should include an explicit structured `/cook` capsule in the assistant reply so `/cook` can confirm the already-formed mission instead of re-deriving it from broad ambient context.",
|
|
23
|
+
"for that handoff capsule to start workflow immediately, it must already be implementation-startable: a bounded `first_slice_goal`, repo-change-oriented acceptance, `implementation_surfaces`, `verification_commands`, and `why_this_slice_first`",
|
|
24
|
+
"The preferred capsule is still advisory startup intake, not canonical workflow state, and it only counts as implementation-ready when it already names the first bounded slice, repo-change-oriented acceptance, implementation surfaces, and verification commands.",
|
|
25
|
+
"`/cook` first looks for a fresh explicit primary-agent handoff capsule. If one is valid and implementation-startable, `/cook` builds the startup brief from that handoff and only uses recent discussion as validation or supplemental notes.",
|
|
26
|
+
"`/cook` falls back to deriving a startup brief from recent discussion only when no fresh explicit handoff is blocking startup—for example, when there is no fresh capsule or only stale or invalidated capsules—before showing the existing approval-only Start/Cancel gate.",
|
|
27
|
+
"The pre-`/cook` handoff capsule itself is not canonical workflow state. It is only startup intake for `/cook`.",
|
|
24
28
|
],
|
|
25
29
|
"CHANGELOG.md": [
|
|
26
|
-
"made `/cook`
|
|
27
|
-
"
|
|
28
|
-
"
|
|
30
|
+
"made explicit primary-agent `/cook` handoff the preferred startup-intake path by teaching ordinary-chat handoff turns to emit a structured `cook_handoff` capsule and letting `/cook` prefer that capsule over broad context re-inference when it is fresh, valid, and implementation-startable",
|
|
31
|
+
"tightened implementation-ready explicit handoffs so the structured capsule must already carry a bounded `first_slice_goal`, repo-change-oriented acceptance, `implementation_surfaces`, `verification_commands`, and `why_this_slice_first` before `/cook` will start workflow from it",
|
|
32
|
+
"kept the pre-`/cook` handoff capsule as advisory startup intake only, not canonical `.agent/**` workflow state, while still using context-derived startup as the fallback only when no fresh explicit handoff is blocking startup",
|
|
33
|
+
"kept context-derived startup as a fallback only when there is no fresh explicit handoff blocking startup, so stale or invalidated capsules can still fall back to recent discussion while fresh non-startable handoffs fail closed instead of silently rewriting canonical state",
|
|
34
|
+
"made finished-workflow suppression stay a safety layer instead of a replacement mission when a fresh explicit `/cook` handoff exists, and blocked negative rejection/suppression text from becoming a Startable startup mission",
|
|
29
35
|
],
|
|
30
36
|
"extensions/completion/prompt-surfaces.ts": [
|
|
31
37
|
'"/cook is the only explicit entrypoint into long-running completion workflow."',
|
|
32
38
|
'"When you judge that the task has matured into completion-workflow scope',
|
|
33
|
-
'"
|
|
39
|
+
'"Distinguish a workflow-worthy handoff from an implementation-ready handoff: only emit the implementation-ready capsule when the first bounded implementation slice is concrete enough to start immediately."',
|
|
40
|
+
'"Otherwise append one exact fenced block in the same assistant reply using ```cook_handoff ... ``` JSON with kind/source/handoff_kind plus mission, scope, constraints or non_goals, acceptance, risks, notes, captured_at, source_turn_id, first_slice_goal, first_slice_non_goals, implementation_surfaces, verification_commands, why_this_slice_first, and optional task_type/evaluation_profile/why_cook_now."',
|
|
41
|
+
'"The capsule is startup intake for /cook only: do not present it as canonical .agent state',
|
|
34
42
|
],
|
|
35
43
|
}
|
|
36
44
|
|
package/scripts/smoke-test.sh
CHANGED
|
@@ -170,6 +170,10 @@ assert handoff.exists(), 'ordinary non-/cook turn should inject the /cook handof
|
|
|
170
170
|
handoff_text = handoff.read_text()
|
|
171
171
|
assert '/cook is the only explicit entrypoint into long-running completion workflow.' in handoff_text, 'ordinary handoff reminder should preserve the explicit /cook workflow boundary'
|
|
172
172
|
assert 'stop short of long-running implementation and tell the user to run /cook.' in handoff_text, 'ordinary handoff reminder should require primary-agent handoff before implementation'
|
|
173
|
+
assert '```cook_handoff ... ``` JSON' in handoff_text, 'ordinary handoff reminder should require the explicit structured /cook handoff capsule'
|
|
174
|
+
assert 'implementation_workflow_handoff' in handoff_text, 'ordinary handoff reminder should require the implementation-ready handoff kind'
|
|
175
|
+
assert 'first_slice_goal, first_slice_non_goals, implementation_surfaces, verification_commands, why_this_slice_first' in handoff_text, 'ordinary handoff reminder should require first-slice startability fields'
|
|
176
|
+
assert 'The capsule is startup intake for /cook only' in handoff_text, 'ordinary handoff reminder should keep the capsule non-canonical'
|
|
173
177
|
assert not auto_resume.exists(), 'ordinary non-/cook turn should not queue auto-resume before /cook activation'
|
|
174
178
|
assert 'Skipped completion workflow auto-resume prompt (test mode)' not in output, 'ordinary non-/cook turn should not attempt auto-resume'
|
|
175
179
|
PY
|
|
@@ -35,11 +35,49 @@ When the task is judged ready for completion workflow, the primary agent must:
|
|
|
35
35
|
- stop before long-running implementation
|
|
36
36
|
- not edit tracked product files in ordinary chat for that workflow-level task
|
|
37
37
|
- tell the user to run `/cook`
|
|
38
|
-
- explain that `/cook` will
|
|
38
|
+
- explain that `/cook` will first look for a fresh explicit primary-agent handoff and otherwise fall back to recent discussion before asking for confirmation
|
|
39
|
+
- distinguish a workflow-worthy handoff from an implementation-ready handoff
|
|
40
|
+
- only append an implementation-ready `/cook` handoff capsule when the first bounded implementation slice is concrete enough to start immediately
|
|
41
|
+
|
|
42
|
+
Required capsule format:
|
|
43
|
+
|
|
44
|
+
````text
|
|
45
|
+
```cook_handoff
|
|
46
|
+
{
|
|
47
|
+
"kind": "cook_handoff",
|
|
48
|
+
"source": "primary_agent",
|
|
49
|
+
"captured_at": "<ISO-8601 timestamp>",
|
|
50
|
+
"source_turn_id": "<current assistant turn id>",
|
|
51
|
+
"mission": "<startable implementation mission>",
|
|
52
|
+
"scope": ["..."],
|
|
53
|
+
"constraints": ["..."],
|
|
54
|
+
"non_goals": ["..."],
|
|
55
|
+
"acceptance": ["..."],
|
|
56
|
+
"risks": ["..."],
|
|
57
|
+
"notes": ["..."],
|
|
58
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
59
|
+
"first_slice_goal": "<bounded first slice goal>",
|
|
60
|
+
"first_slice_non_goals": ["..."],
|
|
61
|
+
"implementation_surfaces": ["path/or/surface"],
|
|
62
|
+
"verification_commands": ["npm test -- example"],
|
|
63
|
+
"why_this_slice_first": "<why this first slice should start the workflow>",
|
|
64
|
+
"task_type": "completion-workflow",
|
|
65
|
+
"evaluation_profile": "completion-rubric-v1",
|
|
66
|
+
"why_cook_now": "<why the task is ready for /cook now>"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
````
|
|
70
|
+
|
|
71
|
+
Notes:
|
|
72
|
+
|
|
73
|
+
- `constraints` may be replaced or supplemented by `non_goals` when clearer.
|
|
74
|
+
- `first_slice_goal`, `first_slice_non_goals`, `implementation_surfaces`, `verification_commands`, and `why_this_slice_first` are required only for implementation-ready handoffs; if the work is workflow-worthy but that first slice is still vague, tell the user to run `/cook` without emitting this implementation-ready capsule.
|
|
75
|
+
- The mission must be positively startable implementation work; do not use rejection or suppression text as the mission.
|
|
76
|
+
- The capsule is startup intake for `/cook` only. It is not canonical `.agent/**` state, not active-slice state, and not a second repo contract source.
|
|
39
77
|
|
|
40
78
|
Suggested wording:
|
|
41
79
|
|
|
42
|
-
> This task is now mature enough for the `/cook` workflow. If you want me to start implementation, run `/cook`. I’
|
|
80
|
+
> This task is now mature enough for the `/cook` workflow. If you want me to start implementation, run `/cook`. I’ve also attached an explicit `/cook` handoff capsule so `/cook` can confirm this plan directly before the workflow begins.
|
|
43
81
|
|
|
44
82
|
A short recap may include mission, scope, or acceptance, but that recap must not be presented as canonical plan state.
|
|
45
83
|
|