Repository navigation
Description
Bug Description
A list item that is ordinary prose still mints a typed relation, taking its type
from the last word before the wikilink.
- Added [[Target Note]] to the rosterfiles that as a kind of relationship called Added. Nobody wrote a
relationship there — it is a sentence from a log.
This is the sibling of #1219 (timestamp-prefixed transcript lines) and #1241
(extended checkbox markers) on the relation side rather than the observation
side: a recognizer whose shape is broad enough to eat ordinary writing.
Steps To Reproduce
mainata7a8bfb679be04e6f84d93b79dd4ee20bb5bc6eb(2026-08-14).- Parse:
from markdown_it import MarkdownIt
from basic_memory.markdown.plugins import observation_plugin, relation_plugin
md = MarkdownIt().use(observation_plugin).use(relation_plugin)
for src in [
"- Added [[Target Note]] to the roster",
"- Mother [[Target Note]]",
"- Calls [[Target Note]] every Sunday",
"- spouse_of [[Target Note]]",
]:
rels = [r for t in md.parse(src) if t.meta for r in t.meta.get("relations", [])]
print(f"{src!r} -> {rels}")Actual Behavior
'- Added [[Target Note]] to the roster' -> [{'type': 'Added', 'target': 'Target Note', 'context': None}]
'- Mother [[Target Note]]' -> [{'type': 'Mother', 'target': 'Target Note', 'context': None}]
'- Calls [[Target Note]] every Sunday' -> [{'type': 'Calls', 'target': 'Target Note', 'context': None}]
'- spouse_of [[Target Note]]' -> [{'type': 'spouse_of', 'target': 'Target Note', 'context': None}]
The first three are prose. Only the fourth was written as a relation.
Note the trailing text is discarded silently: to the roster and
every Sunday do not survive anywhere. The line is read as a relation and the
rest of the sentence is dropped.
Expected Behavior
Prose bullets should keep their links_to edge and produce no typed relation.
- spouse_of [[Target Note]] must keep working.
Why this survived #824
#824 established the current grammar deliberately, and correctly: unquoted
labels must be a single token, multi-word labels must be quoted, and
- some other thing [[Target]] falls through to inline handling. That closed
the case where a whole sentence became a relation type.
A single capitalized English word passes that test. Added is one token
with no whitespace, so by shape alone it is indistinguishable from a
hand-authored spouse_of. The surviving pattern is narrower and more specific
than the original: a sentence-initial capitalized word immediately before a
wikilink, inside a list item.
I don't think this was an oversight — #824's own scope note says the
explicit/inline distinction is ambiguous under the current syntax. This report is
about how much of that ambiguous middle zone is load-bearing in practice, which
turns out to be more than it looks.
Measured impact in a live vault
One real vault, indexed continuously for months, on a build carrying #824 plus a
local tightening that already rejects non-identifier types (dates, **, arrows):
- 457 edges, 63 distinct relation types, 162 typed (the rest
links_to) - 20 of the typed edges are parse artifacts — 12.3%
- Nine of those survive fix(core): parse prose wikilinks as inline links #824's grammar, all of the form above:
Added,Created,Rewrote,Updated,Links:,Calls,Mother,On,see
The everyday writing that produces them is a dated log bullet mentioning a person
by wikilink — which is the shape most note-taking conventions actively encourage.
The more disciplined the logging, the more artifacts.
Mother is the instructive one. Somebody genuinely meant a relationship on that
line. The parser just had no business inventing its type out of the sentence.
Possible directions
Not prescribing, and each has a real cost:
- Reject a type that is followed by more text after the wikilink. A genuine
relation line usually ends at the target or a(context).- Added [[X]] to the rosterhas a prose tail;- spouse_of [[X]]does not. Cheap and catches
most of the nine — but legitimately typed lines with trailing prose lose their
type. - Require lowercase for unquoted types. Kills
Added/Mother/Calls, keeps
spouse_of/relates_to/使用, and gives authors a quoted escape hatch that
already exists. Backward-incompatible for anyone usingRequires [[X]]today. - Anchor to structure — only parse typed relations under a
## Relations
heading or behind an explicit marker. The only truly decidable option, and the
most disruptive. - Leave the grammar alone and document it, so downstream tools know a typed
edge is only as trustworthy as the vocabulary behind it.
Happy to open a PR for whichever direction you'd want, or none — the grammar call
is yours, and I'd rather you make it than have me guess.
Activity
ahmedaminebouchmal commentedon Aug 17, 2026
I reproduced the ambiguity described here. Before preparing a PR, can maintainers confirm the intended grammar policy: reject trailing prose after the wikilink, require lowercase unquoted relation types, or require an explicit relation marker? I can then add regression tests for Added, Mother, and Calls while preserving spouse_of.
phernandez commentedon Aug 21, 2026
Thanks for this — the measured vault impact (12.3% of typed edges as parse artifacts) is what moved it up the queue, and the analysis made the fix easy to scope. Policy answer to your question:
Direction 1 is now the grammar, shipped in #1291 for v0.23: an explicit relation line ends at its target or its
(context); any other trailing text falls through to inlinelinks_tohandling. That killsAdded/Calls/Links:-style artifacts, and as a bonus preserves every wikilink in the tail (the old path silently dropped them). The named cost — legitimately typed lines with trailing prose lose their type — we accept: the old behavior was already discarding that tail from the edge, so falling back to a plain link loses strictly less.The remaining middle zone —
- Mother [[X]], a capitalized single word with no tail — stays open here. It's genuinely undecidable by shape (Requires [[X]]is a legitimate hand-authored type today), so it needs a real policy call between your directions 2 (lowercase-or-quoted requirement, backward-incompatible) and 3 (structural anchoring). Moving this issue to the v0.23.1 milestone for that discussion — if you want to take a run at it once the policy is agreed, the regression-test framing from your report is exactly the right shape.phernandez commentedon Aug 23, 2026
Closing this as resolved for the v0.23 grammar.
#1291 fixed the actionable bug: relation-shaped bullets with prose after the target now fall back to
links_to, preserve the prose, and preserve every wikilink on the line.The remaining no-tail form, such as
- Mother [[Target]], is the documented explicit-relation grammar: relation types are author-defined single-token labels, not a fixed vocabulary. We are not going to distinguish them through capitalization or language heuristics.#1301 tracks the explicit authoring escape hatch we agreed on: a terminal
#bm:links_todirective that forces the line to emit implicitlinks_toedges without polluting tags or indexed content.