Skip to content

chore(guardrails): drop the convention resolver's one-release .claude/source-control.md reads #13472

Description

@kyle-sexton

Refs #9737

Outcome

The commit-subject and PR-title enforcement resolver no longer reads <repo>/.claude/source-control.md. Two rungs read it today, both for one release: the ## convention_source pointer and the ## <key> H2. The resolver is lib/resolve-convention-pattern.sh and its synced copy plugins/guardrails/hooks/resolve-convention-pattern.sh (scripts/shared-copies.txt:19), and block-convention-violation.sh reads the same file itself.

Both readers keep the well-known docs/conventions/source-control/commit-convention.yml rung, tracked file only. That follows the 2026-11-03 decision on #9737: eight repositories get subject enforcement only from that file. The rung must work on its own, with no legacy markdown file present.

The YAML reader landed in guardrails 0.61.0 (plugins/guardrails/CHANGELOG.md:525-531), and 1.3.5 has shipped since. None of those eight repositories tracks a .claude/source-control.md: the contents API returned 404 for each on 2026-11-05 (checked by the drafting session; not re-run at filing). So dropping the two markdown rungs changes enforcement in none of them. The user-global ~/.claude/source-control.md is a drafting input that the resolver never reads, and that stays as it is.

Change

  • lib/resolve-convention-pattern.sh:
    • Remove LEGACY_MD_REL/TEAM_FILE (:95, :142), the convention_source pointer read inside resolve_legacy (:430), and the H2 fallback in team_value (:506-507). Remove h2_value (:155-175), which has no other caller.
    • Keep the well-known rung (WELL_KNOWN_NEUTRAL, git-tracked only) and its checks.
    • Update the header (:14-26) and the diagnostics that mention falling back to the markdown H2.
  • Regenerate the guardrails copy with scripts/sync-shared-copies.sh.
  • plugins/guardrails/hooks/block-convention-violation.sh:
    • Remove conv_pointer (:172-198), its call and the CONV_POINTER append (:210-211), and the .claude/source-control.md entry of CONV_DEPS (:206).
    • Keep the commit-convention.yml entry.
    • Update the header comment (:11).
  • plugins/guardrails/git-hooks/commit-msg-convention.sh:12 comment, plugins/guardrails/README.md:105,145,1764, and the block_convention_gate_enabled description at plugins/guardrails/.claude-plugin/plugin.json:166. Keep the README row and plugin.json in step.
  • docs/contracts/commit-convention/README.md:17,29,50-53,96, the convention_source section (:86-130), and 'for one release' wherever it describes the commit-convention.yml rung, which stays. Check scripts/validate-plugin-contracts.test.sh:680 before renaming that heading.
  • Reword the resolver diagnostics at :455-482 that name convention_source.
  • Tests:
    • Convert the fixtures that set a pattern through .claude/source-control.md to docs/conventions/source-control.yaml or the folder-form file. The files are lib/resolve-convention-pattern.test.sh, plugins/guardrails/hooks/block-convention-violation.test.sh, plugins/guardrails/git-hooks/commit-msg-convention.test.sh and plugins/guardrails/git-hooks/lefthook-remote.test.sh.
    • Replace the legacy-rung cases with one case asserting that a tracked .claude/source-control.md H2 pattern is not enforced.
  • Add a guardrails changelog fragment. Repeat the 0.61.0 note: a commit-msg-convention copy installed before 0.61.0 enforces nothing until /guardrails:setup apply install-git-hooks refreshes it.

Done when

  • git grep -nP '(?<!~/)(?<!HOME/)(?<!\}/)\.claude/source-control\.md' -- lib plugins/guardrails docs/contracts/commit-convention ':!*CHANGELOG*' ':!*.test.sh' prints nothing (on origin/main it prints 18 lines in 7 files).
  • git grep -n 'readonly WELL_KNOWN_NEUTRAL="docs/conventions/source-control/commit-convention.yml"' -- lib/resolve-convention-pattern.sh prints one line.
  • git grep -n 'docs/conventions/source-control/commit-convention.yml' -- plugins/guardrails/hooks/block-convention-violation.sh prints at least one line.
  • grep -n '^## \[1.1.0\]' plugins/guardrails/CHANGELOG.md prints one line (a release after the 0.61.0 YAML reader).
  • bash scripts/sync-shared-copies.sh --check exits 0.
  • bash scripts/run-test-file.sh lib/resolve-convention-pattern.test.sh exits 0.
  • bash scripts/run-test-file.sh plugins/guardrails/hooks/block-convention-violation.test.sh exits 0.
  • bash scripts/run-test-file.sh plugins/guardrails/git-hooks/commit-msg-convention.test.sh exits 0.
  • bash scripts/run-test-file.sh plugins/guardrails/git-hooks/lefthook-remote.test.sh exits 0.
  • scripts/check-changelog-fragments.sh --check-required origin/main exits 0.

Activity

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

    @github-actions
    Contributor

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

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

    Understood: remove the resolver's two one-release reads of .claude/source-control.md (the convention_source pointer and the H2 fallback) from lib/resolve-convention-pattern.sh and its synced copy. Do the same in block-convention-violation.sh, and keep the commit-convention.yml rung. Docs, the plugin.json description, tests and a changelog fragment follow. The scope and done-when checks are exact.

    Possible mismatch to check when picking this up: the done-when item expects a ## [1.1.0] changelog heading, while the body says 1.3.5 has already shipped.

    This is a child of #9737, not a duplicate. #13473, #13471 and #13474 cover other plugins' config reads.

    Automated triage, applied by the lanes App.

  3. 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 Nov 5, 2026
  4. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.
    on Nov 5, 2026
  5. added
    admission-deferredAdmitted but waiting for WIP room; the hourly work-unblock sweep labels it agent-ready.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    and removed
    admission-deferredAdmitted but waiting for WIP room; the hourly work-unblock sweep labels it agent-ready.
    on Nov 5, 2026
  6. github-actions commented on Nov 5, 2026

    @github-actions
    Contributor
    No description provided.
  7. github-actions commented on Nov 5, 2026

    @github-actions
    Contributor
    No description provided.
  8. removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Nov 5, 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.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.

    Type

    Fields

    Work status

    agent-ready

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions