Skip to content

feat(source-control): well-known default path for neutral convention SSOT (F1–F4) - #1185

Merged
kyle-sexton merged 2 commits into
mainfrom
feat/commit-convention-well-known-path
Jul 23, 2026
Merged

feat(source-control): well-known default path for neutral convention SSOT (F1–F4)#1185
kyle-sexton merged 2 commits into
mainfrom
feat/commit-convention-well-known-path

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Resolves the neutral commit-convention SSOT (from #1141) by a fixed 3-rung precedence, identical
on the drafting and enforcement surfaces:

  1. explicit convention_source pointer — relocation override, path stays repo-owned
  2. well-known default docs/conventions/source-control/commit-convention.yml when present — the
    marketplace's own dogfooded docs/conventions/<concern>/ layout; common case reads ONE
    tool-agnostic file, no markdown pointer-parse, nothing in agent-rewritable prose to sever
  3. markdown-H2 in .claude/source-control.md — legacy / back-compat

Full back-compat: absent both a pointer and the well-known file, resolution is unchanged.

Findings folded in (inbox item 20260723-163434):

  • F2 — the well-known default path (lib/resolve-convention-pattern.sh + synced guardrails mirror + config-resolution.md).
  • F1 — setup recommends the neutral SSOT as the default when a second enforcement consumer (commit-msg hook / CI title check) is detected.
  • F3setup check gains drift probes: broken pointer/neutral file → FAIL; resolved neutral file shadowing stale markdown-H2 → WARN.
  • F4 — neutral-YAML preamble trimmed to a 1–2 line header.

Design + re-anchor rationale (reuse-or-replace, recheck-against-upstream, reason-dont-recite, point-dont-copy): docs/topics/commit-convention-well-known-path/design-resolution.md.

Scope note (honest): F3 closes silent severance for well-known-default repos; a repo that relocates via convention_source and then loses the pointer still falls through per-key to markdown — check surfaces it, but prevention there is bounded by design.

Version bumps: source-control 0.24.0 → 0.25.0; guardrails 0.13.0 → 0.14.0 (forced by the sync --check-bump gate — vendored resolver changed).

Test plan

  • bash lib/resolve-convention-pattern.test.sh — 56/56 (added 8 well-known-path cases: resolves-with-no-pointer, wins-over-markdown, explicit-overrides-well-known, fail-closed on broken well-known, per-key markdown fallback, back-compat).
  • scripts/sync-resolve-convention-pattern.sh --check — mirror byte-identical.
  • scripts/sync-resolve-convention-pattern.sh --check-bump origin/main — guardrails bumped.
  • scripts/check-changelog-parity.sh --check-bump origin/main — both CHANGELOGs updated.
  • shellcheck clean on the resolver + mirror.

Related

🤖 Generated with Claude Code

…SSOT (F1-F4)

Resolve the neutral commit-convention SSOT by a fixed 3-rung precedence, identical
on the drafting and enforcement surfaces: explicit convention_source pointer >
well-known docs/conventions/source-control/commit-convention.yml > markdown-H2.
The common case now reads ONE tool-agnostic file with no markdown pointer-parse
and nothing in agent-rewritable prose to sever. Full back-compat.

- F2: well-known default path in lib/resolve-convention-pattern.sh (+ synced
  guardrails mirror, guardrails 0.13.0 -> 0.14.0) and config-resolution.md.
- F1: setup recommends the neutral SSOT as the default when a second enforcement
  consumer (commit-msg hook / CI title check) is detected.
- F3: setup check gains drift probes (broken pointer/neutral file -> FAIL;
  resolved neutral file shadowing stale markdown-H2 -> WARN).
- F4: neutral-YAML preamble trimmed to a 1-2 line header.

Design + re-anchor rationale: docs/topics/commit-convention-well-known-path/.
source-control 0.24.0 -> 0.25.0.

Closes #1184

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 4m 16s —— View job


Code Review: feat(source-control): well-known default path for neutral convention SSOT (F1–F4)

  • Gather context and understand request
  • Review lib/resolve-convention-pattern.sh (core resolver changes)
  • Review lib/resolve-convention-pattern.test.sh (test coverage)
  • Review plugins/source-control/skills/setup/SKILL.md (F1/F3 changes)
  • Review plugins/source-control/skills/setup/reference/apply-convention.md
  • Review plugins/source-control/reference/config-resolution.md
  • Review guardrails sync mirror
  • Review documentation and changelogs
  • Post findings

Summary

Overall: LGTM with minor observations. The implementation is correct, security-hardened, and thoroughly documented. The 3-rung precedence is consistently mirrored across the resolver and all documentation surfaces, and the fail-closed contract is maintained for the well-known path. Minor observations below, none of which block merge.


Core resolver logic (lib/resolve-convention-pattern.sh lines 54–151)

The well-known probe is clean:

readonly WELL_KNOWN_NEUTRAL="docs/conventions/source-control/commit-convention.yml"
...
if [[ -z "$ptr" && -f "$repo_root/$WELL_KNOWN_NEUTRAL" ]]; then
  ptr="$WELL_KNOWN_NEUTRAL"
fi

The constant value docs/conventions/source-control/commit-convention.yml safely clears all the rejection patterns in the subsequent case block (/*, [A-Za-z]:*, *\\*, *..*). Critically, the well-known path then travels through the same symlink/canon/dialect checks as any explicit pointer — no shortcut that could create a privilege difference between the two rungs. The fail-closed contract (broken well-known file → exit 1, never fall back to stale markdown) is correctly maintained. ✓

One note on the *..* pattern: it rejects any path whose string representation contains .. as a substring, which is broader than just ..-as-a-path-segment (e.g., v1..v2.yml would be rejected). This is intentionally conservative/safe and doesn't affect the well-known constant, but worth noting if a consumer ever tries to relocate via convention_source to a file with .. in its basename.


Security

No issues found across the security surface:

Check Result
Symlink file escape (-L test) ✓ Caught, disabled
Symlinked directory segment (pwd -P canon check) ✓ Caught, disabled
POSIX absolute paths (/*) ✓ Rejected
Windows drive-letter paths ([A-Za-z]:*) ✓ Rejected
.. traversal (*..*) ✓ Rejected
Non-posix-ere dialect ✓ Fail-closed
grep injection in yaml_value / check_neutral_key ✓ All k values are hardcoded literals (subject_pattern, pr_title_pattern, dialect, convention_source)

Diagnostic message cosmetics (minor)

When the well-known path fails (e.g., wrong dialect), the error still says:

resolve-convention-pattern: convention_source file declares dialect 'pcre'; enforcement disabled.

A user whose repo has docs/conventions/source-control/commit-convention.yml but no explicit ## convention_source pointer will see a message referencing convention_source they never set. Functionally correct (enforcement is disabled as intended), but could prompt a confused "I never wrote convention_source?" question.

A small prefix like well-known convention file vs convention_source file would distinguish the two origins without changing the exit path. Not a blocker — the F3 check drift probe will surface this condition explicitly with better context before it hits a blocked commit in practice.

Consider this improvement →


Test coverage (lib/resolve-convention-pattern.test.sh lines 279–330)

The new section covers the cases that matter:

Test Coverage
Well-known present, no pointer, no markdown → resolves
Well-known + markdown → well-known wins (rung 2 > 3)
Explicit pointer + well-known → explicit wins (rung 1 > 2)
Well-known with broken dialect → exit 1 (fail closed)
Well-known with empty key + stale markdown → exit 1 (fail closed)
No well-known, no pointer, markdown present → markdown back-compat
Well-known file omits a key → per-key markdown fallback

There is no dedicated test for a symlinked well-known file — the existing symlink tests at lines 258–277 cover the explicit-pointer path. The general symlink guard in the resolver is shared and path-agnostic, so the behavior is correct; it's just not exercised for the well-known rung specifically. Worth a TODO if the test suite ever grows a CI symlink fixture.

Minor: the PR description says "8 well-known-path cases" but counting assert_eq/assert_exit calls in the new section yields 9 assertions (the broken-dialect and empty-key scenarios each emit two assertions). Not a bug.


F1 / F3 in SKILL.md and apply-convention.md

F1 (recommend neutral SSOT when second consumer detected) is correctly gated on inference step 2's hook detection, not on file presence — the gotcha section at line 209 ("Gate inference on the resolved value, never file presence") applies symmetrically here. The text at SKILL.md line 162–166 and apply-convention.md lines 344–348 are consistent.

F3 drift probes (SKILL.md lines 91–105): the two-condition design is sound. The WARN condition ("neutral file resolves AND markdown still carries the same key") correctly points at apply to retire the duplicate rather than silently inheriting the stale value. The FAIL condition ("broken pointer/neutral file") closes the gap where enforcement was silently disabled.


Cross-surface consistency

The 3-rung precedence is stated identically in:

No drift between surfaces. ✓

Guardrails mirror (plugins/guardrails/hooks/resolve-convention-pattern.sh) is byte-identical to the lib source. ✓

Version bumps are appropriate: source-control 0.24.0 → 0.25.0 (new feature) and guardrails 0.13.0 → 0.14.0 (forced by resolver change). ✓


@claude

claude Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 5m 2s —— View job


Security Review — PR #1185

  • Gather PR diff and changed files
  • Analyze shell scripts for injection surfaces (command, path, variable expansion)
  • Check file path handling and trust boundaries
  • Review plugin manifests for supply-chain / version issues
  • Post findings

Summary

No CRITICAL or IMPORTANT issues. The security posture of the resolver is strong: the new well-known-path probe inherits all existing safety gates (absolute-path rejection, ..-traversal guard, symlink-file check, canonical-directory containment). One pre-existing SUGGESTION surfaces because the new well-known-path code path now exercises it via a second trigger.


SUGGESTION — Glob metacharacter expansion in canonical-directory containment check

Confidence: LOW · Pre-existing; newly exercised by the well-known-path code path this PR adds.

lib/resolve-convention-pattern.sh line 181 (identical in the guardrails mirror):

if [[ -z "$canon_root" || -z "$canon_dir" || "$canon_dir/" != "$canon_root/"* ]]; then

In [[ ]], the RHS of != is treated as a glob pattern. If the physical canonical repo-root path (pwd -P) happens to contain glob metacharacters — for instance a directory literally named myrepo[abc] — the RHS becomes /path/to/myrepo[abc]/* where [abc] is interpreted as a character class. A canon_dir of /path/to/myrepob (a sibling directory, outside the repo) would then match the pattern and bypass the containment check.

Exploitation chain for the well-known path (new in this PR):

  1. Consumer repo root has a canonical path containing […] in a directory name (e.g. /ci/builds/project[dev]).
  2. An attacker with write access to the repo creates docs/conventions/source-control/ as a symlink to a directory under /ci/builds/projectd/ (a sibling that matches the character class).
  3. The neutral YAML file at that location is a plain regular file — passes the [[ -L "$NEUTRAL_FILE" ]] check.
  4. cd "$(dirname "$NEUTRAL_FILE")" && pwd -P resolves to the symlinked target outside the repo.
  5. The glob comparison incorrectly accepts the out-of-tree path, and the gate enforces a pattern from outside the repository.

Why confidence is LOW: pwd -P on typical systems returns paths without [, ], *, or ?; directory names with glob metacharacters are unusual enough that no realistic consumer is likely affected. Additionally, step 1 requires the attacker to also control the directory naming of wherever CI clones the repo.

Safe alternative — string prefix comparison without glob expansion:

canon_prefix="${canon_root}/"
if [[ -z "$canon_root" || -z "$canon_dir" || \
      "${canon_dir:0:${#canon_prefix}}" != "$canon_prefix" ]]; then

This is a pure string-prefix test; no characters in canon_root are ever interpreted as glob metacharacters.


Everything else reviewed — no issues

Area Assessment
WELL_KNOWN_NEUTRAL constant (line 59) readonly, no metacharacters, passes all downstream guards intact
Well-known probe (-f "$repo_root/$WELL_KNOWN_NEUTRAL") Probes existence only; sets ptr to the constant, then goes through the same lexical + symlink + canon-dir safety chain as any explicit pointer
yaml_value's grep -E "^${k}:" (line 127) $k is always one of dialect, subject_pattern, or pr_title_pattern — all hardcoded at call sites after the validated $key gate at lines 73–79; no user-controlled string reaches the regex
ERE safety-net grep -E -- "$value" </dev/null (line 285) -- blocks flag injection; /dev/null input means ReDoS cannot trigger; exit-code gate handles invalid expressions
awk -v key="$k" in h2_value (line 100) Value passed as an awk variable, not interpolated into awk source; file content never executed as awk code
Symlink check (lines 175–178) Correctly rejects a symlink at the file level; the canon-dir check (with the suggestion above) handles symlinked directories
Plugin manifests (plugin.json) Version bumps only (0.24.0→0.25.0, 0.13.0→0.14.0); no new dependencies, no new permissions, no pinning regressions
SKILL.md / apply-convention.md Model instructions; shell command templates use $REPO_ROOT from git rev-parse --show-toplevel (trusted) with fixed paths — no injection surface

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d84323f3ce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/resolve-convention-pattern.sh Outdated
Comment thread plugins/source-control/skills/setup/reference/apply-convention.md
…harden canon-prefix (review)

Address PR #1185 review findings:

- Codex P1: the well-known rung activated on mere file existence, so an untracked
  or gitignored file at docs/conventions/source-control/commit-convention.yml
  could silently override tracked team policy (policy-floor violation). Gate the
  rung on `git ls-files --error-unmatch` — activate only when the file is
  git-tracked; git absent or file untracked falls through to the markdown H2.
  Adds two regression tests (untracked -> markdown wins; untracked+no-markdown
  -> no enforcement).
- security-review: replace the `!= "$canon_root/"*` glob match in the symlink
  canon check with a pure string-prefix comparison, so a glob metacharacter in
  the physical repo path cannot be interpreted rather than compared literally.
- Codex P2: update setup eval case 18 to expect the pointerless well-known
  default (no convention_source for the default location; pointer only on
  relocation), matching the new apply-convention default.

Mirror resynced; 58/58 resolver tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 31s —— View job


Review — PR #1185 (follow-up commit 928cd9b)

  • Gather context and understand request
  • Review the follow-up commit diff vs prior review commit
  • Analyze the git-tracked guard implementation
  • Analyze the canon-prefix hardening
  • Cross-check test coverage for the new guards
  • Post findings

Summary

All three review items (Codex P1, security-review suggestion, Codex P2) are correctly implemented. No new issues introduced. Ready to merge.


Codex P1 — git-tracked guard ✓

lib/resolve-convention-pattern.sh line 157–159:

if [[ -z "$ptr" && -f "$repo_root/$WELL_KNOWN_NEUTRAL" ]] &&
  git -C "$repo_root" ls-files --error-unmatch -- "$WELL_KNOWN_NEUTRAL" >/dev/null 2>&1; then
  ptr="$WELL_KNOWN_NEUTRAL"
fi

The >/dev/null 2>&1 suppression is correct: --error-unmatch exits 1 for untracked files (already the right effect); the 2>&1 swallows the "did not match" message and any "not a git repo" error from when git isn't available. Both cases fall through to the markdown H2 — "fail toward prior behavior, never toward the hole." ✓

The && compound is inside an if condition, so set -e doesn't apply to git ls-files failure here. ✓

The policy-floor rationale in the comment (line 150–156) correctly articulates why rung 2 needs a stronger trust signal than rung 3 (markdown has a tracked opt-in by definition; the well-known path does not).

Two new regression tests cover the critical cases:

Test Behavior verified
untracked file ignored -> markdown wins untracked YAML at well-known path + tracked markdown → markdown wins
untracked file + no markdown -> exit 1 untracked YAML + no markdown → no enforcement (exit 1, not activated)

The track() helper (git init -q || true && git add -- "$path") is correct: it uses || true so tests don't fail on a re-init, and git add with a relative path in the repo root is precise. One observation: this means six existing well-known tests now require a real git binary at test time — this was already implied by the newrepo fixture pattern but now it's load-bearing. If CI ever runs these in a minimal container without git, the tests that call track() will silently skip (the || true suppresses errors) and then fail because ls-files won't find the file. Worth a note in the test file header if the suite ever runs in such an environment, though not a blocker given this repo's CI setup.


Security suggestion — canon-prefix hardening ✓

lib/resolve-convention-pattern.sh line 194–196:

canon_prefix="$canon_root/"
canon_dir_slash="$canon_dir/"
if [[ -z "$canon_root" || -z "$canon_dir" || "${canon_dir_slash:0:${#canon_prefix}}" != "$canon_prefix" ]]; then

Correct. The bash substring expansion ${canon_dir_slash:0:${#canon_prefix}} extracts exactly ${#canon_prefix} bytes from canon_dir_slash and compares them as a plain string — no glob characters in canon_root can be interpreted as a pattern. The two intermediate variables are script-level (not function-local), but they're only used in this one check and don't shadow anything. ✓

Guardrails mirror confirmed byte-identical to the lib source. ✓


Codex P2 — eval case 18 ✓

The updated expectation in evals.json now requires:

  • The skill writes at the well-known default path without a convention_source pointer.
  • A pointer is written only for non-default relocation.
  • The verification step confirms the file is staged/tracked (not just present), closing the loop with the new policy floor.

The rename from apply-neutral-ssot-migration-retires-duplicates to apply-neutral-ssot-well-known-default-retires-duplicates is precise. ✓


One open cosmetic observation (carry-over, not a blocker)

Noted in the prior review: when the well-known path fails (e.g. wrong dialect), the diagnostic still reads convention_source file declares dialect '...' even when no explicit convention_source was set. The follow-up commit didn't address this — consistent with the prior review's assessment that F3 check surfacing the condition first makes this low-priority. Confirming it remains the only open non-blocking item.

@claude

claude Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 49s —— View job


Security Review — PR #1185 (HEAD: 928cd9b)

  • Gather context and understand request
  • Fetch PR diff (HEAD~2...HEAD covering both commits d84323f and 928cd9b)
  • Review shell scripts for injection/path/logic/TOCTOU vulnerabilities
  • Review git-tracking gate and canon-prefix fix
  • Review test coverage for new security-critical paths
  • Post findings

Summary

No CRITICAL or IMPORTANT issues. The fixup commit (928cd9b) correctly addresses both security findings from the prior review pass (the Codex P1 untracked-file override and the glob-metacharacter SUGGESTION on the canon-prefix check). One low-confidence SUGGESTION remains on the git ls-files call path; one observation on the TOCTOU window is included for completeness and is mitigated by downstream fail-closed checks.


Addressed by 928cd9b

Prior finding Status
Codex P1 — untracked/gitignored file at well-known path could silently override tracked markdown policy or disable enforcement Fixedgit ls-files --error-unmatch gate added at line 157–159; tests for untracked-with-markdown and untracked-no-markdown both confirm fail-closed/fall-through behavior
Previous Claude SUGGESTION — glob metacharacter in != "$canon_root/"* pattern comparison Fixed — replaced with pure string prefix test at lines 194–196; ${canon_dir_slash:0:${#canon_prefix}} != $canon_prefix is literal byte comparison with no glob interpretation

Remaining: SUGGESTION — git ls-files with leading-dash repo_root

Confidence: LOW

lib/resolve-convention-pattern.sh line 158:

git -C "$repo_root" ls-files --error-unmatch -- "$WELL_KNOWN_NEUTRAL" >/dev/null 2>&1

If $repo_root began with a - (a directory named -foo), git -C -foo would attempt to interpret -foo as a flag sequence; git would error out with an invalid option message and exit non-zero. The condition would fail, the well-known rung would be skipped, and resolution would fall through to the markdown H2 — the safe prior behavior. This is not exploitable for policy override, but an adversarially named repository root could cause the well-known rung to be silently bypassed when it shouldn't be.

In practice $repo_root is supplied by git rev-parse --show-toplevel from the calling hook, which returns an absolute path starting with / — leading-dash is not a realistic concern. Adding -- before "$repo_root" is not possible here since -C consumes the next argument positionally (not ---separated), but the same hardening is achievable by validating the absolute path before the git call:

if [[ -z "$ptr" && -f "$repo_root/$WELL_KNOWN_NEUTRAL" && "$repo_root" == /* ]] &&
  git -C "$repo_root" ls-files --error-unmatch -- "$WELL_KNOWN_NEUTRAL" >/dev/null 2>&1; then

The "$repo_root" == /* guard also aligns with the TEAM_FILE construction at line 82, which implicitly assumes an absolute path.


TOCTOU between git ls-files and downstream checks (not a vulnerability)

Between git ls-files returning success and the subsequent [[ ! -f "$NEUTRAL_FILE" ]] / [[ -L "$NEUTRAL_FILE" ]] / canon-dir checks, the file could theoretically be replaced. Each mutation is caught fail-closed:

  • File deleted: [[ ! -f ]] catches it → exit 1
  • Replaced with symlink: [[ -L ]] catches it → exit 1
  • Replaced with a regular file pointing to canon-dir outside repo: substring check catches it → exit 1

No TOCTOU exploitation path exists; the downstream chain handles every post-ls-files mutation safely.


Everything else reviewed — no issues

Area Result
WELL_KNOWN_NEUTRAL constant (line 59) readonly; docs/conventions/source-control/commit-convention.yml contains no metacharacters; passes all downstream lexical guards (/* | [A-Za-z]:* | *\\* | *..*) intact
Well-known probe (-f "$repo_root/$WELL_KNOWN_NEUTRAL") Double-quoted — no word splitting, no glob expansion; safe
git ls-files --error-unmatch -- "$WELL_KNOWN_NEUTRAL" $WELL_KNOWN_NEUTRAL is a readonly constant, -- guards against flag injection; git exits non-zero on any failure (git unavailable, not a repo, untracked) — all fail toward the prior markdown-H2 behavior
Canon-prefix fix (${canon_dir_slash:0:${#canon_prefix}}) Pure string substring comparison; no pattern characters in canon_root are ever interpreted as globs
yaml_value grep -E "^${k}:" $k is always a hardcoded literal at all call sites; no user-controlled string reaches the regex
ERE safety-net grep -E -- "$value" </dev/null -- blocks flag injection; /dev/null eliminates ReDoS; exit-code gate handles invalid expressions
awk -v key="$k" in h2_value Value passed as awk variable, not interpolated into awk source
Symlink check (line 184) Regular-file-only requirement on the neutral file stands for both the explicit-pointer and well-known rungs
Plugin manifests Version bumps only (0.24.0→0.25.0, 0.13.0→0.14.0); no new permissions, no new remote dependencies
Guardrails mirror Byte-identical to lib source (confirmed by sync script); the same analysis applies
SKILL.md / apply-convention.md Model instructions with no shell execution surfaces; git rev-parse --show-toplevel usage is trusted and fixed-path
evals.json Eval expectation update only; no execution surface

@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Also applied the security-review hardening (advisory): the symlink canon check now uses a pure string-prefix comparison instead of a "$canon_root/"* glob, so a glob metacharacter in the physical repo path can't be interpreted rather than compared literally. (928cd9b)

@kyle-sexton
kyle-sexton merged commit 01c8c6f into main Jul 23, 2026
24 checks passed
@kyle-sexton
kyle-sexton deleted the feat/commit-convention-well-known-path branch July 23, 2026 21:36
kyle-sexton added a commit that referenced this pull request Jul 23, 2026
…ascade (#1190)

## Summary

Renames the marketplace-wide consumer-config layering seam from the
clunky three-noun
`consumer-config-layering` to **`config-cascade`**.

Name chosen via `/naming:name-it-better` (blind 3-lens fan-out):
"cascade" (CSS `@layer`/`!important`)
is the one established term of art that natively carries **both**
per-key override **and** a ratified
precedence-inversion — matching the seam's user→team→local +
policy-floor model. Runner-ups:
`config-layering`, `layer-cascade`, `config-precedence`.

- `git mv docs/conventions/consumer-config-layering → config-cascade`.
- All **live** references updated (name + path): MIGRATION-PLAYBOOK,
PLUGIN-PHILOSOPHY, loop-lane seam,
code-tidying (SKILL + docs-prose lane), testing (README + run-e2e
SKILL/context), `.gitignore`.
- Seam README records the former name (discoverability); CHANGELOG
records the rename with **no
  `contract_version` bump** — name/path only, contract unchanged.
- code-tidying `0.7.1→0.7.2`, testing `0.3.1→0.3.2` (patch) so consumers
receive the corrected doc-URL.
- **Historical** topic docs / CHANGELOGs retain the former name as
frozen record (bare-text mentions,
  not links).

**Provenance context:** the rename was gated (issue #1187) on whether
the seam was legitimately
ratified. Finding: all 12 `docs/conventions/*` seams are PR-introduced
across the repo's whole history;
`consumer-config-layering` (#692) is unremarkable. The shared
`kyle-sexton` identity (human + agents)
makes metadata-level "human-ratified vs agent-accreted" undecidable — a
**repo-wide** property, not a
disqualifier for this seam. The operator's direct direction this session
is the ratification.

## Test plan

- `lychee --offline './**/*.md'` — **0 errors** (2754 links checked); no
dead relative link to the old path.
- `grep -rn '](.*conventions/consumer-config-layering' .` — none (no
dead relative links).
- `scripts/check-changelog-parity.sh --check-bump origin/main` — both
bumped plugins have entries.
- Remaining `consumer-config-layering` mentions are historical bare-text
only (topic PLANs, CHANGELOGs, `.work/`).

## Related

- Closes #1188
- Provenance context: #1187 (audit finding recorded above)
- Follows #1185 (well-known path, which dogfoods the
`docs/conventions/<concern>/` location)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 23, 2026
… both surfaces (#1192)

## Summary

#1185's P1 review hardening — the well-known convention-file rung
activates only when the file is
**git-tracked** — landed only in the enforcement resolver bash. The
drafting spec
(`config-resolution.md`) and the commit-convention seam README still
said rung 2 fires "when that
file exists", and config-resolution.md claimed the surfaces were
"identical" — false after the fix.

**The drift it created:** a repo with an untracked/gitignored well-known
file + a different markdown-H2
`subject_pattern` → drafting resolves the untracked file, enforcement
skips it → the plugin drafts
commits its own gate rejects. Exactly the two-surface divergence the
design exists to prevent.

Adds the git-tracked requirement + how the drafting reader checks it
(`git ls-files --error-unmatch`)
to config-resolution.md, the seam README, and the setup SKILL.md gotcha.
**Docs-only** — the resolver
already enforced tracked; this makes the specs match and "identical on
both surfaces" true again.

source-control `0.25.0 → 0.25.1`.

## Test plan

- `lychee --offline` clean on the three edited docs.
- `scripts/check-changelog-parity.sh --check-bump origin/main` — bump
has an entry.
- No code change (resolver + its 58 tests unchanged); the resolver
already required tracked.

## Related

- Closes #1191
- Follow-up to #1185 / #163434 (well-known default path)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 23, 2026
…ion (#1193)

## Summary

Closes the #1187 provenance audit with a durable **decision record** in
MIGRATION-PLAYBOOK, rather than
a forgery-prone gate.

**Finding:** in this solo-autonomous setup the operator and every agent
act as the same `kyle-sexton`
identity, so no in-repo signal (author / reviewer / merger / commit
signature) distinguishes human
ratification from agent accretion — a **repo-wide property**, not a
per-seam defect. All 12
`docs/conventions/*` seams are PR-introduced and cite a ratifying
issue/PR; none was silently accreted.

**Decision:** decline `CODEOWNERS` / `human-ratified` label / signing
gates under the shared identity —
an agent satisfies the same gate, so they manufacture *false* assurance
(theater). The only real
distinguisher is a separate human-only identity/signing key agents don't
hold; flagged as an infra
option with a revisit trigger, **not imposed**. Interim posture:
ratification stays trust-based and
visible via cited issues/PRs + operator engagement, with the audit trail
as the durable account.

Docs-only (marketplace governance doc — no plugin shipped-content
change, no version bump).

## Test plan

- `lychee --offline docs/MIGRATION-PLAYBOOK.md` — clean.
- Decision record follows the doc's existing dated-decision-record
format.

## Related

- Closes #1187
- Concludes the #163434 work stream (#1185 well-known path, #1190
config-cascade rename, #1192 cross-surface fix)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton pushed a commit that referenced this pull request Aug 15, 2026
Treatments from the 2026-08-15 repo-wide /docs-hygiene:audit-noise run
(1027 files scanned, 55 scanner candidates, 37 findings after two-worker
judgment and a fresh-context adversarial verification pass):

- ghost-refs: PR permalinks added beside prune-surviving slice citations
  (#796, #794, #1459, #1185, #330, #1400), checkout-local caveats on
  memory-tier ledger refs, stale '.work/ destination' clauses stripped
- citations: inline provenance relocated to ## Sources / ## History
  footers (compress skill, suno drift ledger)
- retired-path mentions wrapped in documented opt-out markers where the
  mention is itself the rule/history being stated
- preamble: reference-quadrant 'Why this file exists' collapsed to a
  one-sentence orientation (song-forms-examples)
- enum-list: hardcoded rosters reopened (docs-hygiene README count,
  session-flow README network roster)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9A7ewGsRVk4KWVUhUcgpq
kyle-sexton added a commit that referenced this pull request Aug 15, 2026
…back, paragraph-scope markers (#2721)

No linked issue

## What this is

The apply phase of the first repo-wide `/docs-hygiene:audit-noise` run
(2026-08-15): 1,027 tracked markdown files scanned with the skill's own
`detect.sh`, 55 scanner candidates judged by two concurrent Opus
workers, all actionable verdicts adversarially verified by a
fresh-context verifier (54 checked, 50 upheld, 4 overturned — overturns
applied). Net: 2 Tier 1 + 30 Tier 2 findings, 24 scanner false positives
dismissed, all 33 flagged files passing the existence pre-check.

## Commits

- **`docs:` treatments (31 of 32 actionable findings):** ghost-refs get
carrying-PR permalinks (#796, #794, #1459, #1185, #330, #1400),
checkout-local caveats, or strips; citations relocate to `##
Sources`/`## History` footers; retired-path mentions that ARE the stated
rule/history get opt-out markers; a Reference-quadrant preamble
collapses; hardcoded rosters reopen. Deliberately not edited:
`line-brainstorm-prompt.md:182` (roster inside an output-template code
fence — accepted as a reviewed hardcode; this PR is the recorded
review).
- **`feat(docs-hygiene): 0.12.0`:** audit-noise's clean-tree default
becomes a confirmation-gated repo-wide offer (blocked when unattended)
instead of a silent no-op; `detect.sh`'s opt-out markers now honor the
documented paragraph scope (`-line` distinguished; heading also closes
scope); Tier 3 explicitly carries no treatment; recurring judgment
dismissal grounds codified; carrying/pruning PR numbers sanctioned as
durable ghost-ref pointers; `CHANGELOG.md` skipped by basename per the
long-documented exemption. Tests 38/38;
shellcheck/shfmt/markdownlint/changelog-parity clean.
- **`chore:` version bumps** required by the changelog-parity gate for
touched plugin trees (session-flow 0.23.5, songwriting 1.4.4) and the
regenerated `docs/CATALOG.md`.
- **`fix:` fresh-context verification minors** — diff verification
returned CLEAN (all six PR-citation claims verified against git
history); 6 of its 9 minor observations fixed, 3 recorded as accepted in
the PR comments.

## Dispositions — nothing left dangling

Completed in this PR: Tier-3 treatment semantics, `-line` marker docs,
PR-number pointers, codified dismissal grounds, CHANGELOG basename skip,
marker paragraph scope, clean-tree fallback.

Filed as issues (from the run + the follow-up `/plugin-quality:audit` of
the components this session exercised):

- #2730 — `.work/running-retros/` concern-root codification
(convention-ownership decision)
- #2734 — sibling audit skills adopt the clean-tree fallback
- #2739 — cloud-bootstrap installs npm-global tools into an nvm prefix
invisible to plugin hooks (markdown lint gate silently lost in cloud
sessions; found via this session's hook false-negative)
- #2740 — markdown-format notice wording ("skipped for this session"
misstates the latch) + probed-PATH diagnostic
- #2741 — `detect.sh` per-line subshell forking (~700× grep; root cause
of this run's scan timeout) + chunking affordance for the new fallback
- #2742 — scanner exemption gaps (frontmatter unimplemented,
marker-substring self-trigger, no code-fence awareness, section-state
leaks)

## Verification state

Fresh-context diff verification: CLEAN. Automated security review: clean
at every pushed head. Automated code review: no findings. Local gates
green (38/38 script tests, shellcheck/shfmt, markdownlint, changelog
parity, plugin validation + catalog).

## Related

- Predecessor PR #2696 (closed as premature; carried only the
since-reverted ledger commit)
- Follow-up issues: #2730, #2734, #2739, #2740, #2741, #2742

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01H9A7ewGsRVk4KWVUhUcgpq

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

source-control setup: neutral convention SSOT well-known default path + config surface (F1–F4)

1 participant