diff --git a/.prettierignore b/.prettierignore index e21dc216..bd023dc1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,8 @@ node_modules/ dist/ **/dist/ +**/.wrnexus/** +**/.wrnexus-*/** .publish/ **/.wirefw/ coverage/ diff --git a/docs/framework-remediation-plan.md b/docs/framework-remediation-plan.md index a0710a30..a695ee3c 100644 --- a/docs/framework-remediation-plan.md +++ b/docs/framework-remediation-plan.md @@ -1,12 +1,15 @@ # Framework remediation plan -**Status: completed 2026-08-09.** Every actionable item in this plan has been -implemented and covered by a failing-before regression or an enforceable -ratchet. The final repository state has 102 maintained UI components, zero +**Status: remediation behavior completed; CSS ownership cleanup remains.** The +repository has 102 maintained UI components, zero undeclared non-native output emitters, zero components matching the scaffold definition, and local styles on every component. The core reactive runtime is 48,124 minified bytes; component controllers ship separately at 24,027 bytes. +Section 4.1 remains open: the global `ui.css` still contains legacy component +rules duplicated by local component styles. Those rules must be removed before +the §0.1 ownership convention can be called complete. + Final validation passed the production, package, example, service, editor, showcase-generation, typecheck, lint, formatting, public-API, visual-contract, security, and runtime-size gates. The only skipped test is the explicitly @@ -497,13 +500,17 @@ whichever behaviour was chosen. ## 4. Delivery and the dev loop -### 4.1 Global `ui.css` migration — FIXED +### 4.1 Global `ui.css` migration — PARTIAL **Original issue.** `ui.css` was **175,848 bytes, 26,350 gzipped**, served on every page. Only **42 of 108** components had a local `style {}` block. -**Result.** The maintained library now has **102 of 102** components with local -styles. Built `ui.css` is **77,410 bytes / 12,764 gzipped**. +**Result so far.** The maintained library now has **102 of 102** components +with local styles. After removing the unused `.wire-switch` family, built +`ui.css` is **76,348 bytes / 12,531 gzipped**, but +it still contains a parallel legacy component layer, including `.wire-next`, +`.wire-btn`, `.wire-dropdown`, and related families. Local-style coverage alone +does not complete this item; global component selectors must reach zero. **Change.** Done in groups with the visual contract regenerated after each migration. @@ -512,8 +519,8 @@ migration. ```bash ls packages/ui/components/*.wrn | wc -l # 102 -grep -l '^ style {' packages/ui/components/*.wrn | wc -l # 102 -bun run build && gzip -c examples/basic-app/dist/ui.css | wc -c # 12764 +grep -lE '^[[:space:]]*style[[:space:]]*\{' packages/ui/components/*.wrn | wc -l # 102 +bun run build && gzip -c examples/basic-app/dist/ui.css | wc -c # 12531 ``` Add a ratchet test asserting the gzipped size only ever decreases, so this @@ -560,7 +567,8 @@ therefore deletes the running server's cache. **Change.** The first option was implemented: each process uses `.wrnexus-`, normal server shutdown removes its directory, and -`.wrnexus-*/` is gitignored so an interrupted process cannot pollute a commit. +`.wrnexus-*/` is excluded by Git, ESLint, TypeScript, and Prettier so an +interrupted process cannot pollute a commit or a repository-wide tool run. The considered options were: diff --git a/docs/ui-visual-contract-0.8.json b/docs/ui-visual-contract-0.8.json index e82a3bf5..a6ad67e8 100644 --- a/docs/ui-visual-contract-0.8.json +++ b/docs/ui-visual-contract-0.8.json @@ -104,6 +104,6 @@ "packages/ui/components/switch.wrn": "205591decf50f1f7d190d8da6a3d969e0fd17ec5300c968fb005608da6a6e596", "packages/ui/components/textarea.wrn": "00b48d4dbbd5aedfe51e8e932d124b3e222383360c738ac3b15fbbf478481ff7", "packages/ui/components/tooltip.wrn": "40028dfbb17f6725c76c2e091af9c30ea4db6aa4dea919d38f53874ea70315d1", - "packages/ui/ui.css": "d671a848fcbd340d1140a2855019dccecbd71a81d36276e4f1f6cee9d960da9d" + "packages/ui/ui.css": "2cdf2ab533f0d2ad5dc9576be701408a6388b985ebac5c34e61d71a9de521a94" } } diff --git a/eslint.config.js b/eslint.config.js index b9a32e54..4704745c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,6 +13,7 @@ export default tseslint.config( "**/dist/**", ".publish/**", "**/.wrnexus/**", + "**/.wrnexus-*/**", "coverage/**", "bun.lock", "bun.lockb", diff --git a/packages/dev-server/test/cache-ignore-config.test.ts b/packages/dev-server/test/cache-ignore-config.test.ts new file mode 100644 index 00000000..6f41a8d9 --- /dev/null +++ b/packages/dev-server/test/cache-ignore-config.test.ts @@ -0,0 +1,40 @@ +import { expect, test } from "bun:test"; +import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { join, resolve } from "node:path"; + +const root = resolve(import.meta.dir, "../../.."); + +test("per-process dev caches are excluded from every repository-wide tool", () => { + const eslint = readFileSync(join(root, "eslint.config.js"), "utf8"); + const tsconfig = JSON.parse(readFileSync(join(root, "tsconfig.json"), "utf8")) as { + exclude?: string[]; + }; + const prettier = readFileSync(join(root, ".prettierignore"), "utf8"); + + expect(eslint).toContain('"**/.wrnexus-*/**"'); + expect(tsconfig.exclude).toContain("**/.wrnexus-*"); + expect(prettier).toContain("**/.wrnexus-*/**"); + + const cache = join(root, "packages", "dev-server", "test", ".tmp-cache-ignore", ".wrnexus-123"); + mkdirSync(cache, { recursive: true }); + writeFileSync(join(cache, "broken.client.mjs"), "const = ;\n", "utf8"); + writeFileSync(join(cache, "broken.d.ts"), "type = ;\n", "utf8"); + try { + const lint = Bun.spawnSync( + [ + "bunx", + "eslint", + "--no-warn-ignored", + join(cache, "broken.client.mjs"), + join(cache, "broken.d.ts"), + ], + { cwd: root }, + ); + expect(lint.exitCode).toBe(0); + } finally { + rmSync(join(root, "packages", "dev-server", "test", ".tmp-cache-ignore"), { + recursive: true, + force: true, + }); + } +}); diff --git a/packages/ui/test/ui.test.ts b/packages/ui/test/ui.test.ts index 26b15608..2ff76396 100644 --- a/packages/ui/test/ui.test.ts +++ b/packages/ui/test/ui.test.ts @@ -28,6 +28,7 @@ test("bundled UI assets are discoverable and readable", () => { test("global UI CSS stays below its migration ratchet", () => { expect(gzipSync(new TextEncoder().encode(uiCss())).length).toBeLessThanOrEqual(12_672); + expect(uiCss()).not.toContain(".wire-switch"); }); test("every bundled component carries local styles", () => { diff --git a/packages/ui/ui.css b/packages/ui/ui.css index 65e401f2..6ec9d7e7 100644 --- a/packages/ui/ui.css +++ b/packages/ui/ui.css @@ -609,51 +609,6 @@ background-repeat: no-repeat; padding-right: 2rem; } -/* --- Switch --------------------------------------------------------------- */ -.wire-switch { - display: inline-flex; - align-items: center; - gap: 0.5rem; - cursor: pointer; -} -.wire-switch__input { - position: absolute; - opacity: 0; - width: 0; - height: 0; -} -.wire-switch__track { - position: relative; - width: 2.25rem; - height: 1.25rem; - border-radius: 999px; - background: var(--wire-color-border); - transition: background 0.15s ease; - flex: none; -} -.wire-switch__thumb { - position: absolute; - top: 2px; - left: 2px; - width: calc(1.25rem - 4px); - height: calc(1.25rem - 4px); - border-radius: 999px; - background: #fff; - transition: transform 0.15s ease; -} -.wire-switch__input:checked + .wire-switch__track { - background: var(--wire-color-primary); -} -.wire-switch__input:checked + .wire-switch__track .wire-switch__thumb { - transform: translateX(1rem); -} -.wire-switch__input:focus-visible + .wire-switch__track { - outline: 2px solid var(--wire-color-primary); - outline-offset: 2px; -} -.wire-switch__label { - color: var(--wire-color-text); -} /* --- Progress ------------------------------------------------------------- */ .wire-progress { appearance: none; diff --git a/tsconfig.json b/tsconfig.json index d902e4b1..bd5dda0a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -138,6 +138,7 @@ "dist", "**/dist", "**/.wrnexus", + "**/.wrnexus-*", "focus-shims.d.ts", "tsconfig.focus.json", "**/focus-shims.d.ts",