docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2) - #5967

Merged
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2
Aug 24, 2026
Merged

docs(guides,tooling): clear four .md pages off the doc-snippet ledger (#5174 batch 2)#5967
yinlianghui-tw merged 1 commit into
mainfrom
claude/issue-5174-md-ledger-batch2

Conversation

@yinlianghui-tw

@yinlianghui-twyinlianghui-tw commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Part of #5174 — batch 2. The card stays open: 5 .md guide entries remain after this.

What this does

Walks four pages off UNGATED_DOCS in scripts/check-doc-snippet-types.mjs, clearing the 89 diagnostics they were carrying.

pagediagnostics clearedhow
content/docs/guide/plugins.md2010 fragments declared, 2 blocks already compiled
content/docs/guide/building-crud-app.md217 fragments, 2 blocks fixed, 2 already compiled
content/docs/rfcs/0001-clipboard-paste.md237 fragments
content/docs/guide/architecture.md2510 fragments, 2 blocks fixed
total8934 fragments · 8 compiling (4 of them after an edit)

Ledger entries 53 → 49. Covered documents 169 → 173. 42 blocks newly under the gate.

Every page reached zero the two honest routes only — a block that should compile made self-contained against the built dist/, or a FRAGMENT_MARKER with a written measured reason for one that genuinely cannot. There is no third route in this diff.

Three real documented-API defects the ledger was hiding

These are why covering guide/architecture and building-crud-app was worth doing rather than declaring them wholesale:

  1. building-crud-app.md — the guide's RestDataSource passed QueryParams['$orderby'] straight into URLSearchParams.set. $orderby is a four-shape union (an OData clause string · a Record mapping field name to 'asc'/'desc' · string[] · an array of sort objects) and set takes a string (TS2345). Narrowed to the string form with a comment saying why, rather than stringifying a shape the server cannot parse.
  2. building-crud-app.md — the TaskDetail component used SchemaRenderer with no import of its own. A reader copying that block got TS2304.
  3. architecture.md — the section titled Type Safety, with the line marked // ✅ Type-checked, set ButtonSchema.onClick to the string'handleClick'. The declared type is a zero-argument function returning void or a promise of it (TS2322). The block now declares a handler and passes it.

The fourth edited block is architecture.md's step-2 renderer example, which referenced a schema defined only in the step-1 json fence; it now carries that schema as a typed BaseSchema constant, so the block is copy-pasteable.

The pages that are mostly fragments are mostly fragments for a stated reason: guide/plugins and the clipboard-paste RFC document a package the reader is being taught to create, and an RFC's signature excerpts have no bodies by design. Every marker names which of those it is.

The four binding invariants, measured

Diffed programmatically between origin/main's copy of the script and this branch's copy:

invariantmeasured
covered set strictly grows169 → 173 documents
⛔ no previously-covered document becomes ungatedADDED ledger entries: [] — and previously-covered docs that are now UNGATED: []
surviving entries keep measured reasonssurviving entries with a non-measured reason: [] (49 checked)
⛔ gate strictness never movesproven byte-for-byte, below

REMOVED entries: is exactly the four pages named above and nothing else.

Strictness proven byte-for-byte, not argued. Everything from the // ── Fence scanning banner to EOF — scanFences, listDocuments, derivePackageTypePaths, analyze, compileSnippets, the reporting and main — is byte-identical to origin/main (475 lines). DOC_EXTENSIONS, TS_FENCE_LANGUAGES, FRAGMENT_MARKER, MIN_REASON_LENGTH and COMPILER_OPTIONS each hash identical. The entire script diff is the four removed ledger entries plus the ledger's own docblock prose: 27 insertions, 34 deletions.

CI cost under the #4846 ruling — stated, not absorbed

--build-filter grew 19 → 20 filters (@object-ui/plugin-dashboard, pulled in by exactly one line: guide/plugins.md's import '@object-ui/plugin-dashboard').

Turbo build tasks stayed 33 → 33, and the two task sets are identical package-by-package from --dry=json (tasks ADDED: [], tasks REMOVED: []) — the new filter was already in the closure as a transitive dependency. Four more covered pages cost this gate zero extra build tasks. Nothing here for the maintainer to weigh.

(The real turbo run build reports 32 where --dry=json reports 33: the difference is @object-ui/test-support#build, which the dry run enumerates but which carries no build command. Both sides of the before/after comparison were measured the same way, so the delta of zero is unaffected.)

Verification

All at 41addc61a, working tree clean and byte-identical to what is pushed, union re-run after that commit, from the repo root, against a build of the gate's own filter closure (32 tasks, all successful, serialised through the container's shared heavy-verify entry point). Exit codes captured before any pipe; each line quotes the gate's own printed verdict.

  • node scripts/check-doc-snippet-types.mjs → exit 0. Scanned 222 document(s): 173 covered (37 of them hold a ts/tsx block), 49 ungated · Covered blocks: 203 — 135 to compile, 68 declared fragment(s). · Syntax phase: every block parsed, so every one of them reached the semantic phase. · Semantic phase: 135 of 135 block(s) judged, 0 failed. · Every covered documentation snippet compiles against the built types. Controls green: resolution landed on packages/types/dist/index.d.ts, sentinel produced TS2305, positive control 0 diagnostics.
  • scripts/__tests__/check-doc-snippet-types.test.tsTest Files 1 passed (1) / Tests 20 passed (20). Running the script is not running its test; both were run.
  • check-doc-component-types → exit 0, Every documented component type is registered. (183 doc files, 1056 code blocks)
  • check-doc-links → exit 0, Links are valid across 13 scan roots.
  • check-control-bytes → exit 0, OK (scanned 4950 tracked text file(s); skipped 85 binary), plus a manual control-byte grep over all five changed files: no hits.
  • check-lint-coverage → exit 0, 46/46 packages linted, 0 with outstanding errors.
  • Root eslint (the exact lint:root invocation) → exit 0, 0 errors, 26 warnings, all pre-existing; the one changed .mjs reports errorCount 0, warningCount 0.
  • pnpm check (the CLI self-check the Lint workflow runs) → exit 0, Analyzing 615 files... ✓ All checks passed.

Changeset: none owed, and no label.node scripts/check-changeset-presence.mjs → exit 0: "5 file(s) changed, 0 of them under the src/ of a package the release covers … No source of a released package changed in this range, so no changeset is owed." Followed its verdict. ⛔ No skip-changeset label was applied: that label is not a mechanism in this repo — objectui#3724 established it was documented by a since-deleted second workflow inventory and "neither the workflow nor the label was ever real", a fact scripts/__tests__/ci-cd-pipeline-doc.test.ts still pins. check-changeset-no-major → exit 0.

Lint scope, declared. The root eslint task was run whole, not narrowed. Its population is read from eslint's own config via --format json: 166 files, of which 0 are .md — linting a changed .md directly answers File ignored because no matching configuration was supplied, so four of the five changed files are outside eslint's population by its own configuration. The other 46 per-package lint tasks are scoped to packages/*/, apps/*/ and examples/*/, which this diff does not touch at all.

Fragment markers re-verified rather than inherited.fumadocs-mdx 15.2.3 selects the compiler format by extension (filePath.endsWith(".mdx") ? "mdx" : "md", read from its own dist, two call sites). All four changed .md files were then compiled through @mdx-js/mdx 3.1.1 in format md: all four compile, and doc-snippet occurs 0 times in every compiled output against 34 occurrences in source.

Reverse verification — prediction written before each run, direction included

No build artifact sits between the mutation and the thing under test on either leg: the mutation is markdown the gate reads straight from disk, and the dist/*.d.ts it compiles against is untouched, so no rebuild was needed. Each leg proved the mutation reached disk by grepping the specific text meant to change — never an editor's exit code — and each carried a trap … EXIT INT TERM restore.

Leg 1 — revert architecture.md only, keep its ledger removal. Predicted: exit 1; exactly 25 diagnostics, all on that page; fragments 68 → 58; blocks-to-compile 135 → 145; the two edited blocks fail again as TS2322 and TS2304; NOTE printed; direction MORE findings. Observed: exit 1; 25, all on that page; Covered blocks: 203 — 145 to compile, 58 declared fragment(s); TS2304: Cannot find name 'schema' and the TS2322 on onClick (string not assignable to the handler type); NOTE printed. Match including direction.

Leg 2 — revert all four pages, keep all four ledger removals. Predicted: exit 1; exactly 89 diagnostics split 20/21/23/25; fragments 68 → 34; blocks-to-compile 135 → 169; NOTE printed; direction MORE. Observed: exit 1; 89 exactly, split 20 plugins / 21 building-crud-app / 23 clipboard-paste / 25 architecture — matching the baseline to the unit and per page; Covered blocks: 203 — 169 to compile, 34 declared fragment(s); Syntax phase: 7 block(s) failed to parse; NOTE printed. Match including direction.

Restore leg run, not skipped:git status clean, 34 markers back on disk, git diff HEAD empty, gate exit 0 with 135 of 135 block(s) judged, 0 failed.

Two dispatch measurements checked

What is left on this card

5 .md guide entries: plugin-development 25 · schema-rendering 27 · theming 29 · layout 45 · component-registry 59 = 185 diagnostics, plus 12 .mdx and 32 READMEs. layout and component-registry are 104 between them and are a batch of their own, as the batch-1 seat noted.

Generated by Claude Code

…#5174 batch 2)
Walks `content/docs/guide/plugins.md`, `content/docs/guide/building-crud-app.md`,
`content/docs/rfcs/0001-clipboard-paste.md` and `content/docs/guide/architecture.md`
off `UNGATED_DOCS` — 89 diagnostics, ledger 53 -> 49 entries, covered documents
169 -> 173.
Each page reached zero the two honest ways only: a block that should compile made
self-contained against the built `dist/` (8 blocks now compile, 4 of them after an
edit), or a `FRAGMENT_MARKER` with a written measured reason for one that
genuinely cannot (34 blocks). Nothing about the gate's strictness moved — the
whole mechanism half of the script is byte-identical to `main`.
Three real documented-API defects surfaced and were fixed rather than declared:
`building-crud-app`'s REST adapter passed `QueryParams['$orderby']` (a four-shape
union) straight into `URLSearchParams.set`, which takes a string; its `TaskDetail`
component used `SchemaRenderer` with no import of its own; and `architecture`'s
"Type Safety" section, marked `// ✅ Type-checked`, set `ButtonSchema.onClick` to
the string `'handleClick'` where the declared type is `() => void | Promise<void>`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
Sign up for freeto 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

@yinlianghui-tw@claude