mirror of
https://github.com/openclaw/openclaw.git
synced 2026-11-01 21:18:11 +00:00
* test(ui): deslop q0077 tests
Remove duplicate drag, persistence, resize, animation, keyboard and touch scenarios from debug-diagnostics; debug-overlay-position.e2e.test.ts retains both scenarios verbatim.
Drop the native GitHub status replay: github-connections.test.tsx covers loads native available/unavailable and panels-tools-skills.browser.test.ts covers the shared identity presentation. The retained unidentified System management E2E covers Profile/agent navigation and now preserves the no-write-before-authorization assertions.
Remove unasserted gateway-status proof-image capture and the copied native-settings href inventory. Keep route rendering, touch geometry, desktop fallback, authority, polling and lifecycle assertions; reuse the existing absence assertion helper.
CI-only q0077: 3940 to 3678 test lines; 34 to 31 declarations. Plain oxlint, oxfmt and diff check pass. Tests and coverage intentionally not run. Below the 40 percent target: retained scenarios protect distinct layout, startup ordering, recovery, legacy draft and authorization boundaries.
* test(ui): remove redundant q0077 e2e layers
Keep native GitHub clipboard and personal-scope transport proof; account scope, reconnect, profile retirement and polling are covered by github-connections.test.tsx, github-identity.test.ts and github-identity-personal.test.ts. Profile identity and consent remain covered by profile-page-preferences.test.tsx.
Keep footer notice, dense queue, short-pane reachability and independent touch scroll proof. Remove checks/monitoring and disclosure replays owned by chat-ci-details.e2e.test.ts and session-details-progress.e2e.test.ts. Remove copied launcher labels.
Keep debug active-run paging, tooltip input modes and degraded ping. Snapshot refresh and telemetry histories remain in pages/debug/view.test.ts and debug-overlay.test.ts. Keep transient boot paints and sibling-tab profile ordering; browser chrome projection remains in app/bootstrap.test.ts, with profile appearance in theme-selection-defaults.e2e.test.ts.
Remove startup priority/drain replays owned by app/connection-bootstrap.test.ts; live peer rendering is retained in chat-collaborator-scroll.e2e.test.ts. Keep the explicit refresh, filter and parked-progress scenarios. Desktop write failure and accepted-config reconciliation remain in systems-page.test.ts, with host enabling in desktop-panel-host-setup.test.ts.
CI-only: no tests or coverage run. Plain oxlint, oxfmt and diff check pass. Shard now 2870 lines from original 3940, a 27.2 percent reduction, below the requested 40 percent. No production/support files or routing changed; preserve the remaining distinct behavior rather than delete it for the metric.
* test(release): deslop q0080 tests
Share bootstrap identity, artifact paths, JSON writes, and packed-byte fixtures. Keep all archive size, inventory, UTF-8, workflow-ref, and output-root boundaries.
The removed whitespace alias replay uses the same parser guard as plugin-publication-artifact.test.ts: rejects tar manifest ambiguity (whitespace prefix). Its rejects a hidden duplicate package.json after a single zero tar block case also protects against stopping after the first canonical manifest. The remaining exact bootstrap policy-limit cases stay here.
* test(scripts): remove redundant q0080 proof layers
Remove copied declaration/cache-input inventories and exact broker read-order lists. Keep behavioral cache reuse/invalidation, output preservation, mutation refusals, trusted checkout, tokenless fixture, and noop-only guards.
The shared compiler-failure preservation path remains covered by write-plugin-sdk-entry-dts.test.ts: rejects source declaration export before replacing published or local declarations; declaration-stage.test.ts also retains sibling compiler errors without publication. Keep unified missing-receipt failures with cache on and off. Remove a legacy TypeScript declaration-path probe whose installed subject no longer exists.
Gateway numeric parsing remains covered by parallels-smoke-model.test.ts: rejects loose Parallels numeric limits before starting smoke lanes. Retain gateway-specific precedence. Trim repeated JSX predicate variants and startup log combinations; clean-shutdown warning/failure inputs now reach their intended guard instead of failing on the earlier backfill check. No test runs per CI-only mode.
* test(scripts): remove duplicated q0080 oracle layers
Drop the source-extracted run.sh replay with mocked command effects and copied event inventory. The real projects-startup-migration Docker scenario retains schema-before-startup, Doctor repair, log and snapshot assertions. It is opt-in, so this removes the default unit-frequency sequencing replay.
Drop snapshot-oracle self-tests: doctor-session-worktree-workspace.test.ts repairs discovered worktree sessions only through Doctor and releases their databases; startup-migration.worktree-workspace.test.ts backfills the persisted project workspace through the resolver once. Both exercise real persisted session entries, not constructed snapshots.
Drop gateway response-oracle self-tests in favor of server-http.probe.test.ts prepared-suspension liveness/readiness, server-methods.suspension-admission.test.ts blocked dispatch, and gateway-suspend-coordinator.test.ts ready-lease and expiry proof. Keep client deadline, socket cleanup, capability and malformed-health tests. No production assertions removed; no test runs per CI-only mode.
* test(scripts): deslop q0079 tests
Keep tsdown plan serialization and explicit output cleanup in their existing owner tests. Drop iOS runtime rejection replays covered by newest-compatible-runtime plus unavailable-runtime; dirty-tracked retains source admission, and successful native scenarios retain Xcode parsing. The provider-duplicate fixture now appends its duplicate after the valid prefix so it independently proves the count guard; provider-out-of-order retains ordering proof.
Remove workflow name/runner inventories and unused result-fixture overrides while retaining signing, permissions, target identity and sanitized upload guards. CI-only: oxfmt, diff-check and plain oxlint passed; no test or coverage execution. Honest reduction is 73 lines, below the 40% target: unique process cleanup, memory containment and native lifecycle contracts remain.
* test(scripts): remove redundant q0079 proof layers
Replace the iOS workflow resource collector replay with routing checks: ios-resource-timeline.test.ts owns workload exit/collector lifecycle, and ios-release-fastlane-gates.test.ts owns screenshot startup behavior. Native adapter tests retain signing, source identity, read-only RPC, credential isolation, cleanup and cancellation boundaries while dropping copied argument/proof inventories.
Drop the direct third-party tsdown syntax replay: write-plugin-sdk-entry-dts.test.ts rejects transitive declaration export before replacing published or local declarations. Retain a cheap real-child exit-65 test for wrapper status propagation. Keep all independently owned process supervision, memory containment and path safety cases.
CI-only: oxfmt, plain oxlint and diff-check pass; no tests or coverage run. Additional structural reduction remains below 40 percent because remaining lifecycle/topology branches lack replacement proof.
* test(scripts): consolidate q0079 decision fixtures
Table the nine tsdown planner paths and four symlink operations with shared assertions, retaining exact filter ordering, cleanup selection, pre-traversal refusal and unchanged target files. Remove repeated admission calls from memory rows while retaining each topology's selected heap and the independent admission tests.
Use the iOS native lifecycle as the build-only/qualification ordering proof instead of repeating mock inventories; keep source admission, selected runtime execution, resource retention and setup RPC evidence. The runTrials comparison case owns ABBA order rather than replaying armPlan directly.
CI-only: oxfmt, plain oxlint and diff-check passed; no tests or coverage run. Original 3664 test lines now 3163. Further reductions to the 40 percent target would remove unique currently retained behavior; no production or support files changed.
* test(qa-lab): deslop q0078 tests
Reuse existing Control UI fixture helpers and Gateway client acquisition. Remove per-scenario timeout report plumbing and the redundant media transform no-throw probe.
Retained proof: control-ui-media-transcript.real-gateway.e2e.test.ts still completes real provider turns after successful and failed attachments and checks display-only error persistence. All 17 declarations (20 expanded cases) remain, including private completion package migration, native hook pressure, approval ordering, requester authority and hard-kill recovery.
CI-only campaign: oxlint, oxfmt and diff checks passed; no tests or coverage run. LOC 3796 -> 3695 (2.7%); 40% target not reached because remaining scenarios cover distinct behavior.
* test(scripts): deslop q0081 tests
Factor repeated child lifecycle fixtures and release-note target options; express Markdown fixtures as paragraphs without changing their bytes. Remove the unreferenced afterBaselineOutput helper and the redundant correction-tag helper assertion; the retained correction-tag renderer case exercises the same normalization branch. Keep all distinct release-publication, signing, process-tree, diagnostic, and timeout cases. CI-only campaign: plain oxlint, oxfmt, and diff-check; no test or coverage runs. Reduction is below target because no further safe structural deletions were identified.
* test(scripts): remove duplicate q0081 proof layers
Keep immutable changelog reads in the pinned legacy/split renderer CLI test and docs CLI protection in the inline-disclosure scenario. Keep full rendering in pinned beta and exact-size boundary tests. Retain explicit fork-adapter outcomes instead of repeating native dependency controls. Reuse the managed-child synthetic fixture; native Job descendants after abort cover the removed taskkill failure replay. Keep selector routing variants in test/npm-publish-plan.test.ts and one repair guard at the publication boundary. Remove copied progress wording and workflow inventory; consolidate equivalent argv variants and bounded output diagnostics. CI-only: plain oxlint, formatting and diff-check pass; no test runs. Total shard reduction remains below the 40 percent target because remaining cases protect distinct publication, signing and lifecycle behavior.
* test(scripts): consolidate q0081 sibling proof
Remove normal-exit process matrix rows covered by managed-child-process.output starts-owned-tree-cleanup, windows native-Job-descendants normal-exit, and drain still-fails-on-kill cases. Keep the unique Job handle-close failure. Combine npm PATH and toolchain inventory fixtures while retaining both execution routes. Remove duplicate extended-stable verification covered by verify-release-notes and redundant release lookup call-shape replay covered by preflight evidence error tests. Keep the ClickClack runtime snapshot regression from a842ad35f3. CI-only: plain oxlint, formatting and diff-check passed; no tests or coverage ran. Shard remains below requested reduction because further unique contracts lack replacement proof.
* test(qa-lab): deslop q0084 tests
Keep the distinct authority, recovery, transport and upgrade scenarios. Remove the malformed approval snapshot replay: src/gateway/server-methods/exec-approvals.test.ts retains rejects malformed node approval snapshots at the gateway boundary, covering the validatePayload rejection in exec-approvals.ts.
Remove the repeated-request diagnostic projection layer without changing its settlement, deadline, ordering or exactly-once assertions. Reuse Node stream buffering and the existing loopback listener in the Telegram artifact fixture.
* test(scripts): deslop q0083 tests
Remove profile replays of the shared admission deadline; retain the queue-age and exact-expiry contract in the existing deadline case. Keep malformed-JSON redaction covered by the truncated JSON case.
Drop workflow metadata inventories and duplicated SQLite summary assertions. Retain ClawHub credential isolation, artifact binding, trusted-source and pre-token ordering guards. ci-workflow-guards.test.ts owns repository-wide action SHA pinning; bench-sqlite-reliability.test.ts retains the full crash and recovery report assertions.
CI-only campaign: oxlint, oxfmt and diff checks passed. Runtime tests and coverage intentionally deferred to hosted CI. The 40 percent line target could not be reached without removing distinct release, authority or lifecycle proof.
* test(scripts): remove redundant q0083 proof layers
Replace Testbox workflow inventories with a generic admission invariant and one shared shell-boundary proof. Retain ClawHub credential isolation, immutable artifact binding, and pre-credential verification while removing copied metadata and helper internals.
Keepers: compiler-input-snapshot.test.ts owns metadata invalidation; vitest-worker-artifacts.test.ts owns real shared compilation and source rebuilding. prepublish-plugin-registry-artifact.test.ts and prepublish-plugin-registry-shell.test.ts own invalid registry identity/digest rejection. test-projects.test.ts and vitest-specialized-config.test.ts own UI routing variants; pr-ci-dispatch.test.ts owns publisher proof decoding.
The SQLite smoke still runs the full crash/recovery executable; remove report reassertions of invariants already enforced by its publication, restore, repository, compaction, and runner owners. Keep distinct lifecycle, authority, ordering, and report-boundary checks.
CI-only: oxfmt, plain oxlint and diff checks pass; no tests or coverage run. Total shard 3297 to 2705 lines (18.0 percent), below the requested 40 percent without deleting distinct remaining behavior.
* test(scripts): trim remaining q0083 fixture duplication
Remove obsolete compiler config fixture inputs after retiring their replay cases. Move command binding assertions into the existing shell execution proof. Remove workflow metadata and diagnostic-source restatements while keeping the actual credential, publication, and immutable handoff guards.
The package-compat.test.ts plugins/kitchen-sink logger help-error/timeout cases own shared fixture-command failure behavior; keep one onboarding entry-point failure and one Doctor status/redaction case rather than replaying each helper at later calls.
CI-only proof: oxfmt, plain oxlint and git diff --check pass. No test, build or coverage runs. Shard now 3297 to 2652 lines; 40 percent remains unsupported without removing distinct lifecycle or authority proof.
* test(ui): deslop q0082 tests
Remove repeated dashboard retry, denial, board-less and queued progress proof: board-widget-cell-plugin.test.ts covers retry/denial and board-less target liveness; session-progress-card.test.ts covers queued progress.
Keep browser geometry, target scope, live mention updates, and authority/lifecycle scenarios. Drop sidebar self-comparison and repeated activity grouping, count, and inventory assertions covered by session-activity-view.test.ts. CI-only static validation: oxlint, oxfmt and diff-check passed. No runtime tests or coverage run. Reduction is 171/3820 lines (4.5%); the 40% target is not met.
* test(ui): consolidate q0082 e2e proof layers
Retire eviction replay covered by chat-page-retained-sessions.test.ts (keeps edited panes mounted through overflow), parked-pane lifecycle and queued-edit token tests. Retire outbox pagination replay covered by chat-pending-inputs.pagination.test.ts (retires consumed server queue chips outside the transcript window; discovers and retains a live queue beyond the latest page).
Retire generic submission-gate and full-access creation replay covered by session-method-access.test.ts, submit-gates.test.ts and permission-selection.test.ts. Keep current-authority downgrade, incognito, remote project actions and folder-boundary integration.
Retire widget scope-selection replay covered by lib/board/widgets/session-progress.test.ts (moves the listener with context and activity without duplicating it on selection changes). Keep browser geometry and a compact repeated-failure backoff regression; history errors remain covered by chat-history-observation.test.ts and empty/loading Details by chat-details-arrival.test.ts.
Reduce the real-Gateway web-search matrix to persisted legacy clearing, disabled re-enable and New Session policy; chat-composer-capability-menu.e2e.test.ts retains positive toggles, readiness, disconnect and false/omitted variants. Keep bundle byte identity and persisted sibling readback.
Retire chat identity-link replay covered by chat-message.test.tsx (sender provenance links only profiles), chat-details-people.test.tsx (same-name identities, focused activity links) and person-activity-link-solid.test.tsx. Keep actual hovercard navigation, filter reloads and exact missing bookmarks. URL canonicalization remains covered by session-activity.test.ts.
Replace the activity capture showcase with minimal browser paint/geometry input; session-activity-view.test.ts owns grouping, facets and viewing lists. Remove Team fixture inventories and generic widget smoke covered by control-ui-team-scale-fixture.test.ts and board-mcp-app.e2e.test.ts; retain font loading, continuous scroll coverage and independent warm-state restore proof.
CI-only: plain oxlint, oxfmt and diff-check passed. No tests, builds, coverage or Testbox commands ran. No production/support edits or file deletions. Preserve the preceding q0082 commit; the 40 percent reduction target remains unmet.
* test(qa-lab): consolidate q0078 owner-boundary proof
Port q0078 commits 0c5afea2b11ded52b04a9da291b4dfcccea23da1, 698f3951d60c4d39a1a14fe1de0573cde1778b50, and d4da54b0d8c446bc678da7ba50536a424538b60c onto the campaign lane. The first cleanup was already present.
Preserve the newer lane inventory consolidation and its native QA routing assertion using the retained media-transcript fixture. Keep the source shard deletions and owner-boundary consolidation unchanged elsewhere.
CI-only validation: oxlint and oxfmt --check passed for 13 surviving changed files; staged and working-tree diff checks passed. Independent review found no actionable P0-P2 porting defects. No test suites or coverage run; 8 QA test declarations retain 10 expanded cases for landing CI.
* test(qa-lab): remove redundant q0084 e2e layers
Port q0084 commits 7a4650ae8d19128d7bff0a36e41b7268cff9fc17 and 4367b001707acb09601cec45ad2d825d80bb4709 onto the campaign lane. The first commit is already present in the lane. Preserve the lane removal of the control-plane inventory entry while applying the remaining retired test entries and reload-owner consolidation.
Approval, pending-work, MCP, and memory provenance coverage remains at the focused owner boundaries documented by the source shard. No newer lane test cases or assertions were removed: the five test files affected by the second commit matched its parent exactly.
CI-only validation: plain oxlint and oxfmt --check passed for all three surviving changed files; git diff --check passed. Independent review found no actionable P0-P2 findings. No tests, coverage, Testbox, or check-changed were run; runtime proof is deferred to landing CI.
* test(ui): deslop q0085 tests
Remove diagnostic screenshot and report layers; reuse provider fixture setup and consolidate the sidebar identity proof into agent selection.
Retained coverage: command-palette.test.ts covers visible catalog keyboard order and selected agent navigation. model-providers/data.test.ts covers profile-scoped readiness versus provider-wide rejection; view.test.ts and profiles-view.test.tsx cover rejected and quiet profile presentation. model-providers.e2e.test.ts and model-providers-page.catalog.test.ts retain selected-agent loading and refresh behavior.
Preserve meetings interim/final summary polling, metadata observation interleavings, IME safety, and companion reset races. CI-only validation: plain oxlint, oxfmt, and diff checks passed; tests and coverage deliberately not run. Shard test LOC 3980 to 3529 (11.3 percent), below the 40 percent target because the remaining scenarios protect distinct behavior.
* test(ui): consolidate redundant q0085 e2e layers
Retire the real-Gateway folding replay: session-diff-panel.test.ts protects manual folding, mode changes, refresh retention and source invalidation; session-diff-folds.test.ts protects syntax and gaps; sessions-diff.test.ts protects real Git patch production. chat-session-diff.e2e.test.ts retains browser patch, gap and highlighting coverage. Remove only the deleted path from routing and timing inventories.
Composer keepers: chat-view.test.ts protects IME Escape, reply precedence and abort; chat-composer-actions.test.ts and chat-flow.active-run-follow-ups.e2e.test.ts protect alternate sends. Carry the streaming context-menu assertion into the retained quoted-draft scenario.
Task keepers: chat-pane-task-suggestions.test.ts protects rejected acceptance, retry, dismissal reconciliation and scope retirement. Retain each launch mode, capability gating, contrast and responsive-layout branch in E2E. Metadata keepers: chat-metadata-store.test.ts protects hidden startup fallback, missing commands and shared reads; model-catalog-store.test.ts protects pending catalog reuse. Retain browser visibility, activation and hidden-global checks.
Startup keepers: chat-send.test.ts protects timeout settlement and recovery; chat-send-submit.test.ts protects explicit failed-run retries with pending history. Retain model receipt gating and route startup failures. Agent keepers: lib/agents/index.test.ts protects forced roster refresh ownership, settings-agent-selector.e2e.test.ts protects independent settings selection, and sessions/route.test.ts protects scoped queries. Keep both palette reload orderings.
Companion history protects post-Clear pending-turn custody; retain image read races, reset recovery and stale-session rejection checks. Meetings view.browser.test.ts protects notes versus transcript separation, and meetings-page.test.ts protects bounded reader requests. Retain grouping, silent-capture styling, live summary cadence, downloads and capture navigation.
CI-only: plain oxlint, oxfmt and git diff --check pass; no tests, builds, coverage or Testbox runs. Cumulative q0085 test LOC 3980 to 2387, a 40.03 percent reduction. This is an additional commit; preserve the earlier shard commit.
* test(tooling): deslop q0088 tests
Remove repeated lint-selection rows and eager-selection checks already exercised by the direct runner's channels and gateway-methods subprocess cases.
Replace resolver-derived package inventories with a focused QA lifecycle/native sibling prerequisite test. Native envelope coverage remains in the runtime-consumer, measured-envelope and file-budget cases; executable discovery and process-owner routing remain in extension-test-plan.test.ts.
CI-only campaign: plain oxlint, oxfmt and diff checks pass; runtime validation is deferred to hosted CI. Retain the remaining security, release and lifecycle scenarios; this shard is below the requested line-reduction target.
* test(tooling): remove redundant q0088 proof layers
Keep one lint policy decision and one generic full-owner scope invariant; consolidate direct SDK importer fixtures. Remove copied assertion-report inventory and repeated notification wording/status variants while retaining credential, checkout, retry and publication guards.
Replace timing log generation in the native envelope test with its measured input. Log refitting remains covered by test/scripts/ci-test-timings.test.ts; file lifetime and estimate scope remain covered here and in extension-test-plan.test.ts.
Remove batch lifecycle replay: vitest-worker-artifacts.test.ts covers shared completed generations and real borrowers; vitest-runner-outcome.test.ts batch terminal classification covers disposal before completion publication. The retained batch cache/preparation case still proves actual generation cleanup.
Remove matrix receipt/digest replay covered by extensions/qa-lab/src/code-mode-model-matrix.runtime-identity.test.ts and code-mode-model-matrix.test.ts extended process/evidence cases. Retain frozen-runtime provenance, comparison, workloads and interruption evidence here.
CI-only: oxfmt, plain oxlint and diff checks pass; no tests or builds run. Total shard reduction remains below 40%; unique process, authority and release behaviors are retained.
* test(scripts): deslop q0086 tests
Remove Knip wrapper and launch-shape duplication covered by check-deadcode-reporting.test.ts and pnpm-runner.test.ts; keep real process-tree, stream, and parser boundary proof. Consolidate Watch bootstrap, token rotation, persisted reconnect and artifact redaction into one lifecycle.
Reduce repeated workflow path rows and report text inventories while retaining branch representatives, typed count assertions, publication authority and supply-chain checks. Replace the copied workflow audit-step inventory with executable admission checks for every post-scope step. Consolidate placeholder rejection fixtures without dropping outcomes.
CI-only campaign: formatting, plain oxlint and diff-check passed; no tests, coverage or builds run. LOC 3620 -> 3507; declarations 90 -> 86. Below the 40% target: remaining suites cover distinct planner ownership, artifact invalidation, staging rollback, bundle boundaries and publication safety. No production, support or configuration changes.
* test(scripts): consolidate q0086 tooling proof layers
Remove copied workflow path and step inventories; keep generic scheduled scope coverage and executable audit admission. Retain one planner case per selection branch instead of profile/input cross-products.
Owner-boundary keepers: ci-workflow-planning.test.ts retains full compiler proof without adding a boundary row and gates published-driver dispatch revision mismatches; extension-boundary-cache.test.ts reuses observed compiler lookups and rejects newly effective resolutions; compiler-input-snapshot.test.ts retains linked topology and generator invalidation. Installed README presentation stays owned by src/plugins/installed-plugin-overview.test.ts.
Exercise Docker volume cleanup and nonzero exit through the existing real-wrapper envelope fixture instead of a parallel mocked shell library. Reuse the existing trusted TLS fixture for Watch reconnects. Check npm provenance on actual publication arguments, not source text. No production or shared-helper changes.
CI-only: formatting, plain oxlint and diff-check passed. No tests or coverage run. Additional 3507 -> 3107 lines; cumulative 3620 -> 3107 (14.2%), below 40%: preserve remaining distinct executable failure, authority, storage, staging and protocol proof.
* test(scripts): trim q0086 fixtures and duplicate assertions
Use one advisory fixture with optional URL, and prove missing-option errors through the CLI instead of repeating the parser helper. Consolidate multi-package selection order into the real serial publication scenario.
Remove full-owner assertion replay covered by ci-workflow-planning.test.ts extension lint PR admission, copied workflow path comparisons, duplicate import parser variants and self-reported Watch metadata inventories. Keep Watch request signatures, authentication, rotation, polling and both adapter command paths. Simplify fixed compiler fixture parameters and repeated static asset rows.
CI-only proof: formatter, plain oxlint and diff-check passed; no tests, builds or coverage runs. Additional 3107 -> 2961 lines. Cumulative 3620 -> 2961 (18.2%): 40% target remains unmet because the remaining executable failure and authority paths have no substantiated replacement. No production, helper, config or file deletions.
* test(ui): deslop q0087 tests
Remove capture-only screenshot/video plumbing and share repeated profile, diagnostic-response, and comment-send fixtures without dropping their assertions.
Retained coverage: update-triage automatic diagnoses successfully while missing triage module covers manual confirmation and failure recovery; cloud-startup-failure history/cold-scope cases retain reload and retry while disconnect/replace-client retain warm failures; usage-calendar-boundaries east/west cases retain both calendar modes and Today/7d/All retain preset branches. Drop only the redundant manual, baseline, and aligned-calendar rows plus same-path 30d/90d/1y replays.
CI-only: oxfmt, plain oxlint, and diff-check pass. No runtime or coverage measurement. Below 40% target: retain distinct browser geometry, authority, service-worker publication, gesture, storage, and lifecycle-race contracts.
* test(ui): remove redundant q0087 e2e layers
Keep mobile dashboard geometry while dropping owner-covered persistence, command and sidebar replays: dashboard-presentation-defaults.test.ts (transient request, personal precedence, read-only, save opening face) and app-sidebar-row-identity.browser.test.ts (live face and href updates).
Keep native queue removal races and eventual delivery; queued-message-edit.test.ts covers dropped-connection edits and separate composer sends, and chat-flow.queue-reorder.e2e.test.ts covers reconnect order. Drop the cold palette replay covered by command-palette-attachments.test.ts (settles a cold submit exactly once) and command-palette-first-open.e2e.test.ts (cold files and cancellation).
Drop transcript-replacement comments covered by chat-comment-controller.test.ts (edits and deletes without a built-in transcript) and native-plugin-ui.e2e.test.ts; tooltip.test.ts owns repeated Escape and focused-hover behavior. session-progress-disclosure-controller.test.ts owns completion/remount choices. Update storage faults belong to lazy-shell-action.test.ts; overlays-update-triage.test.ts owns passive failures and explicit-click admission.
Shrink calendar and widget fixtures; replace retired usage helper imports with existing canonical factories. Preserve rollover, skipped midnight, native inertia, widget nonce/media behavior, Incognito deletion and deployed-worker handoff. CI-only: formatting, plain oxlint and diff-check pass; no runtime tests. Cumulative reduction is 24.1%, below 40%; further identified cuts would remove distinct behavior.
* test(ui): narrow q0087 scenarios to unique browser boundaries
Retain the triage missing-chunk browser regression; automatic failure admission and successful diagnosis remain in overlays-update-triage.test.ts (passive failure and explicit click) and update-triage.runtime.test.ts (requires explicit diagnosis despite stale campaign).
Retain cloud cold-scope gating and every deleted-Incognito outcome. Warm client replacement is covered by session-placement-startup.delivery.test.ts (restores paused content without effects after storage failure and client replacement); ordinary queuing/recovery by new-session-page.cloud-startup.runtime-load.e2e.test.ts; diagnostics and copy by chat-error-details.e2e.test.ts and chat-view.test.ts (keeps startup Retry owned by retryable).
Remove plugin-composer comment replays covered by native-plugin-ui.e2e.test.ts (canonical chat admission and view recovery) and chat-comment-controller.test.tsx. Preserve Escape dismissal before keyboard reopening. Remove the anonymous post-deploy replay covered by control-ui-session-entry.real-auth.e2e.test.ts (ignores spoofed identity on anonymous canonical documents while protecting the handoff) and control-ui-public-session-entry.test.ts.
Trim redundant cache readback while preserving flush and per-frame reload proof; use the existing one-pixel image fixture instead of screenshot artwork. CI-only: plain oxlint, formatting and diff-check passed; no tests or coverage run. Total 3396 to 2226 lines (34.5%); 40% remains unmet because the audited remaining scenarios have distinct browser coverage.
* test(ui): retain private server registration for preserved diff proof
* test: preserve distinct coverage and repair replay fixtures
272 lines
11 KiB
TypeScript
272 lines
11 KiB
TypeScript
import { fork, spawnSync, type ChildProcess } from "node:child_process";
|
|
import { on, once } from "node:events";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
import { parseSqliteReliabilityCli } from "../../scripts/lib/sqlite-reliability-cli.js";
|
|
import {
|
|
formatReliabilityStderr,
|
|
STRESS_TABLE_SQL,
|
|
type ReliabilityReport,
|
|
} from "../../scripts/lib/sqlite-reliability-contract.js";
|
|
import { monitorSqliteWalDuring } from "../../scripts/lib/sqlite-reliability-wal-monitor.js";
|
|
import {
|
|
canonicalPathWithExistingParent,
|
|
isPendingPathInRepository,
|
|
} from "../../scripts/lib/sqlite-reliability-worker-paths.js";
|
|
import { resolveVitestNodeArgs } from "../../scripts/lib/vitest-process-env.mts";
|
|
import { openNodeSqliteDatabase } from "../../src/infra/node-sqlite.js";
|
|
import {
|
|
resolveRuntimeWorkerThreadExecArgv,
|
|
resolveRuntimeWorkerUrl,
|
|
} from "../../src/infra/runtime-worker-url.js";
|
|
import {
|
|
closeOpenClawStateDatabaseForTest,
|
|
openOpenClawStateDatabase,
|
|
} from "../../src/state/openclaw-state-db.js";
|
|
import { resolveTestNodeExecPath } from "../../src/test-utils/node-process.js";
|
|
import { withinTest } from "../helpers/promise.js";
|
|
import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js";
|
|
import { toolingTsEntrypoints } from "./tooling-ts-runtime.test-support.js";
|
|
|
|
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
|
|
const makeRoot = () => tempDirs.make("openclaw-sqlite-reliability-test-");
|
|
const nodeExecutable = resolveTestNodeExecPath();
|
|
const nodeArgs = resolveVitestNodeArgs();
|
|
// Windows repeats ACL checks and crash/restore copies throughout the full proof.
|
|
const RELIABILITY_PROOF_TIMEOUT_MS = process.platform === "win32" ? 480_000 : 240_000;
|
|
const RELIABILITY_SMOKE_TEST_TIMEOUT_MS = process.platform === "win32" ? 1_200_000 : 300_000;
|
|
|
|
function reliabilitySmokeTest(name: string, test: () => void): void {
|
|
it(name, test, RELIABILITY_SMOKE_TEST_TIMEOUT_MS);
|
|
}
|
|
|
|
function runProof(args: string[], env: NodeJS.ProcessEnv = {}) {
|
|
const result = spawnSync(
|
|
nodeExecutable,
|
|
[...nodeArgs, "--import", "tsx", "scripts/bench-sqlite-reliability.ts", ...args],
|
|
{
|
|
cwd: process.cwd(),
|
|
env: { ...process.env, ...env },
|
|
encoding: "utf8",
|
|
timeout: RELIABILITY_PROOF_TIMEOUT_MS,
|
|
},
|
|
);
|
|
if (result.error) {
|
|
throw result.error;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
async function waitForChildReady(child: ChildProcess): Promise<void> {
|
|
for await (const args of on(child, "message", { close: ["exit"] })) {
|
|
const message: unknown = args[0];
|
|
if (message && typeof message === "object" && "kind" in message && message.kind === "ready") {
|
|
return;
|
|
}
|
|
}
|
|
throw new Error("writer child exited before ready");
|
|
}
|
|
|
|
function waitForChildExit(
|
|
child: ChildProcess,
|
|
): Promise<{ code: number | null; signal: NodeJS.Signals | null }> {
|
|
return once(child, "exit").then(([code, signal]) => ({ code, signal }));
|
|
}
|
|
|
|
describe("scripts/bench-sqlite-reliability", () => {
|
|
it.each([
|
|
["whitespace-only stderr", " \n\t ", ""],
|
|
[
|
|
"multiline quoted stderr",
|
|
' first line\n"quoted"\\path ',
|
|
' stderr="first line\\n\\"quoted\\"\\\\path"',
|
|
],
|
|
])("formats %s", (_name, stderr, expected) => {
|
|
expect(formatReliabilityStderr(stderr)).toBe(expected);
|
|
});
|
|
|
|
it("detects a transient WAL overrun before the file shrinks", async () => {
|
|
const walPath = path.join(makeRoot(), "database.sqlite-wal");
|
|
let stopRequests = 0;
|
|
|
|
await expect(
|
|
monitorSqliteWalDuring({
|
|
maxWalBytes: 1024,
|
|
onLimitExceeded: () => {
|
|
stopRequests += 1;
|
|
},
|
|
operation: async () => {
|
|
fs.writeFileSync(walPath, Buffer.alloc(2048));
|
|
await new Promise((resolve) => {
|
|
setTimeout(resolve, 25);
|
|
});
|
|
fs.truncateSync(walPath, 0);
|
|
return "complete";
|
|
},
|
|
pollIntervalMs: 5,
|
|
walPath,
|
|
}),
|
|
).rejects.toThrow("SQLite reliability WAL exceeded the 1024-byte profile limit: 2048 bytes");
|
|
expect(stopRequests).toBe(1);
|
|
});
|
|
|
|
it("rejects malformed arguments before creating state", () => {
|
|
const unknown = runProof(["--wat"]);
|
|
expect(unknown).toMatchObject({ status: 2, stdout: "" });
|
|
expect(unknown.stderr.trim()).toBe("error: Unknown argument: --wat");
|
|
|
|
expect(() => parseSqliteReliabilityCli(["--profile", "smoke", "--profile", "large"])).toThrow(
|
|
"--profile was provided more than once",
|
|
);
|
|
expect(() => parseSqliteReliabilityCli(["--profile", "huge"])).toThrow(
|
|
'--profile must be one of smoke, default, large; got "huge"',
|
|
);
|
|
expect(parseSqliteReliabilityCli(["--help", "--profile", "huge"])).toEqual({
|
|
help: true,
|
|
});
|
|
});
|
|
|
|
reliabilitySmokeTest("proves snapshot reliability while safely reusing state", () => {
|
|
const stateDir = makeRoot();
|
|
const previousSyncedRepository = path.join(
|
|
stateDir,
|
|
"sqlite-reliability-runs/previous-run/synced-snapshots",
|
|
);
|
|
const previousArtifact = path.join(previousSyncedRepository, "previous-artifact");
|
|
fs.mkdirSync(previousSyncedRepository, { recursive: true, mode: 0o700 });
|
|
fs.writeFileSync(previousArtifact, "retained");
|
|
|
|
const existingDatabase = openOpenClawStateDatabase({
|
|
env: { ...process.env, OPENCLAW_STATE_DIR: stateDir },
|
|
});
|
|
try {
|
|
existingDatabase.db.exec(STRESS_TABLE_SQL);
|
|
existingDatabase.db
|
|
.prepare(
|
|
"INSERT INTO openclaw_reliability_entries (batch, ordinal, payload) VALUES (?, ?, ?)",
|
|
)
|
|
.run(999_999, 0, "stale-profile-row");
|
|
} finally {
|
|
closeOpenClawStateDatabaseForTest();
|
|
}
|
|
|
|
const output = path.join(stateDir, "report.json");
|
|
const compilerPolicyProbe = path.join(stateDir, "compiler-policy-probe.mjs");
|
|
fs.writeFileSync(
|
|
compilerPolicyProbe,
|
|
`import { isMainThread } from "node:worker_threads";
|
|
if (isMainThread && !process.execArgv.includes("--no-concurrent-sparkplug")) {
|
|
throw new Error("SQLite proof subprocess discarded the selected Node compiler policy");
|
|
}
|
|
`,
|
|
);
|
|
const result = runProof(["--profile", "smoke", "--state-dir", stateDir, "--output", output], {
|
|
NODE_OPTIONS: [
|
|
process.env.NODE_OPTIONS,
|
|
`--import=${pathToFileURL(compilerPolicyProbe).href}`,
|
|
]
|
|
.filter(Boolean)
|
|
.join(" "),
|
|
});
|
|
|
|
expect(result.status, result.stderr).toBe(0);
|
|
expect(result.stderr).toBe("");
|
|
expect(result.stdout).toContain("SQLITE_RELIABILITY_TARGET=global");
|
|
expect(result.stdout).toContain("SQLITE_RELIABILITY_RESTORES_VERIFIED=5");
|
|
expect(result.stdout).not.toContain("=missing");
|
|
const firstReport = JSON.parse(fs.readFileSync(output, "utf8")) as ReliabilityReport;
|
|
expect(firstReport).toMatchObject({ concurrentRestoresVerified: 2, restoresVerified: 5 });
|
|
expect(firstReport.writer.rowsCommitted).toBeGreaterThan(0);
|
|
expect(firstReport.transactionProof.heldRows).toBeGreaterThan(0);
|
|
expect(firstReport.maintenanceProof.postCompact.state.sha256).toMatch(/^[a-f0-9]{64}$/);
|
|
expect(firstReport.maintenanceProof.postCompact.state.batches).toBeGreaterThan(0);
|
|
expect(firstReport.maintenanceProof.postCompact.state.rows).toBeGreaterThan(0);
|
|
// The subprocess verifies payloads, crash exits, recovery, and compaction
|
|
// before returning; keep report-specific expectations here, not a replay.
|
|
const { repositoryInterruption: repository } = firstReport.maintenanceProof;
|
|
for (const [proof, published, visible] of [
|
|
[repository.beforePending, false, 1],
|
|
[repository.pending, true, 3],
|
|
[repository.afterCommit, true, 5],
|
|
] as const) {
|
|
expect(proof).toMatchObject({
|
|
crashSnapshotVerifiedAfterCrash: published,
|
|
crashSnapshotVisibleAfterCrash: published,
|
|
visibleSnapshotsAfterCrash: visible,
|
|
});
|
|
}
|
|
expect(firstReport.walBytes.limit).toBeGreaterThan(0);
|
|
expect(firstReport.walBytes.peak).toBeGreaterThan(0);
|
|
expect(firstReport.walBytes.peak).toBeLessThanOrEqual(firstReport.walBytes.limit);
|
|
|
|
expect(firstReport.paths.syncedRepository).not.toBe(previousSyncedRepository);
|
|
expect(fs.readFileSync(previousArtifact, "utf8")).toBe("retained");
|
|
|
|
const database = openNodeSqliteDatabase(firstReport.paths.sourceDatabase, { readOnly: true });
|
|
try {
|
|
const staleRows = database
|
|
.prepare("SELECT COUNT(*) AS rows FROM openclaw_reliability_entries WHERE batch = ?")
|
|
.get(999_999) as { rows?: unknown };
|
|
expect(Number(staleRows.rows)).toBe(0);
|
|
} finally {
|
|
database.close();
|
|
}
|
|
});
|
|
|
|
it("matches crash barriers across filesystem path aliases", () => {
|
|
const realRoot = makeRoot();
|
|
const aliasRoot = path.join(makeRoot(), "alias");
|
|
fs.symlinkSync(realRoot, aliasRoot, process.platform === "win32" ? "junction" : "dir");
|
|
const repositoryPath = path.join(realRoot, "snapshots");
|
|
const snapshotPath = path.join(repositoryPath, "snapshot");
|
|
fs.mkdirSync(snapshotPath, { recursive: true });
|
|
|
|
const canonicalRepositoryPath = canonicalPathWithExistingParent(
|
|
path.join(aliasRoot, "snapshots"),
|
|
);
|
|
expect(canonicalRepositoryPath).toBe(path.join(fs.realpathSync.native(realRoot), "snapshots"));
|
|
expect(
|
|
isPendingPathInRepository(
|
|
path.join(aliasRoot, "snapshots", "snapshot", ".pending"),
|
|
canonicalRepositoryPath,
|
|
),
|
|
).toBe(true);
|
|
|
|
const finalAlias = path.join(realRoot, "final-alias");
|
|
fs.symlinkSync(snapshotPath, finalAlias, process.platform === "win32" ? "junction" : "dir");
|
|
expect(canonicalPathWithExistingParent(finalAlias)).toBe(
|
|
path.join(fs.realpathSync.native(realRoot), "final-alias"),
|
|
);
|
|
});
|
|
|
|
it("stops the writer when its parent IPC channel disconnects", async ({ signal }) => {
|
|
const databasePath = path.join(makeRoot(), "writer.sqlite");
|
|
const writerUrl = resolveRuntimeWorkerUrl(toolingTsEntrypoints.sqliteReliabilityWriter);
|
|
const child = fork(
|
|
fileURLToPath(writerUrl),
|
|
[databasePath, "8", "64", "4", "256", String(64 * 1024 * 1024), "1"],
|
|
{
|
|
cwd: process.cwd(),
|
|
execPath: nodeExecutable,
|
|
execArgv: [...nodeArgs, ...resolveRuntimeWorkerThreadExecArgv(writerUrl, nodeExecutable)],
|
|
serialization: "json",
|
|
stdio: ["ignore", "ignore", "pipe", "ipc"],
|
|
},
|
|
);
|
|
const exitPromise = waitForChildExit(child);
|
|
// Readiness and exit are both owned by this child; the test signal owns the deadline.
|
|
void exitPromise.catch(() => {});
|
|
try {
|
|
await withinTest(waitForChildReady(child), signal);
|
|
child.disconnect();
|
|
await expect(withinTest(exitPromise, signal)).resolves.toEqual({ code: 0, signal: null });
|
|
} finally {
|
|
if (child.exitCode === null && child.signalCode === null) {
|
|
child.kill("SIGKILL");
|
|
}
|
|
await exitPromise;
|
|
}
|
|
});
|
|
});
|