session 2026-08-23: the vault got instruments, a convention, and a name for what it lacks
Fool: FOOL-SEED-RULE.md §2a corrected two days before the beacon — the heading
claimed a ruling scope the recorded ruling could not reach (d6377af, pushed).
Obsidian: the paper bridge tested and working, first notebook transcription
filed under its own entry date; vault-links.py built and twice caught failing
while its selftest read green; Paradigm + Marshall read in full; the Archive
Convention and Re-encounter placed in the vault; the vault's CLAUDE.md
rewritten after fifteen months stale.
Files: session record + notebook-provenance reference memory + 6 KG lines
(3 drift-patterns, 2 preventions, 1 measured-state); MEMORY.md rotated with
the prior Active Session demoted verbatim to MEMORY-reference.md;
scripts/vault-links.py archive-path fix (substring -> path component, 3 new
controls, 26/26).
No new PENDING items — today's vault work is steward-direct and touches no
governed artifact.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQKeKY9T9d95KpvHwwok8T
This commit is contained in:
co-authored by
Claude Opus 5
parent
9bc84a6f16
commit
e3da9abad1
+28
-1
@@ -149,13 +149,26 @@ class Index:
|
||||
return sorted({n for n in self.by_name if pref.match(n) and pref.sub("", n) == base})
|
||||
|
||||
|
||||
ARCHIVE_DIR = "99. Archive"
|
||||
|
||||
def in_archive(path, vault):
|
||||
"""Exact path-COMPONENT match, never a substring.
|
||||
|
||||
Earned 2026-08-23, hours after this file was written to avoid exactly this class:
|
||||
`"99. Archive" in str(p)` also matches `99. Archives—Previous Iterations`, an ARC
|
||||
folder inside 00. Compass. 78 live notes were silently excluded from every "live
|
||||
vault" figure of the day (1153 counted as archive; the real archive holds 1070).
|
||||
A substring is not a path."""
|
||||
return ARCHIVE_DIR in path.relative_to(vault).parts
|
||||
|
||||
|
||||
def scan(vault, include_archive=False, once_per_note=True):
|
||||
idx = Index(vault)
|
||||
dead, case_only, total = defaultdict(set), defaultdict(set), 0
|
||||
for p in sorted(idx.vault.rglob("*.md")):
|
||||
if "/.obsidian/" in str(p):
|
||||
continue
|
||||
if not include_archive and "99. Archive" in str(p):
|
||||
if not include_archive and in_archive(p, idx.vault):
|
||||
continue
|
||||
text = strip_code(p.read_text(errors="replace"))
|
||||
raws = [target_of(m) for m in WIKI.findall(text)]
|
||||
@@ -253,6 +266,20 @@ def selftest():
|
||||
chk("a vault with no broken links reports ZERO [negative control — proves the"
|
||||
" scanner is not manufacturing findings]", len(dead2) == 0 and tot2 == 1, state)
|
||||
shutil.rmtree(d2, ignore_errors=True)
|
||||
|
||||
# --- archive exclusion must match a path COMPONENT, not a substring ---
|
||||
d3 = Path(tempfile.mkdtemp())
|
||||
(d3 / "99. Archive").mkdir(); (d3 / "99. Archives—Previous Iterations").mkdir()
|
||||
(d3 / "99. Archive" / "Old.md").write_text("x\n")
|
||||
(d3 / "99. Archives—Previous Iterations" / "Live.md").write_text("x\n")
|
||||
(d3 / "Plain.md").write_text("x\n")
|
||||
chk("a note in '99. Archive/' IS excluded [positive control]",
|
||||
in_archive(d3 / "99. Archive" / "Old.md", d3), state)
|
||||
chk("a note in '99. Archives—Previous Iterations/' is NOT excluded [the 78-note"
|
||||
" over-match of 2026-08-23 — a substring is not a path]",
|
||||
not in_archive(d3 / "99. Archives—Previous Iterations" / "Live.md", d3), state)
|
||||
chk("a note at the vault root is NOT excluded", not in_archive(d3 / "Plain.md", d3), state)
|
||||
shutil.rmtree(d3, ignore_errors=True)
|
||||
finally:
|
||||
shutil.rmtree(d, ignore_errors=True)
|
||||
print(f"\n{'SELFTEST PASS' if not state['fail'] else 'SELFTEST FAIL'}"
|
||||
|
||||
Reference in New Issue
Block a user