Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,15 @@ jobs:
- id: vue-pnpm-vite5
framework: vue
package-manager: pnpm
version-args: '--vite-version=5.4.21'
version-args: '--vite-version=5.4.21 --scope=list'
- id: next15-npm-webpack
framework: next
package-manager: npm
version-args: '--framework-version=15.5.28'
- id: next16-pnpm-turbopack
framework: next
package-manager: pnpm
version-args: '--framework-version=16.4.3'
version-args: '--framework-version=16.4.3 --scope=table'
- id: nuxt3-npm
framework: nuxt
package-manager: npm
Expand Down
12 changes: 10 additions & 2 deletions docs/agent-targets-and-replay.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Only `resolved` identifies one exact target and returns its available runtime co

Handles survive DOM moves. Removed/recycled targets and changed source or identity constraints invalidate them. Never persist a handle as the only identity for a later session. Browser drivers still check visibility, enabled state, overlays and normal actionability; discovery does not imply that an element can be clicked immediately.

Semantic table rows and list items (`tr`, `li`, `[role="row"]`, and `[role="listitem"]`) also constrain actions using their non-private, non-editable text. An ordinary row with a customer name beside an unlabeled Edit button can therefore be identified without adding a test ID. Row text changes retire local handles, including when a virtualized or position-keyed list retains the same action DOM node. Text segments remain separate so differently divided cell values cannot collide by concatenation. Input values and blocked/editable descendants are excluded. Duplicate rows remain ambiguous; long or redacted identity still stops portable replay. Changes to other visible row content may conservatively require a new capture.

PII is checked before segment encoding, including email/card/phone values split across text nodes; sensitive row identity is redacted as a whole and cannot be replayed. Local fingerprints retain complete raw ancestor constraints privately. If more than four identified ancestor scopes are needed, the portable locator is explicitly unsupported rather than silently dropping an outer business identity. The same applies when raw identity exceeds size limits even if redaction would shorten it.

## Explicit recording

