Skip to content

Add reopen edges and decision screen rendering - #41

Merged
Hafeok merged 5 commits into
mainfrom
claude/revisit-if-edge-type-e9q8fl
Aug 13, 2026
Merged

Add reopen edges and decision screen rendering#41
Hafeok merged 5 commits into
mainfrom
claude/revisit-if-edge-type-e9q8fl

Conversation

@Hafeok

@Hafeok Hafeok commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the reopen edge feature (format 4/7) and the ledger show command for rendering decision screens. This settles the watched-edge question from the basis-quality re-typing session by making reopen edges a distinct type, separate from ground bases, with their own scanning and reporting paths.

Key Changes

Core reopen edge support:

  • Added revisit_if field to ledger VersionRaw (format 4) and ddd Decision (format 7)
  • New RevisitRef and RevisitEdge types to represent reopen pointers structurally separate from bases
  • Reopen edges are pinned (like bases) so they are detectable when claims move
  • Separate scanning pass (reopen_scan) that never sees based_on, ensuring fired tripwires don't report as basis loss

Decision screen rendering (ledger show):

  • New show module with Screen struct carrying hashed content, both edge kinds kept apart, filing act, and acceptance situation
  • BasisText trait for resolving pointer arguments; NoText implementation for bare pointers
  • Selector enum (One, Set, Group, All) for covering multiple decisions in one pass
  • Group enum (Mechanical, Individual) derived from discharge, never hand-listed
  • Terminal rendering in show_render with aligned block output; JSON serialization via struct directly
  • CLI integration: ledger show command with --decision, --set, --group, --json flags

Ledger format evolution:

  • Format 4 (spec v1.5): adds revisit_if field, hashed when present, omitted when absent
  • No CANONICAL_FORM bump; every existing digest unchanged; file gate's ten classes unchanged
  • Updated format migrations and validation to support format 4

DDD format evolution:

  • Format 7: adopts the reopen edge shape from ledger format 4
  • Decision struct gains revisit_if: Vec<RevisitEdge> field
  • Separate why rendering for reopen edges under their own heading

Reporting:

  • LedgerSection gains reopened list and reopen_checked count, separate from pin_drift
  • ddd report shows fired reopen edges distinctly from basis loss
  • New Reopened struct in ledger gate for reporting

Testing:

  • New show_tests.rs covering screen assembly, edge separation, acceptance situation
  • New revisit_tests.rs for reopen edge firing, coverage, gate separation
  • New sign_tests.rs split from tests.rs (signing verbs: accept, revoke, supersede)
  • CLI integration test ledger-cli/tests/show.rs for end-to-end screen rendering
  • Acceptance worksheet (docs/acceptance-worksheet-2026-08.md) documenting the 80-entry pass

Seam declarations:

  • 33 new seam declarations for transcribed entries (mechanical group)
  • Seam declarations for show.rs, revisit.rs, show_render.rs, basis_text.rs, inspect.rs, and CLI command surfaces

Notable Implementation Details

  • The screen is a projection, never an instruction: it says what the decision is and what its state is, and names the command that would sign it. Filing the signature is the principal's act.
  • Reopen edges are never a basis: a decision does not rest on the claim, but the claim's death reopens the decision. This is enforced structurally—the basis-loss scan reads only based_on.
  • Weight class (Group) is derived from discharge, not hand-listed, so it cannot go stale as entries are added.
  • Basis argument text is resolved through BasisText trait, keeping ledger-core free of adopter ontologies.
  • The two edge kinds (ground and reopen) are kept apart in rendering: they never share a block, so a reader sees the distinction clearly.

https://claude.ai/code/session_01YXS9qyjKVanMXnpwCJpwJm

claude added 5 commits August 13, 2026 09:18
The principal ruled (2026-08-13) that a watched-not-grounding edge is a
distinct edge type, not a basis: this claim's death reopens the decision;
it is not the decision's ground. It is filed as its own edge with its own
vocabulary, never inside based_on, so neither the basis-loss scan nor
`why` reads it as ground — and a status movement on a revisit_if edge
produces a reopen finding, not a basis-loss finding.

