Skip to content

feat(lib): record written_against and per-key provenance in the shared setup writer #9809

Description

@kyle-sexton

Refs #6594. Slice 2 of 4. Blocked by #9801 (slice 1, the owner doc). Runs in parallel with slice 4.

Problem

No shared setup writer can tell a team-chosen value from an inherited default, so when a plugin changes a recommended default, apply cannot know whether to update the stored value (#6594 Problem 5). lib/setup-apply.mjs on origin/main validates and writes <home>/<plugin>.yaml but records neither the plugin version the file was written against nor a per-value source. Only developer-experience records provenance, and only for its prose file (plugins/developer-experience/skills/setup/reference/conventions-file.md, written_against front matter and per-section source=chosen|default markers).

Fix

In lib/setup-apply.mjs (and the generated per-plugin copies through scripts/sync-shared-copies.sh):

  • Write a top-level written_against: <plugin>@<version> when the writer writes the file, read from the plugin's .claude-plugin/plugin.json.
  • Record per key whether the team chose it or it was inherited, in a separate top-level provenance: map (<key>: chosen for a value the operator set or confirmed, <key>: default for one filled at the plugin default). Values stay flat where they are today, so no existing reader (lib/config-cascade.mjs, lib/parse-concern-value.sh, scripts/check-convention-yaml.sh, the plugins' JSON Schemas) changes what it parses; allow the two new top-level keys where the writer validates. Keep reading a file without provenance (treat its values as chosen, report INFO once).
  • --check: list each default value whose plugin default changed since written_against (INFO), and each chosen value whose default changed, with the old and new default (WARN, never rewritten).
  • Writing with --yes: update default values to the new plugin default and print each change; never change a chosen value.
  • Document the shape in the ## Provenance section of docs/conventions/setup-lifecycle/README.md.

Prose files keep developer-experience's per-section markers; this slice does not change them.

Done when

  • bash lib/setup-apply.test.sh exits 0, with new cases for: written_against written on create; a default value updated after a default change; a chosen value kept and reported WARN with old and new defaults; a file without provenance read with one INFO line
  • bash scripts/sync-shared-copies.sh --check exits 0
  • bash lib/config-cascade.test.sh and bash lib/parse-concern-value.test.sh exit 0, with one new case each reading a file that carries written_against and provenance: and returning the same value as the file without them
  • grep -c 'written_against' docs/conventions/setup-lifecycle/README.md prints 1 or more
  • ci-status is green on the PR head

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 24, 2026
  2. github-actions commented on Oct 24, 2026

    @github-actions
    Contributor

    The triage sweep dispatched intake triage for this issue (attempt 2 of 2).

  3. github-actions commented on Oct 24, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: scoped
    Basis: automated intake triage; the lanes App applied this class.

    Size: Medium
    Complexity: Medium
    Uncertainty: Known
    Flags: none
    Blocked by: none

    Understood: extend the shared setup writer so it writes a top-level written_against: <plugin>@<version> and a separate provenance: map (chosen/default per key). It also adds --check reporting and --yes updates for default drift, and documents the shape in the setup-lifecycle README. The done-when items are specific and checkable. The issue names #9801 as a blocker, but it isn't in the open-issues list I was given, so I treated it as not blocking. No likely duplicates found.

    Automated triage, applied by the lanes App.

  4. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 24, 2026
  5. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    status: needs-decisionAwaiting a human or maintainer judgment call.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 24, 2026
  6. melodic-automation-lanes commented on Oct 24, 2026

    @melodic-automation-lanes
    Contributor

    Not admitted to the issue lane: a Feature needs an open parent issue a listed human filed that awaits no decision. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).

  7. kyle-sexton commented on Oct 26, 2026

    @kyle-sexton
    MemberAuthor

    Released for re-triage under the owner's 2026-10-26 rule: a person is involved only for "1. A change in original intent/vision 2. Something comes up during implementation ... that alters intent/vision or the primary design 3. If there is a HIGH/CRITICAL security issue". None applies here, so the hold label came off and intake triage runs again now.

    To hold this issue again, add needs-human (or status: needs-decision) and name which of the three applies.

  8. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    status: needs-decisionAwaiting a human or maintainer judgment call.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 26, 2026
  9. melodic-automation-lanes commented on Oct 26, 2026

    @melodic-automation-lanes
    Contributor

    The latest triage verdict holds nothing: admission moved the issue to status: confirmed; its comment says why.

  10. kyle-sexton commented on Oct 27, 2026

    @kyle-sexton
    MemberAuthor

    Released for re-triage under the owner's 2026-10-26 rule: a person is involved only for "1. A change in original intent/vision 2. Something comes up during implementation ... that alters intent/vision or the primary design 3. If there is a HIGH/CRITICAL security issue". None applies here, so the hold label came off and intake triage runs again now.

    To hold this issue again, add needs-human (or status: needs-decision) and name which of the three applies.

  11. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    on Oct 27, 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.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Fields

    No fields configured for Feature.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions