Skip to content

source-control: neutral tool-agnostic convention SSOT — author-directed reopen of #913 #1141

Description

@kyle-sexton

Parent

Source: handoff-inbox item 20260723-084404-source-control-convention-ssot-reopen (Finding F1 — HIGH feature, an author-directed REOPEN of the #913 decline). Read #913's full decline rationale first; if the reopen is rejected again, record the updated rationale in #913 so future audits stop resurfacing it.

What to build

A neutral, tool-agnostic convention SSOT for the layered source-control convention config — decoupling the team-tracked convention values from the .claude/source-control.md markdown-H2 grammar so enforcement (commit-msg hooks, CI) and drafting (any agent) can consume one file.

Why the recorded decline is reopened (all four grounds in the item body): the plugin author explicitly directed it this session ("we need a solution that reduces coupling… use a SSOT… I am the author"); a real consuming machine holds three hand-synced byte-identical copies of one regex; AGENTS.md became an LF-stewarded cross-agent pointer standard while no ecosystem tool offers one config consumed by both enforcement and drafting; and plugin-audit recurring-concerns.md #4/#5 already encode the opposite of #913.

Design constraints (item body is the full brief — this is the contract):

  • Repo/user/machine-agnostic; nothing hardcodes a consuming repo's layout or assumes a machine-local hook, CI, or AGENTS.md exists — each is an optional consumer, never a prerequisite.
  • Author-stated principle: every implementation detail is configurable (neutral-file path repo-scoped, any well-known search list, regex dialect declaration, all lifted to config or justified as contract). Sweep for baked-in constants before shipping.
  • New optional repo-declared pointer (e.g. convention_source) or resolver search path with the neutral file ahead of .claude/source-control.md; default stays .claude/source-control.md — full back-compat, zero action for existing consumers.
  • Neutral format: flat-scalar YAML (subject_pattern, pr_title_pattern, optional flat pr_body_required_sections, optional dialect: defaulting posix-ere). The Conventional Commits keyword works there exactly as in the markdown layer. One-sed extraction must hold.
  • Steelman the incumbent before treating replacement as settled (markdown-H2 was chosen so config doubles as human-readable doc): test that YAML # comments + a prose pointer doc cover those purposes; if not, frontmatter-hybrid re-enters as the compromise.
  • Enforcement contract unchanged: POSIX ERE only, never translated, unresolved = no enforcement, team-tracked source only. Extend lib/resolve-convention-pattern.sh to flat-YAML-parse when the pointer declares it (note: this lib syncs to standards — check the resolve-convention-pattern-sync gate and coordinate both sides byte-identical, precedent fix(guardrails): machine-path right boundary — segment class, not trailing separator #1095/standards#255).
  • Layering preserved: neutral file feeds the team layer; user + local overlay files unchanged; plugin-only keys may stay .claude/-side.
  • setup apply gains the neutral-file path and on migration retires the duplicated pattern from .claude/source-control.md rather than leaving both authoritative.
  • Monorepo per-directory scoping: out of scope V1, note it.

Acceptance criteria

  • feat(source-control): convention parse-contract + shared enforcement resolver seam #913 read; reopen decision + rationale recorded there (whichever way it lands)
  • Neutral-file resolution works end-to-end (resolver lib + drafting surfaces + setup), default path unchanged for existing consumers
  • Incumbent steelman documented; format decision recorded with the walk-through of requirements
  • Every new knob is config, not constant; enforcement stays POSIX-ERE, fail-closed layering semantics unchanged
  • Sync-gated lib changes coordinated with the standards mirror byte-identical
  • Tests across the resolution ladder incl. pointer + neutral file; suite passes; version bump + CHANGELOG

Blocked by

Metadata

Metadata

Assignees

Labels

priority: highSignificant impact, or blocks an imminent release; staff this cycle.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions