be delete <file> should gate on mtime first, then a content-hash double-check when the mtime has drifted, and be delete --force <file> should delete a dirty file anyway. The impl is mtime-only with no hash fallback and no force bypass on the file/dir path, so a file with a drifted-but-identical mtime is wrongly refused and a deliberately dirty delete is impossible. The goal is to match the documented gate (see DELETE). User ruling 2026-05-31.
sniff/DEL.c implements only the mtime check; the hash double-check and the force bypass are missing code, not bugs in existing logic.
!SNIFFAtKnown(mtime) → DELDIRTY with no content fallback; the file's own comment flags the hash fallback as TODO pending a baseline-tree path→sha lookup.--force / -r only drive the recursive branch drop in DELBranch; there is no force bypass on the file or dir delete path.cp (identical bytes, fresh mtime) onto
bin/lib/store.js → be status/be diff bin clean (1396 ok, empty) yet be delete bin → DELDIRTY "bin has unstamped changes". The hash double-check would let this through (bytes == baseline blob).
be get <path> is a
no-staging overwrite that re-writes the file with a NEW mtime → still unstamped, delete still refuses; be put <path> stages a phantom (content==baseline). Only a FULL be get (rewrites the ..be.idx stamp sidecar) re-stamps it clean.
None; needs a baseline-tree path→sha lookup exposed to DEL.c for the content double-check.
Add the hash double-check and thread a force flag.
force flag into DELStage / del_dir so be delete --force <file> skips the dirty gate.--force over dirty (proceed).be get <path> re-stamp + the misleading message(out of this ticket's scope; the content double-check makes it moot for the identical-bytes case, but the "revert" advice is still wrong on its own).
9718a03a: content double-check + --force bypass on both the file and dir
delete paths. del_content_eq_baseline() (sniff/DEL.c) resolves the path's baseline blob via KEEPTreeDescend over SNIFFAtBaselineTreeSha and delegates the bytes-vs-baseline compare to the existing CLASSWtEqBase; the gate is now !force && !SNIFFAtKnown(mtime) && !content_eq_baseline. force threaded DELStage → del_stage_named → del_dir (--force in SNIFF.exe.c). New sniff/test/delforce.sh (SNIFFdelforce, 6 cases); sniff/delete suite 16/16.