Skip to content

refactor(attribution): move the .claude/attribution.json settings to docs/conventions/attribution.yaml #9729

Closed
3 of 3 issues completed

Description

@kyle-sexton

Parent

Refs #5906

Depends on

  • none: on the frontier now

Outcome

The attribution settings this repository keeps in .claude/attribution.json resolve from docs/conventions/attribution.yaml,
validated by a schema the plugin ships. The old location is read only when the YAML is absent, for one release.
The setup skill, if the plugin has one, writes the YAML.

Decisions

  • ADR 0064 Decision 1: a plugin's team settings live in one docs/conventions/<concern>.yaml, validated by a
    JSON Schema at plugins/<plugin>/schemas/<concern>.schema.json (Decision 6), checked in CI by
    scripts/check-convention-yaml.sh (Decision 7). Script readers use the shared reader lib/parse-concern-value.sh.
  • ADR 0075: layers are plugin default < userConfig < team <home>/<concern>.yaml < personal
    <home>/<concern>.local.<ext>; every resolver reports the layer that supplied each value.
  • Migrate per-skill .claude config files to userConfig, one conventions doc, or the cascade (ADR 0018) #5906 (comment 2026-10-04): each reader keeps reading the old file for one release when the new file is
    absent, and this repository keeps its old file until the cleanup slice.

Key interfaces

  • The attribution audit's config reader and reference.

Done when

  • docs/conventions/attribution.yaml carries every value of .claude/attribution.json and scripts/check-convention-yaml.sh --check exits 0 against plugins/attribution/schemas/attribution.schema.json.
  • scripts/run-test-file.sh plugins/attribution/skills/audit/scripts/check-stamps.test.sh exits 0.
  • scripts/run-test-file.sh plugins/attribution/skills/audit/scripts/list-corpus.test.sh exits 0.
  • scripts/run-test-file.sh plugins/attribution/skills/audit/scripts/sweep-ledger.test.sh exits 0.
  • The reader's tests include: the YAML wins when both exist, the old location is read when the YAML is absent, and the resolver names the layer that supplied each value.
  • No skill body tells an agent to read or write the old location: git grep -n for it under plugins/attribution prints only compatibility-read code, its tests and changelog lines.
  • The PR body lists each migrated setting with its new home and schema.
  • scripts/check-changelog-fragments.sh --check-required origin/main exits 0.

Out of scope

