Repository navigation
Settle the Markdown Lint Exclusion Seam as a Nested Config - #1494
Conversation
Settles #1487, which asked what to do about `ptr727/Financial-Modeling`'s modified `.markdownlint-cli2.jsonc`. The issue put up three dispositions: accept the divergence, re-vendor and erase the two exclusions, or declare a seam. This takes the seam. ## What the seam is A repository excluding a subtree of its own puts a `.markdownlint-cli2.jsonc` carrying its own `ignores` beside that content, rather than editing the shared root config. The canonical stays `verbatim` and fleet-generic, and the rule block it carries keeps its byte-level drift detection. Measured against markdownlint-cli2 0.23.2, the version bundled in the pinned `markdownlint-cli2-action` v24.2.0: - A nested config's `ignores` is honored; `globs` and `gitignore` are read only from the config in the directory the linter is invoked from, so a nested copy of either is inert. - Nested patterns resolve against the directory holding the file. A `**/`-prefixed pattern works there because it is depth-relative; a path written from the repository root matches nothing and reports no error. - A nested config's settings merge with those above it, so the fleet rule block still governs the files it does not exclude. - The exclusion filters files even when a run names them explicitly as arguments, which is how `scripts/docker_lint.py` invokes the linter. ## Why not the alternatives `accept` leaves that repository permanently reporting as modified fixed content and needing a hand merge on every hub change to the file. Dropping the file to `intent`, which is what `.editorconfig-checker.json` does for the same repo-local-exclusions reason, would stop `MD013`, `MD033`, `MD046`, and `MD060` being judged at all, per `spec/fidelity-model.md`. A plain `re-vendor` puts a committed document archive and the owner's freeform notes back under a bare local run, which is the failure class #1466 was filed about. ## Second carrier `Blog` excludes `content/**` and `themes/*/**` through the CI `markdown-exclude-globs` input only. Once it re-vendors the canonical that #1474 gave a `globs` key, a bare local run lints the vendored theme and the WordPress archive. The seam covers it, and `themes/` takes `*/**` rather than `**/*.md` so its own `themes/README.md` stays linted. ## Filed rather than fixed here Whole-unit review passes over the four changed canonical units raised 35 findings that predate this change, none introduced by it. Two are verified defects in fleet-carried content: the `MD060` comment has `compact` and `tight` inverted, and its stated rationale is false, since the rule's default already allows both spacings. Two more follow from #1474: the config's `globs` key is additive to command-line arguments, so a per-file invocation lints the whole tree, and `globs` covers `.md` but not `.markdown`. `reports/canonical-review.json` records the passes. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The seam this branch settles is falsified by the audit dimension that measures the same property. `spec/project-types.json`'s `parity.markdownlint` asserts "One .markdownlint-cli2.jsonc", at `letter` verdict and `appliesTo` `*`, and `AUDIT.md` "4. Per-Dimension Checks" states it in prose as "one config per linter". So the first repository to follow the prescription in `spec/divergences.json` would have drawn a `linter-parity` drift finding for doing what `CODESTYLE.md` now mandates. Both now say a nested `.markdownlint-cli2.jsonc` merges into that config rather than forking it. The framing is merge semantics rather than what the nested file carries, because two narrower attempts were both wrong: keying on a subtree "the repository does not author" splits from the scope wording every other surface uses, and permitting a nested config "carrying only a subtree exclusion" would have failed this repository's own `host-setup/agent-safety/claude/.markdownlint-cli2.jsonc`, which carries an `MD041` rule override and no exclusion at all. `docs/reusable-workflows.md` also stops claiming Blog has already migrated. It has not: both nested paths 404 and its `test-pull-request.yml` still carries `markdown-exclude-globs`, which the same section reprints as the CI-only alternative, so the section asserted two contradictory current states for one repository. The Blog shapes are written as a migration it is owed. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Findings from the branch's own review passes, none of them cosmetic. `docs/reusable-workflows.md` said "Only `ignores` works from a nested config", which this repository's own `host-setup/agent-safety/claude/.markdownlint-cli2.jsonc` falsifies: it carries an `MD041` override and no exclusion, and a nested `config` block works precisely because settings merge. The text now states the merge and names `globs` and `gitignore` as the inert pair. Two claims about `ptr727/Blog` were false. Its root config predates the `globs` key, carrying neither `globs` nor `ignores`, so a bare local run there exits 2 on a usage error rather than linting `content/` and `themes/`, and its migration needs the re-vendor as well as the nested files. It was also called the only repository owed the seam, which the `Financial-Modeling` row in the same change contradicts. The seam's scope named "a committed data archive or a vendored theme it does not author" while the ledger row blesses excluding `notes/forms-decisions.md`, a file that repository's owner writes. The surfaces now name the category, content a repository does not treat as authored prose, with the archive, the theme, and a hand-maintained record as its examples. `parity.markdownlint` and the `AUDIT.md` sentence said a nested config "merges into that config rather than forking it", which is true of every nested config and so can never be false, leaving a `letter`-tier auditor no predicate. Both now say the count is of the root config, which is a hand count of one path, and neither extends the editor-parity claim to a nested `ignores`, the one surface where that parity does not hold. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 32 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (6)
📒 Files selected for processing (10)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🟢 Approval recommended
The changes consistently update the spec, audit wording, documentation, and canonical guidance to support nested markdownlint exclusions without introducing behavioral or contract inconsistencies.
Pull request overview
This pull request documents and codifies a fleet-wide seam for repo-local Markdown lint exclusions by using nested .markdownlint-cli2.jsonc files colocated with excluded content, keeping the repository-root config canonical and verbatim for drift detection.
Changes:
- Updates audit/spec parity language to clarify that the linter-parity check counts only the repository-root
.markdownlint-cli2.jsonc, allowing nested configs without failing parity. - Records the governed divergence resolution path for
ptr727/Financial-Modeling(re-vendor root config, move repo-local ignores into nested configs). - Updates linting documentation and the markdownlint canonical config commentary to reflect the nested-config seam and the fleet-wide
node_modulesignore.
File summaries
| File | Description |
|---|---|
| spec/project-types.json | Clarifies markdownlint parity assertion to count only the root config and permit nested configs. |
| spec/fidelity-model.md | Explains why markdownlint remains verbatim with repo-local excludes moved to nested configs. |
| spec/divergences.json | Adds a tracked Financial-Modeling divergence disposition describing the nested-config migration. |
| reports/canonical-review.json | Updates canonical review ledger entries/digests for the affected units. |
| docs/reusable-workflows.md | Documents the nested-config seam as the correct way to exclude unowned/vendored Markdown. |
| CODESTYLE.md | Codifies the nested-config approach for repo-local markdownlint exclusions. |
| AUDIT.md | Updates linter-parity prose to state nested .markdownlint-cli2.jsonc does not count as a second config. |
| .markdownlint-cli2.jsonc | Adds explanatory comments tying the fleet-wide ignores list to the nested-config seam. |
| .github/skills/python-codestyle/references/profiles.md | Removes outdated guidance about markdownlint rule disabling at repo root (generated copy). |
| .github/skills/comment-and-doc-style/SKILL.md | Adds nested-config seam guidance (generated copy). |
| .claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md | Mirrors the generated skill update for the Claude plugin distribution. |
| .claude-plugin/fleet-skills/skills/comment-and-doc-style/SKILL.md | Mirrors the generated skill update for the Claude plugin distribution. |
| .claude-plugin/fleet-skills/.source-digests/python-codestyle | Updates plugin source digest for the python-codestyle skill distribution. |
| .claude-plugin/fleet-skills/.source-digests/comment-and-doc-style | Updates plugin source digest for the comment-and-doc-style skill distribution. |
| .agents/skills/python-codestyle/references/profiles.md | Removes outdated markdownlint guidance from the authored skill source. |
| .agents/skills/comment-and-doc-style/SKILL.md | Adds the nested-config seam guidance to the authored skill source. |
Review details
- Files reviewed: 16/16 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@coderabbitai review |
|
…g, and the Release-Trigger Retirement (#1489) Promotes thirteen merged pull requests from `develop` to `main`. ## What this promotes - **#1486** State the `host-tools.json` carry rule and stop the empty-overlay warning. `spec/files.json` now requires the declaration unconditionally, and `host_gate.py` no longer warns on an empty one. - **#1484** Fan the validator's pytest leg out over a `python-versions` input, so a caller with more than one interpreter no longer silently loses its other legs to a pinned 3.13, with an entry guard that refuses a value `fromJson` would otherwise admit. - **#1476** Retire the publish-on-merge release trigger, which `spec/files.json` applied to an interface contract whose task has no publish-on-merge path. - **#1479** Ship the release caller snippet and retire the not-yet-released claim. - **#1474** Exclude `node_modules` from markdownlint and Docker lint discovery at any depth. - **#1468** Move the carried-surface cluster off decision, recording the measurements and what stays unmeasured on the issues that hold them. - **#1498** Correct the release-caller snippet's publish-on-merge claim, raised by CodeRabbit against this promotion and fixed on its own branch, since a promotion PR's head is `develop`. - **#1494** Settle the markdown lint exclusion seam as a nested config. - **#1492** Check declared deployment environments and fix the carried-payload rule. - **#1501** Move the session handoff to a chain of labeled issues. Two of its units are verbatim fidelity, `AGENTS.md` "Session Scope" and `GOVERNANCE.md` "Communicating with the User", so every fleet repo picks them up on its next resync. - **#1505** Refuse a bare handoff link rather than reading it as no successor, answering a finding raised against this promotion. - **#1504** Reject a deployment environment name or branch carrying surrounding whitespace, answering two more. - **#1506** Encode an environment name before it becomes a path segment, delete a branch that cannot fire, and dedupe a registry name by case, answering two more and declining one on a reproduction. ## Closing references A `develop`-targeted pull request registers no closing reference, so the issues those pull requests settled close with this promotion. #1470 is the one that needs a word. Two of its seven acceptance items are not met as literally written, and the maintainer's decision to close it here anyway, with the basis for both, is recorded on the issue itself. Closes #1483 Closes #1473 Closes #1487 Closes #1482 Closes #1475 Closes #1470 ## Left open deliberately - **#1499**, **#1500** follow-ups #1501 filed rather than fixed. - **#1503** the validator-looser-than-its-consumer class, filed from findings on this promotion and deliberately not closed by it. Five instances recorded, and the fix is a design decision rather than a check. - **#1497** the Docker delta list never says to remove the `push:` block. - **#1472** the fleet-level pin call, deliberately not pre-empted by #1479. - **#1321**, **#1464** carry #1468's decision record and remain in their own scope. ## Verification `origin/main..origin/develop` merges clean, no end-of-line conflict. Each promoted pull request ran the fleet gate set on its own branch before merging; this promotion adds no content of its own. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01817rckKywjfoaEV5WF9TKs
Settles #1487.
The decision
#1487 put up three dispositions for
ptr727/Financial-Modeling's modified.markdownlint-cli2.jsonc: accept the divergence, re-vendor and erase its two exclusions, or declare a seam. This takes the seam.A repository excluding a subtree of its own puts a
.markdownlint-cli2.jsonccarrying its ownignoresbeside that content, rather than editing the shared root config. The canonical staysverbatimand fleet-generic, soMD013,MD033,MD046, andMD060keep byte-level drift detection.The alternatives cost more.
acceptleaves that repository permanently reporting as modified fixed content, needing a hand merge on every hub change to the file. Dropping the file tointent, which is what.editorconfig-checker.jsondoes for the same repo-local-exclusions reason, would stop the rule block being judged at all, perspec/fidelity-model.md. A plainre-vendorputs a committed document archive and the owner's freeform notes back under a bare local run, the failure class #1466 was filed about.Measured, not inferred
Against markdownlint-cli2
0.23.2, the build bundled in the pinnedmarkdownlint-cli2-actionv24.2.0:ignores**/-prefixed works; a repo-root path matches nothing and reports no errorglobs/gitignoreconfigblockglobsignoresand noglobsThe explicit-file-argument case matters because that is how
scripts/docker_lint.pyinvokes the linter.The audit check this would have broken
spec/project-types.json'sparity.markdownlintasserted "One.markdownlint-cli2.jsonc", atletterverdict andappliesTo*, withAUDIT.mdstating it in prose. The first repository to follow the prescription inspec/divergences.jsonwould have drawn alinter-paritydrift finding for doing whatCODESTYLE.mdnow mandates. Both now say the count is of the root config, so a nested one is not a second one.Two narrower wordings were tried and were wrong. Permitting a nested config "carrying only a subtree exclusion" fails this repository's own
host-setup/agent-safety/claude/.markdownlint-cli2.jsonc, which carries anMD041override and no exclusion. Keying on a subtree "the repository does not author" splits from the scope wording every other surface uses, and from the ledger row in this change.Second carrier
Blogis owed this too and has not adopted it. It excludescontent/**andthemes/*/**through the CI input only, and its root config predates theglobskey, so its migration is the re-vendor plus one nested file per excluded tree.themes/takes*/**rather than**/*.mdso its own authoredthemes/README.mdstays linted, and that placement also sits outside the vendored theme directories, where a re-vendor cannot delete it.Deliberately not done here
reports/divergences.mdis not regenerated.RESYNC.mdregenerates it "before using it as a work list", and generating it from this branch bakes in a canonical that exists nowhere yet: the run listed ProjectTemplate itself as a stale carrier of its own file, alongside about thirty lines of unrelated fleet movement from other unpromoted hub work. The ledger entry is the durable record and the report regenerates at the next resync.Filed rather than fixed
The review passes raised roughly 50 findings that predate this change, none introduced by it, split across two follow-up issues. Four are verified defects in fleet-carried content, including the
MD060comment havingcompactandtightinverted against the rule's own vocabulary.Verification
prose_lint.py(whole tree),repo_gate.py --check eol,spec/validate.py,build_dist.py --check,spec/audit.py --selftest,workflow_reuse.py --selftest,gh-write-guard.py --selftest, and 1171 unit tests, all clean.docker_lint.pyfor markdownlint, cspell, and editorconfig-checker, clean over 182 Markdown files.93b1f0d.A
develop-targeted pull request registers no closing reference, so #1487 closes with the promotion.🤖 Generated with Claude Code
https://claude.ai/code/session_01KZqEEfFr85oibauzz3GKm3