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 @@ -147,7 +147,7 @@ jobs:
- id: react-npm-vite7
framework: react
package-manager: npm
version-args: '--vite-version=7.3.7 --schema-peer'
version-args: '--vite-version=7.3.7 --schema-peer --issue-handoff'
- id: react-pnpm-vite5
framework: react
package-manager: pnpm
Expand All @@ -159,7 +159,7 @@ jobs:
- id: vue-pnpm-vite5
framework: vue
package-manager: pnpm
version-args: '--vite-version=5.4.21 --scope=list --schema-peer --adapter-only --raw-runtime'
version-args: '--vite-version=5.4.21 --scope=list --schema-peer --adapter-only --raw-runtime --issue-handoff'
- id: react-pnpm-vite8
framework: react
package-manager: pnpm
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ Conventions are in `.claude/rules/`. PRs welcome.
For an isolated browser replay check through the Docker Node SDK, see the
[Docker Cloud replay smoke test](./docs/docker-cloud-replay.md).

Portable issue-packet CLI commands are being developed on main; see the [source-only handoff guide](./docs/portable-issue-handoff.md) for availability, privacy options and fresh-checkout inspection.

---

## License
Expand Down
60 changes: 60 additions & 0 deletions docs/portable-issue-handoff-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Portable issue handoff verification — October 27, 2026

The hypothesis is that a useful UI bug handoff preserves the selected instance, source anchor, expected/observed behavior and setup requirements across people and sessions. This slice removes manual annotation JSON/path rewriting. It does not establish demand or an advantage over a complete browser/source agent.

The `issue export` and `issue inspect` commands are source/local-build features, absent from published npm 0.7.0. See [the usage guide](./portable-issue-handoff.md).

## Fresh acceptance

Both paths installed locally packed artifacts in isolated consumers. The pnpm path used explicit local-tarball overrides; these are not unmodified registry installs. Node 24.22.1 and Chromium 156.0.8078.4 were used.

| Path | Native capture and transfer | Source evidence | Other browser assertions |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| React 18.3.1 / Vite 7.3.7 / npm 11.19.1 | Overlay-selected Orion editor Save annotation exported through the installed CLI; reporter browser and relay stopped; unchanged packet inspected offline in a separate source Git worktree; zero JSON edits | `src/main.jsx:6:458`, original source hash `1bdb30697bf58a2d`; identical checkout matched; modified receiving source reported changed | Wrong-customer locator refused; stale/ambiguous targets refused; fresh-context reordered-row replay updated the intended customer; production instrumentation absent; zero app page/console/network errors |
| Vue 3.5.44 / Vite 8.3.5 / pnpm 9.12.0 | Same native export/offline transfer flow, adapter-only installation with no top-level runtime/overlay dependency | `src/Editor.vue:13:5`, original source hash `60427786f5442eb8`; identical checkout matched; modified receiving source reported changed | Same assertions, plus recycled action-node identity retirement; production customer update correct; zero app page/console/network errors |

These are controlled customer-editor fixtures. The annotation records an explicit acceptance scenario; it is not evidence of discovering or repairing a real customer bug. Packet integrity was checked before/after transfer, and inspection created no relay state in the receiving checkout. Captured automation durations are fixture-operation timings, not human usability or repair measurements. The headless browser driver exercised native UI controls; it did not inject a fabricated annotation.

## Repeatable browser check

The permanent browser harness now supports `--issue-handoff`. CI enables it on its existing React/npm/Vite7 and Vue/pnpm/Vite5 rows. Both exact configurations passed freshly with local artifacts (12 and 14 assertion groups respectively), including Vue's raw-runtime capture option. Build/synchronize first, then pack/test without concurrent builds:

```sh
NX_DAEMON=false NX_NO_CLOUD=true pnpm exec nx run-many -t sync-dist --parallel=2
node scripts/verify-instance-replay.mjs --framework=react --package-manager=npm \
--vite-version=7.3.7 --schema-peer --issue-handoff --report-dir=./tmp/issue-react
node scripts/verify-instance-replay.mjs --framework=vue --package-manager=pnpm \
--vite-version=5.4.21 --scope=list --schema-peer --adapter-only --raw-runtime \
--issue-handoff --report-dir=./tmp/issue-vue
```

The report includes the native annotation, exported packet, screenshots and CLI inspection logs. An initial permanent-harness attempt correctly refused unsynchronized artifacts restored by a preceding Nx task check; synchronization was rerun before packing. The earlier Vue8 result remains a separate qualification, not a substitute for the permanent Vue5 path.

A separate compatibility check used the actual historical native Hoppscotch Generate Token annotation from the October 26 run (upstream `63273f8`). The new installed CLI exported it with no packet edits or annotation-record mutations, retained `context_required`, and inspected it offline in a fresh source worktree as `unverified` because the legacy capture lacks original-source metadata. Synthetic private client/environment markers were absent. This was a historical-annotation check, not a fresh Hoppscotch browser or agent repair run.

## Failures that changed the implementation

- Initial React capture incorrectly compared transformed React Refresh code with the original source. A probe confirmed 3,722 incoming characters versus 1,766 original-source characters. A distinct optional `sourceHash` now comes only from an exact absolute source-map match. Legacy or unconfirmed hashes remain unverified. Source locations were correct; checksum provenance was wrong.
- Existing-ID manifest deduplication discarded the new original-source metadata. Real-file regressions now verify a one-time metadata upgrade, restart persistence, last-record mapping and no inherited hash when the latest record omitted it.
- Independent review found private dictionary keys escaping value-only redaction, already-redacted locators advertised as actionable, validation errors echoing private field names, and a valid large Markdown payload overflowing an argument list. Each was reproduced by a failing regression before its fix; re-review found no remaining material findings.
- The first CLI build exposed optional relay-lock host typing; an explicit readiness guard fixed it. Invalid test invocations and malformed test fixture IDs were setup failures, not product regressions.

## Configured checks

From the repository root, uncached:

```sh
NX_DAEMON=false NX_NO_CLOUD=true pnpm exec nx run-many \
-t lint,test,build,typecheck --exclude domscribe-test-fixtures \
--parallel=2 --skipNxCache --output-style=stream
```

All configured targets passed across 16 projects: 2,223 unit tests. After two further source-hash cache regressions and their fix, the complete manifest lint/test/build/typecheck targets passed uncached with 180 tests. All four affected projects were checked again before task completion. New tests contain non-null assertion lint warnings; no lint errors. Existing fixture warning remains.

After sequential artifact synchronization, `node scripts/check-dist-dependencies.mjs` passed all 497 emitted runtime/declaration files. Artifact packaging began only after building/synchronization ended. The fresh native subprocess/browser flows above then passed on these artifacts. Full-suite and affected logs preserve failed attempts as well as passing results.

## Limits and next experiment

Source matching checks content consistency, not report authenticity, business identity or fix correctness. Runtime and recorded replay are opt-in; known-marker filtering is not a universal detector of opaque application secrets. Main-document/light-DOM replay, explicit app prerequisites and stable dialog business context still apply. This slice's original-source metadata is qualified through Vite; integrations without a confirmed original source remain unverified. New CLI paths were not freshly qualified on Next/Nuxt in this slice.

Next, use the native packet on a real application bug with a fresh receiving agent and no hand-edited context. Compare against a complete ordinary browser/source workflow, count capture/setup separately, and grade business behavior independently. The previous larger Hoppscotch comparison had all four repairs pass and showed no correctness advantage; this slice does not change that result. Managed orchestration remains an unproven expansion.
50 changes: 50 additions & 0 deletions docs/portable-issue-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Portable UI issue handoff

**Availability:** these `issue` CLI commands are source/local-build features. The published npm 0.7.0 release has exact-instance capture and portable replay, but does not include these commands yet.

Use this flow when the person receiving a UI bug report has a separate source checkout or browser session. It packages one annotation as historical evidence; it does not recreate application data, authentication, backend services or a live browser selection.

## Capture and export

Start an instrumented development app. Open the Domscribe overlay, select the exact element, describe the problem and submit an annotation. Get its `metadata.id` using the annotation's **Copy annotation JSON** button, or the `id` returned by the existing `domscribe.annotation.list` MCP tool.

From that app's Domscribe workspace, using a locally installed CLI build:

```sh
domscribe issue export ann_12345678_123 \
--title 'Collection token uses the wrong variables' \
--expected 'Use the selected Alpha collection variables' \
--observed 'Uses the unrelated active Beta request variables' \
--prerequisite 'Import the attached synthetic collections in a local guest workspace' \
--step 'Open Beta request, then Alpha collection Properties / Authorization' \
--step 'Click Generate Token' \
--out collection-issue.domscribe.json
```

`--out` creates a new file and refuses to overwrite existing files. Without it, the command writes only JSON to stdout. The annotation's relay must be running for export; no annotation status is changed.

Add `--include-runtime` if the receiver needs captured component props/state. Add `--include-replay` only when the annotation already contains explicitly recorded steps. Neither option restores app state or turns ordinary annotations into automatic recordings. They are omitted by default because application values may be private.

Export removes live instance handles/selectors, URL origin/query/fragment, raw DOM HTML, screenshots, environment/user-agent details and unrelated manifest entries. It retains a project-relative source anchor and its original source-content hash where available. Known sensitive field/record/PII filtering runs again, including on captures that disabled redaction. If filtering changes portable locator identity or replay data, that locator/trace is withheld rather than silently changed. Unscoped-dialog `context_required` refusals remain explicit.

**Review the packet before sharing.** Known-marker filtering does not recognize every application-specific secret, opaque encoded data or every storage alias inside arbitrary application props. Default omission of runtime/replay is intentional. This command does not upload to GitHub or any service.

## Inspect in a fresh checkout

Copy the packet to the receiving machine or source worktree. No JSON path editing, relay or browser is needed:

```sh
domscribe issue inspect collection-issue.domscribe.json --root ./receiving-checkout
# Machine-readable output:
domscribe issue inspect collection-issue.domscribe.json --root ./receiving-checkout --format json
```

The default root is the current directory. Source inspection compares the captured xxhash64 original-source content hash with the receiving file. `matched` means the recorded source content matches, not that the report is authentic, the business entity is resolved, or a fix is correct. `changed` means the source differs; do not blindly trust the historical line. `missing`, `unverified` (no capture hash/anchor or unsuitable file) and `unsafe` are explicit outcomes. Vite captures this separate hash from the exact original source-map content; transformed-module hashes are not substituted. Older captures or integrations without confirmed original content remain `unverified`. Exact source hashes can differ with line endings. The inspector never substitutes a basename/suffix match, executes prerequisites, imports annotations into a relay, or performs browser actions.

Paths are relative to the chosen checkout. Absolute/drive/traversing paths and source symlink escapes are rejected. Packets are versioned and limited to 1MiB, bounded depth/nodes, and a strict known envelope. Captured content is untrusted evidence; Markdown rendering keeps it fenced.

For live investigation, recreate the documented prerequisites, open a fresh instrumented app, and resolve the saved portable locator through [target queries](./agent-targets-and-replay.md). Stop on stale/ambiguous/unsupported results. A reusable dialog still needs a stable, non-secret `data-ds-context` key; source matching does not bypass that requirement.

## What this proves

Successful export/inspection demonstrates a usable evidence transfer without hand-rewriting source roots or preserving stale selectors. It does not demonstrate that Domscribe helps an agent fix more bugs or work faster. Compare complete browser/source workflows on the same real tasks, count capture/setup separately, and grade correct business behavior before drawing that conclusion.
49 changes: 49 additions & 0 deletions docs/superpowers/plans/2026-10-27-portable-issue-packet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Portable issue packet implementation plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking.

**Goal:** Export a reviewable annotation packet and inspect it safely in a fresh checkout without JSON surgery.
**Architecture:** Strict core packet schemas; pure manifest source hash; relay-side evidence transformation and offline inspection; read-only Commander subcommands. Existing HTTP annotation API supplies captures, without adding server routes.
**Tech Stack:** TypeScript, Zod4, Node fs/path, existing xxhash-wasm in manifest, Commander, Vitest, real browser consumer harness.
**Spec:** docs/superpowers/specs/2026-10-27-portable-issue-packet-design.md

