Use when running spectra Design Review, before /spectra-archive, or ad-hoc on changes touching paginated queries. Detects client-server schema mismatch. NOT for 一般 code review(走 review-rules)。
Scanned 9/5/2026
Install to Claude Code
npx -y skills add Charles5277/nuxt-supabase-starter --skill data-sanity --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Data Sanity?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/charles5277-data-sanity)More formats (shields.io, HTML) on the badges page.
---
name: data-sanity
description: "Use when running spectra Design Review, before /spectra-archive, or ad-hoc on changes touching paginated queries. Detects client-server schema mismatch. NOT for 一般 code review(走 review-rules)。"
effort: medium
metadata:
author: clade
version: "1.0"
permission_tier: read-only
---
<!-- 🔒 LOCKED — managed by clade · auto-generated by sync-to-cursor; edit source in .claude/ then re-run sync -->
`/data-sanity` — Layer C static data-shape audit.
Born from perno `app-status-badge-extraction`(2026-05-24): `attendance/amendments.vue` 用 `useEmployeeListQuery({ perPage: 200 })`,但 server schema 是 `perPage: z....max(100)` → API 400 → `employeeNameMap` empty → 員工 column 整列「-」。typecheck / lint / design review / verify:ui 全沒抓到,因為它是**資料形狀**問題,不是型別或視覺問題。
這是 clade 自有 skill(**不是** `/impeccable` 的 sub-command — impeccable 是第三方 npx-managed skill,clade 不擁有)。
## 何時跑
- **`/spectra-apply` Section 7 Design Review 期間**:對本 change 觸及的 paginated query + lookup-resolved column 跑一次。
- **`/spectra-archive` Step 0 之前**:archive gate 的 data-shape 防線。
- **Ad-hoc**:任何改到 `useXxxQuery({ <param>: <literal> })` 或 lookup map 的工作。
## 怎麼跑
從 clade central 呼叫(`<clade-vendor>` = `~/offline/clade/vendor`,與其他 vendor script 同慣例):
```bash
node <clade-vendor>/scripts/audit-data-sanity.ts \
--consumer-path . \
[--files <comma-separated-touched-files>] \
--json
```
- 不給 `--files` → walk 整個 consumer(skip node_modules/.nuxt/dist)。
- 給 `--files` → 只掃指定檔(spectra-apply 時傳本 phase touched files 較快)。
## 偵測項
1. **PARAM_BOUNDARY(Critical — blocks archive)**:client 端 pagination-ish param literal(`perPage` / `per_page` / `pageSize` / `limit` / `take` / `first` / `count` / `top` / `size`)超過(max)或低於(min)同名 server zod bound(`.max(N)` / `.min(N)` / `.length(N)`)。對應 UI-INV-2(lookup-resolved column 解析率 100%)。
2. **LOOKUP_MAP_RISK(advisory / warn)**:偵測 `xxxMap` / `xxxLookup` / `xxxById` 從 query data(`.reduce(` / `Object.fromEntries(` / `new Map(`)建的 lookup map。提醒:來源 query 若失敗,此 map empty → 對應 column uniform fallback。確認來源 query param 在 schema bound 內。
> **限制(heuristic,非真 AST)**:clade home 無 oxc-parser / @vue/compiler-sfc,本 audit 是 dependency-free regex 掃描(與 `d-pattern-audit.ts` / `manual-review-audit.ts` 同慣例),靠 **param 名跨檔對應** 連結 client literal ↔ server bound。同名 param 出現在不相關 schema 時可能 false-link;PARAM_BOUNDARY 命中後請人工確認該 client query 真打到該 server endpoint。
## 結果處置
- **exit 0 `status: "pass"`** → 通過。advisory lookupRisks 印到 stderr 供參考,不 block。
- **exit 1 `status: "fail"`**(含 PARAM_BOUNDARY)→ **Critical,MUST block**:root-cause 修 client literal 到 bound 內(典型:`perPage: 200` → `100`),或若新 bound 是有意則調 server schema。**NEVER** 標 phase / archive done、**NEVER** 留給 user 在 manual review 抓。
- JSON schema:`{ status: "pass"|"fail", violations: [{param, clientValue, kind, bound, clientFile, clientLine, serverFile, serverLine}], lookupRisks: [{name, file, line}], scanned: N }`。
## 與其他 Layer 的關係
- **Layer B**(`refactor-invariant-check.ts`):runtime 偵測「column 整欄 fallback」(症狀)。Layer C 是 static 偵測「param 超界」(root cause)。兩者互補。
- **Layer D**(`UI-INVARIANTS.md`):UI-INV-2 是本 skill 的契約來源。
- **Layer E.1**(pre-handoff self-analysis):D4 維度(API contract boundary)可直接引用本 audit 結果。
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!