The cross-repo basis-ref amendment has not landed and is not in flight
(only open PRs are #40 and a stale #10), so this is its own amendment at
the current version: ledger spec v1.5 / format 4, adopted by .ddd at its
format 7 — one shape, specified in the ledger format first. The L6
signing revision renumbers a third time, to spec v1.6 / format 5.

Format: revisit_if is an optional hashed list on a version, its own type
(RevisitRef, never BasisRef), canonicalised under its own key. Absent on
every prior version, so no digest moves, no acceptance is invalidated,
CANONICAL_FORM stays v1, and the file gate's ten classes are unchanged —
resolution is a consumer's business at L0, as it is for every discharge
scheme. Guarded by a canon test: one token as ground and the same token
as a reopen edge are different content.

Reporting: `ddd report escapes` gains a fourth section with its own
heading and its own message; the ledger pin scan retires the `watched:`
marker outright, so a stray one can never surface as basis loss again,
and reads revisit_if into a separate Reopened list. `ddd why` renders the
edges under their own heading, below the ground and visibly apart.
.ddd format 7 gates the field: format-declared, always pinned, and never
the same claim as a basis — an edge read both ways is the conflation the
distinct type exists to end.

`ledger show` lands with it: one screen per decision — hashed content,
both edge kinds kept apart, the filing act, the acceptance situation —
with --json, a --set/--group selector so a pass over 79 entries is one
invocation rather than 79, and each edge's argument text rendered under
its pointer. The weight class (mechanical | individual) is derived from
the discharge, never hand-listed, so the grouping cannot go stale.
ledger-cli gains a display-only ddd-core dependency for that argument
text; ledger-core stays ontology-free, taking the resolver as an input.

Gates green: cargo t, the documented clippy gate, ddd validate (222
entries), ledger verify (196 entries, 91 decisions). The 33 clippy errors
under --all-targets pre-date this branch on main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXS9qyjKVanMXnpwCJpwJm
Each is a re-decision of that entry's edge, filed for the principal's
acceptance — not a silent rewrite. In `.ddd` the claim moves out of
based_on into revisit_if at format 7, pin carried across unchanged
(status, changed, and the content hash M8 recovered at that pinned state);
in the ledger a new version re-takes the ddd-content pin at the entry's
new content and states the reopen edge. Prior versions keep signing
exactly the historical content they named.

  DDD-adapter-02  dec/ddd/internal-not-surface   projected@2026-08-06
  DDD-gates-01    dec/rust/no-unwrap             reported@2026-08-06
  DDD-adapter-01  dec/ddd/m6-proceeds-no-flip    projected@2026-08-02

The third is the one whose pin has drifted, and the drift was deliberate —
the claim moved projected -> reported -> established and was looked at
twice. It moves out of the basis-loss list and into the reopen list, which
is the correction the ruling makes: that decision's ground is the
principal's stated default and has never moved. The other two are unmoved
and do not fire. The two genuine basis losses stay where they were.

The ontology question the M8 migration filed (question/ddd/watched-edge-
kind) gets a version recording the ruling; the earlier version stated the
open question and remains what it always said.

Not migrated, and blocked rather than forgotten: the provenance audit's
one upstream watched-not-grounding row — workspace-member-delivery
tracking the What/How vocabulary. revisit_if gives the relation a home; it
does not give a cross-repo pointer one. Recorded as §10.4 of the audit.

Two gaps closed on the way: the ledger section of `ddd report escapes`
prints reopens on their own lines, and the L2 graph carries the edge under
its own predicate (ledger:revisitIf) — a query walking ledger:basedOn is
asking what a decision rests on, and a reopen edge is not an answer.

`ledger revise` gains --note (the reason for a re-decision belongs where
the filing is read) and `ddd content-hash <id>` prints the pin a ledger
entry must state — M8 computed these inline and hard-coded them, leaving
anyone re-deciding an entry afterwards without the number.

Gates green: cargo t, the documented clippy gate, ddd validate (222
entries), ledger verify (200 entries, 91 decisions), index rebuilt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXS9qyjKVanMXnpwCJpwJm
DDD-gates-02 (projected): a pipeline of sequentially-gated CI steps
reports what broke first, not what it did not check. Verified against the
tree rather than taken on report — main at 75b5472 carried two defects and
showed one: 9df74c1 added `note` to AddArgs and updated one of four call
sites, so the test targets did not compile and CI stopped there; behind
that, ledger-core/src/author/tests.rs sat at exactly the 400-line ceiling
and went to 402 once the call sites were fixed. The second gate failure
was found by hand (7258af1), not by the gate.

The sharpest part of the finding is that the repo already fixed this
failure mode one level down and did not carry it up: `cargo t` is
`test --no-fail-fast` precisely so one failing binary cannot hide the
rest, while the nine steps of product-ci.yml each run under the default
`if: success()`.

Family recorded in the entry: the M6 leakage prediction and L3's
cross-file merge finding — a mechanism guarding the path it can see,
blind to what sits behind it.

The falsifier is two negative results a future run can genuinely produce,
both about whether the hazard is real: that no red run's skipped steps
would have failed on their own, or that the 75b5472 case is re-graded.
Drafted so the remedy cannot fire it — fixing the pipeline changes what
future runs report and says nothing about whether past masking hid
anything. A claim its own remedy kills is the self-sealing defect
DDD-method-07 names.

The remedy is filed as a decision awaiting the principal's acceptance and
is NOT implemented here: independent gates run anyway, or — the floor,
where a step genuinely depends on a failed one — the run reports which
gates did not execute. Allocated as a judgment, honestly: nothing checks
the arrangement, so holding to it rests on a person, and a criterion would
name a discharge resolving to no checker. Cost of the follow-up stated in
the entry: a red build stops failing fast and pays each independent gate's
runtime, the benchmark step most of all.

The claim edge is genuine ground and sits in based_on, not revisit_if —
if the instance is re-graded away the decision loses its reason. First new
use of the distinction the 2026-08-13 ruling draws.

`ledger add` gains --note for parity with revise.

Gates green: cargo t, the documented clippy gate, ddd validate (224
entries), ledger verify (202 entries, 92 decisions), index rebuilt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXS9qyjKVanMXnpwCJpwJm
docs/acceptance-worksheet-2026-08.md: grouping and flags only, since
`ledger show` is now the read. It says plainly that where the two
disagree, `ledger show` wins — it is derived from the log and the
worksheet is written by hand.

Group A is the 33 transcribed seam declarations, and the claim that they
are one shape is checked rather than asserted: all 33 are criterion / pr,
one contract: discharge, one ddd-content: basis and nothing else, no
reopen edge, T1, first version, all filed by the M8 migration on
2026-08-12. What is being ruled once for the group is that the
transcription is faithful. Group B is the 47 individual reads, partitioned
into five sub-groups that sum to 47 — with the overlap named rather than
double-counted: three of the seven re-typed bases are also the revisit_if
conversions, so one screen carries both rulings.

Flags: interceptor-not-extension is held, its basis still
indeterminate:DDD-arch-03 pending the F-7h ruling. Nothing is
mid-migration — the three conversions and the ruling record all landed as
complete versions — and the worksheet says so rather than leaving the
absence to be inferred. The audit's upstream row is noted as blocked, not
in the pass at all, because nothing is filed for it.

Uniform T1 confirmed across all 80: not one tolerance_override, so the
floor was pinned rather than chosen and the grouping is doing the work the
tier would otherwise do. One genuine T2 case proposed, not applied: the
priced escape over 24 undeclared What boundaries and its decision — the
one pair that knowingly carries exposure, and the first L6 signing would
bind. typed-basis considered and declined as tier inflation. The cost of
acting on the proposal is stated: revise has no --tolerance-override
today, and raising the set floor instead strands every member below it.

The sequence names the L009 trap first — accept takes the acceptor from
git config and L009 checks it against the commit author — and is honest
about the loop: the format has no group-acceptance primitive, so the loop
records one judgment 33 times rather than making 33. The wall-clock table
says why the number matters: it is the acceptance-latency instrument's
first reading and L5's requirements input, and a null result is as useful
as a positive one.

ledger-cli/tests/show.rs exercises the screen through the binary — the
ruling is about what a reader sees, so ground-and-reopen-never-share-a-
block is asserted on rendered output, plus the format-4 declare-what-you-
need rule, the selectors, and the two refusals (unknown id, two selectors
at once).

Gates green: cargo t, the documented clippy gate, ddd validate (224
entries), ledger verify (202 entries, 92 decisions).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXS9qyjKVanMXnpwCJpwJm
129 contract-surface events over 15c6352..HEAD, all now discharged by
signed bindings: 124 filed by `ddd bind`, across 15 freshly created
declarations and 11 existing ones.

Every new declaration carries real verdict_knowledge — what a reviewer
learns at that boundary, and where it applies, what the boundary cannot
do. The two that matter most say the ruling out loud: ledger-core's
version.rs boundary states that based_on and revisit_if never merge (two
fields, two hash keys, two types, and a caller reading either as the other
would report a fired tripwire as a lost basis), and ddd-core's revisit.rs
boundary states that a reopen edge always pins, that a claim is ground or
tripwire and never both, and that firing means a fresh look is due rather
than that the ground moved.

show.rs's boundary states its own limit honestly: ledger-core resolves no
basis argument itself, it takes a BasisText resolver as an input, and with
NoText the pointers render bare — which is what keeps the substrate an
outside implementation imports free of any adopter's ontology.

Gates green: cargo t, the documented clippy gate, ddd validate (239
entries), ledger verify (202 entries, 92 decisions), xtask check (0
errors), ddd diff-contracts over 15c6352..HEAD (129 events, 0
undischarged).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXS9qyjKVanMXnpwCJpwJm
@Hafeok
Hafeok merged commit 576efaf into main Aug 13, 2026
6 checks passed
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.

2 participants