Files
Danijel Martinek b10ccba927 feat(scripts): add evaluate-library skill + supporting files
Adds the /evaluate-library skill runbook at .claude/skills/evaluate-library/
with SKILL.md (8-filter + 3-prompt protocol, collect-cheap-skip-expensive
ordering, trace-write step, skip sentinel), POLICY.md (ADR-022 summary
≤2 pages), TRACE-TEMPLATE.md (complete YAML frontmatter + 11 headings in
order), and EXAMPLES/ with one approved (clsx) and one rejected
(trpc-to-openapi, named-consumer: fail) worked trace.

Updates session-start.sh to surface the skill in session pointers.
The skill is auto-registered by the harness on SKILL.md creation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 05:45:43 +00:00

92 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
package: clsx
version: "^2.1.1"
tier: feature
decision: approved
date: 2026-05-14
deciders: [danijel, claude-sonnet-4-6]
adr: null
filter-results:
license: MIT
types: native
maintenance: active
boundary-fit: pass
shadow-check: pass
eu-residency: n/a
cve-scan: clean
named-consumer: pass
verification-commands:
- node -e "const p = JSON.parse(require('fs').readFileSync('./node_modules/clsx/package.json','utf8')); console.log(p.license)"
- ls node_modules/clsx/dist/clsx.d.ts
- npm view clsx time.modified
- pnpm audit --audit-level=moderate
accepted-cves: []
---
## Filter: license
<!-- Result: MIT -->
`package.json` declares `"license": "MIT"`. MIT is on the allowlist. Pass.
## Filter: types
<!-- Result: native -->
`clsx` ships its own `.d.ts` declarations at `dist/clsx.d.ts`. No `@types/clsx` package needed.
The TypeScript surface covers the full public API (`ClassValue`, overloads). Pass.
## Filter: maintenance
<!-- Result: active -->
Last npm release: `2.1.1` published 2024-02-06 (15 months ago at evaluation date — within the 18-month threshold). GitHub shows open PR/issue activity within the last 3 months. The library is small, intentionally stable, and actively maintained. Pass.
## Filter: boundary-fit
<!-- Result: pass -->
`clsx` is a pure string-concatenation utility. It imports nothing from Node.js or browser globals; it has zero transitive dependencies. Adding it to `packages/navigation` as a `feature`-tagged package introduces no boundary violations under ADR-006 or ADR-010. It does not import `@sentry/*`, `@opentelemetry/*`, or any core-reserved vendor SDK. Pass.
## Filter: shadow-check
<!-- Result: pass -->
The locked workspace must-haves are: `zod`, `inversify`, `payload`, `@trpc/server`, `superjson`, `reflect-metadata`. None of these perform CSS class-name composition. There is no existing utility in the workspace for this purpose. Pass.
## Filter: eu-residency
<!-- Result: n/a -->
`clsx` is a pure in-process string utility. It performs no network calls, transmits no user data, and has no SaaS endpoint. EU residency filter does not apply.
## Filter: cve-scan
<!-- Result: clean -->
`pnpm audit --audit-level=moderate` returns 0 vulnerabilities for `clsx@2.1.1` at evaluation time. No accepted advisories.
## Filter: named-consumer
<!-- Result: pass -->
Named consumer: `packages/navigation/src/ui/components/navigation-menu.tsx` — the `NavigationMenuLink` component must compute conditional class names for the active/inactive link state. Without `clsx` this is implemented as a ternary chain that becomes unreadable past three conditions. The component exists today; this is not a hypothetical future use case.
Secondary consumer: `packages/navigation/src/ui/components/mobile-nav.tsx` — open-state drawer overlay class computation. Both components are blocked on this adoption.
## Prompt: replaces
Replaces inline ternary chains like `` `base-class ${isActive ? 'active' : ''} ${isDisabled ? 'disabled' : ''}` ``. No library is being retired — this is a first-time adoption of a class-composition utility. No parallel adoption risk.
## Prompt: migration-cost-out
**Mechanical.** `clsx` is called only at the component leaf level. Removal means replacing `clsx(...)` calls with equivalent template-literal ternaries — a mechanical sed-style refactor bounded to the `packages/navigation/src/ui/` subtree. No data format dependencies, no vendor lock-in, no protocol coupling.
## Prompt: alternatives-considered
1. **`classnames`** — functional equivalent, MIT, widely used. Rejected in favour of `clsx` because `clsx` is the successor written by the same author with better TypeScript support and 2× faster benchmarks at comparable bundle size (330 B vs 440 B minzipped). `classnames` would also pass all eight filters; `clsx` is strictly preferable.
2. **Inline ternary chains (no library)** — the current approach. Adequate for one or two conditions; degrades rapidly past three. The `navigation-menu` component already has four conditional classes; this is the threshold where a utility library pays for itself. Rejected as the status quo.
3. **`tailwind-merge`** — superset of `clsx` that also de-duplicates conflicting Tailwind classes. Overkill for this use case (navigation components use a small, non-conflicting class set). Higher migration cost out (data-format dependency on Tailwind class semantics). Deferred.