file.c:58:mJ, a line in the anchored blob plus a 2+ char hashletLITE-025 minted BEE-005:1Jz:mJpI — a ron64 BYTE OFFSET plus a 4..10 char EVEN hashlet — and a page full of them reads heavy (gritzko, 2026-08-16). Two cuts, ruled in chat: segment 1 becomes the LINE in the anchored blob (the hashlet already pins the blob, so a line in it is exactly as stable as a byte offset in it — LITE-025:46:zc ruled blob-vs-weave, not byte-vs-line), and the hashlet shrinks to a 2-char minimum, extended ONE char at a time only when it collides in the path's own history OR to get one non-digit into it. BEE-005:58:mJ: legible before AND after minting, and the mint becomes a pure append. The corpus is migrated once by a temporary converter verb, then the old form is forgotten.
The permalink form and its readers/writers, as landed:
path:OFF:HASHLET, OFF = ron64 byte offset into the anchored blob (pm.packOffset), HASHLET = ron64 pairs, 12 bits a pair = 3 hex, min 4 chars, EVEN, one non-digit, extended by 2 (LITE-025:19:zc, LITE-025:20:zc; index/perma.js isHashlet hashletHex mintHashlet packOffset).door.js permaTail/splitRef (segment 2 non-digit decides), door.js seatOf -> index/perma.js follow(partial, offSeg, hash, from) -> land -> anchorOf -> blobsFor (hex-prefix compare over historyOf, EARLIEST wins, then the working blob via blobIdOf) -> tokenAt/tokenNow on one CFOLD pair -> lineCol.index/hook.js mintRef/mintForeign (ref.path + ":" + pm.packOffset(off) + ":" + h), the LITE-027 topological order (byte offsets in a target shift when its own refs are rewritten), index/mint.js (BEE-016) reusing the same, view/see.js reading pm.byteAt for line bands.quickjab/dog/tok/LINK.rl:94 commit = ":" ron64{1,4} ":" (ron64 ron64){2,5} fuses the anchor into the ONE F token; :58:mJ does NOT fuse today (segment 2 needs 4+ even chars), :58:mJpI does. Anchors are capped at 10 chars (DOG-034).core/Link.mkd:1:wc, core/Link.mkd:10:wc, core/Link.mkd:22:wc (hand-written — gritzko edits), README.mkd, door.js:416:WK, LINK.rl:20.test/perma/pty.js (its own mint() oracle, :ES:LjJu-style fixtures, "an ODD-length segment 2 is no hashlet"), test/hook/{hook,first,cycle,ticket,cross}.js, test/mint/mint.js, test/see/run.sh, test/land/pty.js, test/click/click.js, test/chat/name.js, test/diff/fork.js, test/http/run.sh.///bee (60+ TICKET:OFF:HASH refs minted 2026-08-16 in index/*.js, door.js, tests), ///bee-journal tickets, possibly ///quickjab. Committed history keeps the old spellings forever.file.c:58:mJ is the permalink; everything that minted, fused, split or followed the old form does the same for the new one, and one converter run turns the corpus over.
path:LINE:HASHLET. LINE = 1-based line in the ANCHORED blob, decimal digits as typed. HASHLET = 2..10 ron64 chars, 6 bits each, a bit-prefix of the blob sha1 (k chars = top 6k bits); grown ONE char at a time until it is unique among the path's other blobs AND carries a non-digit. Segment 2 all-digit = a column, as before.hashlet -> earliest blob in the path's history whose sha1 top 6k bits match, else the working blob; the line is turned into a byte with pm.byteAt(was, line, 1); the rest of the walk (tokenAt/tokenNow, deleter, notes, lo/hi) is unchanged.bee mint, foreign): path:LINE:h — the line the ref names in the target image, the hashlet minted for that image's blob id against the path's other blobs. A ref past the end still mints nothing.commit = ":" [0-9]{1,10} ":" ron64{2,10} in LINK.rl, so a 2-char or odd hashlet fuses; six includers regenerated.bee reperma [--dry-run] <file>... (index/reperma.js, the BEE-016 mint shape) turns every OLD permalink in the named files into the new form TEXTUALLY, with NO index or ODB read: the hashlet is kept — an old pairwise hashlet is bit-for-bit a new one (12 bits a pair = 6 bits a char, big-endian) — and TRIMMED to its shortest prefix (min 2) that carries a non-digit; the ron64 offset is decoded and turned into the LINE it falls on in the file AS IT IS ON DISK NOW (the path found the way the door finds any path:LINE ref — ladder, mount table, fs), lineCol(bytes, off).line. A path no file answers is left and reported. Deleted after the corpus is converted (its own follow-up).README.mkd, door.js, perma.js header, LINK.rl header; core/Link.mkd is gritzko's.~/src/bee3 (fast-forwarded to main first, git -C ~/src/bee3 merge --ff-only main); the dog grammar in a git worktree of ~/src/quickjab/dog symlinked as dog/ into a git worktree of ~/src/quickjab, built into ~/src/quickjab/build-bee3 (cmake -S <quickjab wt> -B ~/src/quickjab/build-bee3 -DJAB_JSRC=$HOME/src/bee3 -DQUICKJAB_JSRC_PACK=ON, then ninja, ctest -j16). Neither main tree is touched.x.mkd:58:mJ fuses as one F token and follows; x.mkd:58:m (all-digit segment 2 aside) — a 1-char hashlet does not; a :58:mJ written by the hook is what a git commit lands.:OFF:HASH fixtures and oracles rewritten to :LINE:HASH, pty.js's mint() oracle re-derived, "ODD-length is no hashlet" flipped); no assertion about behaviour changes meaning. Full ctest green.hook.js fTokens stays the one scanner (LITE-033); the converter reads F tokens like bee mint.Ruled by gritzko in chat, 2026-08-16.
:LINE:COL:HASH form (YAGNI; the 10-char anchor cap would eat it anyway).k chars = the sha1's top 6k bits (BigInt shift), so odd lengths mean something. Extend ONLY on collision in the path's own history or to obtain a non-digit. Both hashletBits(h) -> { bits, val } and mintHashlet(sha, others) live in index/perma.js, ONE file owning both directions (LITE-026:102:xo stands).splitRef reads segment 1 as digits only; an old :1Jz:mJpI splits as no anchor at all (segment 1 is not all-digit) and lands on the file. The converter is the migration; committed history keeps dead old links, accepted.:5:mJpI, offset < 10) is indistinguishable from a new-form line and is reported, never guessed. gritzko 2026-08-16: the conversion is offset -> decimal line against the CURRENT file bytes plus hashlet TRIM to 2 chars (3+ only to get a non-digit) — no re-mint, no uniqueness check, no db read: no file here has a history long enough to need it, and the corpus was minted a day ago.F token and the door never sees it; the temporary min-4 compat was weighed and dropped, it forfeits half the point.~/src/bee3 ff to main; quickjab + dog worktrees, build-bee3 configured and green on the baseLINK.rl commit rule + header comment; regenerate FREE MKDT MDT TOKL RSTT TXTT (ragel -C X.c.rl -o X.rl.c -L); a tok.parse probe shows x.mkd:58:mJ as ONE F tokentest/perma (new fixtures + oracle), test/hook, test/mint amended to :LINE:HASH; run, all red on the baseindex/perma.js: isHashlet (2..10, non-digit), isLine, hashletBits, mintHashlet (step 1, bit compare), blobsFor/anchorOf on bit prefixes, follow(partial, lineSeg, hash, from) + land line -> byte via byteAt; packOffset/offsetOf/hashletHex retireddoor.js permaTail/splitRef: { line, hash }; seatOf passes the lineindex/hook.js mintRef/mintForeign, index/mint.js: path + ":" + line + ":" + hindex/reperma.js + main.js reperma verb (temporary, says so), test/reperma/run.sh on a fixture repo carrying old links, --dry-run firstREADME.mkd, door.js/perma.js/LINK.rl comments; note core/Link.mkd:1:wc,10,22 for gritzkoctest -j16 in build-bee3 green; bee reperma --dry-run over ///bee and ///bee-journal (from bee3, read-only) reported, NOT appliedindex/hook.js:1cG:xoo4) fused NO F token under the digits-only rule, so
fTokens could not see it and reperma left it silently. DOG-043's
oldcommit — TEMPORARY, dropped once the corpus is over — keeps the retired
form fusing as ONE token, so the converter reads whole F tokens like bee
mint and owns no byte walk of its own. door.js splitRef stays new-form
only, so nothing FOLLOWS an old link; it is migrated, not read.quickjab's test/ is GITIGNORED (so the worktree has none — 35
JABC tests cannot even find their .js), dog's abc submodule is empty in a
git worktree, and -I <wt>/dog/.. resolves THROUGH the dog symlink to
~/src, so #include "dog/tok/FREE.h" needs a dog there. What was linked:
quickjab-BEE019/test -> quickjab/test, dog-BEE019/abc/* -> the main dog's
abc/* (per entry, so git status in the dog worktree still works), and
~/src/dog -> ~/src/dog-BEE019. None of it touches a main tree, and the
dog link in ~/src is the only thing outside a worktree.core/Link.mkd is gritzko's: core/Link.mkd:1:wc, :10 and :22 still spell
the permalink file.c:k4:d8K3 / :offset:hashlet. Untouched, as ruled.LANDED IN THE WORKTREES, no VC op run: bee in ~/src/bee3 (15 files changed,
index/reperma.js + test/reperma/run.sh new), the grammar in
~/src/dog-BEE019 (tok/LINK.rl, six regenerated *.rl.c, test/TOK01.c).
ctest -j16 in ~/src/quickjab/build-bee3: *149/149*, up from 145/145 on the
base (the new JSRCreperma plus four JABC legs the test/ symlink revived).
index/perma.js +/−129: isHashlet is 2..10 chars with a non-digit,
isLine is the digits-only segment 1, hashletBits/shaBits/hasBits are
the BIT-prefix comparison (one BigInt off the sha's top 64 bits), and
mintHashlet grows ONE char at a time against blobHistory.
packOffset/offsetOf/hashletHex/isOffset are GONE. follow,
foreignFollow, blobsFor, anchorOf and land take { bits, val } and a
LINE; land turns it into the byte with byteAt(was, line, 1) and the rest
of the walk (tokenAt/tokenNow, deleter, notes, lo/hi) did not move.door.js: permaTail asks isLine of segment 1, splitRef answers
{ line, hash } (off retired), seatOf passes the line to follow.index/hook.js mintRef/mintForeign: ref.path + ":" + ref.line + ":" + h
— byteAt now only asks whether the target image HAS that line, so the mint
is the pure append the ticket asked for. index/mint.js follows suit.index/reperma.js NEW (196) + the reperma verb in main.js: TEXTUAL per
ruling 6 — no repo opened, no ODB read, no re-mint. It scans WHOLE F
tokens through hook.js fTokens (the one scanner) and splits each on its
last two colons the way door.js permaTail does, no byte walk anywhere: a
non-digit ron64 segment 1 under an even 4..10 hashlet is OLD, an all-digit
one is the ruling-6 ambiguity. The hashlet is TRIMMED (mJpI -> mJ,
28Oq -> 28O when two chars are both digits), the ron64 offset is decoded
and lineCol counts it in the file ON DISK, found through door.js
seatOf(path + ":1"). A path nothing answers, an ambiguous one, an offset
past today's end and an all-digit segment 1 are each REPORTED and left.test/reperma/run.sh NEW (13 checks, JSRCreperma), RED FIRST: 10 of 12 bad
against the base binary (no verb, old grammar). It pins the disk-line rule —
dirty.c carries an uncommitted 100-byte first line, so the offset that was
line 20 in the commit converts to line 14 — a SLASHED path (sub/S.c, the
leg oldcommit exists for), the ticket-code shape, and idempotence.test/perma/pty.js (oracle re-derived as the
sha's top 6k bits; "an ODD-length segment 2 is no hashlet" FLIPPED, plus a
1-char floor and an "old form is no anchor" leg), test/hook/{hook,first,
cycle,ticket,cross}.js, test/mint/mint.js, test/land/pty.js (a permalink
lands on the line's FIRST token now, so int, not FSWMARK020),
test/http/run.sh (#b50), dog/test/TOK01.c (file.c:100:a7 fuses,
file.c:k4:d8K3 no longer does). RED FIRST on the base build with the new
grammar: perma 14 bad then a throw, hook 13+3+5+4+6 bad, mint 6+1,
land 7, http 2 — all green after.bee reperma --dry-run over ///bee (index/*.js door.js main.js
test/*/*.js, from ~/src/bee3): *117 would convert, 9 left* — 8 of them
an all-digit segment 1 (BEE-002:135:qexI, index/perma.js:216:vS~I and
friends), 1 an ambiguous file.c in reperma's own header. Over
///bee-journal (todo/BEE/*.mkd todo/LITE/*.mkd): *31 would convert, 8
left* (4 ambiguous file.c from ticket prose, 2 all-digit, and 2 spellings
no file answers: /abs/path/FILE.mkd, a slashless wiki/Bro). With
oldcommit the slashed refs now COUNT — /wiki/Bro:Hf:YlvT,
todo/BEE/BEE-006.mkd:gt:3Bxd, an absolute /home/.../BEE-005.mkd:1_Y:mJpI
— which is the +10 in the journal. NOTHING WAS APPLIED anywhere.bee see BEE-005:58:mJ (the converted
spelling of BEE-005:1Jz:mJpI) lands on line 58 of
bee-journal/todo/BEE/BEE-005.mkd, the very line the old anchor named.Suggested commit (bee3): BEE-019: permalinks name a line and a hashlet