In the instrumented page's JavaScript context:
Expand Down Expand Up @@ -70,9 +74,9 @@ NX_DAEMON=false pnpm exec nx run-many -t build,sync-dist \
--exclude domscribe-test-fixtures --parallel=2 --skipNxCache
node scripts/verify-instance-replay.mjs
node scripts/verify-instance-replay.mjs --framework=vue --package-manager=pnpm \
--vite-version=5.4.21 --report-dir=/tmp/vue-replay-evidence
--vite-version=5.4.21 --scope=list --report-dir=/tmp/vue-replay-evidence
node scripts/verify-instance-replay.mjs --framework=next --package-manager=pnpm \
--framework-version=16.4.3 --report-dir=/tmp/next-replay-evidence
--framework-version=16.4.3 --scope=table --report-dir=/tmp/next-replay-evidence
node scripts/verify-instance-replay.mjs --framework=nuxt --package-manager=npm \
--framework-version=3.21.11 --report-dir=/tmp/nuxt-replay-evidence
```
Expand All @@ -94,6 +98,10 @@ CI runs eight representative combinations, with at most two replay jobs simultan

The default remains React18/npm/Vite7. Use `--framework-version` for exact Next15/16 or Nuxt3/4 releases; use `--vite-version` for React/Vue consumers. Mixed or unsupported flags are rejected. Native SSR consumers use their framework integrations and normal hydration, not the Vite SPA integration. Nuxt excludes the runtime from Vite prebundling so its native plugin and consumer queries share one runtime on cold startup. Each run checks actual installed versions, expected framework source, and local runtime resolution.

`--scope=article` keeps the original labeled-card fixture. `--scope=table` and `--scope=list` use sibling business text with no added row label or test ID. They deliberately retain position-keyed action nodes during a customer replacement and verify that old handles/selectors retire, old portable identity does not resolve, the new runtime props belong to the replacement, and only that customer's UI data changes. CI runs the Vue/pnpm/Vite5 case as a list and the Next16/pnpm case as a table. The other six cases retain article coverage.

The [real-application acceptance matrix](./real-app-acceptance.md) records separate maintained-application tests and their installation/actionability limits.

These are representative synthetic regression cases, not the full version/manager/router matrix or an adoption benchmark. Additional local testing on the Domscribe website (Next16.4.3 / React19.2.4) verified exact installation-tab source/state among six repeated instances, persisted replay after a fresh browser session, safe page-navigation failure, mobile navigation state/replay after reload, and controlled HMR identity changes without resurrecting retired handles. Its production build and UI also worked without instrumentation. This is one maintained app, not evidence for every router, virtualized list, framework version, or agent workflow advantage. Package installs use local tarballs, with explicit pnpm local-artifact overrides so unpublished artifacts cannot be replaced by registry copies. This is not evidence that the new APIs are in the published npm release.

Logs and result JSON are retained in the printed temporary directory on success and failure. `--report-dir` copies a compact evidence bundle. Traces and screenshots are retained when available, with best-effort failure screenshots after browser startup. Server startup and builds are bounded, and the harness stops its owned server process group and relay.
31 changes: 31 additions & 0 deletions docs/real-app-acceptance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Real-application capture and replay acceptance

Sprint 1 tests useful workflows in maintained applications alongside controlled regressions. These checks use locally built, unpublished Domscribe tarballs. They do not imply that the new APIs are available in npm 0.6.1, demonstrate agent efficiency, or restore arbitrary application/backend state.

| Application and task | Acceptance |
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Domscribe website, Next16.4.3/React19.2.4, commit `a6e1a0e8c0c6ce9995c716e7a7cf77b09e392d01`: expand manual setup and select Vue + Vite | Six repeated tab source instances remain ambiguous by source alone; an exact target exposes live state. Persist the two UI actions and replay them in a fresh browser. Verify the actual Vue installation command and committed tab state. Production UI remains functional without instrumentation. |
| [Vue TodoMVC](https://github.com/tastejs/todomvc/tree/ff43b02e59dfa604386bb382034b2cd07c2bcd8a/examples/vue): complete one task among repeated controls | Exact source/runtime correspond to the selected task. Persist a checkbox action; recreate prerequisite tasks through normal UI in a fresh browser in a different order, then replay. Only the intended task becomes completed. |
| Same TodoMVC application: edit a task and reuse its action node | Edit through the app UI. Confirm the DOM action node is retained but the old handle/selector retires and the old portable locator no longer resolves. Recapture the changed task, inspect its actual runtime props, then delete it through the UI while preserving the other task. Production deletion works without instrumentation. |

The TodoMVC workflows passed on October26 with Vue3.5.33, Vue Router4.6.4, plugin-vue6.0.6, Vite7.3.7, Node24.22.1 and Chromium156.0.8078.4. Application components and their handlers were unchanged; test setup adds Domscribe's Vite plugin and a development-only runtime inspection hook in an isolated worktree. The app stores tasks in component memory, so the driver explicitly recreates prerequisite data through UI after a fresh session. That preparation is not evidence of automatic state restoration.

The website's three functional checks passed on October26 with Next16.4.3/React19.2.4 and Chromium156.0.8078.4. There were no page exceptions. Local production hosting returned two metrics-script 404s (`/_vercel/insights/script.js` and `/_vercel/speed-insights/script.js`), retained separately from the functional results; do not describe this local run as having zero console/network errors. Deployment-hosted metrics are a separate website-health check.

## Installation and browser-action limits

The upstream TodoMVC frozen npm install succeeded with its Vite8.0.10 lockfile. Adding Domscribe then failed with `ERESOLVE`: Domscribe's Vue integration declares Vite5–7 support. The successful integration test explicitly pinned Vite7.3.7 in the isolated harness. This is a supported-version test with a workaround, **not a clean Vite8 installation success**. Vite8 support needs separate compatibility work and fresh tests before changing peer ranges.

An initial TodoMVC replay attempted to click its hover-only delete button without revealing it and stopped with `action_failed`; the app CSS hides this button until the row is hovered. The qualified portable workflow uses the visible checkbox. The edit/delete checks explicitly hover the row through the browser driver before clicking. Domscribe does not record hover steps or turn an invisible target into an actionable one.

The website manual setup is inside a closed native `details` element. Its trace must include the summary click before the hidden tab click. A driver that omits that prerequisite does not demonstrate a product failure or a successful replay.

## Controlled regression coverage

The repository consumer harness also exercises a Next16/pnpm semantic table and a Vue3/pnpm/Vite5 semantic list with genuinely recycled action nodes. It asserts fresh-session persisted replay, source/runtime correspondence, intended-business-entity updates, ambiguity refusal, and production stripping. A React18/npm/Vite7 labeled-card run preserves the original path. These fixtures make failures repeatable in CI; they are distinct from the maintained application checks above.

Unit regressions cover native and ARIA table/list scopes, sibling-identity changes, stable moves, duplicate identities, text-segment collisions, private/editable values, redaction and over-limit identity. Five initial tests failed against the original runtime, including an old invoice handle incorrectly remaining `resolved`. A browser table run against the old artifacts also stopped instead of completing portable replay.

Independent review reproduced two additional gaps before delivery: a new row scope displaced outer business identity at the four-scope boundary, and segment encoding allowed split PII to evade pattern matching. Regression tests now require complete local ancestor fingerprints, explicit portable overflow refusal and pre-encoding redaction of split email/card/phone values while still invalidating local handles when that raw identity changes.

These results establish a limited acceptance matrix, not support for every framework, router, virtualizer or business workflow. Long/redacted or indistinguishable rows may require new application labels or a new capture. Shadow DOM, frames, general session restoration and native cloud repair remain outside these tests. Release readiness and real developer demand require separate evidence.
20 changes: 20 additions & 0 deletions docs/superpowers/plans/2026-10-26-semantic-row-targets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Semantic Row Target Safety Implementation Plan

> Execute inline with superpowers:executing-plans; obtain one fresh independent review of the whole branch before delivery.

Goal: prevent an exact row-action handle from silently following a recycled business entity and allow portable replay of ordinary semantic rows without requiring added test IDs.

Diagnosis: at main bfb108d, table/list ancestors without identity attributes/headings are omitted. Changing a sibling invoice ID leaves the Retry button fingerprint unchanged. Fresh-session row actions are ambiguous. The new runtime regressions first failed in five cases (resolved instead of stale; ambiguous instead of resolved), while the original 568 runtime tests passed.

Scope: runtime target-registry identity/matching; runtime regressions; existing browser consumer harness extended with table/list variants; accurate usage/limitations and Sprint1 real-app acceptance matrix. No public schema, dependencies, framework adapters, release or deployment changes.

- [x] RED: retained invoice-row button must retire when sibling identity changes; reordered native/ARIA table/list locators must select the original business row in a fresh runtime.
- [x] GREEN: capture bounded privacy-filtered segmented semantic-row text in ancestor constraints and local fingerprints; use identical conjunctive matching, preserve segment boundaries and existing non-row locators.
- [x] Extend negative tests for duplicate rows, changed identity, private/editable descendants and over-limit row identity; test stable handle under moves.
- [x] Extend real-browser local-tarball consumer verification to semantic table/list rows, actual recycled DOM slots, fresh-session replay, correct business entity, source/runtime correspondence and production removal. Run representative React/Next and Vue/Nuxt cases; label fixtures versus actual apps honestly.
- [x] Establish at least three realistic acceptance workflows spanning maintained Next and an independent Vue app; document confirmed versus planned coverage.
- [ ] Run configured affected lint/test/build/typecheck uncached, broader configured suite before readiness, independent review, fix material findings with regressions, push focused PR, follow latest-head CI and merge with standing authority.

Review focus: no wrong-entity action under DOM reuse; no private/form values in row identity; duplicate/unsupported scopes stop safely; segment collisions do not retain a stale handle; old non-row locator behavior remains compatible. The existing four-ancestor/main-document/light-DOM boundaries remain explicit. Scope text changes can conservatively require recapture.

Review rulings: include all relevant ancestors in private local fingerprints and mark portable overflow unsupported instead of weakening prior business scope. Detect PII on contiguous/spaced filtered text before JSON segment serialization; retain raw local fingerprints. New regression tests first failed on the reviewed head. The initial fix shortened redacted long identity and changed unsupported to not_found; preserve raw-bound unsupported status before exporting redacted bounded identity. Original over-limit tests caught this and must stay green.
Loading
Loading