Development record
internal/core/site keeps a private fence toggle (sections.go isFenceLine, used by Sections, Blocks, and compose.go auditIsMet and releaseOf) that diverges from mdrecord.Mask, the tree's CommonMark reading, and returns wrong sections. isFenceLine matches any line whose trimmed text starts with three backticks and flips a boolean. So it never sees a tilde fence, closes a four-backtick fence on a three-backtick line, closes on a line that carries an info string, and cannot see an HTML comment. Probe at 70daf701 via Sections: a # line inside a ~~~ block becomes a section, and so does a # line inside a three-backtick block quoted in a four-backtick fence (both give sections Doc, a shell comment, Real). A heading parked in <!-- --> becomes the section Parked. An unclosed ~~~ fence is not refused, even though Sections refuses an unclosed backtick fence as its quietest failure. The same walk decides auditIsMet (a ~~~-fenced Acceptance rollup: MET 1 counts as a verdict, the failure iss-2609090951277880 closed for backtick fences) and releaseOf (a ~~~-fenced credit stamps a version). The fix is not a drop-in swap for mdrecord.Mask, because the site deliberately reads fences indented under list items and mdrecord recognises only the 0-3 space indent, so the indent rule needs a decision first.
internal/core/site keeps a private fence toggle (sections.go isFenceLine, used by Sections, Blocks, and compose.go auditIsMet and releaseOf) that diverges from mdrecord.Mask, the tree's CommonMark reading, and returns wrong sections. isFenceLine matches any line whose trimmed text starts with three backticks and flips a boolean. So it never sees a tilde fence, closes a four-backtick fence on a three-backtick line, closes on a line that carries an info string, and cannot see an HTML comment. Probe at 70daf701 via Sections: a # line inside a ~~~ block becomes a section, and so does a # line inside a three-backtick block quoted in a four-backtick fence (both give sections Doc, a shell comment, Real). A heading parked in becomes the section Parked. An unclosed ~~~ fence is not refused, even though Sections refuses an unclosed backtick fence as its quietest failure. The same walk decides auditIsMet (a ~~~-fenced Acceptance rollup: MET 1 counts as a verdict, the failure iss-2609090951277880 closed for backtick fences) and releaseOf (a ~~~-fenced credit stamps a version). The fix is not a drop-in swap for mdrecord.Mask, because the site deliberately reads fences indented under list items and mdrecord recognises only the 0-3 space indent, so the indent rule needs a decision first.
Grounds
- pursued: every document shape in the capture yields only its live sections under Sections (TestSectionsReadFencesAndCommentsByTheCommonMarkRule) and, from 7de521bc on, the site package's committed-corpus tests and the site-render gate pass over the committed corpus (at 7f46da18 alone site-render refused it); a phantom section, an unrefused unclosed span, or a counted fenced rollup or credit would show it wrong
Frontmatter
| id | iss-2609250955051598 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-2609250955051598-internal-core-site-keeps-a-private-fence.md
open on GitHub ↗ · commit history ↗
mentions3
- dcn-26092500000000012026-09-25 — One fence rule for the tree (the run A orchestrator's technical ruling for the fences lane, recorded by the lane implementer). `internal/core/mdrecord` is the tree's one notion of fences and HTML comments: `Mask` and `Unclosed` follow CommonMark for a top-level fence, and `Read(lines, rule)` is the single pass every reading goes through. It is extended once, by a `Rule`: `TopLevel` is CommonMark's top level, and `ListNested` also opens a fence indented four or more columns, which only a list item can hold, closes it within three columns of its opener, and ends it at a column-0 line (fenced code never continues lazily). A run at one to three columns is read by `ListNested` exactly as `TopLevel` reads it, because whether it sits in a list item turns on the list around it and mdrecord does not parse lists; a committed issue record quotes a frontmatter block in a top-level fence whose indented closer is followed by a column-0 line, and the list-item reading refused it. That reading is kept unexported and consulted by `FencedUnderEveryRule`, which masks a line only where every reading agrees. The site reads `ListNested` (it renders fences in list items) with comments masked and refuses an unclosed fence or comment; the lint rules read `FencedUnderEveryRule` with comments left visible, because a mask that hides prose misses a finding silently. The reading exclusion floor fails closed: its verifier does not share the redactor's site walk, reads a line as code only where every reading agrees, lets no comment hide a heading (comment text travels in the bundle, so an excluded heading inside a comment is refused, not redacted by guess), and refuses a fence either rule leaves unclosed. `TestNoSecondFenceRule` in mdrecord is the armed guard: it names any non-test Go file that writes a fence delimiter and keeps state across lines, its allowlist is empty, and a stale entry fails it. Captures resolved on this ruling: iss-2609250955207041, iss-2609250955051598, iss-2609250955209513, iss-2609251044055902, iss-2609251045302499.
- iss-2609090951277880auditIsMet was narrowed to read the Audit Notes section fence-aware and to refuse a negative count, but it still walks EVERY section whose title is Audit Notes and accumulates the met and not-met counts across all of them, with no first-wins rule and no refusal of a duplicate title. An intent record carrying an honest concerns-only rollup plus a second section with the same title, at any heading level, holding a rollup that reads MET 1 therefore ends with met above zero and not-met still zero, and is lifted onto the homepage feature block: exactly the outcome the fence-awareness was added to prevent, reached by duplication instead of by fencing. Verified by reading the accumulation loop, where the title comparison is an equality test inside a loop over all sections and nothing breaks after the first match. It matters because the record body is the input the site trusts for the one testimonial the homepage carries, and a forged section is no harder to write than a forged fenced line was. Fix direction: read the FIRST Audit Notes section only and treat a second one as malformed, the same way a negative count is already treated as malformed. Detector: an intent whose honest Audit Notes rollup is concerns-only, plus a second section titled Audit Notes carrying a passing rollup, must not be featured, while the same intent with one honest passing rollup still is. Residual of iss-2609081941073604.
- iss-2609250955207041The cold-reading exclusion floor can be walked through by a fence shape both of its halves misread the same way, so an excluded heading's section travels in the bundle and nothing refuses. redactExcluded finds headings through site.Sections, whose private fence toggle (iss-2609250955051598) flips a boolean on every line that starts with three backticks. verifyRedaction re-checks with bodyFenceMask, a second private backtick-only toggle, so the two agree on the wrong answer. Probe at 70daf701: a document holding a four-backtick fence that quotes a bare three-backtick line, then '## Private Notes' with a body line, then a ~~~ block holding a three-backtick line. redactExcluded with the heading Private Notes excluded returns nil error and the body line still in the output. Under CommonMark (mdrecord.Mask) the heading is live. The four-backtick block is one fence, and the three-backtick line inside the tilde block is literal. So the manifest asserts a refusal that did not happen, the silent-bypass class iss-2608301350533102 closed for a delimiter inside the frontmatter. The fix is not a one-line swap. Moving the verifier onto mdrecord.Mask would make it refuse this shape, but mdrecord also masks HTML comments, and comment text travels to the reader, so the floor's view of comments needs a decision.