Skip to content

Gap analysis: missing gates behind recurring Hive findings (last 100 issues/PRs) #1718

Closed

Description

@mrbobbytables

Summary

I reviewed the 100 most recent issues (#1447 to #1716, opened 2026-10-14 to 2026-10-21) and the 100 most recent PRs (#1555 to #1717). Hive agents opened 93 of those issues and 75 of those PRs. Most of the findings fall into a small number of recurring classes, and each class keeps coming back because no gate catches the underlying problem. Each finding gets fixed one at a time, and the agent then finds the next instance.

This issue lists those classes, the gate that is missing for each, and a suggested order of work. The aim is to replace whole classes of recurring findings with automated gates, so the agents run out of work in those areas.

The "expected effect" estimates are judgement calls; none of the proposed gates have been prototyped yet.

Findings by class

Counts are by issue title prefix ([quality], [architect] and so on) across the 100 issues.

Class Issues Example issues
quality 43 #1674, #1670, #1620, #1705, #1660, #1676, #1682, #1512
architect 16 #1658, #1690, #1699, #1709, #1669, #1681, #1558, #1622
sec-check 11 #1515, #1672, #1695, #1716, #1494, #1501, #1543, #1684
guide 11 #1568, #1529, #1537, #1663, #1703, #1459, #1637
scanner 10 #1602, #1609, #1599, #1630, #1618, #1594, #1448
ci-maintainer 2 #1707, #1645

1. Code that runs under test but is never asserted (quality)

Pattern: "X's Y arm is unpinned or unasserted: collapsing Z leaves the unit suite green." Examples: #1674 (FilterToolbar's value/label ternary), #1670 (the data: arm of activeScheme), #1620 (useFilterToolbar query exclusion), #1705 (DATELINE_RE arms), #1660 (websiteUrl authority parsing), #1676, #1682, #1512, #1651.

Root cause: test:unit:coverage:check enforces 100% source lines and regions, which only shows that code ran. Nothing checks whether a test would fail if the code changed. The quality agent is doing mutation testing by hand, one branch per issue.

Missing gate: mutation testing (for example StrykerJS with the node:test runner, or a lightweight custom mutator) over src/ and scripts/lib/, with a minimum score ratchet in CI. It could start as incremental, mutating only files changed in the PR, to keep CI time bounded.

Expected effect: this removes the largest single source of Hive issues.

2. Unit-covered branches that no end-to-end build reaches (quality)

Pattern: "guard is unit-covered but reached by no e2e fixture build." Examples: #1486, #1654, #1656, #1692, #1469, #1593, and PRs #1688, #1693, #1717.

Root cause: there is no written policy on which branches need browser coverage. #1617 dropped the per-file region floor, but the quality agent still treats every unreached defensive arm as a bug, and each one costs a new fixture build.

Missing gate (policy, not code): state in GOVERNANCE.md or an ADR that defensive guards (nullish, unparseable, or all-absent data) only need unit coverage, and that e2e coverage is required only for user-reachable interaction states. Then tell the quality agent, through its skill or prompt, not to file this class of issue.

3. Duplication outside the duplication gate's scope (architect)

Pattern: the same component, CSS rule or workflow block copied across files. Examples: #1658, #1690, #1699, #1709 (components); #1669 and #1681 (freshness-note CSS, one copy already drifted); #1558 and #1622 (workflow YAML); #1474, #1553 and #1455 (script helpers).

Root cause: .jscpd.json scans only tests, src and scripts, with minTokens: 50. Workflows and composite actions under .github/ are not scanned, and short CSS-module rules fall under the token threshold.

Missing gates:

  • Add .github to the jscpd path, or add a second jscpd run with YAML-specific settings.
  • Add a CSS-specific jscpd pass over src/**/*.module.css with a lower minTokens, or a stylelint rule.
  • Make the CLONE_CEILING ratchet automatic: fail when the count drops by more than CEILING_SLACK without the ceiling being lowered, so [ci-maintainer] Duplication gate has only one clone below its ceiling #1645-style issues are not needed.

Expected effect: the architect agent's duplication findings move into CI.

4. No linter (scanner and quality)

Pattern: the repository has no ESLint configuration. Several bespoke tests stand in for lint rules, and the remaining cases are filed as issues one by one:

Missing gates:

  • ESLint with eslint-plugin-react (react/no-unknown-property), eslint-plugin-react-hooks, jsx-a11y, and a no-restricted-syntax rule banning new URL(...).pathname for file paths.
  • knip (or depcheck) for unused dependencies, exports, files and scripts.
  • Replace the bespoke guard tests with these rules where they overlap, which also shrinks the test tree.

Expected effect: the scanner agent's static findings, and their one-off guard tests, move into the linter.

5. Security filters that block known-bad patterns, and partial CSP (sec-check)

Pattern: each sec-check issue finds another way past the SVG and MDX active-content filters, or another missing header:

Root cause:

  • stripActiveContent and the MDX gates enumerate dangerous constructs, so every construct they don't list is a bypass.
  • In netlify.toml, only /img/* and /favicons/* carry a full CSP. HTML pages (/*) send only frame-ancestors 'self', so the next findings are predictable: script-src, base-uri, form-action, object-src and Permissions-Policy on pages.

Missing gates:

  • Switch SVG sanitization to an allowlist: only listed elements and attributes survive, and everything else is removed and fails the import. For example, an svgo or DOMPurify allowlist profile, or a hand-rolled allowlist.
  • Switch the MDX gate to an allowlist of node types and URL schemes.
  • Add a property-based or fuzz corpus test (for example fast-check) that feeds generated SVG and MDX through both gates.
  • Define a complete site-wide CSP and Permissions-Policy, with a contract test that asserts every [[headers]] block includes a fixed baseline directive set, so a missing directive fails CI instead of being found later.

Expected effect: high. This category produces the highest-severity issues.

6. Documentation claims nothing verifies (guide)

Pattern: docs describe scripts, routes, workflows, recipes or ADR status that are wrong or have since changed:

Root cause: tests/markdown-references.test.mjs (PR #1580) checks file references, but not:

  • npm run <x> and just <x> mentions
  • site routes
  • workflow names
  • the link between an ADR's status and the state of its tracking issue

Missing gate: extend the Markdown reference contract so that every inline-code npm run X resolves to a package.json script, every just X to a Justfile recipe, every site-relative route to a built route, and every workflow name to a file in .github/workflows/. Add a check that an ADR marked Proposed doesn't reference a closed tracking issue.

Expected effect: the guide agent's drift findings become CI failures in the PR that causes the drift.

7. Dependencies and CI environment (ci-maintainer and sec-check)

Pattern:

Missing gates:

  • Turn on Dependabot security updates, with auto-merge for lockfile-only patch bumps once required checks pass.
  • Add a scheduled check that allowlisted advisories still apply and have an upstream fix tracked.
  • Add a contract test that every job pins a GitHub-hosted runs-on label, or explicitly declares the tools it needs.

8. Self-checks over the test tree

Pattern: stale citations and recorded measurements inside test prose: #1447, #1468, #1471, #1497, PR #1597, and open PR #1714.

Root cause: ADR 0006 retired line-number citations, but there are still 138 #1xxx issue citations under tests/. Each time a cited issue closes, the citation goes stale and is re-filed.

Missing gate: remove issue-number citations from test prose (move the rationale into commit messages or ADRs), then add a lint check that rejects new ones. Close #1714 as covered by this.

Proposed order

  1. Mutation testing gate (class 1), plus the coverage policy ADR (class 2).
  2. ESLint and knip (class 4), retiring the overlapping bespoke guard tests.
  3. Allowlist sanitization, a fuzz corpus, and a full CSP/Permissions-Policy baseline with a contract test (class 5).
  4. The Markdown claims contract (class 6).
  5. Extend duplication scope to .github/ and CSS, and automate the ceiling ratchet (class 3).
  6. Dependabot security auto-merge and the runner contract (class 7).
  7. Remove test-prose issue citations and add the lint check (class 8).

Each item should be its own PR and linked back here. Once each gate lands, update the matching Hive agent's skill or prompt so it stops filing that class of finding.

Activity

  1. added
    testingApproved by a Hive merger/owner for auto-merge on green CI
    tech-debtCreated by Hive for agent-filed issue provenance
    on Oct 21, 2026
  2. mrbobbytables commented on Oct 21, 2026

    @mrbobbytables
    MemberAuthor

    Correction to class 3: scripts/check-duplication.mjs already ratchets the ceiling down (CEILING_SLACK), so only the scope widening (.github/ and CSS) is still open for item 5.

    Work in progress, one PR per item, each linked back here:

  3. mrbobbytables commented on Oct 21, 2026

    @mrbobbytables
    MemberAuthor

    All items now have PRs (none merged yet):

    Item PR
    1, class 1: mutation testing (StrykerJS, baseline 83.81%) #1731
    1, class 2: coverage policy (ADR 0007) #1719
    2: ESLint #1727
    2: knip #1728
    3: allowlist SVG/MDX gates and fast-check corpus #1730
    3: page-wide CSP and Permissions-Policy baseline #1722
    4: Markdown claims contract #1724
    5: duplication gate covers CSS and .github YAML #1721
    6: Dependabot lockfile-only auto-merge #1720
    7: retire issue citations in test prose #1725 (supersedes #1714)

    Runner fix for #1707 needs a CNCF org admin: restrict the gpus runner group so it is not available to cncf/endusers, or remove the ubuntu-24.04 label from those runners. #1733 duplicates #1731.

  4. mrbobbytables commented on Oct 21, 2026

    @mrbobbytables
    MemberAuthor

    All items have landed: #1719, #1720, #1721, #1722, #1724, #1725, #1727, #1728, #1730 and #1731. #1733 and #1714 were closed as duplicates or superseded.

    Fixes made while rebasing onto the combined main:

    Validated main at the final merge: npm ci, test:unit:coverage:check, all six lint checks and npm run build all pass.

    Still open, outside this repository: #1707 needs a CNCF org admin to restrict the gpus runner group.

  5. clubanderson commented on Oct 21, 2026

    @clubanderson

    Thanks Bob - this is exactly the feedback the hive needed, and the gate PRs are great work. Filed two small prompt-level changes upstream so the agents stop generating this kind of work: hivecommons/hive#13427 (stop filing a class once the repo has a gate or policy for it) and hivecommons/hive#13428 (after three same-class findings, propose the gate instead of a fourth finding). Once those land, the lanes will honour the gates you added here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stage/040-covered-by-prAn open PR covers this issuetech-debtCreated by Hive for agent-filed issue provenancetestingApproved by a Hive merger/owner for auto-merge on green CI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions