Skip to content

Route agent instructions instead of restating them - #13

Merged
tony merged 7 commits into
masterfrom
house-style
Aug 22, 2026
Merged

Route agent instructions instead of restating them#13
tony merged 7 commits into
masterfrom
house-style

Conversation

@tony

@tony tony commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

AGENTS.md is read on every task, and CLAUDE.md symlinks to it, so all 364 lines loaded whatever was being changed — the MCP swap gotchas and the comment policy included. A root instruction file should answer which policy applies to the thing being changed, not hold every policy itself.

This splits the policy in three and leaves the root file as a router.

Layout

  • AGENTS.md — a short router: change discipline, then one route per class of change, and nothing else.
  • .github/WRITING.md — how we write: voice, README, changelog, release notes, commit messages, XML documentation, source comments, terminology, Markdown, code blocks, error messages, slop prevention.
  • .github/CONTRIBUTING.md — how we work: setup, the socket root, building, tests, the gates, the MCP server, what a change must carry, pull requests, review, releases, compatibility.

The root CONTRIBUTING.md is gone; .github/CONTRIBUTING.md replaces it. GitHub reads a contributing guide from that location, so the new-issue and new-pull-request pages are unaffected. CLAUDE.md follows the symlink with no separate change.

Routes are phrased as conditions — "for changes to X, follow Y" rather than a bare "read Y" — so an agent re-evaluates per change instead of treating the pointer as a one-time startup instruction. Each listed file is stated to be the single home for its subject, so a rule that appears twice has one governing copy.

This is the content pass, not a skeleton

An earlier version of this branch landed the layout with every section body as the literal string <placeholder>. That commit is gone; the branch is rebuilt from master as six commits carrying real content. Nothing in the tree says <placeholder> any more.

The prose is drawn from what AGENTS.md and the old CONTRIBUTING.md already said, plus what the tree actually does. Where the two disagreed, the tree won:

  • The toolchain claim was wrong. AGENTS.md said dotnet "resolves through mise". There is no mise.toml in the repo, and CI does not use mise at all — it installs the pinned SDK with actions/setup-dotnet from global-json-file. mise exec -- is a local convention, and CONTRIBUTING.md now says so.
  • Two validators were documented; there are five. verify_workflows.py, sync_snippets.py --check and dump_tools.py --check were not mentioned anywhere.
  • <example> is not a house convention. It appears exactly once in 27k lines of src/. WRITING.md says so rather than recommending it.
  • How tested examples work was undocumented. The only account of it was a docstring in sync_snippets.py and an XML comment on a test class. examples/README.md is new and covers it where somebody editing an example already is.
  • The ≤50-character subject rule is not followed. 24 of the last 60 subjects exceed it, the longest at 75. WRITING.md records ≤72 with ≤50 preferred, matching practice. No history is rewritten.

Three fixes so the guides describe the repository

  • CHANGELOG.mdalpha.5, alpha.6 and alpha.7 were bracketed like links with no reference definition, so they rendered as literal text. All three tags exist; the definitions are added.
  • README.md — titled libtmux for .NET, matching every sibling port, and the alpha warning now states the terms the family shares: an -alpha prerelease tag, an unsettled API, no deprecation period, pin an exact version, not recommended for production. The previous wording also claimed behaviour is proven "on every commit", which the tmux matrix does not do — it runs on its own workflow.
  • Install verbdotnet add package becomes dotnet package add in the root README, each package README, and the quality bar that quotes it. Verified against the pinned SDK (10.0.302), which accepts the noun-first form and its --prerelease flag.

How examples are verified

Two mechanisms, catching different failures, now written down in examples/README.md:

  • ReadmeExampleTests compiles every C# block in the nine shipped documents against the real assemblies, and executes the ones tagged ```csharp run against a tmux server of their own.
  • sync_snippets.py + SnippetContractTests cover drift: a block anchored with <!-- snippet: Name --> is materialized from a #region of the same name, --check fails the build on any hand edit, and every published region must be an [Example] method that runs.

CONTRIBUTING.md lists the sync step beside the check, and WRITING.md says which tag to use and why.

Verified

  • dotnet build LibTmux.slnx --configuration Release --warnaserror — 0 warnings, 0 errors.
  • sync_snippets.py --check — 9 snippets current.
  • verify_public_api.py, verify_capabilities.py, verify_workflows.py — all clean.
  • pytest eng — 10 failed, 1103 passed. Identical on master, confirmed by running the same suite at origin/master in a scratch worktree. The failures need the Python libtmux checkout that CI clones and a local run does not have; they are not from this branch.
  • No <placeholder> anywhere; every relative link in the three documents resolves; CLAUDE.md still resolves to the router; no line over 80 columns; no GitHub alert blocks.

Deliberately not done

  • Anchoring more blocks to snippet regions. Only one block in the root README is anchored today. Everything else is still compiled and run, so nothing is unverified — anchoring would only add drift protection, and is worth doing per block rather than in bulk.
  • The other six ports. Rust, Java, TypeScript, Swift and C++ still hold the placeholder skeleton, and the family is split on alpha-warning markup — TypeScript, Swift and C++ use > [!WARNING] blocks that .NET, Rust and Java do not. Untouched here.
  • State the comment bar in CONTRIBUTING #9 edits the root CONTRIBUTING.md this branch deletes. Its prose is a good candidate for the source-comments section; merge order is a judgement call.

