Ruling 2: every tracked text mention of the login's pre-rename spelling becomes igneum-labs (29 files); the commit identity in the scripts becomes igneum-labs <337424239+igneum-labs@users.noreply.github.com> (the same noreply id); the three scripts that hand the stored gh keyring name to gh (register.sh, fetch-ci-artifacts.sh, ship-app.mjs) read it from ~/.config/igneum/gh-user (never in the repository), default igneum-labs; fresh-repo.sh reads the login to rewrite from the encoded list's row 10; the old spelling joins the founder-strings list, so no tracked file may spell it; CLAUDE.md's GitHub paragraph rewritten. The red watcher's self-test fixtures use a neutral author. Ruling 4: docs/ledger-public.md, one row per ledger item (id, the claim in one line, status, what was done in one line, the evidence link or the evidence in words), generated by tools/ledger/export-public.mjs from docs/fud-ledger.md: no round or status-update sections, no commit ids, no time of day, no lane, agent or branch names. 190 items. The gate runs its self-test (a fixture with a commit id, a time, a lane and a branch name comes out clean; --check fails on drift) and its --check on every merge; the founder check reads the output like every tracked file. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
12 KiB
G14: the history rewrite, exact plan and dry-run result (4 October 2026, night)
Internal. Extends docs/fud-fixes.md section 5 (step 4) with the exact commands, what the dry run showed, what
breaks, and the order for the morning. Nothing here has touched the real repository: the dry run ran on a throwaway
mirror clone under the session scratchpad and nothing was pushed. The owner is not named in this file; "the first
name" and "the login" stand for the values the script reads from the history itself.
1. What the history holds today (counts from the real repository, 4 October 2026, 22:30 UTC)
| Item | Count | Where |
|---|---|---|
| Commits | 363 on all branches | |
Commits stamped +0100 (author or committer) |
291 of 363 | the UK or Irish summer offset; 72 are +0000 |
| Commits authored with the personal name | 40 (31 on the old GitHub noreply address, 9 on the personal address) | the commits before the 3 October identity rule |
Commits as the standing login igneum-labs |
323 | |
| The intake key | 6 tracked files, 8 commits (78df757 to 4c9810f) |
packaging/mac/packaged-config.sh, infra/gpu-bench/upload.sh, proving/windows-wsl2/prove-block.sh, prove-shard.sh, proto-cuda/windows-miner/upload-log.bat, proto-cuda/windows-app/upload-log.bat |
| The dl token | 1 tracked file, 1 commit (c47ff03) |
docs/plans/morning-2026-10-04.md |
The .next rotations of both |
0 files, 0 commits | ~/.config/igneum/log-intake-key.next, dl-token.next (4 October 19:25) are not in the tree |
| The relay key and token (current and old) | 0 files, 0 commits | |
| The review files | docs/fud-ledger.md (36 commits from 39c20b7), docs/fud-fixes.md (6 from e7545d5), docs/review/ (4 from 5ab296c), site/ledger.html (5 from 0ec11be) |
tracked, not ignored |
| Tracked files carrying the first name (case-insensitive) | 71 at HEAD; 93 commits touch such content; 10 commit messages carry it | CLAUDE.md, the agent file, plans, packaging, the app's WSL paths, the Chrome profile rule |
| The surname | 4 files at HEAD | |
| The other businesses' names, the registrar, the database id, home paths | the other business 6, the earlier entity 5, the earlier business 4, godaddy 7, soft-voice 3, /Users/ 22, quantum 4 |
identity terms are rewritten by the history pass below; providers and paths are the public-export scrub's job (tools/ci/forbidden-strings.txt), not this pass |
2. The rewrite, exactly
Tool: git-filter-repo 2.47.0 (not installed on the Mac; the dry run used a pip install into the scratchpad,
python3 -m pip install --target <dir> git-filter-repo, run as python3 <dir>/git_filter_repo.py). It refuses to
run on anything but a fresh clone, which is the safety the plan relies on.
The script is dryrun.sh in the scratchpad (rewrite/); it reads every value from the history and from
~/.config/igneum at run time and writes the replacement files with mode 0600, then deletes them. The one
invocation, with the files it writes:
git clone --mirror <repo> clone && cd clone
python3 git_filter_repo.py --force \
--invert-paths --path docs/fud-ledger.md --path docs/fud-fixes.md --path docs/review --path site/ledger.html \
--replace-text replace.txt \
--replace-message messages.txt \
--mailmap mailmap \
--commit-callback '
for attr in ("author_date", "committer_date"):
d = getattr(commit, attr); parts = d.split(b" ")
if len(parts) == 2 and parts[1] != b"+0000":
setattr(commit, attr, parts[0] + b" +0000")
'
| File | Lines (values never written in this plan) |
|---|---|
replace.txt (blob text) |
literal:<intake key>==>***INTAKE-KEY-REMOVED***; literal:<dl token>==>***DL-TOKEN-REMOVED***; the two personal Name <email> strings to the standing login string; the personal email and the old noreply address to [removed]; regex:\bFirst's\b==>the project lead's; regex:\bFirst\s+Last\b==>the project lead; regex:\bFirst\b==>the project lead; regex:\bLast\b==>[removed]; regex:(?i)(?<!igneum-)\bfirst\b==>[user] (the lowercase user-name form in Windows and WSL paths, added after dry run 1 left 20 lines); regex:(?i)\b<second login>\b==>[second-owner-login]; regex:(?i)\b(the other business|the earlier entity|the earlier business|another brand|another brand)\b==>[other-business] |
messages.txt (commit messages) |
the first-name rules and the second-login rule |
mailmap |
both personal identities to igneum-labs <337424239+igneum-labs@users.noreply.github.com> |
The date callback keeps the instant and rewrites the offset to +0000, so no commit moves in time; only the
+0100 fingerprint goes. --invert-paths drops the four internal files from every commit, which empties the
commits that touched nothing else; filter-repo prunes those.
3. The dry run (two passes on the mirror clone, 4 October 2026, 22:35 to 22:55 UTC)
| Check | Before | After pass 2 |
|---|---|---|
| Commits | 364 in the mirror (363 plus the in-progress branch head) | 312: the 52 commits that only touched the dropped files are gone |
| Author and committer identities | 3 | 1: the standing login on all 312 |
| Timezone offsets (author and committer, 624 stamps) | 291 x 2 +0100 |
624 +0000 |
git log -S<intake key> |
8 commits | 0 |
git log -S<dl token> |
1 commit | 0 |
| Commits touching the four dropped files | 51 | 0 |
| Identity grep over every blob in the history (first name outside the login, surname, second login, personal addresses, the other businesses; case-insensitive) | thousands of lines | 0 lines |
| Identity grep over commit metadata (names, addresses, subjects, bodies) | 0 lines | |
CLAUDE.md line 4 after the pass |
the full name | "the project lead's project, started 3 October 2026" |
| Runtime | 2 min 58 s for the filter, 3 min 15 s with the greps |
Pass 1 (case-sensitive name rules only) left 20 blob lines and 2 message lines: the lowercase user-name form in
C:\Users\<first> and WSL paths in app/igneum-app/src/jobrun.rs, prover.rs, docs/plans/shard-test-pc2.md,
packaging/README-ship.md, packaging/ota/publish-jobs.sh, relay/playbooks/shard-test.ps1 and the Chrome-profile
line of CLAUDE.md. The (?i)(?<!igneum-) rule closed them in pass 2.
What the pass does NOT do, by design, and must be done by hand or by the owner:
| Gap | Why | Who |
|---|---|---|
The standing login igneum-labs carries the first name inside it, in every commit's author line and in every file that names the login |
A login is a GitHub setting, not a text rule: renaming it is one setting, the numeric noreply id stays, then one more mailmap line (<new> <337424239+<new>@...> <337424239+igneum-labs@...>) and one more replace rule (igneum-labs to the new login) go into the same pass |
the owner (rename), then the script |
CLAUDE.md as a public file (section 5 step 2 of docs/fud-fixes.md: the registrar, the database id, the browser-profile section, the tooling links) |
The pass replaces names; it does not rewrite paragraphs. The scrubbed CLAUDE.md of step 2 replaces the file in every commit with --path-rename or a blob callback once it exists |
Claude, after the owner approves the public text |
| The second owner login is still an organisation owner | GitHub setting (decision e: one anonymous owner) | the owner |
| Providers, hosts, home paths, machine names | the public-export scrub (tools/ci/forbidden-strings.txt, igneum-public/tools/sync.sh); the private repository keeps them until the public date |
the export |
4. What breaks when the rewrite is applied for real
| What | Why | Recovery |
|---|---|---|
Every worktree of the main checkout (16 today: igneum-wt-appui, bughunt, buildjob, devfee, eff, finality, latency, perf, redteam, release, reliability, ship, site, wallet, testnet, plus two under the scratchpad) |
Their HEADs point at old commit ids that no longer exist in the rewritten history; git status still works on the old objects, git pull and git rebase do not |
Each agent commits and pushes its branch before the freeze; after the rewrite every branch is re-created from the rewritten refs: git worktree remove, git worktree add ../igneum-wt-<name> <branch> |
| Agents' branches (15 local, 11 on origin) | Rewritten with everything else (the mirror clone carries every ref), so the branch names survive with new ids; an agent that keeps an old local branch will have diverged from its rewritten twin by every commit | No agent commits during the freeze; after it, every agent re-creates its worktree, never merges an old-id branch into a new one |
| Open pull requests, if any | Their base and head ids vanish | None open today (the project merges by hand); check gh pr list before the freeze |
The Vercel GitHub integration (igneum project, deploys on push to master) |
The integration links by repository id, not by commit, so it survives a force-push; the first push of the rewritten master triggers one deploy of the same site (the public tree is unchanged by the pass except the dropped site/ledger.html, already a 307 redirect) |
Watch the deploy; nothing to relink. If the repository is re-created instead (section 5, option B), the integration is re-linked once in the Vercel project settings |
The windows-ci and ci workflows |
Run on the rewritten push like any push; the DL_TOKEN secret is a repository setting and survives | Re-set the secrets if the repository is re-created |
Old commit ids in documents (docs/bench-log.md, plans, the ledger) and in the public export |
They name commits that will not exist; filter-repo writes commit-map (old id to new id) in .git/filter-repo/ and rewrites ids it finds in commit messages, not in files |
Keep commit-map with the private notes; the bench log keeps its short ids as historical labels (the public export already strips the history) |
| GitHub's copies of the old objects | A force-push does not delete them from GitHub's object store; cached PR views, old commit URLs and forks keep serving them until GitHub runs a garbage collection, which support can be asked to do | Option B below removes the question |
The fork worktrees under vendor/ |
Separate repositories (vendor/ is gitignored); untouched |
Nothing |
| The intake key and the dl token | Removing them from the history does not revoke them; every shipped package and every installed app carries the current key | Rotate first (the .next values exist since 4 October 19:25): new key in relay/ and in packaging/mac/packaged-config.sh, repackage, republish; the old key keeps working for installed apps until they update, then dies |
5. The order of operations for the morning
- Rotate the secrets: switch the relay and the intake to
log-intake-key.next, the downloads folder todl-token.next, repackage the Mac and Windows apps with the new values, publish, confirm an upload lands under the new key. Then the old values in the history are dead values. - The owner renames the login
igneum-labs(GitHub settings; the noreply id 337424239 stays), confirms the second login is no longer an organisation owner, and approves the publicCLAUDE.mdtext (section 5 step 2). - Freeze: every agent commits and pushes its branch, then stops;
gh pr listmust be empty;git worktree listis recorded. - Mirror clone, run the pass (section 2) with the two extra lines from step 2 and the scrubbed
CLAUDE.mdblob; the greps of section 3 must all read 0; keepcommit-map. - Choose A or B. A:
git push --mirrorfrom the clone to the existing repository, then ask GitHub support to purge the unreachable objects. B (the routedocs/fud-fixes.mdstep 4 prefers): create a fresh repository under the organisation, push the rewritten refs there, re-link Vercel and re-set the two secrets, archive the old repository private. B leaves no old object anywhere. - Re-clone the main checkout from the new history; every agent re-creates its worktree from its rewritten branch.
TZ=UTCon every path that commits: the agents' shells, the ship scripts, the relay; andgit config --globalcannot set a timezone, so the rule is in the environment. The CI identity grep andgit log --format='%ad' --date=raw | grep -c +0100become the daily check (0 is the goal).- The public export (
igneum-network/spec) is unaffected: it carries no history from this repository.
6. What waits for the owner
| Decision | Options |
|---|---|
| The new login name | any handle without a name |
| A or B in step 5 | B recommended |
The public CLAUDE.md text |
section 5 step 2 of docs/fud-fixes.md |
| The day | after step 1; before the public date in every case |