@ryuenn3123/agentic-senior-core 4.3.14 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent-context/prompts/init-project.md +1 -1
- package/.agent-context/prompts/refactor.md +1 -0
- package/.agent-context/review-checklists/pr-checklist.md +1 -3
- package/.agent-context/rules/architecture.md +5 -0
- package/AGENTS.md +67 -115
- package/bin/agentic-senior-core.js +2 -5
- package/lib/cli/adaptive-context/catalog.mjs +4 -0
- package/lib/cli/adaptive-context.mjs +87 -301
- package/lib/cli/compiler.mjs +6 -389
- package/lib/cli/token-optimization.mjs +4 -89
- package/package.json +2 -9
- package/scripts/context-triggered-audit.mjs +1 -1
- package/scripts/{audit-cache-layer-contract.mjs → validate/audits/cache-layer-contract.mjs} +4 -37
- package/scripts/{audit-caching-scope-hygiene.mjs → validate/audits/caching-scope-hygiene.mjs} +1 -34
- package/scripts/{audit-file-size.mjs → validate/audits/file-size.mjs} +1 -62
- package/scripts/{audit-reflection-citations.mjs → validate/audits/reflection-citations.mjs} +2 -35
- package/scripts/{audit-release-bundle.mjs → validate/audits/release-bundle.mjs} +1 -36
- package/scripts/{audit-rule-id-uniqueness.mjs → validate/audits/rule-id-uniqueness.mjs} +1 -36
- package/scripts/validate/config.mjs +0 -18
- package/scripts/validate/file-structure.mjs +0 -4
- package/scripts/validate/utils.mjs +52 -0
- package/scripts/validate.mjs +10 -81
- package/lib/cli/audits/typography-palette-anti-repeat-audit.mjs +0 -239
- package/lib/cli/commands/audit-design-anti-repeat.mjs +0 -39
- package/scripts/audit-typography-palette-anti-repeat.mjs +0 -120
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Typography and palette anti-repeat audit.
|
|
5
|
-
*
|
|
6
|
-
* Scans CSS-like files for font-family declarations and color values, then
|
|
7
|
-
*
|
|
8
|
-
* DEPRECATED: This audit was built for the legacy design-intent.json system
|
|
9
|
-
* and its machine-readable antiRepeatLedger. In the 2026 Context Ops Paradigm,
|
|
10
|
-
* anti-repeat checks are handled by the LLM reading docs/DESIGN.md's
|
|
11
|
-
* "Previous Directions" blocklist. This audit now unconditionally skips.
|
|
12
|
-
* - Typography matches are EXACT family-name matches and are always
|
|
13
|
-
* blocking (kind: typography.previously-shipped-family,
|
|
14
|
-
* diagnosticCode: BOUNDARY_TYPOGRAPHY_LEDGER_VIOLATION).
|
|
15
|
-
* - Palette matches are HEURISTIC. OKLCH-to-OKLCH distance is perceptually
|
|
16
|
-
* uniform (deltaE < threshold => match). Hex-to-hex matches are exact
|
|
17
|
-
* normalized equality. Cross-type matches (hex declared in CSS vs OKLCH
|
|
18
|
-
* in the ledger, or vice versa) are NOT performed; reporting cross-type
|
|
19
|
-
* would require a color-space conversion that is its own correctness
|
|
20
|
-
* surface (tracked in docs/deep-analysis-and-roadmap-backlog.md).
|
|
21
|
-
* - Palette findings BLOCK by default with kind:
|
|
22
|
-
* palette.previously-shipped-color and diagnosticCode:
|
|
23
|
-
* BOUNDARY_PALETTE_LEDGER_VIOLATION. Pass
|
|
24
|
-
* `treatPaletteAsAdvisory: true` (or `--palette-advisory` on the CLI)
|
|
25
|
-
* to opt a project into advisory-only palette reporting; severity drops
|
|
26
|
-
* to "advisory" and the diagnostic code becomes
|
|
27
|
-
* BOUNDARY_PALETTE_LEDGER_ADVISORY. Use the advisory mode only when a
|
|
28
|
-
* project knowingly accepts the false-positive risk of OKLCH distance
|
|
29
|
-
* matching at its chosen threshold.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
33
|
-
import { join, relative } from 'node:path';
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
collectScannableFilePaths,
|
|
37
|
-
lineNumberFromIndex,
|
|
38
|
-
} from './typography-palette-anti-repeat/file-scanner.mjs';
|
|
39
|
-
import {
|
|
40
|
-
extractFontFamiliesFromText,
|
|
41
|
-
extractLedgerTypographyFamilies,
|
|
42
|
-
} from './typography-palette-anti-repeat/typography-utils.mjs';
|
|
43
|
-
import {
|
|
44
|
-
extractColorOccurrencesFromText,
|
|
45
|
-
extractLedgerColors,
|
|
46
|
-
oklchPerceptualDistance,
|
|
47
|
-
} from './typography-palette-anti-repeat/color-utils.mjs';
|
|
48
|
-
|
|
49
|
-
const DEFAULT_OKLCH_DISTANCE_THRESHOLD = 0.04;
|
|
50
|
-
|
|
51
|
-
function findTypographyViolationsForFile({ relativeFilePath, sourceText, ledgerFamilies }) {
|
|
52
|
-
const violations = [];
|
|
53
|
-
const fontFamilyOccurrences = extractFontFamiliesFromText(sourceText);
|
|
54
|
-
for (const familyOccurrence of fontFamilyOccurrences) {
|
|
55
|
-
const ledgerEntry = ledgerFamilies.get(familyOccurrence.family);
|
|
56
|
-
if (!ledgerEntry) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
violations.push({
|
|
60
|
-
file: relativeFilePath,
|
|
61
|
-
line: lineNumberFromIndex(sourceText, familyOccurrence.index),
|
|
62
|
-
kind: 'typography.previously-shipped-family',
|
|
63
|
-
severity: 'blocking',
|
|
64
|
-
diagnosticCode: 'BOUNDARY_TYPOGRAPHY_LEDGER_VIOLATION',
|
|
65
|
-
detail: `CSS declares font-family "${familyOccurrence.family}" which appears in researchDossier.metadata.antiRepeatLedger.previousTypographyChoices ("${ledgerEntry.summary}"). Either escape the previously-shipped trio, or set derivedTokenLogic.tokenContinuityClassification.typography to continuity-retained with explicit rationale.`,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
return violations;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function buildHexAdvisory({ relativeFilePath, sourceText, colorOccurrence, ledgerColor, paletteSeverity, paletteDiagnosticCode }) {
|
|
72
|
-
return {
|
|
73
|
-
file: relativeFilePath,
|
|
74
|
-
line: lineNumberFromIndex(sourceText, colorOccurrence.index),
|
|
75
|
-
kind: 'palette.previously-shipped-color',
|
|
76
|
-
severity: paletteSeverity,
|
|
77
|
-
diagnosticCode: paletteDiagnosticCode,
|
|
78
|
-
detail: `CSS hex "${colorOccurrence.raw}" matches a hex color in researchDossier.metadata.antiRepeatLedger.previousPalettes ("${ledgerColor.sourceEntry.summary}"). Either escape the previously-shipped palette or set derivedTokenLogic.tokenContinuityClassification.palette to continuity-retained with explicit rationale.`,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function buildOklchAdvisory({ relativeFilePath, sourceText, colorOccurrence, ledgerColor, perceptualDistance, oklchDistanceThreshold, paletteSeverity, paletteDiagnosticCode }) {
|
|
83
|
-
return {
|
|
84
|
-
file: relativeFilePath,
|
|
85
|
-
line: lineNumberFromIndex(sourceText, colorOccurrence.index),
|
|
86
|
-
kind: 'palette.previously-shipped-color',
|
|
87
|
-
severity: paletteSeverity,
|
|
88
|
-
diagnosticCode: paletteDiagnosticCode,
|
|
89
|
-
detail: `CSS OKLCH "${colorOccurrence.raw}" is within ${perceptualDistance.toFixed(4)} of an OKLCH color in researchDossier.metadata.antiRepeatLedger.previousPalettes ("${ledgerColor.sourceEntry.summary}") (threshold ${oklchDistanceThreshold}). Heuristic match on perceptually-uniform OKLCH distance; either escape the previously-shipped palette, raise the threshold via --threshold, or set derivedTokenLogic.tokenContinuityClassification.palette to continuity-retained with explicit rationale.`,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function findPaletteFindingsForFile({ relativeFilePath, sourceText, ledgerColors, oklchDistanceThreshold, paletteSeverity, paletteDiagnosticCode }) {
|
|
94
|
-
const findings = [];
|
|
95
|
-
const colorOccurrences = extractColorOccurrencesFromText(sourceText);
|
|
96
|
-
for (const colorOccurrence of colorOccurrences) {
|
|
97
|
-
for (const ledgerColor of ledgerColors) {
|
|
98
|
-
if (colorOccurrence.kind === 'hex' && ledgerColor.kind === 'hex') {
|
|
99
|
-
if (
|
|
100
|
-
colorOccurrence.normalized
|
|
101
|
-
&& ledgerColor.normalized
|
|
102
|
-
&& colorOccurrence.normalized === ledgerColor.normalized
|
|
103
|
-
) {
|
|
104
|
-
findings.push(buildHexAdvisory({
|
|
105
|
-
relativeFilePath, sourceText, colorOccurrence, ledgerColor,
|
|
106
|
-
paletteSeverity, paletteDiagnosticCode,
|
|
107
|
-
}));
|
|
108
|
-
}
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
if (colorOccurrence.kind === 'oklch' && ledgerColor.kind === 'oklch' && colorOccurrence.oklch && ledgerColor.oklch) {
|
|
112
|
-
const perceptualDistance = oklchPerceptualDistance(colorOccurrence.oklch, ledgerColor.oklch);
|
|
113
|
-
if (perceptualDistance <= oklchDistanceThreshold) {
|
|
114
|
-
findings.push(buildOklchAdvisory({
|
|
115
|
-
relativeFilePath, sourceText, colorOccurrence, ledgerColor, perceptualDistance, oklchDistanceThreshold,
|
|
116
|
-
paletteSeverity, paletteDiagnosticCode,
|
|
117
|
-
}));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
// Cross-type (hex declared vs OKLCH ledger or vice versa) is intentionally
|
|
121
|
-
// skipped here; reporting cross-type would require a color-space conversion
|
|
122
|
-
// pass that is its own correctness surface. Tracked in
|
|
123
|
-
// docs/deep-analysis-and-roadmap-backlog.md.
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return findings;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function loadDesignIntentContract() {
|
|
130
|
-
return { contract: null, reason: 'design-intent-deprecated-use-design-md-blocklist' };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function buildSkippedReport(reportShell, reason) {
|
|
134
|
-
return {
|
|
135
|
-
...reportShell,
|
|
136
|
-
passed: true,
|
|
137
|
-
skipped: true,
|
|
138
|
-
reason,
|
|
139
|
-
filesScanned: 0,
|
|
140
|
-
typographyViolationCount: 0,
|
|
141
|
-
paletteFindingCount: 0,
|
|
142
|
-
typographyViolations: [],
|
|
143
|
-
paletteFindings: [],
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Runs the typography and palette anti-repeat audit.
|
|
149
|
-
*
|
|
150
|
-
* @param {object} [auditOptions]
|
|
151
|
-
* @param {string} [auditOptions.repositoryRootPath]
|
|
152
|
-
* @param {string[]} [auditOptions.scanRoots]
|
|
153
|
-
* @param {string} [auditOptions.designIntentRelativePath]
|
|
154
|
-
* @param {number} [auditOptions.oklchDistanceThreshold]
|
|
155
|
-
* @param {boolean} [auditOptions.treatPaletteAsAdvisory]
|
|
156
|
-
*/
|
|
157
|
-
export function runTypographyPaletteAntiRepeatAudit(auditOptions = {}) {
|
|
158
|
-
const repositoryRootPath = auditOptions.repositoryRootPath || process.cwd();
|
|
159
|
-
const scanRoots = Array.isArray(auditOptions.scanRoots) && auditOptions.scanRoots.length > 0
|
|
160
|
-
? auditOptions.scanRoots
|
|
161
|
-
: ['.'];
|
|
162
|
-
const designIntentRelativePath = auditOptions.designIntentRelativePath || 'docs/design-intent.json';
|
|
163
|
-
const oklchDistanceThreshold = typeof auditOptions.oklchDistanceThreshold === 'number'
|
|
164
|
-
? auditOptions.oklchDistanceThreshold
|
|
165
|
-
: DEFAULT_OKLCH_DISTANCE_THRESHOLD;
|
|
166
|
-
const treatPaletteAsAdvisory = auditOptions.treatPaletteAsAdvisory === true;
|
|
167
|
-
const paletteSeverity = treatPaletteAsAdvisory ? 'advisory' : 'blocking';
|
|
168
|
-
const paletteDiagnosticCode = treatPaletteAsAdvisory
|
|
169
|
-
? 'BOUNDARY_PALETTE_LEDGER_ADVISORY'
|
|
170
|
-
: 'BOUNDARY_PALETTE_LEDGER_VIOLATION';
|
|
171
|
-
|
|
172
|
-
const reportShell = {
|
|
173
|
-
auditName: 'audit-typography-palette-anti-repeat',
|
|
174
|
-
reportVersion: '2.0.0',
|
|
175
|
-
generatedAt: new Date().toISOString(),
|
|
176
|
-
designIntentRelativePath,
|
|
177
|
-
paletteSeverity,
|
|
178
|
-
paletteDiagnosticCode,
|
|
179
|
-
oklchDistanceThreshold,
|
|
180
|
-
scope: {
|
|
181
|
-
typographyMatching: 'exact-family-name-after-normalization',
|
|
182
|
-
paletteHexMatching: 'exact-hex-after-7-digit-normalization',
|
|
183
|
-
paletteOklchMatching: 'l*c*h-distance-under-threshold',
|
|
184
|
-
paletteCrossTypeMatching: 'not-supported-color-conversion-out-of-scope',
|
|
185
|
-
paletteCrossTypeMatchingTrackedIn: 'docs/deep-analysis-and-roadmap-backlog.md',
|
|
186
|
-
},
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const designIntentLoad = loadDesignIntentContract();
|
|
190
|
-
if (!designIntentLoad.contract) {
|
|
191
|
-
return buildSkippedReport(reportShell, designIntentLoad.reason);
|
|
192
|
-
}
|
|
193
|
-
if (!antiRepeatLedger || typeof antiRepeatLedger !== 'object') {
|
|
194
|
-
return buildSkippedReport(reportShell, 'anti-repeat-ledger-absent');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const ledgerFamilies = extractLedgerTypographyFamilies(antiRepeatLedger);
|
|
198
|
-
const ledgerColors = extractLedgerColors(antiRepeatLedger);
|
|
199
|
-
const scannableFilePaths = collectScannableFilePaths(repositoryRootPath, scanRoots);
|
|
200
|
-
|
|
201
|
-
/** @type {any[]} */
|
|
202
|
-
const typographyViolations = [];
|
|
203
|
-
/** @type {any[]} */
|
|
204
|
-
const paletteFindings = [];
|
|
205
|
-
|
|
206
|
-
for (const absoluteFilePath of scannableFilePaths) {
|
|
207
|
-
const relativeFilePath = relative(repositoryRootPath, absoluteFilePath).replace(/\\/g, '/');
|
|
208
|
-
let sourceText;
|
|
209
|
-
try {
|
|
210
|
-
sourceText = readFileSync(absoluteFilePath, 'utf8');
|
|
211
|
-
} catch {
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
if (ledgerFamilies.size > 0) {
|
|
215
|
-
typographyViolations.push(...findTypographyViolationsForFile({
|
|
216
|
-
relativeFilePath, sourceText, ledgerFamilies,
|
|
217
|
-
}));
|
|
218
|
-
}
|
|
219
|
-
if (ledgerColors.length > 0) {
|
|
220
|
-
paletteFindings.push(...findPaletteFindingsForFile({
|
|
221
|
-
relativeFilePath, sourceText, ledgerColors, oklchDistanceThreshold,
|
|
222
|
-
paletteSeverity, paletteDiagnosticCode,
|
|
223
|
-
}));
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const blockingViolationCount = typographyViolations.length + (treatPaletteAsAdvisory ? 0 : paletteFindings.length);
|
|
228
|
-
|
|
229
|
-
return {
|
|
230
|
-
...reportShell,
|
|
231
|
-
passed: blockingViolationCount === 0,
|
|
232
|
-
skipped: false,
|
|
233
|
-
filesScanned: scannableFilePaths.length,
|
|
234
|
-
typographyViolationCount: typographyViolations.length,
|
|
235
|
-
paletteFindingCount: paletteFindings.length,
|
|
236
|
-
typographyViolations,
|
|
237
|
-
paletteFindings,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* `agentic-senior-core audit:design-anti-repeat`
|
|
5
|
-
*
|
|
6
|
-
* [DEPRECATED in 2026 Context Ops Paradigm]
|
|
7
|
-
* This script is retired because the anti-repeat ledger is now maintained
|
|
8
|
-
* as plain-text inside docs/DESIGN.md. The Adaptive Context AI agent enforces
|
|
9
|
-
* this naturally without needing regex-based JSON compliance theater.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
export async function runDesignAntiRepeatAuditCommand(commandLineArgs = []) {
|
|
13
|
-
if (commandLineArgs.includes('--json')) {
|
|
14
|
-
process.stdout.write(JSON.stringify({
|
|
15
|
-
passed: true,
|
|
16
|
-
skipped: true,
|
|
17
|
-
reason: 'audit-design-anti-repeat is deprecated in Context Ops 2026. Plain text ledgers in DESIGN.md are handled by the agent contextually.',
|
|
18
|
-
targetDirectoryPath: process.cwd(),
|
|
19
|
-
filesScanned: 0,
|
|
20
|
-
typographyViolationCount: 0,
|
|
21
|
-
paletteFindingCount: 0,
|
|
22
|
-
paletteSeverity: 'advisory',
|
|
23
|
-
oklchDistanceThreshold: 0.04,
|
|
24
|
-
typographyViolations: [],
|
|
25
|
-
paletteFindings: []
|
|
26
|
-
}, null, 2) + '\n');
|
|
27
|
-
return 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
console.log('===============================================');
|
|
31
|
-
console.log(' audit:design-anti-repeat (DEPRECATED)');
|
|
32
|
-
console.log('===============================================');
|
|
33
|
-
console.log(' Audit skipped: audit-design-anti-repeat is retired in Context Ops 2026.');
|
|
34
|
-
console.log(' Plain text ledgers in docs/DESIGN.md are handled by the agent contextually.');
|
|
35
|
-
console.log(' You can safely remove this check from your CI pipeline.');
|
|
36
|
-
console.log('');
|
|
37
|
-
|
|
38
|
-
return 0;
|
|
39
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// @ts-check
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* audit-typography-palette-anti-repeat.mjs
|
|
6
|
-
*
|
|
7
|
-
* Thin CLI wrapper around lib/cli/audits/typography-palette-anti-repeat-audit.mjs.
|
|
8
|
-
* The wrapper defaults to scanning the current working directory so it works
|
|
9
|
-
* for both repo-internal `npm run audit:typography-palette-anti-repeat` (npm
|
|
10
|
-
* sets cwd to the repo root) and direct invocation from a user project. The
|
|
11
|
-
* user-facing entry point is the `audit:design-anti-repeat` subcommand on
|
|
12
|
-
* the published bin (see lib/cli/commands/audit-design-anti-repeat.mjs).
|
|
13
|
-
*
|
|
14
|
-
* Usage:
|
|
15
|
-
* node scripts/audit-typography-palette-anti-repeat.mjs
|
|
16
|
-
* node scripts/audit-typography-palette-anti-repeat.mjs --json
|
|
17
|
-
* node scripts/audit-typography-palette-anti-repeat.mjs --palette-advisory
|
|
18
|
-
* node scripts/audit-typography-palette-anti-repeat.mjs --threshold 0.05
|
|
19
|
-
* node scripts/audit-typography-palette-anti-repeat.mjs --root /path/to/project
|
|
20
|
-
*
|
|
21
|
-
* Default severity:
|
|
22
|
-
* - Typography matches always block.
|
|
23
|
-
* - Palette matches block by default. Pass --palette-advisory to opt a
|
|
24
|
-
* project into advisory-only palette reporting (release stays unblocked
|
|
25
|
-
* by palette findings; typography still blocks).
|
|
26
|
-
*
|
|
27
|
-
* Exit codes:
|
|
28
|
-
* 0 = no blocking violations
|
|
29
|
-
* 1 = at least one BOUNDARY_TYPOGRAPHY_LEDGER_VIOLATION or, in default
|
|
30
|
-
* mode, BOUNDARY_PALETTE_LEDGER_VIOLATION
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
import { resolve } from 'node:path';
|
|
34
|
-
|
|
35
|
-
import { runTypographyPaletteAntiRepeatAudit } from '../lib/cli/audits/typography-palette-anti-repeat-audit.mjs';
|
|
36
|
-
|
|
37
|
-
const COMMAND_LINE_ARGS = process.argv.slice(2);
|
|
38
|
-
const SHOULD_OUTPUT_JSON_ONLY = COMMAND_LINE_ARGS.includes('--json');
|
|
39
|
-
const SHOULD_TREAT_PALETTE_AS_ADVISORY = COMMAND_LINE_ARGS.includes('--palette-advisory');
|
|
40
|
-
|
|
41
|
-
function readStringFlag(flagName) {
|
|
42
|
-
const flagIndex = COMMAND_LINE_ARGS.indexOf(flagName);
|
|
43
|
-
if (flagIndex === -1) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const flagValue = COMMAND_LINE_ARGS[flagIndex + 1];
|
|
47
|
-
if (typeof flagValue !== 'string' || flagValue.length === 0 || flagValue.startsWith('--')) {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
return flagValue;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function readNumericFlag(flagName) {
|
|
54
|
-
const stringValue = readStringFlag(flagName);
|
|
55
|
-
if (stringValue === null) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const numericValue = Number(stringValue);
|
|
59
|
-
return Number.isFinite(numericValue) ? numericValue : null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function main() {
|
|
63
|
-
const oklchDistanceThreshold = readNumericFlag('--threshold');
|
|
64
|
-
const explicitRootPath = readStringFlag('--root');
|
|
65
|
-
const repositoryRootPath = resolve(explicitRootPath || process.cwd());
|
|
66
|
-
|
|
67
|
-
const auditReport = runTypographyPaletteAntiRepeatAudit({
|
|
68
|
-
repositoryRootPath,
|
|
69
|
-
treatPaletteAsAdvisory: SHOULD_TREAT_PALETTE_AS_ADVISORY,
|
|
70
|
-
...(typeof oklchDistanceThreshold === 'number' ? { oklchDistanceThreshold } : {}),
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
if (SHOULD_OUTPUT_JSON_ONLY) {
|
|
74
|
-
process.stdout.write(`${JSON.stringify({ ...auditReport, repositoryRootPath }, null, 2)}\n`);
|
|
75
|
-
process.exit(auditReport.passed ? 0 : 1);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
console.log('===============================================');
|
|
79
|
-
console.log(' audit:typography-palette-anti-repeat');
|
|
80
|
-
console.log('===============================================');
|
|
81
|
-
console.log(` Target directory: ${repositoryRootPath}`);
|
|
82
|
-
console.log(` Files scanned: ${auditReport.filesScanned}`);
|
|
83
|
-
console.log(` Typography violations: ${auditReport.typographyViolationCount} (blocking)`);
|
|
84
|
-
console.log(` Palette findings: ${auditReport.paletteFindingCount} (${auditReport.paletteSeverity})`);
|
|
85
|
-
console.log(` OKLCH distance threshold: ${auditReport.oklchDistanceThreshold}`);
|
|
86
|
-
console.log('');
|
|
87
|
-
|
|
88
|
-
if (auditReport.skipped) {
|
|
89
|
-
console.log(` Audit skipped: ${auditReport.reason}`);
|
|
90
|
-
process.exit(0);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (auditReport.typographyViolations.length > 0) {
|
|
94
|
-
console.log(' Typography violations (blocking):');
|
|
95
|
-
for (const violation of auditReport.typographyViolations) {
|
|
96
|
-
console.log(` [${violation.kind}] ${violation.file}:${violation.line} ${violation.detail}`);
|
|
97
|
-
}
|
|
98
|
-
console.log('');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (auditReport.paletteFindings.length > 0) {
|
|
102
|
-
console.log(` Palette findings (${auditReport.paletteSeverity}):`);
|
|
103
|
-
for (const finding of auditReport.paletteFindings) {
|
|
104
|
-
console.log(` [${finding.kind}] ${finding.file}:${finding.line} ${finding.detail}`);
|
|
105
|
-
}
|
|
106
|
-
console.log('');
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (auditReport.passed) {
|
|
110
|
-
console.log(' No blocking violations against the anti-repeat ledger.');
|
|
111
|
-
process.exit(0);
|
|
112
|
-
}
|
|
113
|
-
const blockingPaletteCount = auditReport.paletteSeverity === 'blocking' ? auditReport.paletteFindingCount : 0;
|
|
114
|
-
console.log(` ${auditReport.typographyViolationCount} typography violation(s) and ${blockingPaletteCount} palette violation(s) found; release blocked.`);
|
|
115
|
-
process.exit(1);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (process.argv[1] && (import.meta.url === `file://${process.argv[1].replace(/\\/g, '/')}` || process.argv[1].endsWith('audit-typography-palette-anti-repeat.mjs'))) {
|
|
119
|
-
main();
|
|
120
|
-
}
|