@linimin/pi-letscook 0.1.60 → 0.1.61
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 +5 -8
- package/README.md +28 -32
- package/extensions/completion/driver.ts +41 -28
- package/extensions/completion/index.ts +76 -63
- package/extensions/completion/prompt-surfaces.ts +15 -13
- package/extensions/completion/proposal.ts +28 -1
- package/package.json +1 -1
- package/scripts/context-proposal-test.sh +49 -154
- package/scripts/refocus-test.sh +4 -4
- package/scripts/release-check.sh +24 -31
- package/scripts/smoke-test.sh +64 -24
- package/skills/cook-handoff-boundary/SKILL.md +54 -26
package/scripts/smoke-test.sh
CHANGED
|
@@ -103,8 +103,55 @@ INLINE_REJECTION_ROUTING_SNAPSHOT="$TMPDIR/inline-arg-routing.json"
|
|
|
103
103
|
INLINE_REJECTION_PROPOSAL_SNAPSHOT="$TMPDIR/inline-arg-proposal.json"
|
|
104
104
|
INLINE_REJECTION_CHOOSER_SNAPSHOT="$TMPDIR/inline-arg-chooser.json"
|
|
105
105
|
BOOTSTRAP_SESSION="$TMPDIR/session-smoke-bootstrap.jsonl"
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
BOOTSTRAP_MESSAGES="$(python3 - <<'PY'
|
|
107
|
+
import json
|
|
108
|
+
capsule = {
|
|
109
|
+
"kind": "cook_handoff",
|
|
110
|
+
"source": "primary_agent",
|
|
111
|
+
"captured_at": "2026-01-01T00:00:02.000Z",
|
|
112
|
+
"source_turn_id": "m0002",
|
|
113
|
+
"mission": "Exercise smoke-test bootstrap.",
|
|
114
|
+
"scope": [
|
|
115
|
+
"Materialize the canonical completion control-plane files.",
|
|
116
|
+
"Keep the smoke test on supported /cook startup behavior."
|
|
117
|
+
],
|
|
118
|
+
"constraints": [
|
|
119
|
+
"Keep startup proposal confirmation approval-only."
|
|
120
|
+
],
|
|
121
|
+
"acceptance": [
|
|
122
|
+
"Scaffold .agent/profile.json, .agent/state.json, .agent/plan.json, .agent/active-slice.json, and .agent/verification-evidence.json for the smoke fixture.",
|
|
123
|
+
"Keep scripts/smoke-test.sh and kickoff-prompt coverage truthful for packaged bootstrap."
|
|
124
|
+
],
|
|
125
|
+
"risks": [
|
|
126
|
+
"Smoke-test bootstrap should stay anchored to the fresh explicit handoff."
|
|
127
|
+
],
|
|
128
|
+
"notes": [
|
|
129
|
+
"Keep the smoke fixture aligned with the shipped explicit-handoff-only startup contract."
|
|
130
|
+
],
|
|
131
|
+
"handoff_kind": "implementation_workflow_handoff",
|
|
132
|
+
"first_slice_goal": "Scaffold canonical completion files and verify the packaged startup contract.",
|
|
133
|
+
"first_slice_non_goals": [
|
|
134
|
+
"Do not broaden the smoke fixture beyond the packaged startup surfaces."
|
|
135
|
+
],
|
|
136
|
+
"implementation_surfaces": [
|
|
137
|
+
".agent/README.md",
|
|
138
|
+
"scripts/smoke-test.sh"
|
|
139
|
+
],
|
|
140
|
+
"verification_commands": [
|
|
141
|
+
"npm run smoke-test"
|
|
142
|
+
],
|
|
143
|
+
"why_this_slice_first": "The packaged explicit-handoff startup path must work before later workflow verification can run.",
|
|
144
|
+
"task_type": "completion-workflow",
|
|
145
|
+
"evaluation_profile": "completion-rubric-v1",
|
|
146
|
+
"why_cook_now": "The startup handoff is concrete enough to bootstrap canonical workflow files."
|
|
147
|
+
}
|
|
148
|
+
messages = [
|
|
149
|
+
{"role": "user", "content": "Please prepare the packaged smoke-test bootstrap path and tell me when it is ready for /cook."},
|
|
150
|
+
{"role": "assistant", "content": "This bootstrap path is ready for /cook. Run /cook to confirm the startup brief.\n\n```cook_handoff\n" + json.dumps(capsule, ensure_ascii=False, indent=2) + "\n```"},
|
|
151
|
+
]
|
|
152
|
+
print(json.dumps(messages, ensure_ascii=False))
|
|
153
|
+
PY
|
|
154
|
+
)"
|
|
108
155
|
|
|
109
156
|
mkdir -p "$ROOT"
|
|
110
157
|
cd "$ROOT"
|
|
@@ -133,12 +180,11 @@ assert not chooser.exists(), 'startup /cook inline-args rejection should not ope
|
|
|
133
180
|
assert '/cook no longer accepts inline arguments.' in output, 'startup /cook inline-args rejection should explain the bare-only entry contract'
|
|
134
181
|
PY
|
|
135
182
|
|
|
136
|
-
|
|
183
|
+
write_session_messages "$BOOTSTRAP_SESSION" "$ROOT" "$BOOTSTRAP_MESSAGES"
|
|
137
184
|
|
|
138
185
|
PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=accept \
|
|
139
186
|
PI_COMPLETION_DISABLE_CONTEXT_PROPOSAL_ANALYST=1 \
|
|
140
187
|
PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
141
|
-
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$BOOTSTRAP_PROPOSAL" \
|
|
142
188
|
PI_COMPLETION_TEST_DRIVER_PROMPT_PATH="$KICKOFF_PROMPT" \
|
|
143
189
|
pi --session "$BOOTSTRAP_SESSION" -e "$PKG_ROOT" -p "/cook" \
|
|
144
190
|
>"$TMPDIR/pi-completion-smoke-bootstrap.out" 2>"$TMPDIR/pi-completion-smoke-bootstrap.err"
|
|
@@ -151,7 +197,7 @@ git ls-files --error-unmatch .agent/README.md .agent/mission.md .agent/profile.j
|
|
|
151
197
|
bash .agent/verify_completion_control_plane.sh >/dev/null
|
|
152
198
|
bash .agent/verify_completion_stop.sh >/dev/null
|
|
153
199
|
|
|
154
|
-
python3 - "$KICKOFF_PROMPT"
|
|
200
|
+
python3 - "$KICKOFF_PROMPT" <<'PY'
|
|
155
201
|
import json
|
|
156
202
|
import sys
|
|
157
203
|
from pathlib import Path
|
|
@@ -165,7 +211,6 @@ plan = json.loads(Path('.agent/plan.json').read_text())
|
|
|
165
211
|
active = json.loads(Path('.agent/active-slice.json').read_text())
|
|
166
212
|
evidence = json.loads(Path('.agent/verification-evidence.json').read_text())
|
|
167
213
|
kickoff = Path(sys.argv[1]).read_text()
|
|
168
|
-
proposal = json.loads(Path(sys.argv[2]).read_text())
|
|
169
214
|
|
|
170
215
|
assert profile['task_type'] == expected_task_type, 'profile.json task_type mismatch after bootstrap'
|
|
171
216
|
assert profile['evaluation_profile'] == expected_eval_profile, 'profile.json evaluation_profile mismatch after bootstrap'
|
|
@@ -179,7 +224,7 @@ assert active['implementation_surfaces'] == [], 'active-slice.json should scaffo
|
|
|
179
224
|
assert active['verification_commands'] == [], 'active-slice.json should scaffold empty verification_commands'
|
|
180
225
|
brief = state['advisory_startup_brief']
|
|
181
226
|
assert brief['kind'] == 'startup_brief', 'state.json should preserve the confirmed startup brief as advisory intake'
|
|
182
|
-
assert brief['source'] == '
|
|
227
|
+
assert brief['source'] == 'primary_agent_handoff', 'smoke bootstrap should record the explicit handoff source in advisory intake'
|
|
183
228
|
assert brief['mission'] == state['mission_anchor'], 'advisory startup brief mission should match the canonical mission anchor after bootstrap'
|
|
184
229
|
assert brief['scope'] == ['Materialize the canonical completion control-plane files.', 'Keep the smoke test on supported /cook startup behavior.'], 'advisory startup brief should preserve scope items'
|
|
185
230
|
assert brief['constraints'] == ['Keep startup proposal confirmation approval-only.'], 'advisory startup brief should preserve constraints'
|
|
@@ -187,10 +232,9 @@ assert brief['acceptance'] == [
|
|
|
187
232
|
'Scaffold .agent/profile.json, .agent/state.json, .agent/plan.json, .agent/active-slice.json, and .agent/verification-evidence.json for the smoke fixture.',
|
|
188
233
|
'Keep scripts/smoke-test.sh and kickoff-prompt coverage truthful for packaged bootstrap.'
|
|
189
234
|
], 'advisory startup brief should preserve acceptance'
|
|
190
|
-
assert brief['risks'] == [], '
|
|
191
|
-
assert
|
|
192
|
-
assert
|
|
193
|
-
assert proposal['source'] == 'session', 'recent-discussion smoke bootstrap should snapshot the structured-session proposal source'
|
|
235
|
+
assert brief['risks'] == ['Smoke-test bootstrap should stay anchored to the fresh explicit handoff.'], 'advisory startup brief should preserve handoff risks'
|
|
236
|
+
assert 'First slice goal: Scaffold canonical completion files and verify the packaged startup contract.' in brief['notes'], 'advisory startup brief should preserve the first_slice_goal in notes'
|
|
237
|
+
assert 'Verification commands: npm run smoke-test' in brief['notes'], 'advisory startup brief should preserve verification_commands in notes'
|
|
194
238
|
assert evidence['artifact_type'] == 'completion-verification-evidence', 'verification-evidence.json artifact_type mismatch after bootstrap'
|
|
195
239
|
assert evidence['subject_type'] == 'none', 'verification-evidence.json should scaffold idle subject_type'
|
|
196
240
|
assert evidence['verification_commands'] == [], 'verification-evidence.json should scaffold empty verification_commands'
|
|
@@ -222,17 +266,13 @@ assert not reminder.exists(), 'ordinary non-/cook turn should not inject complet
|
|
|
222
266
|
assert handoff.exists(), 'ordinary non-/cook turn should inject the /cook handoff boundary reminder'
|
|
223
267
|
handoff_text = handoff.read_text()
|
|
224
268
|
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'
|
|
225
|
-
assert '
|
|
226
|
-
assert '
|
|
227
|
-
assert '
|
|
228
|
-
assert 'do not
|
|
229
|
-
assert '
|
|
230
|
-
assert '
|
|
231
|
-
assert '
|
|
232
|
-
assert 'first_slice_goal, first_slice_non_goals, implementation_surfaces, verification_commands, why_this_slice_first' in handoff_text, 'ordinary handoff reminder should preserve first-slice preview fields when explicitly requested'
|
|
233
|
-
assert 'Any preview capsule is startup intake for /cook only' in handoff_text, 'ordinary handoff reminder should keep any preview non-canonical'
|
|
234
|
-
assert 'resume from canonical .agent state' in handoff_text, 'ordinary handoff reminder should preserve active-workflow canonical resume wording'
|
|
235
|
-
assert 'fresh valid explicit primary-agent handoff capsule from recent ordinary-chat discussion' not in handoff_text, 'ordinary handoff reminder should no longer describe explicit capsules as the default startup path'
|
|
269
|
+
assert 'Do not proactively tell the user to run /cook' in handoff_text, 'ordinary handoff reminder should keep ordinary chat neutral until explicit /cook entry'
|
|
270
|
+
assert 'do not emit a ```cook_handoff``` capsule by default in ordinary chat' in handoff_text, 'ordinary handoff reminder should stop proactive capsule emission'
|
|
271
|
+
assert 'ordinary chat remains ordinary chat until the user explicitly runs /cook' in handoff_text, 'ordinary handoff reminder should preserve the explicit /cook boundary'
|
|
272
|
+
assert 'do not begin long-running product implementation in ordinary chat' in handoff_text, 'ordinary handoff reminder should still block workflow-level implementation before /cook'
|
|
273
|
+
assert 'Only provide a preview startup brief or ```cook_handoff``` capsule in ordinary chat when the user explicitly asks for that preview behavior.' in handoff_text, 'ordinary handoff reminder should restrict preview capsules to explicit preview requests'
|
|
274
|
+
assert 'startup brief from recent discussion using primary-agent-style context' in handoff_text, 'ordinary handoff reminder should describe deferred startup synthesis'
|
|
275
|
+
assert 'Start/Cancel confirmation before canonical workflow state is rewritten' in handoff_text, 'ordinary handoff reminder should preserve confirm-first startup'
|
|
236
276
|
assert not auto_resume.exists(), 'ordinary non-/cook turn should not queue auto-resume before /cook activation'
|
|
237
277
|
assert 'Skipped completion workflow auto-resume prompt (test mode)' not in output, 'ordinary non-/cook turn should not attempt auto-resume'
|
|
238
278
|
PY
|
|
@@ -260,8 +300,8 @@ assert 'Canonical routing profile:' in resume, 'resume prompt should expose cano
|
|
|
260
300
|
assert f'- task_type: {expected_task_type}' in resume, 'resume prompt missing canonical task_type'
|
|
261
301
|
assert f'- evaluation_profile: {expected_eval_profile}' in resume, 'resume prompt missing canonical evaluation_profile'
|
|
262
302
|
assert routing['mode'] == 'bare', 'active bare /cook should snapshot bare routing mode'
|
|
263
|
-
assert routing['action'] == 'continue', 'no-discussion active bare /cook should resume from canonical state without a
|
|
264
|
-
assert routing['reason'] == '
|
|
303
|
+
assert routing['action'] == 'continue', 'no-discussion active bare /cook should resume from canonical state without a concrete replacement mission'
|
|
304
|
+
assert routing['reason'] == 'no_replacement_proposal', 'no-discussion active bare /cook should explain that resume happened because no replacement mission was derived'
|
|
265
305
|
assert routing['currentMissionAnchor'] == state['mission_anchor'], 'resume routing snapshot should keep the current mission anchor'
|
|
266
306
|
assert routing['proposedMissionAnchor'] is None, 'no-discussion active bare /cook should not propose a replacement mission'
|
|
267
307
|
assert not chooser_path.exists(), 'active bare /cook resume should not open the chooser without a fresh explicit handoff'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cook-handoff-boundary
|
|
3
|
-
description: Ordinary-chat boundary contract for
|
|
3
|
+
description: Ordinary-chat boundary contract for keeping main chat advisory until the user explicitly enters `/cook`, while preventing long-running implementation from starting before that explicit workflow entry.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /cook Handoff Boundary
|
|
@@ -14,35 +14,66 @@ This skill governs the boundary between:
|
|
|
14
14
|
|
|
15
15
|
## Core Contract
|
|
16
16
|
|
|
17
|
-
- Ordinary chat may be used to clarify requirements, discuss tradeoffs, propose implementation approaches, and refine scope
|
|
17
|
+
- Ordinary chat may be used to clarify requirements, discuss tradeoffs, propose implementation approaches, and refine scope.
|
|
18
18
|
- `/cook` is the only explicit entrypoint into long-running completion workflow.
|
|
19
|
-
-
|
|
20
|
-
- Before
|
|
19
|
+
- Ordinary chat remains ordinary chat until the user explicitly runs `/cook`.
|
|
20
|
+
- Before that explicit `/cook` entry, the primary agent must stop short of long-running implementation for workflow-level tasks.
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## What Ordinary Chat May Do
|
|
23
23
|
|
|
24
|
-
The primary agent
|
|
24
|
+
The primary agent may:
|
|
25
|
+
|
|
26
|
+
- answer follow-up questions
|
|
27
|
+
- discuss tradeoffs
|
|
28
|
+
- refine scope and constraints
|
|
29
|
+
- summarize likely mission, acceptance, or risks
|
|
30
|
+
- help the user determine whether the work seems large enough for `/cook`
|
|
31
|
+
|
|
32
|
+
The primary agent should not:
|
|
33
|
+
|
|
34
|
+
- proactively tell the user to run `/cook`
|
|
35
|
+
- proactively emit a `cook_handoff` capsule by default
|
|
36
|
+
- act as though workflow has already started
|
|
37
|
+
- rewrite ordinary-chat discussion into canonical workflow state
|
|
38
|
+
|
|
39
|
+
## When Work Looks Workflow-Worthy
|
|
40
|
+
|
|
41
|
+
The primary agent should treat work as workflow-worthy when one or more of the following are true:
|
|
25
42
|
|
|
26
|
-
- the user has clearly shifted from exploration into implementation intent
|
|
27
|
-
- the agent has just produced a concrete plan or proposal whose natural next step would be implementation
|
|
28
43
|
- the task spans multiple files, steps, or verification surfaces
|
|
29
|
-
- the
|
|
44
|
+
- the next natural step would be bounded repo implementation rather than more explanation
|
|
45
|
+
- the work needs resumability, review, audit, or canonical workflow state
|
|
30
46
|
- the task is better treated as a long-running repo mission than a one-off answer or tiny fix
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
Even then, the boundary remains:
|
|
49
|
+
|
|
50
|
+
- ordinary chat can still keep refining the task
|
|
51
|
+
- only explicit `/cook` starts workflow
|
|
52
|
+
|
|
53
|
+
## Required Behavior Before Explicit `/cook`
|
|
33
54
|
|
|
34
|
-
When
|
|
55
|
+
When a task has matured into workflow-level work, the primary agent must:
|
|
35
56
|
|
|
36
57
|
- stop before long-running implementation
|
|
37
|
-
- not edit tracked product files
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
- not edit tracked product files for that workflow-level task in ordinary chat
|
|
59
|
+
- continue ordinary discussion naturally if the user keeps asking questions or refining scope
|
|
60
|
+
- wait for the user to explicitly run `/cook` before treating the conversation as workflow startup
|
|
61
|
+
|
|
62
|
+
## Deferred Handoff Model
|
|
63
|
+
|
|
64
|
+
When the user explicitly runs `/cook`:
|
|
65
|
+
|
|
66
|
+
- `/cook` will synthesize a startup brief from recent discussion using primary-agent-style context
|
|
67
|
+
- `/cook` will show Start / Cancel confirmation before canonical workflow state is rewritten
|
|
68
|
+
- that synthesized startup brief is advisory intake only, not canonical `.agent/**` state by itself
|
|
69
|
+
|
|
70
|
+
This means the primary agent does **not** need to proactively attach startup capsules during ordinary chat just because the task looks ready.
|
|
71
|
+
|
|
72
|
+
## Optional Preview Behavior
|
|
73
|
+
|
|
74
|
+
Only if the user explicitly asks for a preview startup brief or handoff capsule in ordinary chat may the primary agent provide one.
|
|
44
75
|
|
|
45
|
-
Optional preview capsule format
|
|
76
|
+
Optional preview capsule format:
|
|
46
77
|
|
|
47
78
|
````text
|
|
48
79
|
```cook_handoff
|
|
@@ -75,30 +106,27 @@ Notes:
|
|
|
75
106
|
|
|
76
107
|
- `constraints` may be replaced or supplemented by `non_goals` when clearer.
|
|
77
108
|
- `first_slice_goal`, `first_slice_non_goals`, `implementation_surfaces`, `verification_commands`, and `why_this_slice_first` are required only for an implementation-ready preview capsule.
|
|
78
|
-
- If the work is workflow-worthy but the first slice still needs refinement, say that `/cook` will be the right next step once the slice is concrete enough, then keep refining in ordinary chat without emitting a preview capsule unless the user explicitly asks for one.
|
|
79
|
-
- If later ordinary-chat discussion materially changes the startup brief before `/cook` runs, update or replace the preview capsule in a later assistant reply.
|
|
80
|
-
- The mission must be positively startable implementation work; do not use rejection or suppression text as the mission.
|
|
81
109
|
- Any preview capsule is startup intake for `/cook` only. It is not canonical `.agent/**` state, not active-slice state, and not a second repo contract source.
|
|
82
110
|
|
|
83
111
|
Suggested wording:
|
|
84
112
|
|
|
85
|
-
>
|
|
113
|
+
> We are still in ordinary chat until you explicitly run `/cook`. If you want, we can keep refining the first slice here. When you do run `/cook`, it will synthesize a startup brief from our recent discussion and show Start / Cancel before workflow begins.
|
|
86
114
|
|
|
87
115
|
A short recap may include mission, scope, or acceptance, but that recap must not be presented as canonical plan state.
|
|
88
116
|
|
|
89
117
|
## Forbidden Behaviors
|
|
90
118
|
|
|
91
|
-
|
|
119
|
+
Before the user explicitly runs `/cook`, the primary agent must not:
|
|
92
120
|
|
|
93
121
|
- directly begin long-running implementation in ordinary chat
|
|
94
122
|
- modify tracked product files as part of that workflow-level task
|
|
95
123
|
- act as though `/cook` had already been invoked
|
|
96
124
|
- silently rewrite ordinary-chat discussion into active workflow state
|
|
97
|
-
- refuse ordinary-chat clarification
|
|
125
|
+
- refuse ordinary-chat clarification only because `/cook` would now be appropriate
|
|
98
126
|
|
|
99
127
|
## Relationship To `completion-protocol`
|
|
100
128
|
|
|
101
|
-
This skill is only about pre-`/cook` ordinary-chat
|
|
129
|
+
This skill is only about pre-`/cook` ordinary-chat boundary behavior.
|
|
102
130
|
|
|
103
131
|
After the user explicitly enters `/cook`, the separate `completion-protocol` skill governs:
|
|
104
132
|
|