chore(repo): name the vault repo after what it holds, not the engine - #928
chore(repo): name the vault repo after what it holds, not the engine#928wshallwshall wants to merge 12 commits into
Conversation
wshallwshall/MessageFoundry shared a name AND a description with the public
engine repo MEFORORG/MessageFoundry, so two rows in `gh repo list` read as one
project and sessions kept confusing them. Renamed it to
wshallwshall/MessageFoundry-vault, and rewrote its description to name the ASVS
scorecard, role playbooks and handoffs it actually holds.
Checked BEFORE renaming that no ACTIVE vault workflow gates on the old slug: the
9 hardcoded occurrences sit in cla.yml and release.yml, both disabled_manually.
Every active workflow either checks out MEFORORG/MessageFoundry explicitly or
reads the github.repository context, which follows a rename.
This commit carries the engine side, the 13 old-slug references across 8 files.
Two sites are not a plain substitution:
* scripts/hooks/durability_push.sh documents `git remote -v` output, so its
remote table had to match the URL the remote now carries. Both local remotes
were repointed and verified with `git ls-remote`.
* docs/LEDGER-GATE.md quotes the URL a REFLOG literally recorded. That string
stays as recorded, with the current name named beside it. Rewriting it would
make the doc disagree with the artifact it is reading.
Checks: ruff check and ruff format --check on the two touched Python files,
clean. mypy strict on messagefoundry, 268 files, no issues.
scripts/docs/backlog_status_check.py, 670 items OK. pytest on
test_required_workflow_state, test_durability_hook_provenance and
test_coord_alloc_strand_sweep, 40 passed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The vault rename left a PERMANENT GitHub redirect, and GitHub's documentation
names exactly one way to drop one: create a new repository claiming the old
name. That would put the engine's name back in the account listing, so the
redirect stays. The cost of keeping it is that a stale reference does not fail.
It quietly answers, correctly, about the vault, under a name that is gone, and
nothing anywhere reports it.
scripts/quality/stale_repo_slug_check.py greps the TRACKED tree and fails on the
pre-rename slug. Wired as a pre-commit hook with always_run and pass_filenames
false, so a changed-file list cannot narrow what it looked at while still
reporting clean.
Two design points worth a reviewer's attention:
* IT NEVER WRITES THE OLD SLUG AS A LITERAL. The needle is assembled from
parts. Written whole, the guard and its test would each violate the rule
they enforce, and exempting the guard from itself would make it the one
place a real stale reference can hide.
* THE ONE EXEMPTION IS PINNED TO A COUNT, NOT A PATH. docs/LEDGER-GATE.md
quotes a URL a reflog literally recorded. A path-level exemption would blind
the guard to every FUTURE stale reference in that same file, so the pin is
exact and drift in either direction fails.
A clean-tree arm proves nothing on its own, so the tests plant violations and
require the guard to see them: a bare slug, a bare slug hiding on a line that
also carries the current one, the pin drifting up, the pin drifting down, an
untracked file staying out of scope, and two git-failure arms, because "no
matches" and "the search never ran" are the same empty output. The missing-root
arm found a real gap and the GUARD was fixed rather than the test: an OSError
was reaching the caller as a traceback instead of exit 2.
End-to-end control run by hand: a planted probe made the WIRED hook exit 1 with
the site named, and removing the probe returned Passed.
Checks: ruff check and ruff format, clean. mypy --strict on both new files, no
issues. bandit, passed after the repo's usual nosec for a fixed-argv read-only
git call. pytest on tests/test_stale_repo_slug_check.py, 12 passed, and
tests/test_tooling_partition.py, which pins the new manifest entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…check Found while landing the vault rename. install-git-hooks.ps1 lays scripts/hooks/durability_push.sh down as .git/hooks/post-commit VERBATIM, and every instrument that could report it drifting tests a MARKER instead of the content. The two .py payloads installed beside it are content-hashed in both directions. This one IS the implementation, and nothing hashes it. Measured 2026-09-05: the source was updated with the rename, the installed copy was not, and a direct diff was the only thing that said so. -Status printed a hash pair for both payloads and, for the drifted file, the word INSTALLED plus a correct armed-remote line read from live git config. The only green-looking row on the screen was the wrong one. The drift found was comment-only, and that is not the point. A body change would have hidden identically, and in this file the comment IS the safety work: it is what a human reads before choosing a remote, and git push with no remote named resolves to the PUBLIC one. Scope was drawn deliberately and the test inherits it by construction. install-git-hooks.ps1:82 describes $payloads as the .py payloads for -Status to audit, and tests/test_installed_coord_hooks.py:231 parses that same declaration, so the test's scope IS the installer's scope. tests/test_durability_hook_ provenance.py does drive a post-commit hook, and its docstring at :32 says the fixtures never touch the real one -- correct for a provenance test, and it means the file whose name most suggests coverage here provides none. The drift diff is DESCRIBED in the item rather than pasted, and the item records why: the stale-slug guard in this same PR refuses a verbatim quotation and cannot tell quoted evidence from a live reference. docs/BACKLOG.md was deliberately NOT given a count exemption -- 23,000 lines growing daily would make that pin a reflex rather than a decision, which is the one property it exists to buy. The number was allocated with scripts/coord/alloc.ps1, not grepped. Checks: scripts/docs/backlog_status_check.py, 671 items each declaring exactly one status. parse_items confirms #1463 parses as open. The new stale-slug guard exits 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ne session The item cited "38 worktrees share these hooks" as a bare fact. It was true when read and is now 18, measured after the owner reinstalled the hooks. A decaying figure recorded without its as-of time is unusable rather than current, and this one sat in a durable ledger entry. The instruments are not in disagreement, which was the first thing checked: install-git-hooks.ps1:490 and :300 both count `git worktree list` with the identical expression, and a direct `git worktree list` agrees with them. The population itself moved as sibling sessions pruned worktrees -- 43 at session start, 38 an hour later, 18 after the reinstall. The argument the figure supported needs only "more than one", so it is now stated without a number and the readings are recorded beside it with their date. Verified in passing, and it is the reason this session read the count at all: the reinstall cleared the drift #1463 was filed about. The installed post-commit hook is now byte-identical to the committed source, checked by direct diff, because the installer prints no hash for that file -- which is the item. Checks: scripts/docs/backlog_status_check.py, 671 items each declaring exactly one status. The stale-slug guard exits 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… tail docs/BACKLOG.md conflicted at the tail: main gained nine rows while this branch was open, this branch adds #1463. Kept all nine and appended 1463. Both sides open on a bare `## N.` heading, so a blank line is the whole separator needed and no `---` rule is involved. Checked anyway that the result creates no setext heading. tests/tooling_manifest.txt auto-merged. Its one added entry, test_stale_repo_slug_check.py, sits in correct alphabetical position and the file has no duplicate entries. The manifest is not globally sorted and was not before this merge. Verified: 443 rows, no duplicates, no row on main lost. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Lander note: the ledger conflict is resolved, but this PR has a real red of its own. I merged main and resolved the
Measured, with the instrument's own output checked first because a colon-path
So this branch adds the hook and never mirrors it. That is not fallout from my merge, which touched Nothing here can merge until |
Tail append after PR 977 landed. Main rows keep their place, this branch rows follow, because the ledger appends in filing order and not numeric order. Neither silent shape is present: the branch side opens on its own heading, and no prose line lands above a rule. Verified with the shared parse_items. The branch own new work is measured as (branch minus main) minus the MERGE BASE, so a row this branch still carries that main has lost is not miscounted as an addition. No row present on main is missing from the result, no unexpected row appears, no banner field is lost. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts: # docs/BACKLOG.md
# Conflicts: # docs/BACKLOG.md
One conflict, in `docs/BACKLOG.md`, and nothing else: this branch and main both appended items to the same tail. Resolved by rebuilding every item WHOLE from the side that wrote it -- main's 1, then this branch's 1 -- rather than by taking a side at the markers. That distinction is load-bearing rather than pedantic. When two items carry byte-identical banner lines, git aligns on them as a common subsequence, reports two hunks, and leaves the shared lines BETWEEN them marked as context. They are not context: each item owns its own copy. Resolving from the markers hands one item the banner fields and strips the other, producing an item whose status nobody declared and which the hygiene gate then reads as undeclared. Checks run: three-way ledger verification against main and this branch -- no silent revert of a row on main, no unexpected row belonging to neither side, no row that lost a banner field, and the result count equal to main's rows plus this branch's own. VERDICT PASS. No file outside the ledger was touched by this merge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-vault-rename-f3a800
What changed
wshallwshall/MessageFoundryis nowwshallwshall/MessageFoundry-vault, and itsGitHub description now names what it holds instead of describing the engine.
It shared a name AND a description with the public engine repo
MEFORORG/MessageFoundry, so two rows ingh repo listread as one project.wshallwshall/MessageFoundrywshallwshall/MessageFoundry-vaultThree commits, one layer each: the engine-side sweep of the 13 old-slug
references across 8 files, a guard so the tree stays swept, and BACKLOG #1463 for
a gap the work uncovered.
Why the rename disabled nothing
Checked BEFORE renaming. The 9 hardcoded old slugs in the vault sit in
cla.ymland
release.yml, bothdisabled_manually. Every ACTIVE vault workflow eitherchecks out
MEFORORG/MessageFoundryexplicitly or reads thegithub.repositorycontext, which follows a rename. PyPI Trusted Publishing is bound to
MEFORORG/MessageFoundry, not to the renamed repo.Two sites are not a plain substitution
scripts/hooks/durability_push.shdocumentsgit remote -voutput, so itsremote table had to match the URL the remote now carries. Both local remotes
were repointed and verified with
git ls-remoteagainst the new URL.docs/LEDGER-GATE.mdquotes the URL a REFLOG literally recorded. That stringstays as recorded, with the current name named beside it. Rewriting it would
make the doc disagree with the artifact the section is reading.
The guard, and why a rename needs one
GitHub keeps a permanent redirect from the old path, and their documentation
names exactly one way to drop it: create a new repository claiming the old name.
That would put the engine's name back in the account listing, so the redirect
stays. The cost is that a stale reference does not fail. It quietly answers,
correctly, about the vault, under a name that is gone.
scripts/quality/stale_repo_slug_check.pygreps the tracked tree and fails on thepre-rename slug, wired as a
pre-commithook withalways_runandpass_filenames: false.Two design points worth a reviewer's attention:
parts. Written whole, the guard and its test would each violate the rule they
enforce, and exempting the guard from itself would make it the one place a real
stale reference can hide. The accepted cost: grepping the tree for the old slug
will not find the guard.
docs/LEDGER-GATE.mdmay hold exactly 1. A path-level exemption would blind the guard to every
future stale reference in that same file, so drift in either direction fails.
A clean-tree arm proves nothing on its own, so the 12 tests plant violations and
require the guard to see them: a bare slug, a bare slug hiding on a line that also
carries the current one, the pin drifting up, the pin drifting down, an untracked
file staying out of scope, and two git-failure arms, because "no matches" and "the
search never ran" are the same empty output. The missing-root arm found a real
gap and the guard was fixed rather than the test -- an
OSErrorwas reaching thecaller as a traceback instead of exit 2.
End-to-end control run by hand: a planted probe made the WIRED hook exit 1 naming
the site, and removing the probe returned Passed.
The guard then refused this PR's own backlog filing, which quoted the drift
diff verbatim. That is the design working: it cannot tell quoted evidence from a
live reference.
docs/BACKLOG.mdwas deliberately NOT given a count exemption --23,000 lines growing daily would make the pin a reflex rather than a decision --
so the item describes the diff instead and records why.
BACKLOG #1463, filed here
install-git-hooks.ps1:436laysscripts/hooks/durability_push.shdown as.git/hooks/post-commitverbatim, and every instrument that could report itdrifting tests a MARKER rather than content:
install-git-hooks.ps1:162sets$durInstalledby matching a marker theinstaller itself writes in, so it answers "is this ours" and never "is this
current".
:164prints the presence string off it, with no hash.tests/test_installed_coord_hooks.py:353is parametrized at:352overPAYLOADS, parsed at:231from the installer's own$payloads = @("claim_check.py", "push_guard.py"). The test's scope IS theinstaller's scope by construction, and it inherits the gap.
tests/test_durability_hook_provenance.pydoes drive a post-commit hook. Itsdocstring at
:32says the fixtures never touch the real one -- correct for aprovenance test, and it means the file whose name most suggests coverage here
provides none.
commit-msgandpre-pushare thin shims that locate a hashed.pypayload, soa marker is enough for them.
post-commithas no payload: the body IS theimplementation, and nothing hashes it.
This was found the hard way -- a direct diff was the only thing that reported it,
while
-StatusprintedIN SYNChash pairs for both payloads and, for thedrifted file, the word
INSTALLED.Checks run
ruff check+ruff format --checkmypystrict onmessagefoundrymypy --stricton both new filesbanditnosecfor a fixed-argv read-only git callscripts/docs/backlog_status_check.pyparse_itemson the new itempytestguard suitepytesttest_tooling_partition(pins the new manifest entry)pytesttest_required_workflow_state,test_durability_hook_provenance,test_coord_alloc_strand_sweeppre-commithooks, all three commitsFull
pytestwas not run. Hosted-runner legs (for examplewindows-service-smoke) must be read from CI after this process exits.Two things this PR does not do
The installed hook still needs a manual reinstall.
.git/hooks/post-commitcarries the pre-rename remote table. Fixing it means writing into the shared
.gitof the primary checkout, which 38 worktrees share, so it is the owner'shand:
Both payloads already report
IN SYNCand this branch is 0 commits behindorigin/main, so the reinstall cannot downgrade anything -- the only contentchange is the two comment lines.
A stale measurement was left as recorded.
docs/adr/0160-*.mdline 455 saysthe vault reports "every workflow except
ASVS scorecard" asdisabled_manually. Measured today: 6 are active (ASVS scorecard, ASVS verifierdrift, Branch leak scan, SDS citations, SDS standard freshness, threat-model
drift) plus Dependabot Updates and Dependency Graph. It is a dated 2026-08-06
measurement inside a "measurements that produced that decision" block, so
correcting it is its own change, not a side effect of this one.
Five live peer sessions were mailed before the shared
privateremote URLchanged under them.
🤖 Generated with Claude Code