Skip to content

Detect every judgment step a session can skip - #30

Merged
leeovery merged 7 commits into
fix3/e10-gapsfrom
fix3/e11-verification
Aug 25, 2026
Merged

Detect every judgment step a session can skip#30
leeovery merged 7 commits into
fix3/e10-gapsfrom
fix3/e11-verification

Conversation

@leeovery

@leeovery leeovery commented Aug 23, 2026

Copy link
Copy Markdown
Owner

The verification layer: the engine cannot force a session to do judgment work, so it must always detect the work skipped.

  • New lint check: an item whose enrichment landed but where harvest never ran ("harvest these") — fires only when the item owes no work and has a fetched page; "ran and promoted nothing" never fires; renames covered by shortid matching
  • enrich item digest records its own digest pass (record before file write, so a crash reads loud on the digest backstop rather than silently defeating staleness); the separate instruction is gone from the skills
  • New lint check: an item a page cites but no taxonomy topic records — the coverage invariant's other face
  • The dex-run backstop now sends an interrupted item through the full remaining procedure (harvest included); the query skill's false synthesis-refresh claim corrected
  • A media unit resting under media_fetch: none files under "Needs you" with the honest reason, not "the engine retries by itself"
  • Sync converges file↔directory shape conflicts inside synced skills instead of crashing

🤖 Generated with Claude Code

leeovery and others added 7 commits August 23, 2026 21:01
Pass records exist so "ran and promoted nothing" is distinguishable from
"never ran", but only one side had a reader: _stale_passes flags records
whose rules version is old, and an item with NO harvest record was never
examined — a session that skipped harvest left an item digested and cited
on the strength of the shared link alone, on no surface.

lint now lists "harvest these (enrichment landed, no harvest pass on
record)": a live item that owes no further work, has at least one fetched
page on record — a done unit that is not via media/extract-asset, the URL
cap's own reading of "page" — and no harvest pass under any rules version.
The bounds follow the ingest procedure's: an item still owing a unit is
raw and has not reached the harvest step; a no-source capture and an item
whose every unit died have no page to read the subject rule over and owe
description + digest instead, which the run report already names. A pass
covers its item by trailing shortid — the match exclusions already use
across renames — so a renamed item's standing record never reads as a
skipped judgment, and a migration reseed keeps answering to the
rules-version check, not this one.

The finding fires beside the digest backstop rather than deferring to it:
that backstop's repair is digest → place → wiki, which never runs harvest,
so deferring would carry the skipped judgment straight through the repair.
Like the stale-pass row it never exits 1 — no later mechanical stage
breaks on a missing pass the way the wiki layer breaks on a malformed
digest, and the repair is judgment, the report's business. Lives beside
digest_orphans in run.py, on the same ownership seam; torn pass lines stay
lint's loud parse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dex-run step 8 backstop told the session to complete an interrupted
item's "digest → place → wiki steps now" — a repair that skips harvest,
the step that comes before digest in the per-item procedure. An
interruption can predate harvest just as easily as digest, and the
`enrich status` surface the step reads has no never-harvested row, so a
harvest skipped by this path stayed invisible until the next health
check flagged it (the lint check this branch already carries). The lint
catch is the backstop's backstop; the instruction must stop causing the
state it catches.

The step now sends the session through the full remaining per-item
procedure — harvest → digest → place → wiki, per
references/ingest-item.md — and says why: the listing states that a
digest is owed, never that harvest ran.

The dex-lint fix-list's own "finish digest → place → wiki" line is left
as it stands: the lint report lists a skipped harvest as its own
"harvest these" row beside the digest row, so a lint session covers
harvest through that row rather than through this one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dex-query told the owner that syntheses are refreshed by the health
check as new material lands. Nothing does that: lint's staleness check
reads topic pages against their taxonomy members, and a synthesis has no
topic, so it is never compared against anything. Nor will such a check
be built — a synthesis is question-shaped and dated on purpose, and a
mechanical check cannot tell one gone stale from one deliberately scoped
to its date; that distinction is judgment.

