Skip to content

feat: ship the retired-conventions mechanism (Phase 2b) - #3597

Merged
kyle-sexton merged 5 commits into
mainfrom
chore/retired-conventions-mechanism
Sep 2, 2026
Merged

feat: ship the retired-conventions mechanism (Phase 2b)#3597
kyle-sexton merged 5 commits into
mainfrom
chore/retired-conventions-mechanism

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Closes #3596

Summary

Phase 2b of the customization-consistency program: the approved retired-conventions mechanism (ADR 0018; unanimous blind tournament + hybrid amendments) — per-plugin append-only retirements.yaml, one shared deterministic helper, CI schema/wiring/eval enforcement, the owner doc with the two fixed setup lines, an audit-pass fleet-sweep lane, and the pointer-line resolver. No plugin ships a manifest yet; Phase 2c lands the first carrier (source-control).

Stacked on the Phase 1d PR (#3585) with the 2a branch merged in; retarget as the stack merges.

Fix

  • plugins/claude-config/lib/check-retirements.sh (+ 174-check .test.sh): detection (file/dir/line, content_match reused-path guard, CRLF-safe), TSV findings id/kind/path/action/status/note, exit 0/1/2 (invalid record fails the whole run loudly), --clean <id> with the migrate --i-migrated gate and Windows-lock exit-2 re-run rule.
  • scripts/validate-plugin-contracts.mjs (+ fixtures in its test harness): flat-YAML-subset parser, field/enum/path rules, append-only vs VALIDATE_CONTRACTS_BASE_REF (legal edits: status flip, note/successor defect fix; whole-manifest deletion caught via git ls-tree), manifest ⇔ synced-helper ⇔ setup-reference bidirectional wiring, one eval per record id as a validator FAILURE.
  • scripts/sync-check-retirements.sh + registry entry (commented until the first carrier, per the drift checker's <2-plugin stale rule) + check-retirements-sync CI job; affected-tests now supports canonical-only clusters.
  • docs/conventions/retired-conventions/ (contract 1.0): schema, helper contract, the two fixed setup lines, demotion rule, eval-per-record, fleet sweep, dual-read window bounds, deferred CI aggregate with revive trigger. Convention-registry rows added for retired-conventions and plugin-reconfiguration.
  • plugins/claude-config audit-pass: runtime fleet-sweep lane over installed plugins' manifests (read-only; declared carve-out on the hub's never-reads-another-plugin rule for this published data seam) + reference/retired-conventions-sweep.md spoke.
  • plugins/claude-config/lib/resolve-convention-home.sh (+ 61-check .test.sh): AGENTS.md-canonical pointer-line resolver per config-cascade's expression doctrine (exit 0 resolved / 1 no pointer / 2 usage / 3 FAIL with distinct causes; pure-shim CLAUDE.md skipped; untrusted-input hardened, no eval, CR stripped, line cap).
  • claude-config bumped 0.40.4 with a CHANGELOG entry (parity gate).

Verification

  • PLAN.md 2b Sanity Check: check-retirements.sh --help exits 0; its test suite 174/174; validate-plugin-contracts.test.sh all assertions passed (incl. malformed-fixture red cases); registry line present (commented, annotated); test -f docs/conventions/retired-conventions/README.md holds.
  • Real tree: node scripts/validate-plugin-contracts.mjs green (51 setup skills, 0 manifests, 2951 files).
  • Resolver suite 61/61; shellcheck clean (0.11.0) on all new/touched shell files; markdownlint 0 issues on all touched markdown; catalog/cheatsheet checks green.
  • Pre-flight consumer check: repo-wide grep for retirements.yaml / check-retirements consumers before this change: zero (new contract).

Related

Refs ADR 0018, docs/topics/customization-consistency/PLAN.md Phase 2b, tournament record design/mechanism-validation.md, PRs #3582 #3583 #3584 #3585 #3587. Phase 2c uncomments the registry line with the first carrier.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T21:54:30.716852Z f7aec15 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: f7aec1549d

ℹ️ 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 plugins/claude-config/lib/check-retirements.sh
Comment thread scripts/validate-plugin-contracts.mjs Outdated
Comment thread scripts/validate-plugin-contracts.mjs Outdated
Comment thread scripts/validate-plugin-contracts.mjs
Comment thread scripts/validate-plugin-contracts.mjs Outdated
kyle-sexton and others added 3 commits September 2, 2026 10:59
Implements the approved hybrid (unanimous blind tournament + user
approval; ADR 0018):

- plugins/claude-config/lib/check-retirements.sh (+174-check test
  suite): manifest-driven detection and gated cleanup of retired
  consumer conventions. TSV findings, exit 0/1/2, CRLF-safe matching,
  --clean with the migrate --i-migrated gate, content_match reused-path
  guard at clean time too.
- retirements.yaml schema validation wired into
  scripts/validate-plugin-contracts.mjs: flat-YAML-subset parser, field
  and enum rules, append-only vs VALIDATE_CONTRACTS_BASE_REF (legal
  edits: status flip, note/successor defect fix), bidirectional wiring
  (manifest <-> synced helper copy + setup reference), and one eval per
  retirement record as a validator failure. Fixture coverage in the
  test harness; real corpus stays green.
- scripts/sync-check-retirements.sh + registry entry (commented until
  the first carrier lands in Phase 2c, per the drift checker's stale
  rule) + check-retirements-sync CI job; affected-tests now supports
  canonical-only sync clusters.
- docs/conventions/retired-conventions/ (contract 1.0): schema, helper
  contract, the two fixed setup lines, demotion rule, eval-per-record,
  fleet sweep, deferred CI aggregate with revive trigger. Registry rows
  for retired-conventions and plugin-reconfiguration.
- claude-config audit-pass gains the runtime fleet-sweep lane over
  installed plugins' retirements.yaml (read-only, never cleans).
- plugins/claude-config/lib/resolve-convention-home.sh (+61-check test
  suite): the AGENTS.md pointer-line resolver per config-cascade's
  expression doctrine; untrusted-input hardened.

Gates: helper 174/174, resolver 61/61, validator suite all green, real
tree validates, shellcheck clean, markdownlint clean, catalog ok.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uBXt1tMEReShbpG5gsFUd

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
… newline)

