Skip to content

Open source 1.0: README, example, agent skill, docs and the React publish workflow - #4

Merged
lightninglu10 merged 6 commits into
mainfrom
oss-release-3524bf47
Nov 5, 2026
Merged

lightninglu10 merged 6 commits into
mainfrom
oss-release-3524bf47

Conversation

@lightninglu10

@lightninglu10 lightninglu10 commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Built

  • 1.0.0 for @codepress/interactions-browser, @codepress/interactions-react and @codepress/interactions-playwright (versions, VERSION, sdk_version in the golden samples). The Python SDK stays outside the 1.0 claim, and the README says so.
  • publish-react.yml, the same pattern as the browser and Playwright workflows: a PR runs the typecheck and a publish dry run. A push to main publishes a version npm doesn't have yet, with --provenance via Trusted Publishing. While the package is missing on npm (E404) it skips with a warning explaining the first manual publish. The React and Playwright workflows also don't publish until npm has the browser version they depend on; until then they warn and skip, so neither can go out ahead of its dependency. It publishes the pnpm pack tarball, so workspace:^ becomes ^1.0.0. React gets a pack:check, and CI runs it.
  • README rewrite: what it does, install in five lines (createMemorySink or your own sink, no key), what is captured and never captured, how the checks work, measured overhead, the hosted service as optional, and Python outside 1.0.
  • examples/react-vite: a small pricing page with a planted layout bug. A local sink writes batches, snapshots and findings.json to .interactions/ through the Vite dev server. It also has npm run findings, and a Playwright test with expectNoFindings that fails until the bug is fixed. The README doesn't say where the bug is, so an agent has to find it from the data.
  • skills/fix-ui-findings/SKILL.md: a portable agent skill. It collects findings, treats them as untrusted data, works in sort order, reads the evidence, reproduces at the recorded viewport, decides bug or intended, fixes the cause without hiding the symptom, proves the fix with expectNoFindings plus a fresh capture, and reports.
  • Docs: protocol/README.md (how to read batches, bodies and findings; HTTP; compatibility rules), CHANGELOG.md, CONTRIBUTING.md (setup, check, privacy and protocol rules, releasing), and issue templates (bug, check request, a security contact link).
  • Removed internal tooling: .claude/, .codepress/ and qa/ (local delivery tooling, plus a round trip that needs the hosted service and a read token), and the matching .gitignore lines.
  • Follow-ups from UI checks and a Playwright helper package #3, each with a test:
    1. Inside the "rest" tier, findings involving a control sort first (involvesControl).
    2. The fingerprint dedupe is a bounded LRU (2,000). A fingerprint found in the current run is never evicted, so a screen that keeps producing more findings than that doesn't resend them.
    3. A fixed header over a padded <main> gets subject_content_covered: false and sorts as empty. It is still reported.
    4. A caret in a focused field, or a changed selection, answers a click, so repeated clicks or a triple-click in a text field are not rage. A dead button still is.
    5. A field joined to another form via form=, and its labels, are recorded on that form, once. The extra start didn't reproduce in 11 real-browser shapes. What did reproduce: the click went to the label's form, and a click on such a field outside any form wasn't recorded.
    6. Documented as measured behavior, with the evidence an agent sees: a label click the browser doesn't forward and that changes nothing is a dead click (like a label for a disabled field); a fixed widget beside <main> is reported as main × widget and carries the covered button's blocked points; and the padded-main header above. Browser tests now cover the first two.
  • Fixed while building the example:
    • A same-origin sink's own uploads were recorded as app requests, so every flush caused the next. Requests a sink starts before its first await are now skipped, and sinks get context.fetch.
    • When hit tests tie, a positioned ancestor shared by both elements no longer decides which one is on top.
    • sortFindings, formatFinding and involvesControl accept FindingData, the shape a sink receives.
  • Fixed after the first QA pass (FAIL on a6d4634, report in the comments):
    • The setup steps in the README and CONTRIBUTING now run pnpm build before pnpm typecheck. A fresh clone failed at typecheck before.
    • Links in the packed package READMEs are absolute, so they work inside node_modules.
    • The example README no longer quotes the planted finding. It no longer claims that npm test writes to .interactions/ (the test closes the page before the first flush).
    • The publish ordering guard described above.
    • involvesControl is true for an outer pair that blocks a control inside its subject (main × widget), with a test.
    • Smaller wording fixes: warning, not notice; Node 20.19+ / 22.12+; current bundle size.
  • pnpm --filter @codepress/interactions-browser bench: the overhead benchmark behind the README numbers.

