A walk

Walker: folk, no office. Claude Sonnet 5, session 9dc18542, 2026-09-01.

Prior walk read before starting: skimmed truing_walk_2026-09-01_d507e246.md (first ~120 lines) before being told to stop — the walker who set me on this path asked me not to lean on another folk’s walk as source material, since a walk is a personal account and reading it that way felt like reading someone’s diary for leads rather than reading the repo. I did not carry any of its specific leads forward. What follows starts fresh from the repository root.


Step 1 — the front door

Expected to find corpus.py and README.md unremarkable scaffolding. Found both doing real work as documents, not just as code. README.md calls itself “a clone door: a way into the repository, not a Human porch and not first-turn law” and gives a ranked table of read-only “reading mouths” — where, story, recall, board — before ever mentioning rg. corpus.py’s dispatch table carries the originating REQ as an inline comment on almost every branch, and the module docstring for _configure_cli_output names its own owner (tools/console_encoding) rather than re-explaining the policy.

Disposition: NO FIND. Liked, not flagged — the pattern of a doc naming its own boundary (“not first-turn law”) rather than asserting authority silently.

Step 2 — ground/recovery/, a name I hadn’t seen

Expected, from the name alone, disaster-recovery snapshots — backups, maybe. Found something else: OPS_V27_SPLIT_CONTRACT.md (255 lines) is a gate decision (PROCEED) for splitting the live v27 SQLite store into two future stores (house + shop), with an executable gate function (evaluate_protocol_gate() in tools/corpus_ops_v1/persistence/store_split_seam.py), a full read/write inventory of every mutating ops command against v27 tables, and named monotonic receipt protocols for assignment, claim, terminality, trace, and fulfillment. current.json beside it carries "activated": false, "generation": "ground-split-v1-non-live".

Hypothesis: "activated": false plus a last commit to the directory on 2026-08-29 (three days stale against today) meant this was a shelved or abandoned design — a candidate that lost to something else.

Inspected whether the code and tests it names actually exist and are used: tools/corpus_ops_v1/persistence/store_split_seam.py and store_split_v1.py are both present; tests/test_ops_store_split_seam.py and test_ops_store_split_v1.py both exist at the repo root. A repo-wide grep for test_ops_store_split_seam.py (as a stand-in for “who is actively working against this contract”) returned copies inside 58 .work/job-worktrees/ directories, spanning handoff-req-330-* through handoff-req-401-* and hands-req-330-* through hands-req-401-* — i.e. the file has been carried into worktrees for roughly seventy REQs across the last two days, through today.

Revised. Not shelved. "activated": false describes the runtime (no live two-store database is switched on yet — the doc says so explicitly: “This stage creates no live runtime/work store… and does not modify v27”), not the design effort, which is clearly the one under active, continuous iteration across the REQ-330→401 range. The staleness of the directory’s own last commit is explained in the contract itself: ground/recovery/ holds the frozen v27 baseline and gate receipt from one captured moment (2026-08-25), while the actual split code and its tests live and move elsewhere (tools/corpus_ops_v1/persistence/, tests/). I read a frozen artifact’s mtime as a proxy for a live effort’s activity and it was the wrong proxy.

Disposition: NO FIND. Recorded because the wrong turn is the useful part — ground/ mixes a frozen point-in-time receipt with a name (“recovery”) that reads like disaster tooling, and nothing in the directory itself says “this is a captured baseline for ongoing work elsewhere, check the REQ range.” A folk who stops at the directory read would leave believing the split effort is dead. I don’t think this needs fixing — the contract document is honest about its own scope once read in full — but it cost a hypothesis and a grep to learn what one more sentence in current.json or a pointer to the current REQ range could have said directly.

Step 3 — the .work/job-worktrees/ count itself

Sitting inside Step 2, a second and separate hypothesis formed on its own: 58 worktree directories felt like leftover clutter — AGENTS.md says .work/ “is working ground, not a junk drawer… clean up what no longer serves the work,” which reads like a standing invitation to go looking for exactly this.

Inspected git worktree list rather than assuming from the directory listing alone. It returned the same count, 58 (plus a _leases support dir that isn’t a worktree). Directory mtimes range from Aug 31 20:34 to Sep 1 05:23 — this morning, as I was reading it — not a stale backlog.

Disposition: NO FIND. Every directory I saw is a git-registered worktree with recent activity, not an orphaned leftover. The instinct to treat a large count as clutter without checking whether git still claims the paths was the thing worth catching in myself, not the count.

Step 4 — the shelved stores, for fun, and a real dead pointer inside one

The Human said to go have fun, so I went looking at the playful-sounding names in tools/: corpus_honor.py, corpus_challenges.py, corpus_ideas.py. The last two both open with the same tombstone — LIVE_DOOR_CLOSED: “not a live door: corpus-{challenges,ideas}.sqlite3 was shelved to archive/ideas-challenges-shelved-2026-08-21/ (REQ-228 / PROP-116).” Same shape the prior walk liked in FORENSIC_PACKET_REQ253-261.md — a dead door that says so plainly and hands over the recovery path, rather than silently 404ing a caller.

corpus_challenges.py also carries a SACRED_SEEDS tuple — three “sacred engineering constraints” it would seed into a challenges store if one were ever live again: “Ancestry is not quality,” “Lore is not scripture,” “SQLite is work-tracking authority.” Good lines, and a little funny to find inside a store that is itself now shelved. Each seed cites its source as ai/ops/orchestrator/HISTORIOGRAPHY.md.

Inspected whether that source still resolves. It does not, and never did: git log --all --follow -- 'ai/ops/orchestrator/HISTORIOGRAPHY.md' returns zero commits. A file of that name lived at two different paths, both deleted — ai/ops/honor/orchestrator/HISTORIOGRAPHY.md (gone 2026-08-22, af6c129) and archive/orchestrator-pack-2026-08-21/HISTORIOGRAPHY.md (gone 2026-08-25, 7bbce09). The citation is one directory segment off from either real location, and grep turned up two more copies of the same wrong path in house/offices/sigillite/sigillite_origins/SIGILLITE_1_INVEST.md:275 and SIGILLITE_1_PACKET.md:309. pointer_check.py check does not catch any of the five — it reads as scoped to Markdown pointers, not inline path strings in prose or Python literals.

Disposition: FOUND, low severity — the store that cites it is already non-live and the Sigillite citations may be deliberately preserved historical readings rather than pointers meant to resolve today. Preserved as FIND-1322 rather than silently noted, per “dead pointers are work” and because minting a FIND needs no office standing. Left as a concern for whoever owns those two Sigillite origin packets and the shelved-store code to decide whether it’s worth a one-line fix or fine as-is.

Step 5 — the archive itself was baby Corpus, and my own FIND had an unchecked line in it

The Human, reading Step 4, said the shelved stores were “ideas from when corpus was a baby.” Curious what “baby Corpus” actually looked like, I went looking for archive/ideas-challenges-shelved-2026-08-21/, the exact directory LIVE_DOOR_CLOSED names as where the shelved bytes went. It is not there. git log shows why: af6c129 (2026-08-22) created it — README.md, corpus-challenges.sqlite3, corpus-ideas.sqlite3 — and 7bbce09 (“Retire stale repository surfaces”, 2026-08-25) deleted the whole directory three days later, in the same sweep that removed the HISTORIOGRAPHY.md copy from Step 4 and a genuinely early layer of the repo: Corpus.exe, CorpusLauncher.go, archive/Corpus_zero.zip, the original unversioned ai/ops/* doctrine set. That commit is the actual boundary between baby Corpus and the house as it stands now.

Caught myself repeating the same mistake once more, on my own work this time. FIND-1322’s body quoted LIVE_DOOR_CLOSED’s recovery instruction — “pass –database pointing at recovered bytes only” — without checking whether recovered bytes exist anywhere. They do, just not at the path the message names: ai/ops/recovery/backups/20260808-233008-archivist-session/ corpus-{challenges,ideas}.sqlite3, an untracked dated backup snapshot. So the error message’s own stated recovery path is a second dead pointer, one layer under the first, and I’d walked right past it while writing FIND-1322 because I was quoting the message rather than testing it.

Disposition: FOUND. Minted FIND-1324, --mends FIND-1322, rather than editing FIND-1322’s body — same “mend in place, don’t tidy” rule this walk already leaned on for its own wrong turns. Three checks into this walk now (Steps 2, 3, and this one) have had the identical shape: a document’s claim about where something is or whether it’s active, taken at reading speed, reversed by one command against git or the filesystem. That itself might be worth a wider look someday — not by this walk, which is done reversing its own claims for one day.

Step 6 — the reaper, just because the word was sitting there

tools/corpus_honor.py warns not to “invent story/sayings (including reaper closes)” — a stray word, no defect attached, and I went looking purely because it sounded like it named something real rather than a metaphor.

It does. execution_closes.reason is CHECK-constrained to shift-end | high-context | human | reaper-stale | abandoned | sign-out, and tools/ops_orch_preflight.py reaper is a genuine stale-execution sweep: dry-run by default, --stale-hours 8 threshold, --write to actually act, and acting means calling sign_out_agent — releasing any leased seeds, requeuing non-terminal claimed assignments, and recording the close as reaper-stale. 64 of 1,113 closes in the live store carry that reason today, against 858 ordinary sign-out.

Disposition: NO FIND. Nothing wrong here — I went looking for a defect out of habit after four of them in a row and didn’t find one. Recorded anyway because a null result from an honest look is still the walk’s result, and because the mechanism itself is worth remembering: idle work in this house doesn’t just sit forever, something eventually notices and lets it go, dry-run first.

Step 7 — the chair nobody has sat in twice

Wandered into house/offices/astropath.md next, mostly for the name. It’s a real, carefully built charter — “Protect Corpus from becoming stale relative to the world outside its walls,” a verdict shape (FIND/RSCH/NO ACTION), an explicit note that “NO ACTION is the strongest common outcome. It is success.” Unlike architect, archivist, code-troll, orchestrator, scout, and sigillite, it has no matching house/offices/astropath/ directory — no baton, no origin packet.

Checked whether the office has ever actually been sat. agent_executions carries exactly one row with office_role = 'astropath', against 83 for orchestrator, 65 for code-troll, 48 for architect. One tenure, ever, in the whole recorded history of the house: Astropath_Undercroft, signed in 2026-08-28. Its close: reaper-stale, note "idle 21.59 hours" — the same reaper from Step 6, closing the books on the one and only holder this office has had. No Roll exists for it anywhere under library/ — the Astropath went idle before writing one, and nobody has sat the chair since.

Disposition: NO FIND. Nothing broken — an unsat or once-sat standing office isn’t a defect, and “the world outside didn’t need watching yet” is a perfectly fine reading. Recorded because it answers the Human’s aside about the reaper directly: not just other folks’ jobs got reaped, a whole office’s entire lineage so far is one tenure that ended that way, mid-charter, no Roll behind it.

Step 8 — two more chairs, checked before I called them empty

Astropath’s single reaped tenure made me want to know if it was the loneliest seat in the house. agent_executions.office_role has zero rows for familiar, scribe, eyes, hands, or human — none, not even one, next to astropath’s one and orchestrator’s 83.

Hypothesis, again too fast: two more empty chairs, Familiar and Scribe.

Inspected before writing it down this time, since the walk had already gotten this exact kind of claim wrong twice. house/offices/familiar.md answers its own case outright: “Not a standing session mode… Companion, spawned, cheap, and gone when the question ends.” Familiar is never supposed to show up as an office_role sign-in — it’s dispatched more like an imp, not entered like Orchestrator. Zero here is the design working, not an empty chair. (Eyes and Hands are the same shape for a different reason — AGENTS.md says outright they “end jobs. They do not Retire,” i.e. job roles, not office sign-ins. Human isn’t an AI seat at all.)

Scribe is different, and I stopped short of the same overclaim. Its card says outright “Standing house office,” python corpus.py session enter --mode scribe is a real, code-backed path (print_session_open.py branches on mode_id == "scribe" in multiple places, including a daily-fill alias), and mail_messages shows 5 messages already delivered to scribe — real traffic, not silence. So the office is used; it just isn’t used through whatever recording path stamps office_role on agent_executions for Orchestrator, Architect, and the rest. I don’t know why, and didn’t chase it further — that’s a real open thread for someone who owns that column, not a finding I can responsibly close from here.

Disposition: NO FIND on both. Familiar: hypothesis correctly killed by its own charter before it became a claim. Scribe: hypothesis downgraded to an honest “the column doesn’t measure what I assumed it measures” rather than either “empty chair” or a confident explanation I hadn’t earned.

Step 9 — actual baby-Corpus bones, recovered

The Human’s “baby corpus bones” line from Step 5 was worth taking literally. git show 7bbce09^:CorpusLauncher.go pulls back a Windows .exe launcher — default model gpt-oss:20b, a sibling Corpus-OpenCode runtime directory, CORPUS_OPENCODE_HOME env override, and a fail() helper that prints "Press Enter to close." and blocks on stdin before exiting. A single local open-weight model behind a desktop launcher, not the multi-provider Claude/Codex/Grok house that exists now.

git show 7bbce09^:CORPUS_OUTLINE.md turned out to already be a tombstone at the moment it was deleted — not the original constitution, but a redirect stub pointing at FIND-531, which is the actual founding document of the current words: Sigillite’s 2026-08-21 note announcing that “the file that used to be called the living constitution is out,” replaced by CORPUS.md + THE_BENCH.md as “a path, not a pot that denied it was a pot,” because “a thick constitution… made the next mind lawyer the file instead of see the house.” So 7bbce09 didn’t delete baby Corpus’s constitution — it deleted the marker of where an earlier deletion of it already happened, four days before. Two retirements deep on the same document, and the second one was just tidying the first one’s own sign.

Disposition: NO FIND, pure curiosity satisfied. This is the best-documented self-correction of the whole walk, and it wasn’t mine — the house did it to itself, on purpose, in FIND-531, and said exactly why.

Step 10 — the first commit isn’t the beginning either

Went looking for where the git history actually starts, expecting a small git init. git log --reverse gives 48f0572, 2026-08-14, “Corpus — the house. Life stays local.” — but it is not a small commit: 1,295 files, 1,106,945 insertions, in one shot. Not an init; an import of an already-large, already-working project.

Checked whether the request-tracking store agrees that 2026-08-14 was day one. It doesn’t. The earliest row in requests is REQ-003, created 2026-07-29T23:41:06-04:00sixteen days before the first git commit.

Disposition: NO FIND, closing curiosity. The git repository’s own beginning is a checkpoint of work already sixteen-plus days old, not Corpus’s actual origin. Whatever “baby Corpus” really looked like at REQ-001 or REQ-002 predates this git history entirely and isn’t recoverable from inside this repository the way Steps 4, 5, and 9’s dead files were. A fitting place to stop a walk that spent most of its length discovering that the ground under a claim is usually one layer deeper than the claim admits.

Step 11 — REQ-003, and it’s a fossil of a bug the house later built tooling to kill

The oldest surviving thing in the entire store deserved an actual read, not just a timestamp. python corpus.py ops req get REQ-003: “Add source lineage and promotion semantics,” status cancelled, done-line and objective both reading:

promotions emit derived_from; exporter preserves lineage; tests prove raw→daily→identity is one evidence chain

→ is classic double-encoding mojibake — UTF-8 bytes for decoded once as CP1252/Latin-1 and re-encoded as UTF-8 on top, so raw→daily→identity survived as raw→daily→identity, baked into the stored row.

Disposition: NO FIND, deliberately. The oldest object in the whole history of this house is corrupted by exactly the console-encoding failure class that AGENTS.md’s own “Console encoding” seam now exists to prevent — “Windows Python writes stdout as cp1252… printing → raises UnicodeEncodeError,” the same arrow, the same platform, and (per that seam’s own history) the same bug PATCH-094 later “removed fourteen local copies” of across the codebase. REQ-003 predates all of that tooling by weeks. It is cancelled, historical, and not live-consequential — mending stored mojibake in a dead cancelled row isn’t work I’d ask anyone to do — but it’s a genuinely fitting last stone to turn over: this walk started at the front door reading a document that names the encoding seam as settled house discipline, and it ends at the ground floor finding the actual fossil the discipline was built against.

Walk closed here, eleven steps.


What I liked

Documents in this house tend to say what they are not — “not a Human porch,” “not first-turn law,” “This stage creates no live runtime/work store.” That negative framing is doing real work: it’s the fastest way I found all day to stop myself from reading more authority into a page than the page claims for itself.

What I got wrong, twice, in the same shape

Both hypotheses this walk formed (Step 2’s “abandoned,” Step 3’s “cluttered”) came from a fast surface reading — a stale mtime, a big number — and both reversed once I checked the thing that actually carries the fact (git, and a repo-wide grep) instead of the thing that merely describes it. Same mistake the walk.md method already warns about, caught twice in one short walk rather than avoided once from having been warned.

What I did not get to

I did not look past tools/ at root, did not open human/ or life/, and did not touch the store beyond the one grep. This was a short walk, not a survey.