- git index exec bits set on the five new shell scripts (exit 126 in
  check-retirements-sync and the hygiene chmod finding).
- validate-plugin-contracts.test.sh clears GIT_DIR/GIT_WORK_TREE/
  GIT_CONFIG before building git fixtures (fixture-git-isolation-gate).
- audit-pass SKILL.md trimmed back under the 500-line hard cap (the
  sweep-lane bullet and carve-out compress; detail lives in the spoke).
- typos-format manifest final newline restored (bump-edit artifact,
  hygiene editorconfig check).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uBXt1tMEReShbpG5gsFUd
generic-api-key treats CLAUDE_SHIM=0 as the secret because the preceding CLAUDE_TOKEN="" line supplies keyword context. Both inits are parser state, not credentials. Inline gitleaks:allow per .gitleaks.toml policy (issues 3610/3599). Historical fingerprints stay in .gitleaksignore; this annotation covers the working tree and later commits.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
@cursor
cursor Bot force-pushed the chore/retired-conventions-mechanism branch from 3315cbc to 26502c9 Compare September 2, 2026 10:59
@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cursor[bot]'s task in 2m 48s —— View job


Code review

Todo list

  • Gather context (PR diff, changed files, existing Codex review comments)
  • Invoke /review:code-review (the skill errored on every attempt; fell back to an equivalent manual review of the full diff — noted below)
  • Post findings as inline comments on changed lines
  • Summarize cross-file/PR-level findings in this comment
  • Final update

Summary

Reviewed the full diff (origin/main...HEAD, 19 files, +3105/-6) plus the existing Codex review comments. Note: /review:code-review returned an error on every invocation this run rather than executing, so I performed the equivalent review by hand instead — reading the new shell/JS helpers directly and cross-checking runtime (check-retirements.sh, resolve-convention-home.sh) against the CI-side validator (validate-plugin-contracts.mjs).

Codex's five findings all check out — verified each against the actual code, all real:

