Skip to content

[Dev Tooling] Extend Markdown linting special AI agent prompt rules to AGENTS.md - #788

Draft
lisa-tarbo wants to merge 3 commits into
mainfrom
markdown-lint-fix
Draft

[Dev Tooling] Extend Markdown linting special AI agent prompt rules to AGENTS.md#788
lisa-tarbo wants to merge 3 commits into
mainfrom
markdown-lint-fix

Conversation

@lisa-tarbo

Copy link
Copy Markdown
Collaborator

Background

Small enhancements to the markdown linting system
Continues with work done on this PR : #746

Details

  1. Reduced line length so fixed changelog.md with long paragraphs. Will use doc writer agents to keep lengths <650 in future
  2. Extend which files have the special AI Agent prompt rules. Now AGENTS get the rules as clarified below

Prompt files (.claude/agents/, .claude/commands/, .github/templates/, and now AGENTS.md) extend the base doc rules with two extra restrictions, both aimed at the same idea: a fenced code block's language tag is a trust signal, not syntax highlighting, since these files are read by Claude as instructions rather than rendered as docs for humans.

MD040 — restricted fence-language vocabulary. Regular docs can label a fence with any language. Prompt files are restricted to exactly three: markdown (a template of expected model output), bash (commands the model may run), and text (untrusted data interpolated into the prompt — never instructions). Adding a new language to this list is a trust decision about what that fence type means, not just a formatting fix.

MD046 — code blocks must be fenced, not indented. This closes a loophole in rule 1: an indented block carries no language label at all, so it could sidestep the vocabulary restriction entirely. Forcing every block to be a fence means every block has to declare what it is.

What not done

  • Keeping scope of PR small so not addressing improvements to GitHub workflows to that linting can be done on the prompts inline
  • Not adding linting to CI. In another issue

Comment thread .markdownlint-cli2.yaml
Comment on lines +17 to +26
# docs — same trust model as .claude/agents/*.md and .github/templates/*.md. They share a
# directory with human-facing docs (README.md, README-*.md), so scope this to the exact
# files rather than a directory cascade.
overrides:
- filter:
- AGENTS.md
- .github/workflows/AGENTS.md
config:
extends: ./.markdownlint-prompts.yaml
combine: replace

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please verify this block actually takes effect — I think it may be a silent no-op, for two independent reasons.

  1. overrides / filter / combine don't appear in the documented markdownlint-cli2 config properties I could check (config, customRules, fix, frontMatter, gitignore, globs, ignores, markdownItPlugins, modulePaths, noBanner, noInlineConfig, noProgress, outputFormatters, showFound). combine: replace in particular reads like ESLint/Prettier syntax rather than cli2's. If cli2 ignores unknown top-level keys, this parses fine and does nothing.
  2. Even if it is supported, it fights this file's own header comment: "a plain .markdownlint.* file in the same directory overrides this file's config property". Root .markdownlint.yaml sits beside this file, so for root-level AGENTS.md the discovered config should win over anything rule-related declared here. .github/workflows/AGENTS.md has no directory config, so it also resolves to the root .markdownlint.yaml.

