be self-locator is just a 120000 leaf, dropping ALL self-locator special-casing
The JS extension special-cases the be self-locator everywhere it meets the submodule graph (a path=="be" branch in get.js mountGitlink/recurseSubMounts, a refusal in submount.mount, a be -> . materialiser — GET-036/GET-037). All of it papers over ONE root mistake: a symlink (be -> .) stored/treated as a 160000 gitlink instead of a 120000 blob. Adopt git's model — a symlink IS a blob whose bytes are the link target verbatim, tree mode 120000, hashed via lstat+readlink, NEVER followed during a walk and never a submodule — and be -> . becomes an ordinary leaf so every special-case dissolves. Scope: be/ JS (classify/post/get/checkout). See GET-036, GET-037, SUBS-041; method Issues.
120000 blob (target bytes, no trailing newline); hashed via lstat+readlink (never followed); checked out with symlink(); it is a LEAF, never recursed; git refuses to follow links when resolving tracked paths.be is committed as a 160000 gitlink (GET-037), so checkout tries to MOUNT it; get.js/submount.js carry be-name special-cases to paper over the crash.lstat, lnk=leaf) — INCLUDING the underlying recursive readdir, else be -> . blows up be/be/be/…; (2) a symlink is never a submodule mount; (3) unlink-before-write on checkout.be is currently the gitlink form; once classify records the on-disk be -> . as a 120000 symlink, post commits it as a blob — the locator must be re-committed.120000 symlink round-trips as a blob (target == bytes) through classify → post → checkout, byte-identical to git, on the JS path.be self-locator special-casing removed (get.js isSelfLocator + mountGitlink branch + recurseSubMounts self-case, submount.mount refusal); be -> . works via the generic symlink leaf path.be/be/be); a symlink is never classified as a mount; checkout unlinks before symlink().be/ JS only, NO C this session. ABC/JS house style; keep the friendly-string throws.be -> . self-link no-recurse test (mirror be-js-sub-selflink); do not regress be-js-sub-cycle.$HOME/todo/GET-039 via be get of beagle-ext; do NOT edit the main tree.120000 strictly as a blob everywhere; symlink kind l is a leaf in classify/checkout/post; no path-name ever knows about be.isSelfLocator and its call sites; the generic 120000-leaf path replaces them.classify.wtScan / io.readdir recursive) does NOT descend a symlink — fix if it does.test/sub/symlink/run.sh (120000 blob commit→checkout, readlink==target, never a mount); be -> . no-recurse → test/sub/selfloop/run.sh (no be/be/be blowup, no ?/be fetch).be special-casing: isSelfLocator is GONE from be/ (grep clean, audit 2026-07-07); submount.mount refusal replaced by the symlink-is-a-120000-blob rule (shared/submount.js:202).symlink() on checkout. → classify.js lstat kind l leaf; core/recurse.js:31 symlink never a mount; shared/checkout.js:56 clear-before-write; selfloop asserts readdir no-follow. Entry-type changes 3026a5fb.be locator as a 120000 symlink → be d31b52ea "commit be symlink".d80bdb5c "js tests pass" (audit did not re-run); only 3026a5fb carries the GET-039 code — record the main landing hashlet(s) and close under the GET-041 umbrella ruling (end-to-end beagle-ext bring-up still fails there 2026-07-07).be corner case ONLY; real 160000 gitlink cycles are SUBS-041's job — do not duplicate the guard.be as a 160000 gitlink hit the mount path until the locator is re-committed.be self-locator special-casing of GET-036/GET-037 with git's symlink-as-blob model (a symlink is a leaf, never a sub).3026a5fb "GET-039: entry type changes (e.g. symlink->dir)", d31b52ea "commit be symlink", JS-069 d89eb236 symlink handling; tests test/sub/symlink + test/sub/selfloop; all be-name special-casing removed. Remaining: formal close pending the GET-041 end-to-end bring-up (jab run-pin + native arms are out of this ticket's JS scope).