DimitriGilbert / DimitriGilbert/workspace-welcome
Test & quality alignment plan
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 2
Description
# Test & Quality Alignment Plan — workspace-welcome
_Revised 2026-09-05: CI removed by owner decision — quality gates are local commands run by the owner/agents; no GitHub Actions._
- **Project**: `workspace-welcome` (`DimitriGilbert/workspace-welcome`)
- **Date**: 2026-09-05
- **Generated by the fleet test-alignment initiative** (wave 1, item 4)
- **Audit report**: [`../.test-alignment-audit/reports/workspace-welcome.md`](../.test-alignment-audit/reports/workspace-welcome.md)
- **Fleet synthesis & decisions**: [`../.test-alignment-audit/synthesis-decisions.md`](../.test-alignment-audit/synthesis-decisions.md)
- **Execution context**: branch `redesign/dashboard-concepts` carries uncommitted WIP. This plan was produced read-only; execution must be coordinated with the owner (see Risks).
---
## 1. Current state (grounded, 2026-09-05)
- pnpm@10.33.4 workspaces monorepo: `apps/web`, `apps/docs`, `packages/api`, `packages/ui`, `packages/env`, `packages/config`. **No `turbo.json`** — the task graph is plain `pnpm -r`.
- **Zero TS tests.** Only verification today: strict `tsc --noEmit` per package (`pnpm run check-types` fans out via `pnpm -r`), the 679-line bash install E2E (`pnpm run test:install`, systemd container, `--local` mode), and the release boot smoke test inside `scripts/release.sh` (HTTP 200 + HTML on port 39771 before packing).
- **No CI**: `.github/` does not exist. No lint, no formatter, no coverage, no Renovate.
- Unused scaffold test deps in `apps/web/package.json` devDeps: `@testing-library/dom`, `@testing-library/react`, `jsdom` — no runner, no imports.
- Rich pure-logic surface in `packages/api/src/lib/` (~5.6k LOC): `report-staleness.ts` (59 LOC, deliberately dependency-free), `scaffold-options.ts` (779 LOC, imports only `zod`), `detect.ts` (`parseRemote` is pure), `snitch.ts` (`REPORT_KEY_RE`, `resolveSnitchCommand`, `buildReportCommand`, `reportKey`, `reportHtmlPath`), plus fixture-testable `git.ts`, `scan.ts`, `report-export.ts`, `agents-md/`.
- `packages/api/tsconfig.check.json` includes `src/**/*.ts` — colocated `*.test.ts` files are typechecked automatically, with zero tsconfig changes. Base tsconfig has `types: ["node"]`, so tests must import from `"vitest"` explicitly (no globals) — which is also the cleaner style.
- `.gitignore` already ignores `coverage/` and `/release/` — new test tooling cannot dirty the tree that `scripts/release.sh`'s clean-tree guard checks.
---
## 2. Adopted decisions (D1–D7, adapted to this stack)
| Decision | Adoption here |
|---|---|
| **D1 — runner & layout** | **vitest v4 line**, `node` environment (no jsdom anywhere in v1). Tests colocated as `*.test.ts` next to source. Single `vitest.config.ts` in `packages/api` (the only testable package today — the LearnABee multi-project pattern is for ≥6 testable packages; revisit if `apps/web` gains component tests). Root-level headless `pnpm test`. **No `passWithNoTests`.** Versions pinned in the `pnpm-workspace.yaml` catalog per repo convention. |
| **D2 — coverage** | `@vitest/coverage-v8`, reporters `text + json + html`, `include` scoped to `packages/api/src/**`, exclude generated (`routeTree.gen.ts` lives in apps, not in scope). This repo starts at **state 3** (zero tests): coverage reported, **no thresholds** until seeds land (Phase 1); then transition to state 2 — thresholds at measured−5, ratchet +5 when green (Phase 4). Never lower a threshold. |
| **D3 — lint/format** | ESLint 9 flat config (`eslint.config.js`, ESM — no extra loader dep) + `typescript-eslint` ^8 `recommendedTypeChecked` via projectService + `eslint-plugin-react-hooks` for `apps/web`. **`import/order` enabled** — this repo's AGENTS.md import-ordering convention becomes a machine rule (explicitly named in D3 for this repo). Ignores: `dist`, `**/routeTree.gen.ts`, `release/`, `tmp/`, `.review/`, `.zcode/`. **Prettier deferred** in v1 — stated here and in AGENTS.md rather than pretended (allowed by D3). |
| **D4 — quality metrics** | `knip` + `jscpd` **report-only** (no baseline yet — D4/§5 forbid gating on unmeasured numbers), surfaced as local reports from on-demand scripts. CRAP/complexity deferred until coverage exists (Phase 4 baseline → CRAP becomes possible later). knip is "recommended" here (this repo ships release tarballs, not npm packages). |
| **D5 — no CI by design (owner decision 2026-09-05)** | **No GitHub Actions, no reusable-workflow caller, no local workflow.** The earlier "thin `ts-ci.yml` caller + a scheduled install-E2E workflow" plan is dropped entirely. Enforcement = the root-level headless verification entrypoint (`pnpm run verify`: check-types → lint → test → build, composed in Phase 3) run by the owner and by agents; the plan's phase validation gates are run by implementer/validator agents before any phase is declared done. **The install E2E and release boot test stay release-tier gates** (per this repo's delta: "they're donor-grade") — run on demand as `pnpm run test:install --local` before releases, never part of the default gate. |
| **D6 — shared config** | Local configs in v1, written in the `@dg/config` preset shape (tsconfig already matches the fleet flag set byte-for-byte; vitest config follows the `createTestConfig` node-env shape). Converge onto `@dg/config`/shared vitest preset **when it publishes**, at the next natural touchpoint — not a churn PR. |
| **D7 — hooks** | No hooks in v1. AGENTS.md will state: "the headless local verification command (`pnpm run verify`) is the quality gate, run by the owner/agents; hooks are local convenience." Optional lefthook pre-push (typecheck + affected tests) listed as a non-blocking nice-to-have. |
**Deviations from the synthesis (reality wins, per brief):**
1. The synthesis table lists this repo as "pnpm/**turbo**" and the fleet constants cite a dangling `lint` task in `turbo.json`. **Reality: no `turbo.json` exists** — the task graph is `pnpm -r`. DoD item 4 ("dead lint task implemented or deleted") therefore becomes "create the lint script" — there is nothing to delete.
2. Delta says "wire the scaffold's unused RTL/jsdom deps **or drop them**". Reality: the UI is mid-redesign on this WIP branch; wiring component tests now would test a moving target with no runner to catch regressions. **Decision: drop them** (Phase 5), satisfying DoD item 6; re-add via catalog only when component tests actually land.
3. D1's "every repo gets a one-command test entry" is satisfied by `pnpm test` (root) added in Phase 0, coexisting with the existing `test:install` (kept verbatim — it is donor-grade and load-bearing for releases).
---
## 3. Subagent execution model (per `subagent-orchestration` skill)
An orchestrator runs the whole plan after one approval; it never writes code itself. Per phase:
1. **Implementer** dispatch: receives the COMPLETE phase requirements below, the file list, the NO-SLOP policy verbatim, and the instruction to run all gatekeeping commands BEFORE reporting done. Role boundary: creates/modifies files only, never validates.
2. **Validator** dispatch (different agent): must ACTUALLY READ every created/modified file, verify each requirement with file paths + line numbers, enforce NO-SLOP (no `any`, no TODO/FIXME, no unused imports, `import type` under `verbatimModuleSyntax`, imports ordered per AGENTS.md: external/workspace first, blank line, local; no dev server started), then run the validation gate. Never modifies code.
3. **Fixer** dispatch on FAIL: receives ALL validator errors at once, fixes all, runs gatekeeping; validator re-runs. Max 3 attempts, then HALT and report.
4. Multi-sub-phase phases (Phase 1): one implementer → one validator **per sub-phase, immediately after each**, then a mandatory **phase-wide validator** reading all sub-phase code together (integration, shared types, import coherence).
**NO-SLOP policy (pasted into every implementer/fixer dispatch, enforced by every validator):** NO `any`, `as any`, `: any` anywhere; NO placeholder code, NO `// TODO`, NO `// FIXME`; NO unused imports/variables; no `console.log` hacks, no `void` hacks; `import type` for type-only imports; external imports first, blank line, then local imports; do not start dev servers; only run scripts that exist in package.json.
**Universal gatekeeping commands (every implementer and fixer, every phase):** `pnpm run check-types` (mandatory per AGENTS.md) plus the phase's own gate.
---
## 4. Phased plan
### Phase 0 — Vitest scaffold + first pure tests (effort: M)
**Goal**: a real, headless, root-invokable unit-test tier exists and is green — no empty-runner moment (config and first tests land together; `passWithNoTests` stays off).
**Tasks (implementer):**
1. `pnpm-workspace.yaml`: add catalog entries (D1: v4 line, pinned via catalog):
```yaml
vitest: ^4.1.0
"@vitest/coverage-v8": ^4.1.0
```
2. `packages/api/package.json`: add `"vitest": "catalog:"` and `"@vitest/coverage-v8": "catalog:"` to devDependencies; add scripts `"test": "vitest run"`, `"test:coverage": "vitest run --coverage"`. Then `pnpm install` (frozen-lockfile-compatible result committed via the lockfile update).
3. Create `packages/api/vitest.config.ts`: `environment: "node"`, explicit imports from `vitest/config`; `coverage` block: provider `v8`, reporters `["text", "json", "html"]`, `include: ["src/**/*.ts"]`, `exclude` tests + `src/**/*.d.ts`. **No `passWithNoTests`.** No globals — tests import `{ describe, it, expect }` from `"vitest"`.
4. Root `package.json`: add `"test": "pnpm -r test"` (headless; `pnpm -r` skips packages without a test script) and `"test:coverage": "pnpm --filter @workspace-welcome/api test:coverage"`.
5. First tests (colocated):
- `packages/api/src/lib/report-staleness.test.ts` — full behavioral coverage of the 59-LOC dependency-free module: staleness at exactly 24h (boundary, `>=`), never stale when either timestamp is null/unparseable, no absolute-age term (old report on untouched project stays fresh).
- `packages/api/src/lib/scaffold-options.test.ts` — start the suite: defaults, required-field validation errors, one representative full-options parse (expanded in Phase 1a).
6. `AGENTS.md`: add a "Testing" section — runner (vitest, node env), commands (`pnpm test`, `pnpm run test:coverage`), locations (colocated `*.test.ts` in `packages/api/src`), coverage status (measured, no thresholds yet), and the D7 sentence: the headless local verification command (`pnpm run verify`) is the quality gate, run by the owner/agents; hooks are local convenience. Existing `test:install` line stays and is labeled as the release-tier E2E.
**Files**: `pnpm-workspace.yaml`, `package.json`, `packages/api/package.json`, `packages/api/vitest.config.ts` (new), 2 test files (new), `AGENTS.md`, `pnpm-lock.yaml` (regenerated by install).
**Validation gate (validator)**: `pnpm run check-types` && `pnpm test` && `pnpm run test:coverage` all pass; coverage report shows measured (non-zero) numbers for `report-staleness.ts` at ~100%; no `passWithNoTests` anywhere; no changes under `scripts/`.
**Role**: implementer → validator (+ fixer loop).
---
### Phase 1 — Seed the pure core of `packages/api/src/lib` (effort: L — three sub-phases)
**Goal**: the audit's P1 ("pure, highly testable logic untested") is closed for the highest-value modules; coverage baseline recorded (D2 state 3 → ready for ratchet).
**Sub-phase 1a — `scaffold-options.ts` (M).** The 779-LOC zod-only module: full suite over option parsing — defaults application, enum/coerce validation failures (assert the error, not just rejection), flag interactions/conflicts, round-trip of the bts.jsonc-relevant shapes (use `packages/api/src/lib/agents-md/bts-jsonc.ts` fixtures if helpful). File: `packages/api/src/lib/scaffold-options.test.ts`.
**Sub-phase 1b — `snitch.ts` pure surface + `detect.ts` parsing (M).**
- `packages/api/src/lib/snitch.test.ts`: `REPORT_KEY_RE` (accept/reject matrix), `reportKey` (determinism, kind/period discrimination, 8-hex hash suffix), `resolveSnitchCommand` and `buildReportCommand` across settings permutations (path with spaces, configured override, default resolution — mock `homedir` via `vi.mock("node:os")` or inject `XDG`-style env; prefer env, no snapshots), `reportHtmlPath`, `cachedReportJob` (use `vi.useFakeTimers()` for TTL/expiry).
- `packages/api/src/lib/detect.test.ts`: `parseRemote` matrix (ssh/https/git URLs, `git@host:org/repo.git`, trailing `.git`, invalid inputs → null); `detectStack` + `readManifestSlice` against temp-dir fixtures written with `fs.mkdtemp` (package.json / Cargo.toml / pyproject permutations).
**Sub-phase 1c — `git.ts` against real temp repositories (M).** No mocks, no prod refactor: fixtures create real git repos in `mkdtemp` dirs (`git init -b main`, commits, branches, a local-path remote, detached HEAD, dirty worktree). Cover `gitStatusHash` (deterministic, changes on commit), `gitInspect` (clean/dirty/branch/detached states), `listBranches` (current, `parseDecorations` behavior through the public API), `switchSafety` (clean → ok; dirty/uncommitted → blocked). Git is available in CI and dev hosts; tests skip-with-explicit-failure-message only if the binary is absent (do not silently pass). File: `packages/api/src/lib/git.test.ts`.
**Files**: 4–5 new `*.test.ts` files (colocated); possibly a tiny `packages/api/src/lib/test-fixtures.ts` helper shared by 1c (temp-repo builder) — created only if duplication would otherwise exceed 3 call sites.
**Validation gate (validator, per sub-phase)**: `pnpm run check-types` && `pnpm test` pass; new suites assert behavior (no tautologies); no production source files modified (this phase is tests-only — flag any prod edit as a violation). **Phase-wide validator** then: reads all Phase-1 suites together, checks fixture-helper coherence, runs `pnpm run test:coverage` and **records the measured baseline in AGENTS.md's Testing section** (package `@workspace-welcome/api`: lines/branches %) — the D2 state-3 artifact that Phase 4's threshold builds on.
**Role**: 3× (implementer → validator), then phase-wide validator (+ fixer loops).
---
### Phase 2 — ESLint (effort: M)
**Goal**: DoD item 4 — lint installed, zero errors, machine-enforced; the AGENTS.md import-order convention becomes a rule.
**Tasks (implementer):**
1. Catalog entries in `pnpm-workspace.yaml`: `eslint: ^9`, `"@eslint/js": ^9`, `typescript-eslint: ^8`, `eslint-plugin-react-hooks: ^6`, `globals: ^16`. Root `package.json` devDeps reference `catalog:`; add script `"lint": "eslint ."`. `pnpm install`.
2. Create root `eslint.config.js` (ESM — repo is `"type": "module"`): `@eslint/js` recommended + `typescript-eslint` `recommendedTypeChecked` with `projectService: true` (monorepo-wide); `eslint-plugin-react-hooks` flat config applied to `apps/**/*.{ts,tsx}`; `import/order` enabled with `groups: ["builtin", "external", "workspace"→ via pattern "@workspace-welcome/*", ...]`, `newlines-between: "always"` — matching AGENTS.md exactly; `@typescript-eslint/no-floating-promises` on (the fleet's most-requested rule per D3); **no rule suppressions to make files pass — fix the violations** (expected hotspots: floating promises in `packages/api/src/lib/*.ts` spawn call sites).
3. Ignores: `**/dist/`, `**/routeTree.gen.ts`, `release/`, `tmp/`, `.review/`, `.zcode/`, `node_modules/`.
4. Note in AGENTS.md (Testing/quality section): Prettier intentionally deferred in v1 (D3-compliant honesty clause).
**Files**: `pnpm-workspace.yaml`, root `package.json`, `eslint.config.js` (new), `AGENTS.md`, source files touched only to fix real violations, `pnpm-lock.yaml`.
**Validation gate (validator)**: `pnpm run check-types` && `pnpm run lint` (zero errors, zero warnings-as-errors) && `pnpm test`. Validator must read `eslint.config.js` line-by-line and verify no blanket `off` switches of type-safety rules were used to reach green.
**Role**: implementer → validator (+ fixer loop).
---
### Phase 3 — Gate composition + dependency hygiene (effort: M)
**Goal**: DoD items 2 and 7 — one headless command gates typecheck + lint + test + build locally; the install E2E is an on-demand release-tier command instead of a remembered one; Renovate present.
**Tasks (implementer):**
1. Root `package.json`: add `"verify": "pnpm run check-types && pnpm run lint && pnpm test && pnpm run build"` — the headless verification entrypoint (D5). The install E2E stays **out** of the default gate (privileged containers, long runtime): it remains the on-demand release-tier command `pnpm run test:install --local`, run by the owner/agents before releases. **`scripts/release.sh` and `scripts/test-install.sh` are NOT modified.**
2. `renovate.json` (new): `{ "extends": ["local>DimitriGilbert"] }` (DoD item 7; a Renovate preset is a non-workflow artifact, unaffected by the no-CI decision). No `"latest"` deps exist in this repo (catalog pins everywhere) — verify and state that in the PR description.
3. Coverage HTML stays local and git-ignored — no artifact uploads (D5). No workflow file is created anywhere; nothing depends on `DimitriGilbert/.github`.
**Files**: `package.json`, `renovate.json` (new).
**Validation gate (validator)**: `pnpm run verify` exits 0 locally and every sub-command exists in `package.json` scripts; fail-fast proven once (validator introduces a failing assertion in a scratch copy and confirms `verify` exits non-zero at the failing step — never on the real tree); the implementer/validator agents record the green output before the phase is declared done (D5); `renovate.json` parses as JSON; no workflow file exists.
**Role**: implementer → validator (+ fixer loop).
---
### Phase 4 — Coverage ratchet + report-only quality metrics (effort: S)
**Goal**: DoD items 3 and 8 — thresholds exist only now that a baseline exists; knip + jscpd report-only local reports.
**Tasks (implementer):**
1. In `packages/api/vitest.config.ts`: set `coverage.thresholds.lines` (and `branches`) to the Phase-1 measured baseline **minus 5** (D2 state-2 entry). Commit; ratchet +5 whenever green, on any PR touching the package; never lower.
2. Catalog: `knip: ^5`, `jscpd: ^4.2`. Root script `"quality:report": "knip && jscpd"`-equivalent driven by config files: `knip.json` (entry points: `packages/api/src/index.ts`, `apps/web/src/*` via the TanStack Start plugin conventions, `packages/api/src/lib/agents-md/cli.ts`; ignore `routeTree.gen.ts`) and `.jscpd.json` (launch-mommy canonical config: `minLines: 8, minTokens: 80`, exclude `**/*.test.ts`, `**/dist/**`, generated dirs, **`exitCode: 0`** — report-only until a baseline exists, per D4).
3. The quality report runs on demand via `pnpm run quality:report`, producing local (git-ignored) reports; the owner/agents run it on demand or during a periodic agent pass — no workflow, no schedule (D5).
**Files**: `packages/api/vitest.config.ts`, `pnpm-workspace.yaml`, root `package.json`, `knip.json` (new), `.jscpd.json` (new), `AGENTS.md` (baseline + ratchet policy), `pnpm-lock.yaml`.
**Validation gate (validator)**: `pnpm run check-types` && `pnpm test` (thresholds active and passing) && `pnpm run quality:report` runs to completion producing report output; `exitCode: 0` confirmed in `.jscpd.json` (no premature gate); thresholds match baseline−5 exactly.
**Role**: implementer → validator (+ fixer loop).
---
### Phase 5 — Cleanup, docs truth, convergence hooks (effort: S)
**Goal**: DoD items 5, 6, and the repo's delta item — no phantom docs, no dead test deps.
**Tasks (implementer):**
1. `apps/web/package.json`: remove `@testing-library/dom`, `@testing-library/react`, `jsdom` (DoD item 6: drop; per deviation 2). `pnpm install` to sync the lockfile. If any future component test lands, re-add via catalog entries deliberately.
2. Update `docs/research/workspace-welcome-architecture.md` §7 ("No ESLint config, no test runner, no CI in-repo. The gate is `check-types`.") to describe the new reality: vitest + coverage + thresholds, ESLint type-checked, the `verify` gate, install-E2E as an on-demand release-tier command.
3. Final `AGENTS.md` pass: Testing section matches reality exactly (runner, commands, locations, coverage + threshold numbers, the local gate statement per D7).
4. Optional, non-blocking (D7): committed `lefthook.yml` with pre-push = `pnpm run check-types` + affected tests; never required, never load-bearing. Skip if the owner prefers zero hooks.
5. Follow-up ticket (not this branch): converge `packages/config/tsconfig.base.json`, `vitest.config.ts`, and `eslint.config.js` onto `@dg/config` when it publishes (D6 adoption-at-touchpoint rule).
**Files**: `apps/web/package.json`, `docs/research/workspace-welcome-architecture.md`, `AGENTS.md`, optionally `lefthook.yml`, `pnpm-lock.yaml`.
**Validation gate (validator)**: `pnpm run check-types` && `pnpm run build` (substantial-change rule per AGENTS.md — the dep removal touches the app package) && `pnpm test` && `pnpm run lint`; `grep` confirms no lingering imports of the removed deps; docs statements verified against actual config files (validator greps each claim).
**Role**: implementer → validator (+ fixer loop).
---
## 5. Definition of Done — synthesis §3 checklist with current status
| # | DoD item | Status in this repo today | Closed by |
|---|---|---|---|
| 1 | Root-level headless test command, documented in AGENTS.md | Missing (no `test` script anywhere) | Phase 0 |
| 2 | Headless verification entrypoint running typecheck + test + lint in one local command; agent records green before a phase is done | Missing (no aggregate command) | Phase 3 |
| 3 | Coverage measured & reported; baseline recorded; thresholds only per D2 state; never lowered | Missing (`.gitignore` has coverage entries for tooling that doesn't exist) | Phase 0 (measure) → Phase 1 (baseline) → Phase 4 (thresholds) |
| 4 | Language-appropriate lint, zero errors, wired into the headless entrypoint; dead lint task implemented or deleted | Missing (no ESLint at all; no turbo.json here — nothing dangling to delete, deviation 1) | Phase 2 |
| 5 | AGENTS.md "Testing" section matches reality — no phantom docs | Missing (AGENTS.md has quality gates but no testing section; architecture doc §7 admits the gap) | Phase 0 (created) → Phase 5 (truth pass) |
| 6 | Dead scaffold test deps removed or used | **Violated today**: `@testing-library/dom`, `@testing-library/react`, `jsdom` unused in `apps/web` | Phase 5 (drop) |
| 7 | Renovate one-liner present; no `"latest"` deps | Half-met: catalog pins everything, no `"latest"` anywhere; no Renovate | Phase 3 |
| 8 | Quality-report script (knip + jscpd, + CRAP where coverage exists) runnable locally, report-only | Missing | Phase 4 (CRAP deferred until coverage mature) |
| 9 | No fake passes (no `passWithNoTests`, no echo-test, no tautologies) | Trivially met (no suite exists; the bash E2E and boot test are real) and stays met — `passWithNoTests` never enabled | All phases |
---
## 6. Risks & notes specific to this repo
- **Uncommitted WIP on `redesign/dashboard-concepts`** (including today's edits to `pnpm-workspace.yaml` and `pnpm-lock.yaml`). Execution must start only after the owner commits (or approves committing) the WIP; phases land as small, individually green commits on this branch. Per AGENTS.md: no stash/reset/clean, no commits or pushes unless the owner asks. All gate proof is local (D5): the agents run `pnpm run verify` and record the output, on any branch.
- **Release-pipeline coupling.** `scripts/release.sh` (clean-tree guard, boot test) and `scripts/test-install.sh` are load-bearing and donor-grade — **no phase modifies them**. New tooling stays clean-tree-safe because `.gitignore` already covers `coverage/` and `/release/`. `pnpm run test:install --local` internally calls `pnpm run release --dry-run`, so dependency additions (lockfile churn) must be verified against a dry-run before the next release.
- **Privileged-container E2E.** The install E2E needs docker/podman with systemd-as-PID-1; it stays an on-demand release-tier command run by the owner/agents before releases, never part of the default `verify` chain (delta: keep it a release-tier gate).
- **Typecheck scope.** `packages/api/tsconfig.check.json` includes `src/**/*.ts`, so all colocated tests are typechecked by the existing gate — no tsconfig edits needed; do not add test excludes. Base tsconfig `types: ["node"]` means no vitest globals — explicit imports only.
- **Catalog discipline.** All new devDeps enter via `pnpm-workspace.yaml` catalog + `catalog:` references (AGENTS.md rule); never a bare version pin in a package.json.
- **`import/order` lint rollout** may surface a large mechanical-fix diff across 278 files; keep it in Phase 2 (its own validator) so test phases stay reviewable. No `--fix-and-ignore`; every fix lands in the diff.
- **jsdom/RTL re-entry risk.** If someone re-adds component tests during the UI redesign, they must come with the D1 jsdom-env decision made explicitly (catalog entries + environment override), not by silently restoring the scaffold deps.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the linked audit report and the Phase 0 file list in this issue, then read AGENTS.md and the root and packages/api package manifests. Run pnpm run check-types to establish the current baseline. Done means the phased testing and quality plan is implemented, validated by its listed local commands, and coordinated with the owner.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- testing, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100