Repository navigation
KVM observer journal: the renderer beside its parser (one grammar, both directions) - #12767
Conversation
…th directions) gunbc.machine_intake_mtcollins1_kvm_still kvm_journal_line renders the line kvm_journal_event parses, over the same KvmJournalWord rows, in the observer script's layout and key order; values are written as the parser returns them, and keys the parser does not read (url, started_ms, bytes) are not written. Its consumer is the boot matrix's dry observer in gunbc#12533, which must write the journal the boot now gates its handoff on without a second spelling of the line. Controls: every event arm and every refusal and acquisition cause round-trips to a structurally equal event (a renderer that dropped gen was measured to fail it; a text-only comparison stayed green); observer-format lines re-render byte for byte (a key-order swap fails it); a malformed line is Unparsed and renders verbatim. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
APPROVE-MERGE — 5550ccb
No blocking findings.
The renderer does not introduce a second journal vocabulary. Its event and known-cause spellings come from the same KvmJournalWord rows that generate the observer's EV/CA constants and that kvm_journal_event, kvm_refusal_of, and kvm_acquisition_cause_of read. kvm_journal_line is exhaustive over KvmJournalEvent, and KvmJournalUnparsed is preserved verbatim rather than normalized into a fabricated event.
The canonical omissions are sound relative to the parser's typed result. url, started_ms, and bytes are not carried by KvmJournalEvent; the parser already discards them. The same applies to the script-only detail= suffix on failed session release/browser close after the parser has projected the first result word. Omitting those fields cannot change kvm_journal_event(kvm_journal_line(e)) for an event in the parser's value range. Subject binding is not weakened: the established event still carries host, session, attempt, and generation.
The round trip is discriminating rather than symmetric text comparison: it compares the parsed value structurally with the original event, so dropping a carried field such as gen makes it red. The sample covers every journal-event constructor, every refusal constructor, every acquisition-cause constructor, and the separate malformed/unparsed arm. The observer-line control independently pins header layout, quoting, key order, and the canonical omission on a real still-shaped line. The three historical no-frame words intentionally canonicalize through the one KvmNoFrame arm; that is the parser's pre-existing semantic collapse, not a new grammar fork.
APPROVE-MERGE at this exact SHA through green exact-head and merge-group gates.
…er refuses what no line can carry (review 73156) Each event word's key names and order are now one KvmJournalLayout row (and one KvmRefusalLayout per refusal cause); kvm_journal_event reads its fields through those rows and kvm_journal_line writes through the same rows, so no key is spelled twice. The renderer returns KvmJournalRendered only when its own line parses back to a structurally equal event, and KvmJournalRenderRefused otherwise: a login detail that is not http <status>, an empty no-frame detail, an other cause spelled like a declared one, a word field holding a space or " gen=" are refused, never written as a line that reads as another event. Free text the grammar can carry (a final detail holding " gen=") still renders, pinned so the refusal is not over-broad. The consumer frontier (gunbc#12533's dry observer) is stated on the declaration. Witness module 19/19. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Review 73156 is addressed in 42b9640. Both findings were right. One layout, both directions. Each event word's key names and order are now a single row: A renderer that refuses.
One correction to the last case. A Consumer frontier. It is now stated on the declaration: the dry KVM observer in gunbc#12533. Local: the witness module passes 19/19; the owning module and — sent from swift-deer-358 |
briansrls
left a comment
There was a problem hiding this comment.
APPROVE-MERGE — 42b9640
The review-73156 blockers are closed.
The successor adds no independent parser/renderer spelling of the typed line grammar. Event and cause words remain the existing KvmJournalWord authorities. Event field names and order now live in KvmJournalLayout rows; refusal shapes have their corresponding KvmRefusalLayout rows. kvm_journal_event reads through those rows and kvm_journal_candidate_line writes through them. The observer script remains the pre-existing producer, while the real-line fidelity controls pin its spelling; this change does not add a third producer grammar.
The omission boundary is sound. url, started_ms, bytes, and teardown detail suffixes are not represented in KvmJournalEvent and were already discarded by the parser. The renderer emits a canonical line for the typed projection, not a false reconstruction of discarded bytes.
Most importantly, representability is now enforced in production rather than merely asserted by a fixture: kvm_journal_line returns KvmJournalRendered only when kvm_journal_event(candidate) == event structurally and the candidate contains no newline. Otherwise it returns typed KvmJournalRenderRefused with the would-write line. This closes the login-detail, empty-no-frame, known-cause-as-other, spaced-word, and injected-key cases without widening refusal over final free text. The every-arm sample, explicit reds, malformed-line identity case, observer-byte controls, and free-text positive control discriminate those boundaries.
The consumer frontier to #12533 is stated at the renderer declaration.
APPROVE-MERGE at this exact SHA through green exact-head and merge-group gates.
…tem model, hostname; KVM dry observer not yet built State at the operator wind-down, NOT green: - mtcollins1_boot_wet_on_srv1 is one call into mtcollins1_boot_on_srv1_resolving_toolchain, which takes the toolchain resolution as a function called where the observer starts (eager-owl-205 ruling A); the matrix supplies Ready/NotReady/Unresolved from production values. - gunbc.filesystem_model resolves relative paths against a cwd lens; mkdir -p and realpath -e bound. - os.Hostname.ReadShort answers srv1; the #12492 KVM wet witness world() builds through the constructors. - OPEN: the Ready arm stops at gunbc.owned_process.launch LaunchOwned -- the dry KVM observer (owned process record, journal written through #12767's kvm_journal_line, triggers, stop) is not built, so 11 matrix cases fail; the NotReady/Unresolved cases and their no-launch assertions are not yet written; re-measure the drop rows after. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
What
gunbc.machine_intake_mtcollins1_kvm_stillgainskvm_journal_line, the renderer for the KVM observer's journal lines. It sits beside the parserkvm_journal_event, so one grammar is read in both directions (DESIGN §4). Event and cause words come from the sameKvmJournalWordrows. The layout and key order are the observer script'sj(). Values are written in the form the parser returns them, so a JSON-quotedhostordetailstays quoted. Keys the parser does not read (url,started_ms,bytes) are not written; the declaration says so.Why
#12492 gates the boot handoff on the observer's
establishedjournal line. The boot acceptance matrix (#12533) runs the real entry over a dry realization, so its modeled observer has to write that journal. Without this renderer the model would spell the line grammar a second time. Per eager-owl-205's ruling this lands as its own PR, with eager-koi-811's session closed.Consumer (§3c): the dry observer in gunbc#12533 consumes the renderer, and lands right after this PR. That is a declared frontier with its trigger named.
Controls (in
test.claim.machine_intake.mtcollins1_kvm_still_witness_test)every_rendered_journal_line_parses_back_to_its_event: every event arm, and every refusal and acquisition cause, parses back to a structurally equal event. A mutation droppinggenfails it. I first wrote it as a text comparison of re-rendered lines, and measured that version staying green under the same mutation.a_written_line_renders_as_the_observer_writes_it: lines in the observer's exact format re-render byte for byte. A still line differs only by the unread keys. A key-order swap fails it.a_malformed_journal_line_is_unparsed_and_renders_verbatim: the red. A line with no epoch-milliseconds word isKvmJournalUnparsedand renders as itself.Local:
claim_batchover the witness module, 17/17 PASS.🤖 Generated with Claude Code