mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 06:45:22 +00:00
[GH-ISSUE #3379] [Bug] Electron inspection reports malformed CDP inventories as complete empty results #1247
Closed
opened 2026-10-16 21:03:19 +00:00 by bsakaguchi
·
2 comments
No Branch/Tag specified
main
codex/procedure-reference-stacked
release-please--branches--main--components--rea-agents
release-please--branches--main--components--rea-agents--release-notes
codex/kuna-independent-retry
codex/byte-search-overlay-coverage
codex/open-failure-target-receipt
codex/kuna-xref-evidence
codex/ghidra-ambiguous-procedure-recovery
codex/function-source-bundle
codex/trace-function-integration-prototype
codex/snapshot-source-closure
codex/recorded-evidence-array-pages
codex/evidence-recovery-redesign
codex/trace-feature-address-scope
codex/call-discovery-scope
codex/ghidra-literal-candidate-evidence
codex/decompile-directory-independent-retry
codex/retry-provenance-base
codex/value-flow-capability-experiment
codex/ghidra-containing-instruction
cursor/readme-discord-button-ef9f
dependabot/github_actions/actions/setup-node-7.1.0
dependabot/github_actions/actions/upload-artifact-7.0.2
dependabot/npm_and_yarn/npm-minor-and-patch-d8d97ce6df
codex/kuna-1989
fix/8559-native-ui-fixture-ownership
fix/8555-go-verifier-mcp-ownership
codex/provider-capability-recovery
fix/8642-rizin-target-stdin
codex/ghidra-memory-effect-scope
codex/ghidra-annotation-entry-selector
codex/ghidra-readonly-recovery
codex/ghidra-regex-verifier-recovery
codex/evidence-discovery-view-guidance
fix/8545-bulk-append-overflow
fix/8428-navigation-refusal-alternatives
codex/address-context-recovery
codex/matching-member-limitations
codex/unknown-scope-contract
codex/evidence-view-guidance
feat/8373-native-trace-views
codex/ghidra-snapshot-verifier-binding
codex/elf-export-visibility
codex/evidence-view-recovery
codex/native-reference-cli-help
codex/provider-candidate-observation-scope
codex/kuna-session-verification
codex/ghidra-switch-lifetime-guidance
codex/pseudocode-paging-discovery
codex/clarify-evidence-view-support
codex/kuna-xrefs-selector-recovery
codex/context-capacity-recovery
codex/evidence-closure-large-links
codex/same-function-evidence-identity
codex/ghidra-verifier-inspected-jdk
codex/audit-guided-workflows
codex/crash-prompt-retained-dossiers
codex/analysis-view-error-recovery
codex/kuna-verifier-target-selection
codex/ghidra-selected-project-call-coverage
codex/docs-native-analysis-scope
codex/ghidra-java-socket-boundary
codex/ghidra-retained-snapshot-verifier
codex/ghidra-search-inventory-facts
fix/8284-zero-argument-parameter-bindings
fix/8198-ui-action-handler-offset
fix/8257-elf-entry-label-identity
fix/8304-deferred-output-schema-projection
fix/8277-call-path-computed-target-uncertainty
fix/pr-8089-conflicts
fix/ci-static-duplicate-export
dependabot/npm_and_yarn/lint-staged-17.6.0
dependabot/github_actions/actions/download-artifact-8.0.2
dependabot/npm_and_yarn/write-file-atomic-8.0.0
dependabot/npm_and_yarn/canonicalize-5.1.0
dependabot/github_actions/actions/cache/restore-6.1.0
dependabot/npm_and_yarn/toon-format/toon-4.4.0
dependabot/github_actions/actions/deploy-pages-5.0.1
codex/review-fixes-pr-2403
codex/review-fixes-pr-2400
codex/process-terminal-width
codex/test-brittleness-cleanup
verify/7167-browser-connect-macos
fix/7167-browser-connect
feat/native-matching-allowance-setting
feat/browser-scenario-dry-run
test/managed-caller-parameters-20261024
codex/parser-fortythird-boundaries
fix/6926-pinvoke-platform-decorations-20261023
fix/6889-har-body-encoding-20261023
fix/6888-sqlite-schema-budget-20261023
fix/dependency-security-gates-6708
cursor/evidence-overwrite-rebase-b4ac
feat/4057-verify-native-exports
fix/windows-acl-observer-overhead-20261022
cursor/erlang-beam-restack-4476
cursor/pe-certificate-review-bf32
fix/6116-javascript-application-fs-errors
fix/6061-unmapped-runtime-script-unknown
feat/browser-scenario-summary
fix/pe-certificates
codex/verify-3407
cursor/rebase-5699
cursor/rebase-5352
cursor/rebase-5600
cursor/fix-cli-schema-omission-10a8
codex/audit-hopper-shutdown-reasons-20261021
fix/demangle-swift-omitted-record
fix/nib-boolean-value-types
cursor/cancellation-partial-observation-a5ac
fix/ib-object-limit-reasons
fix/electron-fuse-limit-advice
fix/kuna-doctor-dangling-cache
fix/fixed-budget-refusal-advice
fix/js-ipc-listener-dedup
fix/js-return-member-provenance
fix/dmg-integrity-retry-advice
fix/ida-doctor-readiness
fix/kuna-version-probe-output-drain
fix/legacy-swift-runtime-name-matching
fix/dylib-lazy-load-commands
fix/browser-scenario-startup-cancel
fix/swift-nested-punycode-classification
fix/compare-unselected-scopes
fix/objc-method-budget-coverage
fix/dmg-mounted-root-observations
audit/ci-tests-20261019-round2
release/6.7.0
fix/wabt-cleanup-retry-resolution
fix/electron-fuse-elf-pe-architecture
fix/native-plist-descriptor-ownership
fix/kuna-caller-cleanup-ownership
experiment/atomic-codemode-20261016
review/first-contributor-3776
fix/call-resolution-full-read-cycles
fix/member-mutation-selection-repeat
experiment/atomic-re-tools-20261015
perf/member-mutation-lazy-origins
perf/static-network-mutation-index
fix/hopper-startup-lifecycle
audit/3050-windows-proof-20261015
feat/windows-window-capture-2183
audit/3049-windows-proof-20261015
audit/3735-macos-fixtures-20261015
fix/batch-decompile-null-pseudocode
fix/kuna-inventory-honors-jobs
experiment/browser-codemode-tool-design-20261015
fix/hopper-clean-runtime-argv
codex/review-2049-27f1b367
review-fixes/pr-2787-routing
fix/3360-scoped-this-emitters
fix/3367-replaced-global-effects
fix/3838-compact-any-value-items
test/hopper-download-probe-20261015
codex/windows-runtime-creation-red-green-20261015
codex/windows-readonly-root-red-green-20261015
codex/windows-root-share-red-green-20261015
codex/exp-1685-win-mcp-startup
codex/bug-sweep-20261015
investigate/2190-windows-package-phases
investigate/3543-macos-cli-deadline
perf/3281-reverse-tools-feedback-quality
fix/3406-hopper-doctor-fixture
fix/3341-wrapper-require-test-context
fix/3301-owned-uninstall-fixtures
fix/3164-compiler-input-ownership
fix/pcap-cleanup-stdout-newline-20261014
perf/interface-builder-summary
codex/review-fixes-pr-1977
fix/ghidra-effective-jvm-platform
fix/docs-turkish-rust-link-20261013
fix/main-maintenance-ci-20261010
fix/recover-binary-session-process-effects
codex/review-fixes-pr-2457
codex/ci-required-cancellation-gate
fix/main-format-baseline-20261013
fix/setup-preserve-entry-fields
cursor/restore-main-checks-1ffc
fix/ghidra-bridge-hashmap-import
codex/shared-ci-jadx-json-default-20261013
codex/shared-ci-ghidra-test-groups-20261013
codex/shared-ci-java-fixture-format-20261013
codex/fix-intrinsic-invocation-boundaries
test/release-preflight-reusable-jobs
test/js-parameter-provenance-expectation
fix/linux-hopper-verification-current
test/2419-ghidra-elf-probe-size
followup/pr-1544-native-ida
codex/fold-pr-2230-contribution
docs/readme-responsible-use
fix/issue-2064
fix/issue-2050
fix/issue-2053
fix/issue-1968
fix/issue-1945
experiment/codemode-bridge-20261011
fix/tool-effects-negative-wording-1904-20261012
fix/1842-electron-interop-provenance
feat/recover-javascript-multi-input
refactor/website-i18n-prep
fix/nativeaot-pe-virtual-extent
fix/browser-verifier-ci-hang
fix/pe-resources-input-selection
docs/beginner-friendly-guides
docs/beginner-setup-guide
fix/javascript-analysis-worker-1563
fix/1649-ghidra-duplicate-names
fix/javascript-export-keys-integration-1369
test/maintenance-boundary-contracts-20261011
review/javascript-export-keys-1369
review/process-live-progress-1483
test/javascript-1495-growth-ratio
fix/ci-escape-timing
docs/normalized-terminal-geometry-1450
release/6.3.0
archive/release-6.3.0-pr1381
release/6.2.0
fix/electron-preload-dynamic-override
fix/javascript-self-referential-bundler-edges
release/6.1.0
cursor/grok-client-cherry-pick-0b56
feat/signature-posture
feat/dyld-shared-cache
feat/artifact-integrity-policy
feat/pkg-inventory
release/6.0.0
chore/sync-release-5.0.0
release/5.0.0
cursor/cloud-agent-node-787e
fix/javascript-xhr-open-endpoints
review/pr-711-realpath-fallback-wording
cleanup/replay-confinement
codex/test-suite-performance
codex/issue-foundations
codex/address-open-issues-2026-07-20
agent/javascript-vite-rollup-esbuild-adapters
agent/process-cleanup
agent/triage-integration
agent/unknown-commands-registry
feat/mcp-identity-metadata
morlvps/issue_cleanup
codex/installer-redesign
morl/roadmap-investigation-core
morl/roadmap-investigation-docs
release-please--branches--main--components--rea
rea-agents-6.8.0
rea-agents-6.7.0
rea-agents-6.6.0
experiment/atomic-codemode-wait-runtime-20261016
rea-agents-6.5.0
rea-agents-6.4.0
rea-agents-6.3.0
rea-agents-6.2.0
rea-agents-6.1.0
rea-agents-6.0.0
rea-agents-5.0.0
rea-agents-4.1.0
rea-agents-4.0.1
rea-agents-4.0.0
rea-agents-3.2.1
rea-agents-3.2.0
rea-agents-3.1.0
rea-agents-3.0.0
rea-agents-2.7.0
rea-agents-2.6.0
rea-agents-2.5.1
rea-agents-2.5.0
rea-agents-2.4.0
rea-agents-2.3.0
rea-agents-2.2.0
rea-agents-2.1.0
rea-agents-2.0.0
rea-agents-1.7.0
rea-agents-1.6.0
rea-agents-1.5.0
rea-agents-1.4.0
rea-agents-1.3.0
rea-agents-1.2.0
rea-agents-1.1.0
rea-agents-1.0.0
rea-agents-0.5.0
rea-agents-0.4.0
rea-agents-0.3.0
rea-0.2.1
rea-0.2.0
Labels
Clear labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
Mirrored from GitHub Pull Request
question
roadmap
triage
No labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
question
roadmap
triage
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
morluto/rea#1247
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @coygeek on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3379
Before submitting
Area
Process capture or runtime observation
Observed behavior
inspect-electron-pageconverts missing or invalid CDP collection arrays into empty inventories while reportingcomplete_within_window. Malformed successful replies for DOM snapshots, resource inventories, and worker discovery each produce a successful result with no exclusion or unavailable section. A caller cannot distinguish these unreadable replies from evidence that the corresponding collection is empty.All four public CLI calls exit with code
0. The valid control returns one DOM node, one resource, and one worker. Each malformed mode changes only the affected collection to an empty result.controlcomplete_within_windowmalformed-domcomplete_within_windowmalformed-resourcescomplete_within_windowmalformed-workerscomplete_within_windowEvery run reports
unavailable_sections: [],excluded: [], and zero dropped events. No real Electron instance emitting these malformed successful replies was established; the observed defect is at the public provider's protocol-admission boundary.Reproduction
sample-observationand save the following assample-observation/sample-repro.mjs. It creates every required input file inline, starts a local HTTP/WebSocket CDP fixture, and isolates the CLI home directory. It requires no installed browser or Electron application.Each run calls
node scripts/rea.mjs inspect-electron-page ENDPOINT page --observation-ms 100 --include-script-sources --jsonwith a fixture-selected literal loopback endpoint and an isolated home directory. The malformed modes independently replace one successful CDP reply: the DOM snapshot becomes{}, the resource tree hasresources: null, or worker discovery hastargetInfos: null. The other collections and target-validation replies remain unchanged.Expected behavior
An invalid or missing required collection must remain unknown or produce an actionable protocol failure. If REA retains a partial result, its completeness must identify the affected section. A valid empty array may represent an empty collection;
nullor absent required arrays must not provide that same evidence.docs/tool-design.md:51-55requires missing coverage to remain unknown rather than absence, anddocs/tool-design.md:77-86requires completeness derived from examined records and verification of malformed outcomes.docs/electron-observation.md:51-56promises explicit completeness for the normalized Electron inventories.Impact and scope
Impact level: P2. Assessment status: supported. Three unreadable producer replies were observed to become successful complete empty results, which can mislead analysis about the presence of DOM nodes, resources, or workers. The verified scope is malformed successful CDP replies, not normal conforming Electron responses.
Workaround status: unverified. A caller could inspect raw CDP replies separately, but no existing REA option was established that restores accurate completeness for the same malformed replies. Retrying without changing the replies does not restore the missing distinction.
REA version
6.4.0 (main at
8dde6370d0)Runtime and platform
Node.js v26.10.0; macOS 27.0.1. Architecture was not recorded for this reproduction.
Target and artifact context
A local HTTP/WebSocket CDP fixture advertises a selected page backed by ordinary local HTML and JavaScript files. It returns one authorized frame and script plus a DOM node, resource, and worker in the valid control. It independently changes the successful DOM, resource, or worker collection reply for each malformed mode. This reproduction uses the public CLI and simulated producer replies; no real Electron producer was established.
Interface
CLI
Earliest failure stage
Capture or observation
Relevant output or evidence
The public CLI matrix above is the primary violation evidence. Evidence provenance: observed. Local verification: reproduced. Reproduction completeness: complete.
Typed outcome or recovery expected
Run the valid control and each malformed mode independently. The control should keep all three observed items. Each malformed mode must fail with a protocol diagnostic or identify its collection as unavailable or excluded with partial completeness. Also run valid empty-array controls to verify that genuinely empty inventories remain distinguishable from unreadable replies. Preserving unrelated observed sections is acceptable; claiming complete coverage for an unreadable section is the failing signal. The valid empty-array controls are restoration checks, not additional reported observations.
Analysis or suspected cause
Source-derived reasoning:
src/browser/CdpElectronInspection.ts:285silently normalizes invalid resource arrays;src/browser/CdpElectronInspection.ts:329-345does the same for missing DOM arrays;src/browser/CdpElectronWorkers.ts:42normalizes invalid worker target arrays. These paths explain why the independently malformed successful replies in the executed public CLI matrix become complete empty inventories. The source locators explain the observed boundary; the public CLI fixture result establishes the violation.Additional context
Related completed issue #2556 concerns malformed child-frame IDs classified as scope exclusions; this report concerns malformed DOM, resource, and worker collection arrays returning complete empty inventories.
Related completed issue #2660 concerns malformed cache enumeration reported with complete storage fingerprints; this report concerns the separate Electron DOM/resource/worker collectors.
Related open issue #3172 concerns unavailable redirect-response fields treated as known evidence during web-capture comparison; this report concerns completeness at Electron collection admission.
Related open issue #3192 concerns false absence load states for ambiguous static script candidates during runtime reconciliation; this report concerns malformed CDP replies before reconciliation.
Related open issue #3316 concerns an alternate asset match hiding a mapped-file digest mismatch; this report concerns malformed collection replies reported as complete empties.
Related completed issue #1500 concerns script-to-frame attribution after execution-context mapping replacement; this report concerns collection completeness independent of script attribution.
Related open feature request #883 requests website worker source and lifecycle attribution; this report concerns inaccurate completeness when Electron worker enumeration supplies no valid collection.
@YunzhouLi-hub commented on GitHub (Oct 15, 2026):
我来承接这个。它和 #3376 是同一个产生边界,我会合成一个 PR 一起修(CONTRIBUTING.md 的 "Choosing a contribution" 要求 keep related corrections together)。
根因
src/browser/CdpCaptureValues.ts:15-21的recordsValue是一个全函数,把三种在 CDP 协议上完全不同的生产者状态塌缩成了同一个[]:[][][][null][]Electron 侧受影响的四条路径,全在
src/browser/CdpElectronInspection.ts和src/browser/CdpElectronWorkers.ts:CdpElectronInspection.ts:329-331—Array.isArray(result.strings) ? ... : [];:334—recordsValue(result.documents):285—recordsValue(tree.resources);:310—recordsValue(tree.childFrames)(子帧丢失还会连带丢掉整棵子树)CdpElectronWorkers.ts:42—recordsValue(recordValue(result)?.targetInfos)因为
CdpCaptureCompleteness的记账簿从来没被通知,unavailable_sections、excluded、dropped_events全是零,src/domain/browserCompleteness.ts:105-111于是落到complete_within_window。调用方无法把这些不可读的回复和「该集合确实为空」的证据区分开。为什么这是产生边界而不是下游打补丁
仓库里已经有正确的惯用法,只是这几条路径没走到:
CdpCaptureCompleteness.unavailable(section)/exclude(section, reason),以及src/domain/browserCompleteness.ts:104已经正确地把unavailableSections映射成attach_limited。全仓库有 72 处调用这个惯用法,包括同族的CdpPageCaptureWorkers.ts:33(if (result === undefined) completeness.unavailable("workers"))和CdpElectronWorkers.ts:38。只有 CDP 命令成功返回、而字段本身畸形的路径在静默塌缩。recordsValue有 24 个调用点、跨 10 个文件(CdpElectronInspection、CdpCaptureStorage、CdpCaptureStorageFingerprints、CdpCaptureEventHandlers、CdpCaptureDocuments、CdpWebMcpDiscovery、CdpPageCaptureWorkers、CdpElectronWorkers、CdpCaptureEventHelpers),所以这是一个被广泛复用的语义漏洞,不是单点遗漏。计划
结构性修法:让
recordsValue把准入结果报出来,使调用方能区分「合法空数组」和「畸形/缺失」。具体是加一个admitRecords(value),对缺失/非数组返回undefined(未知)、对合法空数组返回[],然后把确有记账需求的调用点路由到completeness.unavailable(section)。我会逐个调用点确认 blast radius,其余保持现状。验证
用 issue 里的 loopback HTTP/WebSocket CDP fixture(不需要真实 Electron)覆盖 control 和三种畸形模式:malformed-dom、malformed-resources、malformed-workers。断言每种畸形模式下对应 section 出现在
unavailable_sections且excluded非空,status不再是complete_within_window,同时 control 仍是一个 DOM 节点、一个 resource、一个 worker。本地跑npm run test:local、npm run check:fast、npm run verify:test-discovery,并在回复里报告实测结果和任何未覆盖的部分。我基于 upstream/main
4135c911d读的源码,上面的行号对应该 revision。开工前会先 rebase 到最新 main。@YunzhouLi-hub commented on GitHub (Oct 15, 2026):
PR 已提交:https://github.com/morluto/rea/pull/3850
基于 upstream/main
788864d52重新读源码并 rebase 后实施。先修正我承接评论里的两个数字:recordsValue实际是 19 个调用点、跨 9 个文件(我先前写成 24/10);同族惯用法最贴近的实例是CdpCaptureDocuments.ts:105-114的 web 侧captureResources,它已经做了完全正确的事,我照着它做。实际采用的修法
没有保留
recordsValue作为别名,而是换成两个导出:admitRecords(value)对缺失/非数组返回undefined(未知),只有 present array 携带生产者证据;admittedRecords(value)保留原来的逐条 record 过滤,给不需要记账的调用方用,文档字符串明说畸形条目被无声丢弃、需要记账的调用方应改用admitRecords+ 逐条recordValue。留着
recordsValue就是留着这个陷阱默认值给下一个调用方(AGENTS.md 的 "Remove superseded representations, aliases, wrappers")。这个 issue 里的四条路径
CdpElectronInspection.tstree.resourcesadmitRecords+ 逐条recordValue,缺失/非数组 →exclude("resources", "invalid_protocol_value", null)CdpElectronInspection.tstree.childFrameswalkFrameTrees,它本来就带畸形子帧记账回调CdpElectronInspection.tsresult.stringsadmitRecords,缺失 →exclude("dom", "invalid_protocol_value", null)并直接返回空 DOMCdpElectronInspection.tsresult.documentsstrings缺失时直接停掉是有意的:没有字符串表时documentURL索引无法解析,继续跑会把每篇文档误归因为out_of_target_scope(policy 原因,进policy_filtered_sections而不是unavailable_sections),是错误归因。子帧丢失连带丢整棵子树的问题,随walkFrameTrees的记账回调一起解决。另外
CdpElectronWorkers.ts:42的targetInfos和 web 侧CdpPageCaptureWorkers.ts:34是同一个Target.getTargets缺陷的跨适配器复制,只修一个会留下另一个陷阱,所以两个都修了(都进workerssection 的记账)。剩余的、这个 PR 没做的
有 13 个调用点没有可达的记账簿,我没有改它们,只在 PR 正文里报告为 remaining cleanup:
CdpCaptureDocuments.tsaccessibilityStates:掉一个畸形 state 会让states不完整,但treeIncomplete看不到。要报它需要新的 schema 字段,属于另一个 PR。CdpCaptureStorageFingerprints.ts8 处:该文件自己已有Array.isArray守卫 +cookies.length !== cookieValues.length掉数检测。CdpCaptureStorage.ts、CdpCaptureEventHelpers.ts、CdpCaptureEventHandlers.ts、CdpWebMcpDiscovery.ts。实测
全部在 rebase 后的 base
788864d52上跑:tsc --noEmitnpm run check:fastnpm run test:local4 个改动测试文件npm run test:localsrc/browser全部 34 个测试文件npm run test:local -- tests/evaluation/moduleBoundaries.test.tsnpm run verify:test-discoverynpx oxfmt --check src/browser/npm run docs:checkartifacts:managed-evidence因mkdtempEPERM 失败,在无改动的干净树上同样失败,是环境问题回归证明
把
admitRecords原地改回旧的塌缩原语(缺失返回[]而不是undefined),47 个测试里 12 个失败。其中覆盖这个 issue 的是:CdpElectronInspection.test.ts > reports a frame whose resource inventory is missing rather than empty CdpElectronInspection.test.ts > reports a non-array resource inventory rather than empty CdpElectronInspection.test.ts > keeps a child frame's authorized resources after its parent answered CdpElectronInspection.test.ts > reports a snapshot without its string table rather than empty names CdpElectronInspection.test.ts > reports a snapshot whose documents field is not an array CdpCaptureWorkers.test.ts > Electron: reports a missing target inventory as unavailable rather than no workers代表性断言差异(base revision):
`
`
剩下 8 个新测试两种实现下都过,这是设计如此:它们走的是逐条
recordValue路径,base revision 本来就处理了,是用来防止过度上报的对照组。未覆盖的部分
那 13 个无记账簿可达的调用点保持现状,没有测试锁定它们的 ledger(没有 ledger 可锁定)。没有驱动真实 Chrome/Electron 会话——loopback fixture 覆盖的是同一处 CDP 应答解释分支,与仓库现有 browser 测试的边界相同。