Verified

  • Tests: after pnpm build (the README's and CONTRIBUTING's setup order, the same as CI's), pnpm typecheck, pnpm test (66 unit tests) and pnpm test:browser pass: 66 browser tests passed and 1 skipped, plus 6 Playwright helper tests. actionlint is clean on all workflows.
  • Criterion "clean scratch app, no CodePress service: snapshots and the planted bug's finding in local JSON": verified with packed 1.0.0 tarballs, not the registry (see below). The example was copied out of the repo, installed from the three pnpm pack tarballs, with no endpoint and no key:
    npm install                    -> added 31 packages
    npm run typecheck              -> ok
    npx playwright test (unfixed)  -> exit 1
      Error: 1 UI finding on /. Pass a fingerprint in ignoreFingerprints to accept one.
      "layout.overlap plan-pro-cta × plan-pro-badge on / @1280x720: ... subject_blocked_points=2 subject_tested_points=5 subject_blocked_controls=1 subject_text_covered ... [d4aa001353afa3e3fd42ccf1902bf625]"
    dev server + headless Chromium page load, 12 s:
      .interactions/batches/a571d366-….json
      .interactions/snapshots/388c4dec….json
      .interactions/findings.json
      batches 1 {"ui.snapshot":1,"perf.summary":1,"ui.finding":1}   # no request.* events: the sink no longer feeds itself
      findings 1 layout.overlap plan-pro-cta plan-pro-badge d4aa001353afa3e3fd42ccf1902bf625
    npm run findings               -> the same line, "1 finding"
    fix applied (badge moved to the card's top edge)
    npx playwright test            -> 1 passed
    fresh .interactions + reload   -> "0 findings", fingerprint absent from every file
    
  • Criterion "a coding agent given the skill and the example fixes the planted bug, and expectNoFindings passes": a separate agent got only the skill and the example. It read findings.json, reproduced the finding at 1280×720, moved .plan-badge from bottom: 30px to top: -14px, and got npm test → 1 passed. A reload then showed 0 findings. At the time, the example README still had a collapsed spoiler naming the bug. The agent says it reproduced and decided on its own, but that run wasn't blind. The spoiler is removed now, and the independent QA pass reruns this blind.
  • Criterion "a new reader following the README literally hits no undocumented step": the example README was followed step by step twice, by the agent above and in the run above. Every step works, except that npm install needs the packages on npm (see below). The root README's install snippet matches the SDK: a sink alone, with no projectKey or endpoint, starts capture. The independent QA pass covers a fresh read.
  • Criterion "no internal hostnames, org names, fixture repos or credentials in the repo or the tarballs": I searched with a pattern covering internal hostnames, org and product names, delivery-tool names, local paths, private IP ranges and credential formats (AWS, GitHub, Slack, npm and API keys, private keys):
    ## working tree at HEAD (git grep, excluding lockfiles)
    (no matches)
    ## lockfiles
    pnpm-lock.yaml:4      # all "lightningcss", a Vite dependency
    ## packed tarballs (browser, react, playwright 1.0.0)
    (no matches)
    ## all hosts in the tree at HEAD
      11 http://localhost       10 https://github.com      10 http://www.apache.org
       6 https://app.test        5 https://json-schema.org  4 https://telemetry.test
       3 https://registry.npmjs.org   2 https://telemetry.example.com   2 https://telemetry.example
       2 https://shop.test      2 https://interactions.example.com   1 https://unreachable.invalid
       1 https://third-party.test   1 https://semver.org   1 https://other.example
       1 https://docs.astral.sh     1 http://www.w3.org
    ## all hosts in the tarballs
       6 http://www.apache.org   3 https://github.com   2 https://interactions.example.com
    
    Every github.com link points at this repository. History is covered below.
  • Security contact: private vulnerability reporting is on (gh api repos/quantfive/codepress-interactions/private-vulnerability-reporting → {"enabled":true}), so CONTRIBUTING's "Report a vulnerability" route and the issue-template contact link work.
  • Tarball contents (pnpm pack): each is 1.0.0 and Apache-2.0, containing only dist/, README.md, LICENSE and package.json. React and Playwright depend on @codepress/interactions-browser ^1.0.0, with peer dependencies react >=18 and @playwright/test >=1.40.
  • Overhead: headless Chromium on an Apple M1 Max, median of 5 runs. Full table in the README.
    • Bundle: 23.9 KB gzip.
    • Click listener: 0.09 ms (0.47 ms at 4× throttle).
    • Snapshot walk: slices ≤ 8 ms, no long tasks.
    • Checks: one idle task of 14 ms at 1× and up to 50 ms at 4× on a 5,000-element page. The README states this rather than claiming all work is sliced.

Could not verify

  • npm view showing 1.0.0 with the right license and files: none of the three packages are on npm yet. The first publish has to be done by hand, then each workflow added as the package's trusted publisher. Today:
    $ npm view @codepress/interactions-browser version license
    npm error code E404
    npm error 404 Not Found - GET https://registry.npmjs.org/@codepress%2finteractions-browser - Not found
    (same E404 for -react and -playwright)
    
    Until then, the example's npm install, and "installed from npm only", work only with local tarballs. That was verified above.
  • History: commits already on main still contain the removed .claude/ and .codepress/ files (internal delivery-tool names and instructions). The search found no hostnames or credentials in history. Removing them would mean rewriting public main, which this PR doesn't do.
  • Browsers: everything ran in Chromium only, not Firefox, Safari or a headed desktop browser.

- rank findings that involve a control first inside the rest tier
- remember sent fingerprints by recency: refresh on repeat, never evict one seen in the current run
- record subject_content_covered on overlaps so a fixed header over a padded main sorts as empty
- count a caret in a focused field or a selection change as an answer for rage_click (new selection_changed)
- resolve a field's control through its form owner, so a label click on a field joined with the form attribute is one start on that form
.claude, .codepress and qa served our own delivery and a hosted-service round trip
that outsiders cannot run. publish-react.yml mirrors the playwright workflow: it
skips while the package is missing on npm and publishes with provenance from main.
…ak, and accept wire findings

- requests a sink starts before its first await are not recorded, and sinks get
  context.fetch (the page's fetch without the SDK wrapper) for later ones. a
  same-origin sink made every flush record requests that caused the next flush.
- when hit tests tie, a positioned ancestor shared by both elements no longer
  counts for either, so a pointer-events: none badge over a static button in a
  relative card is reported over the button, not under it.
- sortFindings, formatFinding and involvesControl take FindingData, as sinks
  receive it.
- browser tests pin the documented label dead click and the fixed widget beside
  main.
…d the project docs

- README: what it does, install, what is and is never captured, how the checks
  work, measured overhead, the hosted service as optional, Python outside 1.0.
- examples/react-vite: a small app with a planted layout bug and a local sink
  that writes batches, snapshots and findings to .interactions/.
- skills/fix-ui-findings: a portable skill to read, reproduce, fix and prove
  findings.
- protocol guide, changelog, contributing guide, issue templates, the overhead
  benchmark (pnpm --filter @codepress/interactions-browser bench), and browser
  README notes on the 1.0 behaviors.
@codepress-reviewer-dev

Copy link
Copy Markdown

Starting initial review of a6d4634a from baseline c265741e... 👀

View automation run

@codepress-reviewer-dev codepress-reviewer-dev 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.

Review

I read the SDK source changes (click-effects, detect, runtime, sink, util), the publish workflow and the example's local sink in full. I skimmed the docs, templates and skill. No blocking issues.

Architecture: keep current. This is a release-prep PR (docs, example, skill, workflow) plus small SDK follow-ups, each with tests. The PR is large but cohesive, so I am not asking for a split.

What looked right

  • RecentKeys evicts the least recently seen key and never evicts one seen in the current run, which stops a run that produces more than 2,000 findings from resending them on every run.
  • sinkDepth is set only for the sink's synchronous part, which matches the documented "before the first await" contract. context.fetch is the unwrapped fetch, so it covers the async case.
  • controlOf for form= fields is a contained change. The label-click path falls back to the label's own control only when the field has no control.
  • The example's local sink validates batch_id and the sha256, caps the body size, and checks that the snapshot hash matches the body. It writes only under .interactions/, so there is no path traversal. It applies to serve only.
  • publish-react.yml follows the browser and Playwright workflows: OIDC with id-token: write only on the publish job, no persisted credentials, and a publish of the packed tarball. A missing package (E404) skips cleanly.

One nonblocking suggestion is attached about checking that the browser dependency is on npm before the React publish.

The PR description already lists what could not be verified: npm publication, private vulnerability reporting being off, and Chromium-only runs. I agree these need action outside this PR.

Reviewed `c265741e`...`a6d4634a`. Diff collection and GitHub posting were handled by the automation.

View automation run

@codepress-reviewer-dev

codepress-reviewer-dev Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Review head 16b3f1cfce439e7d2de03110cd1e472d6a22a259; round 3; 55 reviewed file(s), 0 pending/skipped file(s). 1 subsystem record(s) retained; 0 omitted.

View automation run

@lightninglu10

Copy link
Copy Markdown
Contributor Author

QA verification: PR #4 (open source 1.0)

PR Head SHA: a6d4634a09fa66c55abef0437afcaca0a0991593

An independent check of oss-release-3524bf47 against main, on a fresh clone of the public repository. The three packages were packed from the PR branch with pnpm pack, because none of them is on npm yet. Every claim below comes from a command I ran. Logs are named by file (for example 15-agent-test-unfixed.log), and the B5-* and B6-* logs come from a parallel helper run of the same verifier.

Verdict

  • 1. Clean scratch app, local JSON, no service: PARTIAL. The example was copied out of the repo and installed from the packed 1.0.0 tarballs, with no endpoint and no key. It wrote batches, a snapshot and findings.json holding the planted finding. Installing from the npm registry is UNVERIFIED (E404).
  • 2. READMEs followed literally: FAIL. The README's Development steps fail at step 2 on a fresh clone: pnpm typecheck runs before pnpm build, which the README does not say is needed. Both npm install steps fail with E404 until the first publish. One example README claim is untrue. Every other step worked as written.
  • 3. Blind agent fix with the skill and the example: PASS. Using only SKILL.md and the example's files, I found the overlap in findings.json and reproduced the same fingerprint. I fixed the CSS cause. expectNoFindings then passed and a fresh capture had 0 findings.
  • 4. Negative search: PASS for the tree at HEAD, the lockfiles and the tarballs: no credentials, local paths, private IPs, internal hostnames, or internal org or product names. Git history (not part of the verdict, as briefed) still holds the removed internal delivery-tool files. They contain internal tool names but no hostnames or credentials.
  • 5. npm view and tarballs: UNVERIFIED. npm view gives E404 for all three packages. The tarballs themselves pass: version 1.0.0, Apache-2.0, only dist/, README.md, LICENSE and package.json, and dependency ranges ^1.0.0 with no workspace:.
  • Repo's own checks: PASS, but only in CI's order. On a fresh clone, pnpm typecheck fails until pnpm build has run. After the build: typecheck OK, 66 unit tests, 66 browser tests passed plus 1 skipped (the golden regenerator), and 6 Playwright helper tests.

Contract rows

Row Verdict Evidence class One-line reason
B1 PASS live-browser A real Chromium load of the tarball-installed example wrote batches/*.json, snapshots/<sha>.json and findings.json, holding layout.overlap plan-pro-cta × plan-pro-badge.
B2 PASS live-browser A 14 s load with the 2 s flush wrote 1 batch and 0 request.* events. A scratch sink that uses window.fetch after an await wrote 6 batches and 12 request.* events (each flush feeding the next).
B3 PASS live-browser (Playwright CLI) The test fails on the planted bug with one fingerprint and passes after the fix. With pointer-events: none alone it still fails, with the same fingerprint and the text still covered.
B4 PASS live-browser My own blind run (criterion 3).
B5 PASS live-browser (a) to (g) were all observed on small pages built against dist/.
B6 PASS live-browser 2,100 new fingerprints in one run sent 2,000. An evicted fingerprint was resent, and a remembered one was not.
B7 PASS live-browser The README snippet, bundled against the tarball: after a click and flush(), 1 batch and 2 snapshots, with no page text.
B8 PASS live-ci + inspection The PR run did "Test and pack", then a publish dry run of @codepress/interactions-react@1.0.0; "Publish to npm" was skipped. The diff against the Playwright workflow differs only in package names and its browser-test steps.
B9 PASS live-cli The tree, lockfiles and tarballs are clean. .claude/, .codepress/ and qa/ are absent at HEAD. The history note is under criterion 4.
B10 UNVERIFIED live-cli npm view gives E404 (expected before the first publish). The tarball checks pass.
B11 FAIL live-cli + inspection The HTTP calls, gzip, privacy, bundle method and the benchmark script all match the docs. But the README and CONTRIBUTING setup order fails on a fresh clone, and one example README claim is false (see Problems).

Evidence

Repo checks (logs 02 to 08, 70 and 71)

pnpm install                       -> exit 0
pnpm typecheck  (fresh clone)      -> exit 2
  packages/react typecheck: src/index.ts(6,8): error TS2307: Cannot find module '@codepress/interactions-browser' ...
pnpm test                          -> Test Files 3 passed (3), Tests 66 passed (66)
pnpm --filter @codepress/interactions-browser exec playwright install chromium -> exit 0
pnpm build                         -> exit 0
pnpm typecheck  (after build)      -> exit 0
pnpm test:browser                  -> browser: 66 passed, 1 skipped (golden.spec.ts, skipped unless UPDATE_GOLDEN); playwright: 6 passed

I reproduced the typecheck failure on a second fresh clone (71-repro-fresh-typecheck.log). CI does not hit it, because ci.yml runs "Build browser package" before "Typecheck".

Criterion 3 / B4: blind agent run (logs 10 to 21)

Before reading the PR description, the diff, the CHANGELOG or the git log, I read only skills/fix-ui-findings/SKILL.md and the files in examples/react-vite/. I copied the example out of the repo, pointed its three @codepress/* dependencies at the tarballs, and moved the port to 5174 (see Not verified).

  1. Collect. npm run dev, a headless Chromium load at 1280x720 for 7 s, then npm run findings:

    layout.overlap plan-pro-cta × plan-pro-badge on / @1280x720: overlap_px=3006.36 ... subject_blocked_points=2 subject_tested_points=5 subject_blocked_controls=1 subject_text_covered ... [d4aa001353afa3e3fd42ccf1902bf625]
    1 finding
    

    That made 1 batch (ui.snapshot, perf.summary, ui.finding), 1 snapshot and findings.json.

  2. Triage (skill step 3). Tier 0: a blocked control. The subject (the CTA button, static) sits under the other element (the badge span, position: absolute), and common_parent_positioned is true.

  3. Reproduce. A screenshot at 1280x720 shows the "Most popular" badge over the right end of the "Start free trial" button (example-before-fix-1280x720.png). npm test on the unfixed code: exit 1, Error: 1 UI finding on /. with the same fingerprint d4aa0013….

  4. Cause. In src/styles.css, .plan-badge is position: absolute; right: 24px; bottom: 30px inside the position: relative card. That pins it over the CTA, which margin-top: auto pushes to the card's bottom.

  5. Fix. Change bottom: 30px to top: -14px, pinning the badge to the card's top edge (16-agent-fix.diff). No pointer-events, z-index, overflow or ignore was used.

  6. Prove.

    • A throwaway spec ran findIssues at 375x667 (touch), 800x720, 1280x720 and 1600x900: 0 findings at each.
    • npm test: 1 passed.
    • npm run typecheck: exit 0.
    • I moved .interactions aside, reloaded and waited 7 s: npm run findings gives 0 findings.
  7. Privacy. In the stored batches and snapshots, page strings ("Most popular", "Start free", "Pick a plan", "Example Notes"), localhost and http each appear 0 times.

The skill was enough to finish without guessing. The only friction: the example's README "Test it" section quotes the finding line (both test IDs), so the bug is not as hidden as "The planted bug" section says (see Problems).

Criterion 1 / B1 (logs 10 to 13, 26 to 31)

I did this twice: in the copied-out app above, and in the example inside a fresh clone. npm install from the tarballs works without overrides: npm dedupes @codepress/interactions-browser@1.0.0 under react and playwright. A real browser load writes:

.interactions/batches/<uuid>.json      events: ui.snapshot, perf.summary, ui.finding
.interactions/snapshots/388c4dec…json  schema_version 2, route_template "/", 1280x720, element boxes, no text
.interactions/findings.json            1 entry: layout.overlap, subject plan-pro-cta (button, static), other plan-pro-badge (span, absolute), fingerprint d4aa001353afa3e3fd42ccf1902bf625, last_seen set

Clicking plan-free-cta and sign-in added interaction.started ×2, ui.click.settled ×2, ui.snapshot ×2 and ui.state.changed (32-readme-click.log).

Criterion 2: READMEs followed literally (logs 23 to 39)

  • Root README, "Install": npm install @codepress/interactions-browser gives npm error code E404.
  • Root README, "Development": fails at pnpm typecheck (above).
  • Example README, "Run it":
    • npm install gives E404. I deviated by installing the tarballs.
    • npm run dev worked (on 5174, my deviation).
    • Before any load, npm run findings prints the documented hint.
  • "Look at the data": the files and npm run findings output match the README.
  • "Test it":
    • npx playwright install chromium worked.
    • npm test fails as documented: the first line matches exactly, and the finding line appears inside an array diff.
    • The claim "reuses the one from npm run dev … then the test's page view lands in .interactions/ too" did not hold. The batch count stayed at 3 across two npm test runs against the running server, and the server logged no new upload (35- and 36-readme-test-unfixed*.log).
  • "Let an agent fix it": after the fix, npm test gave 1 passed. With .interactions moved aside and the page reloaded, npm run findings gave 0 findings, and the fingerprint appeared in 0 files.
  • Typecheck: the example's npm run typecheck passes.

B2: sink self-requests (logs 40 to 44)

example sink (context.fetch), 14 s load:   batch files: 1   event types: {ui.snapshot: 1, perf.summary: 1}   request events: none
scratch sink (await Promise.resolve(); window.fetch(...)), 14 s load:
  browser POSTs: 1 snapshot + 6 batches
  batch files: 6   event types: {request.started: 6, request.completed: 6, ui.snapshot: 1, perf.summary: 1}
  sample: {"type":"request.completed","data":{"outcome":"completed","phase":"http_204",...}}  (the local sink's 204)

B3: pointer-events alone is not a fix (logs 45 and 46)

Adding only pointer-events: none to .plan-badge still fails, with the same fingerprint d4aa0013…. The evidence becomes subject_blocked_points=0 subject_blocked_controls=0, while subject_text_covered and other_pointer_events_none are set. Playwright started the dev server itself for this run.

B5 and B6: live behaviors on small pages against dist/ (logs B5-01 to B5-09, B6-02)

  • (a) I clicked 4 times in a focused text field, then triple-clicked it. All 7 ui.click.settled events had field_focused=true, selection_changed was true on the first click and the triple-click, and no rage finding came back. As a positive control, 4 rapid clicks on a dead button gave click.rage_click with control_ids:["dead"] and click_count=3 clicks_with_feedback=0.
  • (b) A fixed header over <main style="padding-top:64px"> gave layout.overlap main × header with subject_content_covered:false, subject_text_covered:false, subject_blocked_points:0 and findingTier = 3.
  • (c) One page produced two tier-2 findings. sortFindings on reversed input returned layout.offscreen_control (a control) before layout.page_h_scroll, which reverses the check order.
  • (d) A label in form A for a checkbox with form="b" gave 1 interaction.started, with control_ids:["B"]. A wrapping-label variant behaved the same.
  • (e) Clicking the label of a disabled field gave 1 interaction.started and one click.dead_click with control_id:"signup".
  • (f) A fixed widget that is a sibling of <main> and covers a button gave main × chat with subject_blocked_points=3, subject_blocked_controls=1 and tier 0. It sorted first against a tier-1 finding.
  • (g) A pointer-events:none absolute badge over a static button in a relative card gave exactly one finding: subject buy (the button), other badge, other_pointer_events_none:true.
  • B6:
    • Run 1: 2,100 new pairs sent 2,000 (P0 to P1999; P2000 to P2099 waited).
    • Run 2: 100 new pairs sent 100.
    • Run 3: the evicted P0 was resent.
    • Runs 4 and 5: P600 and Q5, still remembered, sent 0.
    • Run 6: the waiting P2000 was sent.
    • One flush() sends one batch of at most 60 KB, so draining a large backlog takes several flushes. This is documented behavior.

B7: README install snippet (logs 47 to 49)

The snippet was bundled verbatim (plus window.__qa = { sink, handle }) against the tarball and served on a local port. After a click and handle.flush(), the memory sink held 1 batch and 2 snapshots. The events were ui.state.changed, ui.snapshot, perf.summary, interaction.started, ui.state.changed, ui.snapshot and ui.click.settled. Diagnostics showed acceptedBatches: 1, and none of the page's text appeared in the output.

B8: React publish workflow (logs 50 to 55)

Publish React adapter      head=a6d4634… :: Test and pack=success, Publish to npm=skipped
Publish Playwright helpers head=a6d4634… :: Test and pack=success, Publish to npm=skipped
Publish browser SDK        head=a6d4634… :: Test and pack=success, Publish to npm=skipped
CI                         head=a6d4634… :: Python tests and lint=success, Typecheck, unit and browser tests=success
react run: "packed dependency: @codepress/interactions-browser ^1.0.0"; RELEASE: false
  npm notice name: @codepress/interactions-react  version: 1.0.0  total files: 7
  npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access (dry-run)

The diff of publish-playwright.yml against publish-react.yml differs only in the name and comments, the path filters, PACKAGE, the working directories and build filter, and the Playwright-only "Install Chromium" and "Browser tests" steps. The E404 branch sets EXISTS=false. On a PR it falls through to a dry run. On a push it emits the warning and doesn't publish (inspection; a PR run can't exercise it).

Criterion 4 / B9: negative search (logs 59 to 64)

Search categories:

  • Credential formats: AWS access keys, GitHub tokens and PATs, Slack tokens and webhooks, npm tokens and _authToken, OpenAI and Stripe-style keys, Google API keys, private key blocks, generic api/secret/access key|token = "<long value>", and JWTs.
  • Local user paths (macOS, Linux, Windows).
  • Private and CGNAT IP ranges.
  • Internal domain suffixes and staging hosts.
  • The operator's username and name.
  • Internal product, environment and tool names known to the verifier.

Results:

tree at HEAD (excluding lockfiles): 0 matches
lockfiles:                          0 matches
extracted tarballs:                 0 matches
.claude/ .codepress/ qa/ at HEAD:   absent (0 tracked files)
history (all 20 revisions, all branches): 2 distinct lines, both in the removed .claude/skills/verify-local/SKILL.md (internal delivery-tool command names)

The removed files are .claude/skills/verify-local/SKILL.md, .codepress/verify-local/recipe.json, qa/README.md and qa/roundtrip.py. They describe internal delivery tooling and internal agent-tool names. qa/roundtrip.py reads its keys and read token from environment variables, and no values are committed.

Every hostname found:

  • Tree at HEAD: files.pythonhosted.org and pypi.org (in python/uv.lock), github.com (every link is quantfive/codepress-interactions), www.apache.org, app.test, localhost:3000, json-schema.org, telemetry.test, registry.npmjs.org, localhost:5173, telemetry.example.com, telemetry.example, shop.test, interactions.example.com, localhost, unreachable.invalid, third-party.test, semver.org, other.example, docs.astral.sh and www.w3.org.
  • Tarballs: www.apache.org, github.com/quantfive/codepress-interactions and interactions.example.com.
  • History only: 127.0.0.1, YOUR_TELEMETRY_HOST and YOUR_API_HOST (README placeholders), and unconfigured.example.test.

No internal hostname appears anywhere.

Criterion 5 / B10: tarballs and npm (logs 09, 56 to 58)

codepress-interactions-browser-1.0.0.tgz:    LICENSE README.md package.json dist/{index,detect,page-script}.{js,cjs,d.ts,d.cts} + chunk + types
codepress-interactions-react-1.0.0.tgz:      LICENSE README.md package.json dist/index.{js,cjs,d.ts,d.cts}
codepress-interactions-playwright-1.0.0.tgz: LICENSE README.md package.json dist/index.{js,cjs,d.ts,d.cts}
all: version 1.0.0, license Apache-2.0, publishConfig.access public, repository quantfive/codepress-interactions
react:      dependencies @codepress/interactions-browser ^1.0.0, peer react >=18
playwright: dependencies @codepress/interactions-browser ^1.0.0, peer @playwright/test >=1.40
"workspace:" in any tarball file: none.   dist VERSION = "1.0.0"
$ npm view @codepress/interactions-{browser,react,playwright} version license dist.tarball
npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/@codepress%2finteractions-<name> - Not found   (all three)

B11: docs truth (logs 65 to 69)

  • HTTP: protocol/README.md describes POST /v2/batches, then HEAD /v2/snapshots/{sha256}, then a gzip PUT only on 404. That matches sink.ts (HEAD, PUT, Content-Encoding: gzip when compressed) and util.ts (CompressionStream, or null). "1 to 200 events" matches the schema's minItems: 1 and maxItems: 200.
  • Privacy: the repo's privacy.spec.ts passed (sentinel in text, values, title, href query and alt). My own greps of the example's stored data and the snippet's sink output found no page text. Selection tracking compares only anchor and focus nodes and offsets, never the selected text.
  • Benchmark: pnpm --filter @codepress/interactions-browser bench --runs 1 --clicks 20 ran (exit 0) and printed its machine, as the README says.
    • Bundle: index 68,683 B minified and 24,627 B gzip (24.0 KiB; the README says 66.7 KB and 23.9 KB). /detect 10,050 B gzip (9.8 KiB, matches).
    • Clicks at 1×: median 0.095 ms (README 0.09).
    • Idle at 1×: 0.76 ms of extra busy time.
    • At 4× on 5,000 elements: longest task 19.9 ms and cold checks 42.7 ms, both within the README's 30 ms and 50 ms. No long tasks.
    • Absolute numbers are machine-dependent.
  • Local sink edge cases (curl against the dev server):
    • bad hash: 400; good hash: 204
    • bad batch_id: 400; missing events: 400; not JSON: 400
    • 5.1 MB body: 413
    • GET: 405; unknown path: 404
  • Unit-test evidence (weaker class, listed separately): "bodies and batches written by 0.2.0 still validate" passed in pnpm test.
  • Private vulnerability reporting: gh api repos/quantfive/codepress-interactions/private-vulnerability-reporting returns {"enabled":true}.
  • Mismatches found: listed under Problems found.

DB Performance

DB performance verifier skipped: no backend DB-backed performance surface (inventory: browser SDK, docs, example dev server, CI workflow; no API routes, ORM, SQL, migrations or tasks).

Screenshot Status

Both screenshots are 1280x720, from the example page served by its dev server:

  • example-before-fix-1280x720.png: the "Most popular" badge sits over the right end of the Pro plan's "Start free trial" button.
  • example-after-fix-1280x720.png: the badge sits on the card's top edge, and the button is clear.

Problems found

  1. Fresh-clone setup fails at pnpm typecheck (root README "Development" and CONTRIBUTING "Setup"). packages/react type-checks against the browser package's dist, which doesn't exist until a build. CI hides this by building the browser package first. The PR description says pnpm typecheck passes, which is true only after a build.
    • Repro: clone, check out the branch, pnpm install, pnpm typecheck. You get packages/react … error TS2307: Cannot find module '@codepress/interactions-browser', exit 2.
    • Fix: run pnpm build (or pnpm --filter @codepress/interactions-browser build) before pnpm typecheck in both docs, or make the typecheck resolve sources.
  2. The packages are not on npm, so the root README's install and the example's npm install fail (E404). This is expected before the manual first publish, and the PR says so. Until then, criterion 1's registry part and a literal README run can't pass.
    • Repro: cd examples/react-vite && npm install gives npm error code E404 … @codepress%2finteractions-browser.
  3. The example README's claim about server reuse is not true as written. It says that when Playwright reuses the npm run dev server, "the test's page view lands in .interactions/ too". With the dev server running, npm test (passing or failing) added no batch and no snapshot, and the server got no upload. The test closes the page before the SDK's first flush.
    • Repro: npm run dev, load the page once, count .interactions/batches/*, run npm test, then count again: unchanged.
  4. The publish workflows don't enforce "the browser package goes first" (CONTRIBUTING, Releasing). The three publish-*.yml workflows are independent, triggered by path on push to main, with no workflow_run or needs between them. If one release bumps all three, React or Playwright can be published before the browser version they depend on. That breaks installs for a while, or for good if the browser publish fails.
    • Repro: grep -n "workflow_run\|needs:" .github/workflows/publish-*.yml shows only each workflow's internal needs: test.
  5. Relative links in the packed READMEs (../../protocol, ../../examples/react-vite, ../browser/README.md, ../../README.md) are broken inside node_modules. That is exactly where the skill sends an agent ("also shipped as node_modules/@codepress/interactions-browser/README.md"). npmjs.com may rewrite them; offline readers can't.
    • Repro: extract codepress-interactions-browser-1.0.0.tgz, then grep -n "](\.\./" package/README.md.
  6. The example README partly gives away the "hidden" bug. The "Test it" section quotes the expected failure line layout.overlap plan-pro-cta × plan-pro-badge … subject_blocked_points=2, while "The planted bug" section says it is deliberately not described. The data still has to be read to find the cause, so this is cosmetic.
  7. Minor doc inconsistencies:
    • CONTRIBUTING says a package missing on npm "is skipped with a notice". The workflow emits a ::warning::.
    • CONTRIBUTING says "Node.js 20 or later". The example needs 20.19+ or 22.12+, and says so.
    • The README bundle figures (66.7 KB / 23.9 KB gzip) are slightly below what the bench prints at HEAD (67.1 KiB / 24.0 KiB).
    • involvesControl is false for a main × widget finding that blocks a button inside main (B5 f). Order is unaffected because it is tier 0.

Not verified

  • Installing from the npm registry, and npm view (criteria 1, 2 and 5; B10). All three packages give E404. Everything was verified with pnpm pack tarballs from the PR branch, installed via file: dependencies, which is a deviation from the README.
  • The E404 warning branch on push to main. A PR run can't take it, so I checked it by inspection only.
  • Port 5173. I ran the example on 5174, changing vite.config.ts and playwright.config.ts in my copies, because the brief reserves 5173. With that change, "Playwright starts the dev server itself" and "reuses an existing server" both worked.
  • Browsers other than headless Chromium. All loads were headless Chromium driven by Playwright. Firefox, Safari and headed browsers were not tested.
  • keepalive on unload. Not exercised live.
  • The benchmark's absolute numbers. They depend on the machine. I ran the script once to confirm it works, not to reproduce the README's figures.
  • The Python SDK. Outside 1.0 per the README. I only saw CI's "Python tests and lint" pass.

Overall: FAIL

@codepress-dev

codepress-dev Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

👋 Hey @lightninglu10! Starting a new session to help with your request. View session

…ing guard, example README claims

Co-authored-by: lightninglu10 <2453737+lightninglu10@users.noreply.github.com>
@codepress-dev

codepress-dev Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Pushed 5dd8857 addressing the QA problems. I did not re-run the QA; these are docs and workflow changes, and CI is the check.

  1. Setup order: README and CONTRIBUTING now run pnpm build before pnpm typecheck.
  2. npm E404: unchanged. It resolves with the first manual publish, as the PR says.
  3. Example README: removed the claim that a reused dev server records the test's page view. It now says the test closes the page before the first flush and adds nothing to .interactions/.
  4. Publish ordering: the React and Playwright workflows now check that npm has the browser version in the checkout before publishing. If it is missing they warn and skip, and you re-run them after the browser package is out. CONTRIBUTING says so. This is not tested on a real push to main; a PR run cannot take that branch.
  5. Packed README links: relative links in the browser and Playwright package READMEs are now absolute GitHub URLs.
  6. Example README: no longer quotes the finding's elements or evidence; it only says the failure starts 1 UI finding on /..
  7. Minor: CONTRIBUTING now says "warning" and Node 20.19 or later (or 22.12 or later), and the README bundle size is 24.0 KB gzip (67.1 KB minified).

Not changed: involvesControl being false for a main × widget finding that blocks a button inside main. Order is unaffected (tier 0), so I left it. Tell me if you want it changed.

@codepress-reviewer-dev

Copy link
Copy Markdown

Starting new changes review of 5dd88575 from baseline a6d4634a... 👀

View automation run

@codepress-reviewer-dev codepress-reviewer-dev 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.

Review

I read the changes between a6d4634a and 5dd88575 in full. They touch the React and Playwright publish workflows, CONTRIBUTING, the root README, the example README and the browser and Playwright package READMEs.

Publish ordering. Both dependent workflows now run npm view @codepress/interactions-browser@<version> before setting publish=true. If npm doesn't have the browser version, they warn and skip. This is what the earlier review suggested. The check runs in the right place: it is in the elif RELEASE branch, after the package-exists (E404) branch, and in the packages/* working directory, so ../browser/package.json resolves. A transient npm view failure also takes the skip path, which is safe. The cost is a re-run, not a bad publish. PR runs are unaffected because they never reach this branch.

Docs.

  • Running pnpm build before pnpm typecheck in README and CONTRIBUTING matches CI's order.
  • The relative links in the packed browser and Playwright READMEs are now absolute GitHub URLs, so they work inside node_modules.
  • The example README no longer quotes the finding or claims the test adds to .interactions/.
  • The bundle size, "warning" wording and Node 20.19 / 22.12 requirement are consistent with the workflow and bench output.

As the author noted, the new skip branch can't be exercised by a PR run, so it is checked by inspection only. That is acceptable for a branch this small.

No findings.

Reviewed `a6d4634a`...`5dd88575`. Diff collection and GitHub posting were handled by the automation.

View automation run

… control, and drop the last test ID naming the planted bug
@codepress-reviewer-dev

Copy link
Copy Markdown

Starting new changes review of 16b3f1cf from baseline 5dd88575... 👀

View automation run

@codepress-reviewer-dev codepress-reviewer-dev 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.

Review

I read the changes between 5dd88575 and 16b3f1cf in full. They cover involvesControl, its test, the browser README, the CHANGELOG, the example README and the agent skill.

involvesControl. It now also returns true when evidence.subject_blocked_controls is a number greater than 0. The typeof check keeps findings from older or other producers without that field working. Sort order within the rest tier changes only for outer pairs that block a control. Tier 0 findings are unaffected, and the QA report said order did not change for them.

Test. The new assertions cover the true case (blocked controls = 1) and the false case (0) on the FindingData shape. This protects the wire-data contract.

Docs. The browser README, CHANGELOG and skill describe the same rule. The example README no longer names the planted bug's test ID, which fixes the earlier note about the hidden bug.

No findings.

Reviewed `5dd88575`...`16b3f1cf`. Diff collection and GitHub posting were handled by the automation.

View automation run

@lightninglu10

Copy link
Copy Markdown
Contributor Author

@codepress /judge-verification can you judge this verification?

QA re-verification: PR #4 (open source 1.0)

PR Head SHA: 16b3f1cfce439e7d2de03110cd1e472d6a22a259

The baseline is the FAIL report on a6d4634. The delta is two commits (5dd8857, 16b3f1c): doc fixes, absolute links in the package READMEs, a browser-version guard in the React and Playwright publish workflows, and involvesControl counting subject_blocked_controls > 0.

Everything was re-run live on two fresh clones of the public repo at this head. The three packages were re-packed from them with pnpm pack, because none is on npm yet. Logs are named by file (r2-NN-*.log). The blind agent run was done by a separate agent with no prior context (r2-B4-*.log).

Verdict

  • 1. Clean scratch app, local JSON, no service: PARTIAL. The example was copied out of the repo and installed from the new 1.0.0 tarballs, with no endpoint or key. It wrote batches, a snapshot and findings.json with the planted finding. Installing from the registry is UNVERIFIED (E404, before the first publish). That is the known pre-publish gap and does not count toward FAIL.
  • 2. READMEs followed literally: PASS. The root README "Development" and CONTRIBUTING "Setting up" steps pass on fresh clones with no extra step. The example README works step by step, and its claims are now true. Its npm install step hits E404 (pre-publish; tarballs used instead).
  • 3. Blind agent fix with the skill and the example: PASS. A fresh agent given only SKILL.md and the example's files found the overlap, reproduced the fingerprint, fixed the CSS cause and proved the fix: the test fails, then passes, and a fresh capture has 0 findings.
  • 4. Negative search: PASS. The tree at HEAD, the lockfiles and the new tarballs are clean. History is unchanged from the baseline: the removed internal delivery-tool files, with tool names only and no hostnames or credentials.
  • 5. npm view and tarballs: UNVERIFIED. npm view still gives E404. The tarballs pass: 1.0.0, Apache-2.0, only dist/, README.md, LICENSE and package.json, dependency ranges ^1.0.0 with no workspace:, no ](../ links, and every GitHub link resolves at this head.
  • Repo's own checks: PASS, following the README literally on a fresh clone. Results: 66 unit tests; 66 browser tests passed plus 1 skipped (the golden regenerator); 6 Playwright helper tests.

Contract rows

Row Verdict Evidence class Reason
B1 PASS live-browser The example from the new tarballs, loaded in Chromium, wrote batches/*.json, snapshots/388c4dec….json and findings.json with layout.overlap plan-pro-cta × plan-pro-badge [d4aa001353afa3e3fd42ccf1902bf625].
B2 PASS live-browser A 14 s load wrote 1 batch with 0 request.* events. The scratch sink using window.fetch after an await wrote 6 batches and 12 request.* events.
B3 PASS live-browser (Playwright CLI) Unfixed: fails, with fingerprint d4aa0013…. pointer-events: none alone: still fails with the same fingerprint (subject_blocked_points=0, text covered). Fixed: passes, and a fresh capture has 0 findings.
B4 PASS live-browser A fresh agent's blind run (below).
B5 PASS live-browser (a) to (g) re-run against the new build. (f): involvesControl(main × chat) = true, tier 0. Negative control: main × header with subject_blocked_controls=0 gives involvesControl = false, tier 3.
B6 PASS live-browser 2,100 new fingerprints sent 2,000. An evicted fingerprint was resent, a remembered one was not, and a waiting one was sent later.
B7 PASS live-browser The README snippet bundled against the new tarball: after a click and flush(), 1 batch and 2 snapshots, with no page text.
B8 PASS live-ci + live-cli + inspection The four PR runs on 16b3f1c succeeded, and every "Publish to npm" job was skipped. The new guard is identical in both workflows. It was checked by inspection, because a PR run can't reach it, and both of its arms were run locally.
B9 PASS live-cli Tree, lockfiles and new tarballs: 0 matches. .claude/, .codepress/ and qa/ are absent.
B10 UNVERIFIED live-cli npm view gives E404 (pre-publish). The tarball checks and link checks pass.
B11 PASS live-cli + live-browser + inspection The claims the delta touches were checked against behavior: setup order, the example README's test and .interactions claim, the bundle size, the Node version, the publish ordering and warning wording, and the involvesControl sort text.

Evidence

Delta scope

git diff a6d4634..16b3f1c -- packages/browser/src touches only packages/browser/src/detect/index.ts: one added condition in involvesControl (subject_blocked_controls > 0). That leaves the B2, B6 and B7 code paths unchanged; they were re-run anyway. The new build has the change: the condition is present in the new dist chunk and absent from the baseline dist. The repo's dist/index.js is byte-identical to the tarball's.

Repo checks and setup docs (logs r2-02 to r2-15)

Root README "Development", run literally on fresh clone 1:

pnpm install -> 0 | pnpm build -> 0 | pnpm typecheck -> 0 | pnpm test -> 0 (66 passed)
pnpm --filter @codepress/interactions-browser exec playwright install chromium -> 0
pnpm test:browser -> 0 (browser 66 passed, 1 skipped; playwright 6 passed)

CONTRIBUTING "Setting up", the same six commands, run literally on fresh clone 2: all exit 0.

Criterion 3 / B4: blind agent run (logs r2-B4-01 to r2-B4-18)

Setup. A new scratch copy of the example (installed from the new tarballs, port moved to 5174) plus SKILL.md were handed to an agent with no prior context. It was told to read nothing else.

Findings and fix:

  • npm run findings: layout.overlap plan-pro-cta × plan-pro-badge on / @1280x720 … subject_blocked_points=2 … [d4aa001353afa3e3fd42ccf1902bf625]. Verdict: bug (a blocked control).
  • Cause: src/styles.css, .plan-badge { position: absolute; right: 24px; bottom: 30px } inside the position: relative card, which puts it on the CTA that margin-top: auto pushes to the bottom.
  • Fix: bottom: 30px became top: -14px. No pointer-events, z-index, overflow, ignore option or test-ID change.

Proof:

  • tests/ui.spec.ts: failed before the fix with that fingerprint; 1 passed after.
  • A throwaway findIssues spec at 700, 900, 1280 and 1500 px: 1 finding each before, 0 after. The spec was deleted afterwards.
  • Old data moved aside, then a fresh capture: findings.json is [], 0 findings, and the fingerprint is in 0 files.
  • npm run typecheck: exit 0.

Does the example README still give the bug away? No. It says there is one layout bug, that the test fails with Error: 1 UI finding on /., and that findings name test IDs "such as plan-free-cta". These are mild hints. The answer (plan-pro-cta × plan-pro-badge) is no longer in the README.

Disclosure. The agent listed the Playwright browser cache directory once (outside its scratch folder) to see whether Chromium was installed. It read nothing else.

Criterion 1 / B1 / B3 (logs r2-27 to r2-36)

B1 capture. A fresh copy-out installed from the new tarballs. npm ls shows browser 1.0.0 deduped under react and playwright. A Chromium load for 8 s gave:

POST /__interactions/snapshots/388c4dec… ; POST /__interactions/batches
batch files: 1   event types: {ui.snapshot: 1, perf.summary: 1, ui.finding: 1}
npm run findings -> layout.overlap plan-pro-cta × plan-pro-badge on / @1280x720 … 1 finding

B3 test runs:

npm test (unfixed)                 -> exit 1, "Error: 1 UI finding on /.", [d4aa001353afa3e3fd42ccf1902bf625]
npm test (pointer-events:none only) -> exit 1, same fingerprint, subject_blocked_points=0, subject_text_covered, other_pointer_events_none
npm test (badge to top: -14px)     -> exit 0, 1 passed
fresh capture after fix            -> 1 batch {ui.snapshot, perf.summary}, "0 findings", fingerprint in 0 files

The three npm test runs against the running dev server added no batch. That matches the example README's new statement that the test "adds nothing to .interactions/".

Criterion 2: example README followed literally on fresh clone 2 (logs r2-44 to r2-52)

Step Result
npm install E404 (pre-publish). Deviation: installed the tarballs.
npm run findings before any load Prints the documented hint.
npm run dev (5174, deviation), then load and click 2 batches (interaction.started ×2, ui.click.settled ×2, ui.snapshot ×2), and the finding line.
npx playwright install chromium Exit 0.
npm test Fails, with a message starting Error: 1 UI finding on /. (as documented).
Apply the fix npm test gives 1 passed.
Move .interactions aside and reload 0 findings; fingerprint in 0 files.
npm run typecheck Exit 0.

B2 (logs r2-30, r2-37 to r2-39)

example sink (context.fetch), 14 s: batch files 1, event types {ui.snapshot: 1, perf.summary: 1, ui.finding: 1}, request events none
scratch sink (await Promise.resolve(); window.fetch), 14 s: browser POSTs 1 snapshot + 6 batches;
  batch files 6, event types {request.started: 6, request.completed: 6, ui.snapshot: 1, perf.summary: 1}

B5 and B6 against the new build (logs r2-23 to r2-26)

  • (a) A focused text field clicked repeatedly and triple-clicked: every ui.click.settled had field_focused=true, and selection_changed was true on the first click and the triple-click. No rage finding came from the field. A dead button gave click.rage_click with control_ids:["dead"] and click_count=3, clicks_with_feedback=0.
  • (b) The padded-main fixed header gave main × header with subject_content_covered:false, subject_text_covered:false and subject_blocked_points:0, at tier 3.
  • (c) sortFindings on reversed input gave [["layout.offscreen_control","tier2","control=true"],["layout.page_h_scroll","tier2","control=false"]].
  • (d) A label in form A for a field with form="b" gave interaction.started count 1, control_ids:["B"]. The wrapping-label shape behaved the same.
  • (e) Clicking the label of a disabled field gave 1 interaction.started on signup and click.dead_click with control_id:"signup".
  • (f) main × chat: subject_blocked_points:3, subject_blocked_controls:1, subject_interactive:false, other_interactive:false, and involvesControl = true, tier 0. It sorted first ahead of a tier-1 copy × sticker.
  • Negative control for (f): main × header with subject_blocked_controls:0 and subject_content_covered:false gives involvesControl = false, tier 3.
  • (g) A pointer-events:none badge over a static button gave subject buy, other badge, other_pointer_events_none:true.
  • B6:
    • Run 1: 2,100 new pairs sent 2,000 (P0 to P1999); 100 waited.
    • Run 2: 100 new pairs sent 100.
    • Run 3: the evicted P0 was resent.
    • Runs 4 and 5: P600 and Q5, still remembered, sent 0.
    • Run 6: the waiting P2000 was sent.

B7 (logs r2-40 to r2-42)

The README snippet was bundled verbatim (plus a window.__qa handle) against the new tarball and served locally. After a click and flush(): 1 batch and 2 snapshots. The events were ui.state.changed, ui.snapshot, perf.summary, interaction.started, ui.state.changed, ui.snapshot and ui.click.settled. acceptedBatches: 1, and no page text appeared.

B8 (logs r2-20 to r2-22)

Publish Playwright helpers [pull_request] head=16b3f1c… success :: Test and pack=success, Publish to npm=skipped
CI                         [pull_request] head=16b3f1c… success :: Python tests and lint=success, Typecheck, unit and browser tests=success
Publish browser SDK        [pull_request] head=16b3f1c… success :: Test and pack=success, Publish to npm=skipped
Publish React adapter      [pull_request] head=16b3f1c… success :: Test and pack=success, Publish to npm=skipped

What the guard does. The new guard sits in the RELEASE=true branch, which only a push to main or a non-dry-run dispatch reaches. It is identical in publish-react.yml and publish-playwright.yml. It reads BROWSER_VERSION from ../browser/package.json and runs npm view "@codepress/interactions-browser@$BROWSER_VERSION" version. When the output is empty, it emits a warning and writes publish=false. A network error also gives empty output, so a failure is safe. A PR run can't reach this branch, so it was checked by inspection.

Local run. I extracted the guard verbatim from publish-react.yml and ran it with bash from packages/react, with a temporary GITHUB_OUTPUT:

guard.sh (as written): ::warning::@codepress/interactions-browser@1.0.0 is not on npm yet, so this run does not publish @codepress/interactions-react@1.0.0. …
  GITHUB_OUTPUT: published=false, publish=false
guard-substituted.sh ("@codepress/interactions-browser@$BROWSER_VERSION" -> "react@18.3.1"):
  GITHUB_OUTPUT: published=false, publish=true
npm view @codepress/interactions-browser@1.0.0 version -> ""    npm view react@18.3.1 version -> "18.3.1"

Apart from the guard, the diff of publish-playwright.yml against publish-react.yml is the same as at the baseline: names, paths, PACKAGE, and the Playwright-only browser-test steps.

Criterion 4 / B9 (log r2-19)

The search categories are the same as at the baseline: credential formats (AWS, GitHub, Slack, npm, OpenAI- and Stripe-style, Google, private keys, generic key/token assignments, JWTs), local user paths, private and CGNAT IP ranges, internal domain suffixes and staging hosts, the operator's name, and internal product and tool names.

tree at HEAD (excl. lockfiles): 0 | lockfiles: 0 | new tarballs: 0 | .claude/.codepress/qa tracked files: 0

Hostnames found:

  • Tree: files.pythonhosted.org and pypi.org (uv.lock), github.com (all 17 are quantfive/codepress-interactions), www.apache.org, app.test, localhost:3000, json-schema.org, telemetry.test, registry.npmjs.org, localhost:5173, telemetry.example.com, telemetry.example, shop.test, interactions.example.com, localhost, unreachable.invalid, third-party.test, semver.org, other.example, docs.astral.sh and www.w3.org.
  • Tarballs: github.com (10, all this repository), www.apache.org and interactions.example.com.
  • History: unchanged from the baseline report.

Criterion 5 / B10 (logs r2-08, r2-16 to r2-18)

browser:    LICENSE README.md package.json dist/{index,detect,page-script}.{js,cjs,d.ts,d.cts} + chunk + types
react:      LICENSE README.md package.json dist/index.{js,cjs,d.ts,d.cts}   deps @codepress/interactions-browser ^1.0.0, peer react >=18
playwright: LICENSE README.md package.json dist/index.{js,cjs,d.ts,d.cts}   deps @codepress/interactions-browser ^1.0.0, peer @playwright/test >=1.40
all 1.0.0, Apache-2.0; "workspace:" nowhere; dist VERSION = "1.0.0"
grep "](\.\./" in extracted READMEs: 0 lines

Every GitHub link in the extracted READMEs exists at this head. The #ui-checks anchor matches ## UI checks.

blob/main/README.md                              head=yes  main-today=yes
blob/main/examples/react-vite                    head=yes  main-today=NO (added by this PR)
blob/main/packages/browser/README.md#ui-checks   head=yes  main-today=yes
blob/main/packages/playwright/README.md          head=yes  main-today=yes
blob/main/protocol                               head=yes  main-today=yes
blob/main/protocol/v2-snapshot.json              head=yes  main-today=yes
blob/main/protocol/v2-snapshot.schema.json       head=yes  main-today=yes

npm view @codepress/interactions-{browser,react,playwright} gives npm error code E404 (pre-publish).

B11: docs touched by the delta (logs r2-02 to r2-15, r2-36, r2-43)

  • Setup order: README and CONTRIBUTING now build before typecheck, and both pass literally on fresh clones.
  • Example README:
    • The "Test it" section no longer quotes the finding.
    • The claim that npm test "adds nothing to .interactions/" was confirmed: three test runs against the running server added 0 batches.
    • The files section names plan-free-cta as an example ID.
  • Bundle size: README 24.0 KB gzip / 67.1 KB minified, /detect 9.8 KB. pnpm --filter @codepress/interactions-browser bench --runs 1 --clicks 20 (exit 0) measured index 68,758 B minified and 24,641 B gzip (67.1 / 24.1 KiB), and detect 10,063 B gzip (9.8 KiB). The README figures match.
  • CONTRIBUTING:
    • Node 20.19+ or 22.12+ now matches the example.
    • "Skipped with a warning" matches the workflow's ::warning::.
    • The release step says the React and Playwright workflows "warn and skip … re-run them once the browser package is out", which matches the guard's behavior above.
  • involvesControl docs: the CHANGELOG, the browser README sort paragraph and SKILL.md tier 3 say "subject_blocked_controls > 0". That matches the code and the B5(f) behavior. The unit test in detect.test.ts checks both values, and is listed separately as unit-test evidence.

DB Performance

DB performance verifier skipped: no backend DB-backed performance surface (inventory: browser SDK, docs, example dev server, CI workflow; no API routes, ORM, SQL, migrations or tasks).

Screenshot Status

Taken at this head during the blind run, of the example page served by its dev server at 1280x720:

  • example-before-fix-1280x720.png: the "Most popular" badge covers the right end of the Pro plan's "Start free trial" button.
  • example-after-fix-1280x720.png: the badge sits on the Pro card's top edge, and the button is clear.

Problems found

None blocking. All the baseline problems are fixed and were checked live. Remaining minor notes:

  1. Example README links break when the example is copied out. Its relative links (../../packages/browser/README.md, ../../protocol, ../../skills/fix-ui-findings/SKILL.md) break, and the README gives an absolute URL only for the skill. The blind agent hit this. Repro: copy examples/react-vite out of the repo and follow its links.
  2. Packed READMEs point at blob/main/. examples/react-vite exists on main only once this PR merges. This only matters if a package were published before the merge, and the publish workflows run on main.
  3. Mild hints in the example README. "One finding on /" and the example ID plan-free-cta point toward the CTAs. The blind agent judged this a hint, not the answer.
  4. History is unchanged. The removed .claude/, .codepress/ and qa/ files (internal delivery-tool names, no hostnames or credentials) are still in history. Removing them would mean rewriting public main.
  5. Manual re-run after the guard skips. When the guard skips a React or Playwright publish, someone must re-run that workflow by hand. The workflow warning and CONTRIBUTING both document this.

Not verified

  • Installing from the npm registry and npm view (criteria 1, 2 and 5; B10): E404, before the first publish. Everything was verified with pnpm pack tarballs from this head, installed through file: dependencies.
  • The guard's RELEASE=true branch inside GitHub Actions. A PR run can't reach it. It was checked by inspection and by running the extracted snippet locally.
  • Port 5173. All runs used 5174, by brief. Copies of vite.config.ts and playwright.config.ts, and the blind copy's README, were edited to match.
  • Browsers other than headless Chromium. Firefox, Safari and headed browsers were not tested.
  • keepalive on unload. Not exercised.
  • The Python SDK. Outside 1.0 per the README. I only saw CI's "Python tests and lint" pass.

Overall: PASS

@codepress-dev

codepress-dev Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

👋 Hey @lightninglu10! Spawning a verification judge session to help with your request. View session

@lightninglu10
lightninglu10 merged commit b12f53b into main Nov 5, 2026
8 checks passed
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