Ai-setup scoring-checks
Add a new deterministic scoring check in src/scoring/checks/. Returns Check[] array, uses constants from src/scoring/constants.ts, integrates in src/scoring/index.ts. Use when adding scoring logic, creating checks, modifying check weights. Do NOT use for display/UI changes or check result formatting.
git clone https://github.com/caliber-ai-org/ai-setup
T=$(mktemp -d) && git clone --depth=1 https://github.com/caliber-ai-org/ai-setup "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.agents/skills/scoring-checks" ~/.claude/skills/caliber-ai-org-ai-setup-scoring-checks && rm -rf "$T"
.agents/skills/scoring-checks/SKILL.mdScoring Checks
Critical
- Check must return
— Never return a single check or a Promise. Return an empty arrayCheck[]
if the condition fails.[] - Use constants from
— All weights, thresholds, and names must reference constants, never hardcoded values.src/scoring/constants.ts - Deterministic only — No LLM calls. Scoring checks inspect existing files, fingerprint data, and git history. Use
data exclusively.src/fingerprint/ - File structure: Create one file per check in
. Export a default function with signaturesrc/scoring/checks/
.(ctx: ScoringContext) => Check[] - Integration point: Add the check function to the
array inchecks
— this is the ONLY place checks are orchestrated.src/scoring/index.ts
Instructions
-
Create the check file at
.src/scoring/checks/{check-name}.ts- Import
type fromCheck
.../types.js - Import constants from
.../constants.js - Export default function:
export default function {checkName}(ctx: ScoringContext): Check[] { } - Verify file compiles:
.npx tsc --noEmit
- Import
-
Inspect the ScoringContext to access fingerprint data.
- Available:
,ctx.fingerprint
(existing config),ctx.manifest
(history).ctx.git - Example:
(detected sources),ctx.fingerprint.sources
(file tree).ctx.fingerprint.files - Verify using
test setup to mock context.src/scoring/__tests__/
- Available:
-
Build the Check object.
: Unique string, lowercase-kebab (e.g.,id
,'existence'
).'freshness-days-old'
: Human-readable display name (e.g.,name
).'CLAUDE.md exists'
: Number (0–100). Must reference constant frompoints
.src/scoring/constants.ts
: String array explaining why the check passed/failed (max 1–2 sentences each).reasons
: Boolean.passed- Return
if passed,[check]
if failed.[]
-
Reference constants for all numeric values.
- Open
and use existing constants or add new ones.src/scoring/constants.ts - Example:
in constants, then useconst POINTS_EXISTENCE = 10
in check.points: POINTS_EXISTENCE - Verify constant is exported:
.export const POINTS_EXISTENCE = 10
- Open
-
Add the check to the orchestrator in
.src/scoring/index.ts- Import:
.import {checkName} from './checks/{check-name}.js' - Add to
array:checks
.{checkName}(ctx), - Verify tests pass:
.npm test -- src/scoring/__tests__/index.test.ts
- Import:
-
Write a test in
.src/scoring/checks/__tests__/{check-name}.test.ts- Mock
with fingerprint data usingScoringContext
or fixtures from existing tests.memfs - Test both pass and fail cases.
- Verify test runs:
.npx vitest run src/scoring/checks/__tests__/{check-name}.test.ts
- Mock
Examples
User says: "Add a scoring check that verifies CLAUDE.md exists and is not empty."
Actions:
- Create
:src/scoring/checks/existence.ts
import type { Check, ScoringContext } from '../types.js'; import { POINTS_EXISTENCE } from '../constants.js'; export default function existence(ctx: ScoringContext): Check[] { const claudeMd = ctx.manifest.claude; const passed = claudeMd && claudeMd.trim().length > 0; if (!passed) { return []; } return [{ id: 'existence', name: 'CLAUDE.md exists and is not empty', points: POINTS_EXISTENCE, reasons: ['CLAUDE.md is present and contains configuration.'], passed: true, }]; }
-
Add to
:src/scoring/constants.ts
.export const POINTS_EXISTENCE = 10 -
Update
:src/scoring/index.ts
import existence from './checks/existence.js'; // ... const checks = [ existence(ctx), // other checks ];
- Test with
.npm test
Result: Check is integrated and appears in score output.
Common Issues
"Check is not appearing in score output"
- Verify check is added to
array inchecks
.src/scoring/index.ts - Verify it returns
(not a single object or Promise).Check[] - Run
to ensure no import errors.npm run build && npm test
"Type error: ScoringContext has no property X"
- Check
for available context properties.src/scoring/types.ts - Use
,ctx.fingerprint
,ctx.manifest
— not custom properties.ctx.git - Verify fingerprint data exists in test fixture:
in test.console.log(ctx)
"Constant is undefined"
- Open
and confirm constant is exported.src/scoring/constants.ts - Use
to catch missing exports.npm run build - Add new constants if needed and commit to constants.ts first.
"Test fails with 'memfs is not found'"
- Import from test setup:
.import { vol } from 'memfs' - See existing tests in
for memfs usage patterns.src/scoring/checks/__tests__/