From 350cebc39c3b16a9522e055778efd9bf0acd9f75 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Sun, 19 Apr 2026 22:32:40 +0200 Subject: [PATCH] test(config-audit): add baseline-all-a fixture + grade-stability regression test --- .../.claude/rules/typescript.md | 13 ++++++ .../baseline-all-a/.claude/settings.json | 8 ++++ .../fixtures/baseline-all-a/.claude/shared.md | 15 +++++++ .../tests/fixtures/baseline-all-a/.mcp.json | 10 +++++ .../tests/fixtures/baseline-all-a/CLAUDE.md | 44 ++++++++++++++++++ .../fixtures/baseline-all-a/hooks/hooks.json | 28 ++++++++++++ .../fixtures/baseline-all-a/src/index.ts | 4 ++ .../scanners/posture-grade-stability.test.mjs | 45 +++++++++++++++++++ 8 files changed, 167 insertions(+) create mode 100644 plugins/config-audit/tests/fixtures/baseline-all-a/.claude/rules/typescript.md create mode 100644 plugins/config-audit/tests/fixtures/baseline-all-a/.claude/settings.json create mode 100644 plugins/config-audit/tests/fixtures/baseline-all-a/.claude/shared.md create mode 100644 plugins/config-audit/tests/fixtures/baseline-all-a/.mcp.json create mode 100644 plugins/config-audit/tests/fixtures/baseline-all-a/CLAUDE.md create mode 100644 plugins/config-audit/tests/fixtures/baseline-all-a/hooks/hooks.json create mode 100644 plugins/config-audit/tests/fixtures/baseline-all-a/src/index.ts create mode 100644 plugins/config-audit/tests/scanners/posture-grade-stability.test.mjs diff --git a/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/rules/typescript.md b/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/rules/typescript.md new file mode 100644 index 0000000..e1ea3ce --- /dev/null +++ b/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/rules/typescript.md @@ -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 diff --git a/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/settings.json b/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/settings.json new file mode 100644 index 0000000..b350a22 --- /dev/null +++ b/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/settings.json @@ -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" +} diff --git a/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/shared.md b/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/shared.md new file mode 100644 index 0000000..6173f73 --- /dev/null +++ b/plugins/config-audit/tests/fixtures/baseline-all-a/.claude/shared.md @@ -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 diff --git a/plugins/config-audit/tests/fixtures/baseline-all-a/.mcp.json b/plugins/config-audit/tests/fixtures/baseline-all-a/.mcp.json new file mode 100644 index 0000000..1fd7642 --- /dev/null +++ b/plugins/config-audit/tests/fixtures/baseline-all-a/.mcp.json @@ -0,0 +1,10 @@ +{ + "mcpServers": { + "memory": { + "type": "stdio", + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-memory"], + "trust": "workspace" + } + } +} diff --git a/plugins/config-audit/tests/fixtures/baseline-all-a/CLAUDE.md b/plugins/config-audit/tests/fixtures/baseline-all-a/CLAUDE.md new file mode 100644 index 0000000..c24f749 --- /dev/null +++ b/plugins/config-audit/tests/fixtures/baseline-all-a/CLAUDE.md @@ -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 diff --git a/plugins/config-audit/tests/fixtures/baseline-all-a/hooks/hooks.json b/plugins/config-audit/tests/fixtures/baseline-all-a/hooks/hooks.json new file mode 100644 index 0000000..43129ea --- /dev/null +++ b/plugins/config-audit/tests/fixtures/baseline-all-a/hooks/hooks.json @@ -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 + } + ] + } + ] + } +} diff --git a/plugins/config-audit/tests/fixtures/baseline-all-a/src/index.ts b/plugins/config-audit/tests/fixtures/baseline-all-a/src/index.ts new file mode 100644 index 0000000..37d5d73 --- /dev/null +++ b/plugins/config-audit/tests/fixtures/baseline-all-a/src/index.ts @@ -0,0 +1,4 @@ +// Sample TypeScript source file to satisfy rule glob patterns. +export function hello(name: string): string { + return `Hello, ${name}`; +} diff --git a/plugins/config-audit/tests/scanners/posture-grade-stability.test.mjs b/plugins/config-audit/tests/scanners/posture-grade-stability.test.mjs new file mode 100644 index 0000000..cbe66d6 --- /dev/null +++ b/plugins/config-audit/tests/scanners/posture-grade-stability.test.mjs @@ -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`); + } + }); +});