Cheap way to settle it: temporarily add a ```python fence to AGENTS.md and run uv run prek run markdownlint-cli2 --all-files. If MD040 doesn't fire, the override is inert. (I couldn't run the linter in my sandbox — no node/network — so this is unverified either way.)

If it turns out not to work, the per-file mechanism that's known-good at any cli2 version is an inline configure comment at the top of each AGENTS.md:


Downside is it duplicates the vocabulary instead of sharing .markdownlint-prompts.yaml, which loses the "adding a language is a trust decision made in one place" property. Worth the tradeoff discussion in the PR rather than picking silently.

Comment thread docs/changelog.md
File links in historical chat messages now show as plain text instead of downloads. Chatbots and pipelines that use an assistant node still open and still run as before. See [Migrate Assistants](how-to/assistants_migration.md).

## Sep 1, 2026
* **NEW** An embedded widget channel can now require an **OAuth** token instead of its embed key, using the new **Credential mode** setting on the channel. In OAuth mode every request is validated against a token minted by your own backend, the embed snippet shown in Open Chat Studio includes a sample `authTokenProvider` implementation, and the widget must be on version 0.12.0 or later. Existing channels keep the embed-key mode they already have. Leaving the channel's allowed domains blank marks the channel as a server-only integration, so any request from a browser is refused. See [OAuth credential mode](chat_widget/reference.md#oauth-credential-mode).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This line is still over the new limit — it's between 651 and 669 characters (matches ^.{651,}$, not ^.{670,}$), so MD013 will fail here after the drop to 650. It's the only remaining offender I found across all tracked markdown outside docs/api/; the one other >650 hit is .claude/agents/documentation-pr-reviewer.md:3, which is inside YAML front matter and therefore excluded by default.

Splitting it after ...mode they already have. matches the sentence-boundary style used for the other three entries in this PR.

Comment thread .markdownlint.yaml
# Line length — reduce progressively after long lines are fixed
MD013:
line_length: 750
line_length: 650

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The ratchet needs a matching change on the producer side or it'll un-ratchet itself. docs/changelog.md is the file that keeps forcing this limit up, and most of its entries are written by the update-changelog workflow from .github/templates/changelog-instructions.md — which has no line-length guidance in its "General Changelog Guidelines" section. So the next automated changelog PR will land another single-line >650-char entry.

The PR description says "will use doc writer agents to keep lengths <650 in future", but the automation path doesn't go through those agents. One line in the template ("Wrap entries at sentence boundaries; keep each source line under 650 characters") would close it. Fine as a follow-up if you want to keep this PR small, but it's worth an issue rather than nothing.

@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Review: markdown linting extensions

The trust-model reasoning in the description is sound, and extending it to AGENTS.md is the right call — those files are read as instructions, not rendered. Two things need attention before this leaves draft, plus some smaller notes.

Needs attention

  1. The overrides: block may be a no-op. overrides / filter / combine aren't in the markdownlint-cli2 config properties I can verify, and even if they are supported, this file's own header comment says a same-directory .markdownlint.* wins over the cli2 file's rule config — and root .markdownlint.yaml sits right beside it. Please confirm empirically (add a ```python fence to AGENTS.md, run the linter, check MD040 fires). Details and a known-good fallback in the inline comment. I couldn't run the linter in my environment, so I'm flagging this as unverified, not confirmed broken.

  2. docs/changelog.md:35 still exceeds 650 (~651–669 chars), so MD013 fails as-is. It's the only remaining offender in tracked markdown outside docs/api/.

Verified fine

  • .github/workflows/CLAUDE.md is indeed just @AGENTS.md, so the new ignores entry is correct.
  • .github/workflows/AGENTS.md uses only a bash fence and no indented blocks; root AGENTS.md uses only a bash fence. Both have an H1. So if the override does activate, neither file newly violates MD040/MD046/MD041.
  • The four changelog line splits are all at sentence boundaries, and markdown lazy continuation keeps each one inside its list item, so rendering is unaffected. (Couldn't run zensical build here to confirm visually.)
  • scripts/update_confluence_release.py renders markdown to HTML rather than parsing lines, so wrapped entries don't affect it.

Smaller notes

  • ignores will keep growing. - '**/CLAUDE.md' covers this case and any future CLAUDE.md in one entry, instead of adding a path each time someone drops a new @AGENTS.md stub.
  • AGENTS.md "Gotchas" now under-documents the setup. It currently says the mechanism is per-directory .markdownlint.yaml discovery ("A subdirectory config replaces rather than merges, so always extends the parent"). This PR adds a third mechanism that isn't mentioned there, so the next person editing lint config won't know root AGENTS.md is governed by an overrides block. Worth one bullet — especially since the file being linted is the file describing the linting.
  • /create-release reads git diff docs/changelog.md and asks the model to itemize by **NEW** / **CHANGE** prefix. A wrapped continuation line shows up in that diff as an added line with no prefix, which the model could drop or promote to its own entry. Indenting continuation lines by two spaces would make them structurally part of the list item and unambiguous to any line-based consumer — MD007 and MD030 are both off, so nothing objects.
  • Cross-branch risk: this lowers the limit on main, but docs/chat_widget/changelog.md ships from widget-develop. Nothing on this branch exceeds 650, but long lines added there under the old 750 limit would start failing when widget-develop merges back. Worth a quick check on that branch.

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.

1 participant