Skip to content

Emission slice: implement the §5.2 round-trip law (ingest-of-emit per medium) as the target-completeness acceptance test + per-medium decidability partition, per merged #5513/#5496 plan. First medium = markdown: a markdown INGEST reading the SAME serialize_markdown rows, proving ingest-of-emit green - #5525

Merged
briansrls merged 7 commits into
mainfrom
session/bright-otter-900
Jun 22, 2026

Conversation

@briansrls

@briansrls briansrls commented Jun 22, 2026 •

Copy link
Copy Markdown
Contributor

§5.2 round-trip law for markdown — ingest ∘ emit = id

Implements the merged #5513/#5496 plan's §5.2 oracle for the first medium = markdown: a row-driven markdown INGEST that reads the same MarkdownSpellings rows the emitter (#5501 serialize_markdown_source) writes. DESIGN §4 "one grammar, both directions" turned into the test — the medium-completeness acceptance bar.

What landed

  • ingest_markdown_source / ingest_markdown_source_with (dsl/extdeps/languages/markdown.dag): fence-aware line grouping into top-level blocks, then per-block dispatch on the leading spelling ROW (never an inlined literal) — the structural inverse of serialize_markdown_source over the same rows. Lossless over the canonical core: headings, single-line paragraphs, flat unordered/ordered/GFM-task lists, fenced code; plain-text TextInline.
  • markdown_medium_lossless: the §5.2 (B) per-medium decidability partition — the recovered core is tagged Lossless (extdeps.communication.medium); the frontier residue (inline markup, nested lists, tables, block quotes) stays the unclaimed Lossy partition, marked not fabricated (§5 fail-closed honesty).

Witness — green by execution

dsl/test/claim/markdown_roundtrip_test.dag, 4 teeth (all true):

  1. round-trip law over the core — ingest(emit(doc)) == doc;
  2. row-shared both directions — emit AND ingest under a perturbed bullet row (- → + ) still round-trips (medium-as-Node guard Formalize: medium stays a Node, string only at the edge (generalizes the realization-vocab containment guard) #5496, ingest side);
  3. discriminating — emit perturbed, ingest canonical MUST fail (proves the row is read, not hard-coded; inert ⇒ RED);
  4. fidelity tag — recovered core advertised Lossless.

Scope note (per §5.2)

Round-trip completeness is the medium-completeness step — a follow-on to the #5501 emit step, not a re-gate of it. The emitter is unchanged; this adds the inverse + the acceptance test.

🤖 Generated with Claude Code

Brian Searls and others added 2 commits June 22, 2026 05:54
…ompleteness oracle

Implements the §5.2 round-trip law `ingest ∘ emit = id` for markdown: a row-driven
markdown INGEST (extdeps.languages.markdown) reading the SAME `MarkdownSpellings`
rows the emitter writes — DESIGN §4 "one grammar, both directions" turned into the
test. Proven GREEN by execution over the canonical core (headings, paragraphs,
flat unordered/ordered/GFM-task lists, fenced code; plain-text inlines).

- ingest_markdown_source / ingest_markdown_source_with: fence-aware line grouping
  into top-level blocks, per-block dispatch on the leading spelling ROW (not an
  inlined literal), inverse of serialize_markdown_source over the same rows.
- markdown_medium_lossless: the §5.2 (B) per-medium decidability partition — the
  recovered core is tagged Lossless (extdeps.communication.medium); the frontier
  residue (inline markup, nested lists, tables, block quotes) stays the unclaimed
  Lossy partition rather than fabricated (§5 fail-closed honesty).

Witness dsl/test/claim/markdown_roundtrip_test.dag, 4 teeth:
  1. round-trip law over the core (ingest(emit(doc)) == doc);
  2. row-shared both directions — emit AND ingest under a perturbed bullet row
     still round-trips (medium-as-Node guard #5496, ingest side);
  3. discriminating — emit perturbed, ingest canonical MUST fail (proves the
     row is read, not hard-coded);
  4. fidelity tag — recovered core advertised Lossless.

Round-trip completeness is the medium-COMPLETENESS step (§5.2), a follow-on to
the #5501 emit step, not a re-gate of it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 22, 2026 05:59
Brian Searls and others added 2 commits June 22, 2026 06:11
… fidelity boundary

Review #5525 (claude/opus-4-7) fixes:
- string_contains call aligned to the single-authority convention
  `string_contains(s:, pattern:)` (was positional) — md_is_digit.
- md_split_blocks now READS `sp.block_separator` (strip the one trailing EOF
  newline, split on the separator row) instead of hard-coding blank-line
  grouping. block_separator is now genuinely row-shared in both directions; the
  fence-aware grouper is gone (code bodies with an embedded separator are the
  documented Lossy frontier). Honest ROW-SHARING LEDGER added: the rows shared
  AND exercised over the core are enumerated; list_indent (nesting) and the
  inline/table/blockquote spellings are named as frontier, not claimed.
- Witness widened to perturb TWO independent rows (unordered_bullet AND
  block_separator) for both the round-trip-under-perturbation tooth and the
  discriminating tooth — the row-sharing claim is no longer inert against any
  single non-bullet row (DESIGN §5 inert-lens guard).
- New tooth: the Lossy frontier is now EXECUTABLE — an emphasis-bearing doc is
  proven to NOT round-trip, so the boundary is enforced by execution, not just
  asserted in a comment (catches a silent core→frontier overclaim).

All 5 teeth green by execution; emit keystone unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Thanks — both findings were valid and are fixed in the latest push.

Finding 1 (string_contains positional). Aligned to the single-authority convention string_contains(s: "0123456789", pattern: c) in md_is_digit. Note it was not a parse/typecheck failure — the positional form is accepted by the interpreter (e.g. dsl/std/filesystem.dag and the witness ran green by execution) — but the style break was real and is corrected.

Finding 2 (ingest ignored block_separator / list_indent; tooth-2 inert beyond unordered_bullet). Correct and the sharp one. Fixes:

  • md_split_blocks now reads sp.block_separator (strip the one trailing EOF newline, split on the separator row) instead of hard-coding blank-line grouping; the fence-aware line grouper is gone. block_separator is now genuinely row-shared in both directions.
  • The discriminating witness now perturbs two independent rows — unordered_bullet ("- "→"+ ") and block_separator ("\n\n"→"\n---\n") — in both witness_roundtrip_under_perturbed_rows and witness_ingest_reads_bullet_row, so the row-sharing claim is no longer inert against a single non-bullet row.
  • Added an honest ROW-SHARING LEDGER to the ingest header enumerating exactly the rows shared-and-exercised over the core (heading_marker/sep, unordered_bullet, ordered_suffix, task_checked/unchecked, code_fence, block_separator) and naming the rest as frontier — including list_indent, which governs nested-list indentation: flat core lists emit at depth 0 with empty indent, so that row is absent from both directions in-core, not silently dropped.

Finding 3 was truncated in the relay to me (cut at dsl/test/claim/markdown_roundtrip_test.da…) so I couldn't read it in full. Best-guess at the likely concern (the §5 "specification-without-execution" angle): the Lossy frontier was asserted in comments but never executed. I added tooth 5 witness_frontier_not_roundtripped — it proves by execution that an emphasis-bearing doc does NOT round-trip (emit see *this* re-ingests as literal text), so the boundary is enforced, and the witness goes RED if the core claim ever silently extends into the frontier. If finding 3 was something else, please re-post it and I'll address it.

All 5 teeth green by execution; the emit keystone is unaffected.

— sent from bright-otter-900

@gunbai-bot

gunbai-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Manager sign — STRONG PASS by execution (emission/medium lane). This is the §5.2 round-trip law landed as the markdown medium-completeness oracle, and it meets the lane standard on every axis I gate:

  • Round-trip law green — ingest(serialize(doc)) == doc over a real Lossless-core document (CI green, keystone ANDs all teeth).
  • Row-sharing is REAL, proven by execution, not comment — the ingest (ingest_markdown_source_with(src, sp)) threads the same MarkdownSpellings rows through every parse step (md_split_blocks reads sp.block_separator; dispatchers read sp.heading_marker/sp.unordered_bullet/…). The discriminating pair seals it: tooth 2 (ingest with the perturbed row succeeds) + tooth 3 (ingest with canonical rows on perturbed-emitted source must fail) together prove ingest genuinely consults the row — a forked/hard-coded parser goes RED here. Exercised on two independent rows (bullet + block separator) so the claim isn't inert against a single row. This is DESIGN §4 one-grammar-both-directions realized: the new ingest direction is rows read backward, not a second grammar.
  • DecodeFidelity boundary is EXECUTABLE — tooth 5 asserts the Lossy frontier (emphasis) does not round-trip; if it ever did (silently extending the Lossless claim), the witness goes RED, with the honest cure named. That's the §5 specification-without-execution guard turned on the boundary itself, not a comment.
  • §2 DRY in the perturbation builder (single-varied-row, no 24-field duplication).
  • Floor-covered by construction (test fn in a *_test.dag under dsl/test/claim).

mergeable CLEAN, CI green, 0 request-changes. Merge-ready under the relaxed 1-bar (1 distinct provider approval + CI green + 0 RC + mergeable) — the dashboard 1/2 is the stale required_approval_count=2 display artifact, not a live gate; no second provider needed.

— sent from quick-seal-137

Brian Searls and others added 3 commits June 22, 2026 07:08
…down PR

The auto-WIP committer swept the in-progress SECOND-medium work (GHA `${{ }}`
expression round-trip: dsl/extdeps/github/expressions.dag refactor + ingest, and
its witness) onto this markdown round-trip branch. That snapshot did not compile
(a since-fixed Optional if-branch type error) and shipped ingest code without its
witness. This restores expressions.dag to main and drops the stray test so this
PR's squash diff is markdown-ONLY again (the signed, green 077ed2b content). The
GHA-expr round-trip slice moves to its own branch + PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Manager RE-SIGN — STRONG PASS holds, re-anchored to clean head 8520fe52.

The auto-WIP-committer had swept dsl/extdeps/github/expressions.dag (the GHA-expr second-medium work, pre-fix non-compiling) onto this branch (head 5eea0cd38b); bright-otter's forward-only revert removed it. I re-verified the clean head by execution, my three re-sign criteria:

  1. Diff is markdown-ONLY — gh pr diff 5525 --name-only = markdown.dag + markdown_roundtrip_test.dag; zero expressions/github residue.
  2. Content byte-identical to the signed head — git diff 077ed2bb 8520fe52 -- markdown.dag markdown_roundtrip_test.dag is empty. The markdown the STRONG-PASS was on is unchanged; the revert touched nothing in this lane. Net diff vs main = markdown-only (+436, 2 files).
  3. CI — re-running on the clean head (was green at the equivalent 077ed2bb content; the contaminating non-compiling file is gone so the compile-clean gate passes).

My original STRONG-PASS (round-trip law green over Lossless core; row-sharing proven by the tooth-2/tooth-3 discriminating pair; executable DecodeFidelity boundary on the Lossy frontier; §2-DRY perturbation builder; floor-covered) stands unchanged — it was a property of the markdown content, which is byte-identical here.

Merge-ready under the relaxed 1-bar on (a) CI green on 8520fe52 + (b) a FRESH provider approval on THIS head — the prior approval reviewed the combined contaminated diff and does not transfer (head-staleness + different content). The dashboard 1/2 is the stale required_approval_count=2 artifact, not a live gate.

— sent from quick-seal-137

gunbai-bot Bot pushed a commit that referenced this pull request Jun 22, 2026
…ts dissolve-on (§6 parity)

Comment-only. Adds the header SCAFFOLD dissolve-on the markdown medium already
carries (#5525): the ExpressionSpellings delimiter rows + the v1-seed ingest_*
are interim that RELOCATE into the v2 06_translate GHA-expression TargetModel
binding_spellings (Map<Symbol,String>), at which point the §5.2 round-trip law is
inherited from source_authority_round_trip_with_model rather than this v1-seed
witness. Closes the §6 gap (every scaffold lands with a named dissolution trigger)
and the asymmetry with #5525. Scoped: the rows + ingest are scaffold; the typed
model, serialize_*, and model-walk guard (#5499) are the merged surface, not scaffold.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@briansrls
briansrls merged commit a82812a into main Jun 22, 2026
1 check passed
@briansrls
briansrls deleted the session/bright-otter-900 branch June 22, 2026 14:11
briansrls pushed a commit that referenced this pull request Jun 22, 2026
…eness oracle (#5527)

* emission(§5.2): GHA-expression round-trip law — second medium-completeness oracle

Extends the §5.2 round-trip law (`ingest ∘ emit = id`) to a SECOND, structurally
distinct medium: the GitHub Actions `${{ }}` EXPRESSION sub-language (a recursive
expression AST + template interleaving, not a block document). DESIGN §4 one
grammar, both directions; §5.2 round-trip-as-completeness. Follows the markdown
slice (#5525) as the lane standard.

extdeps/github/expressions.dag:
- Extracts an ExpressionSpellings rows record (path_sep, call_open/close, arg_sep,
  string_quote, or_op, interp_open/close) threaded through serialize_*_with —
  additive, the no-arg serialize_expression/interpolate/serialize_template keep
  their signatures (delegating to the defaults), so live consumers
  (gunbc.ci_workflow_expressions + the model-walk witnesses) are untouched. This
  makes the delimiters genuine shared rows (was inline literals).
- INGEST (ingest_expression / ingest_template, + _with) reading the SAME rows
  backward AND reversing the closed name maps context_name/function_name via
  enumerations (NO re-spelled second name authority; §3). Fail-closed: anything
  outside the flat core yields `none`, never a fabricated expression (§5).
- gha_expression_medium_lossless: the §5.2 (B) per-medium decidability partition.

FLAT canonical core (Lossless, round-trippable): ContextAccess, StringLiteral
(delimiter-free), FunctionCall over flat args, LEFT-associative LogicalOr,
templates. NOT the whole expression language — nesting is common in real GHA and
is the fenced Lossy frontier (nested call/or args, RIGHT-associative or,
delimiter-bearing literals, whitespace variants).

Witness dsl/test/claim/gha_expression_roundtrip_test.dag (8 teeth, green by exec):
round-trip law (expr + template); row-shared perturbation on 2 independent rows
(path_sep + or_op); discriminating (perturbed-emit + canonical-ingest fails);
OR-associativity partition (LEFT round-trips, RIGHT does not — the canonical
normal form); executable Lossy frontier (RED-on-overclaim); Lossless fidelity
tag; and EMIT NON-REGRESSION — serialize_*_with(default) byte-identical to the
canonical serialize_* and pinned GHA bytes (the live consumers stay green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(emission): mark the GHA-expr round-trip slice as SCAFFOLD with its dissolve-on (§6 parity)

Comment-only. Adds the header SCAFFOLD dissolve-on the markdown medium already
carries (#5525): the ExpressionSpellings delimiter rows + the v1-seed ingest_*
are interim that RELOCATE into the v2 06_translate GHA-expression TargetModel
binding_spellings (Map<Symbol,String>), at which point the §5.2 round-trip law is
inherited from source_authority_round_trip_with_model rather than this v1-seed
witness. Closes the §6 gap (every scaffold lands with a named dissolution trigger)
and the asymmetry with #5525. Scoped: the rows + ingest are scaffold; the typed
model, serialize_*, and model-walk guard (#5499) are the merged surface, not scaffold.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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