Skip to content

Commit 9050e69

Browse files
authored
chore(tests): remove low-signal tests and consolidate the testing setup (#8295)
* chore(tests): remove low-signal tests and consolidate the testing setup * fix(tests): address review — shared disposable-DB guard, optional Redis suite, restored client-info wire contract
1 parent e6badaf commit 9050e69

4,421 files changed

Lines changed: 4648 additions & 438898 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/cleanup/SKILL.md‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: cleanup
3-
description: Run all code quality skills — effects, memo, callbacks, state, React Query, emcn design review, url-state, and comments — analyzing in parallel, then applying fixes sequentially
3+
description: Run all code quality skills — effects, memo, callbacks, state, React Query, emcn design review, url-state, comments, and test-audit — analyzing in parallel, then applying fixes sequentially
44
argument-hint: "[scope] [fix=true|false]"
55
---
66

@@ -16,9 +16,9 @@ User arguments: $ARGUMENTS
1616

1717
Parse `$ARGUMENTS` into `scope` and `fix`: extract the `fix=true|false` token wherever it appears in the string and strip it from `scope`; defaults are the current changes and `fix=true`. `fix` is consumed by Step 3 only — the passes below always run `fix=false`.
1818

19-
Spawn all eight passes concurrently as subagents in a **single message** (multiple Agent tool calls). Each runs its skill on the parsed `scope` with `fix=false` — analysis and proposals ONLY, no edits. Instruct each agent to return its findings as a structured list: for every proposed change, the file path, line range, a one-line description of the change, and the exact before/after so the orchestrator can apply it without re-deriving.
19+
Spawn all nine passes concurrently as subagents in a **single message** (multiple Agent tool calls). Each runs its skill on the parsed `scope` with `fix=false` — analysis and proposals ONLY, no edits. Instruct each agent to return its findings as a structured list: for every proposed change, the file path, line range, a one-line description of the change, and the exact before/after so the orchestrator can apply it without re-deriving.
2020

21-
Run these eight in parallel on the parsed `scope`:
21+
Run these nine in parallel on the parsed `scope`:
2222

2323
1. `/you-might-not-need-an-effect <scope> fix=false`
2424
2. `/you-might-not-need-a-memo <scope> fix=false`
@@ -28,22 +28,23 @@ Run these eight in parallel on the parsed `scope`:
2828
6. `/emcn-design-review <scope> fix=false`
2929
7. `/you-might-not-need-url-state <scope> fix=false`
3030
8. `/you-might-not-need-a-comment <scope> fix=false`
31+
9. `/test-audit audit <scope>` — read-only; only when the scope adds or changes test files (`*.test.ts(x)`, `*.integration.ts`, `e2e/**`). It applies the authoring gate to every new or changed test and proposes deleting the ones that fail it.
3132

3233
## Step 2 — Converge
3334

34-
Collect all findings into one list, **keeping each proposal tagged with the pass that produced it** — do NOT collapse a file's proposals into a single unlabeled patch, because Step 3 applies in pass order and needs those labels. Detect overlaps where two passes touch the same region (common: a state pass and an effect pass on the same block, or a memo and callback pass on the same component). Reconcile only genuine same-region conflicts, and drop proposals a sibling pass has made moot; a reconciled change inherits the pass label of whichever of its passes comes first in the Step 3 dependency order (effects → state → memo → callback → React Query → url-state → emcn → comments), so it is applied at the earliest safe point. Non-overlapping proposals stay as-is with their own labels. The output is a per-pass list of surviving changes, not a per-file patch.
35+
Collect all findings into one list, **keeping each proposal tagged with the pass that produced it** — do NOT collapse a file's proposals into a single unlabeled patch, because Step 3 applies in pass order and needs those labels. Detect overlaps where two passes touch the same region (common: a state pass and an effect pass on the same block, or a memo and callback pass on the same component). Reconcile only genuine same-region conflicts, and drop proposals a sibling pass has made moot; a reconciled change inherits the pass label of whichever of its passes comes first in the Step 3 dependency order (effects → state → memo → callback → React Query → url-state → emcn → comments → tests), so it is applied at the earliest safe point. Non-overlapping proposals stay as-is with their own labels. The output is a per-pass list of surviving changes, not a per-file patch.
3536

3637
## Step 3 — Sequential apply
3738

3839
If `fix=false`, skip this step — just report the proposals from Step 2.
3940

4041
Otherwise apply the surviving changes yourself (in the main context, not delegated), iterating **pass by pass** in this dependency order so earlier structural changes settle before later passes build on them:
4142

42-
1. effects → 2. state → 3. memo → 4. callback → 5. React Query → 6. url-state → 7. emcn design → 8. comments
43+
1. effects → 2. state → 3. memo → 4. callback → 5. React Query → 6. url-state → 7. emcn design → 8. comments → 9. tests
4344

4445
For each pass in turn, apply all of that pass's changes, then move to the next pass. A file touched by several passes is therefore edited once per pass, in this order — not once as a merged patch. This is what makes the ordering real: a single merged-per-file patch would collapse all passes into one edit and lose it.
4546

46-
Comments apply last, on purpose: that pass operates on whatever the earlier structural passes settled the code into, so it never edits lines a sibling pass is about to delete or rewrite.
47+
Comments apply after every structural pass, on purpose: that pass operates on whatever the earlier passes settled the code into, so it never edits lines a sibling pass is about to delete or rewrite. Tests apply last because they only touch test files; in Step 2, drop any other pass's proposal on a test file the tests pass deletes.
4748

4849
**Treat every Step 1 proposal as snapshot-relative, not authoritative.** All passes analyzed the *original* files in parallel, so a proposal's line ranges and before/after text describe the code as it was *before* any edits — once an earlier pass has run, a later pass's snippet may no longer match. So for each change, before applying:
4950

@@ -55,7 +56,7 @@ After all edits, run `bun run lint:check` (it runs `turbo run lint:check` across
5556

5657
## Step 4 — Summary
5758

58-
Output a summary across all eight passes: what each found, what was applied vs. skipped-as-redundant, and any proposals that need a human decision.
59+
Output a summary across all passes that ran: what each found, what was applied vs. skipped-as-redundant, and any proposals that need a human decision.
5960

6061
## Boundary findings
6162

‎.agents/skills/ship/SKILL.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ When the user runs `/ship`:
3030
- Types: `fix`, `feat`, `improvement`, `chore`
3131
- Scope: short identifier (e.g., `undo-redo`, `api`, `ui`)
3232
- Keep it concise
33-
4. **Run the cleanup pass** — only if the diff modifies UI code (any `.tsx` file, or anything under `apps/sim/components/`, `apps/sim/hooks/`, or `apps/sim/stores/`): `/cleanup`
34-
- `/cleanup` fans out the React/UI passes (effects, memo, callbacks, state, React Query, emcn, url-state) plus the comment pass; skip it when no UI was touched. When it runs, it applies fixes so they land in this commit.
33+
4. **Run the cleanup and test gates**
34+
- If the diff modifies UI code (any non-test `.tsx` file, or anything under `apps/sim/components/`, `apps/sim/hooks/`, or `apps/sim/stores/`), run `/cleanup`. It fans out the React/UI passes (effects, memo, callbacks, state, React Query, emcn, url-state), the comment pass, and the test-audit pass, and applies fixes so they land in this commit.
35+
- Otherwise, if the diff adds or changes tests (`*.test.ts(x)`, `*.integration.ts`, `e2e/**`), run `/test-audit audit <changed test files>` on its own. Every new or changed test must pass the authoring gate; delete the ones that don't rather than shipping them.
3536
5. **Run migration safety** — only if the diff touches `packages/db/migrations/**` or `packages/db/schema.ts`:
3637
- Run `/db-migrate` to review the migration for zero-downtime safety (expand/contract phasing, backward-compatibility with the deployed app version).
3738
- `bun run check:migrations origin/staging` must pass (staging is the PR base). Do not silence a flagged statement with a `-- migration-safe:` annotation unless `/db-migrate` confirmed the old code no longer depends on it; otherwise split the destructive change into a later deploy.
@@ -143,7 +144,7 @@ Tested manually (or describe testing)
143144
## Checklist
144145
- [x] Code follows project style guidelines
145146
- [x] Self-reviewed my changes
146-
- [ ] Tests added/updated and passing
147+
- [ ] Tests added/updated and passing (new tests pass the `test-audit` authoring gate)
147148
- [x] No new warnings introduced
148149
- [x] I confirm that I have read and agree to the terms outlined in the [Contributor License Agreement (CLA)](./CONTRIBUTING.md#contributor-license-agreement-cla)
149150
```

‎.agents/skills/test-audit/SKILL.md‎

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
name: test-audit
3+
description: Invoke whenever writing, changing, reviewing, or sweeping tests. Authoring gate for new tests, plus an audit workflow for low-value, implementation-coupled, or duplicative tests and the test-only production seams they demand.
4+
argument-hint: "[author | audit <path> | campaign <subsystem>]"
5+
---
6+
7+
# Test Audit
8+
9+
Three modes, one value bar. **Authoring** gates every new or changed test at write time.
10+
**Audit** runs a focused sweep of existing tests that re-assert source, duplicate stronger proof,
11+
couple to implementation, or keep test-only production seams alive. **Campaign** prunes one
12+
subsystem's whole test surface in parallel lanes. Optimize for confidence, not deletion count —
13+
but a test that cannot name the bug it catches is cost, not coverage.
14+
15+
Read `.claude/rules/sim-testing.md` first: it defines the test layers, file naming, and the
16+
mechanics (global mocks, `@sim/testing`, performance rules).
17+
18+
## The three rules
19+
20+
1. **Never write unit tests after you write code.** A test written to describe code that already
21+
exists restates the implementation, passes on the first run, and proves nothing. If the change
22+
needs proof, prove it end to end.
23+
2. **Prefer E2E tests; use them to verify complex features.** Exercise the real boundary — real
24+
Postgres/Redis (`*.integration.ts`), a running app over real HTTP, or the packaged desktop app
25+
(Playwright). Every E2E run ends with a **verifiable, repeatable artifact**: a JSON report of
26+
checks with pass/fail and durations, an HTTP status log, a trace, or a screenshot, written to a
27+
path the caller controls (`<SUITE>_REPORT_PATH`) and uploaded by CI on failure.
28+
`apps/sim/scripts/test-scim-e2e.ts` is the reference shape.
29+
3. **If you must test a system in isolation, write the failure modes down first, then write the
30+
code.** List every way the unit can fail (bad input, boundary, concurrency, partial failure,
31+
permission denial, resource cap). Each listed mode becomes one test that fails before the code
32+
exists. A mode you cannot list is not a test you should write.
33+
34+
## Authoring gate
35+
36+
Before adding any test, answer all four. A missing answer means do not add it.
37+
38+
1. What observable behavior, invariant, or independent contract does it protect?
39+
2. What credible regression makes it fail?
40+
3. Why does existing coverage not already catch that failure? Type-check, `next build`,
41+
`bun run check:audits`, and the integration/E2E suites are coverage too. Each contract has one
42+
primary owner at the strongest boundary; another layer needs its own distinct risk. Prefer
43+
extending an existing table-driven case over a near-duplicate test.
44+
4. Does it need a production seam (export, flag, wrapper, injection hook) that no production
45+
caller needs? If yes, test at the real boundary instead.
46+
47+
Then check it against every junk pattern below. A match fails the gate unless the retention bar
48+
names the contract it independently guards. A test that would break under behavior-preserving
49+
refactoring asserts implementation, not behavior.
50+
51+
**Regression tests** must fail on the pre-fix code for the intended reason. Revert each guard of
52+
the fix separately and watch the test named for that guard go red, then restore. A regression
53+
test that never demonstrably failed proves the mock, not the fix. One regression at the owner
54+
boundary covers the bug; do not replay it at every layer it crosses.
55+
56+
## Junk patterns
57+
58+
- assertion-free or `toBeDefined()`-only tests; "renders without crashing";
59+
- restating declarations: block/tool/trigger/provider config (subBlock ids, params, outputs, URL
60+
templates, header maps), constant tables, registries, enums, export lists — type-check and
61+
`check:audits` own these;
62+
- route/handler tests that mock every collaborator and assert `toHaveBeenCalledWith` on the mocks,
63+
or re-assert a mock's canned return;
64+
- mocks that implement the asserted behavior, or one mock standing in for different APIs;
65+
- Zod contract tests proving a schema accepts a valid object or rejects an obviously invalid one;
66+
- React tests of text, class names, aria presence, snapshots, "calls onClick";
67+
- hook tests asserting query keys or fetch URLs; store tests of trivial setters;
68+
- tests of test infrastructure (mocks, factories, builders testing themselves);
69+
- source-text or import greps (`readFileSync(src)` + `toContain`);
70+
- expected values produced by the helper under test;
71+
- duplicate invocations of the same contract, or provider-local replays of a shared helper;
72+
- fixtures that supply the ordering, receipt, or callback the owner should produce;
73+
- negative controls that pass for an unrelated reason (a different guard short-circuits first);
74+
- names or fixtures that promise more than the input exercises;
75+
- dead production code or exports whose only callers are tests.
76+
77+
## Retention bar
78+
79+
Keep a test when it independently enforces one of:
80+
81+
- **security** — authn/authz denial, tenant/workspace isolation, SSRF/URL validation, secret
82+
redaction, encryption, signature verification, path traversal, injection, rate limits;
83+
- **money and data integrity** — billing/usage math, metering, quotas, idempotency, migrations,
84+
persistence semantics, concurrency/locking/leases, outbox, retries;
85+
- **executor semantics** — DAG traversal, loops/parallels, conditions/routers, reference
86+
resolution, streaming, pause/resume, run-from-block, cancellation;
87+
- **real algorithms with edge cases** — chunkers, parsers, query builders, cron, diff/merge,
88+
pagination, encoding, date math, ranking;
89+
- **cross-process wire contracts** — realtime protocol, desktop bridge/IPC, CLI/SDK wire, provider
90+
webhooks, MCP — that type-check cannot see;
91+
- **a regression with a credible repeat**, shown red on the pre-fix code.
92+
93+
Also keep call ordering when order is observable, and a source inspection when it is the cheapest
94+
independent guard of a user-facing byte, key, or path. A retained test that fails on the baseline
95+
is a possible product bug: reproduce it and fix the owner rather than deleting it. Static or slow
96+
is not a deletion reason.
97+
98+
## Audit mode
99+
100+
Keep discovery read-only and report evidence before editing. Before judging a candidate, read the
101+
complete test and its production owner, callers, sibling implementations, overlapping tests, CI
102+
routing (CI discovers `*.integration.ts` by glob; `.github/workflows/*.yml` names a few scripts and
103+
files by path), and relevant history
104+
(`git log --format='%h %s' -5 -- <file>`).
105+
106+
Record for every deletion candidate: the test and location; the failure it can actually detect;
107+
non-test callers of the seam it covers; the stronger remaining proof (or why none is needed); the
108+
production or test-support code its deletion unlocks; and the focused validation command.
109+
110+
**Edit shape.** One coherent owner-boundary batch per PR. When pruning inside a file, also delete
111+
now-unused imports, mocks, fixtures, and helpers. Delete test-only exports and dead production
112+
paths instead of preserving aliases (`rg -n '<name>' --glob '!**/*.test.*'` must show no other
113+
reference, including string and dynamic-import references; never delete route files, registry
114+
entries, or generated files). Prefer net-negative production LOC. Do not add replacement tests
115+
that restate the same implementation.
116+
117+
## Campaign mode
118+
119+
For a whole subsystem or the whole repo:
120+
121+
1. Partition test files into lanes of ~150–350 files by owning directory, and list the protected
122+
set (every `*.integration.ts`, `*.live.test.ts`, `__integration__/**`, `apps/desktop/e2e/**`,
123+
and every path named in `.github/workflows/*.yml`).
124+
2. Give each lane its own git worktree and branch (`git worktree add -b <branch> <path> <base>`,
125+
then `bun install --frozen-lockfile` inside it). Lanes never share a checkout, never symlink
126+
`node_modules`, and never use `git stash` — the stash is shared across worktrees.
127+
3. Each lane commits once and writes a report: counts, categories removed with examples, notable
128+
keeps and why, production seams removed with grep evidence, and the commands it ran.
129+
4. Merge lane branches, then sweep orphaned shared test support (`packages/testing/**`, fixtures,
130+
helpers) that no remaining test imports.
131+
132+
## Validation
133+
134+
Never edit source or tests while Vitest is running in the same checkout.
135+
136+
1. Run the touched and sibling test files. From `apps/sim`:
137+
`../../node_modules/.bin/vitest run <paths>` (never `bunx vitest`, which fetches a different
138+
Vitest). Other workspaces: run from the workspace directory. Never pipe the runner through
139+
`grep`/`tail` where the pipe hides its exit code.
140+
2. If production code changed: `bun run type-check` in that workspace.
141+
3. `bun run check:audits` from the repo root (some audits list test files by path).
142+
4. `bun run lint`, then `git diff --check`.
143+
5. Report `git diff --shortstat` with production and test changes counted separately.
144+
145+
## Handoff
146+
147+
Report the categories removed, production simplifications, retained false positives and why they
148+
stay, the validation actually run, production vs test LOC, and named follow-ups.

0 commit comments

Comments
 (0)