@tony tony changed the title Docs(refactor[agents]): Route instead of restate Route agent instructions instead of restating them Aug 22, 2026
tony added 7 commits August 22, 2026 07:47
why: The prose conventions existed as habit and as scattered rules inside
AGENTS.md, so every new document argued them out again and a contributor
had nowhere to look. Splitting them out gives them one home, and lets a
change that touches no prose skip loading them.

what:
- Add .github/WRITING.md: voice with a diction table, README, changelog,
  release notes, commit messages, XML documentation, source comments,
  terminology, Markdown, code blocks, error messages, slop prevention
- Record the commit format this repository already uses, and say plainly
  that Conventional Commits are not used and should not be introduced
- Ground the XML documentation rules in the tree: one-line summaries,
  verb-first, remarks for the contract, and <example> as the rare case
  it actually is rather than a default
- Ban GitHub alert blocks, because nuget.org renders this README and
  does not understand them
- Say how documented examples are verified: every C# block is compiled
  and a "csharp run" block is executed, with anchoring as the separate
  guarantee against drift
why: AGENTS.md and CONTRIBUTING.md both described the gates, and each
held material the other lacked — the socket root, NU1004 and the macOS
lane only in one, what a change must carry only in the other. Two
partial copies is worse than one, because a contributor cannot tell
which is short.

The file moves under .github/ so one location answers for it. GitHub
reads a contributing guide from there, so the new-issue and
new-pull-request pages are unaffected.

what:
- Take the socket root rule, the mise-pinned toolchain, the gate job,
  the pack-before-integration order, NU1004, the macOS wrapped-line
  finding, the MCP swap, and the evidence recording boundary
- Correct the toolchain claim: there is no mise.toml, and CI installs
  the SDK with setup-dotnet rather than going through mise
- List all five document validators; AGENTS.md named only two
- Point at examples/README.md for the example mechanism, and name the
  sync step that brings a changed example across
- Add Review, Releases and Compatibility, which nothing stated before
- Point at WRITING.md for prose and commit format instead of restating
why: CLAUDE.md symlinks here, so all 364 lines loaded on every task in
the repository — the MCP swap gotchas and the comment policy included,
whichever file was being touched. A root instruction file should answer
which policy applies to the thing being changed, not hold every policy
itself.

what:
- Cut to change discipline and a Which policy applies list
- Phrase each route as a condition on what is being changed rather than
  an unconditional instruction to go read a file
- State that each listed file is the single home for its subject,
  replacing the old arrangement where two files answered the same
  question at different lengths
- Leave nothing here that WRITING.md or CONTRIBUTING.md now carries
why: The title named the package rather than the port, so a reader
arriving from another language could not tell which of the family this
is. The alpha warning also claimed more than the others do, and claimed
it differently, which makes the family's terms look inconsistent when
they are not.

what:
- Title the README "libtmux for .NET", matching every sibling port
- State the alpha terms the same way across the ports: an -alpha
  prerelease tag, an unsettled API, no deprecation period, pin an exact
  version, not recommended for production
- Drop the claim that behaviour is proven on every commit; the tmux
  matrix runs on its own workflow, not on each commit
why: .NET 10 added the noun-first CLI forms and Microsoft recommends
them; the pinned SDK takes "dotnet package add" and its --prerelease
flag. The old form still works, so this is about matching the toolchain
the repository pins rather than fixing a break.

what:
- Rewrite the install command in the root README and in each package
  README to "dotnet package add"
- Track the same change in the quality bar, which quotes the README
- Leave "dotnet tool install" alone; it is already noun-first
why: Every version heading is bracketed like a link, but only alpha.1
through alpha.4 had a reference definition. The three newest headings
rendered as literal text with brackets around them, which reads as a
broken link rather than a deliberate plain heading.

what:
- Define alpha.5, alpha.6 and alpha.7 against their release tags, all
  three of which exist
why: The README's C# is compiled and run because it is quoted from an
example, and the only account of how that works was a docstring in
sync_snippets.py and an XML comment on the test. Somebody adding an
example had nowhere to learn the region markers, and somebody editing a
published block learned about --check from CI failing on a rule no
document stated.

what:
- Add examples/README.md, where somebody editing an example already is:
  what an [Example] is, the topic and region naming, the dedent, the
  usings option, and the nine documents that publish
- Say the loop runs one way — edit the example, then sync; never edit
  the block — and that --check is what CI runs
- Name both failure modes SnippetContractTests holds: a region no
  example runs, and an example the snippet reader cannot see
- Separate the two guarantees: every C# block is compiled and a
  csharp run block is executed, while anchoring is what stops a
  published block drifting from its source
- Link it from the README's documentation list
@tony
tony merged commit 8351640 into master Aug 22, 2026
21 checks passed
@tony
tony deleted the house-style branch August 22, 2026 13:35
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