Skip to content

Commit 8c03b38

Browse files
askalfactions-user
andauthored
auto-rebake: template drift detected 2026-06-24 (#568)
* auto-rebake: template drift detected 2026-06-24T06:27Z (v4.8.93) * fix(template): preserve interactive-only tools across headless rebakes The auto-rebake for CC v2.1.187 dropped AskUserQuestion, EnterPlanMode and ExitPlanMode from the bundled template, breaking buildCCRequest's advertise-respects-client contract (test tool-advertise-respects-client.mjs). Root cause: the bake captures CC headlessly (claude --print -p hi), and CC v2.1.187 stopped advertising these plan-mode/clarification tools in --print mode, so a fresh capture no longer carries them. buildCCRequest advertises only the intersection of the client's declared tools and the template, so a full CC client that declared AskUserQuestion no longer had it advertised. - Restore the 3 tools in src/cc-template-data.json (bundle is a superset). - Add INTERACTIVE_ONLY_TOOLS in src/cc-template.ts and preserve them from the previous bundle in scripts/capture-and-bake.mjs, mirroring the existing win32-only PowerShell/Glob/Grep preservation, so future headless rebakes don't re-drop them. - Add test/template-interactive-tools.mjs to guard the superset invariant. Ref: ticket 00MQRQOIFUC34EDD3BF332C80F --------- Co-authored-by: cc-drift-template-watch[bot] <actions@github.com>
1 parent b392bce commit 8c03b38

6 files changed

Lines changed: 107 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ checklist.
1111

1212
## [Unreleased]
1313

14+
## [4.8.93] - 2026-06-24
15+
16+
- **Template rebake (v2.1.187)** — re-captured `src/cc-template-data.json` after cc-drift-template-watch detected drift against a live CC capture.
17+
- **Fix — preserve interactive-only tools across headless rebakes** — the bake captures CC headlessly (`claude --print -p hi`), and CC v2.1.187 stopped advertising `AskUserQuestion` / `EnterPlanMode` / `ExitPlanMode` in `--print` mode, so the auto-rebake dropped them from the bundled template. Because `buildCCRequest` advertises only the intersection of the client's declared tools and the template, a full CC client that declared `AskUserQuestion` no longer had it advertised (the advertise-respects-client contract). The bake now preserves `INTERACTIVE_ONLY_TOOLS` from the previous bundle — mirroring the existing win32-only `PowerShell`/`Glob`/`Grep` preservation — so the bundled template stays a superset. Added `test/template-interactive-tools.mjs` to guard the invariant.
1418
## [4.8.92] - 2026-06-23
1519

1620
- **CC drift patch** — `SUPPORTED_CC_RANGE.maxTested` bumped `2.1.186` → `2.1.187` for CC v2.1.187. Auto-drafted by `cc-drift-watch.yml`. Template re-capture, if needed, is auto-handled by `cc-drift-template-watch.yml`.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@askalf/dario",
3-
"version": "4.8.92",
3+
"version": "4.8.93",
44
"description": "Use your Claude Pro/Max subscription in any tool — Cursor, Cline, Aider, the Agent SDK, your scripts — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint.",
55
"type": "module",
66
"bin": {

scripts/capture-and-bake.mjs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import { fileURLToPath } from 'node:url';
4040

4141
import { captureLiveTemplateAsync, findInstalledCC } from '../dist/live-fingerprint.js';
4242
import { scrubTemplate, findUserPathHits } from '../dist/scrub-template.js';
43-
import { PLATFORM_ONLY_TOOLS } from '../dist/cc-template.js';
43+
import { PLATFORM_ONLY_TOOLS, INTERACTIVE_ONLY_TOOLS } from '../dist/cc-template.js';
4444
import { computeDrift, formatDriftReport, interpretDrift, formatDriftSummary, stripModelConditionalBetas } from './drift-report.mjs';
4545

4646
const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -120,6 +120,22 @@ if (preservedOtherPlatTools.length > 0) {
120120
// tools insert at their natural position rather than appending at the end.
121121
scrubbed.tools = [...scrubbed.tools, ...preservedOtherPlatTools].sort((a, b) => a.name.localeCompare(b.name));
122122
}
123+
124+
// Preserve interactive-only tools from the previous bundle. The capture spawns
125+
// CC headlessly (`claude --print -p hi`), and CC v2.1.187 stopped advertising
126+
// AskUserQuestion / EnterPlanMode / ExitPlanMode in --print mode — so a fresh
127+
// headless capture drops them even though every real interactive CC client still
128+
// sends them. Like the platform-tool preservation above, re-add them from the
129+
// previous bundle so the bundled JSON stays a superset; dropping them broke
130+
// buildCCRequest's advertise-respects-client contract (v4.8.93). Sorted back in
131+
// alphabetically to match CC's wire order.
132+
const preservedInteractiveTools = (prev.tools || []).filter(
133+
(t) => INTERACTIVE_ONLY_TOOLS.has(t.name) && !scrubbed.tools.some((s) => s.name === t.name),
134+
);
135+
if (preservedInteractiveTools.length > 0) {
136+
log(`preserved ${preservedInteractiveTools.length} interactive-only tool${preservedInteractiveTools.length === 1 ? '' : 's'} from previous bundle (headless capture omits them): ${preservedInteractiveTools.map((t) => t.name).join(', ')}`);
137+
scrubbed.tools = [...scrubbed.tools, ...preservedInteractiveTools].sort((a, b) => a.name.localeCompare(b.name));
138+
}
123139
log(`previous baked template: CC v${prev._version} captured ${prev._captured}, ${prev.tools.length} tools, ${prev.system_prompt.length} char system prompt`);
124140

125141
// ── --check mode: diff and exit; do not write ────────────────────────

src/cc-template-data.json

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"_version": "2.1.186",
3-
"_captured": "2026-06-23T05:37:45.965Z",
2+
"_version": "2.1.187",
3+
"_captured": "2026-06-24T06:27:30.671Z",
44
"_source": "bundled",
55
"_schemaVersion": 3,
66
"agent_identity": "You are a Claude agent, built on Anthropic's Claude Agent SDK.",
@@ -1269,16 +1269,13 @@
12691269
],
12701270
"tool_names": [
12711271
"Agent",
1272-
"AskUserQuestion",
12731272
"Bash",
12741273
"CronCreate",
12751274
"CronDelete",
12761275
"CronList",
12771276
"DesignSync",
12781277
"Edit",
1279-
"EnterPlanMode",
12801278
"EnterWorktree",
1281-
"ExitPlanMode",
12821279
"ExitWorktree",
12831280
"Monitor",
12841281
"NotebookEdit",
@@ -1324,7 +1321,7 @@
13241321
"anthropic_beta": "claude-code-20250219,interleaved-thinking-2025-05-14,thinking-token-count-2026-05-13,context-management-2025-06-27,prompt-caching-scope-2026-01-05,mid-conversation-system-2026-04-07,advisor-tool-2026-03-01,effort-2025-11-24",
13251322
"header_values": {
13261323
"accept": "application/json",
1327-
"user-agent": "claude-cli/2.1.186 (external, sdk-cli)",
1324+
"user-agent": "claude-cli/2.1.187 (external, sdk-cli)",
13281325
"x-stainless-arch": "x64",
13291326
"x-stainless-lang": "js",
13301327
"x-stainless-os": "Linux",
@@ -1349,5 +1346,5 @@
13491346
"output_config",
13501347
"stream"
13511348
],
1352-
"_supportedMaxTested": "2.1.186"
1349+
"_supportedMaxTested": "2.1.187"
13531350
}

src/cc-template.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,28 @@ export function filterToolsForPlatform<T extends { name: string }>(
5151
});
5252
}
5353

