The steward asked for a daily note in Obsidian explaining in plain terms what we did, decisions taken, and commit references — plus significant insights and exchanges between the parties. This is Obsidian tracker item 5, the actual goal, unstarted since 2026-08-19 while four items of frontmatter hygiene stood in front of it. Two prior attempts at this exact genre were read before anything was designed, honouring the tracker's own flag: daily-log/ (4 entries, Mar-Apr 2026) and sessions/ (3 long-form narratives). Both died inside four weeks. Neither had a trigger — they were written when someone remembered. So the design question was never what the note should say. It was what makes it survive. Answer, steward-chosen at each fork: the note lives at 01. Daily/YYYY-MM-DD.md with project work under its own H2 inside it rather than in project folders; a SessionStart hook creates it so existence stops depending on memory; the executor writes during the session because a wrap-only design inherits the wrap's failure mode (2026-08-19 died unwrapped); and the wrap finalises rather than begins. daybook-ensure.py creates only. It will not touch an existing note — that is the control the design turns on, and it is tested, along with a positive control proving the no-dir report distinguishes a missing directory from a broken function. It also reports failure loudly, because the job it sits beside spent five months failing behind a > /dev/null 2>&1. Not revived: the 2025 analogue template — sleep, supplements, homeopathy. Pen and paper beat it and should keep it. That it failed is a finding, not a gap, and this note is a different genre rather than its replacement. PENDING-155 files the steward's idea for the jurist's side: an append-only MCP surface writing a scratch file the executor folds in. Deliberately NOT a tool on governance-mcp.py, whose read-only guarantee is a live AST control with a positive control rather than a comment. A separate one-tool server leaves that intact, and the vault note stays single-writer — the same lesson the thinking-mirror taught this morning. Correction carried into the record: the executor told the steward mid-session that Claude.app has no filesystem access. False since 2026-08-08. Third instance today of a constraint asserted from recall where the substrate was one file away. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JQKeKY9T9d95KpvHwwok8T
224 lines
15 KiB
Markdown
224 lines
15 KiB
Markdown
---
|
||
name: project-obsidian-vault-practice
|
||
description: "Canonical tracker for the Obsidian vault workstream — turning root-and-branch from an archive into a practice, beginning with a ratified Frontmatter Specification v1.0.0. Holds the operational facts (the vault is NOT a git repo; it mirrors to ~/_Dev/david-root-and-branch-vault-git), the applied-pass record, and the open tail. Read before any vault work."
|
||
metadata:
|
||
node_type: memory
|
||
type: project
|
||
modified: 2026-08-20T09:08:17Z
|
||
---
|
||
|
||
# Obsidian vault — from archive to practice
|
||
|
||
**Steward's goal, stated 2026-08-19:** *"optimizing my Obsidian usage and setting up a regular
|
||
workflow to have the important parts of our work captured there… My instinct is that I could
|
||
make better use of it. I want to create an Obsidian 'spec' like we have done for all of our
|
||
serious projects."*
|
||
|
||
**The tool boundary, from the steward, so it is not re-elicited:**
|
||
|
||
| tool | role |
|
||
|---|---|
|
||
| **Drafts.app** | scratchpad; ephemeral text, or text destined elsewhere. Kept essentially empty at the end of every week. |
|
||
| **Notes.app** (Mac/iOS) | confidential material, as locked notes. |
|
||
| **Obsidian** (`root-and-branch`) | notes that must not be lost. *"So far, a sort of archive."* |
|
||
|
||
**Scope note:** the vault is *also* the Compass — the steward's personal operating system.
|
||
`~/CLAUDE.md` says: reference it, never write to it. **That standing rule was suspended for this
|
||
workstream by explicit authorization** (`"I authorize the Compass ones too"`, 2026-08-19), for
|
||
the named mechanical passes only. It is not a general licence.
|
||
|
||
---
|
||
|
||
## Operational facts — do not re-derive
|
||
|
||
- **The vault folder is NOT a git repository.** `~/Library/Mobile Documents/iCloud~md~obsidian/Documents/David, root-and-branch`
|
||
has no `.git`.
|
||
- **It mirrors to `~/_Dev/david-root-and-branch-vault-git`** (remote:
|
||
`git.skemantix.com/David/david-root-and-branch-vault-git`). An automated job commits
|
||
`Mirror sync <timestamp>` on its own schedule — so steward hand-edits land in git without
|
||
anyone asking.
|
||
- **Working reports and machine-readable changelogs live in `~/dotfiles/obsidian/`**:
|
||
`vault-frontmatter-inventory-2026-08-19.md`, `vault-frontmatter-pass1-followups-2026-08-19.md`,
|
||
`vault-governance-block-round2-2026-08-19.md`, `vault-round3-archive-and-relations-2026-08-19.md`,
|
||
plus `fm_inventory.json`, `pass2-changelog.json`, `pass2-flags.json`.
|
||
- **The spec is in the vault, not in dotfiles:** `00. Compass/Frontmatter Specification.md`.
|
||
- ⚠ **`verify-before-compose.sh` fires on `Write|Edit`, and this work runs through Bash.** A vault
|
||
hook wired the same way would not fire on how the work actually runs. Noted 2026-08-19, unfixed.
|
||
|
||
---
|
||
|
||
## Chronological log
|
||
|
||
### 2026-08-19 — census, spec, two passes (session died unwrapped; see [[session-2026-08-19-the-vault-got-a-spec-the-links-were-already-broken]])
|
||
|
||
- **Four read-only census rounds before any edit.** 2,519 notes parsed, no sampling. 400 distinct
|
||
keys over 5,867 instances; **68% of notes have no frontmatter at all.** 66 keys consumed, 29
|
||
written-by-template-and-read-by-nothing, 305 orphaned.
|
||
- **Round 2/3 findings that changed the design:** `owner` was one job in three spellings (cut);
|
||
`canonical` was **one name doing two jobs** (self-descriptive vs pointer-elsewhere); the
|
||
hypothesis that pointer-form marks archival **tested negative** — 65 of 67 pointers sit outside
|
||
`99. Archive`. What actually distinguishes Archive is **decay in practice, declaration in name
|
||
only**: `status: archived` on 2.3% of it, 90% receiving no wikilink from any live note, and **no
|
||
archival policy note anywhere in the vault.**
|
||
- **Frontmatter Specification v1.0.0 ratified** and placed in `00. Compass/`. First principle:
|
||
*storage and lifecycle are orthogonal* — the folder says nothing; only `status:` declares.
|
||
- **Pass 1 and pass 2 applied and pushed.** `949ff14` `31d8e1f` `3d47bd2` `00e741d` `4c364e9`
|
||
`fab8fb0` (**511 edits / 268 files**) `aee615d`.
|
||
- **End state:** `owner` 0 · `change_log` 0 · `domain` 0 · `revisions` 90 · `canonical` 159 ·
|
||
`see_canonical` 3 · `confidence` 9 · `links` 8 kept-and-flagged. **YAML parse errors 16,
|
||
unchanged.**
|
||
- **Two executor tooling defects caught before applying** (§6 handler covered block-style lists
|
||
only — would have done 29 notes of 90 and reported success; §7 logged a retirement it did not
|
||
perform). Both found by **re-censusing an applied copy, not by reading the changelog.**
|
||
- **The jurist corrected its own "88 recoverable" reading**: those were self-descriptive values
|
||
resolving to themselves by construction. **Only 3 of 66 pointers were genuinely recoverable.**
|
||
|
||
### 2026-08-20 — the steward opened Obsidian, and the links were already broken
|
||
|
||
Checked against the mirror's history, not inferred. **Coffee log** (`brew_temp: [[94–96°C]]`) and
|
||
**homeopathy** (`[[Ignatia amara — The Medicine of the Sigh]]` naming a *title* where the file is
|
||
`Ignatia amara.md`) are both **pre-existing**; pass 2 never touched the homeopathy note and
|
||
touched only `linked_note`→`linked_daily_note` in the coffee log.
|
||
|
||
**But the passes are not innocent.** §7 flattened nested `links.parents` — inert YAML Obsidian did
|
||
not render — into top-level `parents/children/peers`, which **made 194 already-unresolvable targets
|
||
render as clickable-and-broken in the properties UI.** The breakage was surfaced, not created. The
|
||
pass report did not predict this, and it should have.
|
||
|
||
|
||
### 2026-08-23 — status check: four items verified against substrate, and one NEW regression found
|
||
|
||
Asked where the workstream stood; verified rather than relayed. **Items 1–4 confirmed live**, with
|
||
two unit corrections: `related` was counted by the tracker in *targets* (194 unresolvable) and a
|
||
file-count (122 notes / 213 targets now) is not comparable to it; and `canonical: 159` is a
|
||
**frontmatter** count — a naive `grep '^canonical:'` returns 239 because it also catches body text.
|
||
The tracker was right and the quick instrument was wrong. YAML parse errors independently
|
||
re-measured at **16**, matching.
|
||
|
||
⚠ **NEW — the vault has a write path the spec does not govern, and it silently reverted pass 2.**
|
||
Mirror sync `a58fc00` (2026-08-22 23:52) changed 14 files and ran *against* the spec:
|
||
`owner` **0 → 9**, `change_log` **0 → 9**, `revisions` **90 → 81**, and `canonical: true` was
|
||
replaced by pointer-form paths. All 9 sit in one subtree,
|
||
`08. Notes/CapableMind/thinking-mirror/chamber/archive/orientation/`.
|
||
|
||
**Mechanism — SUPERSEDES the first reading filed earlier the same day.** The earlier entry named
|
||
*"a job mirrors `docs/thinking/David/`"* and pointed at the launchd agent. **Wrong agent.** Matching
|
||
upstream content is not evidence of which path wrote it, and the launchd job targets a different
|
||
folder entirely. The actual writer is **`/wrap-up` §7**, which rsyncs
|
||
`~/_Dev/CapableMind-AI/docs/thinking/David/` → `08. Notes/CapableMind/thinking-mirror/` **at every
|
||
wrap**. The 2026-08-22 wrap ran it at 23:42; vaultsync committed the result at 23:52 as `a58fc00`.
|
||
|
||
⚠ **There are TWO mirrors of the same source into two different vault folders, and neither knows
|
||
about the other:**
|
||
|
||
| writer | destination | state |
|
||
|---|---|---|
|
||
| `/wrap-up` §7 (every wrap) | `08. Notes/CapableMind/thinking-mirror` | **live** — 251 files, 0 diff from upstream |
|
||
| `com.dglidden.thinking-mirror` (launchd, 48 h) | `00. Compass/00b. Constellations/CapableMind/thinking-mirror` | **dead** — 151 files, 115 behind, frozen since 2026-03-13 |
|
||
|
||
**The launchd job is failing and cannot say so.** `launchctl list` reports last exit **1**; the
|
||
script ends `rsync … > /dev/null 2>&1`, so its own plist `StandardOutPath` receives nothing and the
|
||
log has been 0 bytes since 10 Mar. Precedent for the cause is in `session-ledger-2026-04-16.md`:
|
||
the *vaultsync* agent failed the same silent way for weeks — **macOS TCC / Full Disk Access, rsync
|
||
under launchd against an iCloud path, exit 23** — and was fixed by granting FDA. Same shape here,
|
||
never fixed. ⚠ **Exit 1 is not exit 23, so the TCC diagnosis is a strong hypothesis, NOT
|
||
established.** A manual `--dry-run` of the exact command succeeds (exit 0) when run interactively,
|
||
which is consistent with TCC but does not prove it.
|
||
|
||
**The reframe that resolves this: you do not edit a mirror.** Applying the frontmatter spec to a
|
||
derived tree is a category error — the edits cannot survive their next sync, and pass 2's edits to
|
||
both mirror trees were void the moment they were written. This is not misbehaviour by the mirror.
|
||
|
||
**Not fixed — the disposition is a design choice, not a [FIX]:** exclude the subtree from the spec's
|
||
scope · apply the spec upstream in CapableMind-AI · or declare mirrored notes not-spec-governed and
|
||
say so in the spec. Steward's call.
|
||
|
||
**Item 5 sharpened.** `01. Daily/` holds **11 notes, the most recent 2025-09-04** — nearly a year
|
||
old, and the Daily-Notes plugin is not configured. There is no dormant capture habit to revive; the
|
||
practice would be built from nothing. `00a. _inbox` holds 11 notes.
|
||
|
||
|
||
|
||
### 2026-08-23 (later) — the capture practice is started, and it is a different genre from the one that failed
|
||
|
||
**The steward specified it, and the specification excludes the old daily note.** The 2025 template
|
||
(sleep, supplements, homeopathy, skin, family, reflection) was an attempt to reconcile an analogue
|
||
practice with a digital one; pen and paper won, and **it stays retired — that is a finding, not a
|
||
gap.** What is wanted instead: *"a daily note in obsidian which I can refer to, which explains in
|
||
relatively simple terms what it is that we have done, decisions taken, and references to any
|
||
commits"*, plus *"any significant insights or exchanges that happened between us."*
|
||
|
||
**Two prior attempts at exactly this genre were found before designing anything** (the tracker's own
|
||
"read `daily-log/` and `sessions/` first" flag, honoured): `daily-log/` — 4 entries, Mar 10/12/20 +
|
||
Apr 5, sections Summary / What we did / Status / Blocked / Next, already recording an exchange
|
||
(*"Thistleweld caught the meta-problem at line 183"*); and `sessions/` — 3 long-form narratives,
|
||
linked as children of the daily note. **Both died inside four weeks. Neither had a trigger.** So the
|
||
design question was not what the note should say but what makes it survive.
|
||
|
||
**Built, steward-chosen at each fork:**
|
||
- **Location:** `01. Daily/YYYY-MM-DD.md` — its normal home. **Project work under its own H2/H3
|
||
inside the note, NOT in project folders** (steward, explicitly).
|
||
- **Trigger:** `daybook-ensure.py`, wired into the `SessionStart` hook chain. **Creates only** —
|
||
it will not touch an existing note, which is the control the design turns on. 7 checks, incl. a
|
||
positive control proving the `no-dir` report is real. Registered via the `update-config` skill;
|
||
`jq -e` validates, and a diff against a backup shows only the 8 added lines.
|
||
- **Accretion:** the executor writes during the session; `/wrap-up` §7.5 finalises rather than
|
||
begins. A wrap-only design inherits the wrap's failure mode — 2026-08-19 died unwrapped.
|
||
- **Register:** plain language, explicitly. The hardest part, and named as such in §7.5, because the
|
||
executor's default is dense and written for itself.
|
||
- **Jurist:** recorded by the executor as exchanges pass through it. **PENDING-155** filed for the
|
||
steward's better idea — an append-only MCP surface writing a scratch file the executor folds in.
|
||
⚠ Deliberately **not** a tool on `governance-mcp.py`, whose read-only guarantee is enforced by a
|
||
live AST control with a positive control, not by a comment.
|
||
|
||
⚠ **Correction:** the executor told the steward mid-session that Claude.app "has no filesystem
|
||
access." False since 2026-08-08 — `governance-mcp.py` gives it mediated read access (PENDING-82,
|
||
closed). Same failure class as the two earlier corrections today: asserted from recall where the
|
||
substrate was one file away.
|
||
|
||
|
||
---
|
||
|
||
## Current state — OPEN
|
||
|
||
1. ⚠ **A defect of ours: `see_canonical: "[[Index]]"`** in `09. Atlas of Roots/00. Atlas of Roots — Index.md`,
|
||
converted from `canonical: 09. Atlas of Roots/index.md`, **a file that does not exist**. The only
|
||
`Index.md` notes are `08. Notes/Tools & Workflow/Index.md` and a Catalan `00. Index/index.md`.
|
||
**It resolves to the wrong note or none — 1 of the 3 pointers §3 wrote.** Same basename flaw the
|
||
jurist corrected as a *number* that afternoon, landed in an applied edit as a *mechanism*.
|
||
2. **194 unresolvable `related` targets**, left bare and flagged by §6.
|
||
3. **63 residual `canonical` pointers** — each a note that named an authority for itself and lost
|
||
track of where it lives. Steward's eyes wanted here most: this is the population `canonical` was
|
||
actually describing, invisible while 157 path-strings sat behind one field name.
|
||
4. **16 YAML parse errors**, unchanged across both passes — never in scope, never addressed.
|
||
5. **The actual goal has not been started.** Everything so far is hygiene on an archive. *"A regular
|
||
workflow to have the important parts of our work captured there"* — the capture practice, the
|
||
thing that would make the vault a practice rather than a tidier archive — **has not been
|
||
designed.** Do not let the frontmatter tail stand in for it.
|
||
6. ✅ **RESOLVED 2026-08-23 — the two mirrors are now one, and it reports.** Steward chose: keep
|
||
`/wrap-up` §7, retire the launchd agent. Done and verified: agent unloaded · plist removed from
|
||
`~/Library/LaunchAgents/` **and from `~/dotfiles/config/capablemind/`** (load-bearing —
|
||
`setup-capablemind.sh:135` copies every `*.plist` there into LaunchAgents, so leaving it would
|
||
resurrect the retired job) · deployed script removed · stale tree deleted after three independent
|
||
no-loss checks · `/wrap-up` §7 rewritten to name itself the only writer, forbid edits to the
|
||
derived tree, and report the outcome with its exit code in §8 · spec bumped to **v1.0.1** with
|
||
principle 7 + §1a declaring mirrored trees out of scope. Commit `f1c91d9`.
|
||
**End state verified:** live archive 251 files, 0 diff from upstream; stale tree gone; agent gone.
|
||
|
||
---
|
||
|
||
## What remains — and what it is worth
|
||
|
||
Items 1–4 are the **frontmatter tail**: real, bounded, and *not the goal*. Item 5 is the goal.
|
||
|
||
- **1** is ours and wrong (one bad pointer) — smallest real debt, ~10 minutes once its correct
|
||
target is decided.
|
||
- **2, 3** are steward-judgement work, not executor work: 73 pointer-form `canonical` values and
|
||
213 `related` targets need an eye that knows what the notes *mean*.
|
||
- **4** (16 YAML parse errors) has never been in scope and is a session-sized bite.
|
||
- **5 — the capture practice — STARTED 2026-08-23**, after 4 days as the unstarted goal. Hook +
|
||
in-session accretion + wrap finalisation + a first real note. **It is not proven yet:** two
|
||
predecessors reached 3 and 4 entries. The measure of this one is whether it is still being written
|
||
in four weeks — and §7.5 now requires the wrap to SAY SO if it lapses, rather than letting it fade
|
||
a third time in silence.
|