test(config-audit): add baseline-all-a fixture + grade-stability regression test
This commit is contained in:
parent
a9fb328584
commit
350cebc39c
8 changed files with 167 additions and 0 deletions
13
plugins/config-audit/tests/fixtures/baseline-all-a/.claude/rules/typescript.md
vendored
Normal file
13
plugins/config-audit/tests/fixtures/baseline-all-a/.claude/rules/typescript.md
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
paths: src/**/*.ts
|
||||
---
|
||||
|
||||
# TypeScript Rules
|
||||
|
||||
Use strict TypeScript throughout.
|
||||
|
||||
## Mandatory
|
||||
|
||||
- `strict: true` in tsconfig
|
||||
- No `any` — prefer `unknown` at boundaries
|
||||
- Prefer `type` aliases for simple shapes, `interface` for extendable objects
|
||||
8
plugins/config-audit/tests/fixtures/baseline-all-a/.claude/settings.json
vendored
Normal file
8
plugins/config-audit/tests/fixtures/baseline-all-a/.claude/settings.json
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||
"permissions": {
|
||||
"allow": ["Bash(npm run *)", "Read(src/**)"],
|
||||
"deny": ["Read(./.env)"]
|
||||
},
|
||||
"effortLevel": "medium"
|
||||
}
|
||||
15
plugins/config-audit/tests/fixtures/baseline-all-a/.claude/shared.md
vendored
Normal file
15
plugins/config-audit/tests/fixtures/baseline-all-a/.claude/shared.md
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Shared Configuration
|
||||
|
||||
Common patterns and conventions shared across the baseline fixture.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
- `camelCase` for variables and functions
|
||||
- `PascalCase` for classes, interfaces, and types
|
||||
- `UPPER_SNAKE_CASE` for module-level constants
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Prefer early return over deep nesting
|
||||
- Throw `Error` subclasses with typed messages
|
||||
- Never swallow errors silently
|
||||
10
plugins/config-audit/tests/fixtures/baseline-all-a/.mcp.json
vendored
Normal file
10
plugins/config-audit/tests/fixtures/baseline-all-a/.mcp.json
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"mcpServers": {
|
||||
"memory": {
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
||||
"trust": "workspace"
|
||||
}
|
||||
}
|
||||
}
|
||||
44
plugins/config-audit/tests/fixtures/baseline-all-a/CLAUDE.md
vendored
Normal file
44
plugins/config-audit/tests/fixtures/baseline-all-a/CLAUDE.md
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Baseline Project
|
||||
|
||||
## Overview
|
||||
|
||||
A fixture designed to score Grade A on every v3 quality area (CML, SET, HKV,
|
||||
RUL, MCP, IMP, CNF) before the Token Efficiency scanner is added. Serves as
|
||||
the grade-stability canary for the config-audit v4.0 release.
|
||||
|
||||
## Purpose
|
||||
|
||||
This fixture is the regression canary for the posture scorecard. If a future
|
||||
scanner change drags any v3 quality area below Grade A on this fixture, the
|
||||
change is not release-safe.
|
||||
|
||||
## Commands
|
||||
|
||||
- `npm run build` — Build the project
|
||||
- `npm test` — Run all tests
|
||||
- `npm run lint` — Lint source files
|
||||
|
||||
## Architecture
|
||||
|
||||
Standard Node.js layout with TypeScript under `src/`, unit tests co-located
|
||||
beside implementation files, and shared config imported via `@import`.
|
||||
|
||||
## Conventions
|
||||
|
||||
- TypeScript strict mode; no `any`
|
||||
- Conventional Commits (`type(scope): description`)
|
||||
- Zero runtime npm dependencies where possible
|
||||
- Deterministic test fixtures only
|
||||
|
||||
## Tooling
|
||||
|
||||
- Node.js ≥ 18
|
||||
- `node:test` framework for unit tests
|
||||
- `node --test 'tests/**/*.test.mjs'` runs the full suite
|
||||
|
||||
## Shared Patterns
|
||||
|
||||
Shared conventions and helpers are documented in an imported file to keep the
|
||||
top-level stable-prefix content cache-friendly under Opus 4.7.
|
||||
|
||||
@.claude/shared.md
|
||||
28
plugins/config-audit/tests/fixtures/baseline-all-a/hooks/hooks.json
vendored
Normal file
28
plugins/config-audit/tests/fixtures/baseline-all-a/hooks/hooks.json
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo pre-bash",
|
||||
"timeout": 5000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo post-edit",
|
||||
"timeout": 5000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
4
plugins/config-audit/tests/fixtures/baseline-all-a/src/index.ts
vendored
Normal file
4
plugins/config-audit/tests/fixtures/baseline-all-a/src/index.ts
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Sample TypeScript source file to satisfy rule glob patterns.
|
||||
export function hello(name: string): string {
|
||||
return `Hello, ${name}`;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import { describe, it, beforeEach } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { execFile } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const exec = promisify(execFile);
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||
const FIXTURES = resolve(__dirname, '../fixtures');
|
||||
const POSTURE_BIN = resolve(__dirname, '../../scanners/posture.mjs');
|
||||
|
||||
async function runPostureJson(fixturePath) {
|
||||
const { stdout } = await exec('node', [POSTURE_BIN, fixturePath, '--json'], {
|
||||
timeout: 30000,
|
||||
cwd: resolve(__dirname, '../..'),
|
||||
});
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
|
||||
describe('posture grade stability — baseline-all-a', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
result = await runPostureJson(resolve(FIXTURES, 'baseline-all-a'));
|
||||
});
|
||||
|
||||
it('overallGrade is A', () => {
|
||||
assert.equal(result.overallGrade, 'A');
|
||||
});
|
||||
|
||||
it('every quality area (non-Feature Coverage) has grade A', () => {
|
||||
const qualityAreas = result.areas.filter(a => a.name !== 'Feature Coverage');
|
||||
for (const area of qualityAreas) {
|
||||
assert.equal(area.grade, 'A', `${area.name} has grade ${area.grade}, expected A (score=${area.score})`);
|
||||
}
|
||||
});
|
||||
|
||||
it('has no critical or high findings across scanners', () => {
|
||||
const scanners = result.scannerEnvelope.scanners;
|
||||
for (const s of scanners) {
|
||||
assert.equal(s.counts.critical, 0, `${s.scanner} has ${s.counts.critical} critical findings`);
|
||||
assert.equal(s.counts.high, 0, `${s.scanner} has ${s.counts.high} high findings`);
|
||||
}
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue