diff --git a/docs/superpowers/plans/2026-06-04-pluginos-bridge-ui-polish.md b/docs/superpowers/plans/2026-06-04-pluginos-bridge-ui-polish.md
new file mode 100644
index 0000000..eb6aead
--- /dev/null
+++ b/docs/superpowers/plans/2026-06-04-pluginos-bridge-ui-polish.md
@@ -0,0 +1,1084 @@
+# PluginOS Bridge UI Polish (PR-A2) Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Fix three bridge-plugin UI bugs: dark mode never activates, stale state after reconnect cycle, recent operations not visible during sessions.
+
+**Architecture:** CSS variables resolve through a three-tier chain (Figma vars → `data-theme` fallback → hardcoded literal). DOM mutations funnel through a single idempotent `renderUI(AppState)` function. Activity log keeps its existing class but renders on every state transition.
+
+**Tech Stack:** TypeScript, Vitest with happy-dom for DOM testing, CSS custom properties, no new runtime dependencies.
+
+**Spec:** [docs/superpowers/specs/2026-06-04-pluginos-bridge-ui-polish-design.md](../specs/2026-06-04-pluginos-bridge-ui-polish-design.md)
+
+---
+
+## File Map
+
+**Create:**
+- `packages/bridge-plugin/src/ui/render-ui.ts` — `AppState` type, `renderUI()`, pure helpers
+- `packages/bridge-plugin/src/__tests__/render-ui.test.ts`
+- `packages/bridge-plugin/src/__tests__/activity-log-integration.test.ts`
+- `packages/bridge-plugin/src/__tests__/theme-fallback.test.ts`
+
+**Modify:**
+- `packages/bridge-plugin/src/ui/tokens.cjs` — Figma var fallback chain
+- `packages/bridge-plugin/src/ui-entry.ts` — `setState()` orchestrator, adapters, timer ownership
+- `packages/bridge-plugin/src/ui/activity-log.ts` — `MAX_VISIBLE` 5→10, empty-state copy
+
+**Unchanged (preserved):**
+- `packages/bridge-plugin/src/ui/theme.ts`
+- `packages/bridge-plugin/src/ui.html`
+- `packages/bridge-plugin/src/code.ts`
+
+---
+
+## Conventions
+
+- Commits via `Skill(commit-commands:commit)` — never write commit messages manually
+- After every passing test, read the FULL test output before claiming pass
+- Bridge-plugin tests run under happy-dom (configured in `packages/bridge-plugin/vitest.config.ts` — already in place)
+- All work lands on branch `feat/pr-a2-bridge-ui-polish` (created in Task 0)
+- Push only after the full PR is ready
+
+---
+
+## Task 0: Set up the feature branch
+
+**Files:** None — git only
+
+- [ ] **Step 1: Confirm clean starting state**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && git status && git branch --show-current`
+Expected: clean tree on `main`.
+
+- [ ] **Step 2: Create and switch to feature branch**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && git checkout -b feat/pr-a2-bridge-ui-polish`
+Expected: `Switched to a new branch 'feat/pr-a2-bridge-ui-polish'`.
+
+- [ ] **Step 3: Cherry-pick the vitest CI fix commits from PR-B's branch so CI passes independently**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && git cherry-pick cb43a4a dec47d8 f5b8cfc`
+Expected: 3 commits applied cleanly.
+
+If any conflict: stop and report. PR-A2's bridge-plugin work shouldn't conflict with these dep-only commits.
+
+- [ ] **Step 4: Install deps**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm install`
+Expected: 0 vulnerabilities.
+
+- [ ] **Step 5: Smoke-test the existing suite passes pre-changes**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin`
+Expected: all existing bridge-plugin tests pass (baseline 78 tests in the pre-change codebase).
+
+---
+
+## Task 1: Theme fallback CSS rewrite (U1)
+
+**Files:**
+- Modify: `packages/bridge-plugin/src/ui/tokens.cjs`
+- Create: `packages/bridge-plugin/src/__tests__/theme-fallback.test.ts`
+
+This task converts the hardcoded color tokens to use Figma's injected CSS vars with hardcoded fallbacks. The `[data-theme="dark"]` block still exists but provides values consumed by the fallback chain.
+
+- [ ] **Step 1: Write the failing test**
+
+```typescript
+// packages/bridge-plugin/src/__tests__/theme-fallback.test.ts
+import { describe, it, expect, beforeEach } from "vitest";
+
+const TOKENS_CSS: string = require("../ui/tokens.cjs");
+
+function injectStylesheet(css: string): void {
+ const style = document.createElement("style");
+ style.textContent = css;
+ document.head.appendChild(style);
+}
+
+function clearHead(): void {
+ document.head.innerHTML = "";
+ document.documentElement.removeAttribute("data-theme");
+}
+
+describe("theme fallback chain", () => {
+ beforeEach(() => {
+ clearHead();
+ });
+
+ it("--po-bg references --figma-color-bg with a hardcoded fallback", () => {
+ injectStylesheet(TOKENS_CSS);
+ const value = getComputedStyle(document.documentElement)
+ .getPropertyValue("--po-bg")
+ .trim();
+ // happy-dom doesn't fully resolve var() chains in some scenarios.
+ // Just verify the variable definition references --figma-color-bg.
+ expect(TOKENS_CSS).toContain("--po-bg: var(--figma-color-bg");
+ });
+
+ it("every primary token uses var(--figma-color-*) with a fallback", () => {
+ const expected = [
+ "--po-bg: var(--figma-color-bg",
+ "--po-text: var(--figma-color-text",
+ "--po-border: var(--figma-color-border",
+ ];
+ for (const fragment of expected) {
+ expect(TOKENS_CSS).toContain(fragment);
+ }
+ });
+
+ it("[data-theme=\"dark\"] block still exists with non-empty values", () => {
+ expect(TOKENS_CSS).toContain('[data-theme="dark"]');
+ expect(TOKENS_CSS).toContain("#1e1e1e");
+ });
+
+ it("hardcoded fallbacks are still readable when Figma vars are absent", () => {
+ injectStylesheet(TOKENS_CSS);
+ document.documentElement.setAttribute("data-theme", "dark");
+ const bg = getComputedStyle(document.documentElement)
+ .getPropertyValue("--po-bg")
+ .trim();
+ // In happy-dom, the value should resolve to either the Figma var (empty
+ // when not injected) or the literal fallback. Just verify it's defined.
+ expect(bg.length).toBeGreaterThan(0);
+ });
+});
+```
+
+- [ ] **Step 2: Run the test to verify it fails**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin -- theme-fallback`
+Expected: FAIL on the "uses var(--figma-color-*)" assertions because the current tokens.cjs has hardcoded `#ffffff` etc.
+
+- [ ] **Step 3: Rewrite tokens.cjs**
+
+Replace the contents of `packages/bridge-plugin/src/ui/tokens.cjs` with:
+
+```javascript
+/**
+ * Shared design tokens for bootloader.html and ui.html.
+ * Injected into both at webpack build time via HtmlWebpackPlugin.templateParameters.
+ * Single source of truth for v4 palette, typography, and spacing.
+ *
+ * Theme resolution (three-tier fallback chain):
+ * 1. Figma's injected --figma-color-* vars (when running inside Figma with themeColors: true)
+ * 2. Hardcoded literals (the fallback after the comma in each var() call)
+ * 3. data-theme="dark" overrides the fallback literals for non-Figma contexts
+ * (happy-dom tests, future force-toggle UI, etc.)
+ *
+ * Inside Figma: tier 1 wins, auto-tracks editor theme. theme.ts is dormant.
+ * Outside Figma: tier 1 is undefined, fallback literals apply. data-theme can override.
+ */
+module.exports = `
+:root {
+ --po-bg: var(--figma-color-bg, #ffffff);
+ --po-surface: var(--figma-color-bg-secondary, #ffffff);
+ --po-step-bg: var(--figma-color-bg-tertiary, #fafafa);
+ --po-border: var(--figma-color-border, #ececec);
+ --po-text: var(--figma-color-text, #1a1a1a);
+ --po-text-sub: var(--figma-color-text-secondary, #6b7280);
+ --po-text-muted: var(--figma-color-text-tertiary, #9ca3af);
+ --po-code-bg: var(--figma-color-bg, #ffffff);
+ --po-btn-primary-bg: var(--figma-color-bg-brand, #18181b);
+ --po-btn-primary-fg: var(--figma-color-text-onbrand, #ffffff);
+ --po-btn-secondary-bg: var(--figma-color-bg-secondary, #f4f4f5);
+ --po-btn-secondary-fg: var(--figma-color-text, #18181b);
+ --po-accent: var(--figma-color-bg-brand, #6366f1);
+ --po-accent-soft: #f5f7fc;
+ --po-success: var(--figma-color-bg-success, #10b981);
+ --po-success-soft: var(--figma-color-bg-success-secondary, #ecfdf5);
+ --po-success-text: var(--figma-color-text-success, #047857);
+ --po-warn-soft: var(--figma-color-bg-warning-secondary, #fef3c7);
+ --po-warn-text: var(--figma-color-text-warning, #92400e);
+ --po-error: var(--figma-color-bg-danger, #ef4444);
+ --po-error-soft: var(--figma-color-bg-danger-secondary, #fef2f2);
+ --po-error-text: var(--figma-color-text-danger, #b91c1c);
+ --po-running-soft: #eff6ff;
+ --po-running-text: var(--figma-color-text-component, #1d4ed8);
+ --po-radius: 8px;
+ --po-radius-lg: 12px;
+ --po-shadow: 0 1px 3px rgba(0,0,0,.06), 0 8px 24px rgba(0,0,0,.08);
+ --po-focus: var(--figma-color-border-brand, #0d99ff);
+ --po-font: 'Inter', -apple-system, system-ui, -apple-system, "Helvetica Neue", sans-serif;
+ --po-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
+}
+
+[data-theme="dark"] {
+ --po-bg: var(--figma-color-bg, #1e1e1e);
+ --po-surface: var(--figma-color-bg-secondary, #2c2c2c);
+ --po-step-bg: var(--figma-color-bg-tertiary, #222222);
+ --po-border: var(--figma-color-border, #383838);
+ --po-text: var(--figma-color-text, #f5f5f5);
+ --po-text-sub: var(--figma-color-text-secondary, rgba(255,255,255,.55));
+ --po-text-muted: var(--figma-color-text-tertiary, rgba(255,255,255,.4));
+ --po-code-bg: var(--figma-color-bg, #1e1e1e);
+ --po-btn-primary-bg: var(--figma-color-bg-brand, #ffffff);
+ --po-btn-primary-fg: var(--figma-color-text-onbrand, #18181b);
+}
+`;
+```
+
+If your version of `tokens.cjs` has additional tokens not shown above (the original file may have more lines), preserve those — only convert the color-related ones to the `var(--figma-color-*, fallback)` pattern. Don't touch radii, fonts, shadows.
+
+- [ ] **Step 4: Run the test to verify it passes**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin -- theme-fallback`
+Expected: 4 passed.
+
+- [ ] **Step 5: Run all bridge-plugin tests to confirm no regression**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin`
+Expected: all green.
+
+- [ ] **Step 6: Commit**
+
+Use `Skill(commit-commands:commit)`. Suggested message: `feat(bridge-plugin): use Figma CSS vars with fallback chain in tokens.cjs`.
+
+---
+
+## Task 2: Render-ui module skeleton with `AppState` type
+
+**Files:**
+- Create: `packages/bridge-plugin/src/ui/render-ui.ts`
+
+This task lands the type union and pure helpers. The `renderUI` function comes in Task 3.
+
+- [ ] **Step 1: Write the type module**
+
+```typescript
+// packages/bridge-plugin/src/ui/render-ui.ts
+
+export type RunningOp = {
+ name: string;
+ paramsPreview: string;
+ startedAt: number;
+};
+
+export type AppState =
+ | { kind: "disconnected" }
+ | { kind: "connecting"; lastKnownPort: number | null }
+ | {
+ kind: "connected";
+ file: { name: string; key: string };
+ port: number;
+ running: RunningOp | null;
+ }
+ | { kind: "mismatch"; reason: string; serverVersion: string; pluginVersion: string };
+
+export function pillStateFor(state: AppState): string {
+ if (state.kind === "connected" && state.running) return "running";
+ return state.kind;
+}
+
+export function pillTextFor(state: AppState): string {
+ switch (state.kind) {
+ case "disconnected":
+ return "Not connected";
+ case "connecting":
+ return "Connecting…";
+ case "connected":
+ return state.running ? `Running ${state.running.name}` : "Connected";
+ case "mismatch":
+ return "Update needed";
+ }
+}
+
+export function formatElapsed(ms: number): string {
+ const s = ms / 1000;
+ if (s < 60) return `${s.toFixed(1)}s elapsed`;
+ const minutes = Math.floor(s / 60);
+ const seconds = Math.floor(s % 60);
+ return `${minutes}m ${seconds}s elapsed`;
+}
+```
+
+- [ ] **Step 2: Typecheck**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm run typecheck`
+Expected: no errors.
+
+- [ ] **Step 3: Commit**
+
+Use `Skill(commit-commands:commit)`. Suggested message: `feat(bridge-plugin): add AppState type union and pure helpers`.
+
+---
+
+## Task 3: Pure helpers tests (TDD before adding `renderUI`)
+
+**Files:**
+- Create: `packages/bridge-plugin/src/__tests__/render-ui.test.ts`
+
+This task adds unit tests for the pure helpers (`pillStateFor`, `pillTextFor`, `formatElapsed`). The `renderUI` function tests come in Task 4 once we add the function.
+
+- [ ] **Step 1: Write tests for the pure helpers**
+
+```typescript
+// packages/bridge-plugin/src/__tests__/render-ui.test.ts
+import { describe, it, expect } from "vitest";
+import {
+ pillStateFor,
+ pillTextFor,
+ formatElapsed,
+ type AppState,
+} from "../ui/render-ui.js";
+
+describe("pillStateFor", () => {
+ it("returns kind for non-connected variants", () => {
+ expect(pillStateFor({ kind: "disconnected" })).toBe("disconnected");
+ expect(pillStateFor({ kind: "connecting", lastKnownPort: 9500 })).toBe("connecting");
+ expect(
+ pillStateFor({
+ kind: "mismatch",
+ reason: "x",
+ serverVersion: "0.4.3",
+ pluginVersion: "0.4.2",
+ })
+ ).toBe("mismatch");
+ });
+
+ it("returns 'running' when connected with a running op", () => {
+ expect(
+ pillStateFor({
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: { name: "execute_figma", paramsPreview: "", startedAt: 0 },
+ })
+ ).toBe("running");
+ });
+
+ it("returns 'connected' when connected and idle", () => {
+ expect(
+ pillStateFor({
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: null,
+ })
+ ).toBe("connected");
+ });
+});
+
+describe("pillTextFor", () => {
+ it("returns user-facing strings per state", () => {
+ expect(pillTextFor({ kind: "disconnected" })).toBe("Not connected");
+ expect(pillTextFor({ kind: "connecting", lastKnownPort: null })).toBe("Connecting…");
+ expect(
+ pillTextFor({
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: null,
+ })
+ ).toBe("Connected");
+ });
+
+ it("includes the op name when running", () => {
+ expect(
+ pillTextFor({
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: { name: "lint_styles", paramsPreview: "", startedAt: 0 },
+ })
+ ).toBe("Running lint_styles");
+ });
+
+ it("returns 'Update needed' for mismatch", () => {
+ expect(
+ pillTextFor({
+ kind: "mismatch",
+ reason: "x",
+ serverVersion: "0.4.3",
+ pluginVersion: "0.4.2",
+ })
+ ).toBe("Update needed");
+ });
+});
+
+describe("formatElapsed", () => {
+ it("shows seconds with one decimal under a minute", () => {
+ expect(formatElapsed(500)).toBe("0.5s elapsed");
+ expect(formatElapsed(12_345)).toBe("12.3s elapsed");
+ });
+
+ it("shows minutes + seconds at or above one minute", () => {
+ expect(formatElapsed(60_000)).toBe("1m 0s elapsed");
+ expect(formatElapsed(125_000)).toBe("2m 5s elapsed");
+ });
+
+ it("handles zero correctly", () => {
+ expect(formatElapsed(0)).toBe("0.0s elapsed");
+ });
+});
+```
+
+- [ ] **Step 2: Run the test**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin -- render-ui`
+Expected: 9 passed (3 + 3 + 3 cases).
+
+- [ ] **Step 3: Commit**
+
+Use `Skill(commit-commands:commit)`. Suggested message: `test(bridge-plugin): cover pillStateFor, pillTextFor, formatElapsed helpers`.
+
+---
+
+## Task 4: Implement and test `renderUI` (TDD)
+
+**Files:**
+- Modify: `packages/bridge-plugin/src/ui/render-ui.ts` (append `renderUI`)
+- Modify: `packages/bridge-plugin/src/__tests__/render-ui.test.ts` (append DOM tests)
+
+- [ ] **Step 1: Append the failing tests**
+
+Append to `packages/bridge-plugin/src/__tests__/render-ui.test.ts`:
+
+```typescript
+import { renderUI } from "../ui/render-ui.js";
+
+function setupDom(): void {
+ document.body.innerHTML = `
+
—
+
+
+ —
+ —
+
+ —
+ —
+ —
+
+
+
+
+ `;
+}
+
+describe("renderUI", () => {
+ beforeEach(() => setupDom());
+
+ it("shows disconnected view + pill on disconnected state", () => {
+ renderUI({ kind: "disconnected" });
+ expect(document.getElementById("view-disconnected")!.hidden).toBe(false);
+ expect(document.getElementById("view-connected")!.hidden).toBe(true);
+ expect(document.getElementById("view-mismatch")!.hidden).toBe(true);
+ expect(document.getElementById("status-pill")!.dataset.state).toBe("disconnected");
+ expect(document.getElementById("status-text")!.textContent).toBe("Not connected");
+ });
+
+ it("shows disconnected view + 'Connecting…' pill on connecting state", () => {
+ renderUI({ kind: "connecting", lastKnownPort: 9500 });
+ expect(document.getElementById("view-disconnected")!.hidden).toBe(false);
+ expect(document.getElementById("status-pill")!.dataset.state).toBe("connecting");
+ expect(document.getElementById("status-text")!.textContent).toBe("Connecting…");
+ });
+
+ it("shows connected view with idle-block when running is null", () => {
+ renderUI({
+ kind: "connected",
+ file: { name: "MyFile", key: "abc" },
+ port: 9500,
+ running: null,
+ });
+ expect(document.getElementById("view-connected")!.hidden).toBe(false);
+ expect(document.getElementById("idle-block")!.hidden).toBe(false);
+ expect(document.getElementById("running-block")!.hidden).toBe(true);
+ expect(document.getElementById("file-name")!.textContent).toBe("MyFile");
+ expect(document.getElementById("port-url")!.textContent).toBe("localhost:9500");
+ });
+
+ it("shows connected view with running-block when running is set", () => {
+ const startedAt = Date.now() - 2500;
+ renderUI({
+ kind: "connected",
+ file: { name: "MyFile", key: "abc" },
+ port: 9500,
+ running: { name: "execute_figma", paramsPreview: "{ code: ... }", startedAt },
+ });
+ expect(document.getElementById("running-block")!.hidden).toBe(false);
+ expect(document.getElementById("idle-block")!.hidden).toBe(true);
+ expect(document.getElementById("run-op")!.textContent).toBe("execute_figma");
+ expect(document.getElementById("run-params")!.textContent).toBe("{ code: ... }");
+ expect(document.getElementById("run-elapsed")!.textContent).toMatch(/elapsed/);
+ expect(document.getElementById("status-text")!.textContent).toBe("Running execute_figma");
+ });
+
+ it("shows mismatch view with formatted text", () => {
+ renderUI({
+ kind: "mismatch",
+ reason: "Reinstall the plugin.",
+ serverVersion: "0.4.4",
+ pluginVersion: "0.4.2",
+ });
+ expect(document.getElementById("view-mismatch")!.hidden).toBe(false);
+ expect(document.getElementById("mismatch-text")!.textContent).toContain("0.4.4");
+ expect(document.getElementById("mismatch-text")!.textContent).toContain("0.4.2");
+ expect(document.getElementById("mismatch-text")!.textContent).toContain("Reinstall the plugin.");
+ });
+
+ it("hides running-block defensively when not connected", () => {
+ renderUI({
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: { name: "op", paramsPreview: "", startedAt: Date.now() },
+ });
+ expect(document.getElementById("running-block")!.hidden).toBe(false);
+
+ renderUI({ kind: "disconnected" });
+ expect(document.getElementById("running-block")!.hidden).toBe(true);
+ });
+
+ it("regression: disconnect→reconnect cycle does not leak running-block visibility", () => {
+ // Connected + running
+ renderUI({
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: { name: "op", paramsPreview: "", startedAt: Date.now() },
+ });
+ // User force-closes plugin → bridge disconnects
+ renderUI({ kind: "disconnected" });
+ // Reconnect arrives — no op is running now
+ renderUI({
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: null,
+ });
+ expect(document.getElementById("running-block")!.hidden).toBe(true);
+ expect(document.getElementById("idle-block")!.hidden).toBe(false);
+ });
+
+ it("is idempotent — calling with same state twice yields the same DOM", () => {
+ const state: AppState = {
+ kind: "connected",
+ file: { name: "F", key: "k" },
+ port: 9500,
+ running: null,
+ };
+ renderUI(state);
+ const firstHtml = document.body.innerHTML;
+ renderUI(state);
+ expect(document.body.innerHTML).toBe(firstHtml);
+ });
+});
+```
+
+- [ ] **Step 2: Run the failing tests**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin -- render-ui`
+Expected: FAIL — `renderUI` not exported.
+
+- [ ] **Step 3: Add `renderUI` to `render-ui.ts`**
+
+Append to `packages/bridge-plugin/src/ui/render-ui.ts`:
+
+```typescript
+function el(id: string): HTMLElement {
+ const node = document.getElementById(id);
+ if (!node) throw new Error(`renderUI: missing element #${id}`);
+ return node;
+}
+
+export function renderUI(state: AppState): void {
+ // 1. Status pill
+ const pill = el("status-pill");
+ pill.dataset.state = pillStateFor(state);
+ el("status-text").textContent = pillTextFor(state);
+
+ // 2. Top-level views
+ el("view-disconnected").hidden =
+ state.kind !== "disconnected" && state.kind !== "connecting";
+ el("view-connected").hidden = state.kind !== "connected";
+ el("view-mismatch").hidden = state.kind !== "mismatch";
+
+ // 3. Connected sub-blocks
+ if (state.kind === "connected") {
+ el("file-name").textContent = state.file.name;
+ el("port-url").textContent = `localhost:${state.port}`;
+ el("running-block").hidden = state.running === null;
+ el("idle-block").hidden = state.running !== null;
+ if (state.running) {
+ el("run-op").textContent = state.running.name;
+ el("run-params").textContent = state.running.paramsPreview;
+ el("run-elapsed").textContent = formatElapsed(Date.now() - state.running.startedAt);
+ }
+ } else {
+ // Defensive: explicitly hide running-block when not connected
+ el("running-block").hidden = true;
+ }
+
+ // 4. Mismatch view text
+ if (state.kind === "mismatch") {
+ el("mismatch-text").textContent =
+ `Server ${state.serverVersion} doesn't match plugin ${state.pluginVersion}. ${state.reason}`;
+ }
+}
+```
+
+- [ ] **Step 4: Run tests**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin -- render-ui`
+Expected: 17 passed (9 helper + 8 renderUI cases).
+
+- [ ] **Step 5: Commit**
+
+Use `Skill(commit-commands:commit)`. Suggested message: `feat(bridge-plugin): add idempotent renderUI(AppState) function`.
+
+---
+
+## Task 5: Wire `setState` + adapters into `ui-entry.ts`
+
+**Files:**
+- Modify: `packages/bridge-plugin/src/ui-entry.ts`
+
+This is the integration task. We funnel all existing DOM mutations through a new `setState` orchestrator. The existing `setStatus` and `showView` functions become thin adapters.
+
+- [ ] **Step 1: Read the current ui-entry.ts to understand exact shapes**
+
+Read `packages/bridge-plugin/src/ui-entry.ts` end-to-end. Note:
+- Where `setStatus` is defined (around line 36-47)
+- Where `showView` is defined (around line 49-53)
+- Every direct DOM mutation that touches `#file-name`, `#port-url`, `#running-block`, `#idle-block`, `#run-op`, `#run-params`, `#run-elapsed`, `#mismatch-text`
+- Where the `setInterval` for the elapsed timer lives
+- Where `activityLog` is initialized and pushed/rendered
+
+- [ ] **Step 2: Add imports + state at the top of ui-entry.ts**
+
+Add to the imports near the top (alongside the existing theme imports):
+
+```typescript
+import { renderUI, type AppState, type RunningOp } from "./ui/render-ui";
+```
+
+Add module-level state (somewhere near the existing `let activityLog: ActivityLog;` declaration):
+
+```typescript
+let currentState: AppState = { kind: "disconnected" };
+let elapsedTimer: number | null = null;
+```
+
+- [ ] **Step 3: Add the `setState` orchestrator**
+
+Add this function near the top of the file (alongside the existing `setStatus`, before its definition):
+
+```typescript
+function setState(next: AppState): void {
+ currentState = next;
+ renderUI(next);
+ if (activityLog) {
+ activityLog.render();
+ }
+
+ if (next.kind === "connected" && next.running) {
+ if (elapsedTimer === null) {
+ elapsedTimer = window.setInterval(() => {
+ if (currentState.kind === "connected" && currentState.running) {
+ const elapsed = document.getElementById("run-elapsed");
+ if (elapsed) {
+ // formatElapsed is in render-ui — re-import isn't needed because
+ // we can compute the formatted text via a tiny helper that ALSO
+ // lives in render-ui.ts. Use it directly.
+ const ms = Date.now() - currentState.running.startedAt;
+ elapsed.textContent = formatElapsed(ms);
+ }
+ }
+ }, 100);
+ }
+ } else if (elapsedTimer !== null) {
+ clearInterval(elapsedTimer);
+ elapsedTimer = null;
+ }
+}
+```
+
+Add `formatElapsed` to the import:
+
+```typescript
+import { renderUI, formatElapsed, type AppState, type RunningOp } from "./ui/render-ui";
+```
+
+- [ ] **Step 4: Rewrite `setStatus` as an adapter**
+
+Replace the existing `setStatus(state: StatusState, text?: string)` function body with:
+
+```typescript
+function setStatus(state: StatusState, _text?: string): void {
+ // Adapter: maps the old 5-state model onto the new AppState union
+ const next = computeNextStateFromStatus(currentState, state);
+ setState(next);
+}
+
+function computeNextStateFromStatus(prev: AppState, status: StatusState): AppState {
+ switch (status) {
+ case "disconnected":
+ return { kind: "disconnected" };
+ case "connecting":
+ return {
+ kind: "connecting",
+ lastKnownPort: prev.kind === "connected" ? prev.port : null,
+ };
+ case "connected":
+ if (prev.kind === "connected") {
+ return { ...prev, running: null };
+ }
+ return {
+ kind: "connected",
+ file: { name: "—", key: "—" },
+ port: 0,
+ running: null,
+ };
+ case "running":
+ if (prev.kind === "connected") {
+ return prev; // running is set by a different code path that has the op info
+ }
+ return prev;
+ case "mismatch":
+ return {
+ kind: "mismatch",
+ reason: "",
+ serverVersion: "—",
+ pluginVersion: "—",
+ };
+ }
+}
+```
+
+- [ ] **Step 5: Rewrite `showView` as a no-op (renderUI handles view switching)**
+
+Replace the existing `showView(view)` function body with:
+
+```typescript
+function showView(_view: "disconnected" | "connected" | "mismatch"): void {
+ // Adapter: view switching is now driven by setState/renderUI.
+ // Keeping this function exported as a no-op so existing call sites compile.
+ // Future PR can inline all call sites and delete this entirely.
+}
+```
+
+- [ ] **Step 6: Update the WebSocket "connected" handler to call setState directly**
+
+Find the code path that today does something like `setStatus("connected"); showView("connected"); $("file-name").textContent = ...; $("port-url").textContent = ...;` (around the `ws.onopen` or "SERVER_HELLO" handler, look near lines 240-260 of the original ui-entry.ts).
+
+Replace those individual mutations with a single `setState` call:
+
+```typescript
+setState({
+ kind: "connected",
+ file: { name: currentFileName ?? "—", key: currentFileKey ?? "—" },
+ port: actualPort,
+ running: null,
+});
+```
+
+The variables `currentFileName`, `currentFileKey`, `actualPort` should already be in scope wherever the old code grabbed them. Adapt the names to match what's actually used.
+
+- [ ] **Step 7: Update the "running" code path**
+
+Find where the UI today marks an op as starting (sets running-block visible, fills in op name + params). This is likely in a `WS_RUN_OP_START` or similar message handler.
+
+Replace those mutations with:
+
+```typescript
+if (currentState.kind === "connected") {
+ setState({
+ ...currentState,
+ running: {
+ name: opName,
+ paramsPreview: paramsPreview,
+ startedAt: Date.now(),
+ },
+ });
+}
+```
+
+And on op completion (hide running-block, push activity log entry):
+
+```typescript
+if (currentState.kind === "connected") {
+ setState({ ...currentState, running: null });
+}
+activityLog.push({ ...entry });
+```
+
+- [ ] **Step 8: Update the disconnect / reconnect code paths**
+
+Existing `ws.onclose` handlers call `setStatus("disconnected")` and `setStatus("connecting", "Reconnecting…")`. These already funnel into `setState` via the adapter, so no change needed beyond Step 4. Confirm by tracing each `setStatus(...)` call site.
+
+- [ ] **Step 9: Update the mismatch code path**
+
+Find where the version-mismatch UI is set (likely receives a `SERVER_HELLO` with incompatible version). Replace any direct DOM mutations + `setStatus("mismatch")` with:
+
+```typescript
+setState({
+ kind: "mismatch",
+ reason: "Reinstall both halves of PluginOS to the same version.",
+ serverVersion: serverVersionFromHello,
+ pluginVersion: PLUGIN_VERSION,
+});
+```
+
+Where `PLUGIN_VERSION` is the constant already used somewhere in the file (search for it; usually injected at build time).
+
+- [ ] **Step 10: Remove the old elapsed-timer code**
+
+The original `ui-entry.ts` likely has a `setInterval` for the running-elapsed updates. Since `setState` now manages this timer (Step 3), the old timer should be removed. Search for the elapsed-related `setInterval` and `clearInterval` calls and delete them.
+
+- [ ] **Step 11: Typecheck**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm run typecheck`
+Expected: no errors.
+
+If typecheck flags unused parameters (`_view`, `_text`), they're already prefixed with `_` per the eslint rule and should be fine.
+
+- [ ] **Step 12: Run all bridge-plugin tests**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin`
+Expected: all existing tests pass + 17 new render-ui tests + 4 theme-fallback tests.
+
+If any existing test fails because it asserted on `setStatus` side effects (e.g., a hardcoded DOM mutation that now goes through `renderUI`), update the test to assert on the post-`setState` DOM instead. Do NOT change the new code to preserve old assertions — the new flow is the contract.
+
+- [ ] **Step 13: Commit**
+
+Use `Skill(commit-commands:commit)`. Suggested message: `feat(bridge-plugin): funnel all DOM mutations through setState orchestrator`.
+
+---
+
+## Task 6: Activity log polish
+
+**Files:**
+- Modify: `packages/bridge-plugin/src/ui/activity-log.ts`
+- Create: `packages/bridge-plugin/src/__tests__/activity-log-integration.test.ts`
+
+- [ ] **Step 1: Write the failing integration test**
+
+```typescript
+// packages/bridge-plugin/src/__tests__/activity-log-integration.test.ts
+import { describe, it, expect, beforeEach } from "vitest";
+import { ActivityLog } from "../ui/activity-log.js";
+
+function setupHost(): HTMLElement {
+ document.body.innerHTML = ``;
+ return document.getElementById("activity-log")!;
+}
+
+describe("ActivityLog integration", () => {
+ beforeEach(() => {
+ document.body.innerHTML = "";
+ });
+
+ it("renders the new empty-state copy when no entries", () => {
+ const host = setupHost();
+ const log = new ActivityLog(host);
+ log.render();
+ expect(host.textContent).toContain("No operations yet");
+ });
+
+ it("renders up to 10 entries (MAX_VISIBLE)", () => {
+ const host = setupHost();
+ const log = new ActivityLog(host);
+ for (let i = 0; i < 12; i++) {
+ log.push({
+ op: `op_${i}`,
+ status: "ok",
+ durationMs: 100,
+ params: {},
+ at: Date.now() - i * 1000,
+ });
+ }
+ log.render();
+ const rows = host.querySelectorAll(".activity-row");
+ expect(rows.length).toBe(10);
+ });
+
+ it("renders 5 entries when only 5 exist", () => {
+ const host = setupHost();
+ const log = new ActivityLog(host);
+ for (let i = 0; i < 5; i++) {
+ log.push({
+ op: `op_${i}`,
+ status: "ok",
+ durationMs: 100,
+ params: {},
+ at: Date.now() - i * 1000,
+ });
+ }
+ log.render();
+ const rows = host.querySelectorAll(".activity-row");
+ expect(rows.length).toBe(5);
+ });
+
+ it("error entries get the .err class", () => {
+ const host = setupHost();
+ const log = new ActivityLog(host);
+ log.push({
+ op: "bad_op",
+ status: "error",
+ durationMs: 50,
+ params: {},
+ error: "boom",
+ at: Date.now(),
+ });
+ log.render();
+ expect(host.querySelector(".activity-op.err")).not.toBeNull();
+ });
+});
+```
+
+- [ ] **Step 2: Run the test to verify it fails**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin -- activity-log-integration`
+Expected: FAIL on the empty-state copy + MAX_VISIBLE=10 cases.
+
+- [ ] **Step 3: Read the current activity-log.ts to find the exact lines to change**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && grep -n "MAX_VISIBLE\|activity-empty\|No recent activity" packages/bridge-plugin/src/ui/activity-log.ts`
+
+- [ ] **Step 4: Update the constants and empty-state copy**
+
+In `packages/bridge-plugin/src/ui/activity-log.ts`:
+
+1. Change `const MAX_VISIBLE = 5;` to `const MAX_VISIBLE = 10;`
+2. Change the empty-state HTML from `"No recent activity"` to `"No operations yet — your agent will populate this as it runs."`
+
+Concrete edit (the existing code is shown in the spec; find the line that reads):
+
+```typescript
+this.host.innerHTML = `No recent activity
`;
+```
+
+Replace with:
+
+```typescript
+this.host.innerHTML = `No operations yet — your agent will populate this as it runs.
`;
+```
+
+- [ ] **Step 5: Run the tests**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin -- activity-log`
+Expected: existing `activity-log.test.ts` tests + new integration tests both pass.
+
+If the existing `activity-log.test.ts` asserts the old "No recent activity" copy, update those assertions to match the new copy.
+
+- [ ] **Step 6: Run all bridge-plugin tests**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin`
+Expected: all green.
+
+- [ ] **Step 7: Commit**
+
+Use `Skill(commit-commands:commit)`. Suggested message: `feat(bridge-plugin): bump activity log MAX_VISIBLE to 10 and refresh empty-state copy`.
+
+---
+
+## Task 7: Full check + smoke test prep
+
+**Files:** None (verification only)
+
+- [ ] **Step 1: Run the full pipeline**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm run check`
+Expected: lint, format, typecheck, build, test all pass.
+
+- [ ] **Step 2: Confirm new test files are picked up**
+
+Verify these are in the test output:
+- `packages/bridge-plugin/src/__tests__/theme-fallback.test.ts`
+- `packages/bridge-plugin/src/__tests__/render-ui.test.ts`
+- `packages/bridge-plugin/src/__tests__/activity-log-integration.test.ts`
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && npm test -w packages/bridge-plugin 2>&1 | grep -E "Test Files|Tests"`
+Expected: total test count increased by ~25-30 vs baseline.
+
+- [ ] **Step 3: Confirm clean working tree**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && git status`
+Expected: clean.
+
+- [ ] **Step 4: Document the manual smoke test for the PR description**
+
+The smoke test (run against a real Figma file) goes into the PR body:
+
+```markdown
+## Manual smoke test
+
+Before merging, against a real Figma file:
+
+1. **Dark mode follows Figma:**
+ - Open the plugin in Figma with light mode. Plugin UI is light.
+ - Toggle Figma to dark mode. Plugin UI switches to dark instantly.
+ - Toggle back to light. Plugin UI returns to light.
+
+2. **Running state visible:**
+ - From Claude, call `execute_figma { code: "await new Promise(r => setTimeout(r, 5000)); return 1;" }`.
+ - During the 5s, the connected view shows the running-block with op name "execute_figma" and elapsed time ticking.
+ - On completion: running-block hides, activity log shows the entry.
+
+3. **Stale state regression (the bug):**
+ - From Claude, call `execute_figma { code: "await new Promise(r => setTimeout(r, 10000));" }`.
+ - During the 10s, force-close the plugin pane in Figma.
+ - Reopen the plugin pane. The plugin reconnects via PR-A1's discovery.
+ - Verify: running-block is HIDDEN (because the op was severed). Activity log shows the prior op (with whatever final status it landed on).
+
+4. **Activity log shows recent operations:**
+ - Run 3-4 ops in succession.
+ - Activity log shows them at the top, newest first.
+ - Run 12 more ops. Activity log caps at 10 visible entries.
+ - Refresh the plugin pane: activity log resets to empty (entries are in-memory).
+```
+
+Don't commit this — it goes into the PR description.
+
+---
+
+## Task 8: Push branch + open PR
+
+**Files:** None — git/gh only
+
+- [ ] **Step 1: Push the branch**
+
+Run: `cd "/Users/dimi/Documents/TheVault/00 Joint Projects/PluginOS" && git push -u origin feat/pr-a2-bridge-ui-polish`
+Expected: pre-push hooks pass, branch pushed.
+
+- [ ] **Step 2: Open the PR**
+
+Run `gh pr create --base main --head feat/pr-a2-bridge-ui-polish --title "feat: PR-A2 bridge UI polish — dark mode + state machine + activity log"` with a body containing:
+
+- One-paragraph summary
+- Bulleted list of what's shipped (theme fallback chain, AppState union, renderUI orchestrator, setState funneling, activity log polish)
+- Reference to the design doc and PR-A1 / PR-B
+- The manual smoke test checklist from Task 7 Step 4
+- Test plan: "All unit tests pass via `npm run check`. Manual smoke test pending against a real Figma file."
+
+- [ ] **Step 3: Report the PR URL to the user**
+
+Terminal phase complete.
+
+---
+
+## Self-Review Notes
+
+Performed:
+
+1. **Spec coverage:**
+ - §A (three-tier theme system) → Task 1 ✓
+ - §B (theme.ts preserved) → confirmed via "Unchanged" list in plan File Map ✓
+ - §C (AppState discriminated union) → Task 2 ✓
+ - §D (renderUI function) → Task 4 ✓
+ - §E (setState in ui-entry.ts) → Task 5 ✓
+ - §F (adapter functions) → Task 5 Steps 4-5 ✓
+ - §G (activity log polish) → Task 6 ✓
+ - Backwards compatibility → explicit in spec; preserved by leaving theme.ts, code.ts, ui.html unchanged ✓
+ - Testing strategy → tasks 1, 3, 4, 6 cover all three test files ✓
+ - Non-goals → explicitly not in any task ✓
+
+2. **Placeholder scan:** No TBDs. Task 5 has several "find the existing code path" steps because the existing `ui-entry.ts` is 350+ lines and we don't want to copy it verbatim. Each such step has explicit search criteria and concrete replacement code.
+
+3. **Type consistency:** `AppState`, `RunningOp` shapes consistent across Tasks 2, 3, 4, 5. `renderUI` signature consistent. `formatElapsed` imported in Task 5 matches its definition in Task 2.
+
+4. **Known unknowns:** Task 5 depends on the engineer reading and locating specific code paths in the existing `ui-entry.ts`. This is intentional — the file is large enough that paste-able diffs would be brittle. Explicit search criteria are provided.
diff --git a/docs/superpowers/specs/2026-06-04-pluginos-bridge-ui-polish-design.md b/docs/superpowers/specs/2026-06-04-pluginos-bridge-ui-polish-design.md
new file mode 100644
index 0000000..63ddc12
--- /dev/null
+++ b/docs/superpowers/specs/2026-06-04-pluginos-bridge-ui-polish-design.md
@@ -0,0 +1,345 @@
+# PluginOS Bridge UI Polish (PR-A2) — Design
+
+**Date:** 2026-06-04
+**Status:** Approved for implementation planning
+**Author:** Brainstorm session with Claude
+**Scope:** Single PR. Bridge-plugin-only. Fixes three UI bugs surfaced on 2026-06-03: dark mode never activates, post-reconnect UI shows stale state, recent operations not visible during a session.
+
+## Context
+
+The 2026-06-03 bulk-seed feedback included this verbatim observation:
+
+> *"The Figma UI is crap, and it's also changing. First load is better, if it connects and then disconnects, it's different. We also have the old UI when it's connected, so you cannot see what kind of operations are running or have been ran. Oh, also the color mode of the app is not been picked up, I always view it in Light mode even though my default is dark."*
+
+Three distinct bugs underneath:
+
+1. **Dark mode never activates.** `figma.editorPreferences.theme` returns undefined in current Figma builds. The ternary `theme === "dark" ? "dark" : "light"` silently falls back to light.
+2. **Stale UI after a reconnect cycle.** Multiple sub-elements (`#running-block`, `#idle-block`, `#file-name`, etc.) carry independent visibility state. After disconnect→connecting→connected, one of them is reliably out of sync with the actual app state.
+3. **Activity log not visible during sessions.** Plumbing is already in place (`activity-log.ts` class, HTML mount at `ui.html:204`, JS init at `ui-entry.ts:366`). User's "can't see operations" most likely reflects an older bundled `ui.html` cached via the bootloader pattern. But the deeper fix is making sure the activity log is *always* rendered fresh on every state transition, so any future scenario where the panel goes stale is impossible by construction.
+
+The connection-layer fixes (singleton, discovery, `wait_for_reconnect`) ship in PR-A1 (#29). This PR is the bridge-side UI cleanup that complements those changes.
+
+The full feedback document is at `/Users/dimi/Documents/TheVault/03 Vice Versa/TYPO3 Bootstrap/2026-06-03-pluginos-feedback.md`.
+
+## Goals
+
+1. **Make dark mode follow Figma's editor theme** without depending on `figma.editorPreferences.theme`.
+2. **Eliminate the stale-state-after-reconnect class of bugs** by funneling every UI mutation through a single idempotent `renderUI(state)` function.
+3. **Make recent operations visible** by ensuring the activity log renders on every state transition and improving its empty/full-state UX.
+
+## Non-goals (deferred or rejected)
+
+- **Connection foundation** (singleton, discovery, `wait_for_reconnect`) → PR-A1 #29
+- **Quality helpers** (prelude, lint, `PluginOS.*`) → PR-B #27
+- **Install polish** → PR-C
+- UI redesign — typography refresh, icon set, layout overhaul. Not in scope.
+- Animations / transitions. State changes are instant in v1.
+- Mobile / responsive. Figma plugin pane is fixed at 360×600.
+- Activity log persistence across plugin reloads. Entries are in-memory only; adding `figma.clientStorage` persistence is a separate design.
+- Click-to-view-full-result on activity rows. Existing `copy(op)` click behavior is preserved as-is.
+- Force-light / force-dark user toggle. The `data-theme` system supports it but no UI exposes it in PR-A2.
+
+## Architecture
+
+```
+ Figma editor theme
+ │
+ ▼
+ CSS custom properties auto-injected by themeColors: true
+ │
+ ▼
+ ┌─────────────────────────────────────────────────┐
+ │ ui/tokens.cjs │
+ │ --po-bg: var(--figma-color-bg, #fallback) │ ◄── Three-tier fallback chain:
+ │ --po-text: var(--figma-color-text, #fallback) │ Figma var → data-theme value → literal
+ └──────────────────────┬──────────────────────────┘
+ │
+ ▼
+ Rendered UI
+
+ ┌────────────────────────────────────────────────┐
+ │ ui/theme.ts (unchanged) │ ◄── Fallback for non-Figma contexts
+ │ detectInitialTheme via matchMedia │ (happy-dom tests, edge cases).
+ │ attachThemeListener for THEME_CHANGE │ Sets data-theme attr on .
+ │ applyTheme(theme) │
+ └────────────────────────────────────────────────┘
+
+ ┌────────────────────────────────────────────────┐
+ │ ui/render-ui.ts (new) │
+ │ type AppState = … │ ◄── Single source of truth.
+ │ function renderUI(state: AppState): void │ Idempotent. Pure DOM transformation.
+ │ helpers: pillStateFor, pillTextFor, │ No hidden sub-element state.
+ │ formatElapsed │
+ └────────────────────────────────────────────────┘
+ ▲
+ │ called by setState()
+ │
+ ┌────────────────────────────────────────────────┐
+ │ ui-entry.ts │
+ │ currentState: AppState │
+ │ setState(next): updates state, renders, │ ◄── All DOM mutations funnel through here.
+ │ manages elapsed timer │ No direct mutations elsewhere.
+ │ WebSocket handlers call setState({…}) │
+ └────────────────────────────────────────────────┘
+```
+
+## Component-by-component design
+
+### A. U1 — Three-tier theme system
+
+CSS variables resolve through three layers:
+
+```css
+:root {
+ --po-bg: var(--figma-color-bg, #ffffff);
+ --po-text: var(--figma-color-text, #18181b);
+ --po-border: var(--figma-color-border, #e4e4e7);
+ /* every token uses Figma var with a hardcoded fallback */
+}
+
+[data-theme="dark"] {
+ --po-bg-fallback: #1e1e1e;
+ --po-text-fallback: #f5f5f5;
+ /* fallbacks active when Figma vars are absent */
+}
+```
+
+When the plugin runs in Figma with `themeColors: true`: Figma injects `--figma-color-*` vars that auto-track the editor theme. The CSS resolves to those.
+
+When the plugin runs outside Figma (happy-dom tests, future contexts): Figma vars are undefined. CSS falls back to the literal (`#ffffff` / `#18181b`), which `data-theme="dark"` can override via the second-tier `--po-bg-fallback` chain.
+
+### B. U1 — What stays unchanged
+
+- `ui/theme.ts` — keeps its public API (`applyTheme`, `attachThemeListener`, `detectInitialTheme`). Becomes the secondary theme source instead of primary.
+- `code.ts` `sendTheme()` and `themechange` listener — still useful for environments where Figma's CSS var injection isn't available.
+- The `@ts-expect-error` casts in `code.ts` — preserved with their existing comments (older typings).
+- The HTML default `` — initial-render baseline.
+
+### C. U2 — `AppState` discriminated union
+
+```typescript
+type RunningOp = {
+ name: string;
+ paramsPreview: string;
+ startedAt: number;
+};
+
+type AppState =
+ | { kind: "disconnected" }
+ | { kind: "connecting"; lastKnownPort: number | null }
+ | {
+ kind: "connected";
+ file: { name: string; key: string };
+ port: number;
+ running: RunningOp | null;
+ }
+ | { kind: "mismatch"; reason: string; serverVersion: string; pluginVersion: string };
+```
+
+Every status the existing 5-state model represented maps 1:1 onto this union:
+
+| Old state | New state |
+|---|---|
+| `disconnected` | `{ kind: "disconnected" }` |
+| `connecting` | `{ kind: "connecting", lastKnownPort: … }` |
+| `connected` | `{ kind: "connected", file: …, port: …, running: null }` |
+| `running` | `{ kind: "connected", file: …, port: …, running: { name, paramsPreview, startedAt } }` |
+| `mismatch` | `{ kind: "mismatch", reason, serverVersion, pluginVersion }` |
+
+The `running` state collapses into `connected` because they share the same view container. The presence of a `RunningOp` inside the `connected` variant drives the running-block / idle-block toggle. This eliminates the bug where `running` and `connected` got out of sync after a reconnect.
+
+### D. U2 — `renderUI(state)` function
+
+Lives in `packages/bridge-plugin/src/ui/render-ui.ts` (new file). Pure DOM transformation. Idempotent: calling it twice with the same state is a no-op.
+
+```typescript
+export function renderUI(state: AppState): void {
+ // 1. Status pill
+ const pill = document.getElementById("status-pill")!;
+ const statusText = document.getElementById("status-text")!;
+ pill.dataset.state = pillStateFor(state);
+ statusText.textContent = pillTextFor(state);
+
+ // 2. Top-level views
+ document.getElementById("view-disconnected")!.hidden =
+ state.kind !== "disconnected" && state.kind !== "connecting";
+ document.getElementById("view-connected")!.hidden = state.kind !== "connected";
+ document.getElementById("view-mismatch")!.hidden = state.kind !== "mismatch";
+
+ // 3. Connected sub-blocks
+ if (state.kind === "connected") {
+ document.getElementById("file-name")!.textContent = state.file.name;
+ document.getElementById("port-url")!.textContent = `localhost:${state.port}`;
+ document.getElementById("running-block")!.hidden = state.running === null;
+ document.getElementById("idle-block")!.hidden = state.running !== null;
+ if (state.running) {
+ document.getElementById("run-op")!.textContent = state.running.name;
+ document.getElementById("run-params")!.textContent = state.running.paramsPreview;
+ document.getElementById("run-elapsed")!.textContent =
+ formatElapsed(Date.now() - state.running.startedAt);
+ }
+ } else {
+ // Defensive: explicitly hide running-block when not connected
+ document.getElementById("running-block")!.hidden = true;
+ }
+
+ // 4. Mismatch view text
+ if (state.kind === "mismatch") {
+ document.getElementById("mismatch-text")!.textContent =
+ `Server ${state.serverVersion} doesn't match plugin ${state.pluginVersion}. ${state.reason}`;
+ }
+}
+
+export function pillStateFor(state: AppState): string {
+ if (state.kind === "connected" && state.running) return "running";
+ return state.kind;
+}
+
+export function pillTextFor(state: AppState): string {
+ switch (state.kind) {
+ case "disconnected": return "Not connected";
+ case "connecting": return "Connecting…";
+ case "connected": return state.running ? `Running ${state.running.name}` : "Connected";
+ case "mismatch": return "Update needed";
+ }
+}
+
+export function formatElapsed(ms: number): string {
+ const s = ms / 1000;
+ if (s < 60) return `${s.toFixed(1)}s elapsed`;
+ return `${Math.floor(s / 60)}m ${Math.floor(s % 60)}s elapsed`;
+}
+```
+
+`activityLog.render()` is called by `ui-entry.ts`'s `setState` after `renderUI`, not from inside `renderUI` itself — keeps the pure DOM transformation separate from the component's own internal state.
+
+### E. U2 — `setState` in `ui-entry.ts`
+
+```typescript
+let currentState: AppState = { kind: "disconnected" };
+let elapsedTimer: number | null = null;
+
+function setState(next: AppState): void {
+ currentState = next;
+ renderUI(next);
+ activityLog.render();
+
+ // Manage the elapsed-timer lifecycle from a single place
+ if (next.kind === "connected" && next.running) {
+ if (elapsedTimer === null) {
+ elapsedTimer = window.setInterval(() => {
+ if (currentState.kind === "connected" && currentState.running) {
+ document.getElementById("run-elapsed")!.textContent =
+ formatElapsed(Date.now() - currentState.running.startedAt);
+ }
+ }, 100);
+ }
+ } else if (elapsedTimer !== null) {
+ clearInterval(elapsedTimer);
+ elapsedTimer = null;
+ }
+}
+```
+
+**Invariant:** every DOM mutation in `ui-entry.ts` outside of `activityLog.push()` goes through `setState({...})`. WebSocket message handlers update by computing the next `AppState` from the current one and calling `setState`.
+
+### F. U2 — Adapter functions for migration safety
+
+The existing `setStatus(state, text?)` and `showView(view)` functions are rewritten as thin adapters that funnel into `setState`. They keep the surrounding handler code's shape unchanged. Future refactor can inline the `setState` calls and delete the adapters.
+
+```typescript
+function setStatus(state: StatusState, _text?: string): void {
+ // Compute next AppState from current + new status
+ // This is a migration shim; future PRs can inline at the call sites
+ const next: AppState = computeNextStateFromStatus(currentState, state);
+ setState(next);
+}
+```
+
+### G. U3 — Activity log polish
+
+Three small changes in `ui/activity-log.ts`:
+
+1. `MAX_VISIBLE = 5` → `MAX_VISIBLE = 10`
+2. Empty-state copy: `"No recent activity"` → `"No operations yet — your agent will populate this as it runs."`
+3. No API changes. The class still owns its entries.
+
+One new test (`__tests__/activity-log-integration.test.ts`) mounts the connected view and asserts entries render correctly with the new constants.
+
+## Backwards compatibility
+
+- `theme.ts` public API unchanged
+- `code.ts` `sendTheme()` and `themechange` listener unchanged
+- HTML `` initial-render default preserved
+- WebSocket message protocol unchanged
+- `ActivityLog` class API unchanged (only `MAX_VISIBLE` constant and empty-state copy change)
+- A bridge-plugin built from this PR works identically against an older mcp-server
+
+## Testing strategy
+
+**Unit tests:**
+
+| File | What it tests |
+|---|---|
+| `__tests__/render-ui.test.ts` | `renderUI(state)` for every variant; the disconnect→reconnect cycle regression test |
+| `__tests__/activity-log-integration.test.ts` | Activity log rendered inside the connected view; entry-count cap; empty-state copy |
+| `__tests__/theme-fallback.test.ts` | CSS variable fallback chain works without Figma vars; `data-theme="dark"` overrides correctly |
+| `ui/__tests__/activity-log.test.ts` (existing) | Unchanged behavior; add cases for the new copy + `MAX_VISIBLE` |
+
+**No new integration tests.** The state machine + render layer is fully exercised by `render-ui.test.ts` under happy-dom. The activity log is exercised by its dedicated test. We don't need cross-file integration tests for this scope.
+
+**Manual smoke test** (PR description, run before merge):
+
+1. Open the bridge plugin in Figma. Toggle Figma to dark mode. Plugin UI should switch instantly.
+2. Toggle Figma back to light. Plugin UI switches back.
+3. Run an `execute_figma` op from Claude. Watch the running-block appear with op name + elapsed time.
+4. Force-close + reopen the plugin pane mid-op. After reconnect, running-block should be hidden (no op is running anymore). Activity log shows the prior op.
+5. Run two more ops. Activity log surfaces the 3 most recent at the top.
+6. Disconnect the MCP server (`kill $(pgrep -f pluginos)`). Plugin UI shows "Connecting…" then "Not connected." Reconnect (PR-A1's takeover or manual `npx pluginos`). UI returns to connected with activity log intact.
+
+## Sequencing within the PR
+
+Six loose phases:
+
+1. **Theme fallback CSS (U1)** — rewrite `tokens.cjs`; add `theme-fallback.test.ts`
+2. **`AppState` type + `renderUI` extraction (U2)** — create `ui/render-ui.ts` with the type union, `renderUI`, and pure helpers; add `render-ui.test.ts`
+3. **`setState` + adapter migration (U2)** — introduce `setState()` in `ui-entry.ts`; rewrite `setStatus` / `showView` as adapters; update WebSocket handlers to call `setState({...})`
+4. **Running timer ownership (U2)** — move `setInterval` for `#run-elapsed` into `setState`
+5. **Activity log polish (U3)** — `MAX_VISIBLE` 5→10, empty-state copy, `activity-log-integration.test.ts`
+6. **Full check + manual smoke prep**
+
+After phase 3, the stale-state-after-reconnect bug is fixed. After phase 5, all three of U1/U2/U3 ship.
+
+## Files touched
+
+```
+MODIFY packages/bridge-plugin/src/ui/tokens.cjs (Figma var fallback chain)
+MODIFY packages/bridge-plugin/src/ui-entry.ts (setState + adapters)
+MODIFY packages/bridge-plugin/src/ui/activity-log.ts (MAX_VISIBLE 5→10, empty copy)
+CREATE packages/bridge-plugin/src/ui/render-ui.ts (AppState + renderUI + helpers)
+CREATE packages/bridge-plugin/src/__tests__/render-ui.test.ts
+CREATE packages/bridge-plugin/src/__tests__/activity-log-integration.test.ts
+CREATE packages/bridge-plugin/src/__tests__/theme-fallback.test.ts
+
+UNCHANGED (preserved):
+ packages/bridge-plugin/src/ui/theme.ts (fallback layer)
+ packages/bridge-plugin/src/ui.html (body data-theme default)
+ packages/bridge-plugin/src/code.ts (sendTheme + themechange)
+```
+
+## Open questions deferred to implementation
+
+1. **Exact Figma color variable mapping** — Figma exposes `--figma-color-bg`, `--figma-color-bg-secondary`, `--figma-color-text`, `--figma-color-text-secondary`, `--figma-color-border`, etc. The mapping from our `--po-*` tokens to these is mechanical; decided during phase 1 by inspecting Figma's documented variable list.
+2. **`formatElapsed()` exact thresholds** — current implementation is sub-minute display in seconds; over-minute in `Nm Ms`. May tune during implementation if a manual smoke test shows awkward boundary behavior.
+3. **Whether `setStatus`/`showView` adapters can be deleted in this PR or stay for a future cleanup** — depends on how mechanical the call-site migration turns out to be.
+
+## References
+
+- Feedback source: `/Users/dimi/Documents/TheVault/03 Vice Versa/TYPO3 Bootstrap/2026-06-03-pluginos-feedback.md`
+- Existing theme module: `packages/bridge-plugin/src/ui/theme.ts`
+- Existing tokens: `packages/bridge-plugin/src/ui/tokens.cjs`
+- Existing UI markup: `packages/bridge-plugin/src/ui.html`
+- Existing UI entry: `packages/bridge-plugin/src/ui-entry.ts`
+- Existing activity log: `packages/bridge-plugin/src/ui/activity-log.ts`
+- Companion PR-A1 (connection foundation): #29
+- Companion PR-B (quality helpers): #27
diff --git a/package-lock.json b/package-lock.json
index aaaf674..26474d0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,31 +10,19 @@
],
"devDependencies": {
"@eslint/js": "^10.0.1",
+ "@vitest/coverage-v8": "^4.1.8",
"eslint": "^10.2.0",
"eslint-config-prettier": "^10.1.8",
"husky": "^9.1.7",
"prettier": "^3.8.2",
- "typescript-eslint": "^8.58.2"
- }
- },
- "node_modules/@ampproject/remapping": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
- "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
+ "typescript-eslint": "^8.58.2",
+ "vitest": "^4.1.8"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -42,9 +30,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
- "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -52,13 +40,13 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.29.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
- "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
+ "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.29.0"
+ "@babel/types": "^7.29.7"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -68,25 +56,28 @@
}
},
"node_modules/@babel/types": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
- "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
+ "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@bcoe/v8-coverage": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
- "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
},
"node_modules/@discoveryjs/json-ext": {
"version": "0.5.7",
@@ -753,76 +744,6 @@
"url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
- "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.2.2"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/@istanbuljs/schema": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz",
- "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@jest/schemas": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
- "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@sinclair/typebox": "^0.27.8"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -913,17 +834,6 @@
}
}
},
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/@pluginos/bridge-plugin": {
"resolved": "packages/bridge-plugin",
"link": true
@@ -1286,10 +1196,10 @@
"win32"
]
},
- "node_modules/@sinclair/typebox": {
- "version": "0.27.10",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
- "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
"dev": true,
"license": "MIT"
},
@@ -1303,6 +1213,24 @@
"@types/node": "*"
}
},
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/eslint": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
@@ -1611,31 +1539,29 @@
}
},
"node_modules/@vitest/coverage-v8": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.9.tgz",
- "integrity": "sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.8.tgz",
+ "integrity": "sha512-lt3kovsyHwYe00wq4D1ti0Z974fWj4NLp6siqiyEufUpyFwK9Yhi7rBhac9JL5aA0zoMrJqc4vYPZRUnI7l7nw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@ampproject/remapping": "^2.3.0",
- "@bcoe/v8-coverage": "^0.2.3",
- "debug": "^4.3.7",
+ "@bcoe/v8-coverage": "^1.0.2",
+ "@vitest/utils": "4.1.8",
+ "ast-v8-to-istanbul": "^1.0.0",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
- "istanbul-lib-source-maps": "^5.0.6",
- "istanbul-reports": "^3.1.7",
- "magic-string": "^0.30.12",
- "magicast": "^0.3.5",
- "std-env": "^3.8.0",
- "test-exclude": "^7.0.1",
- "tinyrainbow": "^1.2.0"
+ "istanbul-reports": "^3.2.0",
+ "magicast": "^0.5.2",
+ "obug": "^2.1.1",
+ "std-env": "^4.0.0-rc.1",
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/browser": "2.1.9",
- "vitest": "2.1.9"
+ "@vitest/browser": "4.1.8",
+ "vitest": "4.1.8"
},
"peerDependenciesMeta": {
"@vitest/browser": {
@@ -1644,38 +1570,40 @@
}
},
"node_modules/@vitest/expect": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz",
- "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz",
+ "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "2.1.9",
- "@vitest/utils": "2.1.9",
- "chai": "^5.1.2",
- "tinyrainbow": "^1.2.0"
+ "@standard-schema/spec": "^1.1.0",
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "chai": "^6.2.2",
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/mocker": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz",
- "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz",
+ "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "2.1.9",
+ "@vitest/spy": "4.1.8",
"estree-walker": "^3.0.3",
- "magic-string": "^0.30.12"
+ "magic-string": "^0.30.21"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"msw": "^2.4.9",
- "vite": "^5.0.0"
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"msw": {
@@ -1687,84 +1615,68 @@
}
},
"node_modules/@vitest/pretty-format": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz",
- "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz",
+ "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tinyrainbow": "^1.2.0"
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/runner": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz",
- "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz",
+ "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "2.1.9",
- "pathe": "^1.1.2"
+ "@vitest/utils": "4.1.8",
+ "pathe": "^2.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
- "node_modules/@vitest/runner/node_modules/pathe": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
- "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@vitest/snapshot": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz",
- "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz",
+ "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.1.9",
- "magic-string": "^0.30.12",
- "pathe": "^1.1.2"
+ "@vitest/pretty-format": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "magic-string": "^0.30.21",
+ "pathe": "^2.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
- "node_modules/@vitest/snapshot/node_modules/pathe": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
- "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@vitest/spy": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz",
- "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz",
+ "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "tinyspy": "^3.0.2"
- },
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/utils": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz",
- "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz",
+ "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.1.9",
- "loupe": "^3.1.2",
- "tinyrainbow": "^1.2.0"
+ "@vitest/pretty-format": "4.1.8",
+ "convert-source-map": "^2.0.0",
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -2041,19 +1953,6 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/acorn-walk": {
- "version": "8.3.5",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz",
- "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "acorn": "^8.11.0"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
"node_modules/adm-zip": {
"version": "0.5.17",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.17.tgz",
@@ -2153,6 +2052,18 @@
"node": ">=12"
}
},
+ "node_modules/ast-v8-to-istanbul": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.3.tgz",
+ "integrity": "sha512-jCMQ6ZylLPudp0CDfBmQBZUsrh1/8psbmu9ibeVWKuHWD0YrH9YABwlKu5kVEFoT0GCQQW9Z/SxfuEbbkGQCRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.31",
+ "estree-walker": "^3.0.3",
+ "js-tokens": "^10.0.0"
+ }
+ },
"node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
@@ -2371,18 +2282,11 @@
"license": "CC-BY-4.0"
},
"node_modules/chai": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
- "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
+ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "assertion-error": "^2.0.1",
- "check-error": "^2.1.1",
- "deep-eql": "^5.0.1",
- "loupe": "^3.1.0",
- "pathval": "^2.0.0"
- },
"engines": {
"node": ">=18"
}
@@ -2404,16 +2308,6 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/check-error": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
- "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 16"
- }
- },
"node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
@@ -2544,6 +2438,13 @@
"node": ">= 0.6"
}
},
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
@@ -2640,16 +2541,6 @@
}
}
},
- "node_modules/deep-eql": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
- "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -2666,16 +2557,6 @@
"node": ">= 0.8"
}
},
- "node_modules/diff-sequences": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
- "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
"node_modules/dom-converter": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
@@ -2770,13 +2651,6 @@
"node": ">= 0.4"
}
},
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -2790,13 +2664,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
@@ -2862,9 +2729,9 @@
}
},
"node_modules/es-module-lexer": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
- "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
+ "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
"dev": true,
"license": "MIT"
},
@@ -3193,30 +3060,6 @@
"node": ">=18.0.0"
}
},
- "node_modules/execa": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
- "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^8.0.1",
- "human-signals": "^5.0.0",
- "is-stream": "^3.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^5.1.0",
- "onetime": "^6.0.0",
- "signal-exit": "^4.1.0",
- "strip-final-newline": "^3.0.0"
- },
- "engines": {
- "node": ">=16.17"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
"node_modules/expect-type": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
@@ -3441,23 +3284,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/foreground-child": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
- "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "cross-spawn": "^7.0.6",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -3500,16 +3326,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-func-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
- "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@@ -3547,19 +3363,6 @@
"node": ">= 0.4"
}
},
- "node_modules/get-stream": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
- "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/get-tsconfig": {
"version": "4.14.0",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
@@ -3573,28 +3376,6 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
- "node_modules/glob": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
- "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
- "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -3615,39 +3396,6 @@
"dev": true,
"license": "BSD-2-Clause"
},
- "node_modules/glob/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/glob/node_modules/brace-expansion": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
- "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/glob/node_modules/minimatch": {
- "version": "9.0.9",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
- "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.2"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -3868,16 +3616,6 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/human-signals": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
- "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=16.17.0"
- }
- },
"node_modules/husky": {
"version": "9.1.7",
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
@@ -4010,16 +3748,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -4062,19 +3790,6 @@
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
- "node_modules/is-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
- "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -4116,21 +3831,6 @@
"node": ">=10"
}
},
- "node_modules/istanbul-lib-source-maps": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
- "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.23",
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/istanbul-reports": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
@@ -4145,22 +3845,6 @@
"node": ">=8"
}
},
- "node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
- }
- },
"node_modules/jest-worker": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
@@ -4212,9 +3896,9 @@
}
},
"node_modules/js-tokens": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
- "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz",
+ "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==",
"dev": true,
"license": "MIT"
},
@@ -4322,31 +4006,14 @@
"url": "https://opencollective.com/webpack"
}
},
- "node_modules/local-pkg": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz",
- "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==",
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "mlly": "^1.7.3",
- "pkg-types": "^1.2.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^5.0.0"
+ "p-locate": "^5.0.0"
},
"engines": {
"node": ">=10"
@@ -4362,13 +4029,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/loupe": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
- "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
@@ -4379,13 +4039,6 @@
"tslib": "^2.0.3"
}
},
- "node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -4397,15 +4050,15 @@
}
},
"node_modules/magicast": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz",
- "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==",
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz",
+ "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.25.4",
- "@babel/types": "^7.25.4",
- "source-map-js": "^1.2.0"
+ "@babel/parser": "^7.29.3",
+ "@babel/types": "^7.29.0",
+ "source-map-js": "^1.2.1"
}
},
"node_modules/make-dir": {
@@ -4500,19 +4153,6 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/mimic-fn": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
- "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/minimatch": {
"version": "10.2.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
@@ -4529,16 +4169,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/minipass": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
- "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
"node_modules/mlly": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz",
@@ -4630,35 +4260,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/npm-run-path": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
- "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/npm-run-path/node_modules/path-key": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
- "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@@ -4693,6 +4294,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/obug": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.2.tgz",
+ "integrity": "sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==",
+ "dev": true,
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -4714,22 +4329,6 @@
"wrappy": "1"
}
},
- "node_modules/onetime": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
- "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^4.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -4790,13 +4389,6 @@
"node": ">=6"
}
},
- "node_modules/package-json-from-dist": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
- "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
- "dev": true,
- "license": "BlueOak-1.0.0"
- },
"node_modules/param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
@@ -4854,23 +4446,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/path-to-regexp": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
@@ -4888,16 +4463,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/pathval": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
- "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 14.16"
- }
- },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -5131,34 +4696,6 @@
"renderkid": "^3.0.0"
}
},
- "node_modules/pretty-format": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
- "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/schemas": "^29.6.3",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/pretty-format/node_modules/ansi-styles": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
- "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -5221,13 +4758,6 @@
"node": ">= 0.10"
}
},
- "node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/readdirp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
@@ -5632,19 +5162,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -5693,82 +5210,12 @@
}
},
"node_modules/std-env": {
- "version": "3.10.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
- "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/string-width-cjs": {
- "name": "string-width",
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz",
+ "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==",
"dev": true,
"license": "MIT"
},
- "node_modules/string-width/node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/string-width/node_modules/strip-ansi": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
- "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.2.2"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -5782,46 +5229,6 @@
"node": ">=8"
}
},
- "node_modules/strip-ansi-cjs": {
- "name": "strip-ansi",
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-final-newline": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
- "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/strip-literal": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz",
- "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^9.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
- },
"node_modules/sucrase": {
"version": "3.35.1",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
@@ -5955,21 +5362,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/test-exclude": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.2.tgz",
- "integrity": "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "@istanbuljs/schema": "^0.1.2",
- "glob": "^10.4.1",
- "minimatch": "^10.2.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -6055,30 +5447,10 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/tinypool": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
- "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- }
- },
"node_modules/tinyrainbow": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
- "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/tinyspy": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
- "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
+ "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6271,16 +5643,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/type-detect": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz",
- "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
@@ -6489,36 +5851,6 @@
}
}
},
- "node_modules/vite-node": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz",
- "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cac": "^6.7.14",
- "debug": "^4.3.7",
- "es-module-lexer": "^1.5.4",
- "pathe": "^1.1.2",
- "vite": "^5.0.0"
- },
- "bin": {
- "vite-node": "vite-node.mjs"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "node_modules/vite-node/node_modules/pathe": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
- "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/vite/node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@@ -6551,58 +5883,79 @@
}
},
"node_modules/vitest": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz",
- "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/expect": "2.1.9",
- "@vitest/mocker": "2.1.9",
- "@vitest/pretty-format": "^2.1.9",
- "@vitest/runner": "2.1.9",
- "@vitest/snapshot": "2.1.9",
- "@vitest/spy": "2.1.9",
- "@vitest/utils": "2.1.9",
- "chai": "^5.1.2",
- "debug": "^4.3.7",
- "expect-type": "^1.1.0",
- "magic-string": "^0.30.12",
- "pathe": "^1.1.2",
- "std-env": "^3.8.0",
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz",
+ "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/expect": "4.1.8",
+ "@vitest/mocker": "4.1.8",
+ "@vitest/pretty-format": "4.1.8",
+ "@vitest/runner": "4.1.8",
+ "@vitest/snapshot": "4.1.8",
+ "@vitest/spy": "4.1.8",
+ "@vitest/utils": "4.1.8",
+ "es-module-lexer": "^2.0.0",
+ "expect-type": "^1.3.0",
+ "magic-string": "^0.30.21",
+ "obug": "^2.1.1",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.3",
+ "std-env": "^4.0.0-rc.1",
"tinybench": "^2.9.0",
- "tinyexec": "^0.3.1",
- "tinypool": "^1.0.1",
- "tinyrainbow": "^1.2.0",
- "vite": "^5.0.0",
- "vite-node": "2.1.9",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tinyrainbow": "^3.1.0",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
"why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
},
"engines": {
- "node": "^18.0.0 || >=20.0.0"
+ "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@edge-runtime/vm": "*",
- "@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "2.1.9",
- "@vitest/ui": "2.1.9",
+ "@opentelemetry/api": "^1.9.0",
+ "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "4.1.8",
+ "@vitest/browser-preview": "4.1.8",
+ "@vitest/browser-webdriverio": "4.1.8",
+ "@vitest/coverage-istanbul": "4.1.8",
+ "@vitest/coverage-v8": "4.1.8",
+ "@vitest/ui": "4.1.8",
"happy-dom": "*",
- "jsdom": "*"
+ "jsdom": "*",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
"optional": true
},
+ "@opentelemetry/api": {
+ "optional": true
+ },
"@types/node": {
"optional": true
},
- "@vitest/browser": {
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-preview": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
"optional": true
},
"@vitest/ui": {
@@ -6613,15 +5966,34 @@
},
"jsdom": {
"optional": true
+ },
+ "vite": {
+ "optional": false
}
}
},
- "node_modules/vitest/node_modules/pathe": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
- "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+ "node_modules/vitest/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/vitest/node_modules/tinyexec": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz",
+ "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
},
"node_modules/watchpack": {
"version": "2.5.1",
@@ -6766,13 +6138,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/webpack/node_modules/es-module-lexer": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
- "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/webpack/node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -6856,107 +6221,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs": {
- "name": "wrap-ansi",
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/wrap-ansi-cjs/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-styles": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
- "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
- "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.2.2"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -7026,7 +6290,7 @@
"html-webpack-plugin": "^5.6.0",
"ts-loader": "^9.5.0",
"typescript": "^5.5.0",
- "vitest": "^2.1.0",
+ "vitest": "^4.1.8",
"webpack": "^5.90.0",
"webpack-cli": "^5.1.0"
}
@@ -7051,199 +6315,7 @@
"devDependencies": {
"tsx": "^4.0.0",
"typescript": "^5.0.0",
- "vitest": "^1.0.0"
- }
- },
- "packages/claude-plugin/node_modules/@vitest/expect": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz",
- "integrity": "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/spy": "1.6.1",
- "@vitest/utils": "1.6.1",
- "chai": "^4.3.10"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "packages/claude-plugin/node_modules/@vitest/runner": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz",
- "integrity": "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/utils": "1.6.1",
- "p-limit": "^5.0.0",
- "pathe": "^1.1.1"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "packages/claude-plugin/node_modules/@vitest/snapshot": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz",
- "integrity": "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "magic-string": "^0.30.5",
- "pathe": "^1.1.1",
- "pretty-format": "^29.7.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "packages/claude-plugin/node_modules/@vitest/spy": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz",
- "integrity": "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tinyspy": "^2.2.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "packages/claude-plugin/node_modules/@vitest/utils": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz",
- "integrity": "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "diff-sequences": "^29.6.3",
- "estree-walker": "^3.0.3",
- "loupe": "^2.3.7",
- "pretty-format": "^29.7.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "packages/claude-plugin/node_modules/assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "packages/claude-plugin/node_modules/chai": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz",
- "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assertion-error": "^1.1.0",
- "check-error": "^1.0.3",
- "deep-eql": "^4.1.3",
- "get-func-name": "^2.0.2",
- "loupe": "^2.3.6",
- "pathval": "^1.1.1",
- "type-detect": "^4.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "packages/claude-plugin/node_modules/check-error": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
- "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "get-func-name": "^2.0.2"
- },
- "engines": {
- "node": "*"
- }
- },
- "packages/claude-plugin/node_modules/deep-eql": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz",
- "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-detect": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "packages/claude-plugin/node_modules/loupe": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
- "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "get-func-name": "^2.0.1"
- }
- },
- "packages/claude-plugin/node_modules/p-limit": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz",
- "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^1.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "packages/claude-plugin/node_modules/pathe": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
- "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
- "dev": true,
- "license": "MIT"
- },
- "packages/claude-plugin/node_modules/pathval": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
- "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "packages/claude-plugin/node_modules/tinypool": {
- "version": "0.8.4",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz",
- "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "packages/claude-plugin/node_modules/tinyspy": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz",
- "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
+ "vitest": "^4.1.8"
}
},
"packages/claude-plugin/node_modules/typescript": {
@@ -7260,108 +6332,6 @@
"node": ">=14.17"
}
},
- "packages/claude-plugin/node_modules/vite-node": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz",
- "integrity": "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cac": "^6.7.14",
- "debug": "^4.3.4",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "vite": "^5.0.0"
- },
- "bin": {
- "vite-node": "vite-node.mjs"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- }
- },
- "packages/claude-plugin/node_modules/vitest": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz",
- "integrity": "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@vitest/expect": "1.6.1",
- "@vitest/runner": "1.6.1",
- "@vitest/snapshot": "1.6.1",
- "@vitest/spy": "1.6.1",
- "@vitest/utils": "1.6.1",
- "acorn-walk": "^8.3.2",
- "chai": "^4.3.10",
- "debug": "^4.3.4",
- "execa": "^8.0.1",
- "local-pkg": "^0.5.0",
- "magic-string": "^0.30.5",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "std-env": "^3.5.0",
- "strip-literal": "^2.0.0",
- "tinybench": "^2.5.1",
- "tinypool": "^0.8.3",
- "vite": "^5.0.0",
- "vite-node": "1.6.1",
- "why-is-node-running": "^2.2.2"
- },
- "bin": {
- "vitest": "vitest.mjs"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/vitest"
- },
- "peerDependencies": {
- "@edge-runtime/vm": "*",
- "@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "1.6.1",
- "@vitest/ui": "1.6.1",
- "happy-dom": "*",
- "jsdom": "*"
- },
- "peerDependenciesMeta": {
- "@edge-runtime/vm": {
- "optional": true
- },
- "@types/node": {
- "optional": true
- },
- "@vitest/browser": {
- "optional": true
- },
- "@vitest/ui": {
- "optional": true
- },
- "happy-dom": {
- "optional": true
- },
- "jsdom": {
- "optional": true
- }
- }
- },
- "packages/claude-plugin/node_modules/yocto-queue": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
- "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"packages/mcp-server": {
"name": "pluginos",
"version": "0.4.3",
@@ -7378,12 +6348,12 @@
"@pluginos/shared": "*",
"@types/adm-zip": "^0.5.8",
"@types/ws": "^8.5.0",
- "@vitest/coverage-v8": "^2.1.9",
+ "@vitest/coverage-v8": "^4.1.8",
"adm-zip": "^0.5.17",
"tsup": "^8.5.1",
"tsx": "^4.19.0",
"typescript": "^5.5.0",
- "vitest": "^2.1.0"
+ "vitest": "^4.1.8"
},
"engines": {
"node": ">=18"
@@ -7407,9 +6377,9 @@
"name": "@pluginos/shared",
"version": "0.4.3",
"devDependencies": {
- "@vitest/coverage-v8": "^2.1.9",
+ "@vitest/coverage-v8": "^4.1.8",
"typescript": "^5.5.0",
- "vitest": "^2.1.0"
+ "vitest": "^4.1.8"
}
},
"packages/shared/node_modules/typescript": {
diff --git a/package.json b/package.json
index c25e5e3..5eea0b2 100644
--- a/package.json
+++ b/package.json
@@ -22,14 +22,18 @@
},
"devDependencies": {
"@eslint/js": "^10.0.1",
+ "@vitest/coverage-v8": "^4.1.8",
"eslint": "^10.2.0",
"eslint-config-prettier": "^10.1.8",
"husky": "^9.1.7",
"prettier": "^3.8.2",
- "typescript-eslint": "^8.58.2"
+ "typescript-eslint": "^8.58.2",
+ "vitest": "^4.1.8"
},
"overrides": {
"vite": "^6.4.2",
- "esbuild": "^0.25.0"
+ "esbuild": "^0.25.0",
+ "vitest": "^4.1.8",
+ "@vitest/coverage-v8": "^4.1.8"
}
}
diff --git a/packages/bridge-plugin/package.json b/packages/bridge-plugin/package.json
index 464d676..5f29f89 100644
--- a/packages/bridge-plugin/package.json
+++ b/packages/bridge-plugin/package.json
@@ -16,7 +16,7 @@
"html-webpack-plugin": "^5.6.0",
"ts-loader": "^9.5.0",
"typescript": "^5.5.0",
- "vitest": "^2.1.0",
+ "vitest": "^4.1.8",
"webpack": "^5.90.0",
"webpack-cli": "^5.1.0"
}
diff --git a/packages/claude-plugin/package.json b/packages/claude-plugin/package.json
index eba7463..649e9f6 100644
--- a/packages/claude-plugin/package.json
+++ b/packages/claude-plugin/package.json
@@ -10,7 +10,7 @@
},
"devDependencies": {
"tsx": "^4.0.0",
- "vitest": "^1.0.0",
- "typescript": "^5.0.0"
+ "typescript": "^5.0.0",
+ "vitest": "^4.1.8"
}
}
diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json
index 698f9d7..ef4241f 100644
--- a/packages/mcp-server/package.json
+++ b/packages/mcp-server/package.json
@@ -53,11 +53,11 @@
"@pluginos/shared": "*",
"@types/adm-zip": "^0.5.8",
"@types/ws": "^8.5.0",
- "@vitest/coverage-v8": "^2.1.9",
+ "@vitest/coverage-v8": "^4.1.8",
"adm-zip": "^0.5.17",
"tsup": "^8.5.1",
"tsx": "^4.19.0",
"typescript": "^5.5.0",
- "vitest": "^2.1.0"
+ "vitest": "^4.1.8"
}
}
diff --git a/packages/shared/package.json b/packages/shared/package.json
index cc84225..24117b4 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -11,8 +11,8 @@
"test:coverage": "vitest run --coverage"
},
"devDependencies": {
- "@vitest/coverage-v8": "^2.1.9",
+ "@vitest/coverage-v8": "^4.1.8",
"typescript": "^5.5.0",
- "vitest": "^2.1.0"
+ "vitest": "^4.1.8"
}
}