Activity

  1. added theissue type on Oct 24, 2026
  2. added
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed on Oct 24, 2026
  3. melodic-automation-lanes commented on Oct 24, 2026

    @melodic-automation-lanes
    Contributor

    The work-resolve-issue run that agent-ready started failed or was cancelled before it reported, or it stopped or the token broker refused it because its workflow files differ from main's. work-unblock removed and added agent-ready back to start a fresh run on main's workflow files. It does this once per version of those files, so if this run fails the same way, a person looks at it.

  4. added
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 24, 2026
  5. melodic-automation-lanes commented on Oct 24, 2026

    @melodic-automation-lanes
    Contributor

    The work-resolve-issue lane stopped on its usage limit, not on this issue. It keeps agent-ready, and work-unblock starts it again after 2026-10-25T16:00:00Z.

    Run: https://github.com/melodic-software/claude-code-plugins/actions/runs/40140298272

  6. added
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 25, 2026
  7. 11 remaining items

  8. removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 28, 2026
  9. kyle-sexton commented on Oct 28, 2026

    @kyle-sexton
    MemberAuthor

    Re-triage. The owner restated on 2026-10-27 when an item stops for them:

    Signal me (a needs-human / needs-decision label, or a direct question) only for:

    1. A change to the original intent or vision.
    2. A finding during implementation (things don't always go to plan) that changes the intent, vision or primary design.
    3. A real HIGH/CRITICAL security or cost risk, as defined in section 3.

    Everything else moves through the factory floor on its own. [...] Any other stop is a defect to fix, not a reason to ask me.

    Design for change: reversing a direction later should touch a handful of files, not cascade into breakages or refactoring pain.

    Structural edit first: the poster files the three slices below as sub-issues of #9729, with their blocked-by edges, before any comment or label change. #9729 becomes their tracker. It closes when all three close and never takes agent-ready itself.

    Intent (the body's Outcome, unchanged): the attribution settings this repository keeps in .claude/attribution.json resolve from docs/conventions/attribution.yaml, validated by a schema the plugin ships. The old location is read only when the YAML is absent, for one release. The setup skill writes the YAML. Deleting this repository's old file stays out of scope (the cleanup slice under #5906).

    1. Why did the lane stop?
      Decided: the work is too large for one run, not unclear. The lane hit turn cap 75 twice (https://github.com/melodic-software/claude-code-plugins/actions/runs/40186537977 and https://github.com/melodic-software/claude-code-plugins/actions/runs/40190696088, both in the 2026-10-25 lane comments). Its two partial branches, work-resolve-issue/issue-9729-40186537977-1 and work-resolve-issue/issue-9729-40190696088-1, each touch 22 to 24 files with about 1,400 inserted lines (git diff --stat against their merge base with origin/main). Both mix the reader, the schema, the setup skill, its evals and the README in one change. No question for the owner is open, so needs-human comes off.
    2. How many call sites does the move touch?
      Decided: 4 runtime readers, 1 shared resolver, 1 writer, and 6 prose files. Basis:
      • Resolver: cfg_layers_init in plugins/attribution/skills/audit/scripts/lib.sh:38-45 lists .claude/attribution.json layers for every script.
      • Readers, each calling that resolver and then reading values with its own jq loop: check-stamps.sh:137 and :151 (2 keys, :175, :186); list-corpus.sh:126 and :146 (1 key, :156); score-golden.sh:102 and :108 (3 keys, :118-120); sweep-ledger.sh:124 and the inline loop at :137-138 (1 key). All under plugins/attribution/skills/audit/scripts/.
      • Writer: the setup skill's apply writes .claude/attribution.json (plugins/attribution/skills/setup/SKILL.md:37).
      • Prose naming the old file: plugins/attribution/README.md:88, plugins/attribution/retirements.yaml:14, plugins/attribution/skills/audit/SKILL.md:237, plugins/attribution/skills/audit/reference/source-fetch.md:145, plugins/attribution/skills/setup/SKILL.md:2,15,37,73,74, plugins/attribution/skills/setup/evals/evals.json:85-90.
      • Nothing exists yet at the new location: origin/main has no docs/conventions/attribution.yaml and no plugins/attribution/schemas/ (git ls-tree -r origin/main).
    3. Where does each setting have one owner?
      Decided: one value reader in lib.sh that reads both formats and names the layer behind each value, replacing the four per-script jq readers above. A later change of format or home then touches one file. The fallback is per file, not per key: for each layer, the YAML is read when it exists and the old JSON only when it does not, so one file owns each layer's values. Basis: the body's Outcome ("The old location is read only when the YAML is absent") and the precedent in plugins/ai-slop/skills/audit/scripts/detect.sh:224-233, which reads <home>/ai-slop.yaml and falls back to .claude/ai-slop.json only when the YAML is absent. The plugin's copies of the shared YAML readers come through scripts/shared-copies.txt (scripts/shared-copies.txt:1-4), as ai-slop's do.
    4. Why is the schema in the same slice as this repository's YAML?
      Decided: scripts/check-convention-yaml.sh treats a convention YAML with no schema as a finding (scripts/check-convention-yaml.sh:20-21) and finds the schema at plugins/<concern>/schemas/<concern>.schema.json (scripts/check-convention-yaml.sh:16). CI already runs it (.github/workflows/pr-require-checks.yml:675), so no slice edits a workflow and none needs Build: host session. The YAML lands only after slice 1, because before the reader exists it would be an unread second copy of every value.
    5. Split
      Decided: three slices. Basis: the body's own "Done when" lines, with no added scope. No slice is a deletion; that is the Migrate per-skill .claude config files to userConfig, one conventions doc, or the cascade (ADR 0018) #5906 cleanup slice.

    Slice 1: the attribution audit reads its settings through one reader, YAML first. Blocked by: none.
    Scope: lib.sh resolves each layer's YAML (<home>/attribution.yaml, <home>/attribution.local.yaml, per ADR 0075) and falls back to the old JSON file when the YAML is absent; one shared reader serves all four scripts, score-golden.sh included. No YAML is committed in this slice, so this repository still reads .claude/attribution.json and behavior is unchanged.

    • scripts/run-test-file.sh plugins/attribution/skills/audit/scripts/check-stamps.test.sh exits 0.
    • scripts/run-test-file.sh plugins/attribution/skills/audit/scripts/list-corpus.test.sh exits 0.
    • scripts/run-test-file.sh plugins/attribution/skills/audit/scripts/sweep-ledger.test.sh exits 0.
    • The reader's tests include: the YAML wins when both exist, the old location is read when the YAML is absent, and the resolver names the layer that supplied each value.
    • scripts/check-changelog-fragments.sh --check-required origin/main exits 0.

    Slice 2: this repository's attribution settings move to docs/conventions/attribution.yaml. Blocked by: slice 1.
    Scope: the plugin's schema and this repository's YAML, together. .claude/attribution.json stays in place.

    • docs/conventions/attribution.yaml carries every value of .claude/attribution.json and scripts/check-convention-yaml.sh --check exits 0 against plugins/attribution/schemas/attribution.schema.json.
    • The PR body lists each migrated setting with its new home and schema.
    • scripts/check-changelog-fragments.sh --check-required origin/main exits 0.

    Slice 3: the setup skill writes the YAML and no prose points at the old file. Blocked by: slice 1. It can run beside slice 2.
    Scope: the writer and every prose file listed in item 2 under plugins/attribution. docs/conventions/config-cascade/README.md:770 sits outside the grep below and is not part of this issue.

    • No skill body tells an agent to read or write the old location: git grep -n for it under plugins/attribution prints only compatibility-read code, its tests and changelog lines.
    • scripts/check-changelog-fragments.sh --check-required origin/main exits 0.

    All - [ ] lines above are the body's "Done when" lines, each placed in the slice that changes what it checks, wording unchanged; the changelog line repeats in each slice because each one is its own PR.

    Target labels: on #9729 remove needs-human and add no agent-ready; each sub-issue goes to intake, where its - [ ] lines admit it.

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

    @github-actions
    Contributor

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

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

    Understood: move the attribution settings from .claude/attribution.json to docs/conventions/attribution.yaml. A plugin-shipped schema validates it. The old file is read only when the YAML is absent, for one release. The setup skill writes the YAML.

    The work is too large for one change (about 4 readers, 1 resolver, 1 writer, 6 prose files). The earlier re-triage already splits it into three slices, so this issue acts as their tracker. Nothing is missing and no decision is open. Deleting the old file stays out of scope. No duplicates found.

    Automated triage, applied by the lanes App.

  12. removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 28, 2026
  13. 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.
    on Oct 28, 2026
  14. melodic-automation-lanes commented on Oct 28, 2026

    @melodic-automation-lanes
    Contributor

    Not admitted to the issue lane yet: sub-issue #10543 is open.

  15. github-actions commented on Oct 28, 2026

    @github-actions
    Contributor

    Intake triage did not triage this issue after 2 dispatches, so the sweep no longer dispatches it and labeled it needs-triage for a maintainer. Triage it by hand, and read the runs for why intake did not:

  16. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 28, 2026
  17. kyle-sexton commented on Oct 28, 2026

    @kyle-sexton
    MemberAuthor

    Closing as complete. Its three slices are closed as completed: #10538, #10540 and #10543, via #10542, #10555 and #10586. docs/conventions/attribution.yaml:11-13 on main carries both settings (excluded_paths, trigger_less_stamp_check), and plugins/attribution/schemas/attribution.schema.json validates them. The re-triage record said this issue closes when all three slices close. Deleting the old JSON file stays with #5906's cleanup slice.

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

    needs-triageNot yet classified. Floor until a type and one priority tier are set.priority: mediumReal value, no hard deadline; normal backlog flow.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.

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions