Skip to content

test: kill the surviving mutants in the SVG active content gate - #1793

Merged
mrbobbytables merged 1 commit into
cncf:mainfrom
mrbobbytables:copilot/mutants-svg-active-content
Oct 22, 2026
Merged

mrbobbytables merged 1 commit into
cncf:mainfrom
mrbobbytables:copilot/mutants-svg-active-content

Conversation

@mrbobbytables

Copy link
Copy Markdown
Member

Summary

Group A of #1788: kills the surviving mutants in scripts/lib/svg-active-content.mjs, the single largest contributor to the full-tree mutation backlog (195 survivors in the last scheduled run). Tests only; no source changes.

  • New tests/svg-active-content-vocabulary.test.mjs: table-driven acceptance of every exported allowlist entry (elements, attributes, XHTML, xlink/xml, metadata namespaces) and rejection of root-only attributes off the root, so dropping any entry fails a test.
  • tests/svg-active-content.test.mjs: pins the exact wording of each finding, the one-finding error cascade, DOCTYPE detection and byte-for-byte stripping, processing-instruction ordering, encoding-declaration boundaries, the css-tree tokenizer branches (escaped url(, nested functions, @import, identifiers that merely end in import, parenthesized groups) and the full residual list when stripping fails.

Mutation score (scoped to the file)

killed survived no coverage score
before 859 195 0 82.1%
after 932 24 0 97.5%

The 24 survivors are equivalent mutants, left without suppression: sentinel array initialisers (["Stryker was here"] on arrays that are immediately pushed to), the /[(@]/ fast path (skipping it only costs tokenizer time), close <= 0 vs close < 0 on indexOf results that cannot be 0 after a token end, raw.trim() before url.decode (which trims itself), the end === -1 guard behind sax's own well-formedness error, parser.resume() after the error is already cleared, left-operand true on event.type === 'close', the url( Function branch always being followed by a String token, and the unreachable pi fallthrough in rebuild.

Validation

  • TZ=UTC node --test tests/svg-active-content*.test.mjs: 402 pass
  • npm run test:unit:coverage:check: pass
  • npm run check:format, check:lint, check:duplication, check:unused, check:spelling, check:markdown: pass

Refs #1788

The last full-tree mutation run left 195 surviving mutants in
scripts/lib/svg-active-content.mjs. A table-driven vocabulary test now
accepts every exported allowlist entry (and rejects root-only attributes
off the root), and the gate tests pin the exact wording of each finding,
the one-finding error cascade, DOCTYPE stripping byte for byte, processing
instruction ordering, encoding declaration boundaries, the css-tree
tokenizer branches (escaped url(, nested functions, @import, identifiers
that merely end in "import", parenthesized groups) and the residual list
when stripping fails.

Scoped score for the file: 82.1% to 97.5% (932 killed, 24 survived, 0
without coverage). The survivors are equivalent: sentinel array
initialisers, the `/[(@]/` fast path, `close <= 0` on indexOf results,
`raw.trim()` before url.decode (which trims), the `end === -1` guard
behind sax's own well-formedness error, `parser.resume()` after clearing
the error, left-operand `true` on `event.type === 'close'`, and the
unreachable `pi` fallthrough in rebuild.

Refs cncf#1788

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
@netlify

netlify Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for endusers ready!

Name Link
🔨 Latest commit f179016
🔍 Latest deploy log https://app.netlify.com/projects/endusers/deploys/6ada62668b411030a3e4f489
😎 Deploy Preview https://deploy-preview-1793--endusers.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@mrbobbytables
mrbobbytables added this pull request to the merge queue Oct 22, 2026
Merged via the queue into cncf:main with commit 1d26a89 Oct 22, 2026
14 checks passed
@hivecommons-hive

Copy link
Copy Markdown
Contributor

Scanner pass: no findings. The two touched test files (svg-active-content.test.mjs, new svg-active-content-vocabulary.test.mjs) are disjoint from every open hold-gated PR (#1782, #1784, #1786, #1792), the diff is test-only with no deletions, and the completed checks are green including Mutation testing (only the two E2E jobs were still running at review time). Ready for human review once CI settles.


🐝 Hive Agent: scanner | Instance: hosted-available-lke648397-260827-5n31 | SHA: unknown

— hive: agent=scanner backend=copilot model=kimi-k3 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the diff against main at f179016 (two test files, 369 insertions, no source changes) and ran both suites locally after npm ci: TZ=UTC node --test tests/svg-active-content*.test.mjs passes 402/402. The vocabulary file is table-driven off the module's own exported allowlists, so a dropped entry fails a named case, and the root-only attributes are asserted rejected off the root — exactly the mutant classes the body describes. CI's mutation-testing check is green on this head.

The 24 survivors left are explained plausibly in the body (sentinel initialisers, default-equivalent trims, guards behind sax's own well-formedness error); I did not re-run Stryker to confirm each one, so treat the equivalence list as the author's claim, not verified here.

Looks correct to me — a grounded strengthening of the gate's assertions with no production risk. This is a fork branch the hive cannot push to, so it needs a human merge once the in-progress e2e checks finish.

— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.88

github-merge-queue Bot pushed a commit that referenced this pull request Oct 22, 2026
…rayDeclaration (#1807)

Annotate the 41 surviving mutants that the backlog groups in #1788
verified as equivalent (#1789, #1790, #1793, #1794, #1795) with
Stryker disable directives that carry the reason, so they report as
Ignored instead of Survived and no longer surface as mutation findings.
Exclude the ArrayDeclaration mutator in stryker.config.mjs: every
instance that survived on main seeded an accumulator or fallback whose
contents are unobservable. Hoist the landscape source URL in
DirectoryFreshness into a const so its directive can attach outside the
JSX. Document the directive placement rules in CONTRIBUTING.

Refs #1788

Signed-off-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
Co-authored-by: mrbobbytables <mrbobbytables@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant