fix(brain): a one-word tunnel title must match the prose case-exactly
CI / Mirror to GitHub (push) Successful in 4s
CI / Lint / Test / Vet (push) Successful in 31s

AutoTunnel matched note titles case-insensitively, so a one-word title linked
every entry that happened to use that word. Measured on the live corpus: 185
entries carry an auto-written See-also link to wiki/telos/decisions/wrong.md
(title "WRONG") and 136 to .../status.md — the two most-linked nodes in the
whole graph, and both of them artifacts of the English language rather than
references. telos's projects/problems/strategies/goals/beliefs entries account
for another ~60 between them.

That pollution is not cosmetic: inbound-link count is what the duplicate
Fixer picks survivors by, what orphan detection reads, and what brain_graph
shows.

One-word titles now need the title's own casing in the prose ("WRONG", "BERT",
"NLP" — an entity name in a sentence still links). Multi-word titles keep the
case-insensitive match: "risk tier middleware" is a real mention however it is
capitalised, and a three-word collision is not an accident.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-17 00:08:40 +02:00
co-authored by Claude Opus 5
parent eb2acfeeb8
commit 6e69698343
2 changed files with 79 additions and 15 deletions
+22 -4
View File
@@ -54,11 +54,24 @@ func DetectTunnels(brainDir, content string) ([]TunnelCandidate, error) {
return nil
}
title, _ := readTitleAndCreated(path, strings.TrimSuffix(d.Name(), ".md"))
needle := strings.ToLower(strings.TrimSpace(title))
if needle == "" {
title = strings.TrimSpace(title)
if title == "" {
return nil
}
idx := strings.Index(lowerContent, needle)
// A one-word title has to match the prose case-exactly. Matched
// case-insensitively, it links every entry that happens to use the
// word: "WRONG" (wiki/telos/decisions/wrong.md) collected 185 inbound
// See-also links and "Status" 136, making the two most-linked nodes in
// the graph artifacts of the English language rather than references.
// Multi-word titles keep the case-insensitive match — "risk tier
// middleware" in prose is a real mention however it is capitalised,
// and a three-word collision is not an accident.
haystack, needle := lowerContent, strings.ToLower(title)
if isSingleWord(title) {
haystack, needle = content, title
}
idx := strings.Index(haystack, needle)
if idx == -1 {
return nil
}
@@ -69,7 +82,7 @@ func DetectTunnels(brainDir, content string) ([]TunnelCandidate, error) {
out = append(out, TunnelCandidate{
TargetPath: filepath.ToSlash(rel),
MatchedTerm: title,
Exact: isWholeWord(lowerContent, idx, len(needle)),
Exact: isWholeWord(haystack, idx, len(needle)),
})
return nil
})
@@ -79,6 +92,11 @@ func DetectTunnels(brainDir, content string) ([]TunnelCandidate, error) {
return out, nil
}
// isSingleWord reports whether title is one whitespace-free token.
func isSingleWord(title string) bool {
return !strings.ContainsAny(title, " \t")
}
// isWholeWord reports whether the substring at [idx, idx+n) in s is
// bounded by non-alphanumeric characters (or string edges).
func isWholeWord(s string, idx, n int) bool {