@linimin/pi-letscook 0.1.54 → 0.1.55
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 +2 -2
- package/README.md +12 -17
- package/extensions/completion/driver.ts +44 -110
- package/extensions/completion/index.ts +10 -70
- package/extensions/completion/prompt-surfaces.ts +53 -380
- package/extensions/completion/proposal.ts +5 -65
- package/extensions/completion/role-runner.ts +4 -311
- package/extensions/completion/state-store.ts +212 -5
- package/extensions/completion/transcription.ts +0 -8
- package/extensions/completion/types.ts +0 -114
- package/package.json +15 -4
- package/scripts/active-slice-contract-test.sh +61 -6
- package/scripts/context-proposal-test.sh +33 -29
- package/scripts/legacy-cleanup-test.sh +11 -0
- package/scripts/refocus-test.sh +10 -11
- package/scripts/release-check.sh +11 -11
- package/scripts/role-runner-contract-test.sh +1 -2
- package/scripts/rubric-contract-test.sh +0 -1
- package/scripts/smoke-test.sh +14 -10
- package/extensions/completion/input-routing.ts +0 -819
- package/scripts/cook-trigger-routing-test.sh +0 -1122
|
@@ -85,117 +85,3 @@ export type CompletionStatusSurface = {
|
|
|
85
85
|
liveStateDeltas?: string[];
|
|
86
86
|
liveDetailsLines?: string[];
|
|
87
87
|
};
|
|
88
|
-
|
|
89
|
-
export type NaturalLanguageCookTriggerMode = "off" | "router" | "auto";
|
|
90
|
-
export type CookTriggerClassifierDecision = "offer_workflow" | "normal_prompt" | "unclear";
|
|
91
|
-
export type CookTriggerWorkflowBias = "startup" | "resume" | "refocus" | "next_round" | "unknown";
|
|
92
|
-
|
|
93
|
-
export type CookTriggerClassification = {
|
|
94
|
-
decision: CookTriggerClassifierDecision;
|
|
95
|
-
confidence: number;
|
|
96
|
-
workflowBias: CookTriggerWorkflowBias;
|
|
97
|
-
reason: string;
|
|
98
|
-
focusHint?: string;
|
|
99
|
-
evidence: string[];
|
|
100
|
-
riskFlags: string[];
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
export type CookTriggerConfirmationAction = "start_workflow" | "send_as_normal_chat" | "cancel";
|
|
104
|
-
export type CookTriggerClarificationAction =
|
|
105
|
-
| "route_startup"
|
|
106
|
-
| "route_resume"
|
|
107
|
-
| "route_refocus"
|
|
108
|
-
| "route_next_round"
|
|
109
|
-
| "send_as_normal_chat"
|
|
110
|
-
| "cancel";
|
|
111
|
-
export type CookTriggerRecoveryAction = "retry_routing" | "send_as_normal_chat" | "cancel";
|
|
112
|
-
export type CookTriggerAdoptedArtifactKind = "recent_plan" | "repo_markdown";
|
|
113
|
-
|
|
114
|
-
export type CookTriggerConfirmationActionItem = {
|
|
115
|
-
id: CookTriggerConfirmationAction;
|
|
116
|
-
label: string;
|
|
117
|
-
description: string;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
export type CookTriggerClarificationActionItem = {
|
|
121
|
-
id: CookTriggerClarificationAction;
|
|
122
|
-
label: string;
|
|
123
|
-
description: string;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
export type CookTriggerConfirmationLayout = {
|
|
127
|
-
title: string;
|
|
128
|
-
intro: string;
|
|
129
|
-
evidenceHeading?: string;
|
|
130
|
-
evidenceBody?: string;
|
|
131
|
-
riskHeading?: string;
|
|
132
|
-
riskBody?: string;
|
|
133
|
-
focusHintHeading?: string;
|
|
134
|
-
focusHintBody?: string;
|
|
135
|
-
actionsHeading: string;
|
|
136
|
-
actions: CookTriggerConfirmationActionItem[];
|
|
137
|
-
footer: string;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export type CookTriggerClarificationCapsule = {
|
|
141
|
-
goal?: string;
|
|
142
|
-
scope?: string[];
|
|
143
|
-
nonGoal?: string[];
|
|
144
|
-
doneWhen?: string[];
|
|
145
|
-
selectedWorkflowBias: CookTriggerWorkflowBias;
|
|
146
|
-
reason: string;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
export type CookTriggerAdoptedArtifact = {
|
|
150
|
-
kind: CookTriggerAdoptedArtifactKind;
|
|
151
|
-
basis: "explicit_user_adoption";
|
|
152
|
-
title: string;
|
|
153
|
-
path?: string;
|
|
154
|
-
preview?: string;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
export type CookNaturalLanguageHandoff = {
|
|
158
|
-
preferredRoutingBias?: CookTriggerWorkflowBias;
|
|
159
|
-
triggerText?: string;
|
|
160
|
-
hintText?: string;
|
|
161
|
-
clarificationCapsule?: CookTriggerClarificationCapsule;
|
|
162
|
-
adoptedArtifact?: CookTriggerAdoptedArtifact;
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
export type CookTriggerClarificationLayout = {
|
|
166
|
-
title: string;
|
|
167
|
-
intro: string;
|
|
168
|
-
currentMissionHeading?: string;
|
|
169
|
-
currentMissionBody?: string;
|
|
170
|
-
candidateMissionHeading?: string;
|
|
171
|
-
candidateMissionBody?: string;
|
|
172
|
-
adoptedArtifactHeading?: string;
|
|
173
|
-
adoptedArtifactBody?: string;
|
|
174
|
-
actionsHeading: string;
|
|
175
|
-
actions: CookTriggerClarificationActionItem[];
|
|
176
|
-
footer: string;
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
export type CookTriggerRecoveryActionItem = {
|
|
180
|
-
id: CookTriggerRecoveryAction;
|
|
181
|
-
label: string;
|
|
182
|
-
description: string;
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
export type CookTriggerRecoveryLayout = {
|
|
186
|
-
title: string;
|
|
187
|
-
intro: string;
|
|
188
|
-
failureHeading?: string;
|
|
189
|
-
failureBody?: string;
|
|
190
|
-
actionsHeading: string;
|
|
191
|
-
actions: CookTriggerRecoveryActionItem[];
|
|
192
|
-
footer: string;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
export type CookTriggerDecision = {
|
|
196
|
-
mode: NaturalLanguageCookTriggerMode;
|
|
197
|
-
action: "continue" | "handled" | "routed_to_cook";
|
|
198
|
-
reason: string;
|
|
199
|
-
classification?: CookTriggerClassification;
|
|
200
|
-
bypassReason?: string;
|
|
201
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linimin/pi-letscook",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.55",
|
|
4
4
|
"description": "Pi package for long-running completion workflows with canonical .agent state, role-based subagents, continuity, and verification helpers.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -13,7 +13,14 @@
|
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/linimin/pi-letscook/issues"
|
|
15
15
|
},
|
|
16
|
-
"keywords": [
|
|
16
|
+
"keywords": [
|
|
17
|
+
"pi-package",
|
|
18
|
+
"pi",
|
|
19
|
+
"workflow",
|
|
20
|
+
"completion",
|
|
21
|
+
"agent",
|
|
22
|
+
"subagent"
|
|
23
|
+
],
|
|
17
24
|
"files": [
|
|
18
25
|
"extensions",
|
|
19
26
|
"skills",
|
|
@@ -43,7 +50,11 @@
|
|
|
43
50
|
"typebox": "*"
|
|
44
51
|
},
|
|
45
52
|
"pi": {
|
|
46
|
-
"extensions": [
|
|
47
|
-
|
|
53
|
+
"extensions": [
|
|
54
|
+
"./extensions/completion"
|
|
55
|
+
],
|
|
56
|
+
"skills": [
|
|
57
|
+
"./skills"
|
|
58
|
+
]
|
|
48
59
|
}
|
|
49
60
|
}
|
|
@@ -82,9 +82,13 @@ assertIncludes('extensions/completion/prompt-surfaces.ts', 'Active slice contrac
|
|
|
82
82
|
assertIncludes('extensions/completion/index.ts', 'Canonical active-slice contract drift is currently: ${activeContractDrift}');
|
|
83
83
|
assertIncludes('extensions/completion/prompt-surfaces.ts', '`active_slice_contract_drift_fields: ${args.activeSliceContractDrift}`');
|
|
84
84
|
assertIncludes('extensions/completion/index.ts', 'treat .agent/active-slice.json as the canonical implementation contract');
|
|
85
|
+
assertIncludes('.agent/verify_completion_control_plane.sh', 'const REQUIRED_TRACKED_CONTRACT_FILES = [');
|
|
86
|
+
assertIncludes('.agent/verify_completion_control_plane.sh', 'Required tracked completion contract file is missing from git index:');
|
|
85
87
|
assertIncludes('.agent/verify_completion_control_plane.sh', "const planMirrorFields = ['locked_notes', 'must_fix_findings', 'implementation_surfaces', 'verification_commands', 'basis_commit', 'remaining_contract_ids_before', 'release_blocker_count_before', 'high_value_gap_count_before'];");
|
|
86
88
|
assertIncludes('.agent/verify_completion_control_plane.sh', 'slice_id must match a slice in .agent/plan.json when status carries an exact handoff');
|
|
87
89
|
assertIncludes('.agent/verify_completion_control_plane.sh', '.agent/active-slice.json must match the selected .agent/plan.json slice across: ');
|
|
90
|
+
assertIncludes('.agent/verify_completion_control_plane.sh', '.agent/active-slice.json implementation_surfaces must cover every tracked file changed from basis_commit to current HEAD; missing: ');
|
|
91
|
+
assertIncludes('scripts/release-check.sh', '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');
|
|
88
92
|
NODE
|
|
89
93
|
|
|
90
94
|
ROOT="$TMPDIR/repo"
|
|
@@ -102,11 +106,24 @@ PI_COMPLETION_SKIP_DRIVER_KICKOFF=1 \
|
|
|
102
106
|
pi --session "$BOOTSTRAP_SESSION" -e "$PKG_ROOT" -p "/cook" \
|
|
103
107
|
>"$TMPDIR/pi-active-slice-bootstrap.out" 2>"$TMPDIR/pi-active-slice-bootstrap.err"
|
|
104
108
|
|
|
105
|
-
|
|
109
|
+
git config user.name 'Completion Fixture'
|
|
110
|
+
git config user.email 'completion-fixture@example.com'
|
|
111
|
+
git add .
|
|
112
|
+
git commit -q -m 'fixture basis'
|
|
113
|
+
BASIS_SHA="$(git rev-parse HEAD)"
|
|
114
|
+
printf '\nSlice surface fixture change.\n' >> README.md
|
|
115
|
+
git add README.md
|
|
116
|
+
git commit -q -m 'fixture slice change'
|
|
117
|
+
HEAD_SHA="$(git rev-parse HEAD)"
|
|
118
|
+
|
|
119
|
+
BASIS_SHA="$BASIS_SHA" HEAD_SHA="$HEAD_SHA" python3 - <<'PY'
|
|
106
120
|
import json
|
|
121
|
+
import os
|
|
107
122
|
from pathlib import Path
|
|
108
123
|
|
|
109
124
|
mission = 'Exercise active-slice contract parity.'
|
|
125
|
+
basis_sha = os.environ['BASIS_SHA']
|
|
126
|
+
head_sha = os.environ['HEAD_SHA']
|
|
110
127
|
task_type = 'completion-workflow'
|
|
111
128
|
evaluation_profile = 'completion-rubric-v1'
|
|
112
129
|
verification_commands = [
|
|
@@ -157,8 +174,8 @@ state = {
|
|
|
157
174
|
'last_reground_at': '2026-05-03T00:00:00Z',
|
|
158
175
|
'last_auditor_verdict': None,
|
|
159
176
|
'contract_status': 'selected_slice_pending_implementation',
|
|
160
|
-
'latest_completed_slice':
|
|
161
|
-
'latest_verified_slice':
|
|
177
|
+
'latest_completed_slice': head_sha,
|
|
178
|
+
'latest_verified_slice': head_sha,
|
|
162
179
|
}
|
|
163
180
|
plan = {
|
|
164
181
|
'schema_version': 1,
|
|
@@ -182,7 +199,7 @@ plan = {
|
|
|
182
199
|
'must_fix_findings': must_fix_findings,
|
|
183
200
|
'implementation_surfaces': implementation_surfaces,
|
|
184
201
|
'verification_commands': verification_commands,
|
|
185
|
-
'basis_commit':
|
|
202
|
+
'basis_commit': basis_sha,
|
|
186
203
|
'remaining_contract_ids_before': remaining_contracts,
|
|
187
204
|
'release_blocker_count_before': 0,
|
|
188
205
|
'high_value_gap_count_before': 2,
|
|
@@ -204,7 +221,7 @@ active = {
|
|
|
204
221
|
'must_fix_findings': must_fix_findings,
|
|
205
222
|
'implementation_surfaces': implementation_surfaces,
|
|
206
223
|
'verification_commands': verification_commands,
|
|
207
|
-
'basis_commit':
|
|
224
|
+
'basis_commit': basis_sha,
|
|
208
225
|
'remaining_contract_ids_before': remaining_contracts,
|
|
209
226
|
'release_blocker_count_before': 0,
|
|
210
227
|
'high_value_gap_count_before': 2,
|
|
@@ -223,7 +240,7 @@ Path('.agent/verification-evidence.json').write_text(json.dumps({
|
|
|
223
240
|
'goal': active['goal'],
|
|
224
241
|
'contract_ids': active['contract_ids'],
|
|
225
242
|
'basis_commit': active['basis_commit'],
|
|
226
|
-
'head_sha':
|
|
243
|
+
'head_sha': head_sha,
|
|
227
244
|
'verification_commands': verification_commands,
|
|
228
245
|
'outcome': 'passed',
|
|
229
246
|
'recorded_at': '2026-05-03T00:00:00Z',
|
|
@@ -247,6 +264,19 @@ PY
|
|
|
247
264
|
|
|
248
265
|
bash .agent/verify_completion_control_plane.sh >/dev/null
|
|
249
266
|
|
|
267
|
+
git rm --cached -q .agent/profile.json
|
|
268
|
+
if bash .agent/verify_completion_control_plane.sh >"$TMPDIR/untracked-contract.out" 2>"$TMPDIR/untracked-contract.err"; then
|
|
269
|
+
echo 'expected verifier to fail when a required tracked .agent contract file becomes untracked' >&2
|
|
270
|
+
exit 1
|
|
271
|
+
fi
|
|
272
|
+
if ! grep -q 'Required tracked completion contract file is missing from git index: .agent/profile.json' "$TMPDIR/untracked-contract.err"; then
|
|
273
|
+
echo 'expected verifier failure output to mention the untracked .agent/profile.json contract file' >&2
|
|
274
|
+
cat "$TMPDIR/untracked-contract.err" >&2
|
|
275
|
+
exit 1
|
|
276
|
+
fi
|
|
277
|
+
git add .agent/profile.json
|
|
278
|
+
bash .agent/verify_completion_control_plane.sh >/dev/null
|
|
279
|
+
|
|
250
280
|
python3 - <<'PY'
|
|
251
281
|
import copy
|
|
252
282
|
import json
|
|
@@ -254,7 +284,9 @@ import subprocess
|
|
|
254
284
|
from pathlib import Path
|
|
255
285
|
|
|
256
286
|
plan_path = Path('.agent/plan.json')
|
|
287
|
+
active_path = Path('.agent/active-slice.json')
|
|
257
288
|
base_plan = json.loads(plan_path.read_text())
|
|
289
|
+
base_active = json.loads(active_path.read_text())
|
|
258
290
|
|
|
259
291
|
cases = [
|
|
260
292
|
('slice_id', lambda slice: slice.__setitem__('slice_id', 'different-slice')),
|
|
@@ -285,6 +317,29 @@ for label, mutate in cases:
|
|
|
285
317
|
assert label in combined, f'expected verifier output to mention {label}, got: {combined}'
|
|
286
318
|
|
|
287
319
|
plan_path.write_text(json.dumps(base_plan, indent=2) + '\n')
|
|
320
|
+
active_path.write_text(json.dumps(base_active, indent=2) + '\n')
|
|
321
|
+
|
|
322
|
+
surface_drift_plan = copy.deepcopy(base_plan)
|
|
323
|
+
surface_drift_active = copy.deepcopy(base_active)
|
|
324
|
+
surface_drift_plan['candidate_slices'][0]['implementation_surfaces'] = [
|
|
325
|
+
surface for surface in surface_drift_plan['candidate_slices'][0]['implementation_surfaces']
|
|
326
|
+
if surface != 'README.md'
|
|
327
|
+
]
|
|
328
|
+
surface_drift_active['implementation_surfaces'] = [
|
|
329
|
+
surface for surface in surface_drift_active['implementation_surfaces']
|
|
330
|
+
if surface != 'README.md'
|
|
331
|
+
]
|
|
332
|
+
plan_path.write_text(json.dumps(surface_drift_plan, indent=2) + '\n')
|
|
333
|
+
active_path.write_text(json.dumps(surface_drift_active, indent=2) + '\n')
|
|
334
|
+
result = subprocess.run(['bash', '.agent/verify_completion_control_plane.sh'], capture_output=True, text=True)
|
|
335
|
+
combined = (result.stdout or '') + (result.stderr or '')
|
|
336
|
+
assert result.returncode != 0, 'expected verifier failure when implementation_surfaces omit a tracked basis-to-HEAD diff file'
|
|
337
|
+
assert 'implementation_surfaces must cover every tracked file changed from basis_commit to current HEAD; missing: README.md' in combined, combined
|
|
338
|
+
|
|
339
|
+
plan_path.write_text(json.dumps(base_plan, indent=2) + '\n')
|
|
340
|
+
active_path.write_text(json.dumps(base_active, indent=2) + '\n')
|
|
288
341
|
PY
|
|
289
342
|
|
|
343
|
+
bash .agent/verify_completion_control_plane.sh >/dev/null
|
|
344
|
+
|
|
290
345
|
echo "active-slice contract test passed: $TMPDIR"
|
|
@@ -654,6 +654,16 @@ assert plan['evaluation_profile'] == expected_eval_profile, 'plan.json evaluatio
|
|
|
654
654
|
assert active['mission_anchor'] == mission, 'active-slice.json mission_anchor mismatch after analyst-derived bootstrap'
|
|
655
655
|
assert active['task_type'] == expected_task_type, 'active-slice.json task_type mismatch after analyst-derived bootstrap'
|
|
656
656
|
assert active['evaluation_profile'] == expected_eval_profile, 'active-slice.json evaluation_profile mismatch after analyst-derived bootstrap'
|
|
657
|
+
brief = state['advisory_startup_brief']
|
|
658
|
+
assert brief['kind'] == 'startup_brief', 'state.json should preserve the confirmed startup brief as advisory intake'
|
|
659
|
+
assert brief['mission'] == mission, 'advisory startup brief mission should match the accepted mission anchor'
|
|
660
|
+
assert brief['scope'] == ['Keep the non-running completion widget.', 'Suppress the widget while a completion role is active.'], 'advisory startup brief should preserve scope items separately from canonical planning state'
|
|
661
|
+
assert brief['constraints'] == ['Do not reintroduce any other completion status surface.'], 'advisory startup brief should preserve constraints separately from canonical planning state'
|
|
662
|
+
assert brief['acceptance'] == ['Update README to match the shipped behavior.', 'Keep observability regression coverage truthful.'], 'advisory startup brief should preserve acceptance separately from canonical planning state'
|
|
663
|
+
assert brief['risks'] == ['Stale widget-removal discussion could broaden the startup plan if it gets treated as mission text.'], 'advisory startup brief should preserve derived risks'
|
|
664
|
+
assert brief['notes'] == ['Keep critique separate from the mission anchor so startup analysis does not rewrite the workflow goal.', 'Possible noise: older widget restyle ideas'], 'advisory startup brief should preserve operator notes and possible-noise cautions'
|
|
665
|
+
assert plan['candidate_slices'] == [], 'startup brief should remain advisory intake only until regrounder owns plan selection'
|
|
666
|
+
assert active['status'] == 'idle', 'startup brief should not become the active-slice source before regrounder runs'
|
|
657
667
|
assert proposal['mission'] == mission, 'discussion-only proposal snapshot should keep the inferred mission anchor'
|
|
658
668
|
assert proposal['analysis']['taskType'] == expected_task_type, 'discussion-only proposal snapshot should expose task_type hints separately'
|
|
659
669
|
assert proposal['analysis']['evaluationProfile'] == expected_eval_profile, 'discussion-only proposal snapshot should expose evaluation_profile hints separately'
|
|
@@ -1080,6 +1090,7 @@ assert profile['evaluation_profile'] == expected_eval_profile, 'profile.json eva
|
|
|
1080
1090
|
assert state['mission_anchor'] == mission, 'state.json mission_anchor mismatch after starting the next workflow round'
|
|
1081
1091
|
assert state['task_type'] == expected_task_type, 'state.json task_type mismatch after starting the next workflow round'
|
|
1082
1092
|
assert state['evaluation_profile'] == expected_eval_profile, 'state.json evaluation_profile mismatch after starting the next workflow round'
|
|
1093
|
+
assert state['advisory_startup_brief']['mission'] == mission, 'next-round startup should preserve the confirmed startup brief as advisory intake'
|
|
1083
1094
|
assert plan['mission_anchor'] == mission, 'plan.json mission_anchor mismatch after starting the next workflow round'
|
|
1084
1095
|
assert plan['task_type'] == expected_task_type, 'plan.json task_type mismatch after starting the next workflow round'
|
|
1085
1096
|
assert plan['evaluation_profile'] == expected_eval_profile, 'plan.json evaluation_profile mismatch after starting the next workflow round'
|
|
@@ -1101,8 +1112,7 @@ assert plan['plan_basis'] == 'user_refocus', 'plan_basis should reset to user_re
|
|
|
1101
1112
|
assert active['status'] == 'idle', 'active-slice should reset to idle for the next workflow round'
|
|
1102
1113
|
PY
|
|
1103
1114
|
|
|
1104
|
-
# Active workflow:
|
|
1105
|
-
# still route through the chooser, and leave canonical state unchanged when the user cancels.
|
|
1115
|
+
# Active workflow: inline `/cook` arguments should fail closed immediately and leave canonical state unchanged.
|
|
1106
1116
|
ACTIVE_INLINE_REJECTION_ROUTING="$TMPDIR/context-proposal-active-inline-arg-routing.json"
|
|
1107
1117
|
ACTIVE_INLINE_REJECTION_PROPOSAL="$TMPDIR/context-proposal-active-inline-arg-proposal.json"
|
|
1108
1118
|
ACTIVE_INLINE_REJECTION_CHOOSER="$TMPDIR/context-proposal-active-inline-arg-chooser.json"
|
|
@@ -1123,9 +1133,6 @@ tracked = [
|
|
|
1123
1133
|
Path(sys.argv[1]).write_text(json.dumps({path.name: path.read_text() for path in tracked}, indent=2) + '\n')
|
|
1124
1134
|
PY
|
|
1125
1135
|
|
|
1126
|
-
PI_COMPLETION_EXISTING_WORKFLOW_ACTION=refocus \
|
|
1127
|
-
PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=cancel \
|
|
1128
|
-
PI_COMPLETION_CONTEXT_PROPOSAL_ANALYST_OUTPUT='{"mission":"Replacement mission for the active workflow.","scope":["Review the replacement through the existing workflow chooser first."],"constraints":["Do not rewrite canonical state before the final Start confirmation."],"acceptance":["Show the final replacement proposal only after the chooser selects refocus."],"task_type":"completion-workflow","evaluation_profile":"completion-rubric-v1","confidence":0.9}' \
|
|
1129
1136
|
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$ACTIVE_INLINE_REJECTION_PROPOSAL" \
|
|
1130
1137
|
PI_COMPLETION_TEST_ACTIVE_WORKFLOW_ROUTING_PATH="$ACTIVE_INLINE_REJECTION_ROUTING" \
|
|
1131
1138
|
PI_COMPLETION_TEST_EXISTING_WORKFLOW_CHOOSER_PATH="$ACTIVE_INLINE_REJECTION_CHOOSER" \
|
|
@@ -1138,9 +1145,9 @@ import sys
|
|
|
1138
1145
|
from pathlib import Path
|
|
1139
1146
|
|
|
1140
1147
|
output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
|
|
1141
|
-
routing =
|
|
1148
|
+
routing = Path(sys.argv[3])
|
|
1142
1149
|
proposal = Path(sys.argv[4])
|
|
1143
|
-
chooser =
|
|
1150
|
+
chooser = Path(sys.argv[5])
|
|
1144
1151
|
before = json.loads(Path(sys.argv[6]).read_text())
|
|
1145
1152
|
tracked = [
|
|
1146
1153
|
Path('.agent/mission.md'),
|
|
@@ -1151,17 +1158,15 @@ tracked = [
|
|
|
1151
1158
|
Path('.agent/verification-evidence.json'),
|
|
1152
1159
|
]
|
|
1153
1160
|
|
|
1154
|
-
assert routing
|
|
1155
|
-
assert
|
|
1156
|
-
assert
|
|
1157
|
-
assert
|
|
1158
|
-
assert 'Cancelled replacement workflow proposal.' in output or 'Cancelled existing workflow confirmation.' in output, 'active /cook <hint> cancel should report cancellation'
|
|
1161
|
+
assert not routing.exists(), 'active /cook inline-args rejection should not run active-workflow routing'
|
|
1162
|
+
assert not proposal.exists(), 'active /cook inline-args rejection should not emit a replacement startup-brief proposal'
|
|
1163
|
+
assert not chooser.exists(), 'active /cook inline-args rejection should not open the existing-workflow chooser'
|
|
1164
|
+
assert '/cook no longer accepts inline arguments.' in output, 'active /cook inline-args rejection should explain the bare-only entry contract'
|
|
1159
1165
|
after = {path.name: path.read_text() for path in tracked}
|
|
1160
|
-
assert before == after, 'active /cook
|
|
1166
|
+
assert before == after, 'active /cook inline-args rejection should leave canonical files unchanged'
|
|
1161
1167
|
PY
|
|
1162
1168
|
|
|
1163
|
-
# Completed workflow:
|
|
1164
|
-
# unchanged when the user cancels the approval-only proposal.
|
|
1169
|
+
# Completed workflow: inline `/cook` arguments should also fail closed before any next-round proposal derivation.
|
|
1165
1170
|
mark_done
|
|
1166
1171
|
|
|
1167
1172
|
DONE_INLINE_REJECTION_ROUTING="$TMPDIR/context-proposal-done-inline-arg-routing.json"
|
|
@@ -1184,8 +1189,6 @@ tracked = [
|
|
|
1184
1189
|
Path(sys.argv[1]).write_text(json.dumps({path.name: path.read_text() for path in tracked}, indent=2) + '\n')
|
|
1185
1190
|
PY
|
|
1186
1191
|
|
|
1187
|
-
PI_COMPLETION_CONTEXT_PROPOSAL_ACTION=cancel \
|
|
1188
|
-
PI_COMPLETION_CONTEXT_PROPOSAL_ANALYST_OUTPUT='{"mission":"Update README guidance for the next workflow round.","scope":["Refresh README guidance for /cook hint-driven startup behavior."],"constraints":["Do not rewrite canonical state before Start is accepted."],"acceptance":["Keep the next-round proposal scoped to README updates only."],"task_type":"completion-workflow","evaluation_profile":"completion-rubric-v1","confidence":0.9}' \
|
|
1189
1192
|
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$DONE_INLINE_REJECTION_PROPOSAL" \
|
|
1190
1193
|
PI_COMPLETION_TEST_ACTIVE_WORKFLOW_ROUTING_PATH="$DONE_INLINE_REJECTION_ROUTING" \
|
|
1191
1194
|
PI_COMPLETION_TEST_EXISTING_WORKFLOW_CHOOSER_PATH="$DONE_INLINE_REJECTION_CHOOSER" \
|
|
@@ -1199,7 +1202,7 @@ from pathlib import Path
|
|
|
1199
1202
|
|
|
1200
1203
|
output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
|
|
1201
1204
|
routing = Path(sys.argv[3])
|
|
1202
|
-
proposal =
|
|
1205
|
+
proposal = Path(sys.argv[4])
|
|
1203
1206
|
chooser = Path(sys.argv[5])
|
|
1204
1207
|
before = json.loads(Path(sys.argv[6]).read_text())
|
|
1205
1208
|
tracked = [
|
|
@@ -1211,14 +1214,14 @@ tracked = [
|
|
|
1211
1214
|
Path('.agent/verification-evidence.json'),
|
|
1212
1215
|
]
|
|
1213
1216
|
state_before = json.loads(before['state.json'])
|
|
1214
|
-
assert state_before['current_phase'] == 'done', 'done /cook
|
|
1215
|
-
assert state_before['project_done'] is True, 'done /cook
|
|
1216
|
-
assert not routing.exists(), 'done /cook
|
|
1217
|
-
assert proposal
|
|
1218
|
-
assert not chooser.exists(), 'done /cook
|
|
1219
|
-
assert '
|
|
1217
|
+
assert state_before['current_phase'] == 'done', 'done /cook inline-args rejection should start from a completed workflow'
|
|
1218
|
+
assert state_before['project_done'] is True, 'done /cook inline-args rejection should start from project_done=true'
|
|
1219
|
+
assert not routing.exists(), 'done /cook inline-args rejection should not run active-workflow routing while starting the next round'
|
|
1220
|
+
assert not proposal.exists(), 'done /cook inline-args rejection should not emit a next-round startup-brief proposal'
|
|
1221
|
+
assert not chooser.exists(), 'done /cook inline-args rejection should not open the existing-workflow chooser when starting the next round'
|
|
1222
|
+
assert '/cook no longer accepts inline arguments.' in output, 'done /cook inline-args rejection should explain the bare-only entry contract'
|
|
1220
1223
|
after = {path.name: path.read_text() for path in tracked}
|
|
1221
|
-
assert before == after, 'done /cook
|
|
1224
|
+
assert before == after, 'done /cook inline-args rejection should leave canonical files unchanged'
|
|
1222
1225
|
PY
|
|
1223
1226
|
|
|
1224
1227
|
# Completed workflow again: /cook with no goal should be able to use model-assisted
|
|
@@ -1296,15 +1299,15 @@ from pathlib import Path
|
|
|
1296
1299
|
snapshot = json.loads(Path(sys.argv[1]).read_text())
|
|
1297
1300
|
state = json.loads(Path('.agent/state.json').read_text())
|
|
1298
1301
|
|
|
1299
|
-
assert snapshot['proposalHeading'] == '
|
|
1300
|
-
assert snapshot['critiqueHeading'] == '
|
|
1302
|
+
assert snapshot['proposalHeading'] == 'Startup brief', 'custom confirmation snapshot should expose a dedicated startup-brief section'
|
|
1303
|
+
assert snapshot['critiqueHeading'] == 'Notes and risks', 'custom confirmation snapshot should expose notes separately from the startup-brief body'
|
|
1301
1304
|
assert snapshot['routingHeading'] == 'Routing recommendations', 'custom confirmation snapshot should expose routing recommendations separately from the proposal body'
|
|
1302
1305
|
assert 'approval-only' in snapshot['intro'], 'custom confirmation intro should explain the approval-only gate'
|
|
1303
1306
|
assert state['task_type'] == 'completion-workflow', 'start action should preserve canonical task_type'
|
|
1304
1307
|
assert state['evaluation_profile'] == 'completion-rubric-v1', 'start action should preserve canonical evaluation_profile'
|
|
1305
1308
|
assert 'Mission\nReplace the crowded selector with a clearer action layout.' in snapshot['proposalBody'], 'proposal body should be captured separately from the action list'
|
|
1306
|
-
assert 'Keep critique details separate from the approval-only proposal summary.' not in snapshot['proposalBody'], 'critique notes should not be embedded in the
|
|
1307
|
-
assert 'Critique\n- Keep critique details separate from the approval-only proposal summary.' in snapshot['critiqueBody'], '
|
|
1309
|
+
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'
|
|
1310
|
+
assert 'Critique\n- Keep critique details separate from the approval-only proposal summary.' in snapshot['critiqueBody'], 'notes section should render accepted critique notes separately'
|
|
1308
1311
|
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'
|
|
1309
1312
|
assert 'Possible noise\n- old selector wording' in snapshot['critiqueBody'], 'critique section should render possible-noise notes separately'
|
|
1310
1313
|
assert '- task_type: completion-workflow' in snapshot['routingBody'], 'routing section should render the recommended task_type'
|
|
@@ -1316,6 +1319,7 @@ for action in snapshot['actions']:
|
|
|
1316
1319
|
assert 'Replace the crowded selector with a clearer action layout.' not in action['label'], 'proposal mission should not be embedded in action labels'
|
|
1317
1320
|
assert 'Separate proposal text from actions.' not in action['description'], 'proposal scope should not be embedded in action descriptions'
|
|
1318
1321
|
assert state['mission_anchor'] == 'Replace the crowded selector with a clearer action layout.', 'start action should still accept the proposed mission'
|
|
1322
|
+
assert state['advisory_startup_brief']['mission'] == 'Replace the crowded selector with a clearer action layout.', 'start action should preserve the confirmed startup brief canonically'
|
|
1319
1323
|
assert state['continuation_reason'].startswith('User started workflow via /cook:'), 'start action should persist the startup routing outcome in continuation_reason'
|
|
1320
1324
|
assert 'Keep critique details separate from the approval-only proposal summary.' in state['continuation_reason'], 'start action should persist the accepted critique outcome canonically'
|
|
1321
1325
|
PY
|
|
@@ -54,6 +54,13 @@ assertIncludes('extensions/completion/role-runner.ts', 'async function runContex
|
|
|
54
54
|
assertIncludes('extensions/completion/prompt-surfaces.ts', 'export function buildSystemReminder(');
|
|
55
55
|
assertIncludes('extensions/completion/prompt-surfaces.ts', 'export function buildResumeCapsule(');
|
|
56
56
|
|
|
57
|
+
if (fs.existsSync('extensions/completion/input-routing.ts')) {
|
|
58
|
+
throw new Error('extensions/completion/input-routing.ts should be removed after explicit-/cook cleanup');
|
|
59
|
+
}
|
|
60
|
+
if (fs.existsSync('scripts/cook-trigger-routing-test.sh')) {
|
|
61
|
+
throw new Error('scripts/cook-trigger-routing-test.sh should be removed after explicit-/cook cleanup');
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
assertIncludes('extensions/completion/index.ts', 'scaffoldCompletionFiles as scaffoldCompletionFilesOnDisk');
|
|
58
65
|
assertIncludes('extensions/completion/index.ts', 'return await scaffoldCompletionFilesOnDisk(root, missionAnchor, {');
|
|
59
66
|
assertIncludes('extensions/completion/index.ts', 'applyLiveRoleEvent,');
|
|
@@ -102,6 +109,10 @@ assertNotIncludes('extensions/completion/index.ts', 'async function analyzeConte
|
|
|
102
109
|
assertNotIncludes('extensions/completion/index.ts', 'function deriveMissionAnchor(');
|
|
103
110
|
assertNotIncludes('extensions/completion/index.ts', 'function buildSystemReminder(');
|
|
104
111
|
assertNotIncludes('extensions/completion/index.ts', 'function buildResumeCapsule(');
|
|
112
|
+
assertNotIncludes('extensions/completion/role-runner.ts', 'classifyCookTriggerIntentWithAgent(');
|
|
113
|
+
assertNotIncludes('extensions/completion/role-runner.ts', 'COOK_TRIGGER_CLASSIFIER_SYSTEM_PROMPT');
|
|
114
|
+
assertNotIncludes('extensions/completion/prompt-surfaces.ts', 'buildCookTriggerConfirmationLayout(');
|
|
115
|
+
assertNotIncludes('extensions/completion/prompt-surfaces.ts', 'buildNaturalLanguageHandoffMetadataLines(');
|
|
105
116
|
NODE
|
|
106
117
|
|
|
107
118
|
echo "legacy cleanup test passed: $ROOT"
|
package/scripts/refocus-test.sh
CHANGED
|
@@ -102,8 +102,6 @@ tracked = [
|
|
|
102
102
|
Path(sys.argv[1]).write_text(json.dumps({path.name: path.read_text() for path in tracked}, indent=2) + '\n')
|
|
103
103
|
PY
|
|
104
104
|
|
|
105
|
-
PI_COMPLETION_EXISTING_WORKFLOW_ACTION=cancel \
|
|
106
|
-
PI_COMPLETION_CONTEXT_PROPOSAL_ANALYST_OUTPUT='{"mission":"Replacement mission that should stay in the main chat.","scope":["Replace the current workflow only after explicit approval."],"constraints":["Do not rewrite canonical state before the final Start confirmation."],"acceptance":["Surface the chooser before any replacement workflow rewrite."],"task_type":"completion-workflow","evaluation_profile":"completion-rubric-v1","confidence":0.9}' \
|
|
107
105
|
PI_COMPLETION_TEST_ACTIVE_WORKFLOW_ROUTING_PATH="$INLINE_REJECTION_ROUTING" \
|
|
108
106
|
PI_COMPLETION_TEST_CONTEXT_PROPOSAL_PATH="$INLINE_REJECTION_PROPOSAL" \
|
|
109
107
|
PI_COMPLETION_TEST_EXISTING_WORKFLOW_CHOOSER_PATH="$INLINE_REJECTION_CHOOSER" \
|
|
@@ -117,9 +115,9 @@ import sys
|
|
|
117
115
|
from pathlib import Path
|
|
118
116
|
|
|
119
117
|
output = Path(sys.argv[1]).read_text() + Path(sys.argv[2]).read_text()
|
|
120
|
-
routing =
|
|
118
|
+
routing = Path(sys.argv[3])
|
|
121
119
|
proposal = Path(sys.argv[4])
|
|
122
|
-
chooser =
|
|
120
|
+
chooser = Path(sys.argv[5])
|
|
123
121
|
initial_mission = sys.argv[6]
|
|
124
122
|
before = json.loads(Path(sys.argv[7]).read_text())
|
|
125
123
|
tracked = [
|
|
@@ -131,14 +129,13 @@ tracked = [
|
|
|
131
129
|
Path('.agent/verification-evidence.json'),
|
|
132
130
|
]
|
|
133
131
|
current_state = json.loads(before['state.json'])
|
|
134
|
-
assert current_state['mission_anchor'] == initial_mission, 'active /cook
|
|
135
|
-
assert routing
|
|
136
|
-
assert
|
|
137
|
-
assert not
|
|
138
|
-
assert
|
|
139
|
-
assert 'Cancelled existing workflow confirmation.' in output, 'active /cook <hint> chooser cancel should report cancellation'
|
|
132
|
+
assert current_state['mission_anchor'] == initial_mission, 'active /cook inline-args rejection should start from the current mission anchor'
|
|
133
|
+
assert not routing.exists(), 'active /cook inline-args rejection should not run active-workflow routing'
|
|
134
|
+
assert not proposal.exists(), 'active /cook inline-args rejection should not open final startup-brief confirmation'
|
|
135
|
+
assert not chooser.exists(), 'active /cook inline-args rejection should not open the existing-workflow chooser'
|
|
136
|
+
assert '/cook no longer accepts inline arguments.' in output, 'active /cook inline-args rejection should explain the bare-only entry contract'
|
|
140
137
|
after = {path.name: path.read_text() for path in tracked}
|
|
141
|
-
assert before == after, 'active /cook
|
|
138
|
+
assert before == after, 'active /cook inline-args rejection should leave canonical files unchanged'
|
|
142
139
|
PY
|
|
143
140
|
|
|
144
141
|
SESSION_INITIAL_REFOCUS="$TMPDIR/session-initial-bare-refocus.jsonl"
|
|
@@ -175,6 +172,7 @@ assert profile['evaluation_profile'] == expected_eval_profile, 'profile.json eva
|
|
|
175
172
|
assert state['mission_anchor'] == new_anchor, 'state.json mission_anchor mismatch after refocus'
|
|
176
173
|
assert state['task_type'] == expected_task_type, 'state.json task_type mismatch after refocus'
|
|
177
174
|
assert state['evaluation_profile'] == expected_eval_profile, 'state.json evaluation_profile mismatch after refocus'
|
|
175
|
+
assert state['advisory_startup_brief']['mission'] == new_anchor, 'refocus should preserve the confirmed startup brief as advisory intake'
|
|
178
176
|
assert plan['mission_anchor'] == new_anchor, 'plan.json mission_anchor mismatch after refocus'
|
|
179
177
|
assert plan['task_type'] == expected_task_type, 'plan.json task_type mismatch after refocus'
|
|
180
178
|
assert plan['evaluation_profile'] == expected_eval_profile, 'plan.json evaluation_profile mismatch after refocus'
|
|
@@ -338,6 +336,7 @@ assert profile['evaluation_profile'] == expected_eval_profile, 'profile.json eva
|
|
|
338
336
|
assert state['mission_anchor'] == new_anchor, 'state.json mission_anchor mismatch after bare refocus'
|
|
339
337
|
assert state['task_type'] == expected_task_type, 'state.json task_type mismatch after bare refocus'
|
|
340
338
|
assert state['evaluation_profile'] == expected_eval_profile, 'state.json evaluation_profile mismatch after bare refocus'
|
|
339
|
+
assert state['advisory_startup_brief']['mission'] == new_anchor, 'bare refocus should preserve the confirmed startup brief as advisory intake'
|
|
341
340
|
assert plan['mission_anchor'] == new_anchor, 'plan.json mission_anchor mismatch after bare refocus'
|
|
342
341
|
assert plan['task_type'] == expected_task_type, 'plan.json task_type mismatch after bare refocus'
|
|
343
342
|
assert plan['evaluation_profile'] == expected_eval_profile, 'plan.json evaluation_profile mismatch after bare refocus'
|
package/scripts/release-check.sh
CHANGED
|
@@ -4,8 +4,9 @@ set -euo pipefail
|
|
|
4
4
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
5
|
cd "$ROOT"
|
|
6
6
|
|
|
7
|
-
echo "[release-check] running control-plane validation, explicit-/cook parity, startup/refocus/context regressions, canonical evidence artifact, active-slice contract, observability, legacy cleanup, evaluator calibration, and rubric contract coverage"
|
|
7
|
+
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
8
|
bash .agent/verify_completion_control_plane.sh
|
|
9
|
+
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
|
|
9
10
|
|
|
10
11
|
echo "[release-check] verifying public /cook parity and explicit-entry docs/help"
|
|
11
12
|
python3 - <<'PY'
|
|
@@ -15,24 +16,24 @@ from pathlib import Path
|
|
|
15
16
|
checks = {
|
|
16
17
|
"README.md": [
|
|
17
18
|
"`/cook` is the explicit workflow boundary for starting, continuing, refocusing, or beginning the next round of long-running repo work.",
|
|
18
|
-
"Only explicit `/cook`
|
|
19
|
+
"Only explicit `/cook` enters the workflow. Ordinary prompts stay in the main chat and go straight to the primary agent.",
|
|
19
20
|
"`/cook` is the canonical workflow boundary and manual entry point",
|
|
20
21
|
"Discuss the concrete repo change in the main chat, then run `/cook`",
|
|
22
|
+
"The confirmed startup brief is also preserved there as advisory intake for later re-grounding.",
|
|
21
23
|
],
|
|
22
24
|
"CHANGELOG.md": [
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
+
"made `/cook` derive a confirmable startup brief from recent discussion before any canonical workflow rewrite, then preserve the confirmed brief in canonical state as advisory intake for later re-grounding",
|
|
26
|
+
"removed inline `/cook` arguments from the shipped entry path again so explicit bare `/cook` is the only public command, and fail closed when recent discussion is insufficient or unreliable",
|
|
25
27
|
],
|
|
26
28
|
"extensions/completion/index.ts": [
|
|
27
|
-
'description: "/cook workflow: start, continue, refocus, or start the next round from
|
|
28
|
-
'
|
|
29
|
-
'"/cook is the canonical workflow boundary. Discuss the concrete repo changes in the main chat, then run /cook when you want to start, continue, refocus, or begin the next workflow round."',
|
|
30
|
-
'"/cook failed closed because recent discussion did not produce a clear execution-ready Mission/Scope/Constraints/Acceptance proposal for concrete repo changes. Clarify the concrete repo changes in the main chat and rerun /cook."',
|
|
29
|
+
'description: "/cook workflow: derive a startup brief from recent discussion, then start, continue, refocus, or start the next round from the explicit /cook command"',
|
|
30
|
+
'"/cook failed closed because recent discussion did not produce a clear execution-ready startup brief with Mission/Scope/Constraints/Acceptance for concrete repo changes. Clarify the concrete repo changes in the main chat and rerun /cook."',
|
|
31
31
|
],
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
forbidden = {
|
|
35
35
|
"README.md": [
|
|
36
|
+
"`/cook <hint>`",
|
|
36
37
|
"Natural-language routing is optional and shipped in two modes",
|
|
37
38
|
"PI_COMPLETION_TRIGGER_MODE",
|
|
38
39
|
"workflow-aware router",
|
|
@@ -41,9 +42,8 @@ forbidden = {
|
|
|
41
42
|
],
|
|
42
43
|
"CHANGELOG.md": ["compatibility" + " shim"],
|
|
43
44
|
"extensions/completion/index.ts": [
|
|
44
|
-
'description: "/cook workflow: start, continue, refocus, or start the next round
|
|
45
|
-
'"/cook
|
|
46
|
-
'"/cook failed closed because recent discussion did not produce a clear execution-ready Mission/Scope/Constraints/Acceptance proposal for concrete repo changes. Router mode only offers the same /cook flow, and router recovery only replays to normal chat when you explicitly choose Send as normal chat, so clarify the concrete repo changes in the main chat and rerun /cook."',
|
|
45
|
+
'description: "/cook workflow: start, continue, refocus, or start the next round from an explicit /cook command"',
|
|
46
|
+
'"/cook failed closed because recent discussion did not produce a clear execution-ready Mission/Scope/Constraints/Acceptance proposal for concrete repo changes. Clarify the concrete repo changes in the main chat and rerun /cook."',
|
|
47
47
|
'handleCookNaturalLanguageTrigger',
|
|
48
48
|
],
|
|
49
49
|
}
|
|
@@ -21,10 +21,9 @@ const assertNotIncludes = (file, snippet) => {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
assertIncludes('extensions/completion/role-runner.ts', 'import { completionRootKey, findCompletionRoot, findRepoRoot
|
|
24
|
+
assertIncludes('extensions/completion/role-runner.ts', 'import { completionRootKey, findCompletionRoot, findRepoRoot } from "./state-store";');
|
|
25
25
|
assertIncludes('extensions/completion/role-runner.ts', 'import { parseReportFields, transcribeRoleOutput, type TranscriptionResult } from "./transcription";');
|
|
26
26
|
assertIncludes('extensions/completion/role-runner.ts', 'const agent = await loadAgentDefinition(params.root, params.role);');
|
|
27
|
-
assertIncludes('extensions/completion/role-runner.ts', 'await loadCompletionDataForReminder(params.root);');
|
|
28
27
|
assertIncludes('extensions/completion/role-runner.ts', 'const systemPromptTemp = await writeTempFile(params.root, "pi-completion-role-", agent.systemPrompt);');
|
|
29
28
|
assertIncludes('extensions/completion/role-runner.ts', 'const reportFields = parseReportFields(output);');
|
|
30
29
|
assertIncludes('extensions/completion/role-runner.ts', 'const transcription = exitCode === 0 ? await transcribeRoleOutput(params.role, params.root, output, reportFields) : undefined;');
|
|
@@ -83,7 +83,6 @@ assertIncludes('extensions/completion/prompt-surfaces.ts', '`- task_type: ${deps
|
|
|
83
83
|
assertIncludes('extensions/completion/prompt-surfaces.ts', '`- evaluation_profile: ${deps.currentEvaluationProfile(snapshot) ?? "(missing)"}`');
|
|
84
84
|
assertIncludes('extensions/completion/prompt-surfaces.ts', 'Canonical evaluation handoff for ${role}:');
|
|
85
85
|
assertIncludes('extensions/completion/index.ts', 'buildEvaluationRoleReminderText(snapshot, nextRole)');
|
|
86
|
-
assertIncludes('extensions/completion/index.ts', 'import { parseFirstNumber, parseYesNo } from "./transcription";');
|
|
87
86
|
assertIncludes('extensions/completion/role-runner.ts', 'import { parseReportFields, transcribeRoleOutput, type TranscriptionResult } from "./transcription";');
|
|
88
87
|
assertIncludes('extensions/completion/transcription.ts', 'roleReporting.transcribeCanonicalRoleReport');
|
|
89
88
|
assertIncludes('extensions/completion/role-reporting.js', 'Missing Rubric heading for ${role}.');
|