Move the pin out of .agents/ - #41
Merged
Merged
Conversation
`.agents/` is a generic name in a namespace where every tool marks its own -- `.claude/`, `.cursor/`, `.gemini/`. That left it open to a later tool claiming it, and open to being read as tool output and dropped into a `.gitignore`; five of the thirteen consuming repositories already ignore `.claude/`, so the habit is here. The directory held one file with no second one planned, so it was structure buying nothing while carrying both risks. `.agent-instructions.toml` names this system, and a single file has no directory anyone can ignore wholesale. The move cannot be a flag day. Both reusable workflows run these scripts from `@main` while each repository still carries whatever path its last apply wrote, so a hard switch would turn every repository red at once. The reader takes the old path where that is the only one present, and every write moves the repository onto the new one and deletes the old -- which makes the apply the migration, with nothing for anyone in a consumer to do. The fallback comes out once none is left. Writing the tests for that turned up a bug older than this change. Both drivers staged with `commit -a`, which covers modifications to tracked files and not a new path: delivering to a repository that had to gain a file -- the moved pin, or any pin at all in one being onboarded -- would have pushed rewritten blocks with no pin beside them, and the drift check would then have failed on a file it could not read. `sync.sh` decided "already current" with `diff --quiet`, blind to the same case, and would have skipped exactly the repository that needed the run. The changelog entries sit under `[Unreleased]` rather than a version: this changes no block and no roster entry, so the release-surface guard would refuse a tag for it, correctly. The move reaches consumers through `@main` on their next scheduled apply, and the entries fold into whatever release is cut next. Closes #40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves the pin from
.agents/instructions.tomlto.agent-instructions.tomlat the repository root, behind a compatibility window, and fixes two staging bugs the move exposed.The name
.agents/is generic in a namespace where every tool marks its own —.claude/,.cursor/,.gemini/. That leaves it open to a later tool claiming it, and open to being read as tool output and dropped into a.gitignore; five of the thirteen consuming repositories already ignore.claude/, so the habit is here. The directory held exactly one file with no second one planned..agent-instructions.tomlnames this system, and a single file has no directory anyone can ignore wholesale.Not a flag day
Both reusable workflows run these scripts from
@mainwhile each repository still carries whatever path its last apply wrote, so switching the path outright would turn every repository red at once until each merged the move.Instead,
pin_file.pyreads the old path where that is the only one present, and every write puts the pin on the new path and deletes the old file (and the directory, if it was alone in it). The apply writes the pin on every release it delivers, so a consumer migrates inside the pull request it was getting anyway — nothing to do in any of the thirteen. The fallback comes out in its own release once none is left.Two bugs the tests found
Neither is new; the move is what made them reachable.
git commit -a, which covers modifications to tracked files and not a new path. Delivering to a repository that had to gain a file — the moved pin, or any pin at all in a repository being onboarded — would have pushed the rewritten blocks with no pin beside them, and the drift check would then have failed on a file it could not read. Both nowgit add -A. Inapply.ymlthat is safe because the two checkouts are removed first, which the comment there now says is load-bearing rather than tidiness.sync.shdecided "already current" withgit diff --quiet, which is blind to untracked files — so it would have reported the repository that needed the run as needing nothing. It now asksgit status --porcelain.No tag for this
The changelog entries sit under
[Unreleased]. This changes no block and norepos.jsonentry, socheck_release_surface.shwould refuse a tag for it — correctly, by its own reasoning that scripts and workflows reach consumers from@mainrather than from a release. The move takes effect for every repository on its next scheduled apply, and the entries fold into whatever release is cut next. That release is MINOR by the version scheme's interface clause, whatever else it carries.Verification
scripts/test_pin_file.pyis new (18 checks) and covers both paths, a write that migrates, a directory left alone because something else is in it, a repository holding both files, and one holding neither. CI runs it.test_apply_blocks.pygains an end-to-end migration case;test_sync.py's consumer fixture is deliberately still on the old path, so the fan-out is proved to carry both halves — the new file added and the old one deleted — through real git.lint_blocks.py, and markdownlint pass.Closes #40