Skip to content

docs(gate): assertion-strength audit of the live compiled bundle - #97

Merged
myselfsiddharth merged 1 commit into
mainfrom
track1/b3-assertion-audit
Aug 3, 2026
Merged

docs(gate): assertion-strength audit of the live compiled bundle#97
myselfsiddharth merged 1 commit into
mainfrom
track1/b3-assertion-audit

Conversation

@myselfsiddharth

Copy link
Copy Markdown
Contributor

Closes #61.

Summary

Audits every step of artifacts/compiled/traj-gate-live-create-stat-dashboard-from-testdata-9.5.21.bundle.json against the audit's central question: if this step silently did nothing, would its assertion fail? No assertion or strength label is changed — this is the audit, strengthening is follow-up work.

  • Load-bearing count: 6/12 (steps 0, 1, 3, 7, 10, 11) — matches the compiler's existing strong/weak split exactly under a table-only reading. Reproducible via node scripts/assertion-audit.mjs.
  • Every weak step (2, 4, 5, 6, 8, 9) mapped to a docs/gate/compiler.md blind spot, with a strengthen / needs richer fingerprint / inherently weak recommendation each. Two are novel, code-grounded findings: step 8 already has an unused new-landmark signal (newLandmarks() is computed but never used as the assertion target when a click has its own locator — src/compiler/assertions.ts:286); step 2 has an unused dom_digest diff the compiler's own priority-8 fallback could use instead of a non-discriminating "is the clicked button still visible" check.

Empirical verification (required by the issue)

Ran against a freshly booted, freshly seeded 9.5.21 testbed (npm run testbed -- --version 9.5.21), through the unmodified ReplayRunner / evaluateAssertion / bundleToProgram — no product code patched. Method: swap the target step's compiled_action for a genuine { type: "wait" } no-op, leave the assertion untouched, run.

  • Steps 0 and 1 (both "would catch a no-op," both url-matches, strong): confirmed. Neutered runs produced ASSERTION_FAILED with the expected URL mismatch in both cases — satisfies the issue's "at least two claims verified empirically."
  • Step 3 (also "strong," ADR-0007 hide-on-select case): confirmed NOT load-bearing today. Both the real click and the neutered no-op produced PASS. Root cause: the assertion's target is a recorded structural/positional CSS path that resolves to zero elements on a fresh, unmodified 9.5.21 instance — the same version it was recorded on, no version bump involved. This is exactly the "is the structural locator stable run-to-run" question ADR-0006 left open for Record the ADR-0006 gate task live against the seeded base version #24, now answered empirically: no, at least not for this row.
  • Step 4 (weak fill): the same structural-locator defect makes it fail unconditionally — confirmed the real, correctly-executed fill still times out after 5000ms. So this row isn't just "weak" (fails to discriminate), it's currently non-functional regardless of what the step does.
  • Steps 5, 6, 8, 9 were not independently tested; flagged as sharing the same assertion shape, not claimed as confirmed.

This cuts both ways on any published number: step 3 would currently score a no-op step as valid, while steps 2/4-shaped rows would currently score a correct execution as a failure. The doc's "Statement of consequence" section spells this out for whoever writes the gate memo, as the issue requires.

A smaller, secondary finding (documented, not fixed): url-matches in src/runner/assertions.ts reads page.url() once with no poll loop despite carrying timeout_ms, unlike element-visible. Grafana 9.5.21 appends ?orgId=1 to /dashboard/new client-side ~500ms after domcontentloaded (confirmed manually), so a fresh full-page navigate races that evaluator — worked around in the verification harness by settling manually, not fixed in product code.

Test plan

  • npm run lint:docs — clean (46 docs)
  • npm run ci — clean (secret-scan, contracts, lint, typecheck, unit + integration tests all pass)
  • node scripts/assertion-audit.mjs reproduces the 6 strong / 6 weak / 6-load-bearing counts mechanically from the committed bundle
  • Live empirical check against a real 9.5.21 testbed instance (see above) — container torn down afterward, no scratch files committed

Checklist (from the issue)

  • Every step in the compiled bundle has a row (12/12)
  • Load-bearing step count stated as a plain fraction, derived mechanically from the artifact
  • At least two "would catch a no-op" claims verified empirically (steps 0, 1) — plus a third tested and found to disprove itself (step 3), reported in full rather than dropped
  • Every weak step mapped to a blind spot or follow-up issue
  • Consequence for the gate memo stated explicitly
  • No assertion or strength label changed in this PR
  • docs/README.md index row added
  • Branch track1/b3-assertion-audit

🤖 Generated with Claude Code

Audits every step of the live create-stat-dashboard-from-testdata bundle
against the question "if this step silently did nothing, would its
assertion fail?" — 6/12 steps are load-bearing by that reading, matching
the compiler's existing strong/weak split.

Empirical verification (required by the issue) against a live 9.5.21
instance confirmed steps 0 and 1 as genuinely load-bearing, but also found
that step 3's "strong" assertion currently passes regardless of whether
its step ran: its target is a recorded structural locator that resolves
to zero elements on a freshly booted, unmodified 9.5.21 instance — a
locator-stability defect (ADR-0006's open #24 question), not an
assertion-strength one. The same defect makes at least two "weak" steps
(2, 4) fail unconditionally instead of merely failing to discriminate.
Both directions are called out explicitly since either would corrupt a
section 9 number computed from this bundle before any cross-version
comparison even starts.

No assertion or strength label is changed. Counts are reproducible via
scripts/assertion-audit.mjs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@myselfsiddharth
myselfsiddharth requested a review from a team as a code owner July 30, 2026 10:18
@github-actions github-actions Bot added the size/L <= 600 changed lines label Jul 30, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation gate PRD section 9 gate measurement area: tooling Touches tooling labels Jul 30, 2026
@github-actions
github-actions Bot requested a review from OM152002 July 30, 2026 10:18
@myselfsiddharth

Copy link
Copy Markdown
Contributor Author

@copilot review this PR

Copilot AI commented Aug 3, 2026

Copy link
Copy Markdown

@copilot review this PR

I reviewed this PR and found no high-confidence issues requiring changes.

@myselfsiddharth

Copy link
Copy Markdown
Contributor Author

Review

Docs-only PR (no product code touched): a new docs/gate/assertion-audit.md, a reproducibility script scripts/assertion-audit.mjs, and one index row in docs/README.md. Closes #61.

What it does

Per-step audit of all 12 rows in the committed traj-gate-live-create-stat-dashboard-from-testdata-9.5.21.bundle.json, answering "would this assertion catch a silent no-op?" per row, a mechanically-reproducible load-bearing count, a blind-spot mapping for every weak row, and a live empirical check against a real 9.5.21 testbed for the required "at least two" no-op claims (delivered three, including one that disproves itself).

Verification performed

I checked this PR's claims against the actual repo rather than taking the prose at face value:

  • Ran scripts/assertion-audit.mjs against the real bundle in this checkout — it reproduces the stated 6 strong / 6 weak, 6/12 load-bearing exactly, with the same step indices (0, 1, 3, 7, 10, 11).
  • Confirmed src/runner/assertions.ts's url-matches case does read page.url() once with no waitFor/poll loop, unlike the element-visible branch — Finding 2 is accurate.
  • Confirmed src/compiler/assertions.ts:286 (const locator = primary ?? landmarkAsLocator(landmarkPick);) — newLandmarks()-derived locator is only ever used when primary is undefined, exactly as claimed for the step 8 recommendation.
  • Confirmed the step 2 dom_digest pair (006b965317eacdbcdee4609c1269959d) and the step 8 landmark diff ([main, navigation, banner][..., form]) against experiments/gate-v1/trajectories/grafana-create-stat-dashboard-from-testdata-9.5.21.json — both match the doc exactly.
  • Confirmed every blind-spot number cited (1, 3, 8) matches docs/gate/compiler.md's actual "Known blind spots" list.
  • Confirmed the frontmatter and the ## Open questions / what I could not verify header satisfy scripts/lint-docs.mjs's required keys/allowed values.
  • Confirmed all StepOutcome values used in the empirical table (ASSERTION_FAILED, TIMEOUT, REPAIR_EXHAUSTED, PASS) are real members of the type in src/metrics/types.ts.

Everything checked out. This is unusually well fact-checked for a docs PR — every specific code reference, line number, and data value I spot-checked was accurate rather than approximate.

Issue-checklist compliance

Matches issue #61's "before you open the PR" checklist item-for-item: every step has a row, the fraction is derived mechanically (not hand-counted), every weak step maps to a blind spot, the gate-memo consequence is stated explicitly and in plain language, no strength label or assertion was touched, the README index row was added, and the branch name matches.

Minor observations (non-blocking)

  • Scope creep, disclosed correctly. Finding 1 (structural-locator staleness) and Finding 2 (url-matches polling gap) are runner/locator bugs, not assertion-strength findings — but the doc is explicit that both are out of scope for this PR and attributes Finding 1 to the already-open Record the ADR-0006 gate task live against the seeded base version #24 rather than silently fixing or filing redundantly. No action needed, just noting it's the right call.
  • LOAD_BEARING_STEP_INDICES in scripts/assertion-audit.mjs is a hardcoded judgment call, not derived from the bundle — this is unavoidable (the question "would this fail on a no-op" isn't mechanically computable from the JSON alone) and the script's own comment says so plainly, plus it prints a divergence warning if strong-count and load-bearing-count ever split. Reasonable given the constraint.
  • The doc's empirical table shows step 0's "real action" column as "(see caveat below)" — this forward-reference is resolved by Finding 2 later in the doc, but a reader skimming just the table might be momentarily confused before reaching that section. Not worth restructuring for.

Risk

Very low. No product code changed; the two runner-level bugs surfaced (locator staleness, url-matches polling) are documented as follow-up work, not silently patched. The one real risk is that the audit's central finding — that the section 9 gate number can currently be inflated and deflated simultaneously by locator staleness — needs to actually get picked up by whoever writes the gate memo. The doc states this plainly, which is what the issue required.

Recommendation: approve.

@myselfsiddharth
myselfsiddharth merged commit 6cb90b2 into main Aug 3, 2026
14 checks passed
@myselfsiddharth
myselfsiddharth deleted the track1/b3-assertion-audit branch August 3, 2026 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: tooling Touches tooling documentation Improvements or additions to documentation gate PRD section 9 gate measurement size/L <= 600 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audit assertion strength on the live compiled task before the matrix runs

2 participants