{"record":{"id":"fb1981aa068c401b","repo":"affaan-m/ECC","slug":"normalizepath-path-relative-root-outputpath","errorCode":null,"errorMessage":"${normalizePath(path.relative(ROOT, outputPath))} is out of date; run npm run command-registry:write","messagePattern":"(.+?) is out of date; run npm run command-registry:write","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/ci/generate-command-registry.js","lineNumber":227,"sourceCode":"}\n\nfunction writeRegistry(registry, outputPath = DEFAULT_OUTPUT_PATH) {\n  fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n  fs.writeFileSync(outputPath, formatRegistry(registry), 'utf8');\n}\n\nfunction checkRegistry(registry, outputPath = DEFAULT_OUTPUT_PATH) {\n  const expected = formatRegistry(registry);\n  let current;\n\n  try {\n    current = fs.readFileSync(outputPath, 'utf8');\n  } catch (error) {\n    throw new Error(`Failed to read ${normalizePath(path.relative(ROOT, outputPath))}: ${error.message}`);\n  }\n\n  if (current !== expected) {\n    throw new Error(`${normalizePath(path.relative(ROOT, outputPath))} is out of date; run npm run command-registry:write`);\n  }\n}\n\nfunction formatTextSummary(registry) {\n  const lines = [\n    'Command registry statistics',\n    '',\n    `Total commands: ${registry.totalCommands}`,\n    '',\n    'By type:',\n  ];\n\n  for (const [type, count] of Object.entries(registry.statistics.byType)) {\n    lines.push(`  ${type}: ${count}`);\n  }\n\n  lines.push('', 'Top agents:');\n  for (const { agent, count } of registry.statistics.topAgents) {","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/ci/generate-command-registry.js#L209-L245","documentation":"`checkRegistry` reads docs/COMMAND-REGISTRY.json and string-compares it to `formatRegistry(registry)` (the freshly-generated, pretty-printed JSON). If they differ by even one character, it throws `docs/COMMAND-REGISTRY.json is out of date; run npm run command-registry:write`. The registry is deterministic (sorted keys, 2-space indent, trailing newline), so any drift is real.","triggerScenarios":"Triggered by `--check` when a command file was added, removed, renamed, or edited (description/type/agent/skill references changed) without regenerating docs/COMMAND-REGISTRY.json. Also fires if the file's formatting (indent, trailing newline, key order) was altered by an editor or different Node version.","commonSituations":"A contributor adds a new command .md but forgets to run the write step. A command's frontmatter description is tweaked. A command file is renamed. Someone reformats the JSON with prettier (different indent). CI runs --check on a PR that touched commands/.","solutions":["Run `node scripts/ci/generate-command-registry.js --write` (or `npm run command-registry:write`) to regenerate the artifact, then commit it.","If you believe the diff is spurious, check formatting: the file must use 2-space indent, sorted object keys, and a single trailing newline.","Add the write step to your pre-commit flow so command edits automatically refresh the registry.","Re-run `--check` to confirm zero diff."],"exampleFix":"// before — added commands/my-command.md, did not regenerate registry\nnode scripts/ci/generate-command-registry.js --check\n// -> docs/COMMAND-REGISTRY.json is out of date; run npm run command-registry:write\n\n// after\nnode scripts/ci/generate-command-registry.js --write\ngit add docs/COMMAND-REGISTRY.json\ngit commit -m \"chore: regenerate command registry\"","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst { generateRegistry, formatRegistry } = require('./scripts/ci/generate-command-registry.js');\nconst expected = formatRegistry(generateRegistry());\nconst current = fs.readFileSync('docs/COMMAND-REGISTRY.json', 'utf8');\nif (current !== expected) {\n  console.error('docs/COMMAND-REGISTRY.json is stale. Run: npm run command-registry:write');\n  process.exit(1);\n}","typeGuard":"function registryIsUpToDate(root, outputPath) {\n  const { generateRegistry, formatRegistry } = require('./scripts/ci/generate-command-registry.js');\n  const expected = formatRegistry(generateRegistry({ root }));\n  try {\n    return fs.readFileSync(outputPath, 'utf8') === expected;\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  run(['--check']);\n} catch (error) {\n  if (/is out of date/i.test(error.message)) {\n    console.error('Regenerate: node scripts/ci/generate-command-registry.js --write && git add docs/COMMAND-REGISTRY.json');\n  }\n  throw error;\n}","preventionTips":["Run `npm run command-registry:write` whenever you add, remove, rename, or edit a file in commands/.","Commit the regenerated artifact in the same commit as the command change.","Do not reformat docs/COMMAND-REGISTRY.json with prettier — the check requires 2-space indent + trailing newline + sorted keys.","Add a pre-commit hook that runs `--check` when commands/ is touched."],"tags":["ci","command-registry","artifact-stale","documentation-drift","deterministic"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}