54+
/**
55+
* Tools CC only advertises in an INTERACTIVE session. The bake captures CC
56+
* headlessly (`claude --print -p hi`, see live-fingerprint.ts), and CC v2.1.187
57+
* dropped these plan-mode / clarification tools in `--print` mode — so a fresh
58+
* headless capture no longer carries them even though every real interactive CC
59+
* client still advertises them. Like PLATFORM_ONLY_TOOLS, the bundled template
60+
* must stay a SUPERSET: register them here so a headless auto-rebake preserves
61+
* them from the previous bundle instead of dropping them. Dropping them broke
62+
* buildCCRequest's advertise-respects-client contract (the v4.8.93 regression):
63+
* dario advertises only the intersection of the client's declared tools and this
64+
* template, so a missing AskUserQuestion meant dario could not advertise it even
65+
* when a full CC client declared it. Unlike PLATFORM_ONLY_TOOLS these are NOT
66+
* platform-filtered — they stay in CC_TOOL_DEFINITIONS on every host so a client
67+
* that declares them is always honored. Add new interactive-only tools here as
68+
* CC adds them.
69+
*/
70+
export const INTERACTIVE_ONLY_TOOLS: Set<string> = new Set([
71+
'AskUserQuestion',
72+
'EnterPlanMode',
73+
'ExitPlanMode',
74+
]);
75+
5476
/** CC's exact tool definitions for the current platform — filtered from the bundled union. */
5577
export const CC_TOOL_DEFINITIONS = filterToolsForPlatform(TEMPLATE.tools, process.platform);
5678

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Regression: the bundled CC template must always carry the interactive-only
4+
* tools (AskUserQuestion, EnterPlanMode, ExitPlanMode).
5+
*
6+
* Bug (v4.8.93): the bake captures CC headlessly (`claude --print -p hi`, see
7+
* live-fingerprint.ts). CC v2.1.187 stopped advertising the plan-mode /
8+
* clarification tools in `--print` mode, so an auto-rebake dropped them from
9+
* src/cc-template-data.json. Because buildCCRequest advertises only the
10+
* INTERSECTION of the client's declared tools and the bundled template, a full
11+
* CC client that declared AskUserQuestion no longer had it advertised — the
12+
* "advertise-respects-client" contract broke (tool-advertise-respects-client.mjs
13+
* caught it). These tools are not platform-scoped, so they must remain in the
14+
* template (and in CC_TOOL_DEFINITIONS) on EVERY host, the same way the bake
15+
* preserves win32-only PowerShell/Glob/Grep from the previous bundle.
16+
*
17+
* Fix: scripts/capture-and-bake.mjs preserves INTERACTIVE_ONLY_TOOLS from the
18+
* previous bundle on every bake; this test guards the resulting invariant so a
19+
* future headless bake (or manual edit) can't silently re-drop them.
20+
*
21+
* In-process — no proxy / OAuth / upstream.
22+
*/
23+
24+
import { CC_TEMPLATE, CC_TOOL_DEFINITIONS, INTERACTIVE_ONLY_TOOLS } from '../dist/cc-template.js';
25+
26+
let pass = 0, fail = 0;
27+
function check(label, cond) {
28+
if (cond) { pass++; console.log(` ✅ ${label}`); }
29+
else { fail++; console.log(` ❌ ${label}`); }
30+
}
31+
function header(name) { console.log(`\n${'='.repeat(70)}\n ${name}\n${'='.repeat(70)}`); }
32+
33+
header('bundled template carries every interactive-only tool');
34+
{
35+
check('INTERACTIVE_ONLY_TOOLS is non-empty', INTERACTIVE_ONLY_TOOLS.size > 0);
36+
37+
const templateNames = new Set((CC_TEMPLATE.tools || []).map((t) => t.name));
38+
for (const name of INTERACTIVE_ONLY_TOOLS) {
39+
check(`template tools[] contains ${name}`, templateNames.has(name));
40+
const def = (CC_TEMPLATE.tools || []).find((t) => t.name === name);
41+
check(`${name} has a non-empty description`,
42+
!!def && typeof def.description === 'string' && def.description.length > 0);
43+
check(`${name} has an input_schema`, !!def && typeof def.input_schema === 'object' && def.input_schema !== null);
44+
}
45+
}
46+
47+
header('interactive-only tools are NOT platform-filtered (present on every host)');
48+
{
49+
// CC_TOOL_DEFINITIONS is the current platform's filtered view of the bundle.
50+
// Interactive tools must survive that filter everywhere — unlike PowerShell/
51+
// Glob/Grep, they are not registered in PLATFORM_ONLY_TOOLS.
52+
const ccNames = new Set(CC_TOOL_DEFINITIONS.map((t) => t.name));
53+
for (const name of INTERACTIVE_ONLY_TOOLS) {
54+
check(`CC_TOOL_DEFINITIONS (platform ${process.platform}) contains ${name}`, ccNames.has(name));
55+
}
56+
}
57+
58+
console.log(`\ntemplate-interactive-tools: ${pass} passed, ${fail} failed`);
59+
if (fail > 0) process.exit(1);

0 commit comments

Comments
 (0)