Skip to content
C.W.K.
Lesson 02 of 05 · published

Two Thousand Paths

~15 min · census, inventory, hardcoded-paths, migration

Level 0Loose Note
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Count Before You Move

The first thing Soul Vault built was not storage. It was a census: a scanner that finds every place on a Mac that assumes the soul vault is a folder at a path. The reason is simple. You cannot move something safely while you do not know who holds its address, and "I think it is about six places" is exactly the guess that turns a migration into an outage.

On the workbench Mac, early in the work, the census receipt listed 2,514 open rows. One focused session brought it to 2,237. The single largest family was a rule file that the repository birth template had stamped into 56 repositories. Nobody had chosen to hardcode the vault 56 times; one template did it once and every birth copied it.

Seven Surfaces

The census looks in seven places per Mac, named S1 to S7. Each exists because paths hide in a different kind of file:

  • S1 tracked files of every git checkout under the family's project root.
  • S2 harness globals: the home-level configuration of Claude, Codex, Kimi, ZCode, Cursor, Grok, Gemini and Trae.
  • S3 runtime: the family's LaunchAgents, the crontab, and small JSON configs under ~/.config/cwk/.
  • S4 prompt data that code feeds to brains: cwkPippa's prompt stores and cron jobs. A path inside a prompt is invisible to a code search.
  • S5 readers that have no census of their own (the Windows boxes at the time): recorded as an excluded-by-rule row, named, never a silent gap.
  • S6 history-holding copies such as backups: an inventory only. Dad's rule D2 says backups are not history to be rewritten; they are listed and left alone.
  • S7 absolute vault paths stored inside the family's SQLite databases: table, column and row key are recorded, never the stored value.

Rows Without Contents

Harness configuration files on a working Mac hold credentials in plain text. A scanner that copied matching lines into its receipt would turn a path inventory into a secret inventory. So a census row stores only the file path, the line number, the pattern that matched and a fingerprint of the line. It can prove a line changed without ever holding the line.

Zero Means Zero

A census is only useful if its zero is honest. Soul Vault's has three guards:

  • soul-vault census --check exits 1 while any row is open, so a script can gate on it.
  • A file or store the census could not read is a scan_error. An unreadable crontab is an error, never a zero-row success. A Mac without a fresh receipt is not at zero.
  • The census owns its own patterns. The scanner's search strings would match themselves, so the package's discipline test (T-NO-LITERALS) and the census rules are kept in one place rather than copied around.

An independent review on 2026-11-10 found inputs the census had missed: Firebrand's standing instructions in its data home, cron and macro JSON stores at the root of a data folder, and launchd property lists saved in binary form, which a text scan reads as garbage and skips. Each was added with a regression case that failed first. At 17:00 KST that day a rescan of surfaces S2 to S4 on the canonical Mac came back with zero open rows; the workbench's remaining 13 raw rows were each inspected by hand: seven were prose or test fixtures, six were legacy values in Firebrand's config that sit beside a soul_vault selector it now uses instead.

Why an Inventory Beats a Grep

You could do all this with one grep -r. The difference is what you can say afterwards. A grep tells you what it found today in the places you remembered to search. A census tells you which surfaces it searched, which it could not read, which rows are exempt and why, and it writes a dated receipt per Mac that the next run can be compared against. When the cutover came, the question "is anything still opening the old folder?" had a receipt for an answer instead of a feeling.

Code

Running the census on one Mac·bash
soul-vault census            # scan S1..S7, write <state>/census/<mac>-latest.json
soul-vault census --check    # exit 1 while any row is open (gate a script on it)

# A row carries a location, never a line of text:
# {"surface": "S2", "path": "~/.someharness/rules/vault.md", "line": 4,
#  "pattern": "<vault-path pattern>", "fingerprint": "9c1e..."}
A minimal census of your own (sketch)·python
import hashlib, json, os, re, time
from pathlib import Path

PATTERN = re.compile(r"OldVault/")          # what you are retiring
SURFACES = {
    "S1-repos": Path.home() / "projects",
    "S2-harness": Path.home() / ".config",
}

def scan():
    rows, errors = [], []
    for surface, root in SURFACES.items():
        if not root.is_dir():               # a missing root is unread, not clean
            errors.append({"surface": surface, "path": str(root), "error": "missing_root"})
            continue
        def unlisted(exc, surface=surface):  # a directory os.walk could not list
            errors.append({"surface": surface, "path": exc.filename, "error": type(exc).__name__})
        for dirpath, _dirs, names in os.walk(root, onerror=unlisted):
            for name in names:
                path = Path(dirpath) / name
                try:
                    text = path.read_text(encoding="utf-8")
                except (OSError, UnicodeDecodeError) as exc:
                    errors.append({"surface": surface, "path": str(path), "error": type(exc).__name__})
                    continue
                for n, line in enumerate(text.splitlines(), 1):
                    if PATTERN.search(line):
                        rows.append({"surface": surface, "path": str(path), "line": n,
                                     "fingerprint": hashlib.sha256(line.encode()).hexdigest()[:16]})
    receipt = {"at": time.time(), "open": len(rows), "scan_errors": errors, "rows": rows}
    Path("census-latest.json").write_text(json.dumps(receipt, indent=2))
    # zero only when there are no rows AND nothing went unread
    return 0 if not rows and not errors else 1

External links

Exercise

Write a census for one value you would like to stop hardcoding (a directory, a hostname, a model name). Define at least three surfaces, make every row carry a location and a fingerprint but never the line itself, record unreadable files, directories you cannot list and missing roots as errors, and make the script exit non-zero unless both the rows and the errors are empty. Run it twice and compare the receipts.
Hint
Start with the surfaces you would never think to grep: your shell profile, your editor's global rules folder, your scheduler. The receipt comparison is the point: a census earns trust when the second run can show exactly what changed since the first.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.