Skip to content

Add three rules to the shared blocks and cut 0.3.1 - #53

Merged
sehkone merged 4 commits into
mainfrom
sehkone/issue-50
Aug 12, 2026
Merged

Add three rules to the shared blocks and cut 0.3.1#53
sehkone merged 4 commits into
mainfrom
sehkone/issue-50

Conversation

@sehkone

@sehkone sehkone commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Three rule additions to the shared blocks, cut as 0.3.1 in the same branch.

What lands

  • workflow / GitHub issues and PRs — how to recover an issue or pull request body that was overwritten. The block already said how to avoid writing to the wrong one and nothing about what to do once a body had gone anyway. That half is unguessable: GitHub keeps every prior version, but only userContentEdits in the GraphQL API exposes them, and nothing in the gh command line suggests it exists. The bullet names the query, names --body-file as the restore, and says not to retype the body from memory.
  • changelog — a released file carries no [Unreleased] section, plus a rewrite of the no-references bullet so its reasoning covers the rule it sits under. The categorical rule was justified entirely by Closes #N and Part of #N being automation keywords, which left a plain reference resting on nothing; the reader argument reaches the whole rule, and the keyword case stays as the sharper one.
  • workflow / Commit messages — do not build a commit body out of literal \n escapes. They land in the subject as characters, the body comes out empty, and git exits 0, so one mistake breaks three rules of that section at once with no lint downstream that reads commit subjects.

Release

Rule additions are MINOR, which shifts down to PATCH below 1.0.0, so 0.3.1. The cut is in this branch rather than a follow-up:

  • ## [Unreleased] became ## [0.3.1] - 2026-08-12, folding in the drift-warning entries that were already sitting there, and the link reference became a compare range. No [Unreleased] heading or link reference is left behind — which is the rule this release adds.
  • The reworded no-references bullet is under ### Changed, not ### Added. Its rule does not move and only the reasoning under it does, but the bullet shipped in 0.3.0, so a consumer of that release sees the text in its own AGENTS.md change. Same call 0.2.1 made for the agentcoop wording rewrite.
  • Both changed blocks differ from 0.3.0, so check_release_surface.sh has something to compare and the tag can be cut.

Verification

Run on the final tree, all green:

  • python3 scripts/lint_blocks.py — blocks OK. The userContentEdits line is the tight one at 75 of 76 columns.
  • All seven script suites — render, apply_blocks, sync, release_surface, lint_blocks, pin_file, check_drift.
  • markdownlint-cli2 "**/*.md" — 0 issues in 9 files.
  • release.yml's notes extraction simulated against 0.3.1: 50 lines, non-empty. This is the step that fails after the tag is pushed, so it was worth checking before the tag exists.

After merge

Tag 0.3.1 by hand, then the README's "Changing a block" step 5 — confirm the pin in all thirteen consumers.

Closes #50
Closes #51
Closes #52

The block says how to avoid writing to the wrong issue or pull request
-- confirm the target with a read first, re-verify every write with a
structured `--json` query -- and says nothing about what to do once a
body has been overwritten anyway.

That gap is worth a bullet because the recovery cannot be worked out in
the moment. GitHub keeps every prior version of a body, but only
`userContentEdits` in the GraphQL API exposes them, and nothing in the
`gh` command line suggests it exists. An agent that does not know this
reports the text as lost, or reconstructs it from what it remembers --
and a body that reads like the original and is not is harder to notice,
and harder to undo, than an empty one.

There is a path that reaches it in normal use. Refining an issue
rewrites the issue body, which is an overwrite rather than a create,
and the agent doing it reads the consuming repository's AGENTS.md.

One bullet, because nothing has gone wrong yet. The prevention rules
work -- a session doing dozens of `gh` writes clobbered nothing -- so
this is for the case where they do not, and it earns its lines by being
unguessable rather than by being common.

Closes #50
The block says how to write an entry and nothing about the sections
those entries sit in. One convention is missing, and this repository has
been caught by it twice: 0.1.2 and 0.1.3 were both tagged with an empty
`[Unreleased]` left behind, and the 0.1.4 entries were still sitting
under that heading, which would have extracted an empty body and
aborted the release after the tag was pushed. `release.yml` builds the
notes by scanning for the heading that matches the tag, so this is not
cosmetic tidying -- it is the difference between a release and a tag
with no release behind it.

The knowledge lives in one commit message here. All thirteen consuming
repositories keep a CHANGELOG.md and none of them can see it.

The no-references bullet is rewritten in the same change because its
reasoning did not reach its rule. The rule is categorical -- no issue or
pull request references -- while everything justifying it was about
`Closes #N` and `Part of #N` being automation keywords. A plain (#123)
is neither a keyword nor a command to a bot, so a reader holding one had
nothing to weigh. The reason that does reach it is the reader: a release
note names something in a tracker they may not be able to open, and the
history behind it is git's to hold. The keyword argument survives as the
sharper case rather than the whole of it, and the bullet loses the
sentence that repeated the one before it.

Closes #51
The block says a commit separates its title from its body with a blank
line. It does not say that the usual way of getting that wrong produces
a commit git accepts without complaint: passing the whole message as one
`-m` argument with `\n` in it puts the escapes in the subject as two
literal characters, leaves the body empty, and exits 0 with nothing on
stderr.

One mistake breaks three rules of that section at once -- the title runs
past 50 characters, there is no blank line, and there is no body to
explain why. Nothing downstream catches it. No lint reads commit
subjects, and by the time a person reads the log the commit is history,
needing a rebase to fix once it has been pushed.

It is also a mistake only an agent makes, which is why it belongs in
these blocks rather than in a contributing guide. A person running `git
commit` gets an editor and never composes the message as a single shell
argument. An agent assembling a command string is exactly who reaches
for `\n`, and every commit an agent writes in these repositories goes
through that path, including the ones an AgentCoop run makes.

Closes #52
The three block changes on this branch each add a rule, which the
grading in README.md makes MINOR and shifts down to PATCH below 1.0.0.
They touch `blocks/`, so the surface guard has something to compare
against 0.3.0 and the tag can be cut -- unlike the last two releases,
which existed only because `repos.json` moved.

The drift-warning entries were already sitting under `[Unreleased]`.
They fold into this version rather than staying behind it. A released
file carries no `[Unreleased]` section, and `release.yml` builds the
notes by finding the heading that matches the tag, so an empty section
left there fails the release after the tag has already been pushed --
which is one of the three rules this release adds.

The reworded no-references bullet is `### Changed` rather than
`### Added`. The rule itself does not move and only the reasoning under
it does, but that bullet shipped in 0.3.0, so a consumer of that release
sees the text in its own `AGENTS.md` change. That is the test an entry
has to pass, and it is the same call 0.2.1 made for a wording-only
rewrite of the `agentcoop` block.
@sehkone
sehkone merged commit ffaf556 into main Aug 12, 2026
1 check passed
@sehkone
sehkone deleted the sehkone/issue-50 branch August 12, 2026 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant