Audit of be's submodule recursion across all verbs (2026-06-05). Model and spec in Submodules. Recursion is default-on for every source type (git/ssh included); --sub is a dead no-op, --nosub is the only opt-out. HEAD, GET (checkout/clone/force/prune), and POST topology (post-order, synthetic dot-branch ?/<sub>/.<parent>/<branch>, gitlink bumps, detached-refuse) all work. SUBS-001..012, 016..020 landed; the gaps below are the deltas that remain.
| Ticket | Sev | Verb | One-line | |--------|-----|------|----------| | SUBS-013 | LOW | put | full git submodule add parity: stage a new 160000 gitlink + .gitmodules from be put — needs a chosen URL source + pin grammar (escalated from SUBS-009) | | SUBS-025 | MED | get | sub recursion leaks raw fetch progress (git band-2 KEEP.c:2377 + keeper: fetched N ref(s) WIRECLI.c:1017) to stderr instead of relaying it as hunks | | SUBS-027b | MED | all | landed: no-backward-bump (719cb085, post/51) + R2 keep-alive (0c67bea8, post/52) + be head pin axis (b9c6b647, head/04-05). OPEN: R1 cache, Edited + coord-mismatch axes, loud error+--force/diverged-refusal, get reapply, test matrix (post/26,27 still gated) | | SUBS-029 | MED | post | LANDED 3fd64016 — recursive post stamped a phantom no-op gitlink put in a sub shard; fixed by the tip-vs-pin gate in sniff/PUT.c (+ PUTNONE-tolerant bepost_bump_sub); repro post/50 | | SUBS-030 | MED | status | DONE — ts LANDED d7eaf5c4 (advanced-sub row carries sub-tip commit ts via SNIFFSubTipTs) + adv-marker LANDED 69f51bd3 (advanced-only sub → adv, content → mod). JS parity follow-up JS-045 | | SUBS-031 | HIGH | post | LANDED 60cf0b10 — git-.git→official sub-push now gated behind --force (default skip + one-line notice; revises SUBS-020 case 2); post/43 rewritten to both arms. Unblocks URI-006 St.2 | | SUBS-032 | MED | head/patch | nested abc sub resolves to WRONG source — be head→be://…?/abc no-refs (HOMENOPROJ); be patch→official github fetch, not the local shard (SUBS-017-class) | | SUBS-035 | HIGH | post | LANDED 6496c039 — detached sub now COMMITS (stays detached ?newhash) + parent commit attaches it to ?/<sub>/.<parent>/<branch> via the gitlink bump; POSTDET-refuse gated top-level-only (DIS-009/GET-024); test/post/54 | | SUBS-038 | LOW | get/patch | a sub re-get whose .gitmodules url BASENAME changed since the first mount fetches the wrong (new-basename) shard while the mount is the old basename → subs_pin_present false-positive → child object not found/SNIFFFAIL. Latent edge case (stable basenames in real flows); found in PATCH-005 fixture | | SUBS-039 | MED | all | reusable submodule-path delegation: route a <sub>/<path> verb arg into the mounted sub. PUT arm LANDED 1c4a97c8 (put.js subMountPrefix+stageInSub). OPEN: the DELETE arm (delete.js delStage has no sub split), hoist the splitter shared (pair with recurse.js resolveRepoForPath), unmounted-sub refuse, repros. Child of DIS-058 D10 | | SUBS-041 | MED | get | depth cap LANDED 6388c34e (MAX_SUBMODULE_DEPTH=8, get.js recurseSubMounts bail + warn). OPEN: the ONE bounded-deep-chain repro test (none greps the cap today). be/ JS, main tree | | SUBS-040 | HIGH | get/post/status | submodule branch tracking: I1-I3 (be/ JS mount ON dot-branch, advance on cascade post, measure vs dot-branch) FIXED live (rode DIS-058 mount chain + post advanceRef; test sub verified clean on its dot-branch 2026-07-07). OPEN: the dot-branch-advance repro assert (sub/cycle checks tip+gitlink only) + native I4/I5 (be put/post ?/<dot-branch> wrong-store sha / name mangle) | | SUBS-045 | MED | log/commit/blob/tree | be/ JS: prefixed nav URIs + descent — core LANDED 36b1aec0 (recurse.js resolveRepoForPath; log emit + commit:/tree: descend; test/log/subnav). OPEN: blob:/size: still sub-blind (live: jab blob:be/main.js from root → BLOBNONE) + status/diff/ls nav-target audit. Read twin of SUBS-039; child of DIS-058 |
Closed in the 2026-07-07 audit: SUBS-026 (last residual, the be head pin axis, landed b9c6b647); SUBS-033 (staged-gitlink status, 707bbbbe); SUBS-036 (idempotent synth-branch re-anchor, ae64dc7f, post/55); SUBS-037 (superseded — the JS get/post recursion redo landed under DIS-058 D1-D9 da0c12c3+da7fa5a7, gate be-js-sub-cycle); SUBS-042 (post selective gate, 1c4a97c8, sub/selective); SUBS-043 (undeclared/symlink never sub-classified, 36b1aec0, verified live); SUBS-044 (bare put/delete sub recursion, a715b0d3, sub/bareput+baredel); SUBS-046 (local sub mount reuses the store, d80bdb5c, jab-only suite green); SUBS-047 (same-source sub fetch fixes, rode 50e90012, be-js-unit-submount).
SUBS-027 (4-record/3-axis submodule state model + SUBSDirty classifier + be status Advanced-detection) landed 1585ac47+4ae70e29; the records, recursion semantics and the remaining axes (Edited compute, coord-mismatch) carry on in SUBS-027b. SUBS-014/015 (slashless-dir "did you mean dir/?" hint + blob: empty-ref resolves in the parent) landed 141cf77c. SUBS-022 (relative argv[0] broke chdir'd sub-spawns — dog/HOME.c realpaths argv0 before dirname) landed 453c55c2; SUBS-034 (the bare-name PATH-resolved residual — realpath the found exe before the sibling lookup) landed 6df16caa+5efa0966 with a deterministic be-sniff-bare-name repro. SUBS-023 (synthetic dot-branch ?/<sub>/.<parent> won't resolve on get) CLOSED — WON'T FIX (normal recursion re-attaches by pin, tested; the synthetic-name get is an unused internal form). SUBS-020 POST mirror (push each sub to the SAME destination GET fetches from — beagle→peer, git-non-.git→parent-relative, git-.git→official; bepushgit_recurse_cb + KEEP.exe.c branch-strip; post/43+44) landed 3eba8e76; GET side 4121eaaf. Case 2 (git-.git→official) is being gated behind --force by SUBS-031 (default skip). SUBS-021 (re-post leaked a SHA into the sub dot-branch's <subproj> slot) landed 8c69c16b — gated the sniff/GET.c raw-hex re-post fallback on DOGIsHashlet not DOGIsFullSha (sha-prefix gets still pass); test post/41-sub-synth-no-sha-in-subproj. SUBS-024 (POST/GET to a non-.git git remote routed an ABSOLUTE-.gitmodules-url sub to its official upstream, not parent-relative → unreachable abort) landed b09b09bf — case 4 = <remote>/<subpath> via SNIFFSubCandidateGitRel on both sides; post/45+get/53. Open follow-up: subs_recover_locator flags ssh git remotes as src_beagle (why GET case 3 never fired over ssh) — worked around by keying case 3/4 on URI form; own ticket TBD.