LANDED eec94934 (2026-06-06). Fixed via the absorbed-tree (theirs) ULOG cursor described in §"Root cause / fix"; repro test/post/28 green and off WILL_FAIL; full ctest 298/298.
HIGH — silent data inclusion. In commit-all (implicit) mode, be post commits an untracked file the user never staged, purely because the file's mtime collides with an in-scope put / patch row's timestamp. be post classifies each on-disk file by looking its mtime up in the wtlog via SNIFFAtRowAtTs (sniff/AT.c), which resolves a row by timestamp alone and never checks the row's path. An untracked sibling whose mtime aliases a put/patch/mod stamp is therefore misattributed as that row's work and ADDed to the commit (sniff/POST.c post_classify_step, the SNIFFAtKnown → SNIFFAtRowAtTs → POST_V_ADD branch).
Two variants, one root cause:
feature.c
(PATCH stamps it with the patch row's ts); an untracked junk.txt whose mtime equals that ts is swept into the same commit.
be post is now
commit-all (SUBS-001); the recursion's be put <sub> writes a sub-bump put <sub>#<40-hex> row. Any untracked file actively written during the post (e.g. a 2> file-in-the-wt stderr redirect) aliases that put stamp and is swept — and, because the post keeps writing it after hashing, lands committed-but-dirty, breaking the next branch switch. This is what blocks test/patch/28 (SUBS-002's repro) at its setup step.
tracked.c.b: add feature.c, commit; back to trunk.be patch ?./b — absorbs feature.c, stamps it with the patch row ts.printf ... > junk.txt; touch -r feature.c junk.txt — alias the stamp.be post '#absorb b' — commit-all (a patch row is in scope).be tree:?<tip> shows BOTH feature.c (correct) AND junk.txt (BUG).
Commit-all = git commit -a: every dirty tracked file plus files genuinely introduced by an absorbed patch land; an untracked sibling never does unless explicitly be put-staged. feature.c (in the absorbed tree) commits; junk.txt (in no absorbed tree) does not.
junk.txt is committed because its mtime aliases the patch stamp and POST trusts the ts→row lookup without verifying the row pertains to this path.
SNIFFAtRowAtTs is a ts-keyed lookup; the stamp model assumes mtime uniquely identifies the owning row, but ms-granularity mtimes alias (same DIS-023 class). The clean fix procures the absorbed (theirs) tree(s) as a ULOG from keeper — KEEPCommitTreeSha on each in-scope SNIFFAtPatchEntries sha, then KEEPTreeULog — and feeds it into the existing N-way classify merge as a 5th cursor (a thr verb, exactly like the baseline base cursor bu). An untracked file (!src_base) reaching the stamp-owned ADD branch is then committed only if it carries a src_thr record (i.e. it is genuinely in an absorbed tree); otherwise it is an alias and is ignored. No separate lookups, no parallel path-set — membership rides the merge. Covers both variants: the put-alias post has no patch rows, so the theirs cursor is empty and the untracked file is never ADDed.
test/post/28-untracked-alias-not-swept — deterministic local patch-alias repro (touch -r); WILL_FAIL until fixed. The put-alias variant is covered end-to-end once SUBS-002 unblocks test/patch/28.