Skip to content

Fix broken release packaging, test the fragile core, and polish to a higher bar - #15

Merged
ShiosOS merged 10 commits into
mainfrom
cursor/professional-polish-fixes-1cf5
Jul 14, 2026
Merged

Fix broken release packaging, test the fragile core, and polish to a higher bar#15
ShiosOS merged 10 commits into
mainfrom
cursor/professional-polish-fixes-1cf5

Conversation

@ShiosOS

@ShiosOS ShiosOS commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

A critical repo-wide review surfaced one release-breaking bug, several correctness gaps, and a structural testing hole. This PR fixes all of them across two passes.

Pass 1 — correctness and hygiene

Release packaging shipped a broken extension (the important one)

manifest.json loads checks.js as a content script, but the hand-maintained INCLUDE list in scripts/build.mjs never picked it up — so every .zip/.xpi produced by npm run build (including the tag-triggered release workflow) shipped without the status-checks helpers that content.js depends on.

Rather than appending the missing filename, the packaged file list is now derived from manifest.json (content scripts, background scripts, icons, popup, plus the popup's <script src> tags), the build fails loudly if a referenced file is missing on disk, and test/build.test.mjs runs the real build in CI and asserts the archive contents. This class of bug can't silently recur — proven later in this PR, when the new pages.js module was picked up by the build automatically.

Behavior fixes

  • Stale checks indicator — GitHub updates check-row aria-labels in place (running → successful) without structural DOM changes, so the childList-only body observer never refreshed the indicator. It now also watches aria-label attribute mutations.
  • Popup desync — the popup didn't listen to chrome.storage.onChanged, so toggling via the in-page button left an open popup showing the wrong active state.
  • Unvalidated stored preference — a corrupted storage value could make the button label disagree with the actual sort. A shared normalizeOrder() now coerces anything unrecognized to newest at both read sites.

Pass 2 — raising the bar on the core

The fragile heart of the extension is now tested

The GitHub DOM selectors — the code that breaks every time GitHub ships a UI change, and the repo's #1 maintenance burden — lived untested inside content.js. They now live in pages.js (same UMD pattern as the other modules) with jsdom fixtures mirroring the real Conversation, modern React Commits, and legacy Rails Commits structures, plus URL-routing tests. content.js shrinks to observer/storage/UI glue.

background.js got the same treatment: logic in a factory that tests exercise against a stubbed chrome API (listener registration stays synchronous at load, per MV3 service-worker rules). Tests cover URL matching — including rejecting /files, /checks, commit permalinks, and non-GitHub hosts — icon selection, tab events, and the runtime.lastError path.

Test count goes from 28 to 79, and both modules join the enforced coverage gate (now 96% statements across five modules).

Checks-state false positives

The failure regex matched bare substrings, so a passing check named failover-suite or cancellation-service was reported as failing. Status words now match as explicit inflected phrases behind word boundaries, with regression tests for embedded-status-word names and every phrase GitHub actually emits.

Everything else

  • init() no longer swallows storage failures as an unhandled rejection; stored-order and checks-state types tightened from string to unions.
  • CI matrix now tests Node 22 (the engines floor) alongside 24, and checkout uses persist-credentials: false.
  • The popup follows prefers-color-scheme instead of forcing dark colors on light-mode users.
  • Accessibility: plain-text aria-labels on the injected toggle and indicator, which previously conveyed state via glyphs and color only.
  • The orphaned icon-128-disabled.png is wired into the action icon set; README documents checks.js/pages.js and the selector-maintenance workflow; package.json gains repository/homepage/bugs; npm audit fix cleared seven undici advisories (dev-only tree); CHANGELOG updated.

Verification

format:check, lint, typecheck (strict tsc --checkJs), coverage (79 tests, all thresholds met), and build all pass; the built archive was inspected and contains all 15 manifest-referenced files.

Not done here (possible follow-ups)

  • Replace the placehold.co README screenshot with a real capture.
  • CONTRIBUTING.md / issue and PR templates.
  • Browser-level E2E (e.g. Playwright or web-ext) for the remaining content.js/popup.js glue and real-GitHub smoke testing.
Open in Web Open in Cursor 

cursoragent and others added 9 commits July 14, 2026 17:32
The hand-maintained INCLUDE list in scripts/build.mjs had fallen out of
sync with manifest.json: checks.js was loaded as a content script but
never packaged, so published .zip/.xpi builds shipped with the
status-checks helpers missing. Derive the file list from the manifest
(content scripts, background scripts, icons, popup, and the popup's
<script src> tags), fail the build if any referenced file is missing,
and add a packaging test that inspects the real archive in CI.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
icon-128-disabled.png existed in the repo but was referenced nowhere;
add both 128px variants to the action icons so high-DPI toolbars get a
crisp icon and the asset ships for a reason.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
- normalizeOrder() in constants.js coerces whatever comes out of
  chrome.storage into a valid order value, so a stale or corrupted
  entry can no longer desync the toggle label from the sort behavior.
- The popup mirrors chrome.storage.onChanged, so toggling via the
  in-page button updates an open popup immediately.
- The body observer also watches aria-label mutations: GitHub updates
  check-row labels in place (running -> successful) without structural
  changes, which previously left the checks indicator stale.
- The injected toggle and checks indicator get plain-text aria-labels;
  the visible text leans on glyphs and color alone.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
- README: document checks.js in the file table, list the typecheck
  script, and correct the test command description.
- package.json: add repository, homepage, and bugs fields.
- CHANGELOG: record the packaging fix and behavior changes under
  Unreleased.
- npm audit fix: bump transitive undici (jsdom) past known advisories.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
The selectors that break when GitHub ships UI changes — the extension's
main maintenance burden — lived untested inside content.js. They now
live in pages.js (same UMD pattern as the other modules) with jsdom
tests whose fixtures mirror the real Conversation, modern React
Commits, and legacy Rails Commits structures, plus path-routing tests.
content.js shrinks to observer/storage/UI glue.

background.js gets the same treatment: logic in a factory that Node
tests exercise against a stubbed chrome API, with listener registration
kept synchronous at load (an MV3 service-worker requirement). Tests
cover URL matching (incl. rejecting /files, /checks, commit permalinks,
non-GitHub hosts), icon selection, tab-event handling, and the
runtime.lastError path.

Both modules join the coverage gate; content.js also stops silently
swallowing storage failures at init (logs instead of an unhandled
rejection), and the stored-order/checks-state types tighten from string
to unions.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
A passing check named e.g. failover-suite or cancellation-service was
reported as failing because the failure regex matched bare substrings.
Match explicit inflected status phrases behind word boundaries instead,
with regression tests for embedded-status-word names and for every
inflected form GitHub actually emits.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
Run the matrix on Node 22 (package.json engines floor) and 24 so an
engines violation can't slip through, and pass persist-credentials:
false to checkout since no CI step needs the token after clone.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
The popup hardcoded GitHub dark-mode colors, which looked out of place
for light-mode users. Move the palette to custom properties with a
prefers-color-scheme override and declare color-scheme so form controls
match.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
@cursor cursor Bot changed the title Fix broken release packaging and polish extension behavior Fix broken release packaging, test the fragile core, and polish to a higher bar Jul 14, 2026
@ShiosOS
ShiosOS marked this pull request as ready for review July 14, 2026 17:53
cursor[bot]
cursor Bot approved these changes Jul 14, 2026
Splitting the check job into a Node 22/24 matrix renamed its check runs
to 'check (22)' / 'check (24)', so the branch-protection rule requiring
a status named 'check' waited forever ('Expected — Waiting for status
to be reported'). Add a merge-gate job that reports the stable 'check'
name and fails unless every matrix leg succeeded.

Co-authored-by: Julius Walton <ShiosOS@users.noreply.github.com>
@ShiosOS
ShiosOS merged commit 7283a84 into main Jul 14, 2026
9 checks passed
@ShiosOS
ShiosOS deleted the cursor/professional-polish-fixes-1cf5 branch July 14, 2026 18:25

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: medium. Cursor Bugbot completed successfully with no findings requiring human review. Approved; no reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@ShiosOS ShiosOS mentioned this pull request Jul 14, 2026
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.

2 participants