Skip to content

test(planning): probe user_config substitution of an unset default and a saved boolean in a fresh session #9886

Description

@kyle-sexton

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.

Activity

  1. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 24, 2026
  2. added theissue type on Oct 24, 2026
  3. github-actions commented on Oct 24, 2026

    @github-actions
    Contributor

    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 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.

    Automated triage, applied by the lanes App.

  4. melodic-automation-lanes commented on Oct 24, 2026

    @melodic-automation-lanes
    Contributor

    The triage verdict left this issue at status: needs-decision:

    • held by needs-human
    • no lanes App verdict comment shows whether an earlier verdict was flagged
  5. added
    host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 27, 2026
  6. kyle-sexton commented on Oct 28, 2026

    @kyle-sexton
    MemberAuthor

    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.

    What ran:

    • Test plugin uprobe. Its userConfig has four keys:
      • unset_str_default: string, default DEFAULT_STR_9886
      • unset_bool_default: boolean, default true
      • saved_bool: boolean, default false
      • saved_str_control: string, the positive control
    • 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:

    1. 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.
    2. 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.
    3. 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.

    Target labels: add none; remove host-run.

  7. removed
    host-runNeeds an unattended run on a host; the host runner takes it, not a person or the issue lane.
    on Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: mediumReal value, no hard deadline; normal backlog flow.status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.status: needs-decisionAwaiting a human or maintainer judgment call.work-class: read-onlyAudits, research, reports. No repository mutation; tracker and queue writes only.

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions