@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.
- package/.agent/README.md +2 -3
- package/.agent/verify_completion_control_plane.sh +21 -34
- package/CHANGELOG.md +17 -0
- package/README.md +23 -26
- package/agents/completion-bootstrapper.md +1 -2
- package/agents/completion-regrounder.md +10 -16
- package/extensions/completion/driver.ts +49 -117
- package/extensions/completion/index.ts +74 -123
- package/extensions/completion/policy-guards.ts +1 -1
- package/extensions/completion/prompt-surfaces.ts +15 -156
- package/extensions/completion/proposal.ts +21 -21
- package/extensions/completion/role-runner.ts +10 -11
- package/extensions/completion/state-store.ts +43 -85
- package/extensions/completion/types.ts +2 -3
- package/package.json +1 -1
- package/scripts/active-slice-contract-test.sh +28 -12
- package/scripts/canonical-evidence-artifact-test.sh +46 -59
- package/scripts/context-proposal-test.sh +58 -57
- package/scripts/refocus-test.sh +17 -17
- package/scripts/release-check.sh +14 -13
- package/scripts/role-runner-contract-test.sh +2 -2
- package/scripts/smoke-test.sh +24 -71
- package/skills/completion-protocol/SKILL.md +8 -9
- package/skills/completion-protocol/references/completion.md +2 -37
- package/skills/cook-handoff-boundary/SKILL.md +18 -16
|
@@ -147,7 +147,7 @@ mkdir -p "$ROOT"
|
|
|
147
147
|
cd "$ROOT"
|
|
148
148
|
git init -q
|
|
149
149
|
|
|
150
|
-
# No workflow yet: bare /cook should be able to generate a primary-agent
|
|
150
|
+
# No workflow yet: bare /cook should be able to generate a primary-agent handoff in the same entry,
|
|
151
151
|
# then continue directly to startup confirmation.
|
|
152
152
|
SESSION_ZERO="$TMPDIR/session-zero.jsonl"
|
|
153
153
|
DISCUSSION_ZERO=$'Mission: Remove the completion status line while keeping the completion widget.
|
|
@@ -178,7 +178,7 @@ capsule = {
|
|
|
178
178
|
"Keep observability regression coverage truthful."
|
|
179
179
|
],
|
|
180
180
|
"risks": [],
|
|
181
|
-
"notes": ["Generated by the primary-agent
|
|
181
|
+
"notes": ["Generated by the primary-agent handoff step triggered from /cook."],
|
|
182
182
|
"handoff_kind": "implementation_workflow_handoff",
|
|
183
183
|
"first_slice_goal": "Remove the completion status line while preserving the widget behavior.",
|
|
184
184
|
"first_slice_non_goals": ["Do not reintroduce another status surface."],
|
|
@@ -203,13 +203,13 @@ from pathlib import Path
|
|
|
203
203
|
|
|
204
204
|
output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
|
|
205
205
|
snapshot = Path(sys.argv[3])
|
|
206
|
-
assert Path('.agent').exists(), 'primary-agent
|
|
207
|
-
assert snapshot.exists(), 'primary-agent
|
|
206
|
+
assert Path('.agent').exists(), 'primary-agent handoff generation should scaffold canonical state in the same /cook entry'
|
|
207
|
+
assert snapshot.exists(), 'primary-agent handoff generation should emit a startup proposal snapshot'
|
|
208
208
|
proposal = json.loads(snapshot.read_text())
|
|
209
209
|
brief = json.loads(Path('.agent/state.json').read_text())['advisory_startup_brief']
|
|
210
|
-
assert proposal['source'] == 'handoff_capsule', 'generated primary-agent
|
|
211
|
-
assert brief['source'] == 'primary_agent_handoff', 'generated primary-agent
|
|
212
|
-
assert 'Initialized completion control plane' in output, 'same-entry primary-agent
|
|
210
|
+
assert proposal['source'] == 'handoff_capsule', 'generated primary-agent handoff should be consumed as handoff capsule startup source'
|
|
211
|
+
assert brief['source'] == 'primary_agent_handoff', 'generated primary-agent handoff should record primary_agent_handoff advisory intake'
|
|
212
|
+
assert 'Initialized completion control plane' in output, 'same-entry primary-agent handoff generation should initialize canonical workflow state'
|
|
213
213
|
PY
|
|
214
214
|
|
|
215
215
|
rm -rf .agent
|
|
@@ -258,7 +258,7 @@ output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
|
|
|
258
258
|
snapshot = Path(sys.argv[3])
|
|
259
259
|
assert not Path('.agent').exists(), 'user-authored faux handoff without supporting discussion should still fail closed without writing canonical state'
|
|
260
260
|
assert not snapshot.exists(), 'user-authored faux handoff should not emit a startup proposal snapshot'
|
|
261
|
-
assert '
|
|
261
|
+
assert 'primary-agent handoff step could not prepare a concrete startup handoff' in output, 'user-authored faux handoff should fail closed when primary-agent handoff generation yields no handoff'
|
|
262
262
|
PY
|
|
263
263
|
|
|
264
264
|
# No workflow yet: malformed or invalid assistant handoff capsules must also fail closed.
|
|
@@ -280,10 +280,10 @@ output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
|
|
|
280
280
|
snapshot = Path(sys.argv[3])
|
|
281
281
|
assert not Path('.agent').exists(), 'invalid assistant handoff without supporting discussion should fail closed without writing canonical state'
|
|
282
282
|
assert not snapshot.exists(), 'invalid assistant handoff should not emit a startup proposal snapshot'
|
|
283
|
-
assert '
|
|
283
|
+
assert 'primary-agent handoff step could not prepare a concrete startup handoff' in output, 'invalid assistant handoff should fail closed when no valid handoff can be prepared'
|
|
284
284
|
PY
|
|
285
285
|
|
|
286
|
-
# No workflow yet: a fresh explicit primary-agent
|
|
286
|
+
# No workflow yet: a fresh explicit primary-agent handoff should still bootstrap canonical startup state.
|
|
287
287
|
SESSION_ONE="$TMPDIR/session-one.jsonl"
|
|
288
288
|
HANDOFF_SNAPSHOT_ONE="$TMPDIR/context-proposal-explicit-startup.json"
|
|
289
289
|
HANDOFF_MESSAGES_ONE="$(python3 - <<'PY'
|
|
@@ -309,7 +309,7 @@ capsule = {
|
|
|
309
309
|
"Stale widget-removal discussion could broaden the startup plan if the handoff is ignored."
|
|
310
310
|
],
|
|
311
311
|
"notes": [
|
|
312
|
-
"Keep the startup
|
|
312
|
+
"Keep the startup brief aligned with the explicit primary-agent plan."
|
|
313
313
|
],
|
|
314
314
|
"handoff_kind": "implementation_workflow_handoff",
|
|
315
315
|
"first_slice_goal": "Land the completion-status removal and keep the completion widget coverage truthful.",
|
|
@@ -326,11 +326,11 @@ capsule = {
|
|
|
326
326
|
"why_this_slice_first": "The startup boundary regression is already bounded enough to implement safely.",
|
|
327
327
|
"task_type": "completion-workflow",
|
|
328
328
|
"evaluation_profile": "completion-rubric-v1",
|
|
329
|
-
"why_cook_now": "The explicit startup
|
|
329
|
+
"why_cook_now": "The explicit startup brief is concrete and ready for repo changes."
|
|
330
330
|
}
|
|
331
331
|
messages = [
|
|
332
332
|
{"role": "user", "content": "Please think through the completion widget startup boundary and tell me when it is ready for /cook."},
|
|
333
|
-
{"role": "assistant", "content": "This task is now ready for /cook. Run /cook to confirm the startup
|
|
333
|
+
{"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```"},
|
|
334
334
|
]
|
|
335
335
|
print(json.dumps(messages, ensure_ascii=False))
|
|
336
336
|
PY
|
|
@@ -379,8 +379,8 @@ assert brief['acceptance'] == ['Update README to match the shipped behavior.', '
|
|
|
379
379
|
assert brief['risks'] == ['Stale widget-removal discussion could broaden the startup plan if the handoff is ignored.'], 'advisory startup brief should preserve handoff risks'
|
|
380
380
|
assert 'First slice goal: Land the completion-status removal and keep the completion widget coverage truthful.' in brief['notes'], 'advisory startup brief should preserve first_slice_goal in notes'
|
|
381
381
|
assert 'Verification commands: npm run context-proposal-test' in brief['notes'], 'advisory startup brief should preserve verification_commands in notes'
|
|
382
|
-
assert plan['candidate_slices'] == [], 'startup
|
|
383
|
-
assert active['status'] == 'idle', 'startup
|
|
382
|
+
assert plan['candidate_slices'] == [], 'startup brief should remain advisory intake only until regrounder owns plan selection'
|
|
383
|
+
assert active['status'] == 'idle', 'startup brief should not become the active-slice source before regrounder runs'
|
|
384
384
|
assert proposal['mission'] == mission, 'explicit startup proposal snapshot should keep the handoff mission anchor'
|
|
385
385
|
assert proposal['source'] == 'handoff_capsule', 'explicit startup proposal snapshot should expose the handoff capsule source'
|
|
386
386
|
assert proposal['analysis']['taskType'] == expected_task_type, 'explicit startup proposal snapshot should expose task_type hints separately'
|
|
@@ -561,7 +561,7 @@ assert plan['mission_anchor'] == mission, 'summary-only active bare /cook should
|
|
|
561
561
|
assert active['mission_anchor'] == mission, 'summary-only active bare /cook should keep active-slice.json unchanged'
|
|
562
562
|
PY
|
|
563
563
|
|
|
564
|
-
# Active workflow: a fresh explicit
|
|
564
|
+
# Active workflow: a fresh explicit handoff that is not implementation-startable should still fail closed
|
|
565
565
|
# without rewriting canonical state.
|
|
566
566
|
SESSION_ONE_NON_STARTABLE_ACTIVE="$TMPDIR/session-one-non-startable-active.jsonl"
|
|
567
567
|
NON_STARTABLE_ACTIVE_ROUTING="$TMPDIR/active-non-startable-routing.json"
|
|
@@ -577,7 +577,7 @@ capsule = {
|
|
|
577
577
|
"source_turn_id": "m0002",
|
|
578
578
|
"mission": "Replace the current widget mission from a vague explicit handoff.",
|
|
579
579
|
"scope": [
|
|
580
|
-
"Replace the active workflow from a fresh explicit
|
|
580
|
+
"Replace the active workflow from a fresh explicit handoff."
|
|
581
581
|
],
|
|
582
582
|
"constraints": [
|
|
583
583
|
"Do not rely on recent discussion to fill in missing implementation details."
|
|
@@ -603,7 +603,7 @@ capsule = {
|
|
|
603
603
|
"evaluation_profile": "completion-rubric-v1"
|
|
604
604
|
}
|
|
605
605
|
messages = [
|
|
606
|
-
{"role": "user", "content": "We may need a different active workflow, but only if there is a fresh explicit
|
|
606
|
+
{"role": "user", "content": "We may need a different active workflow, but only if there is a fresh explicit handoff."},
|
|
607
607
|
{"role": "assistant", "content": "Only use this capsule if it is concrete enough.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
608
608
|
]
|
|
609
609
|
print(json.dumps(messages, ensure_ascii=False))
|
|
@@ -656,12 +656,12 @@ after = {
|
|
|
656
656
|
assert routing['mode'] == 'bare', 'fresh non-startable explicit handoff should snapshot bare routing mode'
|
|
657
657
|
assert routing['action'] == 'blocked', 'fresh non-startable explicit handoff should fail closed for active bare /cook'
|
|
658
658
|
assert routing['reason'] == 'fresh_explicit_handoff_not_startable', 'fresh non-startable explicit handoff should keep the dedicated explicit-handoff fail-closed reason'
|
|
659
|
-
assert 'fresh explicit primary-agent
|
|
659
|
+
assert 'fresh explicit primary-agent handoff exists' in routing['blockedFailureMessage'], 'fresh non-startable explicit handoff should surface the dedicated fail-closed message'
|
|
660
660
|
assert 'acceptance is not anchored to concrete repo changes or verification' in routing['blockedFailureMessage'], 'fresh non-startable explicit handoff should explain why the capsule is not startable'
|
|
661
661
|
assert not resume_path.exists(), 'fresh non-startable explicit handoff should not queue a resume prompt'
|
|
662
662
|
assert not chooser_path.exists(), 'fresh non-startable explicit handoff should not open the replacement chooser'
|
|
663
663
|
assert not proposal_path.exists(), 'fresh non-startable explicit handoff should not open final proposal confirmation'
|
|
664
|
-
assert 'fresh explicit primary-agent
|
|
664
|
+
assert 'fresh explicit primary-agent handoff exists' in output, 'fresh non-startable explicit handoff should explain that the explicit capsule blocked active-workflow replacement'
|
|
665
665
|
assert before == after, 'fresh non-startable explicit handoff should leave canonical state unchanged'
|
|
666
666
|
PY
|
|
667
667
|
|
|
@@ -706,7 +706,7 @@ state = json.loads(Path('.agent/state.json').read_text())
|
|
|
706
706
|
assert state['mission_anchor'] == expected, 'completed-topic suppression should keep the done workflow mission anchor unchanged'
|
|
707
707
|
assert state['continuation_policy'] == 'done', 'completed-topic suppression should keep the workflow closed'
|
|
708
708
|
assert not snapshot.exists(), 'completed-topic suppression should not emit a proposal snapshot when the latest discussion only repeats finished work'
|
|
709
|
-
assert '
|
|
709
|
+
assert 'primary-agent handoff step could not prepare a concrete startup handoff' in output, 'completed-topic suppression should fail closed when no concrete primary-agent handoff can be prepared'
|
|
710
710
|
PY
|
|
711
711
|
|
|
712
712
|
# Completed workflow: bare /cook should also suppress proposals that merely restate canonical
|
|
@@ -749,7 +749,7 @@ from pathlib import Path
|
|
|
749
749
|
output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
|
|
750
750
|
snapshot = Path(sys.argv[3])
|
|
751
751
|
assert not snapshot.exists(), 'verification-evidence overlap suppression should not emit a proposal snapshot for already verified work'
|
|
752
|
-
assert '
|
|
752
|
+
assert 'primary-agent handoff step could not prepare a concrete startup handoff' in output, 'verification-evidence overlap suppression should fail closed when no concrete primary-agent handoff can be prepared'
|
|
753
753
|
PY
|
|
754
754
|
|
|
755
755
|
# Completed workflow: bare /cook should fail closed for next-round discussion-only startup too,
|
|
@@ -777,7 +777,7 @@ capsule = {
|
|
|
777
777
|
"Preserve the tracked completion control-plane files."
|
|
778
778
|
],
|
|
779
779
|
"risks": [],
|
|
780
|
-
"notes": ["Generated by the primary-agent
|
|
780
|
+
"notes": ["Generated by the primary-agent handoff step triggered from /cook."],
|
|
781
781
|
"handoff_kind": "implementation_workflow_handoff",
|
|
782
782
|
"first_slice_goal": "Bootstrap the next workflow round from the normalized implementation mission.",
|
|
783
783
|
"first_slice_non_goals": ["Do not reopen finished slices from the previous workflow."],
|
|
@@ -803,13 +803,13 @@ previous = sys.argv[4]
|
|
|
803
803
|
state = json.loads(Path('.agent/state.json').read_text())
|
|
804
804
|
if snapshot.exists():
|
|
805
805
|
proposal = json.loads(snapshot.read_text())
|
|
806
|
-
assert proposal['source'] == 'handoff_capsule', 'done-workflow generated startup should snapshot the primary-agent
|
|
806
|
+
assert proposal['source'] == 'handoff_capsule', 'done-workflow generated startup should snapshot the primary-agent handoff source'
|
|
807
807
|
assert state['mission_anchor'] != previous, 'done-workflow discussion-only startup should advance to the new mission anchor'
|
|
808
808
|
assert state['continuation_policy'] == 'continue', 'done-workflow discussion-only startup should reopen workflow state'
|
|
809
|
-
assert 'Started a new completion workflow round
|
|
809
|
+
assert 'Started a new completion workflow round from explicit primary-agent handoff' in output, 'done-workflow generated startup should report explicit primary-agent handoff startup'
|
|
810
810
|
PY
|
|
811
811
|
|
|
812
|
-
# Completed workflow: a fresh explicit primary-agent
|
|
812
|
+
# Completed workflow: a fresh explicit primary-agent handoff should still start the next round.
|
|
813
813
|
mark_done
|
|
814
814
|
|
|
815
815
|
SESSION_TWO="$TMPDIR/session-two.jsonl"
|
|
@@ -821,7 +821,7 @@ capsule = {
|
|
|
821
821
|
"source": "primary_agent",
|
|
822
822
|
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
823
823
|
"source_turn_id": "m0002",
|
|
824
|
-
"mission": "Ship the next workflow round from a fresh explicit
|
|
824
|
+
"mission": "Ship the next workflow round from a fresh explicit handoff.",
|
|
825
825
|
"scope": [
|
|
826
826
|
"Reset canonical state back to reground for the fresh mission.",
|
|
827
827
|
"Preserve the tracked completion control-plane files."
|
|
@@ -837,10 +837,10 @@ capsule = {
|
|
|
837
837
|
"Done-state history could override the fresh mission if the explicit handoff is ignored."
|
|
838
838
|
],
|
|
839
839
|
"notes": [
|
|
840
|
-
"This next round must come from the fresh explicit
|
|
840
|
+
"This next round must come from the fresh explicit handoff rather than recent discussion."
|
|
841
841
|
],
|
|
842
842
|
"handoff_kind": "implementation_workflow_handoff",
|
|
843
|
-
"first_slice_goal": "Start the next round from the fresh explicit
|
|
843
|
+
"first_slice_goal": "Start the next round from the fresh explicit handoff and preserve canonical control-plane files.",
|
|
844
844
|
"first_slice_non_goals": [
|
|
845
845
|
"Do not resume the completed workflow when the new round is clearly different."
|
|
846
846
|
],
|
|
@@ -851,7 +851,7 @@ capsule = {
|
|
|
851
851
|
"verification_commands": [
|
|
852
852
|
"npm run context-proposal-test"
|
|
853
853
|
],
|
|
854
|
-
"why_this_slice_first": "The fresh explicit
|
|
854
|
+
"why_this_slice_first": "The fresh explicit handoff is the smallest truthful next-round startup after the previous workflow closed.",
|
|
855
855
|
"task_type": "completion-workflow",
|
|
856
856
|
"evaluation_profile": "completion-rubric-v1",
|
|
857
857
|
"why_cook_now": "A new implementation-ready mission was identified after the previous round closed."
|
|
@@ -875,7 +875,7 @@ import json
|
|
|
875
875
|
import sys
|
|
876
876
|
from pathlib import Path
|
|
877
877
|
|
|
878
|
-
mission = 'Ship the next workflow round from a fresh explicit
|
|
878
|
+
mission = 'Ship the next workflow round from a fresh explicit handoff.'
|
|
879
879
|
expected_task_type = 'completion-workflow'
|
|
880
880
|
expected_eval_profile = 'completion-rubric-v1'
|
|
881
881
|
mission_text = Path('.agent/mission.md').read_text()
|
|
@@ -891,7 +891,7 @@ assert profile['evaluation_profile'] == expected_eval_profile, 'profile.json eva
|
|
|
891
891
|
assert state['mission_anchor'] == mission, 'state.json mission_anchor mismatch after starting the next workflow round from explicit handoff'
|
|
892
892
|
assert state['task_type'] == expected_task_type, 'state.json task_type mismatch after starting the next workflow round from explicit handoff'
|
|
893
893
|
assert state['evaluation_profile'] == expected_eval_profile, 'state.json evaluation_profile mismatch after starting the next workflow round from explicit handoff'
|
|
894
|
-
assert state['advisory_startup_brief']['mission'] == mission, 'next-round explicit
|
|
894
|
+
assert state['advisory_startup_brief']['mission'] == mission, 'next-round explicit handoff should preserve the confirmed startup brief as advisory intake'
|
|
895
895
|
assert state['advisory_startup_brief']['source'] == 'primary_agent_handoff', 'next-round explicit handoff should preserve the handoff advisory source'
|
|
896
896
|
assert plan['mission_anchor'] == mission, 'plan.json mission_anchor mismatch after starting the next workflow round from explicit handoff'
|
|
897
897
|
assert plan['task_type'] == expected_task_type, 'plan.json task_type mismatch after starting the next workflow round from explicit handoff'
|
|
@@ -960,7 +960,7 @@ tracked = [
|
|
|
960
960
|
]
|
|
961
961
|
|
|
962
962
|
assert not routing.exists(), 'active /cook inline-args rejection should not run active-workflow routing'
|
|
963
|
-
assert not proposal.exists(), 'active /cook inline-args rejection should not emit a replacement startup-
|
|
963
|
+
assert not proposal.exists(), 'active /cook inline-args rejection should not emit a replacement startup-brief proposal'
|
|
964
964
|
assert not chooser.exists(), 'active /cook inline-args rejection should not open the existing-workflow chooser'
|
|
965
965
|
assert '/cook no longer accepts inline arguments.' in output, 'active /cook inline-args rejection should explain the bare-only entry contract'
|
|
966
966
|
after = {path.name: path.read_text() for path in tracked}
|
|
@@ -1018,7 +1018,7 @@ state_before = json.loads(before['state.json'])
|
|
|
1018
1018
|
assert state_before['current_phase'] == 'done', 'done /cook inline-args rejection should start from a completed workflow'
|
|
1019
1019
|
assert state_before['project_done'] is True, 'done /cook inline-args rejection should start from project_done=true'
|
|
1020
1020
|
assert not routing.exists(), 'done /cook inline-args rejection should not run active-workflow routing while starting the next round'
|
|
1021
|
-
assert not proposal.exists(), 'done /cook inline-args rejection should not emit a next-round startup-
|
|
1021
|
+
assert not proposal.exists(), 'done /cook inline-args rejection should not emit a next-round startup-brief proposal'
|
|
1022
1022
|
assert not chooser.exists(), 'done /cook inline-args rejection should not open the existing-workflow chooser when starting the next round'
|
|
1023
1023
|
assert '/cook no longer accepts inline arguments.' in output, 'done /cook inline-args rejection should explain the bare-only entry contract'
|
|
1024
1024
|
after = {path.name: path.read_text() for path in tracked}
|
|
@@ -1026,7 +1026,7 @@ assert before == after, 'done /cook inline-args rejection should leave canonical
|
|
|
1026
1026
|
PY
|
|
1027
1027
|
|
|
1028
1028
|
# Completed workflow again: model-assisted discussion analysis alone should still fail closed
|
|
1029
|
-
# without a fresh explicit primary-agent
|
|
1029
|
+
# without a fresh explicit primary-agent handoff.
|
|
1030
1030
|
mark_done
|
|
1031
1031
|
|
|
1032
1032
|
SESSION_FIVE="$TMPDIR/session-five.jsonl"
|
|
@@ -1052,7 +1052,7 @@ capsule = {
|
|
|
1052
1052
|
"Add a regression test."
|
|
1053
1053
|
],
|
|
1054
1054
|
"risks": [],
|
|
1055
|
-
"notes": ["Generated by the primary-agent
|
|
1055
|
+
"notes": ["Generated by the primary-agent handoff step triggered from /cook."],
|
|
1056
1056
|
"handoff_kind": "implementation_workflow_handoff",
|
|
1057
1057
|
"first_slice_goal": "Land the regression-test-backed parser follow-up without rewriting the parser.",
|
|
1058
1058
|
"first_slice_non_goals": ["Do not broaden the mission with stale scope."],
|
|
@@ -1078,8 +1078,8 @@ state = json.loads(Path('.agent/state.json').read_text())
|
|
|
1078
1078
|
|
|
1079
1079
|
if snapshot.exists():
|
|
1080
1080
|
pass
|
|
1081
|
-
assert state['continuation_policy'] == 'continue', 'done-workflow analyst-backed primary-agent
|
|
1082
|
-
assert 'Started a new completion workflow round
|
|
1081
|
+
assert state['continuation_policy'] == 'continue', 'done-workflow analyst-backed primary-agent handoff should reopen the workflow'
|
|
1082
|
+
assert 'Started a new completion workflow round from explicit primary-agent handoff' in output, 'done-workflow analyst-backed startup should report explicit primary-agent handoff startup'
|
|
1083
1083
|
PY
|
|
1084
1084
|
|
|
1085
1085
|
# Custom confirmation UI: start should render proposal content separately from approval-only Start/Cancel actions.
|
|
@@ -1135,17 +1135,17 @@ from pathlib import Path
|
|
|
1135
1135
|
snapshot = json.loads(Path(sys.argv[1]).read_text())
|
|
1136
1136
|
state = json.loads(Path('.agent/state.json').read_text())
|
|
1137
1137
|
|
|
1138
|
-
assert snapshot['proposalHeading'] == 'Startup
|
|
1139
|
-
assert snapshot['critiqueHeading'] == 'Notes and risks', 'custom confirmation snapshot should expose notes separately from the startup-
|
|
1138
|
+
assert snapshot['proposalHeading'] == 'Startup brief', 'custom confirmation snapshot should expose a dedicated startup-brief section'
|
|
1139
|
+
assert snapshot['critiqueHeading'] == 'Notes and risks', 'custom confirmation snapshot should expose notes separately from the startup-brief body'
|
|
1140
1140
|
assert snapshot['routingHeading'] == 'Routing recommendations', 'custom confirmation snapshot should expose routing recommendations separately from the proposal body'
|
|
1141
1141
|
assert 'approval-only' in snapshot['intro'], 'custom confirmation intro should explain the approval-only gate'
|
|
1142
1142
|
assert state['task_type'] == 'completion-workflow', 'start action should preserve canonical task_type'
|
|
1143
1143
|
assert state['evaluation_profile'] == 'completion-rubric-v1', 'start action should preserve canonical evaluation_profile'
|
|
1144
1144
|
assert 'Mission\nReplace the crowded selector with a clearer action layout.' in snapshot['proposalBody'], 'proposal body should be captured separately from the action list'
|
|
1145
|
-
assert 'Keep critique details separate from the approval-only proposal summary.' not in snapshot['proposalBody'], 'critique notes should not be embedded in the startup-
|
|
1145
|
+
assert 'Keep critique details separate from the approval-only proposal summary.' not in snapshot['proposalBody'], 'critique notes should not be embedded in the startup-brief body'
|
|
1146
1146
|
assert 'Critique\n- Keep critique details separate from the approval-only proposal summary.' in snapshot['critiqueBody'], 'notes section should render accepted critique notes separately'
|
|
1147
1147
|
assert 'Risks\n- Bundling critique into the action list would make the confirmation harder to scan.' in snapshot['critiqueBody'], 'critique section should render risk notes separately'
|
|
1148
|
-
assert '- Possible noise: old selector wording' in snapshot['critiqueBody'], 'critique section should preserve additional operator notes separately from the startup-
|
|
1148
|
+
assert '- Possible noise: old selector wording' in snapshot['critiqueBody'], 'critique section should preserve additional operator notes separately from the startup-brief body'
|
|
1149
1149
|
assert '- task_type: completion-workflow' in snapshot['routingBody'], 'routing section should render the recommended task_type'
|
|
1150
1150
|
assert '- evaluation_profile: completion-rubric-v1' in snapshot['routingBody'], 'routing section should render the recommended evaluation_profile'
|
|
1151
1151
|
assert [action['id'] for action in snapshot['actions']] == ['start', 'cancel'], 'custom confirmation actions should stay Start/Cancel only'
|
|
@@ -1155,7 +1155,7 @@ for action in snapshot['actions']:
|
|
|
1155
1155
|
assert 'Replace the crowded selector with a clearer action layout.' not in action['label'], 'proposal mission should not be embedded in action labels'
|
|
1156
1156
|
assert 'Separate proposal text from actions.' not in action['description'], 'proposal scope should not be embedded in action descriptions'
|
|
1157
1157
|
assert state['mission_anchor'] == 'Replace the crowded selector with a clearer action layout.', 'start action should still accept the proposed mission'
|
|
1158
|
-
assert state['advisory_startup_brief']['mission'] == 'Replace the crowded selector with a clearer action layout.', 'start action should preserve the confirmed startup
|
|
1158
|
+
assert state['advisory_startup_brief']['mission'] == 'Replace the crowded selector with a clearer action layout.', 'start action should preserve the confirmed startup brief canonically'
|
|
1159
1159
|
assert state['continuation_reason'].startswith('User started workflow via /cook:'), 'start action should persist the startup routing outcome in continuation_reason'
|
|
1160
1160
|
assert 'Keep critique details separate from the approval-only proposal summary.' in state['continuation_reason'], 'start action should persist the accepted critique outcome canonically'
|
|
1161
1161
|
PY
|
|
@@ -1221,7 +1221,7 @@ assert 'Discuss changes in the main chat and rerun /cook.' in output, 'cancel co
|
|
|
1221
1221
|
assert not Path('.agent').exists(), 'cancel action should not write canonical workflow state'
|
|
1222
1222
|
PY
|
|
1223
1223
|
|
|
1224
|
-
# Explicit primary-agent
|
|
1224
|
+
# Explicit primary-agent handoff: /cook should prefer the structured handoff capsule over broad context re-inference.
|
|
1225
1225
|
HANDOFF_ROOT_START="$TMPDIR/handoff-root-start"
|
|
1226
1226
|
mkdir -p "$HANDOFF_ROOT_START"
|
|
1227
1227
|
cd "$HANDOFF_ROOT_START"
|
|
@@ -1251,7 +1251,7 @@ capsule = {
|
|
|
1251
1251
|
"Stale auth discussion could broaden the startup brief if the handoff is ignored."
|
|
1252
1252
|
],
|
|
1253
1253
|
"notes": [
|
|
1254
|
-
"Keep the startup
|
|
1254
|
+
"Keep the startup brief aligned with the explicit primary-agent plan."
|
|
1255
1255
|
],
|
|
1256
1256
|
"handoff_kind": "implementation_workflow_handoff",
|
|
1257
1257
|
"first_slice_goal": "Land the redirect callback fix and its regression coverage.",
|
|
@@ -1272,7 +1272,7 @@ capsule = {
|
|
|
1272
1272
|
}
|
|
1273
1273
|
messages = [
|
|
1274
1274
|
{"role": "user", "content": "Please think through the login redirect fix and tell me when it is ready for /cook."},
|
|
1275
|
-
{"role": "assistant", "content": "This task is now ready for /cook. Run /cook to confirm the startup
|
|
1275
|
+
{"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```"},
|
|
1276
1276
|
]
|
|
1277
1277
|
print(json.dumps(messages, ensure_ascii=False))
|
|
1278
1278
|
PY
|
|
@@ -1296,7 +1296,7 @@ assert snapshot['source'] == 'handoff_capsule', 'explicit handoff startup should
|
|
|
1296
1296
|
assert snapshot['mission'] == 'Fix login redirect callback behavior.', 'explicit handoff startup should preserve the primary-agent mission'
|
|
1297
1297
|
assert state['mission_anchor'] == 'Fix login redirect callback behavior.', 'explicit handoff startup should use the handoff mission as canonical mission_anchor'
|
|
1298
1298
|
assert state['advisory_startup_brief']['source'] == 'primary_agent_handoff', 'explicit handoff startup should preserve the advisory intake source'
|
|
1299
|
-
assert state['advisory_startup_brief']['risks'] == ['Stale auth discussion could broaden the startup brief if the handoff is ignored.'], 'explicit startup
|
|
1299
|
+
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'
|
|
1300
1300
|
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'
|
|
1301
1301
|
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'
|
|
1302
1302
|
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'
|
|
@@ -1306,7 +1306,7 @@ assert 'Primary-agent /cook handoff rationale: The implementation plan is concre
|
|
|
1306
1306
|
PY
|
|
1307
1307
|
|
|
1308
1308
|
# Fresh but non-startable explicit handoff: /cook should fail closed instead of falling back
|
|
1309
|
-
# to a broad recent-discussion startup
|
|
1309
|
+
# to a broad recent-discussion startup brief when the explicit capsule is still too vague.
|
|
1310
1310
|
HANDOFF_ROOT_VAGUE="$TMPDIR/handoff-root-vague"
|
|
1311
1311
|
mkdir -p "$HANDOFF_ROOT_VAGUE"
|
|
1312
1312
|
cd "$HANDOFF_ROOT_VAGUE"
|
|
@@ -1373,12 +1373,13 @@ output = Path(sys.argv[2]).read_text() + Path(sys.argv[3]).read_text()
|
|
|
1373
1373
|
|
|
1374
1374
|
assert not snapshot.exists(), 'fresh non-startable handoff should not emit a startup proposal snapshot'
|
|
1375
1375
|
assert not Path('.agent').exists(), 'fresh non-startable handoff should fail closed without writing canonical state'
|
|
1376
|
-
assert 'fresh explicit primary-agent
|
|
1376
|
+
assert 'fresh explicit primary-agent handoff exists' in output, 'fresh non-startable handoff should explain that the explicit capsule blocked startup'
|
|
1377
1377
|
assert 'acceptance is not anchored to concrete repo changes or verification' in output, 'fresh non-startable handoff should explain the workflow-only acceptance failure'
|
|
1378
|
-
assert '
|
|
1378
|
+
assert 'implementation_surfaces is empty' in output, 'fresh non-startable handoff should explain the missing implementation_surfaces requirement'
|
|
1379
|
+
assert 'verification_commands is empty' in output, 'fresh non-startable handoff should explain the missing verification_commands requirement'
|
|
1379
1380
|
PY
|
|
1380
1381
|
|
|
1381
|
-
# Fresh explicit
|
|
1382
|
+
# Fresh explicit handoff with complete first-slice fields but vague acceptance: /cook should still fail closed
|
|
1382
1383
|
# with the dedicated explicit-handoff message instead of bootstrapping canonical state.
|
|
1383
1384
|
HANDOFF_ROOT_VAGUE_ACCEPTANCE="$TMPDIR/handoff-root-vague-acceptance"
|
|
1384
1385
|
mkdir -p "$HANDOFF_ROOT_VAGUE_ACCEPTANCE"
|
|
@@ -1450,13 +1451,13 @@ from pathlib import Path
|
|
|
1450
1451
|
snapshot = Path(sys.argv[1])
|
|
1451
1452
|
output = Path(sys.argv[2]).read_text() + Path(sys.argv[3]).read_text()
|
|
1452
1453
|
|
|
1453
|
-
assert not snapshot.exists(), 'fresh explicit
|
|
1454
|
-
assert not Path('.agent').exists(), 'fresh explicit
|
|
1455
|
-
assert 'fresh explicit primary-agent
|
|
1456
|
-
assert 'acceptance is not anchored to concrete repo changes or verification' in output, 'fresh explicit
|
|
1454
|
+
assert not snapshot.exists(), 'fresh explicit handoff with vague acceptance should not emit a startup proposal snapshot'
|
|
1455
|
+
assert not Path('.agent').exists(), 'fresh explicit handoff with vague acceptance should fail closed without writing canonical state'
|
|
1456
|
+
assert 'fresh explicit primary-agent handoff exists' in output, 'fresh explicit handoff with vague acceptance should use the dedicated explicit-handoff fail-closed message'
|
|
1457
|
+
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'
|
|
1457
1458
|
PY
|
|
1458
1459
|
|
|
1459
|
-
# Done workflow + fresh
|
|
1460
|
+
# Done workflow + fresh handoff: the fresh explicit handoff should override done-state suppression and start the new round.
|
|
1460
1461
|
HANDOFF_ROOT_DONE="$TMPDIR/handoff-root-done"
|
|
1461
1462
|
mkdir -p "$HANDOFF_ROOT_DONE"
|
|
1462
1463
|
cd "$HANDOFF_ROOT_DONE"
|
|
@@ -1625,7 +1626,7 @@ output = Path(sys.argv[2]).read_text() + Path(sys.argv[3]).read_text()
|
|
|
1625
1626
|
|
|
1626
1627
|
assert not snapshot.exists(), 'stale handoff should not emit a startup proposal snapshot'
|
|
1627
1628
|
assert not Path('.agent').exists(), 'stale handoff should fail closed without writing canonical state'
|
|
1628
|
-
assert '
|
|
1629
|
+
assert 'primary-agent handoff step could not prepare a concrete startup handoff' in output, 'stale handoff should fail closed when the synthesized handoff step produces nothing'
|
|
1629
1630
|
PY
|
|
1630
1631
|
|
|
1631
1632
|
# Negative handoff rationale: a non-startable capsule must not become the startup mission.
|
package/scripts/refocus-test.sh
CHANGED
|
@@ -114,10 +114,10 @@ capsule = {
|
|
|
114
114
|
],
|
|
115
115
|
"risks": [],
|
|
116
116
|
"notes": [
|
|
117
|
-
"Use
|
|
117
|
+
"Use explicit primary-agent handoff startup for the refocus regression fixture."
|
|
118
118
|
],
|
|
119
119
|
"handoff_kind": "implementation_workflow_handoff",
|
|
120
|
-
"first_slice_goal": "Bootstrap the refocus regression fixture from a fresh explicit
|
|
120
|
+
"first_slice_goal": "Bootstrap the refocus regression fixture from a fresh explicit handoff.",
|
|
121
121
|
"first_slice_non_goals": [],
|
|
122
122
|
"implementation_surfaces": [
|
|
123
123
|
"scripts/refocus-test.sh"
|
|
@@ -128,7 +128,7 @@ capsule = {
|
|
|
128
128
|
"why_this_slice_first": "The refocus regression fixture needs canonical state before active-workflow routing can be exercised.",
|
|
129
129
|
"task_type": "completion-workflow",
|
|
130
130
|
"evaluation_profile": "completion-rubric-v1",
|
|
131
|
-
"why_cook_now": "The active-workflow refocus regression needs a fresh explicit startup
|
|
131
|
+
"why_cook_now": "The active-workflow refocus regression needs a fresh explicit startup boundary."
|
|
132
132
|
}
|
|
133
133
|
messages = [
|
|
134
134
|
{"role": "user", "content": "Prepare the refocus regression fixture and tell me when it is ready for /cook."},
|
|
@@ -215,7 +215,7 @@ tracked = [
|
|
|
215
215
|
current_state = json.loads(before['state.json'])
|
|
216
216
|
assert current_state['mission_anchor'] == initial_mission, 'active /cook inline-args rejection should start from the current mission anchor'
|
|
217
217
|
assert not routing.exists(), 'active /cook inline-args rejection should not run active-workflow routing'
|
|
218
|
-
assert not proposal.exists(), 'active /cook inline-args rejection should not open final startup-
|
|
218
|
+
assert not proposal.exists(), 'active /cook inline-args rejection should not open final startup-brief confirmation'
|
|
219
219
|
assert not chooser.exists(), 'active /cook inline-args rejection should not open the existing-workflow chooser'
|
|
220
220
|
assert '/cook no longer accepts inline arguments.' in output, 'active /cook inline-args rejection should explain the bare-only entry contract'
|
|
221
221
|
after = {path.name: path.read_text() for path in tracked}
|
|
@@ -243,7 +243,7 @@ capsule = {
|
|
|
243
243
|
],
|
|
244
244
|
"risks": [],
|
|
245
245
|
"notes": [
|
|
246
|
-
"Use a fresh explicit primary-agent
|
|
246
|
+
"Use a fresh explicit primary-agent handoff for the active-workflow replacement."
|
|
247
247
|
],
|
|
248
248
|
"handoff_kind": "implementation_workflow_handoff",
|
|
249
249
|
"first_slice_goal": "Replace the initial smoke-test workflow with the widget mission.",
|
|
@@ -254,14 +254,14 @@ capsule = {
|
|
|
254
254
|
"verification_commands": [
|
|
255
255
|
"npm run refocus-test"
|
|
256
256
|
],
|
|
257
|
-
"why_this_slice_first": "The fresh explicit
|
|
257
|
+
"why_this_slice_first": "The fresh explicit handoff is the only supported replacement entry while a workflow is active.",
|
|
258
258
|
"task_type": "completion-workflow",
|
|
259
259
|
"evaluation_profile": "completion-rubric-v1",
|
|
260
260
|
"why_cook_now": "A different active workflow is ready and explicitly handed off by the primary agent."
|
|
261
261
|
}
|
|
262
262
|
messages = [
|
|
263
263
|
{"role": "user", "content": "The smoke-test workflow is active, but a different replacement workflow may now be ready."},
|
|
264
|
-
{"role": "assistant", "content": "Use this fresh explicit
|
|
264
|
+
{"role": "assistant", "content": "Use this fresh explicit handoff if you want /cook to replace the active workflow.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
265
265
|
]
|
|
266
266
|
print(json.dumps(messages, ensure_ascii=False))
|
|
267
267
|
PY
|
|
@@ -296,7 +296,7 @@ assert profile['evaluation_profile'] == expected_eval_profile, 'profile.json eva
|
|
|
296
296
|
assert state['mission_anchor'] == new_anchor, 'state.json mission_anchor mismatch after refocus'
|
|
297
297
|
assert state['task_type'] == expected_task_type, 'state.json task_type mismatch after refocus'
|
|
298
298
|
assert state['evaluation_profile'] == expected_eval_profile, 'state.json evaluation_profile mismatch after refocus'
|
|
299
|
-
assert state['advisory_startup_brief']['mission'] == new_anchor, 'refocus should preserve the confirmed startup
|
|
299
|
+
assert state['advisory_startup_brief']['mission'] == new_anchor, 'refocus should preserve the confirmed startup brief as advisory intake'
|
|
300
300
|
assert plan['mission_anchor'] == new_anchor, 'plan.json mission_anchor mismatch after refocus'
|
|
301
301
|
assert plan['task_type'] == expected_task_type, 'plan.json task_type mismatch after refocus'
|
|
302
302
|
assert plan['evaluation_profile'] == expected_eval_profile, 'plan.json evaluation_profile mismatch after refocus'
|
|
@@ -312,7 +312,7 @@ assert active['status'] == 'idle', 'active-slice.json status should reset to idl
|
|
|
312
312
|
assert routing['mode'] == 'bare', 'supported refocus should use bare active-workflow routing mode'
|
|
313
313
|
assert 'explicitGoal' not in routing, 'supported bare refocus should not expose removed explicit-goal shim fields'
|
|
314
314
|
assert 'explicitGoalProvided' not in routing, 'supported bare refocus should not expose removed explicit-goal shim fields'
|
|
315
|
-
assert routing['action'] == 'refocus', 'supported bare /cook should classify as refocus when a fresh explicit
|
|
315
|
+
assert routing['action'] == 'refocus', 'supported bare /cook should classify as refocus when a fresh explicit handoff proposes a different mission'
|
|
316
316
|
assert routing['reason'] == 'fresh_explicit_handoff', 'supported bare /cook should record the explicit-handoff replacement reason'
|
|
317
317
|
assert routing['proposedMissionAnchor'] == new_anchor, 'explicit handoff routing snapshot should expose the replacement mission anchor'
|
|
318
318
|
assert routing['proposalSource'] == 'handoff_capsule', 'explicit handoff routing snapshot should preserve the handoff source'
|
|
@@ -331,7 +331,7 @@ if [[ "$INITIAL_MISSION" == "$UPDATED_MISSION" ]]; then
|
|
|
331
331
|
exit 1
|
|
332
332
|
fi
|
|
333
333
|
|
|
334
|
-
# Fresh explicit
|
|
334
|
+
# Fresh explicit handoff replacements must still reach the chooser and final Start/Cancel gate while the
|
|
335
335
|
# workflow is active.
|
|
336
336
|
BARE_REFOCUS_MISSION='Exercise explicit active-workflow replacement coverage.'
|
|
337
337
|
BARE_REFOCUS_MESSAGES="$(python3 - <<'PY'
|
|
@@ -354,7 +354,7 @@ capsule = {
|
|
|
354
354
|
],
|
|
355
355
|
"risks": [],
|
|
356
356
|
"notes": [
|
|
357
|
-
"This replacement should come only from the fresh explicit
|
|
357
|
+
"This replacement should come only from the fresh explicit handoff, not recent discussion inference."
|
|
358
358
|
],
|
|
359
359
|
"handoff_kind": "implementation_workflow_handoff",
|
|
360
360
|
"first_slice_goal": "Exercise the active-workflow explicit-handoff replacement path.",
|
|
@@ -365,14 +365,14 @@ capsule = {
|
|
|
365
365
|
"verification_commands": [
|
|
366
366
|
"npm run refocus-test"
|
|
367
367
|
],
|
|
368
|
-
"why_this_slice_first": "The active workflow should only replace from a fresh explicit
|
|
368
|
+
"why_this_slice_first": "The active workflow should only replace from a fresh explicit handoff.",
|
|
369
369
|
"task_type": "completion-workflow",
|
|
370
370
|
"evaluation_profile": "completion-rubric-v1",
|
|
371
371
|
"why_cook_now": "The primary agent explicitly handed off a replacement workflow while the current one is active."
|
|
372
372
|
}
|
|
373
373
|
messages = [
|
|
374
374
|
{"role": "user", "content": "The current workflow is active, but there is a fresh explicit replacement handoff ready."},
|
|
375
|
-
{"role": "assistant", "content": "Use this fresh explicit
|
|
375
|
+
{"role": "assistant", "content": "Use this fresh explicit handoff if you want /cook to replace the active workflow.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
376
376
|
]
|
|
377
377
|
print(json.dumps(messages, ensure_ascii=False))
|
|
378
378
|
PY
|
|
@@ -417,7 +417,7 @@ assert routing['proposedMissionAnchor'] == replacement_mission, 'explicit-handof
|
|
|
417
417
|
assert routing['proposalSource'] == 'handoff_capsule', 'explicit-handoff routing should preserve the handoff source'
|
|
418
418
|
assert chooser['title'].startswith('Existing completion workflow found'), 'bare chooser snapshot should describe the existing-workflow prompt'
|
|
419
419
|
assert chooser['choices'][0].startswith('Continue current workflow'), 'bare chooser should keep the continue option'
|
|
420
|
-
assert chooser['choices'][1].startswith('Start new workflow from explicit primary-agent
|
|
420
|
+
assert chooser['choices'][1].startswith('Start new workflow from explicit primary-agent handoff'), 'bare chooser should offer the explicit-handoff replacement option'
|
|
421
421
|
assert 'Start/Cancel confirmation' in chooser['choices'][1], 'bare chooser should mention the approval-only replacement confirmation'
|
|
422
422
|
assert chooser['choices'][2].startswith('Cancel'), 'bare chooser should keep the cancel option'
|
|
423
423
|
assert 'Discuss changes in the main chat and rerun /cook.' in output, 'bare chooser cancel should redirect users back to the main chat and rerun /cook'
|
|
@@ -504,7 +504,7 @@ assert profile['evaluation_profile'] == expected_eval_profile, 'profile.json eva
|
|
|
504
504
|
assert state['mission_anchor'] == new_anchor, 'state.json mission_anchor mismatch after bare refocus'
|
|
505
505
|
assert state['task_type'] == expected_task_type, 'state.json task_type mismatch after bare refocus'
|
|
506
506
|
assert state['evaluation_profile'] == expected_eval_profile, 'state.json evaluation_profile mismatch after bare refocus'
|
|
507
|
-
assert state['advisory_startup_brief']['mission'] == new_anchor, 'bare refocus should preserve the confirmed startup
|
|
507
|
+
assert state['advisory_startup_brief']['mission'] == new_anchor, 'bare refocus should preserve the confirmed startup brief as advisory intake'
|
|
508
508
|
assert plan['mission_anchor'] == new_anchor, 'plan.json mission_anchor mismatch after bare refocus'
|
|
509
509
|
assert plan['task_type'] == expected_task_type, 'plan.json task_type mismatch after bare refocus'
|
|
510
510
|
assert plan['evaluation_profile'] == expected_eval_profile, 'plan.json evaluation_profile mismatch after bare refocus'
|
|
@@ -540,7 +540,7 @@ capsule = {
|
|
|
540
540
|
"Do not rewrite canonical state before the final Start confirmation."
|
|
541
541
|
],
|
|
542
542
|
"acceptance": [
|
|
543
|
-
"Replace the active workflow using the synthesized primary-agent
|
|
543
|
+
"Replace the active workflow using the synthesized primary-agent handoff.",
|
|
544
544
|
"Keep deterministic coverage for same-entry active replacement."
|
|
545
545
|
],
|
|
546
546
|
"risks": [],
|
|
@@ -556,7 +556,7 @@ capsule = {
|
|
|
556
556
|
"verification_commands": [
|
|
557
557
|
"npm run refocus-test"
|
|
558
558
|
],
|
|
559
|
-
"why_this_slice_first": "Active replacement should work when the primary-agent
|
|
559
|
+
"why_this_slice_first": "Active replacement should work when the primary-agent handoff is synthesized in the same /cook entry.",
|
|
560
560
|
"task_type": "completion-workflow",
|
|
561
561
|
"evaluation_profile": "completion-rubric-v1",
|
|
562
562
|
"why_cook_now": "The user explicitly chose workflow mode and the replacement handoff can be synthesized immediately."
|
package/scripts/release-check.sh
CHANGED
|
@@ -5,37 +5,38 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
5
5
|
cd "$ROOT"
|
|
6
6
|
export PI_COMPLETION_RUNNING_RELEASE_CHECK=1
|
|
7
7
|
|
|
8
|
-
echo "[release-check] running control-plane validation, tracked .agent contract coverage, slice-surface parity,
|
|
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"
|
|
9
9
|
bash .agent/verify_completion_control_plane.sh
|
|
10
10
|
git ls-files --error-unmatch .agent/README.md .agent/mission.md .agent/profile.json .agent/verify_completion_stop.sh .agent/verify_completion_control_plane.sh >/dev/null
|
|
11
11
|
|
|
12
|
-
echo "[release-check] verifying public /cook parity and
|
|
12
|
+
echo "[release-check] verifying public /cook parity and primary-agent-handoff docs/help"
|
|
13
13
|
python3 - <<'PY'
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
16
|
checks = {
|
|
17
17
|
"README.md": [
|
|
18
18
|
"You can still implement directly in ordinary chat when you do not need workflow state.",
|
|
19
|
-
"When you explicitly run `/cook`, it first checks for a fresh explicit primary-agent
|
|
20
|
-
"
|
|
21
|
-
"Explicit `/cook` capsules are still valid startup intake, but they are no longer the only path because `/cook` can synthesize the primary-agent
|
|
19
|
+
"When you explicitly run `/cook`, it first checks for a fresh explicit primary-agent handoff.",
|
|
20
|
+
"If one is missing, it calls a same-entry primary-agent handoff synthesis step from the current task context, then asks you to **Start** or **Cancel** before rewriting canonical workflow state.",
|
|
21
|
+
"Explicit `/cook` capsules are still valid startup intake, but they are no longer the only path because `/cook` can synthesize the primary-agent handoff in the same entry when needed.",
|
|
22
22
|
],
|
|
23
23
|
"CHANGELOG.md": [
|
|
24
|
-
"
|
|
25
|
-
"
|
|
24
|
+
"preserved the confirmed `/cook` startup intent in canonical `.agent/startup-brief.json` so workflow entry is durable before regrounding authors canonical slices",
|
|
25
|
+
"moved workflow-session legitimacy away from in-memory routing activation and legacy `/skill:completion-protocol` prompt dependence toward canonical workflow-session state plus explicit `/cook` entry turns",
|
|
26
26
|
],
|
|
27
27
|
"extensions/completion/prompt-surfaces.ts": [
|
|
28
|
-
'"If the user explicitly runs /cook, the extension should call a primary-agent
|
|
29
|
-
'"
|
|
28
|
+
'"If the user explicitly runs /cook, the extension should call a primary-agent handoff synthesis step from the current task context, show Start/Cancel confirmation, and persist the confirmed startup brief into .agent/** without making the user rerun /cook."',
|
|
29
|
+
'"Do not expect /cook to infer or guess startup intent from recent discussion alone; /cook should use explicit primary-agent handoff data, whether it already exists or is synthesized in the same /cook entry."',
|
|
30
30
|
'"In ordinary chat, do not load or follow completion-protocol, and do not call completion_role."',
|
|
31
31
|
],
|
|
32
32
|
"extensions/completion/index.ts": [
|
|
33
|
-
'"/cook failed closed because the
|
|
34
|
-
'description: "/cook workflow:
|
|
35
|
-
'"Do not call completion_role from ordinary chat; it is reserved for
|
|
33
|
+
'"/cook failed closed because the primary-agent handoff step could not prepare a concrete startup handoff from the current task context. Clarify the mission, first slice, or verification intent in the main chat, then rerun /cook."',
|
|
34
|
+
'description: "/cook workflow: start or replace workflow only from an explicit primary-agent handoff, or resume the current workflow from canonical state"',
|
|
35
|
+
'"Do not call completion_role from ordinary chat; it is reserved for active /cook workflow sessions."',
|
|
36
|
+
'`COMPLETION WORKFLOW DRIVER\\nStart or continue the completion workflow for this repo.',
|
|
36
37
|
],
|
|
37
38
|
"extensions/completion/policy-guards.ts": [
|
|
38
|
-
'return "completion_role may only be used from an
|
|
39
|
+
'return "completion_role may only be used from an active /cook workflow session.";',
|
|
39
40
|
],
|
|
40
41
|
"skills/cook-handoff-boundary/SKILL.md": [
|
|
41
42
|
'- load or follow `completion-protocol` while still in ordinary chat',
|