Uh oh!
There was an error while loading. Please reload this page.
fix(spec): make check:skill-examples' marked-block extraction fence-aware - #11689
Merged
Conversation
…ware The orphan-marker scan learned to ignore an `os:check` marker shown as example text inside a wrapping fence, so this gate's own convention could be documented in the roots it governs. The extraction loop was deliberately left out of that fix and kept recognising a bare ```ts / ```tsx / ```typescript fence-open line wherever it appeared, with no notion of sitting inside another fence. A marker ALONE nested in an illustration was therefore handled correctly, while a fully worked one -- marker AND a real ts fence, both example text inside a wrapper -- was extracted and handed to tsc as a genuine example: compiling by luck, or failing the whole gate against documentation prose. Both loops now read one `fenceOwners()` walk, which records per line which top-level fence owns it: `owners[i] >= 0` answers the orphan scan's question, `owners[i] === i` answers extraction's. The extraction loop's fence-open pattern is a strict subset of the CommonMark one the walk uses, so a genuine top-level block always owns itself and the guard cannot suppress one. No corpus occurrence trips this, so the counts are identical either side of the fix (257 marked examples across 99 files, three surfaces). The self-test is where the defect is measurable: a nested worked illustration with deliberately uncompilable payloads extracts nothing, while the identical payloads with the wrapper removed all extract -- and the same pair is pinned inside a JSDoc gutter-wrapped docblock, where ownership must be judged on stripped lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rxnd8cyFnoU8V5y21PaTsy
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. |
This was referenced Aug 24, 2026
os-warren
marked this pull request as ready for review
August 24, 2026 13:21
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#11355
The gap
check:skill-exampleshas two loops over the same lines. #10791 made the orphan scanfence-aware, so a marker shown as example text inside a wrapping fence claims nothing — that
is what lets this gate's own convention be documented in the very roots it governs. It
deliberately left the marked-block extraction loop alone, so extraction still matched a
bare ts / tsx / typescript fence-open line wherever it appeared, with no notion of sitting
inside another fence.
A marker alone nested in an illustration was therefore handled correctly. A fully worked
one — the marker AND a real ts fence, both written as example text inside a wrapper — was
extracted and handed to
tscas a genuine example: compiling by luck, or failing the wholegate with a diagnostic pointing at documentation prose.
Triage ruling on the card (2026-08-24) chose option 1 of the body — share the fence walk —
and asked for the nested-illustration self-test on the #10533 precedent in
scripts/check-role-word.mjs. Option 2 (document the limitation) was not chosen.The fix
Both loops now read one
fenceOwners()walk — the same walk #10791 landed, returningwhich top-level fence owns each line rather than merely whether one does:
owners[i] >= 0— "this marker is inside a fence" — the orphan scan's question, semanticsunchanged from [finding] check:skill-examples flags an
os:checkmarker shown INSIDE a fenced example as an orphan, so the convention cannot be documented in the roots it governs #10791.owners[i] === i— "this ts fence opens at top level" — extraction's question.The extraction loop's fence-open pattern is a strict subset of the CommonMark one the walk
uses (three backticks plus an info string containing no backtick), so a genuine top-level
block always owns itself and the new guard cannot suppress one. Two independent notions of
"am I in a fence" in one file is how the halves drifted apart in the first place, so there is
now only one.
Verification
Local, all at
478b817e6with a clean tree.Consumer duty — the gate against the real corpus, before and after. Byte-identical apart
from the self-test's own success line (which now names the new pinned behaviour); no corpus
occurrence trips this, exactly as the card predicted:
Where the defect is measurable: the self-test. Reverse-verified from the committed state
by deleting only the guard line (
perl -i, restore armed as atrapbefore the edit).Mutation proved on disk by anchored counts — deleted text 1 → 0, neighbouring anchor 1 → 1,
1846 → 1845 lines — and restoration proved byte-identical (
git hash-objectequals the HEADblob,
git status --porcelainempty). No build is interposed in either leg: the gate runs astsx scripts/check-skill-examples.ts, straight off the source, and the self-test half neverreads
distat all. Ablated, the self-test goes red naming the defect:Those two poison payloads are precisely what would have reached
tsc. Restored, exit 0.The un-nested control passes in both legs, deliberately: it is what proves the nested red
comes from the nesting and not from the payload or the marking (the #10533 (B3) shape). Both
poison payloads also sit after an inner close but before the wrapper's own, so a length-blind
closer surfaces as a second extracted block rather than as silence. The third fixture repeats
the pair inside a JSDoc-gutter-wrapped docblock — nothing else would catch ownership being
computed over raw instead of gutter-stripped lines, which would return the defect on exactly
the roots whose prose lives in docblocks.
Gate families — derived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackfrom the real change set (not a hand-written path list). All 18 matched families green, plus
check:nul-bytesandpnpm --filter @objectstack/spec typecheck(which is what type-checksscripts/**, viacheck:scripts-typecheck).One family is red for a reason that is not this diff:
check-dev-prereqsreports "Theworkspace is not built". It measures workspace build completeness — this worktree built only
the
@objectstack/client-react...closure the gate needs. Run against the pristine sharedcheckout, which carries none of these changes, it fails the same way and harder (67 of 67
packages unbuilt, versus 34 of 67 here). CI builds the workspace before gates.
Notes
skip-changesetlabel: the changeset check is path-blind(any PR with no newly added
.changeset/*.mdfails), and every prior change to this gateshipped a
@objectstack/specpatch changeset. The label remains the PM's call.packages/spec/scripts/check-skill-examples.tsplus itsself-test, which live in the same file, and the changeset. No fixture content was copied
from the card's rendered body — the body carries a live specimen of this very trap and its
own illustration is mangled by GitHub; all fixtures are constructed in code.
Generated by Claude Code