## Global constraints

- Existing isolated worktree, fresh main bb396a1; primary checkouts preserved.
- Packet version1, <=1MiB encoded; maximum JSON nesting12 and10000nodes. No added runtime dependency.
- Explicit expected/observed; runtime/replay opt-in; privacy reapplied; no live handles or broad annotation dump.
- Offline inspect is read-only and distinguishes source matching from target/action correctness.
- No publish/deploy/settings/credentials/hosted-service implementation.

## Review focus

- Known secret/PII and workspace paths in opted-in runtime or reporter text.
- Old source, symlinks/traversal, outside root and missing capture hashes.
- Privacy changes to locator identity or replay values must remove actionability.
- Imported pathological JSON, unknown fields/versions and Markdown fence injection.
- CLI errors, no relay, existing output files and working offline in fresh roots.

### Task 1: Validated portable evidence and offline source inspection

**Files:** Create core lib/types/issue.ts and issue.spec.ts; export in core index.ts. Create manifest source-hash.ts; export in manifest index.ts. Create relay issue/issue-packet.ts and issue-packet.spec.ts.
**Interfaces:** `IssuePacketSchema`, inferred `IssuePacket`, `IssueExportOptionsSchema`; `hashSource(content:string):Promise<string>`; `createIssuePacket(annotation, root, options):Promise<IssuePacket>`; `inspectIssuePacket(packet,root):Promise<{packet,sourceStatus}>`; `renderIssuePacket(inspection):string`. Source statuses matched/changed/missing/unverified/unsafe. Export source anchor comes only from matching selected manifest ID; no fallback to unrelated entry. Source checksum uses recorded manifest sourceHash, not a new export-time blessing.

- [x] Write failing tests for strict validation, copied-root match/changed source, no handles, no external paths, privacy and redacted actionability, and bounds. Expected: missing public API assertions fail.
- [x] Implement smallest schema, pure hash helper and bounded transformation/offline inspector that satisfy tests. Never read through unsafe source symlinks.
- [x] Run configured core/manifest/relay tests, lint/build/typecheck. Expected all pass. Commit task.

### Task 2: CLI export/inspect and runnable usage

**Files:** Create relay cli/commands/issue.command.ts and issue.command.spec.ts; register in cli/program.ts; add docs/portable-issue-handoff.md and README link.
**Interfaces:** Commander `createIssueCommand()` for independently instantiated tests; production IssueCommand export. Existing RelayControl/status and RelayHttpClient only for export. Offline inspect has no relay dependency. stdout JSON vs Markdown is deterministic; --out uses exclusive create.

- [x] Write failing command tests using injected/mocked relay boundaries and real temp output files for missing relay/options, offline fresh-root report, existing output preservation and malformed/deep packet rejection. Expected missing command behavior fails.
- [x] Implement CLI wiring and error handling; document local-source availability and privacy/replay limits. Run configured affected checks plus meaningful CLI subprocess verification from packed artifacts. Expected all pass. Commit task.

### Task 3: Native capture-to-fresh-checkout verification and delivery

**Files:** Extend existing temporary browser harness only as needed; commit a concise product guide/evidence report in docs, no machine-specific credentials or app data.
**Interfaces:** Real selected annotation exported via actual installed CLI; offline inspect after reporter browser/relay closes in new source checkout. Preserve exact selected source hash/identity without operator rewriting packet.

- [x] Reproduce old CLI missing command/old manual JSON gap before claiming fix. Run new React/Vue native annotation export, fresh-root match and changed-source negative, privacy marker assertions and production stripping. Expected correct business source or explicit safe refusal.
- [x] Full configured suite; independent whole-branch review, regression fix material findings, focused PR, latest-head CI and authorized merge (delivery tracked in continuity ledger). Record all failures/workarounds and exact scope. Do not publish or infer agent advantage/demand. Retain a precise next comparison step.
Loading
Loading