Claude Code applies SKILL.md effort: as output_config.effort; any change from the session baseline invalidates the prompt cache at BOTH scope boundaries (entry + exit, the latter often machine-fired via subagent-completion notification). The reporter's owned measurement confirms it: /gsd-progress (effort:low) in a medium session → cache_creation 63,404 (entry) + 18,589 (exit), while a no-effort skill shows none. ~76% of invocations paid in full. Fix (trek-e AC#2/AC#4): convertClaudeCommandToClaudeSkill no longer emits effort: into Claude-runtime skill frontmatter (src/runtime-artifact-conversion.cts + duplicated bin/install.js). normalizeClaudeSkillEffort removed (dead). The six declaring skills (plan-phase/execute-phase/autonomous/next/progress/stats) no longer carry effort. Source command files keep effort (input, used elsewhere); the separate agent-effort surface (#3160) is untouched. Tests: install-runtime-artifacts #769 block flipped to assert effort is ABSENT from installed SKILL.md + converter output (the AC#4 behavioral coverage). Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -392,16 +392,6 @@ function skillFrontmatterName(skillDirName) {
|
||||
return skillDirName;
|
||||
}
|
||||
|
||||
function normalizeClaudeSkillEffort(effort) {
|
||||
// #3039: `max` is rejected by Anthropic models when extended thinking is
|
||||
// disabled (400: output_config.effort 'max' is not supported when thinking
|
||||
// is disabled). The frontmatter is static at install time and the installer
|
||||
// cannot know whether thinking will be on or off at invocation. `high` is the
|
||||
// maximum value that works in both states on all supported models.
|
||||
if (effort === 'xhigh' || effort === 'max') return 'high';
|
||||
return effort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Qwen Code skills accept an optional numeric `priority` frontmatter field.
|
||||
* Per the Qwen skills spec (qwen-code/docs/users/features/skills.md, verified
|
||||
@@ -458,10 +448,13 @@ function convertClaudeCommandToClaudeSkill(content, skillName, runtime = null, c
|
||||
const description = extractFrontmatterField(frontmatter, 'description') || '';
|
||||
const argumentHint = extractFrontmatterField(frontmatter, 'argument-hint');
|
||||
const agent = extractFrontmatterField(frontmatter, 'agent');
|
||||
// #769: preserve context: and effort: from source command files so they
|
||||
// are emitted into the installed SKILL.md frontmatter unchanged.
|
||||
// #769: preserve context: from source command files so it is emitted into
|
||||
// the installed SKILL.md frontmatter unchanged. (#3151: effort: is no longer
|
||||
// emitted into skill frontmatter — a static effort value changes
|
||||
// output_config.effort on invocation and invalidates the caller's prompt
|
||||
// cache at both scope boundaries; the reporter's owned measurement confirms
|
||||
// the mechanism. The separate agent-effort surface is tracked by #3160.)
|
||||
const context = extractFrontmatterField(frontmatter, 'context');
|
||||
const effort = extractFrontmatterField(frontmatter, 'effort');
|
||||
|
||||
// Preserve allowed-tools as YAML multiline list (Claude native format)
|
||||
const toolsMatch = frontmatter.match(/^allowed-tools:\s*\n((?:\s+-\s+.+\n?)*)/m);
|
||||
@@ -498,12 +491,13 @@ function convertClaudeCommandToClaudeSkill(content, skillName, runtime = null, c
|
||||
}
|
||||
if (argumentHint) fm += `argument-hint: ${yamlQuote(argumentHint)}\n`;
|
||||
if (agent) fm += `agent: ${agent}\n`;
|
||||
// #769: emit context: and effort: when present so the runtime can honour
|
||||
// them natively (context: fork = isolated subagent window; effort: =
|
||||
// token-budget tier). Fields are Claude-specific; unknown frontmatter
|
||||
// fields are silently ignored by other runtimes (backward-compatible).
|
||||
// #769: emit context: when present so the runtime can honour it natively
|
||||
// (context: fork = isolated subagent window). Claude-specific; unknown
|
||||
// frontmatter fields are silently ignored by other runtimes (backward-compatible).
|
||||
// (#3151: effort: is intentionally NOT emitted into skill frontmatter — a
|
||||
// static effort value changes output_config.effort on invocation and
|
||||
// invalidates the caller's prompt cache at both scope boundaries.)
|
||||
if (context) fm += `context: ${context}\n`;
|
||||
if (effort) fm += `effort: ${normalizeClaudeSkillEffort(effort)}\n`;
|
||||
if (toolsBlock) fm += toolsBlock;
|
||||
fm += '---';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user