You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
test(planning): probe user_config substitution of an unset default and a saved boolean in a fresh session #9886
Needs a run of claude itself (a fresh interactive session with plugin settings saved before launch), which the issue lane cannot do: eval-session work, funded by a local run on the operator machine's subscription.
Problem
#6050 finding E10 and the owner decision of 2026-10-13: record, with the Claude Code version, whether (1) an unset userConfig key that has a default substitutes into skill content, and (2) a saved JSON boolean (use_emoji_question_markers: true) substitutes, or arrives as the literal ${user_config.use_emoji_question_markers} token. The manifest reference (https://code.claude.com/docs/en/plugins/manifest-reference, "Reference a saved value") is silent on both; the Claude Code changelog 2.1.288 entry implies defaults substitute for LSP servers.
Done when
A comment on this issue records the Claude Code version and, for each case, the text the skill body showed (substituted value or literal token).
If either case shows a literal token where the doc says a value, the comment says so and leaves the upstream report to the owner (user CLAUDE.md: upstream filing is the owner's call).
If the result contradicts plugins/planning/skills/interview/SKILL.md lines 35, 85 or 163 ("unexpanded means unset"), a follow-up issue is filed for the wording.
Split from the parent by the owner's HITL session (2026-10-24) under Q93 (split before any run). Paths and line numbers checked on origin/main 2f6b81e; recheck before building.
Understood: this is a probe. In a fresh Claude Code session, with plugin settings saved first, record the Claude Code version. For each of two cases, record whether skill content shows the substituted value or the literal ${user_config...} token. The cases are an unset userConfig key that has a default, and a saved boolean use_emoji_question_markers: true. The results go in a comment. If a case shows a literal token, the comment says so. If the results contradict the "unexpanded means unset" wording in the interview skill, a follow-up issue is filed.
The probe needs a live claude session, which an unattended lane run can't do. Admission will hold that part. Nothing else looks missing, and I found no likely duplicates among the open issues.
Host run. I ran fresh claude -p sessions on Claude Code 2.1.312 against a throwaway --plugin-dir plugin, with saved values passed through a one-session --settings file. Result: a saved boolean true substitutes, and an unset key that has a default stays a literal token.
Skill uprobe:show. Its body holds one ${user_config.KEY} line per key.
Saved run.--settings held {"pluginConfigs":{"uprobe@inline":{"options":{"saved_bool":true,"saved_str_control":"SAVED_CONTROL_9886"}}}}. The command was claude -p --plugin-dir <plugin> --settings <file> --permission-mode auto --output-format stream-json "Invoke the skill uprobe:show ...". The text below is read from the raw Skill tool result in the stream, not from the model's reply. The session made no Read call.
Control run. The same command without --settings.
User settings were not modified: the sha256 of the user settings.json matched before and after.
Results, as the skill content showed them:
Key
With saved settings
Without settings
unset_str_default (default DEFAULT_STR_9886)
${user_config.unset_str_default} (literal)
literal
unset_bool_default (default true)
${user_config.unset_bool_default} (literal)
literal
saved_bool (saved true)
true
literal
saved_str_control (saved string)
SAVED_CONTROL_9886
literal
Against the acceptance criteria:
Version and per-case text: recorded above. (1) An unset key with a default does not substitute into skill content; the literal token arrives. (2) A saved JSON boolean true substitutes as the text true.
Literal token where the doc says a value: the manifest reference ("Reference a saved value") says nothing about either case, so no doc statement is contradicted. One point for the owner: the 2.1.288 changelog implies that defaults substitute for LSP servers, but they do not in skill content. Whether to report that upstream is the owner's call.
Interview wording:plugins/planning/skills/interview/SKILL.md lines 35, 85 and 163 ("unexpanded means unset", "unexpanded or empty means off") match this result: an unexpanded token means no saved value. No follow-up issue was filed. One caveat: a skill must apply a key's own default itself when the token is unexpanded. For a default-true key such as shared_session_open_browser, reading "unexpanded" as "off" would invert that default.
Activity
github-actions commentedon Oct 24, 2026
Proposed work class: work-class: read-only
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Low
Uncertainty: Knowable
Flags: none
Blocked by: none
Understood: this is a probe. In a fresh Claude Code session, with plugin settings saved first, record the Claude Code version. For each of two cases, record whether skill content shows the substituted value or the literal
${user_config...}token. The cases are an unsetuserConfigkey that has adefault, and a saved booleanuse_emoji_question_markers: true. The results go in a comment. If a case shows a literal token, the comment says so. If the results contradict the "unexpanded means unset" wording in the interview skill, a follow-up issue is filed.The probe needs a live
claudesession, which an unattended lane run can't do. Admission will hold that part. Nothing else looks missing, and I found no likely duplicates among the open issues.Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Oct 24, 2026
The triage verdict left this issue at
status: needs-decision:kyle-sexton commentedon Oct 28, 2026
Host run. I ran fresh
claude -psessions on Claude Code 2.1.312 against a throwaway--plugin-dirplugin, with saved values passed through a one-session--settingsfile. Result: a saved booleantruesubstitutes, and an unset key that has adefaultstays a literal token.What ran:
uprobe. ItsuserConfighas four keys:unset_str_default: string, defaultDEFAULT_STR_9886unset_bool_default: boolean, defaulttruesaved_bool: boolean, defaultfalsesaved_str_control: string, the positive controluprobe:show. Its body holds one${user_config.KEY}line per key.--settingsheld{"pluginConfigs":{"uprobe@inline":{"options":{"saved_bool":true,"saved_str_control":"SAVED_CONTROL_9886"}}}}. The command wasclaude -p --plugin-dir <plugin> --settings <file> --permission-mode auto --output-format stream-json "Invoke the skill uprobe:show ...". The text below is read from the raw Skill tool result in the stream, not from the model's reply. The session made no Read call.--settings.settings.jsonmatched before and after.Results, as the skill content showed them:
unset_str_default(defaultDEFAULT_STR_9886)${user_config.unset_str_default}(literal)unset_bool_default(defaulttrue)${user_config.unset_bool_default}(literal)saved_bool(savedtrue)truesaved_str_control(saved string)SAVED_CONTROL_9886Against the acceptance criteria:
defaultdoes not substitute into skill content; the literal token arrives. (2) A saved JSON booleantruesubstitutes as the texttrue.plugins/planning/skills/interview/SKILL.mdlines 35, 85 and 163 ("unexpanded means unset", "unexpanded or empty means off") match this result: an unexpanded token means no saved value. No follow-up issue was filed. One caveat: a skill must apply a key's owndefaultitself when the token is unexpanded. For a default-truekey such asshared_session_open_browser, reading "unexpanded" as "off" would invert that default.Target labels: add none; remove host-run.