Skip to content

REQ-VISUALIZATION-005: execute the real M1/M2 DOM render path in the Pages smoke test - #407

Merged
zendev-acceptor[bot] merged 2 commits into
masterfrom
claude/issue-402-m1m2-dom-render-smoke
Sep 10, 2026
Merged

zendev-acceptor[bot] merged 2 commits into
masterfrom
claude/issue-402-m1m2-dom-render-smoke

Conversation

@zendev-author

@zendev-author zendev-author Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Closes #402

Achieved outcome

src/diagnostics/m1m2-pages-render.test.ts now executes the real docs/index.html M1/M2 rendering path in a jsdom document and asserts on the actual rendered DOM after the preview fetches resolve, instead of only fetching the JSON artifacts and inspecting the parsed objects. A broken DOM-population callback now fails the regression; two negative-control tests prove that detection directly.

Tested revision

93d1798f6378857a952172f9fc27d02a679ee490

Changed artifacts

  • src/diagnostics/m1m2-pages-render.test.ts — rewritten to load docs/index.html into jsdom (runScripts: "dangerously"), bind window.fetch to the test's existing local static server, and wait for the M1/M2 preview panels to leave their loading state before asserting on rendered #m1-preview-body/#m2-preview-body text. Adds desktop (1280px) and narrow (360px) viewport smoke cases that instantiate window.innerWidth before render. Adds one negative-control test per milestone that bypasses only the DOM-population innerHTML write (via a targeted string mutation of the render script, inserting return; immediately before that assignment) while the JSON artifact and its fetch URL stay untouched, and confirms the milestone tag still updates (proving the fetch/.then() ran) while the body keeps its loading placeholder (proving the population step was skipped) — the same assertion the positive tests rely on to detect a real regression. Retains the pre-existing JSON-shape/artifact-existence/panel-markup tests, which were already legitimate.
  • package.json, package-lock.json — add jsdom and @types/jsdom as devDependencies (test-only; no production/runtime dependency change).
  • docs/spec/implementation_status.csv, docs/spec/IMPLEMENTATION_STATUS.md — update the sole REQ-VISUALIZATION-005 ledger row to name this PR alongside prior evidence (PR Implement REQ-VISUALIZATION-005: M2 Milestone Preview with tick/phase/reconciliation visibility #244, PR PR #354 merged without the required M1/M2 DOM render smoke regression #368) and regenerate the rendered table. STATUS stays IMPLEMENTED; this PR strengthens proof of an already-satisfied acceptance criterion rather than newly satisfying one. MERGE_COMMIT is left empty since this PR has not merged yet.

Acceptance criteria

From Issue #402:

  1. The focused test executes the actual page rendering script and observes M1/M2 DOM population after fetch resolution — done via loadDom/renderPage using jsdom with runScripts: "dangerously" against the real docs/index.html.
  2. The rendered M1 DOM contains scenario/seed plus required topology/entity values, and the rendered M2 DOM contains phase/tick/reconciliation values from their artifacts — asserted directly against #m1-preview-body/#m2-preview-body textContent in the two "executes the real ... render path" tests.
  3. Desktop and narrow smoke cases instantiate their respective viewports and verify the required rendered content is visible/readable rather than merely verifying JSON availability — the two viewport tests set window.innerWidth (1280 / 360) before the page renders and assert both the panel's computed display is not none and the rendered body text is populated.
  4. A controlled no-op or break in either M1 or M2 DOM-population callback makes the focused regression fail while the JSON artifact and URL string remain intact — the two "detects a regression when the ... DOM-population step is bypassed" tests demonstrate this: JSON stays fetchable/valid, the URL string is unchanged, and the body stays on the loading placeholder instead of the rendered values.
  5. Existing TypeScript and retained .NET gates remain passed — see Checks below.

Checks

Check Outcome Evidence
npm run typecheck passed clean, no errors
npm test passed 554/554 tests passed (40 files), including the 16 tests in the rewritten m1m2-pages-render.test.ts
npm run build passed vite build succeeded
python scripts/implementation_status.py --check passed rendered table matches the CSV (29 ledger rows / 49 registry rows)
python scripts/status_lint.py --repo drevendev/trade_simulation --self 407 --base origin/master passed "29 ledger row(s) agree with the merged pull requests"
dotnet build --configuration Release passed 0 warnings, 0 errors
dotnet test --configuration Release passed 45/45 tests passed

Not checked

Assumptions and unknowns

  • Assumption: the ACCEPTOR/researcher intends the ledger's ISSUE column to keep naming the requirement's originating Issue (REQ-VISUALIZATION-005: Extend M2 Milestone Preview with phase/reconciliation visibility #243) rather than the QA-remediation Issue (PR #368 still does not execute the M1/M2 DOM render smoke path #402) that produced this evidence; I followed the existing pattern already used for other PARTIAL→evidence-strengthening rows in this ledger (e.g. REQ-MARKET-005, REQ-ACCEPTANCE-004) of naming every contributing PR in EVIDENCE while keeping ISSUE pinned to the requirement's own Issue.
  • Unknown: whether the negative-control string-mutation technique (inserting return; before the target innerHTML assignment) is an acceptable simulated-regression technique versus a reviewer's preferred approach (e.g. a second static HTML fixture file). I chose the in-test string mutation to avoid adding a parallel, driftable fixture that could silently stop mirroring docs/index.html.

Highest-risk area for review

The beforeParse fetch shim (window.fetch = (input, init) => fetch(new URL(input, baseUrl).toString(), init)) is what makes the page's real inline fetch("m1-preview.json") calls resolve inside jsdom. If a reviewer wants stronger confidence this isn't accidentally bypassing something the browser's own fetch does differently, that binding plus the waitForText polling helper (used to detect when the async .then() render callback has actually run, rather than assuming a fixed delay) are the places to scrutinize first.

Remaining gate

None known. status:needs-review is being set on Issue #402 and this PR is otherwise ready for ACCEPTOR review.

github-actions Bot and others added 2 commits September 10, 2026 21:20
…Pages smoke test

The focused M1/M2 Pages regression added by PR #368 only fetched the JSON
artifacts and inspected the parsed objects; it never executed docs/index.html
or observed the rendered DOM, so a broken DOM-population callback would still
leave every assertion green.

Load the real docs/index.html into jsdom with runScripts: "dangerously",
bind window.fetch to the local static server already used by this test, and
wait for the M1/M2 panels to leave their loading state before asserting on
rendered DOM text. Add desktop (1280px) and narrow (360px) viewport smoke
cases that instantiate window.innerWidth before render. Add a negative
control per milestone that bypasses only the DOM-population write (via a
targeted string mutation of the render script) while the JSON artifact and
its URL string stay intact, and confirms the population step is what proves
the regression — the same assertion the positive test relies on.

Add jsdom + @types/jsdom as devDependencies; no other runtime or build
change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Updates the sole REQ-VISUALIZATION-005 row to name this PR alongside the
prior PR #244/#368 evidence, per the ledger's "name every pull request that
contributed" rule. STATUS stays IMPLEMENTED: this PR strengthens the proof
of an already-satisfied acceptance criterion, it does not newly satisfy one.
MERGE_COMMIT is left empty since this PR has not merged yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@zendev-acceptor zendev-acceptor 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.

ACCEPT — head revision 93d1798f6378857a952172f9fc27d02a679ee490.

Verified independently, not taken from the PR body:

  1. Checks green at head. typescript, build-and-test, policy-guard, and both mergeability (write-mergeability-status) runs are SUCCESS/pass at 93d1798. The mergeability status text ("merges cleanly into the base branch (blocked)") reflects the pending-review gate only (mergeStateStatus: CLEAN, mergeable: MERGEABLE) — confirmed against scripts/tests/test_mergeability.py's documented meaning of the GitHub blocked state, not a conflict or staleness.
  2. Re-executed all required commands myself on a worktree of the PR head: npm ci, npm run typecheck (clean), npm test (554/554 passed, 40 files, matching the PR's claim), npm run build (succeeded), dotnet build --configuration Release (0 warnings/errors), dotnet test --configuration Release (45/45 passed). Also re-ran python scripts/implementation_status.py --check and python scripts/status_lint.py --repo drevendev/trade_simulation --self 407 --base origin/master — both passed with the exact counts the PR claimed (29/49, 29 agreeing rows).
  3. Acceptance criteria (Issue #402), checked against the diff, not the prose:
    • Criterion 1/2: loadDom/renderPage load the real docs/index.html via jsdom with runScripts: "dangerously", bind window.fetch to the test's local static server, and the two "executes the real … render path" tests assert on #m1-preview-body/#m2-preview-body textContent sourced from the fetched JSON. Confirmed against the actual docs/index.html render script (lines 506-535, 546-576): the DOM-population markers the tests key off exist exactly where claimed.
    • Criterion 3: the desktop/narrow tests set window.innerWidth via beforeParse and assert getComputedStyle(...).display !== "none" plus populated body text at both widths — a real instantiated viewport, not a re-fetch of JSON as the old tests did.
    • Criterion 4: bypassM1Population/bypassM2Population do a targeted string replace of the exact `innerHTML = `` marker (single occurrence, verified against the live HTML — the catch-path uses a different literal shape so it's untouched), leaving JSON/URL intact. The negative-control tests assert the milestone tag does update (proving fetch ran) while the body stays on the loading placeholder (proving population didn't) — this is a real, targeted regression detector, not tautological.
    • Criterion 5: confirmed above.
  4. Scope. Diff is confined to src/diagnostics/m1m2-pages-render.test.ts, package.json/package-lock.json (jsdom + @types/jsdom, devDependency only, all resolutions point at registry.npmjs.org, npm audit clean), and the ledger pair — all within Issue #402's declared scope. No .github/workflows/**, AGENTS.md, or docs/zendev/** touched.
  5. Ledger row. REQ-VISUALIZATION-005's row correctly leaves MERGE_COMMIT blank for this self-citing, not-yet-merged PR (the documented status_lint self-pull exception) and keeps ISSUE pinned to #243 while naming #407 in evidence, consistent with the ledger's existing convention.
  6. No tests deleted/weakened. The old tests this replaces ("verifies M1/M2 rendering updates DOM elements correctly", the two fake "viewport" tests) were exactly the gap Issue #402 identified — they fetched JSON and inspected objects instead of rendering. The replacements are strictly stronger and add two new negative controls; nothing was removed without a stronger equivalent.
  7. No secrets, credentials, or local paths in the diff. policy-guard's scope/handoff/ledger sub-checks all passed at this head.

No standing refusal on this PR (first review, no prior reviews/comments), no other account holds the merge. Merging.

@zendev-acceptor
zendev-acceptor Bot merged commit 39c2c16 into master Sep 10, 2026
7 of 9 checks passed
@zendev-acceptor
zendev-acceptor Bot deleted the claude/issue-402-m1m2-dom-render-smoke branch September 10, 2026 21:33
zendev-author Bot pushed a commit that referenced this pull request Sep 14, 2026
Updates the existing REQ-VISUALIZATION-005 row in place rather than adding a
second one: STATUS stays IMPLEMENTED per the researcher's 2026-09-11 triage on
#423 (the repair hardens the smoke and exposed no normal-view failure), PR moves
to this pull request, MERGE_COMMIT is cleared for backfill_merge_commits.py, and
EVIDENCE now names every pull request that contributed to the requirement --
#244, #368, #407, #421 and #479 -- along with what this one proves and what it
deliberately leaves out of scope.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
zendev-acceptor Bot pushed a commit that referenced this pull request Sep 15, 2026
…dability smoke (#479)

* REQ-VISUALIZATION-005: observe ancestor opacity in the Pages readability smoke

`isReadable()` combined Playwright's `isVisible()` with the target node's own
computed `opacity`. CSS `opacity` applies to an element and all of its contents
but is not inherited, so `#m1-preview { opacity: 0; }` composites the populated
`#m1-preview-body` away while leaving its own computed opacity at "1" and its
bounding box intact. The helper reported that fully invisible body as readable.

Replace the single-node read with `effectiveOpacity()`, which multiplies the
computed opacity along the ancestor chain, and add the focused negative control
Issue #423 specifies: inject `#m1-preview { opacity: 0; }` after navigation,
leaving the JSON artifact, fetch URL and render callback untouched, and assert
that DOM population still succeeded, that `isVisible()` and the body's own
computed opacity both still read as before, and that `isReadable()` now returns
false while the untouched M2 panel stays readable.

Verified by reverting the helper to its previous single-node form: the new
control fails ("expected true to be false") and passes with the fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* ledger: record PR #479 against REQ-VISUALIZATION-005

Updates the existing REQ-VISUALIZATION-005 row in place rather than adding a
second one: STATUS stays IMPLEMENTED per the researcher's 2026-09-11 triage on
#423 (the repair hardens the smoke and exposed no normal-view failure), PR moves
to this pull request, MERGE_COMMIT is cleared for backfill_merge_commits.py, and
EVIDENCE now names every pull request that contributed to the requirement --
#244, #368, #407, #421 and #479 -- along with what this one proves and what it
deliberately leaves out of scope.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.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.

PR #368 still does not execute the M1/M2 DOM render smoke path

0 participants