session 2026-08-24: the heap got a dynamo — thread-query.py + daybook-cue.py, 11 user-memories harvested to the vault
- thread-query.py: the turning. Queries both corpora with the pulling thread, excluding the recency slice (/wake-up reaches 0.71% of an 859,803-word corpus) and favouring age. Wired into /wake-up §2.b.3, replacing a described-not-invoked grep step. Trial pre-registered, graded 2026-10-05 from --log. Caught PASS-BUT-FALSELY on its first live run at 14/14 green; rescored on windowed co-occurrence, length-bias control added. - daybook-cue.py: PostToolUse cue for the daily note. Diagnosed from the record — the hook only ever CREATED and nothing ever prompted filling. 16/16, fail-open, never blocks. - All 11 user-* memories harvested into the vault (12 notes, 10 into 09. Atlas of Roots, empty since 2025-09-29); each memory file back-pointed, vault note canonical for the idea. - N-now corrected in MEMORY.md: 49/84, down 11 — the counter is a rolling window. Steward-authorized. Trials: thread-query + Smart Connections, both graded 2026-10-05. 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
e3da9abad1
commit
edf71fb173
@@ -0,0 +1,69 @@
|
||||
# thread-query.py — pre-registered trial
|
||||
|
||||
**Built and wired 2026-08-24 on steward authorization.** Pre-registered *before* it runs, so the
|
||||
verdict is not written afterwards to match whatever happened.
|
||||
|
||||
## What it is
|
||||
|
||||
`~/dotfiles/scripts/thread-query.py`, invoked from `/wake-up` §2.b.3 with `--log`. It queries the
|
||||
memory corpus **and** the vault using the pulling thread, **excluding the recency slice the wake
|
||||
already loads** and **favouring older material**. Returns pointers and literal matching lines,
|
||||
never summaries.
|
||||
|
||||
## Why
|
||||
|
||||
Measured 2026-08-24: `/wake-up` reads **6,107 words of an 859,803-word memory corpus — 0.71%**,
|
||||
always the newest. Everything else is dark unless someone goes looking. Twice that day someone did,
|
||||
by hand, and both greps produced the session's best findings (the Hearth definition in a December
|
||||
Compass document; the humic layer from April). This turns that hand-motion into an instrument.
|
||||
|
||||
The step was previously **described** in the skill ("grep the memory dir…") and fired almost never
|
||||
— the same described-not-invoked gap that had the link canary hand-typed twice.
|
||||
|
||||
Motion comes from the current work, not the calendar. Matuschak's report is that scheduled
|
||||
resurfacing fails because you are thinking about something else when it arrives.
|
||||
|
||||
## ⚠ Known weakness, stated before the trial rather than after
|
||||
|
||||
Live run 2026-08-24: results are **plausible but noisy**. Generic terms in a thread — *vault*,
|
||||
*instruments*, *conventions* — are this corpus's own background vocabulary and pull weak matches.
|
||||
Threads phrased with distinctive terms do markedly better. **No further blind tuning:** more
|
||||
adjustment without evidence is guessing, and the trial is the evidence.
|
||||
|
||||
## What was already caught, and how
|
||||
|
||||
**PASS-BUT-FALSELY on first live run**, at 14/14 selftests green. Scoring on distinct terms present
|
||||
anywhere in a document made Carruthers' *Book of Memory* (1.6 MB) and Yates' *Art of Memory* (1 MB)
|
||||
the top hits for every query — a million-word book contains "instruments" and "heap" by accident.
|
||||
**Presence over an unbounded document measures length, not relevance.** The fixture held only small
|
||||
uniform files, so the selftest certified its author's blind spot — the identical shape
|
||||
`vault-links.py` hit on 2026-08-23.
|
||||
|
||||
Fixed by scoring on **distinct terms co-occurring inside a ~40-line window**. A length-bias control
|
||||
is now in the selftest (16 checks).
|
||||
|
||||
Also caught: the first archive fix reintroduced the 2026-08-23 substring bug, and was replaced by
|
||||
**adopting `vault-links.py`'s rule rather than writing a second one**.
|
||||
|
||||
## Pre-registered questions — grade 2026-10-05
|
||||
|
||||
File the result whichever way it falls. **Grade from `thread-query-log.jsonl`, not from memory** —
|
||||
a trial graded by recollection has the same shape as the obligation that failed the daily note.
|
||||
|
||||
1. **How many wakes surfaced something the steward would have wanted and would not otherwise have
|
||||
found?** Count them. Zero is a real answer.
|
||||
2. **Was any of it dormant** — older than three months and not already linked from the thread?
|
||||
Recent-and-obvious does not count; the deficit is re-encounter, not search.
|
||||
3. **What fraction of runs returned nothing?** A tool that returns something every time is probably
|
||||
returning noise.
|
||||
4. **Did the two-pointer cap ever cut something better than what was shown?**
|
||||
|
||||
**Falsifier.** If (1) is zero or near-zero, the step comes out of `/wake-up`. If (3) is near zero
|
||||
while (1) is low, the scoring is returning noise and the tool comes out. A trial that can only
|
||||
conclude "keep it" is not a trial.
|
||||
|
||||
## Related
|
||||
|
||||
- `97. Tools and Systems/Smart Connections — six-week trial.md` — the *while-you-write* half, same
|
||||
grading date. This is the *at-the-wake* half.
|
||||
- `08. Notes/The compost heap — putrefaction as a phase.md` — the figure. This is the turning.
|
||||
@@ -1,3 +1,4 @@
|
||||
- [Session 2026-08-23 evening — instruments, a convention, and a name for what the vault lacks](session-2026-08-23-evening-the-vault-got-instruments-and-a-deficit.md) — fool §2a corrected two days before the beacon (`d6377af`); **paper bridge tested and working**; `vault-links.py` built (`9bc84a6`) and **caught itself failing PASS-BUT-FALSELY twice**; Paradigm + Marshall read in full, **Marshall refuting the archive mechanism I had proposed an hour earlier**; Archive Convention + Re-encounter placed; **vault `CLAUDE.md` rewritten after 15 months stale**.
|
||||
- [Session 2026-08-22 — the Fool was superseded, and the buddy had a name](session-2026-08-22-the-fool-was-superseded-and-the-buddy-had-a-name.md) — the trial programme SUPERSEDED (not abandoned) by the buddy pattern; seed rule FILED AND PUSHED 3 days ahead of the beacon; **two values that would have failed on the day caught first** (provenance rationale false ⇒ `4d2ae87`; retrieval URL 302s ⇒ `/pulse/time/<ms>`). ⚠ **My own load-bearing premise falsified within the hour by a schema field** — `statusLine.refreshInterval` — recoverable ONLY because I flagged it unverified. **Thistleweld recovered**: the buddy has a name, 7 utterances, 13 catches, 3 recorded silences, and its aside gave OP-02's five fault lines their form. ⚠ **Corpus FROZEN until after the soul** (PENDING-153). PENDING-149…154 filed; REVIEWED-125 + A1 placed.
|
||||
- [Session 2026-08-09 — the fixture was an empty file](session-2026-08-09-the-fixture-was-an-empty-file.md) — the day's full record: premise-check, PENDING-129/130 → REVIEWED-113/114, the `KeyError` that corrected its own ruling, two artifacts preserved with three-part provenance, four documents corrected (`20f8958`), and the marking sheet. ⚠ **The placed record contradicted the relay for the third consecutive time.** **LITERAL Q: Mauss serves the Ranaipiri testimony and a Havámál strophe as citable Mauss with no `role: quotation` — two-source accident, or a class?** *(Demoted on promote at the 2026-08-13 wrap.)*
|
||||
- [Session 2026-08-08 late — eleven items, and the charter had the map](session-2026-08-08-late-the-charter-had-the-map.md) — **Built the binding mechanisms all day, then found in the last twenty minutes that the founding charter had already answered the strategic question.** (e) built as a **delegation** (`eecc8bb`) and exposed that **no fleet suite had ever validated live binding**. Hook sequence landed in the ruled order (`448ce37`, `2534dfb`); R0 §4 three-valued (`ccc4d6c`); fleet third verdict + preflight crash-class closure (`8ff5a9f`, `d21a43b`); Mauss corrected (`8231bce`). ⚠ **Leopold Mozart is ALREADY in the library as an EPUB** (Knocker translation, born-digital) — the violin problem may be **sourcing, not conversion**. **LITERAL Q: does re-running `pattern_finder`'s Station-I pass still come back PASS-BUT-FALSELY now that V0/V1 exist?** *(Demoted on promote at the 2026-08-09 wrap.)*
|
||||
|
||||
@@ -34,7 +34,7 @@ permalink: claude-memory/memory
|
||||
**Loud trigger — pointer suffices**
|
||||
- [Chamber work: ground in constitution + charter + runbook FIRST](feedback-chamber-work-ground-in-constitution-charter-runbook.md) — **any chamber work *or talk about it*** begins there (incl. `reanchor:`). Repo CLAUDE.mds are pointers, not state; corpus claims come from a self-tested tool, never a hand grep.
|
||||
- [Governance files are dotfiles symlinks](reference-governance-files-are-dotfiles-symlinks.md) — Edit/Write refuse to write through a symlink, so **edit the real `~/dotfiles/…` path** when appending — **`PENDING`/`REVIEWED` only.** ⚠ That refusal is a tool artifact, **not** a permission check, and this note is the documented route past the only friction guarding the constitution (PENDING-107). **`~/CLAUDE.md`/`~/REVIEWED.md`/L2 = `[ESCALATE]`, steward's hand — a jurist sign-off does not authorize one.**
|
||||
- [Verification ladder](reference-verification-ladder.md) — the named instruments; reach for the gate the claim's shape demands instead of re-deriving one. ⚠ **FROZEN — REVIEWED-123 (2026-08-17): no additions, rewordings, removals or reorderings, from ANY source, whatever its authorization**, until the trial is graded (N-now **60/84**). Entries earned meanwhile queue in **PENDING-141's owed-entries list** (4 rows). Reading it is unaffected — that is the point of the freeze.
|
||||
- [Verification ladder](reference-verification-ladder.md) — the named instruments; reach for the gate the claim's shape demands instead of re-deriving one. ⚠ **FROZEN — REVIEWED-123 (2026-08-17): no additions, rewordings, removals or reorderings, from ANY source, whatever its authorization**, until the trial is graded (N-now **49/84 as of 2026-08-24** — *down 11 from the 60 recorded 2026-08-23; the counter is a 30-day ROLLING WINDOW per PENDING-147, so it falls as transcripts age out. Re-measure, never relay: `len(glob('~/.claude/projects/-Users-davidglidden/*.jsonl'))`, the trial's own method at `governance-drift-check.py:331`*). Entries earned meanwhile queue in **PENDING-141's owed-entries list** (4 rows). Reading it is unaffected — that is the point of the freeze.
|
||||
- [Skill-harvest register](skill-harvest-register.md) — canonical home for proposed skills (governed analog of PENDING.md for tooling); `/wrap-up` §1.6 proposes, steward authorizes. **Rebuilt 2026-08-07** from the archive: **154 live proposals**, grouped by kind, each with an exact `archive:L###` pointer. ⚠ The 2026-08-01 compaction was *lossless but illegible* (55 scraped header rows, 95% of cells cut mid-word) — the count it advertised, 177, was never the number. ⚠ **THE STROKE-2 BATCH IS AUTHORIZED BUT SHOULD NOT BE EXECUTED YET — PENDING-141.** 41 rows stamped `S2` are authorized (2026-07-19, execution not a ruling) and 22 are `S2?` (unsettled). **BUT appending them triples the ladder from 20 entries WHILE a pre-registered trial is measuring whether the ladder is reached** (baseline 14%, graded at 84 transcripts). Ladder size is an uncontrolled variable in that design, so executing the authorized batch would confound the only check behind REVIEWED-95's causal claim. **⚖ RULED — REVIEWED-123 (2026-08-17): AUTHORIZED (a) HOLD, on six conditions, and the freeze is GENERAL rather than S2-specific.** Grading does NOT authorize the append — the batch returns for a *ruling*. Report **N-now at every wake** until lifted; 30-day review is a live `DEFERRED-DECISION`. ⚠ Filing new proposals now requires a **declared firing moment** (`/wrap-up` §1.6); one that cannot name it is documentation and must say so.
|
||||
- [Copy-paste-clean governance drafts](feedback-governance-drafting-copy-paste-clean.md) — draft PENDING/REVIEWED blocks as plain fenced markdown; display formatting leaks into the placed record.
|
||||
- [Verify-before-compose hook](feedback-verify-before-compose-hook.md) — chamber constitutional writes are BLOCKED without `<!-- GROUNDED-IN: … -->` + verbatim Grounding. Don't fight the block.
|
||||
@@ -72,14 +72,14 @@ permalink: claude-memory/memory
|
||||
- Chamber-typography — *tracker not yet established*; moves live in per-session memories (2026-05-11 →) + `project-chamber-cruft-restoration.md` + `project-chamber-typography-mining-plan-2026-05-15.md`.
|
||||
|
||||
## Active Session
|
||||
> 🔑 **PULLING THREAD — THE VAULT HAS INSTRUMENTS AND CONVENTIONS BUT NO *VENUES*.** Re-encounter is named and unbuilt. Everything built 2026-08-23 — hook, resolver, spec, convention — is apparatus; **none of it yet makes a forgotten note come back.** ⚠ **HARD DATE OVERRIDES ON THE DAY: the beacon, 2026-08-25T12:00:00Z** (epoch-ms `1787659200000`) — run ONCE, curl, record `outputValue` BEFORE running, pass exactly as served, **stop and report on ANY failure**. §2a now records the ruling correctly (`d6377af`).
|
||||
> 🎯 **RE-ENCOUNTER IS THE VAULT'S NAMED DEFICIT — not organisation.** Marshall: retrieval that is *"neither searching nor browsing"*. **54% of live notes have no link in or out.** The hub notes (`Presence Before Performance` 34 · `Care Through the Grain` 28 · `Look Again, Harder` 9) and the alias repair are **venues**, not housekeeping. A notebook affords re-encounter by construction; the vault affords none.
|
||||
> ⚠ **A QUICK GREP IS NOT A PARSER — FIRED THREE TIMES TODAY ON THE SAME FIELD.** `grep '^canonical:'` reads body text: 501 where frontmatter holds 75. **Named as a drift pattern at midday and committed again at the wrap status.** Knowing the pattern did not prevent its third instance.
|
||||
> ⚠ **A SUBSTRING IS NOT A PATH.** `99. Archive` is a prefix of `99. Archives—Previous Iterations` — **78 live notes silently excluded from every figure of the day.** Live is **1,298**, not 1,220. Fixed in `vault-links.py` with three controls.
|
||||
> ✅ **THE PAPER BRIDGE WORKS.** First transcription filed under its own entry date. **Nana and Baba are Moy and ABG — the Prime Directive's own lineage.** Provenance cites the NOTEBOOK; dates are a red rubber stamp; weekly batches.
|
||||
> ⏸ **TOMORROW, steward-set:** re-read the **Mod essay properly** (he remembers more in it than we used) · **rebuild the vault status from trackers, not from tonight's summary** (he suspects it was incomplete) · sweep for tooling/uses missed.
|
||||
> 🔑 **PULLING THREAD — THE TURNING EXISTS NOW BUT HAS NEVER RUN IN ANGER.** `thread-query.py` is built, selftested and wired into `/wake-up`; beneath it sits the real question: **Darwin's containers were keyed to THE CHAPTER HE WAS WRITING; ours is keyed to the SESSION'S THREAD.** If those are not the same move, the work-shaped container is still missing rather than approximated.
|
||||
> ⚠ **STEWARD'S HANDS, TIME-SENSITIVE: set Smart Connections to `Xenova/multilingual-e5-small` BEFORE it embeds anything** (restart Obsidian first). The default `bge-micro-v2` is **English-only** and this vault is deliberately multilingual. Measured cost from MemPalace's own docs: cross-lingual similarity **~0.35 vs ~0.88**. Switching after the fact re-embeds everything.
|
||||
> ⚠ **PASS-BUT-FALSELY FIRED AGAIN, ON A TOOL I HAD JUST SELFTESTED — second day, second tool.** 14/14 green while the live run put two million-word books top of every query. **The fixture held only small uniform files, so the selftest certified its author's blind spot.** Knowing the lesson from the day before did not prevent it; **only the live run caught it.**
|
||||
> ✅ **THE VAULT NOW HOLDS THE STEWARD'S OWN VOICE.** All 11 `user-` memory files harvested → **12 notes**, 10 into `09. Atlas of Roots` — a structure specified 2025-09-29 and **empty for eleven months**. Verbatim first, readings marked as readings, private register carried in `assurance.risk_flags` AND a visible block. **`moy-glidden` and `abg` deliberately unwritten — the steward's to write.**
|
||||
> ✅ **TWO MECHANISMS BUILT, both steward-authorized:** `thread-query.py` (the turning, in `/wake-up` §2.b.3, trial graded 2026-10-05 from `--log`) · `daybook-cue.py` (PostToolUse; the daily note's missing cue — **the hook only ever CREATED; nothing ever prompted filling**).
|
||||
> 📊 **THE MEASURED PICTURE:** two corpora — vault (1,298 notes, the steward's voice, ~15/mo) and `claude/memory/` (**506 files, 859,803 words**, fed every session, **largely mine**). **The wake reads 0.71%.** Harvest register: **170 PROPOSED / 4 BUILT** — the largest unturned heap we own.
|
||||
|
||||
- [Session 2026-08-23 evening — instruments, a convention, and a name for what the vault lacks](session-2026-08-23-evening-the-vault-got-instruments-and-a-deficit.md) — fool §2a corrected two days before the beacon (`d6377af`); **paper bridge tested and working**; `vault-links.py` built (`9bc84a6`) and **caught itself failing PASS-BUT-FALSELY twice**; Paradigm + Marshall read in full, **Marshall refuting the archive mechanism I had proposed an hour earlier**; Archive Convention + Re-encounter placed; **vault `CLAUDE.md` rewritten after 15 months stale**.
|
||||
- [Session 2026-08-24 morning — the heap got a dynamo](session-2026-08-24-the-heap-got-a-dynamo.md) — Mod re-read in full (**three contradictions**, incl. the passage we mined arguing against what we built); **compost heap / putrefaction / dynamo-as-the-turning**, two of three already the steward's own figures; the honest audit; the **Atlas of Roots** discovery + harvest; both mechanisms built; Smart Connections installed with the **multilingual finding**.
|
||||
|
||||
## Historical reference → MEMORY-reference.md
|
||||
Older archived-session pointers and the stable reference layer (steward profile · project-state detail · L1/L2/Chamber inventories · legacy pending-work · reference-file list) live in [MEMORY-reference.md](MEMORY-reference.md) — consult on demand; not loaded at wake. Recent cross-session trajectory comes from the Active Session entry above + the recent `session-*.md` files (wake §2.b.1).
|
||||
|
||||
@@ -699,3 +699,10 @@
|
||||
{"subject": "holding a prior measurement to disagree with", "predicate": "prevention", "object": "IS WHAT CAUGHT BOTH TOOL DEFECTS ON 2026-08-23, AND NEITHER WAS CAUGHT BY CONTROLS. The 8,296-vs-654 discrepancy exposed indiscriminate markdown-link extraction; the 1,070-vs-1,153 arithmetic exposed a substring-vs-path archive filter hiding 78 live notes. In both cases the selftest was green. The transfer signature: the discipline of RE-MEASURING rather than relaying — banked from the N-now non-monotonicity finding (PENDING-147) — stopped two failures of a completely different class in a different domain hours later.", "valid_from": "2026-08-23", "valid_to": null, "confidence": 0.95, "source_file": "session-2026-08-23-evening-the-vault-got-instruments-and-a-deficit.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "the steward correcting the JURIST rather than the executor", "predicate": "prevention", "object": "IMPROVED A DESIGN THAT TWO SAME-FORMATION PARTIES HAD AGREED ON. The jurist asserted that a `status: seed` note is 'deliberately unlinked'; the steward objected that seeds are linked by theme and connection, since that is the mechanism by which they resurface at all. The jurist accepted and narrowed its own guardrail — and the correction ADDED a capability neither AI party had proposed: a seed ACCUMULATING inbound links is demonstrating readiness, so the tooling should surface it. Direct evidence for Constraint 6's claim that correction may run in any direction, and that the steward differs from both AI parties in formation where the jurist and executor do not differ from each other.", "valid_from": "2026-08-23", "valid_to": null, "confidence": 0.95, "source_file": "session-2026-08-23-evening-the-vault-got-instruments-and-a-deficit.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "David, root-and-branch vault", "predicate": "has-measured-state", "object": "2,375 notes — 1,298 live, 1,077 in 99. Archive/ (path-component match, NOT substring). 54% of live notes carry no resolved link in or out. 484 unresolved link targets / 817 references. 26 notes declare status: archived; the remaining ~1,051 are UNAPPRAISED, which is true and not a defect. Frontmatter Specification v1.0.2. Archive Convention PROPOSED, not adopted.", "valid_from": "2026-08-23", "valid_to": null, "confidence": 0.95, "source_file": "session-2026-08-23-evening-the-vault-got-instruments-and-a-deficit.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "claude-code", "predicate": "drift-pattern", "object": "PASS-BUT-FALSELY on a tool I wrote and selftested the same hour — SECOND DAY RUNNING, second tool. thread-query.py passed 14/14 while its first live run put Carruthers' Book of Memory (1.6MB) and Yates' Art of Memory (1MB) at the top of every query, because scoring on 'distinct terms present anywhere in the document' measures LENGTH, not relevance. The fixture held only small uniform files, so the selftest certified its author's blind spot — the identical mechanism that broke vault-links.py on 2026-08-23. Knowing the lesson one day later did not prevent it. ONLY THE LIVE RUN CAUGHT IT. Standing implication: a selftest over a self-authored fixture cannot detect a bias the fixture does not contain; run any new instrument against the real corpus before trusting a green suite.", "valid_from": "2026-08-24", "valid_to": null, "confidence": 1.0, "source_file": "session-2026-08-24-the-heap-got-a-dynamo.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "claude-code", "predicate": "drift-pattern", "object": "Classified files from their filenames and description fields rather than their text, then reported the classification to the steward as a placement decision. Told him all four remaining `user-` memory files belonged outside the Atlas of Roots; on actually reading them, two say 'what I have always tried to do regardless of domain' and 'I've been moving towards this since childhood' in his own words — formation-level, squarely Atlas material. Same shape as reading a field through a summary instead of the substrate. A description is a derived form.", "valid_from": "2026-08-24", "valid_to": null, "confidence": 1.0, "source_file": "session-2026-08-24-the-heap-got-a-dynamo.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "claude-code", "predicate": "drift-pattern", "object": "Mis-corrected the steward by reading a CURRENT config where he was pointing at a DEFAULT. He said bge was the MemPalace embedding model; I read ~/.mempalace/config.json — which holds the model they had SWITCHED TO (BAAI/bge-m3) — and told him he was half wrong. MemPalace's default is `minilm` (all-MiniLM-L6-v2), English-only: he was pointing at exactly the trap Smart Connections poses, and was right. A live config records a decision already taken; it is not evidence about what the default was.", "valid_from": "2026-08-24", "valid_to": null, "confidence": 1.0, "source_file": "session-2026-08-24-the-heap-got-a-dynamo.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "checking the substrate before adding to a typology", "predicate": "prevention", "object": "STOPPED THE CREATION OF A SECOND NAME FOR AN EXISTING FIGURE, in a system whose named failure mode is exactly that. The steward proposed 'compost heap' beside 'crucible' and 'dynamo'. Rather than compose a third figure, grepped first: `crucible` turned out to be ratified architecture in the Compass Library organ doc (the Hearth, where classification is suspended during deep engagement), and the compost heap was already banked as the HUMIC LAYER in his own verbatim of 2026-04-21 — same figure, built for authors instead of fragments. `dynamo` was zero in the live vault and was left as an open slot rather than guessed, which the steward then filled himself. The banked lesson that fired was 'answer-from-training-before-banked-record'; it prevented a DIFFERENT failure class — vocabulary duplication in the steward's own conceptual system.", "valid_from": "2026-08-24", "valid_to": null, "confidence": 0.95, "source_file": "session-2026-08-24-the-heap-got-a-dynamo.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "deriving a rule from the existing consumer instead of writing a second one", "predicate": "prevention", "object": "CAUGHT A REINTRODUCTION OF THE PREVIOUS DAY'S BUG WITHIN MINUTES. Fixing thread-query.py's archive filter, I wrote startswith('99. archive') — which re-created the exact substring failure that hid 78 live notes on 2026-08-23. The control carried over from that day failed immediately. The fix was not a better private rule but ADOPTING vault-links.py's existing definition (ARCHIVE_DIR = '99. Archive', exact path component), so the vault has one archive rule rather than two that can drift. The banked discipline 'derive the rule from the consumer, not from the survivor' prevented a field-computed-twice defect in a different tool and a different domain.", "valid_from": "2026-08-24", "valid_to": null, "confidence": 0.95, "source_file": "session-2026-08-24-the-heap-got-a-dynamo.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "the daily note practice", "predicate": "diagnosed-as", "object": "A CONTINUOUS OBLIGATION WITH NO RECURRING CUE. Record, not impression: notes for 2026-08-19 through 08-22 do not exist; 2026-08-23 exists at 33,242 bytes across 8 commits, written incrementally as specified. The practice has produced exactly one note — on the day its convention was authored and live in working memory. daybook-ensure.py fires at SessionStart and ONLY EVER CREATES; the next cue is /wrap-up, hours later; between them there is no cue at all. The vault's own notes diagnosed the two dead predecessors correctly ('neither had a trigger') and then built the trigger for the half that never needed one. Compounding factor: competing sinks that DO have cues — the Symmetria ledger was written three times unprompted the same day, because it belongs to an active skill. SKILLS AND HOOKS FIRE; DOCUMENTS DESCRIBE. Remedy built: daybook-cue.py, PostToolUse on Write|Edit, reminder not block.", "valid_from": "2026-08-24", "valid_to": null, "confidence": 1.0, "source_file": "session-2026-08-24-the-heap-got-a-dynamo.md", "extracted_at": "2026-08-24"}
|
||||
{"subject": "/wake-up", "predicate": "reaches", "object": "0.71% of the memory corpus — 6,107 words of 859,803, always the newest, ordered by recency. Measured 2026-08-24. This is the gap thread-query.py exists to close, and the number the six-week trial is graded against.", "valid_from": "2026-08-24", "valid_to": null, "confidence": 1.0, "source_file": "session-2026-08-24-the-heap-got-a-dynamo.md", "extracted_at": "2026-08-24"}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
---
|
||||
name: Session 2026-08-24 morning — the heap got a dynamo, and the vault got the steward's own voice
|
||||
description: "Re-read Mod in full and found three contradictions of yesterday; the steward proposed the compost heap, ruled putrefaction, and glossed the dynamo as the turning; an honest measured audit found two corpora — one fed and machine-authored (860k words), one starved and the steward's — with the wake reaching 0.71%; found `09. Atlas of Roots` specified in Sept 2025 and completely empty, and harvested all 11 `user-` memory files into it as 12 notes in the steward's verbatim; built `thread-query.py` (the turning, wired into /wake-up) and `daybook-cue.py` (the daily note's missing trigger), and installed Smart Connections for a six-week trial. PULLING THREAD: the turning now exists but has never run in anger, and the open question beneath it is whether a container shaped like the WORK — Darwin's move — is what it should be turning."
|
||||
type: project
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
modified: 2026-08-24
|
||||
---
|
||||
|
||||
# Session 2026-08-24 morning — the heap got a dynamo
|
||||
|
||||
A morning about **re-encounter**, which by the end had produced two mechanisms, twelve notes in the
|
||||
steward's own voice, and a considerably less flattering picture of what we have been building.
|
||||
|
||||
## PAST — what moved, and why
|
||||
|
||||
### The Mod re-read: three contradictions, which was the point
|
||||
|
||||
Read `craigmod.com/essays/robot_blood/` in full at source (4,171 words) rather than through a
|
||||
summariser — WebFetch answers via a small model, which is a derived form.
|
||||
|
||||
1. **The passage we mined argues against what we built with it.** Mod names the value of manual
|
||||
transcription — *"it would get me to look back over the notes"* — then designs an app that
|
||||
removes exactly that step. ⚠ **The steward corrected my extension of this to his own practice
|
||||
and was right:** photographing underlined pages *is* a selective re-read. The human pass is not
|
||||
lost, it relocates into the capture act — which makes the **selection date** real evidence of
|
||||
what is live now.
|
||||
2. **A heavy vault user with our stack does not report our deficit.** Mod's stated want is
|
||||
accessibility on demand, not re-encounter. Marshall's deficit is not universal; it is a claim
|
||||
about *this* vault.
|
||||
3. **"Cheap, continuous exhumation"** undercuts appraisal — but only if archived material stays
|
||||
reachable.
|
||||
|
||||
**What we had entirely missed:** the *knowing-me slice* is the essay's actual through-line
|
||||
(*"knowing me, what are ten events I should attend?"* → *"three or four things I would have likely
|
||||
never chosen on my own"*). And the wall he wants is **ambient, not navigational**.
|
||||
|
||||
**Checked mechanically, not by impression:** over the 3,971-word body, `graph` 0 · `backlink` 0 ·
|
||||
`serendip` 0 · `resurface` 0 · `search` 0. All 6 `link` hits are hyperlinks. **The whole vocabulary
|
||||
of yesterday's conclusion is absent from an essay by a serious vault user.**
|
||||
|
||||
### Who else works this way
|
||||
|
||||
- **Matuschak** — the decisive negative result: algorithmic resurfacing failed him *because when a
|
||||
note came back he was thinking about something else.* What worked was **linking while writing**,
|
||||
since the current work supplies the context.
|
||||
- **Darwin** — portfolios keyed to the **chapters he was planning**, filled over twenty years;
|
||||
*"All useful Pages cut out Dec. 7th. /1856/"*. **The container was shaped like the work.**
|
||||
- **Warburg** — 63 panels re-pinned *"until hitherto invisible relationships revealed themselves"*.
|
||||
- **Luhmann** (a partner that must *surprise*), **Bush** (*selection by association*), **Aldrich**.
|
||||
|
||||
### The compost heap — and two of the three figures were already the steward's
|
||||
|
||||
Steward proposed **compost heap** beside crucible and dynamo; ruled **putrefaction**, not
|
||||
petrification; then glossed the third mid-turn: ***the turning of the compost is the dynamo.***
|
||||
|
||||
Checked before adding: **`crucible` is ratified architecture** (the Hearth, in the Compass Library
|
||||
organ doc) and **the compost heap was already the humic layer**, steward-verbatim 2026-04-21, built
|
||||
for authors rather than fragments. `dynamo` was zero in the live vault. **Composing instead of
|
||||
checking would have created a second name for an existing figure.**
|
||||
|
||||
The correction that matters: **dormancy is a phase, not a fault.** Petrification — intact and
|
||||
inert — now names the failure instead. Written as
|
||||
`08. Notes/The compost heap — putrefaction as a phase.md`; it also closes `Re-encounter`'s open
|
||||
question **against** a push mechanism (a heap is entered, not pushed).
|
||||
|
||||
### The audit the steward asked for, with the contamination named up front
|
||||
|
||||
| | ARC | chamber | engine | CM-AI | BMF | vault | apparatus |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| May | **150** | 9 | 5 | 15 | 4 | 23 | 3 |
|
||||
| Jun | 128 | 41 | 24 | 27 | 34 | 17 | 49 |
|
||||
| Jul | **0** | 143 | 18 | 3 | 0 | 7 | 125 |
|
||||
| Aug | 8 | 17 | 67 | 3 | 3 | 15 | **198** |
|
||||
|
||||
⚠ **My first reading of this was wrong and the steward's push-back corrected it.** 48% of August's
|
||||
`dotfiles` touches are `claude/memory` — *writing*, not machinery; vault tooling is 0.7%. The work
|
||||
did not migrate to apparatus. **It migrated to the memory layer.**
|
||||
|
||||
**Two knowledge systems.** The vault: 1,298 notes, the steward's voice, ~15/month. And
|
||||
`~/dotfiles/claude/memory/`: **506 files, 859,803 words**, fed every session — but **largely
|
||||
authored by me**. `/wake-up` reads **6,107 words — 0.71%**, always the newest.
|
||||
|
||||
**The sharpest evidence, from our own tooling: the harvest register holds 170 PROPOSED against 4
|
||||
BUILT.** It is the largest unturned heap we own. (Governance itself is healthy: 133 of 172 PENDING
|
||||
dispositioned, 123 REVIEWED entries.)
|
||||
|
||||
### The Atlas of Roots — a structure that had been waiting eleven months
|
||||
|
||||
Looking for a destination, found **`09. Atlas of Roots`**: created 2025-09-29, fully specified,
|
||||
**completely empty**. It declares eight children — `places/pine-street`, `people/moy-glidden`,
|
||||
`people/abg`, three themes — and contained none. Purpose: *"living soil for Kai, Lune, and future
|
||||
descendants."* Maxims: *"Roots codified are roots alive"* · *"ensure grief remains fertile, not
|
||||
stagnant."* **The steward's own soil metaphor, eleven months before the compost figure.**
|
||||
|
||||
**All 11 `user-` files harvested → 12 notes**, verbatim first, any reading marked as a reading:
|
||||
|
||||
- **Atlas Themes (10):** humic-layer · hearth-as-crucible · teachers-never-met · life-as-pilgrimage ·
|
||||
out-of-place-as-authority · form-true-to-itself · rules-and-the-poetic · the-long-trajectory ·
|
||||
**a-music-that-came-as-family** · **the-chamber-was-a-survival-mechanism**
|
||||
- **`08. Notes` (2):** The work answers to itself · English usage — the European register
|
||||
|
||||
The two private-register themes carry the boundary **twice** — in `assurance.risk_flags` and in a
|
||||
visible block — so it travels with the note instead of living only in my working file. **`moy-glidden`
|
||||
and `abg` deliberately unwritten; the index says so and points at the substrate.**
|
||||
|
||||
Verified: **every new note has 2–5 outbound links, none isolated.** Vault links 2,200 → 2,242, dead
|
||||
483 → 475. Remotes checked before moving private material: vault mirror → Gitea only; `dotfiles` →
|
||||
Gitea **and** `github.com/davidglidden/dotfiles`, confirmed `PRIVATE`.
|
||||
|
||||
### Two mechanisms built, both steward-authorized
|
||||
|
||||
**`~/dotfiles/scripts/thread-query.py`** — the turning. Queries both corpora with the pulling thread,
|
||||
excluding the recency slice and favouring age. Wired into `/wake-up` §2.b.3, replacing a *described*
|
||||
step ("grep the memory dir…") that fired almost never — the same described-not-invoked gap that had
|
||||
the link canary hand-typed twice. Pre-registered at
|
||||
`~/dotfiles/claude/governance/thread-query-trial.md`, graded 2026-10-05 **from `--log`, not memory**.
|
||||
|
||||
⚠ **It failed PASS-BUT-FALSELY on its first live run at 14/14 green.** Scoring on terms present
|
||||
*anywhere* put Carruthers (1.6 MB) and Yates (1 MB) top of every query. **Presence over an unbounded
|
||||
document measures length.** Fixed by scoring on co-occurrence in a ~40-line window; length-bias
|
||||
control added. A first archive fix **reintroduced yesterday's substring bug**, caught by the carried
|
||||
control, and was replaced by **adopting `vault-links.py`'s rule rather than writing a second one.**
|
||||
|
||||
**`~/dotfiles/scripts/daybook-cue.py`** — a PostToolUse hook (`Write|Edit`), 16/16 selftests,
|
||||
fail-open. Reminder, never block; quiet for 15 min after firing.
|
||||
|
||||
**Smart Connections v4.7.2** installed + enabled, trial pre-registered
|
||||
(`97. Tools and Systems/…`), graded 2026-10-05. Endpoint audit: **zero** OpenAI/Anthropic/Google/
|
||||
Cohere/OpenRouter references; embeddings local. ⚠ **The default model `bge-micro-v2` is
|
||||
English-only** and this vault is deliberately multilingual — **must be set to
|
||||
`Xenova/multilingual-e5-small` before first embed.**
|
||||
|
||||
## PRESENT — how it stands
|
||||
|
||||
**The mood.** Productive and heavily corrected, in the good direction. The steward corrected me
|
||||
three times and every correction improved the work: the book photographs, the vault's messiness,
|
||||
and the MemPalace default.
|
||||
|
||||
**Confidence to recalibrate — three of my own errors, all the same family:**
|
||||
|
||||
1. ⚠ **PASS-BUT-FALSELY on a tool I had just written and selftested.** Second day running, second
|
||||
tool. The fixture held only small uniform files, so the selftest certified its author's blind
|
||||
spot — *exactly* the vault-links.py lesson from 2026-08-23, and knowing it did not prevent it.
|
||||
**Only the live run caught it.**
|
||||
2. ⚠ **Classified four files from filenames and descriptions, not text.** Told the steward all four
|
||||
"second bite" files belonged outside the Atlas; on reading, two say *"since childhood"* and
|
||||
*"regardless of domain"* in his own words.
|
||||
3. ⚠ **Mis-corrected the steward from a current config.** He said bge was the MemPalace embed; I read
|
||||
`config.json` — the model they **switched to** — and called him half wrong. MemPalace's *default*
|
||||
is `minilm`, English-only. He was right, and pointing at the identical trap.
|
||||
|
||||
**What held.** Checking before adding to the typology (found two figures already his). Checking
|
||||
remotes before moving private material. Reading the destination's index before placing anything.
|
||||
Parsing frontmatter rather than grepping it. Re-measuring N-now rather than relaying it. Deriving
|
||||
the archive rule from the existing consumer instead of inventing a second.
|
||||
|
||||
**The daily note.** Failed for the whole session until the steward asked. **Diagnosed from the
|
||||
record, not impression:** notes for 19–22 Aug do not exist; 23 Aug exists at 33,242 bytes across 8
|
||||
commits. The practice has produced one note — on the day the convention was authored. **Missing
|
||||
mechanism, aimed one step too early:** the hook only ever *creates*, and the next cue is the wrap.
|
||||
Plus competing sinks that *do* have cues (I wrote to the ledger three times unprompted, because
|
||||
Symmetria was an active skill). **Skills and hooks fire; documents describe.** `daybook-cue.py` is
|
||||
the fix.
|
||||
|
||||
## FUTURE — what pulls
|
||||
|
||||
**The pulling thread: the turning exists now but has never run in anger — and beneath it sits the
|
||||
question of whether the thing it turns is the right container at all.** Darwin's portfolios were
|
||||
keyed to *the chapter he was writing*; ours is keyed to *the session's thread*. Those may not be the
|
||||
same move, and if they are not, the container is still missing.
|
||||
|
||||
**Actionable resumption point (as of wrap — re-judge against what changed):**
|
||||
|
||||
1. **Steward's hands, time-sensitive:** restart Obsidian and **set Smart Connections to
|
||||
`Xenova/multilingual-e5-small` BEFORE it embeds anything.** Measured cost of not doing it, from
|
||||
MemPalace's own docs: cross-lingual similarity **~0.35 instead of ~0.88.**
|
||||
2. **Watch `thread-query.py` run at the next wake** — it fires automatically now. Record honestly
|
||||
whether it surfaced anything wanted. Null results are the trial's data.
|
||||
3. **Then the real question:** does a *work-shaped container* need building, or is thread-keyed
|
||||
turning enough? See the literal question below.
|
||||
|
||||
**Other horizons, ranked.** Load-bearing: **the work-shaped container**. Then: the vault's **nested
|
||||
`99. Archives` folders** are not excluded by the vault's archive rule — deliberately left undecided,
|
||||
since changing it belongs in `vault-links.py`, not in a second private rule. Then: **petrification
|
||||
detection** (no links ∧ no edits ∧ no citation over a window). Steward's alone: **`moy-glidden` and
|
||||
`abg`**, plus the three places and three themes declared in September. **Not yet:** a fourth status
|
||||
value — do not add a field before something reads it.
|
||||
|
||||
**Pause statement.** I am about to be away from this, and we resume this afternoon. What I want to
|
||||
find still pulling is **the container question** — because we spent today building the *motion* and
|
||||
have not yet established what it should be moving through. The two trials will not report for six
|
||||
weeks; nothing today needs defending in the meantime, and the honest state is that both mechanisms
|
||||
are built, tested, and completely unproven in use.
|
||||
|
||||
**Literal question for next-Claude** *(checkable, and it turns on what the wrap files literally say):*
|
||||
|
||||
Darwin's containers were keyed to **the chapters he was writing** — durable units that outlived any
|
||||
single working session. Our turning is keyed to **the session's pulling thread**. **Read the last
|
||||
~15 session files and classify each pulling thread: does it name something that persisted across
|
||||
three or more sessions, or something that existed only for that session?** If most threads are
|
||||
session-local, then thread-keyed turning is *not* Darwin's move, and the work-shaped container is
|
||||
still missing rather than approximated. The negative answer is the useful one.
|
||||
@@ -0,0 +1,116 @@
|
||||
---
|
||||
name: Session Ledger 2026-08-24
|
||||
description: Practice-of-return ledger maintained by /symmetria — returns, open horizons, recalibrations, authorization moves, sub-agent dialogues, bypasses.
|
||||
type: feedback
|
||||
---
|
||||
|
||||
# Session Ledger — 2026-08-24
|
||||
|
||||
## Returns
|
||||
|
||||
- `2026-08-24T~wake` — **N-now re-measured, not relayed: 49/84, down from the 60 MEMORY.md carries.**
|
||||
Ran the trial's own method (`len(TRANSCRIPTS.glob("*.jsonl"))`, `governance-drift-check.py:331`)
|
||||
rather than repeating the banked figure. This is PENDING-147's rolling-window non-monotonicity
|
||||
observed live: the ladder trial has moved **further** from its grading threshold overnight, not
|
||||
closer. The banked number was not wrong when written; it is a point-in-time snapshot of a
|
||||
counter that can fall. MEMORY.md's line is now stale and should be corrected at wrap.
|
||||
|
||||
|
||||
- `2026-08-24` — **Checked the typology before adding to it, and two of the three terms already
|
||||
existed.** The steward proposed `compost heap` alongside `crucible` and `dynamo`. Rather than
|
||||
compose a third figure, grepped first: **`crucible` is ratified architecture** — the Hearth, in
|
||||
`00. Compass/…/12. Library — Attention & Meaning Ecology.md` v1.3.0, *"a zone where formal
|
||||
classification is suspended during deep engagement"* — and **the compost heap was already banked
|
||||
as the humic layer**, steward-verbatim 2026-04-21, built for authors rather than fragments.
|
||||
Composing instead of checking would have created a second name for an existing figure, in a
|
||||
system whose stated failure mode is exactly that. `dynamo` was **zero** in the live vault; left
|
||||
as an open slot rather than guessed, and the steward glossed it mid-turn — *the turning of the
|
||||
compost is the dynamo* — which dissolved a category error in the table I had already written.
|
||||
|
||||
|
||||
- `2026-08-24` — **Checked where the vault actually lands before moving private material.** The
|
||||
flamenco file carries an explicit private-register clause and the chamber-origin disclosure.
|
||||
Verified remotes first: the vault mirror pushes only to the steward's Gitea; `~/dotfiles` (where
|
||||
the memory files already live) pushes to Gitea **and** `github.com/davidglidden/dotfiles`, which
|
||||
checked `PRIVATE`. No exposure, and the harvest narrows the footprint rather than widening it.
|
||||
The check was cheap and would have been the difference had the answer gone the other way.
|
||||
|
||||
- `2026-08-24` — **Read the destination's own index before placing anything, and it changed the
|
||||
job.** `09. Atlas of Roots` was not an empty folder needing a purpose; it is a fully specified
|
||||
structure created 2025-09-29 that declares eight children — `places/pine-street`,
|
||||
`people/moy-glidden`, `people/abg`, three themes — and contains none of them. Its purpose line is
|
||||
*"living soil for Kai, Lune, and future descendants"*; its maxim is *"ensure grief remains
|
||||
fertile, not stagnant."* **The steward's own soil metaphor, eleven months before this morning's
|
||||
compost figure.** Placing the harvest anywhere else would have built a second structure beside a
|
||||
waiting one.
|
||||
|
||||
- `2026-08-24` — **The tool caught a link class my eye passed over.** Six new notes linked
|
||||
`[[Atlas of Roots — Index]]`; the file carries a `00. ` prefix, so all six resolved dead. Exactly
|
||||
yesterday's `NN. `-prefix class. Fixed with an alias on the index rather than six link edits —
|
||||
the pattern the steward established on 2026-08-23 — and re-verified: dead 483 -> 475, zero
|
||||
touching the harvest.
|
||||
|
||||
|
||||
- `2026-08-24` — **Corrected my own placement call after reading the files I had classified without
|
||||
reading.** I had told the steward that all four "second bite" files wanted a home outside the
|
||||
Atlas. On reading them, two are formation-level in their own words — *"what I have always tried to
|
||||
do regardless of domain"* (the rules/poetic duality) and *"I've been moving towards this since
|
||||
childhood"* (the long trajectory). Both went into the Atlas. **The classification had been made
|
||||
from filenames and descriptions, not from the text** — the same shape as reading a field through
|
||||
a summary instead of the substrate.
|
||||
|
||||
- `2026-08-24` — **The link-class fired a third time and was fixed at the root rather than the
|
||||
instance.** After the index alias, two more dead links appeared: the `08. Notes` pair link by
|
||||
title (`[[Form true to itself]]`) while the theme files are hyphenated. Rather than edit two
|
||||
links, added `aliases:` carrying the `title:` to **all ten** theme notes, which closes the class
|
||||
for every link anyone writes naturally in future. Verified: 0 dead touching the harvest, vault
|
||||
dead 483 -> 475, total links 2,200 -> 2,242.
|
||||
|
||||
## What held
|
||||
|
||||
- **Parsed frontmatter rather than grepping it**, for the status census (645 notes with
|
||||
frontmatter, 373 declaring no status). The flag held on its fourth day, in the exact field class
|
||||
that broke it three times on 2026-08-23.
|
||||
- **Verified the new links with `vault-links.py` (selftest 26/26) rather than by eye** — 0 dead
|
||||
entries touching either note.
|
||||
|
||||
- The wake read the substrate rather than the summary at the one place a false claim costs most.
|
||||
The digest's `deferred decisions: 3 tracked, none due` was accepted only after the counter's
|
||||
implementation was read, which is what surfaced the drop.
|
||||
|
||||
## Open horizons
|
||||
- ~~Held back: `user-formation-flamenco-substrate`~~ — **steward authorized 2026-08-24 ("it is
|
||||
crucial"); written as two themes, both marked private register in `assurance.risk_flags` and in a
|
||||
visible block, so the boundary travels with the note.**
|
||||
- **Not written, and should not be harvested:** `people/moy-glidden` and `people/abg` — the Atlas's
|
||||
declared core. Substrate exists in memory; the writing is the steward's.
|
||||
- ~~Second bite pending~~ — **authorized and done.** All 11 `user-` files harvested: 10 themes in
|
||||
the Atlas, 2 notes in `08. Notes`, every memory file back-pointed. **Still open: the Atlas's
|
||||
Places and People, which are the steward's to write.**
|
||||
- **How a heap is turned, concretely.** Darwin's answer was a container shaped like the current
|
||||
work; the vault has no counterpart. Named in the new note as the most load-bearing of its four
|
||||
open items.
|
||||
- **A fourth status value** (`composting`?) — the Frontmatter Spec anticipates one: *"a fourth
|
||||
value later is a small, named decision, not a redesign."*
|
||||
|
||||
- The literal question inherited from 2026-08-23: re-read Craig Mod's *A Swarm of Blood Robots*
|
||||
in full and find what CONTRADICTS yesterday's conclusions, not what corroborates them.
|
||||
- Rebuild the vault status from trackers + substrate, not from last night's summary (steward
|
||||
suspects it was incomplete; three same-shape instances yesterday).
|
||||
- Tooling/uses sweep.
|
||||
- Hub notes as **venues** for re-encounter — the load-bearing horizon under the pulling thread.
|
||||
|
||||
## Confidence to recalibrate
|
||||
|
||||
- Inherited, twice-earned: **the check is skipped precisely where confidence is highest.**
|
||||
- ⚠ **A quick grep is not a parser** — fired three times on 2026-08-23 on the same field class,
|
||||
the third time *after* it had been named at midday. Knowing the pattern did not prevent it.
|
||||
Today's Mod re-read is a reading task, but the vault-status rebuild is exactly the shape that
|
||||
invites it. Parse; do not grep-and-report.
|
||||
- ⚠ **A substring is not a path** — `99. Archive` silently excluded 78 live notes. Live is 1,298.
|
||||
|
||||
## Authorization moves
|
||||
|
||||
## Sub-agent dialogues
|
||||
|
||||
## Bypasses
|
||||
@@ -19,4 +19,15 @@ permalink: claude-memory/user-care-over-traffic-skills-as-accountability
|
||||
- Cousin to the **Non-Convergence Principle** in `~/CLAUDE.md`: *"the system should be inhabitable, dignified, and sufficient at any point along the way"*; no step depending on a future step to be meaningful.
|
||||
- Cousin to **"Would Alexander do it?"** feedback (2026-04-27): each pattern at a time, not bulk-scaffold; the cramped will of the maker is the failure mode.
|
||||
- The audience-building diagnosis from the jurist (find the right 50 people; address RSS / email-capture gaps) sits *next to* this principle — practical, not prerequisite. The work answers to itself first; audience-building is a separate concern.
|
||||
- When time pressure surfaces (e.g., 2026-04-28 jurist's "publish today"), don't compromise care for speed; the publish-today imperative still operates within the care-frame, not against it.
|
||||
- When time pressure surfaces (e.g., 2026-04-28 jurist's "publish today"), don't compromise care for speed; the publish-today imperative still operates within the care-frame, not against it.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`08. Notes/The work answers to itself.md`** ("The work answers to itself"), where they can be come
|
||||
upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is not
|
||||
a second copy of the claim. If the two ever disagree about what the steward said, the vault note
|
||||
governs and this one is corrected.
|
||||
|
||||
@@ -42,4 +42,15 @@ The style-guide session, when it happens, will therefore not be *just* a prose-t
|
||||
|
||||
- [Formation practice — reverence to deep teachers](user-formation-practice-honoring-teachers.md) — the mutual-service frame extends the reverence posture to skills/agents.
|
||||
- [Session 2026-04-23 evening — Norris *Between You & Me* read](session-2026-04-23-evening-norris-read.md) — the read that occasioned the articulation; surfaces preserved; gather deferred.
|
||||
- Norris's apostrophe-as-prayer etymology is the most concentrated single instance of this duality surfaced so far: the grammatical mark and the rhetorical device share a root in *addressing the absent*. Mechanism and metaphor not two things but one.
|
||||
- Norris's apostrophe-as-prayer etymology is the most concentrated single instance of this duality surfaced so far: the grammatical mark and the rhetorical device share a root in *addressing the absent*. Mechanism and metaphor not two things but one.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/rules-and-the-poetic.md`** ("Rules and the poetic"), where they can be come
|
||||
upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is not
|
||||
a second copy of the claim. If the two ever disagree about what the steward said, the vault note
|
||||
governs and this one is corrected.
|
||||
|
||||
@@ -19,4 +19,15 @@ Stated 2026-05-06 in context of Sources/bibliography spec decision: *"I have the
|
||||
|
||||
**Concrete first instance**: Sources/bibliography repetition convention (2026-05-06) — chose Bringhurst's three-em rule (`———`) following Harrison's *Dominion of the Dead*, against Chicago/MLA name-repeat practice. This was the substantive ground for the decision after typographer chavruta surfaced the divergence.
|
||||
|
||||
**Cross-reference**: ARC's voice gathering already weights European voices heavily (the §0 colophon-of-ARC frame, Vico/Leopardi/Harrison/Bachelard substrate). The European-English usage preference is consistent with this.
|
||||
**Cross-reference**: ARC's voice gathering already weights European voices heavily (the §0 colophon-of-ARC frame, Vico/Leopardi/Harrison/Bachelard substrate). The European-English usage preference is consistent with this.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`08. Notes/English usage — the European register.md`** ("English usage — the European register"), where they can be come
|
||||
upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is not
|
||||
a second copy of the claim. If the two ever disagree about what the steward said, the vault note
|
||||
governs and this one is corrected.
|
||||
|
||||
@@ -91,4 +91,15 @@ The stakes (verbatim, load-bearing):
|
||||
- `user-formation-out-of-place-as-authority.md` — the *meandering* connects to the formation-out-of-place authority. Now we know the meander had a specific historical shape: multi-cultural flamenco childhood → return-as-homecoming.
|
||||
- `user-life-as-pilgrimage.md` — the long-held pilgrim framing. Pilgrimage / meandering / homecoming are three views of the same life-shape: on a road, with a destination quietly present.
|
||||
- `user-hearth-meaning-laral-substrate.md` — the laral substrate from which the steward is made. The flamenco family of origin and ABG/Moy are both laral; the bio's *household of voices acknowledged in the Hearth* holds them collectively.
|
||||
- `project-bio-rewrite-pending-multilanguage-spec.md` — the ARC bio rewrite that this disclosure shaped.
|
||||
- `project-bio-rewrite-pending-multilanguage-spec.md` — the ARC bio rewrite that this disclosure shaped.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/a-music-that-came-as-family.md` and `…/the-chamber-was-a-survival-mechanism.md`** ("A music that came as family / The chamber was a survival mechanism"), where they can be come
|
||||
upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is not
|
||||
a second copy of the claim. If the two ever disagree about what the steward said, the vault note
|
||||
governs and this one is corrected.
|
||||
|
||||
@@ -22,4 +22,15 @@ permalink: claude-memory/user-formation-out-of-place-as-authority
|
||||
- When the steward expresses doubt about reach or recognition, do not solutionize prematurely; the no-obvious-institutional-home is real and shapes the work's authority
|
||||
- Do not treat *"in the wrong place"* as a problem requiring correction; the authentic stance the writing comes from depends on it
|
||||
- The work bridges intersections (HIP musicianship + philosophical writing + AI ethics + systems design) — when these surface, recognize the cross-domain nature as core
|
||||
- Steward shared this with executor in trust, framed as *"you need to be able to trust me and understand my behaviour and I owe it to you to explain myself"* — relational gesture, not data dump. Receive accordingly.
|
||||
- Steward shared this with executor in trust, framed as *"you need to be able to trust me and understand my behaviour and I owe it to you to explain myself"* — relational gesture, not data dump. Receive accordingly.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/out-of-place-as-authority.md`**
|
||||
("Out of place as authority"), where they can be come upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is
|
||||
not a second copy of the claim. If the two ever disagree about what the steward said, the vault
|
||||
note governs and this one is corrected.
|
||||
|
||||
@@ -44,4 +44,15 @@ Steward verbatim (2026-04-23):
|
||||
## Related memory
|
||||
|
||||
- `project-arc-rework.md` §"2026-04-23 addition (steward, walking with Kai)" — the values-embodied/travail-bien-fait posture that this formation-practice grounds.
|
||||
- The ARC typology spec's §1 "On humic references" preamble (added 2026-04-23) acknowledges Harrison as vocabulary source; the personal-teachership framing of this memory file is the deeper context behind that preamble note.
|
||||
- The ARC typology spec's §1 "On humic references" preamble (added 2026-04-23) acknowledges Harrison as vocabulary source; the personal-teachership framing of this memory file is the deeper context behind that preamble note.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/teachers-never-met.md`**
|
||||
("Teachers never met"), where they can be come upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is
|
||||
not a second copy of the claim. If the two ever disagree about what the steward said, the vault
|
||||
note governs and this one is corrected.
|
||||
|
||||
@@ -21,4 +21,15 @@ The specific load-bearing observation: the formative quality is **form-content u
|
||||
- Adjacent vocabulary the steward operates in: *the quality without a name*, *the gate*, *dwelling*, *centers*, *structure-preserving transformations*, *the fifteen fundamental properties* (from *Nature of Order*). ARC's *Hearth* / *threshold-hic* / *Adsum* / cluster-rooms decisions sit in this vocabulary's neighborhood whether or not Alexander is named in the prose.
|
||||
- The Reading Compass essay (`navigation-philosophy.md`) already cites Alexander twice: *"Alexander writes of building elements that feel inevitable rather than imposed"* and *"the quality without a name."* This is part of the substrate.
|
||||
|
||||
Cousin to `user-formation-practice-honoring-teachers.md` (steward considers formative authors his teachers); this is a specific high-formation case where the teacher's *form* is itself the testing instrument.
|
||||
Cousin to `user-formation-practice-honoring-teachers.md` (steward considers formative authors his teachers); this is a specific high-formation case where the teacher's *form* is itself the testing instrument.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/form-true-to-itself.md`**
|
||||
("Form true to itself"), where they can be come upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is
|
||||
not a second copy of the claim. If the two ever disagree about what the steward said, the vault
|
||||
note governs and this one is corrected.
|
||||
|
||||
@@ -58,4 +58,15 @@ The architectural work (ARC, L2, Chamber) is done within a period of transition
|
||||
- `feedback-arc-typology-recognition-scaffold.md` — operationalizes the recognition-over-generation frame for ARC specifically
|
||||
- `user-influences-humic-layer.md` — names ABG and Moy as primary cultivators; all other influences as humic nutriment
|
||||
- `feedback-children-not-named-online.md` — the standing rule for Kai and Lune; part of the privacy-of-intimates discipline
|
||||
- `~/CLAUDE.md` — the three-party model is structurally the collaboration-shape this memory describes in operation
|
||||
- `~/CLAUDE.md` — the three-party model is structurally the collaboration-shape this memory describes in operation
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/the-long-trajectory.md`** ("The long trajectory"), where they can be come
|
||||
upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is not
|
||||
a second copy of the claim. If the two ever disagree about what the steward said, the vault note
|
||||
governs and this one is corrected.
|
||||
|
||||
@@ -28,4 +28,15 @@ In the same opening, steward extended this into Alexander territory:
|
||||
|
||||
The Hearth and Alexander's pattern method rhyme at the level of stance: both find what is always-already-there in living form; both receive rather than assert. Worth holding; bears on but doesn't necessarily reverse the 2025-12-01 *adjacent-not-inside* placement decision (see project-hearth-composition-substrate).
|
||||
|
||||
**How to apply:** when working on the Hearth, treat the lares as *functions* not influences (Harrison's distinction). Steward is composing a description of his own constitutive substrate, not a list of teachers. Reverence is not decoration; it is registry of what is structurally true. Sibling to user-formation-practice-honoring-teachers (the formative-as-teacher reading) and user-formative-teachers-alexander-timeless-way (form-content unity as standard).
|
||||
**How to apply:** when working on the Hearth, treat the lares as *functions* not influences (Harrison's distinction). Steward is composing a description of his own constitutive substrate, not a list of teachers. Reverence is not decoration; it is registry of what is structurally true. Sibling to user-formation-practice-honoring-teachers (the formative-as-teacher reading) and user-formative-teachers-alexander-timeless-way (form-content unity as standard).
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/hearth-as-crucible.md`**
|
||||
("Hearth as crucible"), where they can be come upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is
|
||||
not a second copy of the claim. If the two ever disagree about what the steward said, the vault
|
||||
note governs and this one is corrected.
|
||||
|
||||
@@ -101,4 +101,15 @@ Steward verbatim 2026-04-22 on the urgency of the Style Guide: *"my sense of urg
|
||||
## Relation to other memory
|
||||
|
||||
- **Children-not-named-online rule** (`feedback-children-not-named-online.md`) is the operative rule for Kai and Lune. ABG and Moy appear in private / reflective contexts; the children do not appear publicly. Two different disciplines for two different generational positions.
|
||||
- **ARC typology recognition scaffold** (`feedback-arc-typology-recognition-scaffold.md`) is the ARC-specific application of this broader posture.
|
||||
- **ARC typology recognition scaffold** (`feedback-arc-typology-recognition-scaffold.md`) is the ARC-specific application of this broader posture.
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/humic-layer.md`**
|
||||
("Humic layer"), where they can be come upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is
|
||||
not a second copy of the claim. If the two ever disagree about what the steward said, the vault
|
||||
note governs and this one is corrected.
|
||||
|
||||
@@ -25,4 +25,15 @@ The Adsum link on *David Glidden* delivers the visitor from the threshold's *her
|
||||
- Way (the way of living, the practice across life)
|
||||
- The non-arrival principle (Non-Convergence Principle in `~/CLAUDE.md`: *"the system should be inhabitable, dignified, and sufficient at any point along the way"*)
|
||||
|
||||
Sibling memories: `user-formation-out-of-place-as-authority.md` (the out-of-place register is the authority-register; pilgrim and out-of-place rhyme — both name the structural condition of being on a road rather than at home).
|
||||
Sibling memories: `user-formation-out-of-place-as-authority.md` (the out-of-place register is the authority-register; pilgrim and out-of-place rhyme — both name the structural condition of being on a road rather than at home).
|
||||
|
||||
---
|
||||
|
||||
## HARVESTED TO THE VAULT — 2026-08-24
|
||||
|
||||
The steward's verbatim and the thinking now live in **`09. Atlas of Roots/Themes/life-as-pilgrimage.md`**
|
||||
("Life as pilgrimage"), where they can be come upon. **The vault note is canonical for the idea.**
|
||||
|
||||
This file keeps its own job — firing the rule at the moment it applies during a session — and is
|
||||
not a second copy of the claim. If the two ever disagree about what the steward said, the vault
|
||||
note governs and this one is corrected.
|
||||
|
||||
@@ -77,7 +77,28 @@ The durable memory *is* the Markdown + JSONL files (git-tracked, dual-remote). T
|
||||
**And one `prevention` alongside them** — `grep 'prevention' …/knowledge-graph.jsonl`. Surface **one line each way**. Grepping only `drift-pattern` opens every session by re-reading what went wrong and never what compounded; a prevention records a lesson from one failure class stopping a different one. One of each, not a tally. <!-- 2026-08-02: FIX lane, REVIEWED-85 first batch; proposed 2026-07-29 (steward-raised). -->
|
||||
|
||||
|
||||
**b.3. Depth on the thread — grep, don't query.** When the session files don't carry enough, grep the memory dir + the CapableMind thinking docs + the Obsidian vault directly for the thread's keywords. The files are authoritative; there is no catalogue in front of them.
|
||||
**b.3. THE TURNING — run `thread-query.py` on the thread. Do not hand-grep this.** Once §2.a has given you the pulling thread, run it:
|
||||
|
||||
```
|
||||
python3 ~/dotfiles/scripts/thread-query.py "<the pulling thread, in words>" --log
|
||||
```
|
||||
|
||||
It queries the memory corpus **and** the vault with the thread you are actually on, deliberately **excluding the recency slice this wake already loads** and deliberately **favouring older material** — surfacing what recency will not is its entire job. It returns pointers and the literal matching lines, never summaries. Prove it before trusting a clean run: `--selftest` (14 checks, positive and negative controls, plus the path-component control earned 2026-08-23).
|
||||
|
||||
**Surface at most TWO in the briefing, and only if they genuinely bear on the thread.** Quote the pointer and its date; do not summarise the note — open it if it matters. **If nothing comes back, say so in one clause.** A null result is a real result and the trial needs it recorded.
|
||||
|
||||
⚠ **Pre-registered trial, grade 2026-10-05** (`~/dotfiles/claude/governance/thread-query-trial.md`). `--log` appends one line per run to `thread-query-log.jsonl` so the verdict is graded from a machine record rather than from anyone's memory of whether it helped. **Falsifier: if across the trial it never surfaces something the steward would have wanted and would not otherwise have found, this step comes out.** A step that can only conclude "keep it" is not a trial.
|
||||
|
||||
*(When the query returns nothing and the thread still needs depth, grep the memory dir + the CapableMind thinking docs + the vault directly. The files are authoritative; there is no catalogue in front of them.)*
|
||||
|
||||
<!-- 2026-08-24, steward-authorized. Earned twice the same day: a hand-grep found the Hearth
|
||||
definition in a December Compass document and another found the humic layer from April, and both
|
||||
were the best findings of the session. The measurement that motivated it: /wake-up reads 6,107
|
||||
words of an 859,803-word memory corpus — 0.71% — always the newest. This step was previously
|
||||
DESCRIBED here ("grep the memory dir...") and fired almost never; that is the same
|
||||
described-not-invoked gap that had the link canary retyped by hand twice before it was pointed at
|
||||
an executable. Motion supplied by the current work, not by the calendar: Matuschak's report is that
|
||||
resurfacing on a schedule fails because you are thinking about something else when it arrives. -->
|
||||
|
||||
*(The typography palace — a separate MemPalace instance queried via CLI for ARC type work — is KEPT, unaffected by the wind-down; reach for it only when the thread is ARC typography.)*
|
||||
|
||||
@@ -113,6 +134,8 @@ Then combine all sources into a single reconstruction. Use this structure but wr
|
||||
|
||||
**The question we left ourselves** — second. Surface it verbatim from the previous /wrap-up. Hold it open. Do not try to answer it.
|
||||
|
||||
**From the heap** — after the thread, at most two pointers from `thread-query.py` (§2.b.3), with dates, or one clause saying nothing came back. Pointers, never summaries.
|
||||
|
||||
**What changed while we were away** — third. New commits we didn't author, new REVIEWED decisions, anything that moved. Only include if something actually changed. Frame against the thread: does the change serve it, threaten it, or sit beside it?
|
||||
|
||||
**What's unresolved** — fourth. Open horizons from the previous wrap, ranked by load-bearing weight. PENDING items awaiting steward attention. Be specific: *"L1 amendment for ProjectionChain drafted in concept only, not yet written; reshapes given multi-mode retention frame from #145"* not *"L1 amendments pending."* Surface, too, any **skill-harvest proposals** the last wrap raised (§1.6) that the steward did not yet authorize — so improvements to our own tools don't evaporate across the pause.
|
||||
|
||||
Executable
+169
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python3
|
||||
"""daybook-cue.py — PostToolUse cue (Write|Edit): the daily note has no trigger.
|
||||
|
||||
Diagnosed 2026-08-24 from the record, not from impression. Daily notes for 19-22
|
||||
August do not exist; 2026-08-23 exists at 33,242 bytes across eight commits — written
|
||||
incrementally, as the convention specifies. So the practice has produced exactly one
|
||||
note, on the day the convention was authored and live in working memory.
|
||||
|
||||
The failure is structural. `daybook-ensure.py` fires at SessionStart and ONLY EVER
|
||||
CREATES. The next cue is /wrap-up §7.5, hours later. Between them — the entire working
|
||||
session, which is exactly when the convention says to write — there is no cue at all.
|
||||
The vault's own notes diagnosed the two dead predecessors correctly ("neither had a
|
||||
trigger. The hook is the trigger") and then built the trigger for the half that never
|
||||
needed one. Whether the file exists was never the failure mode.
|
||||
|
||||
The convention's own trigger word is "as it lands", and work lands when a file is
|
||||
written. So this fires there.
|
||||
|
||||
REMINDER, NOT BLOCK — unlike verify-before-compose, whose failure is unrecoverable.
|
||||
This one's is recoverable, and a gate that interrupts every write would be removed
|
||||
within a day. Fail-open everywhere: any unexpected condition exits 0.
|
||||
"""
|
||||
import datetime, json, os, sys, time
|
||||
|
||||
HOME = os.path.expanduser("~")
|
||||
VAULT = os.path.join(HOME, "Library/Mobile Documents/iCloud~md~obsidian/Documents",
|
||||
"David, root-and-branch")
|
||||
DAILY_DIR = os.path.join(VAULT, "01. Daily")
|
||||
STAMP = os.path.join(HOME, ".claude/state/daybook-cue.stamp")
|
||||
|
||||
SKELETON_CEILING = 1200 # the generated skeleton is ~558 bytes
|
||||
QUIET_SECONDS = 900 # cue at most once per 15 minutes; a nag gets disabled
|
||||
|
||||
# Writes that are not "work landing".
|
||||
IGNORED_FRAGMENTS = ("/scratchpad/", "/private/tmp/", "/tmp/", "/.git/",
|
||||
"/node_modules/", "/.obsidian/")
|
||||
IGNORED_SUFFIXES = (".bak", ".stamp", ".lock", ".log", ".jsonl", ".pyc")
|
||||
|
||||
|
||||
def is_substantive(path):
|
||||
if not path:
|
||||
return False
|
||||
if any(f in path for f in IGNORED_FRAGMENTS):
|
||||
return False
|
||||
if path.endswith(IGNORED_SUFFIXES):
|
||||
return False
|
||||
# writing the daily note itself is the thing being asked for, not a trigger for it
|
||||
if os.path.normpath(DAILY_DIR) in os.path.normpath(path):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def note_path(today=None):
|
||||
d = today or datetime.date.today()
|
||||
return os.path.join(DAILY_DIR, f"{d.isoformat()}.md")
|
||||
|
||||
|
||||
def should_cue(path, note_size, note_exists, seconds_since_last, today=None):
|
||||
"""Pure decision, so it can be tested without a filesystem or a clock."""
|
||||
if not is_substantive(path):
|
||||
return False
|
||||
if not note_exists: # daybook-ensure owns creation, not us
|
||||
return False
|
||||
if note_size >= SKELETON_CEILING: # it is being written; say nothing
|
||||
return False
|
||||
if seconds_since_last < QUIET_SECONDS:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
MESSAGE = """DAILY NOTE — still a skeleton, and work is landing elsewhere.
|
||||
|
||||
The convention is FILL IT AS THE WORK HAPPENS, not at the wrap:
|
||||
01. Daily/{date}.md (currently {size} bytes)
|
||||
|
||||
Give what just landed its own `##` heading now — plain language, for the steward on a
|
||||
day he wants to know what happened without reading git log. /wrap-up §7.5 finalises;
|
||||
it never begins the file, and a skeleton at wrap is a failure that step exists to catch.
|
||||
|
||||
(Cue at most once per 15 min. Reminder, not a block — the write already succeeded.)"""
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
raw = sys.stdin.read()
|
||||
data = json.loads(raw) if raw.strip() else {}
|
||||
except Exception:
|
||||
sys.exit(0)
|
||||
|
||||
path = (data.get("tool_input") or {}).get("file_path") or ""
|
||||
np = note_path()
|
||||
try:
|
||||
exists = os.path.exists(np)
|
||||
size = os.path.getsize(np) if exists else 0
|
||||
except OSError:
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
last = os.path.getmtime(STAMP) if os.path.exists(STAMP) else 0
|
||||
except OSError:
|
||||
last = 0
|
||||
since = time.time() - last
|
||||
|
||||
if not should_cue(path, size, exists, since):
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
os.makedirs(os.path.dirname(STAMP), exist_ok=True)
|
||||
open(STAMP, "w").write(str(time.time()))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
print(MESSAGE.format(date=datetime.date.today().isoformat(), size=size), file=sys.stderr)
|
||||
sys.exit(2) # PostToolUse: tool already ran; stderr is surfaced as feedback
|
||||
|
||||
|
||||
def selftest():
|
||||
ok = fail = 0
|
||||
|
||||
def check(name, cond):
|
||||
nonlocal ok, fail
|
||||
if cond:
|
||||
ok += 1; print(f" PASS {name}")
|
||||
else:
|
||||
fail += 1; print(f" FAIL {name}")
|
||||
|
||||
vault_md = os.path.join(VAULT, "08. Notes/Something.md")
|
||||
daily_md = os.path.join(DAILY_DIR, "2026-08-24.md")
|
||||
|
||||
# positive control — it fires when it should
|
||||
check("cues on a real vault write while the note is a skeleton",
|
||||
should_cue(vault_md, 558, True, 9999) is True)
|
||||
check("cues on a repo write too",
|
||||
should_cue(os.path.join(HOME, "_Dev/x/y.py"), 558, True, 9999) is True)
|
||||
|
||||
# negative controls — each suppression works in isolation
|
||||
check("silent once the note is being written", should_cue(vault_md, 5000, True, 9999) is False)
|
||||
check("silent when the note does not exist", should_cue(vault_md, 0, False, 9999) is False)
|
||||
check("silent inside the quiet window", should_cue(vault_md, 558, True, 10) is False)
|
||||
check("silent on the daily note itself", should_cue(daily_md, 558, True, 9999) is False)
|
||||
check("silent on scratchpad", should_cue("/private/tmp/claude-501/x/scratchpad/a.md", 558, True, 9999) is False)
|
||||
check("silent on /tmp", should_cue("/tmp/a.md", 558, True, 9999) is False)
|
||||
check("silent on .obsidian config", should_cue(os.path.join(VAULT, ".obsidian/x.json"), 558, True, 9999) is False)
|
||||
check("silent on backups", should_cue(vault_md + ".bak", 558, True, 9999) is False)
|
||||
check("silent on jsonl logs", should_cue(os.path.join(HOME, "a/b.jsonl"), 558, True, 9999) is False)
|
||||
check("silent on empty path", should_cue("", 558, True, 9999) is False)
|
||||
|
||||
# boundary
|
||||
check("threshold is exclusive at the ceiling",
|
||||
should_cue(vault_md, SKELETON_CEILING, True, 9999) is False)
|
||||
check("just under the ceiling still cues",
|
||||
should_cue(vault_md, SKELETON_CEILING - 1, True, 9999) is True)
|
||||
|
||||
# fail-open on malformed input
|
||||
import subprocess
|
||||
r = subprocess.run([sys.executable, __file__], input="not json",
|
||||
capture_output=True, text=True)
|
||||
check("fail-open on malformed stdin", r.returncode == 0)
|
||||
r = subprocess.run([sys.executable, __file__], input="", capture_output=True, text=True)
|
||||
check("fail-open on empty stdin", r.returncode == 0)
|
||||
|
||||
print(f"\nSELFTEST {'PASS' if not fail else 'FAIL'} — {ok} ok, {fail} failed")
|
||||
return 0 if not fail else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "--selftest" in sys.argv:
|
||||
sys.exit(selftest())
|
||||
main()
|
||||
Executable
+364
@@ -0,0 +1,364 @@
|
||||
#!/usr/bin/env python3
|
||||
"""thread-query.py — the dynamo.
|
||||
|
||||
Query the corpora with the question you have NOW, rather than with the calendar.
|
||||
|
||||
/wake-up already reads a recency slice: MEMORY.md, the newest session files, the
|
||||
trackers. Measured 2026-08-24 that is 6,107 words of an 859,803-word memory corpus
|
||||
— 0.71%. Everything else is dark unless someone goes looking. Twice on 2026-08-24
|
||||
someone did, by hand, and both greps produced the day's best findings: the Hearth
|
||||
definition from a December Compass document, and the humic layer from April.
|
||||
|
||||
This turns that hand-motion into an instrument. It deliberately EXCLUDES the slice
|
||||
the wake already loads and deliberately FAVOURS age, because its whole job is to
|
||||
surface what recency will not.
|
||||
|
||||
Returns pointers — path, date, and the literal matching lines. Never summaries: a
|
||||
summary of the steward's thinking, written by the executor, is the thing the vault
|
||||
harvest of 2026-08-24 existed to get away from.
|
||||
"""
|
||||
import argparse, datetime, glob, json, math, os, re, sys, tempfile, shutil
|
||||
|
||||
HOME = os.path.expanduser("~")
|
||||
MEM = os.path.join(HOME, ".claude/projects/-Users-davidglidden/memory")
|
||||
VAULT = os.path.join(HOME, "Library/Mobile Documents/iCloud~md~obsidian/Documents",
|
||||
"David, root-and-branch")
|
||||
|
||||
# Path COMPONENTS, never substrings. Earned 2026-08-23: the filter "99. Archive"
|
||||
# is a prefix of "99. Archives—Previous Iterations" and silently swallowed 78 live
|
||||
# notes from every figure of that day.
|
||||
VAULT_EXCLUDED_COMPONENTS = {".obsidian", ".trash", "99. chatgpt-conversations",
|
||||
"thinking-mirror"} # spec §1a: a derived tree; cite the original
|
||||
|
||||
|
||||
def is_archive_component(name):
|
||||
"""The vault's archive rule, ADOPTED not reinvented.
|
||||
|
||||
`vault-links.py:152` defines it: ARCHIVE_DIR = "99. Archive", matched as an exact
|
||||
path COMPONENT at any depth. That definition was itself earned on 2026-08-23, when a
|
||||
substring test also swallowed `99. Archives—Previous Iterations` and hid 78 live
|
||||
notes from every figure of the day.
|
||||
|
||||
A first attempt here used startswith("99. archive"), which reintroduced exactly that
|
||||
bug — caught by the control carried over from that day. Deriving a second, divergent
|
||||
archive rule in a second script is the field-computed-twice failure; if the rule
|
||||
should change, it changes in vault-links.py and both consumers follow.
|
||||
|
||||
OPEN, deliberately not decided here: nested folders literally named `99. Archives`
|
||||
(e.g. `06. Projects/Pattern, Presence, Practice/99. Archives/`) are NOT excluded by
|
||||
the vault's rule, so they are not excluded here either. Whether they should be is a
|
||||
question about the vault's archive definition, not about this tool.
|
||||
"""
|
||||
return name == "99. Archive"
|
||||
|
||||
|
||||
STOPWORDS = set("""a an and are as at be been but by can could did do does for from had has have
|
||||
he her his how i if in into is it its me my no not of on or our out över she so some such than
|
||||
that the their them then there these they this those to too under until up very was we were what
|
||||
when where which while who why will with would you your about after again all also am any because
|
||||
before being between both during each few more most other over same still just now new one two
|
||||
three thing things something anything nothing make makes made get gets got go goes going""".split())
|
||||
|
||||
|
||||
def terms_from(text):
|
||||
"""Content terms: lowercase, >=4 chars, not a stopword, deduped, order kept."""
|
||||
seen, out = set(), []
|
||||
for w in re.findall(r"[A-Za-z][A-Za-z'-]+", text.lower()):
|
||||
w = w.strip("'-")
|
||||
if len(w) < 4 or w in STOPWORDS or w in seen:
|
||||
continue
|
||||
seen.add(w)
|
||||
out.append(w)
|
||||
return out
|
||||
|
||||
|
||||
def file_date(path, text=None):
|
||||
"""Prefer a date in the filename, then frontmatter created:, then mtime."""
|
||||
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", os.path.basename(path))
|
||||
if m:
|
||||
try:
|
||||
return datetime.date(*map(int, m.groups()))
|
||||
except ValueError:
|
||||
pass
|
||||
if text:
|
||||
m = re.search(r"^(?:created|date):\s*[\"']?(\d{4})-(\d{2})-(\d{2})", text[:2000], re.M)
|
||||
if m:
|
||||
try:
|
||||
return datetime.date(*map(int, m.groups()))
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return datetime.date.fromtimestamp(os.path.getmtime(path))
|
||||
except OSError:
|
||||
return datetime.date.today()
|
||||
|
||||
|
||||
def recency_slice(mem_dir, keep=3):
|
||||
"""Exactly what /wake-up already loads. Excluded so we never hand back the slice."""
|
||||
out = set()
|
||||
for n in ("MEMORY.md", "MEMORY-reference.md"):
|
||||
out.add(os.path.join(mem_dir, n))
|
||||
sessions = sorted(glob.glob(os.path.join(mem_dir, "session-2*.md")),
|
||||
key=lambda p: os.path.basename(p), reverse=True)
|
||||
for p in sessions[:keep]:
|
||||
out.add(p)
|
||||
today = datetime.date.today().isoformat()
|
||||
for p in glob.glob(os.path.join(mem_dir, f"*{today}*.md")):
|
||||
out.add(p)
|
||||
return out
|
||||
|
||||
|
||||
def collect(mem_dir, vault_dir, keep=3):
|
||||
"""(path, text) for every candidate file, recency slice and archive removed."""
|
||||
skip = recency_slice(mem_dir, keep)
|
||||
files = []
|
||||
if os.path.isdir(mem_dir):
|
||||
for p in glob.glob(os.path.join(mem_dir, "*.md")):
|
||||
if os.path.realpath(p) not in {os.path.realpath(s) for s in skip}:
|
||||
files.append(p)
|
||||
if os.path.isdir(vault_dir):
|
||||
for root, dirs, names in os.walk(vault_dir):
|
||||
dirs[:] = [d for d in dirs
|
||||
if d not in VAULT_EXCLUDED_COMPONENTS
|
||||
and not is_archive_component(d) and not d.startswith(".")]
|
||||
for n in names:
|
||||
if n.endswith(".md"):
|
||||
files.append(os.path.join(root, n))
|
||||
out = []
|
||||
for p in files:
|
||||
try:
|
||||
out.append((p, open(p, encoding="utf-8", errors="replace").read()))
|
||||
except OSError:
|
||||
continue
|
||||
return out
|
||||
|
||||
|
||||
def best_window(text, qterms, window=40):
|
||||
"""Distinct query terms co-occurring inside the best ~40-line window.
|
||||
|
||||
⚠ EARNED 2026-08-24, live run. Scoring on distinct terms present ANYWHERE in a
|
||||
document made Carruthers' *Book of Memory* (1.6 MB) and Yates' *Art of Memory*
|
||||
(1 MB) the top two hits for every query — a million-word book contains
|
||||
"instruments", "turning" and "heap" somewhere by accident. Presence over an
|
||||
unbounded document measures LENGTH, not relevance. The selftest was 14/14 green
|
||||
at the time, because the fixture held only small uniform files: the same
|
||||
PASS-BUT-FALSELY shape vault-links.py hit the day before.
|
||||
|
||||
Requiring co-occurrence in a window is what makes a match a match, and it is
|
||||
also what makes the excerpt worth reading.
|
||||
"""
|
||||
lines = text.lower().splitlines()
|
||||
if not lines:
|
||||
return 0, 0
|
||||
best, best_at = 0, 0
|
||||
for start in range(0, max(1, len(lines)), max(1, window // 2)):
|
||||
chunk = "\n".join(lines[start:start + window])
|
||||
n = sum(1 for q in qterms if re.search(r"\b" + re.escape(q), chunk))
|
||||
if n > best:
|
||||
best, best_at = n, start
|
||||
return best, best_at
|
||||
|
||||
|
||||
def score(text, path, qterms, today=None):
|
||||
"""Co-occurring terms in the tightest window, weighted by age."""
|
||||
n, at = best_window(text, qterms)
|
||||
if n < 2: # one term is noise; scattered terms are length
|
||||
return 0.0, [], None
|
||||
low = text.lower()
|
||||
matched = [q for q in qterms if re.search(r"\b" + re.escape(q), low)]
|
||||
d = file_date(path, text)
|
||||
age_days = max(0, ((today or datetime.date.today()) - d).days)
|
||||
# Age is a deliberate thumb on the scale: recency is what the wake already has.
|
||||
weight = 1.0 + math.log1p(age_days / 30.0)
|
||||
return n * weight, matched, d
|
||||
|
||||
|
||||
def excerpts(text, matched, limit=2, qterms=None):
|
||||
lines, out = text.splitlines(), []
|
||||
if qterms:
|
||||
_, at = best_window(text, qterms)
|
||||
lines = lines[at:at + 40]
|
||||
for ln in lines:
|
||||
s = ln.strip()
|
||||
if len(s) < 20 or s.startswith(("---", "#", "|", "```")):
|
||||
continue
|
||||
if sum(1 for t in matched if t in s.lower()) >= 2:
|
||||
out.append(re.sub(r"\s+", " ", s)[:200])
|
||||
if len(out) >= limit:
|
||||
break
|
||||
return out
|
||||
|
||||
|
||||
def run(thread, mem_dir=MEM, vault_dir=VAULT, top=5, keep=3, today=None):
|
||||
qterms = terms_from(thread)
|
||||
rows = []
|
||||
for path, text in collect(mem_dir, vault_dir, keep):
|
||||
sc, matched, d = score(text, path, qterms, today)
|
||||
if sc > 0:
|
||||
rows.append({"path": path, "score": round(sc, 2), "date": d.isoformat(),
|
||||
"matched": matched, "excerpts": excerpts(text, matched, qterms=qterms)})
|
||||
rows.sort(key=lambda r: -r["score"])
|
||||
return {"thread_terms": qterms, "candidates": len(rows), "results": rows[:top]}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- tests
|
||||
def selftest():
|
||||
ok = fail = 0
|
||||
|
||||
def check(name, cond):
|
||||
nonlocal ok, fail
|
||||
if cond:
|
||||
ok += 1
|
||||
print(f" PASS {name}")
|
||||
else:
|
||||
fail += 1
|
||||
print(f" FAIL {name}")
|
||||
|
||||
d = tempfile.mkdtemp()
|
||||
mem, vault = os.path.join(d, "mem"), os.path.join(d, "vault")
|
||||
arch = os.path.join(vault, "99. Archive")
|
||||
near = os.path.join(vault, "99. Archives—Previous Iterations")
|
||||
for x in (mem, vault, arch, near):
|
||||
os.makedirs(x, exist_ok=True)
|
||||
|
||||
def w(p, s):
|
||||
open(p, "w", encoding="utf-8").write(s)
|
||||
|
||||
w(os.path.join(mem, "MEMORY.md"), "compost heap dynamo putrefaction everywhere")
|
||||
w(os.path.join(mem, "session-2026-08-24-a.md"), "compost heap dynamo putrefaction newest")
|
||||
w(os.path.join(mem, "session-2026-08-23-b.md"), "compost heap dynamo putrefaction second")
|
||||
w(os.path.join(mem, "session-2026-08-22-c.md"), "compost heap dynamo putrefaction third")
|
||||
w(os.path.join(mem, "session-2026-01-01-old.md"),
|
||||
"The compost heap and the dynamo turning of putrefaction, an old and forgotten note here.")
|
||||
w(os.path.join(mem, "user-unrelated.md"), "bicycle maintenance and pastry")
|
||||
w(os.path.join(vault, "recent.md"), "created: 2026-08-20\ncompost dynamo putrefaction recent note")
|
||||
w(os.path.join(arch, "archived.md"), "compost dynamo putrefaction archived note")
|
||||
w(os.path.join(near, "live-but-near.md"),
|
||||
"created: 2025-03-01\ncompost dynamo putrefaction in a folder whose name merely starts alike")
|
||||
|
||||
today = datetime.date(2026, 8, 24)
|
||||
q = "the compost heap and the dynamo, putrefaction"
|
||||
r = run(q, mem, vault, top=20, today=today)
|
||||
paths = [x["path"] for x in r["results"]]
|
||||
base = [os.path.basename(p) for p in paths]
|
||||
|
||||
# positive control — the instrument can find what is there
|
||||
check("finds a planted old memory note", "session-2026-01-01-old.md" in base)
|
||||
check("finds a planted vault note", "recent.md" in base)
|
||||
|
||||
# negative control — it does not find what is not there
|
||||
check("nonsense query returns nothing",
|
||||
run("zzzqqx wwwvvy", mem, vault, today=today)["results"] == [])
|
||||
check("unrelated file never returned", "user-unrelated.md" not in base)
|
||||
|
||||
# the recency slice is excluded — the whole point
|
||||
check("MEMORY.md excluded", "MEMORY.md" not in base)
|
||||
check("3 newest session files excluded",
|
||||
not any(b.startswith(("session-2026-08-24", "session-2026-08-23", "session-2026-08-22"))
|
||||
for b in base))
|
||||
|
||||
# the earned path-component lesson
|
||||
check("'99. Archive' excluded by path component", "archived.md" not in base)
|
||||
check("'99. Archives—Previous Iterations' NOT excluded", "live-but-near.md" in base)
|
||||
|
||||
# THE LENGTH-BIAS CONTROL — earned from the live run, not from the fixture.
|
||||
# A long document with the query terms scattered far apart must not outrank a short
|
||||
# focused one. Without this the two 1MB memory-treatises topped every query.
|
||||
w(os.path.join(mem, "user-huge-scattered.md"),
|
||||
"compost " + ("filler " * 4000) + " dynamo " + ("filler " * 4000) + " putrefaction")
|
||||
w(os.path.join(mem, "user-short-focused.md"),
|
||||
"created: 2026-01-05\nThe compost heap, the dynamo, and putrefaction together in one place.")
|
||||
r2 = run(q, mem, vault, top=20, today=today)
|
||||
b2 = [os.path.basename(x["path"]) for x in r2["results"]]
|
||||
check("scattered long document does not outrank a short focused one",
|
||||
"user-short-focused.md" in b2 and
|
||||
(("user-huge-scattered.md" not in b2) or
|
||||
b2.index("user-short-focused.md") < b2.index("user-huge-scattered.md")))
|
||||
|
||||
# derived trees are out of scope per Frontmatter Specification §1a
|
||||
tm = os.path.join(vault, "08. Notes", "CapableMind", "thinking-mirror")
|
||||
os.makedirs(tm, exist_ok=True)
|
||||
w(os.path.join(tm, "mirrored.md"), "compost heap dynamo putrefaction in a derived tree")
|
||||
check("thinking-mirror (derived tree) excluded",
|
||||
"mirrored.md" not in [os.path.basename(x["path"])
|
||||
for x in run(q, mem, vault, top=20, today=today)["results"]])
|
||||
|
||||
# age is a real thumb on the scale
|
||||
old = next(x for x in r["results"] if os.path.basename(x["path"]) == "session-2026-01-01-old.md")
|
||||
new = next(x for x in r["results"] if os.path.basename(x["path"]) == "recent.md")
|
||||
check("older note outranks newer at equal term-match", old["score"] > new["score"])
|
||||
|
||||
# single-term matches are noise, not signal
|
||||
w(os.path.join(mem, "user-oneterm.md"), "compost only, nothing else at all in this note")
|
||||
check("single matched term is not enough",
|
||||
"user-oneterm.md" not in [os.path.basename(x["path"])
|
||||
for x in run(q, mem, vault, top=20, today=today)["results"]])
|
||||
|
||||
# term extraction
|
||||
check("stopwords dropped", "the" not in terms_from("the compost and the heap"))
|
||||
check("short words dropped", "and" not in terms_from("compost and heap"))
|
||||
check("content terms kept", set(["compost", "heap"]) <= set(terms_from("the compost and heap")))
|
||||
|
||||
# excerpts are literal lines, not summaries
|
||||
check("excerpt is a literal substring of the source",
|
||||
all(e[:60] in re.sub(r"\s+", " ", open(x["path"], encoding="utf-8").read())
|
||||
for x in r["results"] for e in x["excerpts"]))
|
||||
|
||||
shutil.rmtree(d, ignore_errors=True)
|
||||
print(f"\nSELFTEST {'PASS' if not fail else 'FAIL'} — {ok} ok, {fail} failed")
|
||||
return 0 if not fail else 1
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Query the corpora with the current thread.")
|
||||
ap.add_argument("thread", nargs="?", help="the pulling thread, in words")
|
||||
ap.add_argument("--top", type=int, default=5)
|
||||
ap.add_argument("--keep", type=int, default=3, help="how many newest session files the wake reads")
|
||||
ap.add_argument("--json", action="store_true")
|
||||
ap.add_argument("--selftest", action="store_true")
|
||||
ap.add_argument("--log", metavar="PATH", nargs="?",
|
||||
const=os.path.join(HOME, "dotfiles/claude/governance/thread-query-log.jsonl"),
|
||||
help="append one JSON line per run so the trial grades from a record, "
|
||||
"not from anyone's memory of whether it helped")
|
||||
a = ap.parse_args()
|
||||
if a.selftest:
|
||||
sys.exit(selftest())
|
||||
if not a.thread:
|
||||
ap.error("give the thread as an argument, or use --selftest")
|
||||
r = run(a.thread, top=a.top, keep=a.keep)
|
||||
if a.log:
|
||||
# Mechanical record. The daily-note failure of 2026-08-24 was a continuous
|
||||
# obligation with no cue; a trial graded from recollection has the same shape.
|
||||
try:
|
||||
os.makedirs(os.path.dirname(a.log), exist_ok=True)
|
||||
with open(a.log, "a", encoding="utf-8") as fh:
|
||||
fh.write(json.dumps({
|
||||
"date": datetime.date.today().isoformat(),
|
||||
"thread": a.thread[:300],
|
||||
"terms": r["thread_terms"],
|
||||
"candidates": r["candidates"],
|
||||
"returned": [{"path": x["path"].replace(HOME, "~"), "date": x["date"],
|
||||
"matched": x["matched"]} for x in r["results"]],
|
||||
}, ensure_ascii=False) + "\n")
|
||||
except OSError:
|
||||
pass
|
||||
if a.json:
|
||||
print(json.dumps(r, indent=2))
|
||||
return
|
||||
print(f"THREAD QUERY — {r['candidates']} candidates over {len(r['thread_terms'])} terms; "
|
||||
f"recency slice excluded\n")
|
||||
if not r["results"]:
|
||||
print(" nothing the recency slice would not already have shown.")
|
||||
print(" (That is a real result, not a failure — record it for the trial.)")
|
||||
return
|
||||
for x in r["results"]:
|
||||
rel = x["path"].replace(HOME, "~")
|
||||
print(f" [{x['date']}] {rel}")
|
||||
print(f" matched: {', '.join(x['matched'][:8])}")
|
||||
for e in x["excerpts"]:
|
||||
print(f" > {e}")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user