One new finding, posted inline: validate-plugin-contracts.mjs:643 has the same parity bug as the line-636 finding above but for single-quoted values — '' inside a single-quoted value gets unescaped to ' in CI's parser but stays literal at runtime (strip_quotes only strips the outer layer for both quote kinds, per the helper's own MANIFEST doc comment). Same fix applies to both quote branches.

Everything else reviewed clean:

  • resolve-convention-home.sh — pointer-line grammar, region/marker state machine, valid_home path-segment validation (including the foo//bar empty-segment case), and the AGENTS.md-canonical / CLAUDE.md-shim logic all hold up under trace-through; no gaps found.
  • sync-check-retirements.sh, cross-plugin-source-registry.txt registry entry (correctly commented out per the drift checker's <2-plugin rule), and the ci.yml / affected-tests.sh canonical-only-cluster changes are consistent with the stated contract.
  • Docs changes (PLUGIN-PHILOSOPHY.md, plugin-reconfiguration/README.md, retired-conventions/README.md, audit-pass SKILL.md) are prose-only and consistent with the code they describe.

No security-relevant findings beyond the file-cleanup containment gap already covered above (this lane is scoped to correctness/maintainability; a security-review lane would be the place for a deeper look at that gap's severity).

Comment thread plugins/claude-config/lib/check-retirements.sh
Comment thread scripts/validate-plugin-contracts.mjs Outdated
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 3 times. The lane skips further automatic reviews after 5; deleting this comment resets the count.

File and line --clean now re-resolve the parent with pwd -P and refuse a
target that lands outside --root, matching the dir branch. The contract
parser matches the helper's exact --- separator, quote-stripping, path
grammar, and complete retirement-id eval coverage.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cursor[bot]'s task in 2m 49s —— View job


Code review

Todo list

  • Gather context (PR diff, changed files, prior Codex/Claude review comments)
  • Invoke /review:code-review (errored on every attempt again this run — same as the prior pass; fell back to an equivalent manual review, focused on the delta since the last review)
  • Verify the fix commit against the previously-reported findings
  • Check for regressions/new issues introduced by the fix
  • Final update

Summary

This run was triggered by the fix: keep retirements cleanup and the contract validator aligned commit (0e9f8b5), which lands directly on top of the prior review round (Codex + Claude reviewed at 26502c9). I re-verified each of that round's findings against the current code rather than re-deriving them from scratch.

All six previously-reported findings are fixed, and each got a regression test:

Finding Fix Test added
check-retirements.sh:510file cleanup had no symlink-containment check new assert_target_inside_root helper (L487–L495), called from both the file and line branches check-retirements.test.sh case 12b: clean through a symlinked .claude exits 2 and leaves the external file untouched
validate-plugin-contracts.mjs — separator regex tolerated trailing whitespace raw === "---" exact match (L603) new malformed_case: trailing-whitespace separator is not a record break
validate-plugin-contracts.mjs — double-quote value unescaping (\", \\) diverged from runtime's strip_quotes quoted values now sliced verbatim, no .replace() (L632) new malformed_case: a double-quoted match keeps backslashes instead of unescaping them
single-quote ''' unescaping had the same divergence (my earlier finding) same fix, single-quote branch (L637) covered by the same parser rewrite; verified by reading — both quote branches now share identical (no-op) semantics
badRepoRelativePath missed ., foo/., foo//bar, tabs that the runtime rejects predicate extended to match the runtime's case grammar exactly (L704–L720) 4 new malformed_case entries: ., foo/., foo//bar, a tab in the path
eval coverage used substring includes() (id-prefix false positive) textCoversRetirementId with a boundary-aware regex (L722–L725) new case: an eval mentioning only alpha-r0010 no longer covers alpha-r001

I traced assert_target_inside_root and the rewritten badRepoRelativePath against the runtime's strip_quotes (check-retirements.sh:234) and path-rejection case (check-retirements.sh:274-284) line by line — the CI-side parser and the runtime helper now agree on separator grammar, quote-stripping, path grammar, and eval-coverage matching. The dir branch's pre-existing containment check (check-retirements.sh:517-524) is untouched and still correct.

No new issues found in this delta, and nothing else in the PR changed since the last review round. I wasn't able to execute the shell/Node test suites directly in this sandbox (commands beyond trivial ones required approval that wasn't available), so this verification is from reading the diff and cross-referencing runtime vs. validator logic, not from running check-retirements.test.sh / validate-plugin-contracts.test.sh myself — the PR's own Verification section and the new regression tests added in this commit cover that ground.

No inline comments posted this round — there's nothing new to anchor; the prior round's inline findings are now resolved by 0e9f8b5.

…ce line

editorconfig rejects trailing whitespace in the test file. The --- plus
space record break is now printf'd so the fixture still exercises the
helper grammar without failing the hygiene lane.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
@claude

claude Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cursor[bot]'s task in 1m 29s —— View job


Code review

Todo list

  • Gather context (PR diff, changed files, prior Codex/Claude review comments)
  • Invoke /review:code-review (errored on every attempt again this run, same as both prior passes; fell back to a manual review of the delta since the last reviewed commit)
  • Verify the new commit against the previously-reported findings
  • Check for regressions/new issues introduced by the change
  • Final update

Summary

This run was triggered by f2a901f (test: build the trailing-space separator fixture without a dirty source line), the only commit since the prior review round at 0e9f8b5 (where all six previously-reported Codex/Claude findings were confirmed fixed with regression tests).

That commit touches only scripts/validate-plugin-contracts.test.sh, +6/-2. It replaces a heredoc containing a literal --- (trailing-space) line with an equivalent piped construction (cat <<'YAML' ... ; printf '%s \n' '---'; cat <<'YAML' ...) so the source file itself no longer contains trailing whitespace, which the repo's editorconfig/hygiene lane rejects.

I traced this against malformed_case and write_manifest (write_manifest just cats its own stdin to the manifest file) and conforming_retirements_fixture (which is called first inside malformed_case, but sources its own manifest content from a separate function rather than the caller's fd0). So the pipe correctly flows through to the later write_manifest alpha call untouched, and the resulting byte stream is identical to the original heredoc: a file record, then a line that is exactly --- + newline (dash-dash-dash, one trailing space), then a second file record. This is a mechanical, behavior-preserving fixture change with no logic difference — no new issues found.

I wasn't able to execute the shell/Node test suites directly in this sandbox (commands beyond trivial ones required approval that wasn't available in this run), so this verification is from reading the diff and tracing the stdin plumbing by hand, not from running validate-plugin-contracts.test.sh myself. The PR's own Verification section states this suite passes.

No inline comments posted this round — nothing new to anchor. All prior findings from the two earlier review rounds remain fixed and unaffected by this commit.

@kyle-sexton
kyle-sexton merged commit 781fa7d into main Sep 2, 2026
65 checks passed
@kyle-sexton
kyle-sexton deleted the chore/retired-conventions-mechanism branch September 2, 2026 11:41
cursor Bot pushed a commit that referenced this pull request Sep 2, 2026
…ment check

The Phase 2c copy was written against pre-2b helper bytes. After #3597 the
canonical file refuses a symlink parent on file and line --clean; the
carrier copy must stay byte-identical. Also mark the new sync script
executable.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
kyle-sexton added a commit that referenced this pull request Sep 2, 2026
…ne the rest (Phase 2c) (#3601)

Closes #3600

## Summary

Phase 2c of the customization-consistency program: convert the one
schema-expressible bespoke retirement (source-control's neutral-SSOT
migration) to the retirements.yaml mechanism Phase 2b shipped, dedupe
the context-guard/rate-limit-guard twin legacy-statusline detection
through the cross-plugin sync registry, and stamp every remaining
bespoke migration with its reason class. **Stacked on the Phase 2b PR
(#3597)**; retarget as the stack merges.

## Fix

- **source-control** ships its first retirement manifest. Record
`source-control-r001` detects the redundant `## convention_source`
pointer naming the well-known default path
(`docs/conventions/source-control/commit-convention.yml`), retired when
the V2 well-known-path migration (#1185, v0.25.0) made rung 2 resolve
that file pointer-free. Wiring per the owner doc: synced
`lib/check-retirements.sh`, the two fixed setup lines in
`check`/`apply`, one eval per record id, the registry uncomment, and the
Implementers row. The shadowed-markdown WARN stays live prose with an
explicit rationale: it is conditional on resolver state (a neutral file
resolving *and* carrying the key), which the repo-scope presence schema
cannot express, and markdown-H2 alone is still the sanctioned rung 3 —
an append-only record that knowingly over-fires must not ship.
- **Twin dedup** (ADR 0018, decision 6): the guards' shim-revision
ladder and legacy version-pinned wiring detection now live in one
byte-identical spoke,
`skills/setup/reference/legacy-statusline-detect.md` (context-guard
canonical), with `scripts/sync-legacy-statusline-detect.sh`, a registry
entry, and the `legacy-statusline-detect-sync` CI lane in
`ci-status.needs`.
- **Rationale lines**: context-guard, rate-limit-guard, machine-health
(machine-scope surface, outside the repo-scope schema per ADR 0018),
work-items (forge-label backfill), guardrails (hook provisioning),
planning and review (versioned-contract upgrade under `apply`) each
state in one sentence why their migration logic stays bespoke.
- Eight plugins patch-bumped with CHANGELOG entries (source-control
0.55.16, context-guard 0.7.22, rate-limit-guard 0.7.13, machine-health
0.11.5, work-items 0.39.25, guardrails 0.29.14, planning 0.34.7, review
0.26.9).

## Verification

- `VALIDATE_CONTRACTS_BASE_REF=origin/main node
scripts/validate-plugin-contracts.mjs` — green (1 retirement manifest:
schema, append-only, helper byte-identity, setup reference, eval
coverage).
- Fixture-repo run of the helper: detect emits the `source-control-r001`
row (exit 1); `--clean` without `--i-migrated` refuses (exit 2);
`--clean --i-migrated` removes exactly the pointer line (exit 0);
re-detect clean (exit 0).
- `sync-check-retirements.sh` and `sync-legacy-statusline-detect.sh`
`--check` / `--check-bump origin/main`,
`check-cross-plugin-source-drift.sh --check`, `check-lane-coverage.sh
--check` (46 lanes) — all green.
- markdownlint clean on all touched markdown; shellcheck clean on the
new sync script; catalog and cheatsheet checks in sync.
- PLAN.md 2c Sanity Check: `grep -n "shim-revision\|legacy"
plugins/source-control/skills/setup/SKILL.md` — zero hits; per skipped
plugin the rationale line exists.

## Related

Refs #3596 (mechanism), PR #3597, ADR 0018 (decisions 4 and 6),
`docs/conventions/retired-conventions/README.md`,
`docs/MIGRATION-PLAYBOOK.md` § Retired conventions.

---------

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
kyle-sexton added a commit that referenced this pull request Sep 2, 2026
…#3620)

Closes #3619

## Summary

Phase 2d PILOT of the customization-consistency program (ADR 0018):
migrates plugin-quality's team-shared config surface from the dedicated
`.claude/plugin-quality.md` three-layer cascade to a convention doc at
the consumer's convention home (`<home>/plugin-quality/README.md`),
bound by the pointer line and resolved by the shared resolver. First
plugin to ship `retirements.yaml` alongside source-control's (records
`plugin-quality-r001` migrate, `plugin-quality-r002` overlay delete),
enrolling the check-retirements sync cluster and creating the
resolve-convention-home cluster (sync script, registry entry, CI job).
**Stacked on the Phase 2b PR (#3597)**; expect a trivial registry/ci.yml
merge with the 2c PR (#3601) whichever lands second.

## Fix

Reading side: audit resolves home → topic doc → dual-read (retired file
is authority while present, WARN every run) → defaults; retired
user-global/overlay layers read nowhere, WARN-visible. Setup: `check`
reports the four resolver outcomes distinctly (exit 1 = INFO
unconfigured, exit 3 causes = FAIL ask-don't-infer) plus the two fixed
retirement lines; `apply` binds the home on operator confirmation only
(marked-region append, never outside it), converges the topic doc (the
old file's values are the migration source), then per-record gated
cleanup. config-cascade and retired-conventions Implementers rows
rewritten in the same PR per the doctrine's row rule. Bumps:
plugin-quality 0.6.11, claude-config 0.40.5.

## Verification

Deterministic consumer-repo sim
(`scripts/pilot-plugin-quality-sim.test.sh`, 23 assertions, wired into
the new resolve-convention-home-sync CI job): populated-AGENTS.md region
append leaves prose byte-identical; resolver exit codes; exact detection
TSV for both records; migrate-gate refusal without `--i-migrated`; clean
+ re-detect clean; CRLF root file. Validator (append-only + wiring +
eval-per-record) green against origin/main; both sync clusters
`--check`/`--check-bump` green; drift check green; resolver 61/61 and
helper 174/174; markdownlint, shellcheck, eval lint, lane coverage,
catalog/cheatsheet green; skill-quality PASS on both touched skills
(audit SKILL.md trimmed back under the 500-line cap).

## Related

Refs #3596/#3597 (mechanism), #3600/#3601 (2c), ADR 0018, config-cascade
§ Expression doctrine, retired-conventions convention. **POST-PILOT USER
GATE:** this pilot is the template the user reviews before any other
surface migrates — in particular seven flagged doctrine calls (overlay
delete-not-migrate; no content_match on r002; WARN routed through the
r002 record in setup while user-global stays prose-only; audit-side
resolver exit-3 report-and-continue; dual-read eval living audit-side;
records stamped with the shipping version; the gitignore-overlay
recommendation dropped from the migrated surface). No other surface
migrates until ratified.

Co-authored-by: ksextonmelodic <ksextonmelodic@gmail.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.

mechanism: ship retirements.yaml + shared check-retirements helper + pointer-line resolver (Phase 2b)

2 participants