The skill now says what is true: refreshing happens in the query path
itself, when a session reads a synthesis whose generated: date predates
material that changes its answer, and rewrites it. The design doc makes
no synthesis-refresh claim, so it needed no correction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Writing a digest and recording its pass were two commands, and only the
first had a product the session could see. A forgotten `enrich pass
--stage digest` cost the staleness backstop its comparand silently: a
digest with no pass record is dated by nothing, so no later enrichment
ever reads as newer than it, and the item escapes "Digest these"
forever. One motion, one verb: `enrich item digest` now records the pass
itself, through the same record_pass path the CLI's pass verb calls —
one pass-writing path, not two.

Ordering is chosen by which crash residue has a reader. The record goes
in after validation and before the file write: a refused payload records
nothing, and a crash between the two writes leaves a pass with no digest
file, which digest_orphans' no-digest branch lists loudly. The opposite
order leaves a digest with no pass — the very unreadable state this
change removes — so the record goes first. The confirmation line says
the pass was recorded, so a session never doubts it into a duplicate
`enrich pass`.

The skills drop the separate digest pass step (the ingest procedure's §6
now says the verb records it; dex-run's state-writes rule and the
contract say the same), while `enrich pass --stage digest` stays as the
manual re-record and the harvest/wiki recorder. Design §4/§10/§14
updated to the same account. Updated assertions:
test_writes_the_canonical_digest, test_a_rewrite_says_so_and_replaces_
every_field and test_item_digest_writes_the_digest now expect the
"digest pass recorded" confirmation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
state-formats.md states the invariant: every corpus item appears in at
least one topic's items or in uncategorized-shares. lint only ever read
one face of it — orphans fires on an item that is uncited AND
unledgered — so an item a page cites that no topic records was invisible
on every surface: a citation is not a placement, and nothing asked the
placement question about the cited.

The check shares the derivations the orphan logic already computes: the
cited set is the wiki scan's, the uncategorized set stays the orphan
check's own, and the new placed set is the union of every topic's items
(uncategorized-shares included, being a topic in the same dict), read
with the same tolerance for hand-mangled shapes. It renders beside the
orphan row in the wiki section, capped and elided like every listing,
and like orphans it is a finding, never exit 1 — the repair is judgment.
The dex-lint fix-list names it: append the id to each matching topic's
items, or ledger it into uncategorized-shares.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A media unit parked blocked/waiting/error rests untouched while
media_fetch is `none` — the drain defers every media job before spending
anything — yet the standing view and run report filed it under "Waiting
on the engine — N entries it retries by itself", with "attempt n of m"
promising retries that are switched off. What actually unblocks it is
the owner flipping the config.

The classification is a rendering fact, not a ledger one, so no status
changes: the row builder — _parked_row, the one place both surfaces'
rows are made and the one with the config in hand, since payloads are
self-contained by design — marks such a row `resting`, gives it the
reason that names the unblock ("media_fetch is `none` — stays parked
until it is turned back on", the drain's own note vocabulary), and drops
the attempt framing. The surfaces' ownership split reads the mark: a
resting row is the owner's, rendered under Needs you with no retry note.
`manual` media rows are excluded — they wait on the owner either way,
and turning media back on resumes nothing for them, so their stated
reason stands. Design §11's split account and vocabulary table updated
to carry the exception.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Template evolution across releases can replace a synced file with a
same-named directory, or fold a directory down to one file. Sync only
knew how to mirror content: mkdir(parents=True) over the standing file
raised FileExistsError, read_text over the standing directory raised
IsADirectoryError, and either one killed the whole sync — an instance
that could not take the release that shipped the change.

Inside the dex-* directories sync owns, the template is authoritative —
the rule the prune step already established — so a shape conflict is now
converged, not crashed on: the conflicting entry is removed, the removal
reported as a machinery change ("template ships a directory here now" /
"template ships a file here now"), and the copy writes the template's
shape. Both directions are handled, and a symlink is unlinked rather
than followed, as everywhere in sync. Non-dex trees are untouched, as
before: nothing instance-owned is ever removed to make room. All three
new tests crash the unfixed sync (FileExistsError on file→directory,
IsADirectoryError on the other two). Design §12's mirror account gains
the shape sentence.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leeovery leeovery changed the title fix3/e11 verification Detect every judgment step a session can skip Aug 23, 2026
@leeovery
leeovery marked this pull request as ready for review August 23, 2026 21:48
@leeovery
leeovery merged commit 0a45778 into main Aug 25, 2026
@leeovery
leeovery deleted the fix3/e11-verification branch August 25, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant