@oddessentials/repo-standards 4.3.0 → 5.0.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/version.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type {\n MasterJson,\n StackChecklistJson,\n StackId,\n CiSystem,\n} from \"./types.js\";\nimport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION } from \"./version.js\";\n\n// Re-export types for consumers\nexport type { MasterJson, StackChecklistJson, StackId, CiSystem };\n\n// Re-export version info (stable API contract)\nexport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION };\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Path to config directory:\n// - When running from src/ (dev/test): use repo root config/\n// - When running from dist/ (installed): use dist/config/\nconst isDevMode = __dirname.includes(\"src\");\nconst configDir = isDevMode\n ? join(__dirname, \"..\", \"config\")\n : join(__dirname, \"config\");\n\n/** Load the master spec JSON from the packaged dist directory */\nexport function loadMasterSpec(): MasterJson {\n const filePath = join(configDir, \"standards.json\");\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** Load a stack-specific checklist (optionally filtered by CI system) */\nexport function loadBaseline(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n const suffix = ci ? `.${ci}` : \"\";\n const file = `standards.${stack}${suffix}.json`;\n const filePath = join(configDir, file);\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** List all supported stacks (derived from the master spec) */\nexport function listSupportedStacks(): readonly StackId[] {\n const spec = loadMasterSpec();\n return Object.keys(spec.stacks) as StackId[];\n}\n\n/** List all supported CI systems (derived from the master spec) */\nexport function listSupportedCiSystems(): readonly CiSystem[] {\n const spec = loadMasterSpec();\n return spec.ciSystems as CiSystem[];\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadBaseline - loads stack-specific standards checklist.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getStandards(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n return loadBaseline(stack, ci);\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadMasterSpec - loads the master standards schema.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getSchema(): MasterJson {\n return loadMasterSpec();\n}\n","/**\n * AUTO-GENERATED at build time by scripts/build.ts\n * DO NOT EDIT MANUALLY\n *\n * This module provides version information for the repo-standards package.\n * Consumers should import from here instead of package.json to avoid\n * ESM/CJS interop issues.\n */\n\nexport const STANDARDS_VERSION = '4.2.0';\nexport const STANDARDS_SCHEMA_VERSION = 4;\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,MAAM,eAAe;;;ACOvB,IAAM,oBAAoB;AAC1B,IAAM,2BAA2B;;;ADQxC,IAAMA,cAAa,cAAc,YAAY,GAAG;AAChD,IAAMC,aAAY,QAAQD,WAAU;AAKpC,IAAM,YAAYC,WAAU,SAAS,KAAK;AAC1C,IAAM,YAAY,YACd,KAAKA,YAAW,MAAM,QAAQ,IAC9B,KAAKA,YAAW,QAAQ;AAGrB,SAAS,iBAA6B;AAC3C,QAAM,WAAW,KAAK,WAAW,gBAAgB;AACjD,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,aACd,OACA,IACoB;AACpB,QAAM,SAAS,KAAK,IAAI,EAAE,KAAK;AAC/B,QAAM,OAAO,aAAa,KAAK,GAAG,MAAM;AACxC,QAAM,WAAW,KAAK,WAAW,IAAI;AACrC,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,sBAA0C;AACxD,QAAM,OAAO,eAAe;AAC5B,SAAO,OAAO,KAAK,KAAK,MAAM;AAChC;AAGO,SAAS,yBAA8C;AAC5D,QAAM,OAAO,eAAe;AAC5B,SAAO,KAAK;AACd;AAOO,SAAS,aACd,OACA,IACoB;AACpB,SAAO,aAAa,OAAO,EAAE;AAC/B;AAOO,SAAS,YAAwB;AACtC,SAAO,eAAe;AACxB;","names":["__filename","__dirname"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/version.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type {\n MasterJson,\n StackChecklistJson,\n StackId,\n CiSystem,\n} from \"./types.js\";\nimport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION } from \"./version.js\";\n\n// Re-export types for consumers\nexport type { MasterJson, StackChecklistJson, StackId, CiSystem };\n\n// Re-export version info (stable API contract)\nexport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION };\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Path to config directory:\n// - When running from src/ (dev/test): use repo root config/\n// - When running from dist/ (installed): use dist/config/\nconst isDevMode = __dirname.includes(\"src\");\nconst configDir = isDevMode\n ? join(__dirname, \"..\", \"config\")\n : join(__dirname, \"config\");\n\n/** Load the master spec JSON from the packaged dist directory */\nexport function loadMasterSpec(): MasterJson {\n const filePath = join(configDir, \"standards.json\");\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** Load a stack-specific checklist (optionally filtered by CI system) */\nexport function loadBaseline(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n const suffix = ci ? `.${ci}` : \"\";\n const file = `standards.${stack}${suffix}.json`;\n const filePath = join(configDir, file);\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** List all supported stacks (derived from the master spec) */\nexport function listSupportedStacks(): readonly StackId[] {\n const spec = loadMasterSpec();\n return Object.keys(spec.stacks) as StackId[];\n}\n\n/** List all supported CI systems (derived from the master spec) */\nexport function listSupportedCiSystems(): readonly CiSystem[] {\n const spec = loadMasterSpec();\n return spec.ciSystems as CiSystem[];\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadBaseline - loads stack-specific standards checklist.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getStandards(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n return loadBaseline(stack, ci);\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadMasterSpec - loads the master standards schema.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getSchema(): MasterJson {\n return loadMasterSpec();\n}\n","/**\n * AUTO-GENERATED at build time by scripts/build.ts\n * DO NOT EDIT MANUALLY\n *\n * This module provides version information for the repo-standards package.\n * Consumers should import from here instead of package.json to avoid\n * ESM/CJS interop issues.\n */\n\nexport const STANDARDS_VERSION = '4.4.0';\nexport const STANDARDS_SCHEMA_VERSION = 4;\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,MAAM,eAAe;;;ACOvB,IAAM,oBAAoB;AAC1B,IAAM,2BAA2B;;;ADQxC,IAAMA,cAAa,cAAc,YAAY,GAAG;AAChD,IAAMC,aAAY,QAAQD,WAAU;AAKpC,IAAM,YAAYC,WAAU,SAAS,KAAK;AAC1C,IAAM,YAAY,YACd,KAAKA,YAAW,MAAM,QAAQ,IAC9B,KAAKA,YAAW,QAAQ;AAGrB,SAAS,iBAA6B;AAC3C,QAAM,WAAW,KAAK,WAAW,gBAAgB;AACjD,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,aACd,OACA,IACoB;AACpB,QAAM,SAAS,KAAK,IAAI,EAAE,KAAK;AAC/B,QAAM,OAAO,aAAa,KAAK,GAAG,MAAM;AACxC,QAAM,WAAW,KAAK,WAAW,IAAI;AACrC,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,sBAA0C;AACxD,QAAM,OAAO,eAAe;AAC5B,SAAO,OAAO,KAAK,KAAK,MAAM;AAChC;AAGO,SAAS,yBAA8C;AAC5D,QAAM,OAAO,eAAe;AAC5B,SAAO,KAAK;AACd;AAOO,SAAS,aACd,OACA,IACoB;AACpB,SAAO,aAAa,OAAO,EAAE;AAC/B;AAOO,SAAS,YAAwB;AACtC,SAAO,eAAe;AACxB;","names":["__filename","__dirname"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oddessentials/repo-standards",
3
3
  "private": false,
4
- "version": "4.3.0",
4
+ "version": "5.0.0",
5
5
  "description": "Standards and CI filtering utilities for multi-stack repository governance.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -0,0 +1,39 @@
1
+ // scripts/generate-readme-counts.ts
2
+ // Generates checklist item counts dynamically from standards.json
3
+ // Prevents count rot by computing at build time
4
+
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+
8
+ interface MasterJson {
9
+ version: number;
10
+ checklist: {
11
+ core: unknown[];
12
+ recommended: unknown[];
13
+ optionalEnhancements: unknown[];
14
+ };
15
+ }
16
+
17
+ function main() {
18
+ const rootDir = process.cwd();
19
+ const masterPath = path.join(rootDir, "config", "standards.json");
20
+
21
+ if (!fs.existsSync(masterPath)) {
22
+ console.error(`standards.json not found at ${masterPath}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ const raw = fs.readFileSync(masterPath, "utf8");
27
+ const master: MasterJson = JSON.parse(raw);
28
+
29
+ const coreCount = master.checklist.core.length;
30
+ const recommendedCount = master.checklist.recommended.length;
31
+ const optionalCount = master.checklist.optionalEnhancements.length;
32
+
33
+ // Output markdown snippet for README
34
+ console.log(
35
+ `**${coreCount} core** (required), **${recommendedCount} recommended**, **${optionalCount} optional enhancements**`,
36
+ );
37
+ }
38
+
39
+ main();
@@ -18,11 +18,21 @@ interface ValidationResult {
18
18
 
19
19
  interface ChecklistItem {
20
20
  id: string;
21
+ executionStage?: string;
21
22
  appliesTo?: { stacks?: string[]; ciSystems?: string[] };
22
23
  ciHints?: Record<string, unknown>;
23
24
  stackHints?: Record<string, unknown>;
24
25
  }
25
26
 
27
+ const VALID_EXECUTION_STAGES = new Set([
28
+ "pre-commit",
29
+ "pre-push",
30
+ "ci-pr",
31
+ "ci-main",
32
+ "release",
33
+ "nightly",
34
+ ]);
35
+
26
36
  interface MigrationStep {
27
37
  focusIds?: string[];
28
38
  }
@@ -196,6 +206,40 @@ function validateCoverageThreshold(config: Config): ValidationResult {
196
206
  return { valid: true, errors: [] };
197
207
  }
198
208
 
209
+ /**
210
+ * Validate executionStage coverage - all items should have a valid executionStage
211
+ */
212
+ function validateExecutionStageCoverage(config: Config): ValidationResult {
213
+ const allItems = [
214
+ ...config.checklist.core,
215
+ ...config.checklist.recommended,
216
+ ...config.checklist.optionalEnhancements,
217
+ ];
218
+
219
+ const errors: string[] = [];
220
+ const stageCounts: Record<string, number> = {};
221
+
222
+ for (const item of allItems) {
223
+ if (!item.executionStage) {
224
+ errors.push(`Item "${item.id}" is missing executionStage`);
225
+ } else if (!VALID_EXECUTION_STAGES.has(item.executionStage)) {
226
+ errors.push(
227
+ `Item "${item.id}" has invalid executionStage "${item.executionStage}"`,
228
+ );
229
+ } else {
230
+ stageCounts[item.executionStage] =
231
+ (stageCounts[item.executionStage] ?? 0) + 1;
232
+ }
233
+ }
234
+
235
+ // Log stage distribution (informational, not an error)
236
+ if (errors.length === 0 && Object.keys(stageCounts).length > 0) {
237
+ // This is just for debugging, not shown in normal output
238
+ }
239
+
240
+ return { valid: errors.length === 0, errors };
241
+ }
242
+
199
243
  /**
200
244
  * Generate a normalized, deterministic string representation of the config.
201
245
  * Uses deep stable key ordering at all depths.
@@ -236,6 +280,7 @@ export function validateStandardsConfig(
236
280
  validateStackReferences(config),
237
281
  validateCiHintKeys(config),
238
282
  validateCoverageThreshold(config),
283
+ validateExecutionStageCoverage(config),
239
284
  ];
240
285
 
241
286
  const allErrors = results.flatMap((r) => r.errors);
@@ -278,6 +323,7 @@ export function validateStandardsSchema(): void {
278
323
  console.log("✓ All appliesTo.stacks reference valid stack keys");
279
324
  console.log("✓ All ciHints keys are valid ciSystems");
280
325
  console.log("✓ Coverage threshold semantics are valid");
326
+ console.log("✓ All items have valid executionStage");
281
327
  }
282
328
 
283
329
  // CLI entry point