Uh oh!
There was an error while loading. Please reload this page.
feat: gascity acceptance and cleanup (hy-sadjq) - #39
Merged
philcunliffe merged 1 commit intoMay 26, 2026
Conversation
Reframe gascity from "excluded and invisible" to "excluded from default activation but discoverable through the plugin catalog." Update test and smoke labels/comments to reflect that gascity absence in status is about the config scenario, not a blanket prohibition. Add catalog test for gascity contributions (source, commands, dataset, init preset, skill). Add detach coverage to the gascity smoke test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
philcunliffe
merged commit May 26, 2026
bf503c4
into
integration/hypaware-plugin-surfaces
6 checks passed
Uh oh!
There was an error while loading. Please reload this page.
philcunliffe added a commit
that referenced
this pull request
May 26, 2026
* chore: open plugin surface integration branch * feat: config-backed sink materialization (hy-9d39h) (#37) * feat: config-backed sink materialization (hy-9d39h) Add production runtime materialization for configured sinks, so daemon boot and CLI dispatch automatically instantiate sinks from config.sinks entries without manual kernel.sinks.instantiate() calls. - Add `fromProvider(provider, name, range)` to capability registry for provider-specific capability lookup - New `src/core/sinks/materialize.js` resolves writer/destination/encoder capabilities and calls sinks.instantiate() for all three sink shapes (request, blob, table-format) - Wire materializeSinks into daemon runtime (after plugin activation) and CLI dispatch (after boot) - Update local_parquet_export smoke to use config-backed sinks instead of manual instantiation, proving the production path works - 19 new tests covering all sink shapes, error modes, and fromProvider Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(types): resolve CI typecheck failures for sink materialization (hy-9d39h) - Add tmpRoot to RunDaemonOptions interface - Add fromProvider to CapabilityRegistry interface and activation facade - Capture config.sinks before withSpan callback to preserve TS narrowing Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: plugin-owned product logic — client descriptors, generalized skills, hook migration (hy-bv310) (#38) Move client-specific and plugin-specific product behavior out of core and behind plugin-owned manifest descriptors: - Add `contributes.client` descriptor to plugin manifests with skill_dir, attach_probe, and required_upstreams fields - Extend plugin catalog to extract client descriptors from manifests - Replace hardcoded client loops in status.js with catalog-driven descriptor iteration for attach probing - Generalize `hyp skills install` to resolve skill directories from catalog instead of hardcoding .claude/skills and .codex/skills - Move `claude-hook session-context` command from core to the Claude plugin — registered during plugin activation - Rewrite V1 advisory diagnostics to derive client/upstream checks and encoder/blob-store checks from catalog metadata instead of hardcoded plugin name sets Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: gascity acceptance and plugin-surface cleanup (hy-sadjq) (#39) Reframe gascity from "excluded and invisible" to "excluded from default activation but discoverable through the plugin catalog." Update test and smoke labels/comments to reflect that gascity absence in status is about the config scenario, not a blanket prohibition. Add catalog test for gascity contributions (source, commands, dataset, init preset, skill). Add detach coverage to the gascity smoke test. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: replace inline import types with @import declarations and sanitize env var derivation (hy-hfne7) (#40) Replace 20+ inline import('...') type annotations with @import JSDoc declarations at file tops across validate.js, status.js, materialize.js, and sink-materialize.test.js. Fix resolveClientSettingsPath to sanitize non-alphanumeric characters (hyphens, dots, etc.) in client names when deriving env var keys, so that hyphenated clients like 'claude-desktop' produce valid POSIX env var names (CLAUDE_DESKTOP_HOME instead of CLAUDE-DESKTOP_HOME). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address PR 35 diagnostic review feedback * fix: surface CLI sink materialization warnings --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
philcunliffe pushed a commit
that referenced
this pull request
Aug 11, 2026
…pellings Three heading-id divergences from the pandoc that master shelled out to. Each one still renders the heading correctly, so the only visible symptom is a pandoc-era `#anchor` that silently dangles. All measured against a real pandoc 3.1.11 binary with one heading per document, so no de-dup counter drift can cascade between cases. Uppercase `&#X...;` never decoded. The entity regex spelled the hex alternative `#x[0-9a-fA-F]+`, which made the existing `body[1] === 'X'` guard unreachable: marked's escaper passes the uppercase form through (its no-encode pattern spells the prefix `#[Xx]`), so it arrived verbatim and leaked its digits. `## A A B` minted `a-x41-b` against pandoc's `a-a-b`. This also left `�` inside the out-of-range window unsubstituted, leaking digits where the guard's own comment says it must not, so that comment is corrected too. `'` was missing from NAMED_ENTITIES, so `## What's next` minted `whataposs-next` against pandoc's `whats-next` - a single-entry hole in the exact case the decoder's docstring uses to motivate itself, while `'`, `'` and `’` were all already right. The rest of the HTML5 ASCII-punctuation block had the same hole and is added with it: all 27 names were verified individually against pandoc rather than taken on trust. `<br>` was deleted outright by the general tag strip where pandoc's reader yields a space, welding `## Line one<br/>Line two` into `line-oneline-two`. It now substitutes a space before the tag strip and after the whitespace collapse, because pandoc counts that space as its own token: `## A <br /> B` mints `a---b`, not `a-b`. The match is lowercase-only, since pandoc treats `<BR>` as raw inline HTML contributing nothing. Every other tag still vanishes without a trace; `<span>a</span>b` and `A<em>B</em>C` are pinned so a future general tag-to-space rule cannot regress them. Moving the collapse ahead of the tag strip also stops a tag's own inner whitespace being merged away, which pandoc likewise counts as its own token. The heading renderer's comment claiming pandoc emits no id for a `<br>`-only heading was wrong and is corrected: pandoc mints `-`, and now so does this. Two measured divergences are left alone deliberately. U+2028, U+2029 and U+FEFF are in JS's `\s` but pandoc drops them, each minting one extra hyphen; the literal-authored spellings break further upstream in marked's block parser (no heading is emitted at all), so a character-class fix would only close half the case. And pandoc slugs a Markdown image's alt text (`## ` -> `img`) but emits no id for a raw-HTML `<img alt="...">`, which this renderer already matches; marked emits byte-identical HTML for both, so there is no string-level discriminator and a fix belongs at the token level, not here. LLP 0208's footnote consequence is tightened: it described only the multi-token definition, which survives as literal text. A single-token one (`[^1]: notes.md`) is parsed as a link reference definition instead, so the definition line disappears and the reference becomes a live link that rewriteHrefs then rewrites. Co-Authored-By: Claude <noreply@anthropic.com>
bgmcmullen added a commit
that referenced
this pull request
Aug 11, 2026
* Report renderer drops pandoc and converts in process (LLP 0205) Supersedes LLP 0196 open question 1's keep-pandoc resolution through the escape hatch that resolution named for itself: the only pandoc property the component vocabulary relies on is gfm passing raw HTML through untouched, "so in-process rendering stays available if the dependency ever becomes a problem." Server-side generation (hypaware-server LLP 0112) made it one twice over: pandoc would be that daemon's first non-npm binary, and execFileSync blocks the single thread every customer org shares, measured at ~40ms per page. The substitution was measured before it was made: all 94 files of a real reports tree converted under both engines; 66 structurally identical, 28 differing only in pandoc's syntax-highlighting markup, 0 genuine differences. After the swap the same tree renders to 94 pages with zero structural diffs against the pandoc reference, and the style-before-theme link order holds on every page. - pandocPage becomes htmlPage: marked (pinned, zero transitive deps) plus an explicit standalone template doing what -s did, with assets/head.html inlined after the base stylesheet link so theme.css keeps loading last (LLP 0196#theme-layer). - A renderer override reproduces pandoc's heading ids, -1 suffixes included, so existing in-page anchors keep resolving. - hasPandoc, the CLI preflight, the help text, the CI apt-get step, and the skill's prerequisite all go. The render tests lose their skip guard and run everywhere: a renderer with no external dependency has no excuse for untested paths. 3892 tests pass, none skipped for pandoc. - Syntax highlighting is the one visible change, light mode only: the stylesheet's token rules sit in its dark-mode block and flattened pandoc's spans to one colour anyway. language-* classes survive for later colour. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Report render: pandoc-parity heading ids and table alignment, pinned by tests Round-1 review of #705. The pandoc-to-marked swap was measured structurally, which is exactly the comparison that cannot see either of these: one changes an attribute's spelling, the other changes text the browser never shows. - headingId was fed marked's already-escaped inline HTML, so `&` reached the slug rule as `&` and left its letters behind: `Cost & Usage` minted cost-amp-usage where pandoc mints cost--usage, and every authored [link](#whats-next) pointed at what39s-next. It now strips tags, unescapes, collapses whitespace runs before dropping punctuation (a dropped `&` leaves two spaces and pandoc emits both hyphens), and hyphenates per space rather than per run. Unicode letter and number classes keep `Café résumé` and `日本語` intact, as pandoc does. Re-verified 24/24 against pandoc 3.1.11 `-f gfm -t html5`, `-1` repeat suffixes included. - A tablecell override restates column alignment as pandoc's inline `style="text-align: ..."`. marked's built-in emits `align="right"`, a presentational hint the cascade ranks below assets/style.css's `th, td { text-align: left }`, so every right-aligned numeric column and every centred column silently rendered left, against tabular-nums. - test/core/report-render.test.js gains a golden page over the authoring vocabulary (component block byte-for-byte, aligned table, fenced block with its language class, headings carrying `&`, `'` and `/`) plus an anchor integrity check: every href="#..." must match an id on the page. Both fixes above fail this test before they land. - src/core/reports/README.md drops the stale "pandoc is still a hard dependency" rule and pandoc's `-H` for head.html. It ships in the package. - assets/style.css suppresses the list marker on task lists, which pandoc's template did through a task-list class marked does not emit. Footnotes are a real loss (marked's gfm has none) and are accepted and recorded rather than extension-patched. - LLP 0208 narrows its measurement claim to what is true of tables, and records the footnote and task-list consequences. LLP 0196 gains a header-level Superseded-in-part-by forward-ref. Co-Authored-By: Claude <noreply@anthropic.com> * Report render: fix round-2 findings on heading ids, entities, and task lists Four residual round-2 findings on PR #705's pandoc-to-marked swap, each verified against a real pandoc 3.1.11 binary. Finding A: heading ids dropped combining marks (`[^\p{L}\p{N}_\s-]` stripped `\p{M}`), mangling Indic, Thai, Arabic/Hebrew, Vietnamese and decomposed Latin text unconditionally. headingId now NFC-normalizes before lowercasing and keeps `\p{M}` in the retained class, matching pandoc on decomposed "Café résumé", Turkish dotted-I, and Devanagari. Finding B: unescapeHtml only covered the five entities marked itself emits, so an author-written entity (`’`, `'`, ...) leaked its raw letters/digits into the slug and could dangle an in-page anchor. Replaced the five-entity table with a general decoder: numeric (`&#NNN;`, `&#xHH;`) plus a bounded, case-sensitive "HTML4" named-entity table (Latin-1, Greek, typography), sourced from the WHATWG entity list and stored as codepoints rather than literal characters. Case-sensitive matching was chosen over the case-insensitive suggestion after measuring pandoc itself: it decodes `&` (a real legacy dual-case alias) but not `&MDASH;` or `&RSQUO;`, and a case-fold would wrongly collide distinct entries like `Α`/`α`. Fixing this also surfaced a second bug: whitespace-run collapsing had to move to before entity decoding, or a decoded ` ` merged with real spaces around it into one hyphen instead of pandoc's one-hyphen-per-token count (verified: `A B` -> `a---b`). Finding C: the `ul:has(> li > input[type="checkbox"])` rule only matched "tight" task lists; a blank-line-separated ("loose") list wraps the checkbox in `li > p > input`, so it kept its bullet. The selector now matches both shapes. Also matched pandoc's cheap-to-copy indent behavior: pandoc's template kept the list's normal indent and pulled the checkbox left with a negative margin, rather than zeroing padding-left. LLP 0208's task-list bullet is corrected to name both shapes instead of just one. Finding D: a heading that reduces to nothing (`## <emoji>`) minted `id=""`; pandoc emits no id attribute. The heading renderer now omits the attribute when the slug is empty, while still running pandoc's own de-dup counter against the empty base for a repeat (`id="-1"`). Each fix is pinned in test/core/report-render.test.js, verified to fail against the pre-fix renderer before the change landed. Co-Authored-By: Claude <noreply@anthropic.com> * Report render: an out-of-range numeric entity no longer aborts the build Two heading-id findings from the round-2 entity decoder, both measured against a real pandoc 3.1.11 binary. An out-of-range numeric character reference in a heading crashed the whole render. `unescapeHtml` called `String.fromCodePoint` behind only a `Number.isFinite` guard, and that throws above U+10FFFF. The window is reachable rather than theoretical: marked's escaper passes numeric references of up to 7 decimal or 6 hex digits through untouched, so every value in `�`-`�` and `�`-`�` arrived verbatim. The blast radius is what made it worth fixing now: `renderReports` wipes `html/` before building and builds in sorted slug order, so one bad heading in one report destroyed the already-built pages of every report sorting at or after it and left the landing page stale. Reports are model-authored, so the input is not fully under a human's control. pandoc substitutes U+FFFD, which its slug then strips, minting `a--b` for `## A � B`, so the guard substitutes U+FFFD too rather than returning the entity intact, which would leak its digits into the id. Lone surrogates and U+10FFFF stay on the `fromCodePoint` path, where they already matched pandoc. `headingId` also trimmed after the punctuation strip, which pandoc does not do. Any heading starting or ending with stripped punctuation next to a space minted a different id: `## 🚀 Rollout plan` gave `rollout-plan` where pandoc gives `-rollout-plan`, and `## end &` gave `end` where pandoc gives `end-`. Emoji-led headings are ordinary in model-authored reports, so every pandoc-era `#-rollout-plan` anchor dangled silently, contradicting LLP 0208's promise that existing in-page anchors keep resolving. The trim is dropped, which restores parity across the whole measured table, including the all-whitespace case (pandoc mints `-` for `## ( )`, not no id) and the de-dup counters that run off those degenerate bases. Headings that reduce to the truly empty string still carry no id, and the reader has already trimmed authored outer whitespace, so no stray leading hyphen appears. Regression tests cover both, plus the amplifier: a malformed entity in one report must not destroy the pages of the reports that sort after it. Co-Authored-By: Claude <noreply@anthropic.com> * Report render: heading ids keep pandoc's `&#X`, `'` and `<br>` spellings Three heading-id divergences from the pandoc that master shelled out to. Each one still renders the heading correctly, so the only visible symptom is a pandoc-era `#anchor` that silently dangles. All measured against a real pandoc 3.1.11 binary with one heading per document, so no de-dup counter drift can cascade between cases. Uppercase `&#X...;` never decoded. The entity regex spelled the hex alternative `#x[0-9a-fA-F]+`, which made the existing `body[1] === 'X'` guard unreachable: marked's escaper passes the uppercase form through (its no-encode pattern spells the prefix `#[Xx]`), so it arrived verbatim and leaked its digits. `## A A B` minted `a-x41-b` against pandoc's `a-a-b`. This also left `�` inside the out-of-range window unsubstituted, leaking digits where the guard's own comment says it must not, so that comment is corrected too. `'` was missing from NAMED_ENTITIES, so `## What's next` minted `whataposs-next` against pandoc's `whats-next` - a single-entry hole in the exact case the decoder's docstring uses to motivate itself, while `'`, `'` and `’` were all already right. The rest of the HTML5 ASCII-punctuation block had the same hole and is added with it: all 27 names were verified individually against pandoc rather than taken on trust. `<br>` was deleted outright by the general tag strip where pandoc's reader yields a space, welding `## Line one<br/>Line two` into `line-oneline-two`. It now substitutes a space before the tag strip and after the whitespace collapse, because pandoc counts that space as its own token: `## A <br /> B` mints `a---b`, not `a-b`. The match is lowercase-only, since pandoc treats `<BR>` as raw inline HTML contributing nothing. Every other tag still vanishes without a trace; `<span>a</span>b` and `A<em>B</em>C` are pinned so a future general tag-to-space rule cannot regress them. Moving the collapse ahead of the tag strip also stops a tag's own inner whitespace being merged away, which pandoc likewise counts as its own token. The heading renderer's comment claiming pandoc emits no id for a `<br>`-only heading was wrong and is corrected: pandoc mints `-`, and now so does this. Two measured divergences are left alone deliberately. U+2028, U+2029 and U+FEFF are in JS's `\s` but pandoc drops them, each minting one extra hyphen; the literal-authored spellings break further upstream in marked's block parser (no heading is emitted at all), so a character-class fix would only close half the case. And pandoc slugs a Markdown image's alt text (`## ` -> `img`) but emits no id for a raw-HTML `<img alt="...">`, which this renderer already matches; marked emits byte-identical HTML for both, so there is no string-level discriminator and a fix belongs at the token level, not here. LLP 0208's footnote consequence is tightened: it described only the multi-token definition, which survives as literal text. A single-token one (`[^1]: notes.md`) is parsed as a link reference definition instead, so the definition line disappears and the reference becomes a live link that rewriteHrefs then rewrites. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: test <test@test.com>
philcunliffe added a commit
that referenced
this pull request
Aug 11, 2026
…710) * Report renderer drops pandoc and converts in process (LLP 0205) Supersedes LLP 0196 open question 1's keep-pandoc resolution through the escape hatch that resolution named for itself: the only pandoc property the component vocabulary relies on is gfm passing raw HTML through untouched, "so in-process rendering stays available if the dependency ever becomes a problem." Server-side generation (hypaware-server LLP 0112) made it one twice over: pandoc would be that daemon's first non-npm binary, and execFileSync blocks the single thread every customer org shares, measured at ~40ms per page. The substitution was measured before it was made: all 94 files of a real reports tree converted under both engines; 66 structurally identical, 28 differing only in pandoc's syntax-highlighting markup, 0 genuine differences. After the swap the same tree renders to 94 pages with zero structural diffs against the pandoc reference, and the style-before-theme link order holds on every page. - pandocPage becomes htmlPage: marked (pinned, zero transitive deps) plus an explicit standalone template doing what -s did, with assets/head.html inlined after the base stylesheet link so theme.css keeps loading last (LLP 0196#theme-layer). - A renderer override reproduces pandoc's heading ids, -1 suffixes included, so existing in-page anchors keep resolving. - hasPandoc, the CLI preflight, the help text, the CI apt-get step, and the skill's prerequisite all go. The render tests lose their skip guard and run everywhere: a renderer with no external dependency has no excuse for untested paths. 3892 tests pass, none skipped for pandoc. - Syntax highlighting is the one visible change, light mode only: the stylesheet's token rules sit in its dark-mode block and flattened pandoc's spans to one colour anyway. language-* classes survive for later colour. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Report render: pandoc-parity heading ids and table alignment, pinned by tests Round-1 review of #705. The pandoc-to-marked swap was measured structurally, which is exactly the comparison that cannot see either of these: one changes an attribute's spelling, the other changes text the browser never shows. - headingId was fed marked's already-escaped inline HTML, so `&` reached the slug rule as `&` and left its letters behind: `Cost & Usage` minted cost-amp-usage where pandoc mints cost--usage, and every authored [link](#whats-next) pointed at what39s-next. It now strips tags, unescapes, collapses whitespace runs before dropping punctuation (a dropped `&` leaves two spaces and pandoc emits both hyphens), and hyphenates per space rather than per run. Unicode letter and number classes keep `Café résumé` and `日本語` intact, as pandoc does. Re-verified 24/24 against pandoc 3.1.11 `-f gfm -t html5`, `-1` repeat suffixes included. - A tablecell override restates column alignment as pandoc's inline `style="text-align: ..."`. marked's built-in emits `align="right"`, a presentational hint the cascade ranks below assets/style.css's `th, td { text-align: left }`, so every right-aligned numeric column and every centred column silently rendered left, against tabular-nums. - test/core/report-render.test.js gains a golden page over the authoring vocabulary (component block byte-for-byte, aligned table, fenced block with its language class, headings carrying `&`, `'` and `/`) plus an anchor integrity check: every href="#..." must match an id on the page. Both fixes above fail this test before they land. - src/core/reports/README.md drops the stale "pandoc is still a hard dependency" rule and pandoc's `-H` for head.html. It ships in the package. - assets/style.css suppresses the list marker on task lists, which pandoc's template did through a task-list class marked does not emit. Footnotes are a real loss (marked's gfm has none) and are accepted and recorded rather than extension-patched. - LLP 0208 narrows its measurement claim to what is true of tables, and records the footnote and task-list consequences. LLP 0196 gains a header-level Superseded-in-part-by forward-ref. Co-Authored-By: Claude <noreply@anthropic.com> * Report render: fix round-2 findings on heading ids, entities, and task lists Four residual round-2 findings on PR #705's pandoc-to-marked swap, each verified against a real pandoc 3.1.11 binary. Finding A: heading ids dropped combining marks (`[^\p{L}\p{N}_\s-]` stripped `\p{M}`), mangling Indic, Thai, Arabic/Hebrew, Vietnamese and decomposed Latin text unconditionally. headingId now NFC-normalizes before lowercasing and keeps `\p{M}` in the retained class, matching pandoc on decomposed "Café résumé", Turkish dotted-I, and Devanagari. Finding B: unescapeHtml only covered the five entities marked itself emits, so an author-written entity (`’`, `'`, ...) leaked its raw letters/digits into the slug and could dangle an in-page anchor. Replaced the five-entity table with a general decoder: numeric (`&#NNN;`, `&#xHH;`) plus a bounded, case-sensitive "HTML4" named-entity table (Latin-1, Greek, typography), sourced from the WHATWG entity list and stored as codepoints rather than literal characters. Case-sensitive matching was chosen over the case-insensitive suggestion after measuring pandoc itself: it decodes `&` (a real legacy dual-case alias) but not `&MDASH;` or `&RSQUO;`, and a case-fold would wrongly collide distinct entries like `Α`/`α`. Fixing this also surfaced a second bug: whitespace-run collapsing had to move to before entity decoding, or a decoded ` ` merged with real spaces around it into one hyphen instead of pandoc's one-hyphen-per-token count (verified: `A B` -> `a---b`). Finding C: the `ul:has(> li > input[type="checkbox"])` rule only matched "tight" task lists; a blank-line-separated ("loose") list wraps the checkbox in `li > p > input`, so it kept its bullet. The selector now matches both shapes. Also matched pandoc's cheap-to-copy indent behavior: pandoc's template kept the list's normal indent and pulled the checkbox left with a negative margin, rather than zeroing padding-left. LLP 0208's task-list bullet is corrected to name both shapes instead of just one. Finding D: a heading that reduces to nothing (`## <emoji>`) minted `id=""`; pandoc emits no id attribute. The heading renderer now omits the attribute when the slug is empty, while still running pandoc's own de-dup counter against the empty base for a repeat (`id="-1"`). Each fix is pinned in test/core/report-render.test.js, verified to fail against the pre-fix renderer before the change landed. Co-Authored-By: Claude <noreply@anthropic.com> * Report render: an out-of-range numeric entity no longer aborts the build Two heading-id findings from the round-2 entity decoder, both measured against a real pandoc 3.1.11 binary. An out-of-range numeric character reference in a heading crashed the whole render. `unescapeHtml` called `String.fromCodePoint` behind only a `Number.isFinite` guard, and that throws above U+10FFFF. The window is reachable rather than theoretical: marked's escaper passes numeric references of up to 7 decimal or 6 hex digits through untouched, so every value in `�`-`�` and `�`-`�` arrived verbatim. The blast radius is what made it worth fixing now: `renderReports` wipes `html/` before building and builds in sorted slug order, so one bad heading in one report destroyed the already-built pages of every report sorting at or after it and left the landing page stale. Reports are model-authored, so the input is not fully under a human's control. pandoc substitutes U+FFFD, which its slug then strips, minting `a--b` for `## A � B`, so the guard substitutes U+FFFD too rather than returning the entity intact, which would leak its digits into the id. Lone surrogates and U+10FFFF stay on the `fromCodePoint` path, where they already matched pandoc. `headingId` also trimmed after the punctuation strip, which pandoc does not do. Any heading starting or ending with stripped punctuation next to a space minted a different id: `## 🚀 Rollout plan` gave `rollout-plan` where pandoc gives `-rollout-plan`, and `## end &` gave `end` where pandoc gives `end-`. Emoji-led headings are ordinary in model-authored reports, so every pandoc-era `#-rollout-plan` anchor dangled silently, contradicting LLP 0208's promise that existing in-page anchors keep resolving. The trim is dropped, which restores parity across the whole measured table, including the all-whitespace case (pandoc mints `-` for `## ( )`, not no id) and the de-dup counters that run off those degenerate bases. Headings that reduce to the truly empty string still carry no id, and the reader has already trimmed authored outer whitespace, so no stray leading hyphen appears. Regression tests cover both, plus the amplifier: a malformed entity in one report must not destroy the pages of the reports that sort after it. Co-Authored-By: Claude <noreply@anthropic.com> * Report render: heading ids keep pandoc's `&#X`, `'` and `<br>` spellings Three heading-id divergences from the pandoc that master shelled out to. Each one still renders the heading correctly, so the only visible symptom is a pandoc-era `#anchor` that silently dangles. All measured against a real pandoc 3.1.11 binary with one heading per document, so no de-dup counter drift can cascade between cases. Uppercase `&#X...;` never decoded. The entity regex spelled the hex alternative `#x[0-9a-fA-F]+`, which made the existing `body[1] === 'X'` guard unreachable: marked's escaper passes the uppercase form through (its no-encode pattern spells the prefix `#[Xx]`), so it arrived verbatim and leaked its digits. `## A A B` minted `a-x41-b` against pandoc's `a-a-b`. This also left `�` inside the out-of-range window unsubstituted, leaking digits where the guard's own comment says it must not, so that comment is corrected too. `'` was missing from NAMED_ENTITIES, so `## What's next` minted `whataposs-next` against pandoc's `whats-next` - a single-entry hole in the exact case the decoder's docstring uses to motivate itself, while `'`, `'` and `’` were all already right. The rest of the HTML5 ASCII-punctuation block had the same hole and is added with it: all 27 names were verified individually against pandoc rather than taken on trust. `<br>` was deleted outright by the general tag strip where pandoc's reader yields a space, welding `## Line one<br/>Line two` into `line-oneline-two`. It now substitutes a space before the tag strip and after the whitespace collapse, because pandoc counts that space as its own token: `## A <br /> B` mints `a---b`, not `a-b`. The match is lowercase-only, since pandoc treats `<BR>` as raw inline HTML contributing nothing. Every other tag still vanishes without a trace; `<span>a</span>b` and `A<em>B</em>C` are pinned so a future general tag-to-space rule cannot regress them. Moving the collapse ahead of the tag strip also stops a tag's own inner whitespace being merged away, which pandoc likewise counts as its own token. The heading renderer's comment claiming pandoc emits no id for a `<br>`-only heading was wrong and is corrected: pandoc mints `-`, and now so does this. Two measured divergences are left alone deliberately. U+2028, U+2029 and U+FEFF are in JS's `\s` but pandoc drops them, each minting one extra hyphen; the literal-authored spellings break further upstream in marked's block parser (no heading is emitted at all), so a character-class fix would only close half the case. And pandoc slugs a Markdown image's alt text (`## ` -> `img`) but emits no id for a raw-HTML `<img alt="...">`, which this renderer already matches; marked emits byte-identical HTML for both, so there is no string-level discriminator and a fix belongs at the token level, not here. LLP 0208's footnote consequence is tightened: it described only the multi-token definition, which survives as literal text. A single-token one (`[^1]: notes.md`) is parsed as a link reference definition instead, so the definition line disappears and the reference becomes a live link that rewriteHrefs then rewrites. Co-Authored-By: Claude <noreply@anthropic.com> * Heading ids: every raw tag starting with `br` yields a space (#709) Deferred findings from PR #705, which this stacks on. Item 1 (fixed). pandoc 3.1.11's stringify keys on a raw inline's LEADING TEXT, not on a parsed tag name, so ANY raw inline HTML token whose text starts with the case-sensitive prefix `<br` becomes a space. The regex here was spelled `<br(?:\s[^>]*)?\/?>` on the stated rationale that it must not "swallow `<brand>`"; pandoc swallows `<brand>` too, so that rationale was false and the code comment recording it is corrected. Widening to `/<br[^>]*>/g` closes 11 divergences with no regressions, verified case by case against a real pandoc 3.1.11 binary, one heading per document so no de-dup counter drift can read as parity: `## A <brand> B` a--b -> a---b (pandoc a---b) `## A <brand>x</brand> B` a-x-b -> a--x-b (only the open tag counts) `## A <bra> B` a--b -> a---b `## A <br-x> B` a--b -> a---b `## A <br2> B` a--b -> a---b `## A <brand attr="y"> B` a--b -> a---b `## A <brand/> B` a--b -> a---b `## A <breakfast time> B` a--b -> a---b `## A <brand > B` a--b -> a---b `## A <brand>B` a-b -> a--b `## A<brand> B` a-b -> a--b The exclusions stay excluded: `<BR>`, `<Br>` and `<bR>` miss the lowercase prefix, `</brand>` starts `</b`, and `<b>`, `<bold>`, `<span>`, `<custom>` and `<q>` are not `br` at all. Widening is safe because the regex never sees a string marked did not already accept as a tag: marked escapes invalid tag syntax to entities first, and pandoc likewise leaves `<br@>` as text. Items 2 and 3 (recorded, not fixed). Both stay deferred, with the measurement behind them now in the doc instead of only the PR thread. Item 4. LLP 0208 records the footnote, task-list and highlighting consequences but promised heading ids "so existing in-page anchors keep resolving" without naming where that is inexact. A new `#heading-id-gaps` consequence names the two remaining classes, and `headingId` carries a `@ref` to it. Co-Authored-By: Claude <noreply@anthropic.com> * Fix PR #710 review findings: revert LLP 0208 settled text, correct @ref gloss LLP 0208 is Status: Active and merged to master, so its Decision paragraph is a settled record; revert the added qualifier on the heading-id sentence back to the master text and keep only the additive #heading-id-gaps consequence section. The @ref gloss in render.js overstated the constraint: the entity spellings of the Unicode separators/BOM are decoded by unescapeHtml and are reachable inside headingId, only the literal spellings break above this function in marked's block parser. Reword the gloss to match the LLP section it cites. * Correct BOM attribution in heading-id gap notes (#710 review round 2) Round 2 verified against marked 18.0.9 through the real renderReports path that a literal U+FEFF survives inline parsing and reaches headingId intact (`## K <BOM> L` renders `<h2 id="k-l">`), so its divergence comes from the slug rule's own `\s` handling, not from marked's block parser. Only a literal U+2028/U+2029 breaks upstream, splitting the block so no heading is produced at all. Reword the @ref gloss and the LLP 0208 #heading-id-gaps sub-bullet so the BOM is no longer cited as evidence of upstream breakage, and record that a slug-rule-only change would close the BOM case in full. Comment and doc accuracy only; no executable code, regex, or test changes. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Brendan McMullen <bgmcmullen@comcast.net> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: test <test@test.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merges polecat/hy-sadjq → integration/hypaware-plugin-surfaces
Bead: hy-sadjq