Architecture decides what the store can hold. This stage is about the smaller, more easily-skipped rules that decide what actually gets written into it correctly — the kind of thing that only shows up once real content, not toy data, is going through the write gate.
The scope axis, and the rule that closes its loophole
Every entry carries a scope: project, portfolio, or local_only. The rule that matters more than the axis itself: project scope requires an actual edge to a real project node — you can’t mark something project-scoped and leave it floating with nothing to attach to. Under-binding is the safe failure; a piece of standalone context correctly lives at portfolio scope rather than being force-fitted onto a project it doesn’t actually belong to. The standalone-chat question worked through exactly this: the store doesn’t structurally privilege projects at all — a project is just a node with a type, and where a fact came from is metadata, not schema. Getting the scope right at write time is a discipline question, not something the schema enforces for you.
Reject-and-repropose, not silent correction
When a proposal turns out wrong — not malicious, just mis-scoped or mis-encoded — the convention is to reject it and have it re-proposed properly, not quietly patch it in place. A rejected proposal leaves no trace in the authoritative log; nothing about it is retried automatically. The clearest real example of this working is the temporal-grounding skill capture below, where a scope error on the first attempt was caught, the proposal rejected, and a corrected version re-proposed — rather than the record being edited after the fact to look as if it had been right the first time. Keeping the wrong attempt visible-then-superseded (or, if never approved, simply absent) rather than smoothed over is the same honesty principle the write gate itself is built on: the record shouldn’t look more finished than the process that produced it actually was.
The HTML-entity gotcha
Two separate moments surfaced the same small, easy-to-miss defect class: field content passed to propose_entry can arrive HTML-entity-escaped rather than as plain text, and nothing in the tool surface catches that automatically. A Stage 1.3-era gap review flagged it in the abstract — “no mention of how to handle or detect content-encoding issues (HTML entity escaping) in proposed field values before they’re surfaced for approval” — worked out through direct conversation rather than being in SKILL.md from the start. It then showed up for real during the temporal-grounding capture below: Claude caught the escaping in its own draft proposal before staging it — “HTML entity escaping snuck in there. Let me fix that.” — and corrected it pre-submission. Small, but exactly the kind of defect that would otherwise sit invisibly in the log looking like a formatting choice rather than a bug.
The temporal-grounding skill: the system catching and correcting itself
The clearest worked example of this whole stage is a single capture, mem-local entity e40. I’d caught Claude reasoning about a “tomorrow” event as if it might already have happened — a directional logic error, not a fuzzy estimate — and had a temporal-grounding skill written to fix it: always compute dates via bash rather than reasoning about them mentally, re-anchor “today” fresh each turn instead of trusting an earlier one, and explicitly check whether a resolved date is before or after today before answering a has-this-happened-yet question.
Capturing that decision into mem-local surfaced two convention questions at once, and both were worked through rather than glossed:
- Scope, corrected. The first proposal (staged as #108) marked the capture
projectscope. It wasn’t edged to any actual project — the Robin Hood half-marathon dates it hardcodes are training-plan content, not evidence the skill belongs to that project. Proposal #108 was rejected and re-proposed atportfolioscope, the honest reading per the under-binding rule above. - A known trade-off, written down rather than silently accepted. The skill hardcodes anchor dates (race day, training start) as literal text rather than querying Google Calendar or mem-local live at run time. That was a deliberate, considered choice — trial the simpler bash-only version first and check it’s token-efficient before adding a lookup call to every date-related question — not an oversight. The capture records the trade-off explicitly, including that the hardcoded “17 weeks total” figure had already been found stale against a corrected ~21-week figure elsewhere, so a future reader isn’t left thinking the drift risk went unnoticed.
Why this stage matters
None of this is architecture. A scope-binding rule, a reject-and-repropose habit, an entity-encoding footnote — none of it would survive being called a “decision” the way the bi-temporal model or the write gate would. But it’s the layer where the store’s honesty actually gets tested. An architecture can be sound and a store can still fill up quietly with mis-scoped, half-encoded, quietly-patched entries if nobody holds this line. The temporal-grounding capture is one live example of the line actually holding — not just holding in the register’s prose.
Sources: mem-local e40 (temporal-grounding skill, proposal #108 rejected and re-proposed); Improving AI’s temporal reasoning abilities, 5 Aug 2026; Memory management, 21 Jul 2026 (SKILL.md gap review, HTML-entity flag); earlier, unpublished notes memory-system-standalone-chat-inclusion; mem-local e13 (Stage-1.2 vocabulary-integrity cluster).