Skip to content

conflicts

1. The block, verbatim

Pass --detect-conflicts to memhtml apply and each result gains a conflict field naming what that op’s claim contradicts. Dedupe catches an op whose content is IDENTICAL to something stored; this catches an op that says something DIFFERENT about the same thing, the case dedupe is blind to and the one that actually rots a corpus. The match is grammatical, not semantic: a claim is split into a frame (the subject and relation, up to its last of/is/in/to/by/as) and a value, and two claims conflict when they share a frame. The pool ceiling is 64 and The pool ceiling is 128 share the pool ceiling is. conflict.path names an ACTIVE memory already holding that slot; conflict.batch_index names an EARLIER op in this same call, which is the case nothing else can see because neither op is stored yet; conflict.claim is the other claim’s own text, so you can decide without a second read. It is null when nothing matched, and also when the claim has no frame shape. The rule refuses frames under three tokens and values over six, so short claims and claims trailed by a clause are deliberately unmatched rather than loosely matched. On a line using article_html instead of body it is always null, because the claim lives inside your markup and is not read until the store renders it. THE ASSIST NEVER CHANGES WHAT IS WRITTEN. An op carrying a conflict is written exactly as it would have been without the flag: nothing is archived, nothing is refused, and later does not win. That is deliberate, because sometimes the contradiction IS the answer. A memory recording that a runbook step changed necessarily contradicts the memory stating the old step, and a system that resolved that for you would delete the pair a reader needs in order to see the change at all. You decide per conflict: keep both (they are about different things, or both are true), memhtml correct <path> instead (the new claim supersedes the old one, and the old one stays readable under archive/), or drop the line (you were about to restate something already stored). Archived memories never match, so a superseded claim stops contradicting the claim that superseded it. When you have already decided that later wins (a re-scrape, a settings sync, any stream where each line is the newest statement of its slot), pass --consolidate last-wins (the batch tool’s consolidate: "last-wins") and the batch RESOLVES those matches instead of reporting them. Ops sharing a frame key write ONE file carrying the LATER value at the FIRST index that claimed the slot; each later restatement reports consolidated_into naming that slot and the summary counts it under consolidated, neither written nor failed. A stored ACTIVE memory occupying a surviving slot is archived with a supersedes link from the new file, its archive path reported as superseded_path, the same chain memhtml correct leaves, so ancestry reads identically. OFF by default, and the key is the conflict rule’s own: the frame split is a rule measured in the eval harness before it was believed and ported verbatim into @memhtml/domain’s frame.ts, which detection and consolidation share, so anything the rule refuses to key (short frames, clause values) is never consolidated, and what you saw reported with --detect-conflicts is exactly what this flag would have acted on. Every supersede, memhtml correct and --consolidate last-wins alike, also stamps a VALIDITY WINDOW, in the same one commit. The superseded memory gains memhtml-valid-until set to the moment the new fact became true (the winner’s own memhtml-valid-from, else its first <time datetime>, else the operation’s instant), and the winner gains memhtml-valid-from at that same moment, so one window closes exactly where the next opens. Min-wins: a memory already stating an EARLIER memhtml-valid-until keeps it, because a fact cannot outlive its earliest stated bound. That is what --as-of on memhtml search reads: pass an ISO instant and the result is what was believed valid AT THAT MOMENT. Since-superseded memories return, each marked superseded_by naming what replaced it, and facts not yet valid then are absent. History is read from the files, not replayed from git, so it survives a full index rebuild. The frame rule deliberately refuses to match a REWORDING — same fact, different words shares no frame key — and dedupe refuses it too, because the bytes differ. That gap is --detect-near-duplicates (the batch tool’s detect_near_duplicates): each result gains a near_duplicates list naming ACTIVE memories (or earlier ops in this same stream) whose text sits at or above cosine 0.92 against the op’s claim and body, best first, each entry carrying the other claim’s text, the measured similarity, and one of path or batch_index, the same split conflict uses. PROPOSE-ONLY, exactly like --detect-conflicts, and for one more reason: the score is geometry, and geometry is weak on the tokens that carry polarity — a claim and its negation also sit above 0.92 — so read the paired claim before folding anything. Left alone, the next sleep’s dedup-merge folds true rewordings under its divergence guards; this flag is for a batch writer that should not have to wait for a sleep run to learn it restated the corpus. It costs one embedding call per batch. On an article_html line it is always null (the claim lives inside your markup), and when the embedder cannot run at all (MEMHTML_EMBED=off, or the call failed) the result carries near_duplicates_degraded: true and every near_duplicates is null, meaning UNCHECKED rather than unique.

2. Commands it names

3. Provenance

A loader generates this page from apps/cli/src/commands.ts while the site builds, so no file in the repository holds it: the block is authored beside COMMANDS and is served verbatim by memhtml manifest, so this page and the live answer are the same bytes. Change the registry and this page changes with it.