@forge-ts/enforcer 0.19.2 → 0.19.4

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 CHANGED
@@ -250,7 +250,7 @@ async function enforce(config) {
250
250
  for (const symbol of symbols) {
251
251
  if (!symbol.exported) continue;
252
252
  if (ignoreSet.has(symbol.name)) continue;
253
- if (symbol.documentation?.tags?.["forge-ignore"] !== void 0) continue;
253
+ if (symbol.documentation?.tags?.forgeIgnore !== void 0) continue;
254
254
  if (symbol.kind === "file") continue;
255
255
  const isFunctionLike = symbol.kind === "function" || symbol.kind === "method";
256
256
  if (!hasSummary(symbol)) {
@@ -574,7 +574,7 @@ async function enforce(config) {
574
574
  for (const symbol of symbols) {
575
575
  if (!symbol.exported) continue;
576
576
  if (ignoreSet.has(symbol.name)) continue;
577
- if (symbol.documentation?.tags?.["forge-ignore"] !== void 0) continue;
577
+ if (symbol.documentation?.tags?.forgeIgnore !== void 0) continue;
578
578
  const isFn = symbol.kind === "function" || symbol.kind === "method";
579
579
  if (!isFn) continue;
580
580
  const examples = symbol.documentation?.examples ?? [];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/deprecation-tracker.ts","../src/enforcer.ts","../src/formatter.ts"],"sourcesContent":["import type { ForgeSymbol } from \"@forge-ts/core\";\n\n/** A detected usage of a deprecated symbol. */\nexport interface DeprecatedUsage {\n\t/** The deprecated symbol being consumed. */\n\tdeprecatedSymbol: string;\n\t/** The package that exports the deprecated symbol. */\n\tsourcePackage: string;\n\t/** The file importing the deprecated symbol. */\n\tconsumingFile: string;\n\t/** Line number of the import. */\n\tline: number;\n\t/** The deprecation message. */\n\tdeprecationMessage: string;\n}\n\n/**\n * Scans symbols for imports of deprecated exports from other packages.\n *\n * @param symbols - All symbols from the walker across the entire project.\n * @returns Array of deprecated usages found.\n */\nexport function findDeprecatedUsages(symbols: ForgeSymbol[]): DeprecatedUsage[] {\n\t// Build a set of deprecated symbol names with their source info\n\tconst deprecatedExports = new Map<string, { sourceFile: string; message: string }>();\n\n\tfor (const symbol of symbols) {\n\t\tif (symbol.exported && symbol.documentation?.deprecated) {\n\t\t\tdeprecatedExports.set(symbol.name, {\n\t\t\t\tsourceFile: symbol.filePath,\n\t\t\t\tmessage: symbol.documentation.deprecated,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (deprecatedExports.size === 0) return [];\n\n\t// For each symbol that has a {@link} or references a deprecated name,\n\t// check if it's from a different package\n\tconst usages: DeprecatedUsage[] = [];\n\n\t// Check links\n\tfor (const symbol of symbols) {\n\t\tconst links = symbol.documentation?.links ?? [];\n\t\tfor (const link of links) {\n\t\t\tconst deprecated = deprecatedExports.get(link.target);\n\t\t\tif (deprecated && deprecated.sourceFile !== symbol.filePath) {\n\t\t\t\t// Different file references a deprecated symbol\n\t\t\t\tconst sourcePackage = extractPackageName(deprecated.sourceFile);\n\t\t\t\tconst consumingPackage = extractPackageName(symbol.filePath);\n\n\t\t\t\tif (sourcePackage !== consumingPackage) {\n\t\t\t\t\tusages.push({\n\t\t\t\t\t\tdeprecatedSymbol: link.target,\n\t\t\t\t\t\tsourcePackage,\n\t\t\t\t\t\tconsumingFile: symbol.filePath,\n\t\t\t\t\t\tline: link.line,\n\t\t\t\t\t\tdeprecationMessage: deprecated.message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn usages;\n}\n\n/** Extract package name from file path (e.g., \"packages/core/src/...\" -> \"core\"). */\nfunction extractPackageName(filePath: string): string {\n\tconst match = filePath.match(/packages\\/([^/]+)\\//);\n\treturn match?.[1] ?? \"root\";\n}\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport {\n\tcreateWalker,\n\ttype EnforceRules,\n\ttype ForgeConfig,\n\ttype ForgeError,\n\ttype ForgeResult,\n\ttype ForgeSymbol,\n\ttype ForgeWarning,\n\tfilterByVisibility,\n\tisRuleBypassed,\n\treadLockFile,\n\tvalidateAgainstLock,\n} from \"@forge-ts/core\";\nimport { findDeprecatedUsages } from \"./deprecation-tracker.js\";\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Checks whether a symbol has at least a summary in its documentation.\n * @internal\n */\nfunction hasSummary(symbol: ForgeSymbol): boolean {\n\treturn (\n\t\tsymbol.documentation?.summary !== undefined && symbol.documentation.summary.trim().length > 0\n\t);\n}\n\n/**\n * Splits a signature parameter list on top-level commas, respecting angle\n * bracket nesting so that `Record<string, string[]>` is not split.\n * @internal\n */\nfunction splitParams(raw: string): string[] {\n\tconst parts: string[] = [];\n\tlet depth = 0;\n\tlet current = \"\";\n\tfor (const ch of raw) {\n\t\tif (ch === \"<\" || ch === \"(\") {\n\t\t\tdepth++;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \">\" || ch === \")\") {\n\t\t\tdepth--;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \",\" && depth === 0) {\n\t\t\tparts.push(current);\n\t\t\tcurrent = \"\";\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\tif (current.trim()) {\n\t\tparts.push(current);\n\t}\n\treturn parts;\n}\n\n/**\n * Returns the names of parameters that are declared on a function/method symbol\n * but lack a corresponding `@param` tag in its documentation.\n *\n * Since the AST walker populates `documentation.params` from parsed TSDoc, we\n * compare the set of documented param names against the names that appear in\n * the symbol's type signature. When no signature is available the check is\n * skipped (returns empty array).\n *\n * @internal\n */\nfunction undocumentedParams(symbol: ForgeSymbol): string[] {\n\tconst sig = symbol.signature;\n\tif (!sig) return [];\n\n\t// Parse parameter names out of the signature string.\n\t// Signatures look like: \"(a: string, b: number) => void\"\n\t// Must handle nested generics: \"(tags: Record<string, string[]>) => void\"\n\tconst parenMatch = sig.match(/^\\(([^)]*)\\)/);\n\tif (!parenMatch || !parenMatch[1].trim()) return [];\n\n\tconst rawParams = splitParams(parenMatch[1])\n\t\t.map((p) =>\n\t\t\tp\n\t\t\t\t.trim()\n\t\t\t\t.split(\":\")[0]\n\t\t\t\t.trim()\n\t\t\t\t.replace(/^\\.{3}/, \"\")\n\t\t\t\t.replace(/\\?$/, \"\")\n\t\t\t\t.trim(),\n\t\t)\n\t\t.filter((p) => p.length > 0 && p !== \"this\");\n\n\tif (rawParams.length === 0) return [];\n\n\tconst documentedNames = new Set((symbol.documentation?.params ?? []).map((p) => p.name));\n\treturn rawParams.filter((name) => !documentedNames.has(name));\n}\n\n/**\n * Returns `true` when a function/method symbol has a non-void return type but\n * no `@returns` block in its documentation.\n * @internal\n */\nfunction missingReturns(symbol: ForgeSymbol): boolean {\n\tconst sig = symbol.signature;\n\tif (!sig) return false;\n\n\t// Extract return type: everything after the last \"=>\"\n\tconst arrowIdx = sig.lastIndexOf(\"=>\");\n\tif (arrowIdx === -1) return false;\n\tconst returnType = sig.slice(arrowIdx + 2).trim();\n\n\tconst isVoidLike =\n\t\treturnType === \"void\" ||\n\t\treturnType === \"never\" ||\n\t\treturnType === \"undefined\" ||\n\t\treturnType.startsWith(\"Promise<void>\") ||\n\t\treturnType.startsWith(\"Promise<never>\") ||\n\t\treturnType.startsWith(\"Promise<undefined>\");\n\n\tif (isVoidLike) return false;\n\treturn symbol.documentation?.returns === undefined;\n}\n\n/**\n * Returns `true` when a `@deprecated` tag is present but carries no\n * explanatory text.\n * @internal\n */\nfunction deprecatedWithoutReason(symbol: ForgeSymbol): boolean {\n\tconst deprecated = symbol.documentation?.deprecated;\n\tif (deprecated === undefined) return false;\n\t// The walker stores `\"true\"` when the tag has no content.\n\treturn deprecated === \"true\" || deprecated.trim().length === 0;\n}\n\n/**\n * Extracts generic type parameter names from a symbol's signature.\n * Handles patterns like `<T>`, `<T, U>`, `<T extends Record<string, unknown>>`, etc.\n * Respects nested angle brackets so constraints are not prematurely closed.\n * @internal\n */\nfunction extractGenericTypeParams(signature: string | undefined): string[] {\n\tif (!signature || !signature.startsWith(\"<\")) return [];\n\t// Find the matching closing '>' respecting nesting\n\tlet depth = 0;\n\tlet endIdx = -1;\n\tfor (let i = 0; i < signature.length; i++) {\n\t\tif (signature[i] === \"<\") depth++;\n\t\telse if (signature[i] === \">\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) {\n\t\t\t\tendIdx = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (endIdx === -1) return [];\n\tconst inner = signature.slice(1, endIdx);\n\t// Split on top-level commas (depth 0)\n\tconst params: string[] = [];\n\tlet paramDepth = 0;\n\tlet current = \"\";\n\tfor (const ch of inner) {\n\t\tif (ch === \"<\" || ch === \"(\") {\n\t\t\tparamDepth++;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \">\" || ch === \")\") {\n\t\t\tparamDepth--;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \",\" && paramDepth === 0) {\n\t\t\tparams.push(current);\n\t\t\tcurrent = \"\";\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\tif (current.trim()) params.push(current);\n\treturn params.map((p) => p.trim().split(/\\s+/)[0].trim()).filter((p) => p.length > 0);\n}\n\n/**\n * Returns `true` when a property signature looks optional —\n * i.e. includes `| undefined` in the type.\n * @internal\n */\nfunction isOptionalProperty(child: ForgeSymbol): boolean {\n\tconst sig = child.signature;\n\tif (!sig) return false;\n\tif (sig.includes(\"| undefined\") || sig.includes(\"undefined |\")) return true;\n\treturn false;\n}\n\n/**\n * Extracts a flat map of biome rule names to their configured level\n * from a parsed biome.json structure.\n * Walks `linter.rules.<group>.<ruleName>` and normalises both string\n * and object (`{ level: \"error\" }`) forms.\n * @internal\n */\nfunction extractBiomeRules(biome: Record<string, unknown>): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\tconst linter = biome.linter as Record<string, unknown> | undefined;\n\tif (!linter) return result;\n\tconst rules = linter.rules as Record<string, unknown> | undefined;\n\tif (!rules) return result;\n\tfor (const [group, groupRules] of Object.entries(rules)) {\n\t\tif (\n\t\t\tgroup === \"recommended\" ||\n\t\t\tgroup === \"all\" ||\n\t\t\ttypeof groupRules !== \"object\" ||\n\t\t\tgroupRules === null\n\t\t)\n\t\t\tcontinue;\n\t\tfor (const [ruleName, ruleValue] of Object.entries(groupRules as Record<string, unknown>)) {\n\t\t\tconst fullName = `${group}/${ruleName}`;\n\t\t\tif (typeof ruleValue === \"string\") {\n\t\t\t\tresult[fullName] = ruleValue;\n\t\t\t} else if (typeof ruleValue === \"object\" && ruleValue !== null && \"level\" in ruleValue) {\n\t\t\t\tresult[fullName] = String((ruleValue as Record<string, unknown>).level);\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Returns `true` when `current` is a weaker biome level than `locked`.\n * Ranking: error > warn > off.\n * @internal\n */\nfunction isWeakerBiomeLevel(current: string, locked: string): boolean {\n\tconst rank: Record<string, number> = { off: 0, warn: 1, error: 2 };\n\tconst currentRank = rank[current] ?? 0;\n\tconst lockedRank = rank[locked] ?? 0;\n\treturn currentRank < lockedRank;\n}\n\n/**\n * Extracts major.minor from a semver-like string.\n * Handles patterns like \">=22.0.0\", \"^22.0.0\", \"~22.0.0\", \"22.0.0\", \"22.0\".\n * @internal\n */\nfunction parseSemverMajorMinor(version: string): [number, number] | null {\n\tconst match = version.match(/(\\d+)\\.(\\d+)/);\n\tif (!match) return null;\n\treturn [Number(match[1]), Number(match[2])];\n}\n\n/**\n * Compares two [major, minor] tuples.\n * Returns negative if a < b, 0 if equal, positive if a > b.\n * @internal\n */\nfunction compareMajorMinor(a: [number, number], b: [number, number]): number {\n\tif (a[0] !== b[0]) return a[0] - b[0];\n\treturn a[1] - b[1];\n}\n\n// ---------------------------------------------------------------------------\n// Rule map\n// ---------------------------------------------------------------------------\n\n/**\n * Maps E-code strings to their corresponding {@link EnforceRules} key.\n * @internal\n */\nconst RULE_MAP: Record<string, keyof EnforceRules> = {\n\tE001: \"require-summary\",\n\tE002: \"require-param\",\n\tE003: \"require-returns\",\n\tE004: \"require-example\",\n\tE005: \"require-package-doc\",\n\tE006: \"require-class-member-doc\",\n\tE007: \"require-interface-member-doc\",\n\tW006: \"require-tsdoc-syntax\",\n\tE013: \"require-remarks\",\n\tE014: \"require-default-value\",\n\tE015: \"require-type-param\",\n\tW005: \"require-see\",\n\tE016: \"require-release-tag\",\n\tW007: \"require-fresh-guides\",\n\tW008: \"require-guide-coverage\",\n\tE017: \"require-internal-boundary\",\n\tE018: \"require-route-response\",\n\tW009: \"require-inheritdoc-source\",\n\tW010: \"require-migration-path\",\n\tW011: \"require-since\",\n\tE019: \"require-no-ts-ignore\",\n\tE020: \"require-no-any-in-api\",\n\tW012: \"require-fresh-link-text\",\n\tW013: \"require-fresh-examples\",\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the TSDoc enforcement pass against a project.\n *\n * The enforcer walks all exported symbols that meet the configured minimum\n * visibility threshold and emits diagnostics for any documentation deficiencies\n * it finds.\n *\n * ### Error codes\n * | Code | Severity | Condition |\n * |------|----------|-----------|\n * | E001 | error | Exported symbol is missing a TSDoc summary. |\n * | E002 | error | Function/method parameter lacks a `@param` tag. |\n * | E003 | error | Non-void function/method lacks a `@returns` tag. |\n * | E004 | error | Exported function/method is missing an `@example` block. |\n * | E005 | error | Package entry point (index.ts) is missing `@packageDocumentation`. |\n * | E006 | error | Public/protected class member is missing a TSDoc comment. |\n * | E007 | error | Interface/type alias property is missing a TSDoc comment. |\n * | W001 | warning | TSDoc comment contains parse errors. |\n * | W002 | warning | Function body throws but has no `@throws` tag. |\n * | W003 | warning | `@deprecated` tag is present without explanation. |\n * | W006 | warning | TSDoc parser-level syntax error (invalid tag, malformed block, etc.). |\n * | E009 | error | tsconfig.json required strict-mode flag is missing or disabled (guard). |\n * | E010 | error | Config drift: a rule severity is weaker than the locked value. |\n * | E013 | error | Exported function/class is missing a `@remarks` block. |\n * | E014 | warn | Optional property of interface/type is missing `@defaultValue`. |\n * | E015 | error | Generic symbol is missing `@typeParam` for a type parameter. |\n * | W005 | warn | Symbol references other symbols via `{@link}` but has no `@see` tags. |\n * | W007 | warn | Guide FORGE:AUTO section references a symbol that no longer exists. |\n * | W008 | warn | Exported public symbol is not mentioned in any guide page. |\n * | E017 | error | `@internal` symbol re-exported through public barrel (index.ts). |\n * | E018 | warn | `@route`-tagged function missing `@response` tag. |\n * | W009 | warn | `{@inheritDoc}` references a symbol that does not exist. |\n * | W010 | warn | `@breaking` tag present without `@migration` path. |\n * | W011 | warn | New public export missing `@since` version tag. |\n *\n * When `config.enforce.strict` is `true` all warnings are promoted to errors.\n *\n * @param config - The resolved {@link ForgeConfig} for the project.\n * @returns A {@link ForgeResult} describing which symbols passed or failed.\n * @example\n * ```typescript\n * import { loadConfig } from \"@forge-ts/core\";\n * import { enforce } from \"@forge-ts/enforcer\";\n * const config = await loadConfig();\n * const result = await enforce(config);\n * if (!result.success) {\n * console.error(`${result.errors.length} errors found`);\n * }\n * ```\n * @public\n */\nexport async function enforce(config: ForgeConfig): Promise<ForgeResult> {\n\tconst start = Date.now();\n\tconst errors: ForgeError[] = [];\n\tconst warnings: ForgeWarning[] = [];\n\n\tconst walker = createWalker(config);\n\tconst allSymbols = walker.walk();\n\tconst symbols = filterByVisibility(allSymbols, config.enforce.minVisibility);\n\n\t// ---------------------------------------------------------------------------\n\t// Ignore file: read symbol names to skip enforcement on (Knip integration)\n\t// ---------------------------------------------------------------------------\n\tconst ignoreSet = new Set<string>();\n\tif (config.enforce.ignoreFile) {\n\t\tconst ignoreFilePath = resolve(config.rootDir, config.enforce.ignoreFile);\n\t\tif (existsSync(ignoreFilePath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(ignoreFilePath, \"utf-8\");\n\t\t\t\tfor (const rawLine of content.split(\"\\n\")) {\n\t\t\t\t\tconst trimmed = rawLine.trim();\n\t\t\t\t\tif (trimmed.length > 0 && !trimmed.startsWith(\"#\")) {\n\t\t\t\t\t\tignoreSet.add(trimmed);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore read errors gracefully\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Emit a diagnostic. The configured per-rule severity determines whether\n\t * the diagnostic is an error or warning; \"off\" suppresses it entirely.\n\t * When `strict` is enabled every warning is promoted to an error.\n\t */\n\tfunction emit(\n\t\tcode: string,\n\t\tmessage: string,\n\t\tfilePath: string,\n\t\tline: number,\n\t\tcolumn: number,\n\t\tguidance?: { suggestedFix?: string; symbolName?: string; symbolKind?: string },\n\t): void {\n\t\tconst ruleKey = RULE_MAP[code];\n\n\t\t// For rule codes tracked in the map, honour the per-rule severity.\n\t\tif (ruleKey !== undefined) {\n\t\t\tconst configuredSeverity = config.enforce.rules[ruleKey];\n\t\t\tif (configuredSeverity === \"off\") return;\n\t\t\tconst effectiveSeverity = config.enforce.strict ? \"error\" : configuredSeverity;\n\t\t\tconst diag = { code, message, filePath, line, column, ...guidance };\n\t\t\tif (effectiveSeverity === \"error\") {\n\t\t\t\terrors.push(diag);\n\t\t\t} else {\n\t\t\t\twarnings.push(diag);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// For codes not in the map (W003, E008, etc.) fall back to the old\n\t\t// behaviour: always emit, respect strict mode for warnings.\n\t\tconst diag = { code, message, filePath, line, column, ...guidance };\n\t\t// Codes starting with \"W\" are warnings by default.\n\t\tif (code.startsWith(\"W\") && !config.enforce.strict) {\n\t\t\twarnings.push(diag);\n\t\t} else {\n\t\t\terrors.push(diag);\n\t\t}\n\t}\n\n\tfor (const symbol of symbols) {\n\t\tif (!symbol.exported) continue;\n\n\t\t// Skip enforcement for symbols in the ignore file (Knip dead-export integration)\n\t\tif (ignoreSet.has(symbol.name)) continue;\n\n\t\t// Skip enforcement for symbols with @forge-ignore tag\n\t\tif (symbol.documentation?.tags?.[\"forge-ignore\"] !== undefined) continue;\n\n\t\t// Skip specific rules for the \"file\" symbol (which just carries @packageDocumentation)\n\t\tif (symbol.kind === \"file\") continue;\n\n\t\tconst isFunctionLike = symbol.kind === \"function\" || symbol.kind === \"method\";\n\n\t\t// E001 — Missing summary\n\t\tif (!hasSummary(symbol)) {\n\t\t\temit(\n\t\t\t\t\"E001\",\n\t\t\t\t`Exported symbol \"${symbol.name}\" is missing a TSDoc summary comment.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `/**\\n * [Description of ${symbol.name}]\\n */`,\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// E002 — Undocumented parameters\n\t\tif (isFunctionLike) {\n\t\t\tconst missing = undocumentedParams(symbol);\n\t\t\tfor (const paramName of missing) {\n\t\t\t\temit(\n\t\t\t\t\t\"E002\",\n\t\t\t\t\t`Parameter \"${paramName}\" of \"${symbol.name}\" is not documented with a @param tag.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `@param ${paramName} - [Description of ${paramName}]`,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E003 — Missing @returns\n\t\tif (isFunctionLike && missingReturns(symbol)) {\n\t\t\temit(\n\t\t\t\t\"E003\",\n\t\t\t\t`\"${symbol.name}\" has a non-void return type but is missing a @returns tag.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `@returns [Description of the return value]`,\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// E004 — Missing @example\n\t\tif (isFunctionLike && symbol.documentation) {\n\t\t\tconst hasExample = (symbol.documentation.examples ?? []).length > 0;\n\t\t\tif (!hasExample) {\n\t\t\t\temit(\n\t\t\t\t\t\"E004\",\n\t\t\t\t\t`Exported function \"${symbol.name}\" is missing an @example block. Add a fenced code block showing usage.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `@example\\n * \\`\\`\\`typescript\\n * // Usage of ${symbol.name}\\n * ${symbol.name}();\\n * \\`\\`\\``,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E006 — Class member missing documentation\n\t\t// E007 — Interface/type member missing documentation\n\t\tif (symbol.kind === \"class\" || symbol.kind === \"interface\") {\n\t\t\tconst errorCode = symbol.kind === \"class\" ? \"E006\" : \"E007\";\n\t\t\tfor (const child of symbol.children ?? []) {\n\t\t\t\tif (child.kind === \"property\" || child.kind === \"method\") {\n\t\t\t\t\tif (!hasSummary(child)) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\terrorCode,\n\t\t\t\t\t\t\t`Member \"${child.name}\" of ${symbol.kind} \"${symbol.name}\" is missing a TSDoc comment.`,\n\t\t\t\t\t\t\tchild.filePath,\n\t\t\t\t\t\t\tchild.line,\n\t\t\t\t\t\t\tchild.column,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsuggestedFix: `/**\\n * [Description of ${child.name}]\\n */`,\n\t\t\t\t\t\t\t\tsymbolName: child.name,\n\t\t\t\t\t\t\t\tsymbolKind: child.kind,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// E013 — Missing @remarks on exported functions/classes\n\t\tif (symbol.kind === \"function\" || symbol.kind === \"class\") {\n\t\t\tconst hasRemarks = symbol.documentation?.tags?.remarks !== undefined;\n\t\t\tif (!hasRemarks) {\n\t\t\t\temit(\n\t\t\t\t\t\"E013\",\n\t\t\t\t\t`Exported ${symbol.kind} \"${symbol.name}\" is missing a @remarks block.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `@remarks [Detailed description of ${symbol.name}]`,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E014 — Missing @defaultValue on optional properties of interfaces/types\n\t\tif (symbol.kind === \"interface\" || symbol.kind === \"type\") {\n\t\t\tfor (const child of symbol.children ?? []) {\n\t\t\t\tif (child.kind !== \"property\") continue;\n\t\t\t\tif (!isOptionalProperty(child)) continue;\n\t\t\t\tconst hasDefaultValue = child.documentation?.tags?.defaultValue !== undefined;\n\t\t\t\tif (!hasDefaultValue) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"E014\",\n\t\t\t\t\t\t`Optional property \"${child.name}\" of ${symbol.kind} \"${symbol.name}\" is missing @defaultValue.`,\n\t\t\t\t\t\tchild.filePath,\n\t\t\t\t\t\tchild.line,\n\t\t\t\t\t\tchild.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuggestedFix: `@defaultValue [Default value of ${child.name}]`,\n\t\t\t\t\t\t\tsymbolName: child.name,\n\t\t\t\t\t\t\tsymbolKind: child.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// E015 — Missing @typeParam on generic symbols\n\t\tif (symbol.kind === \"function\" || symbol.kind === \"class\" || symbol.kind === \"interface\") {\n\t\t\tconst typeParamNames = extractGenericTypeParams(symbol.signature);\n\t\t\tif (typeParamNames.length > 0) {\n\t\t\t\tconst documentedTypeParams = new Set(\n\t\t\t\t\t(symbol.documentation?.tags?.typeParam ?? []).map((tp) =>\n\t\t\t\t\t\ttp.split(/\\s/)[0].replace(/-$/, \"\").trim(),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tfor (const typeParamName of typeParamNames) {\n\t\t\t\t\tif (!documentedTypeParams.has(typeParamName)) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"E015\",\n\t\t\t\t\t\t\t`Type parameter \"${typeParamName}\" of \"${symbol.name}\" is not documented with @typeParam.`,\n\t\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\t\tsymbol.line,\n\t\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsuggestedFix: `@typeParam ${typeParamName} - [Description of ${typeParamName}]`,\n\t\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// W005 — {@link} references present but no @see tags\n\t\tif (symbol.documentation?.links && symbol.documentation.links.length > 0) {\n\t\t\tconst hasSee =\n\t\t\t\tsymbol.documentation.tags?.see !== undefined && symbol.documentation.tags.see.length > 0;\n\t\t\tif (!hasSee) {\n\t\t\t\temit(\n\t\t\t\t\t\"W005\",\n\t\t\t\t\t`\"${symbol.name}\" references other symbols via {@link} but has no @see tags.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: \"@see [Related symbol name]\",\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E016 — Missing release tag on exported symbols\n\t\t{\n\t\t\tconst releaseTags = [\"public\", \"beta\", \"internal\", \"alpha\"];\n\t\t\tconst hasReleaseTag = releaseTags.some(\n\t\t\t\t(tag) => symbol.documentation?.tags?.[tag] !== undefined,\n\t\t\t);\n\t\t\tif (!hasReleaseTag) {\n\t\t\t\temit(\n\t\t\t\t\t\"E016\",\n\t\t\t\t\t`Exported symbol \"${symbol.name}\" is missing a release tag (@public, @beta, or @internal).`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: \"@public\",\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E017 — @internal symbol re-exported through public barrel (index.ts)\n\t\tif (\n\t\t\tsymbol.documentation?.tags?.internal !== undefined &&\n\t\t\t/[/\\\\]index\\.ts$/.test(symbol.filePath)\n\t\t) {\n\t\t\temit(\n\t\t\t\t\"E017\",\n\t\t\t\t`@internal symbol \"${symbol.name}\" is re-exported through public barrel \"${symbol.filePath}\".`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `Remove \"${symbol.name}\" from the public barrel file (index.ts) or remove the @internal tag.`,\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// E018 — @route-tagged function missing @response\n\t\tif (symbol.documentation?.tags?.route && !symbol.documentation?.tags?.response) {\n\t\t\temit(\n\t\t\t\t\"E018\",\n\t\t\t\t`Route handler \"${symbol.name}\" is missing a @response tag. Document expected HTTP responses.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: \"@response 200 - Success response\",\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// W010 — @breaking without @migration\n\t\tif (symbol.documentation?.tags?.breaking && !symbol.documentation?.tags?.migration) {\n\t\t\temit(\n\t\t\t\t\"W010\",\n\t\t\t\t`\"${symbol.name}\" has a @breaking tag but no @migration path. Provide migration guidance.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: \"@migration [Describe how to migrate from the old API]\",\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// W011 — New public export missing @since\n\t\t{\n\t\t\tconst releaseTags = [\"public\", \"beta\", \"alpha\"];\n\t\t\tconst hasReleaseTag = releaseTags.some(\n\t\t\t\t(tag) => symbol.documentation?.tags?.[tag] !== undefined,\n\t\t\t);\n\t\t\tif (hasReleaseTag && !symbol.documentation?.tags?.since) {\n\t\t\t\temit(\n\t\t\t\t\t\"W011\",\n\t\t\t\t\t`Exported symbol \"${symbol.name}\" has a release tag but is missing @since version.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: \"@since 1.0.0\",\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E020 — `any` type in public API signature\n\t\tif (symbol.documentation?.tags?.internal === undefined && symbol.signature) {\n\t\t\tconst anyRegex = /\\bany\\b/g;\n\t\t\tif (anyRegex.test(symbol.signature)) {\n\t\t\t\temit(\n\t\t\t\t\t\"E020\",\n\t\t\t\t\t`Exported symbol \"${symbol.name}\" has \\`any\\` in its signature. Use a specific type or generic.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// W003 — @deprecated without reason\n\t\tif (deprecatedWithoutReason(symbol)) {\n\t\t\temit(\n\t\t\t\t\"W003\",\n\t\t\t\t`\"${symbol.name}\" is marked @deprecated but provides no explanation.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// W006 — TSDoc parser syntax messages\n\t\tif (symbol.documentation?.parseMessages) {\n\t\t\tfor (const msg of symbol.documentation.parseMessages) {\n\t\t\t\temit(\n\t\t\t\t\t\"W006\",\n\t\t\t\t\t`TSDoc syntax: ${msg.text} [${msg.messageId}]`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tmsg.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// W006 — TSDoc parser syntax messages on child symbols\n\t\tif (symbol.children) {\n\t\t\tfor (const child of symbol.children) {\n\t\t\t\tif (child.documentation?.parseMessages) {\n\t\t\t\t\tfor (const msg of child.documentation.parseMessages) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"W006\",\n\t\t\t\t\t\t\t`TSDoc syntax: ${msg.text} [${msg.messageId}]`,\n\t\t\t\t\t\t\tchild.filePath,\n\t\t\t\t\t\t\tmsg.line,\n\t\t\t\t\t\t\tchild.column,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsymbolName: child.name,\n\t\t\t\t\t\t\t\tsymbolKind: child.kind,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// W013 — Stale @example blocks (arg count mismatch with function signature)\n\tfor (const symbol of symbols) {\n\t\tif (!symbol.exported) continue;\n\t\tif (ignoreSet.has(symbol.name)) continue;\n\t\tif (symbol.documentation?.tags?.[\"forge-ignore\"] !== undefined) continue;\n\n\t\tconst isFn = symbol.kind === \"function\" || symbol.kind === \"method\";\n\t\tif (!isFn) continue;\n\n\t\tconst examples = symbol.documentation?.examples ?? [];\n\t\tif (examples.length === 0) continue;\n\n\t\t// Extract parameter count from signature\n\t\tconst sig = symbol.signature;\n\t\tif (!sig) continue;\n\n\t\tconst parenMatch = sig.match(/^\\(([^)]*)\\)/);\n\t\tif (!parenMatch) continue;\n\n\t\tconst rawParamStr = parenMatch[1].trim();\n\t\tlet paramCount = 0;\n\t\tif (rawParamStr.length > 0) {\n\t\t\tconst params = splitParams(rawParamStr)\n\t\t\t\t.map((p) =>\n\t\t\t\t\tp\n\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t.split(\":\")[0]\n\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t.replace(/^\\.{3}/, \"\")\n\t\t\t\t\t\t.replace(/\\?$/, \"\")\n\t\t\t\t\t\t.trim(),\n\t\t\t\t)\n\t\t\t\t.filter((p) => p.length > 0 && p !== \"this\");\n\t\t\tparamCount = params.length;\n\t\t}\n\n\t\t// Build a regex to find calls to this function in example code\n\t\tconst funcCallRegex = new RegExp(`\\\\b${symbol.name}\\\\s*\\\\(`, \"g\");\n\n\t\tfor (const example of examples) {\n\t\t\tfuncCallRegex.lastIndex = 0;\n\t\t\tlet callMatch = funcCallRegex.exec(example.code);\n\t\t\twhile (callMatch) {\n\t\t\t\t// Count arguments by finding the matching closing paren\n\t\t\t\tconst startIdx = callMatch.index + callMatch[0].length;\n\t\t\t\tlet depth = 1;\n\t\t\t\tlet idx = startIdx;\n\t\t\t\twhile (idx < example.code.length && depth > 0) {\n\t\t\t\t\tconst ch = example.code[idx];\n\t\t\t\t\tif (ch === \"(\" || ch === \"<\" || ch === \"[\" || ch === \"{\") depth++;\n\t\t\t\t\telse if (ch === \")\" || ch === \">\" || ch === \"]\" || ch === \"}\") depth--;\n\t\t\t\t\tidx++;\n\t\t\t\t}\n\t\t\t\t// Extract the arguments substring\n\t\t\t\tconst argsStr = example.code.slice(startIdx, idx - 1).trim();\n\t\t\t\tlet argCount = 0;\n\t\t\t\tif (argsStr.length > 0) {\n\t\t\t\t\t// Split on top-level commas\n\t\t\t\t\targCount = splitParams(argsStr).length;\n\t\t\t\t}\n\n\t\t\t\tif (argCount !== paramCount) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"W013\",\n\t\t\t\t\t\t`@example in \"${symbol.name}\" may be stale — function signature has ${paramCount} parameter(s) but example call has ${argCount} argument(s).`,\n\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\texample.line,\n\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcallMatch = funcCallRegex.exec(example.code);\n\t\t\t}\n\t\t}\n\t}\n\n\t// E019 — ts-ignore / ts-expect-error in non-test files\n\t// Scan each unique non-test source file that contains symbols for suppression directives.\n\t{\n\t\tconst tsIgnoreRegex = /\\/\\/\\s*@ts-(ignore|expect-error)/g;\n\t\tconst testPathRegex = /(\\.(test|spec)\\.ts$|__tests__[/\\\\])/;\n\t\tconst scannedFiles = new Set<string>();\n\t\tfor (const symbol of allSymbols) {\n\t\t\tif (scannedFiles.has(symbol.filePath)) continue;\n\t\t\tscannedFiles.add(symbol.filePath);\n\t\t\tif (testPathRegex.test(symbol.filePath)) continue;\n\t\t\ttry {\n\t\t\t\tconst fileContent = readFileSync(symbol.filePath, \"utf-8\");\n\t\t\t\tconst lines = fileContent.split(\"\\n\");\n\t\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\t\ttsIgnoreRegex.lastIndex = 0;\n\t\t\t\t\tif (tsIgnoreRegex.test(lines[i])) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"E019\",\n\t\t\t\t\t\t\t`Non-test file \"${symbol.filePath}\" contains @ts-ignore at line ${i + 1}. Remove the suppression or move the code to a test file.`,\n\t\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\t\ti + 1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Skip unreadable files\n\t\t\t}\n\t\t}\n\t}\n\n\t// E005 — Missing @packageDocumentation on index.ts entry points\n\t// Group symbols by file to check if any index.ts file lacks @packageDocumentation.\n\tconst indexFiles = new Map<string, ForgeSymbol[]>();\n\tfor (const symbol of allSymbols) {\n\t\tif (symbol.filePath.endsWith(\"index.ts\")) {\n\t\t\tconst bucket = indexFiles.get(symbol.filePath) ?? [];\n\t\t\tbucket.push(symbol);\n\t\t\tindexFiles.set(symbol.filePath, bucket);\n\t\t}\n\t}\n\tfor (const [filePath, fileSymbols] of indexFiles) {\n\t\tconst hasPackageDoc = fileSymbols.some(\n\t\t\t(s) => s.documentation?.tags?.packageDocumentation !== undefined,\n\t\t);\n\t\tif (!hasPackageDoc) {\n\t\t\temit(\n\t\t\t\t\"E005\",\n\t\t\t\t`Package entry point \"${filePath}\" is missing a @packageDocumentation TSDoc comment.`,\n\t\t\t\tfilePath,\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `/**\\n * @packageDocumentation\\n * [Package overview description]\\n */`,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\t// E008 — Dead {@link} references\n\t// Build a set of all known symbol names (simple and qualified).\n\tconst knownSymbols = new Set<string>();\n\tfor (const s of allSymbols) {\n\t\tknownSymbols.add(s.name);\n\t\tif (s.children) {\n\t\t\tfor (const child of s.children) {\n\t\t\t\tknownSymbols.add(`${s.name}.${child.name}`);\n\t\t\t\tknownSymbols.add(child.name);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check all {@link} references across every symbol (not just filtered ones).\n\tfor (const symbol of allSymbols) {\n\t\tconst docLinks = symbol.documentation?.links ?? [];\n\t\tfor (const link of docLinks) {\n\t\t\tif (!knownSymbols.has(link.target)) {\n\t\t\t\temit(\n\t\t\t\t\t\"E008\",\n\t\t\t\t\t`{@link ${link.target}} in \"${symbol.name}\" references a symbol that does not exist in this project.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tlink.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `Remove or update the {@link ${link.target}} reference to point to an existing symbol.`,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// W012 — Orphaned {@link} display text detection\n\t// Build a map of symbol name → summary for comparison with link display text.\n\t{\n\t\tconst COMMON_WORDS = new Set([\n\t\t\t\"the\",\n\t\t\t\"a\",\n\t\t\t\"an\",\n\t\t\t\"is\",\n\t\t\t\"are\",\n\t\t\t\"was\",\n\t\t\t\"were\",\n\t\t\t\"be\",\n\t\t\t\"been\",\n\t\t\t\"being\",\n\t\t\t\"have\",\n\t\t\t\"has\",\n\t\t\t\"had\",\n\t\t\t\"do\",\n\t\t\t\"does\",\n\t\t\t\"did\",\n\t\t\t\"will\",\n\t\t\t\"would\",\n\t\t\t\"could\",\n\t\t\t\"should\",\n\t\t\t\"may\",\n\t\t\t\"might\",\n\t\t\t\"shall\",\n\t\t\t\"can\",\n\t\t\t\"need\",\n\t\t\t\"must\",\n\t\t\t\"to\",\n\t\t\t\"of\",\n\t\t\t\"in\",\n\t\t\t\"for\",\n\t\t\t\"on\",\n\t\t\t\"with\",\n\t\t\t\"at\",\n\t\t\t\"by\",\n\t\t\t\"from\",\n\t\t\t\"as\",\n\t\t\t\"into\",\n\t\t\t\"through\",\n\t\t\t\"during\",\n\t\t\t\"before\",\n\t\t\t\"after\",\n\t\t\t\"above\",\n\t\t\t\"below\",\n\t\t\t\"between\",\n\t\t\t\"out\",\n\t\t\t\"off\",\n\t\t\t\"over\",\n\t\t\t\"under\",\n\t\t\t\"and\",\n\t\t\t\"but\",\n\t\t\t\"or\",\n\t\t\t\"nor\",\n\t\t\t\"not\",\n\t\t\t\"so\",\n\t\t\t\"yet\",\n\t\t\t\"both\",\n\t\t\t\"either\",\n\t\t\t\"neither\",\n\t\t\t\"each\",\n\t\t\t\"every\",\n\t\t\t\"all\",\n\t\t\t\"any\",\n\t\t\t\"few\",\n\t\t\t\"more\",\n\t\t\t\"most\",\n\t\t\t\"other\",\n\t\t\t\"some\",\n\t\t\t\"such\",\n\t\t\t\"no\",\n\t\t\t\"only\",\n\t\t\t\"own\",\n\t\t\t\"same\",\n\t\t\t\"than\",\n\t\t\t\"too\",\n\t\t\t\"very\",\n\t\t\t\"this\",\n\t\t\t\"that\",\n\t\t\t\"these\",\n\t\t\t\"those\",\n\t\t\t\"it\",\n\t\t\t\"its\",\n\t\t]);\n\n\t\tconst symbolSummaryMap = new Map<string, string>();\n\t\tfor (const s of allSymbols) {\n\t\t\tif (s.documentation?.summary) {\n\t\t\t\tsymbolSummaryMap.set(s.name, s.documentation.summary);\n\t\t\t}\n\t\t\tif (s.children) {\n\t\t\t\tfor (const child of s.children) {\n\t\t\t\t\tif (child.documentation?.summary) {\n\t\t\t\t\t\tsymbolSummaryMap.set(child.name, child.documentation.summary);\n\t\t\t\t\t\tsymbolSummaryMap.set(`${s.name}.${child.name}`, child.documentation.summary);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction extractSignificantWords(text: string): Set<string> {\n\t\t\treturn new Set(\n\t\t\t\ttext\n\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t.split(/\\W+/)\n\t\t\t\t\t.filter((w) => w.length > 0 && !COMMON_WORDS.has(w)),\n\t\t\t);\n\t\t}\n\n\t\tfor (const symbol of allSymbols) {\n\t\t\tconst docLinks = symbol.documentation?.links ?? [];\n\t\t\tfor (const link of docLinks) {\n\t\t\t\tif (!link.text) continue;\n\t\t\t\tif (!knownSymbols.has(link.target)) continue;\n\t\t\t\tconst targetSummary = symbolSummaryMap.get(link.target);\n\t\t\t\tif (!targetSummary) continue;\n\t\t\t\tconst linkWords = extractSignificantWords(link.text);\n\t\t\t\tconst summaryWords = extractSignificantWords(targetSummary);\n\t\t\t\tif (linkWords.size === 0 || summaryWords.size === 0) continue;\n\t\t\t\tlet overlap = 0;\n\t\t\t\tfor (const word of linkWords) {\n\t\t\t\t\tif (summaryWords.has(word)) overlap++;\n\t\t\t\t}\n\t\t\t\tif (overlap === 0) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"W012\",\n\t\t\t\t\t\t`{@link ${link.target} | ${link.text}} in \"${symbol.name}\" has display text that appears stale relative to target summary \"${targetSummary}\".`,\n\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\tlink.line,\n\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// W009 — {@inheritDoc} source doesn't exist\n\tfor (const symbol of allSymbols) {\n\t\tconst inheritDocTargets = symbol.documentation?.tags?.inheritDoc;\n\t\tif (inheritDocTargets && inheritDocTargets.length > 0) {\n\t\t\tfor (const target of inheritDocTargets) {\n\t\t\t\tif (!knownSymbols.has(target)) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"W009\",\n\t\t\t\t\t\t`{@inheritDoc ${target}} in \"${symbol.name}\" references a symbol that does not exist in this project.`,\n\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\tsymbol.line,\n\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuggestedFix: `Remove or update the {@inheritDoc ${target}} reference to point to an existing symbol.`,\n\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// W004 — Cross-package deprecated symbol usage\n\tconst deprecatedUsages = findDeprecatedUsages(allSymbols);\n\tfor (const usage of deprecatedUsages) {\n\t\temit(\n\t\t\t\"W004\",\n\t\t\t`Import of deprecated symbol \"${usage.deprecatedSymbol}\" from package \"${usage.sourcePackage}\": ${usage.deprecationMessage}`,\n\t\t\tusage.consumingFile,\n\t\t\tusage.line,\n\t\t\t0,\n\t\t\t{\n\t\t\t\tsuggestedFix: `Replace usage of \"${usage.deprecatedSymbol}\" with its recommended replacement.`,\n\t\t\t\tsymbolName: usage.deprecatedSymbol,\n\t\t\t\tsymbolKind: \"variable\",\n\t\t\t},\n\t\t);\n\t}\n\n\t// E009 — tsconfig strictness regression\n\tconst e009Bypassed = isRuleBypassed(config.rootDir, \"E009\");\n\tif (config.guards.tsconfig.enabled) {\n\t\tconst tsconfigPath = join(config.rootDir, \"tsconfig.json\");\n\t\ttry {\n\t\t\tconst raw = readFileSync(tsconfigPath, \"utf-8\");\n\t\t\tlet parsed: { compilerOptions?: Record<string, unknown> } | undefined;\n\t\t\ttry {\n\t\t\t\tparsed = JSON.parse(raw) as { compilerOptions?: Record<string, unknown> };\n\t\t\t} catch (parseErr) {\n\t\t\t\tif (e009Bypassed) {\n\t\t\t\t\twarnings.push({\n\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\tmessage: `[BYPASSED] tsconfig.json: failed to parse — ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,\n\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\tmessage: `tsconfig.json: failed to parse — ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,\n\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (parsed) {\n\t\t\t\tconst compilerOptions = parsed.compilerOptions ?? {};\n\t\t\t\tconst requiredFlags = config.guards.tsconfig.requiredFlags;\n\t\t\t\tfor (const flag of requiredFlags) {\n\t\t\t\t\tconst value = compilerOptions[flag];\n\t\t\t\t\tif (value !== true) {\n\t\t\t\t\t\tif (e009Bypassed) {\n\t\t\t\t\t\t\twarnings.push({\n\t\t\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\t\t\tmessage: `[BYPASSED] tsconfig.json: required flag \"${flag}\" is ${value === false ? \"disabled\" : \"missing\"} — expected true`,\n\t\t\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\terrors.push({\n\t\t\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\t\t\tmessage: `tsconfig.json: required flag \"${flag}\" is ${value === false ? \"disabled\" : \"missing\"} — expected true`,\n\t\t\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (readErr) {\n\t\t\t// tsconfig.json not found — skip E009 gracefully\n\t\t\tif (\n\t\t\t\treadErr instanceof Error &&\n\t\t\t\t\"code\" in readErr &&\n\t\t\t\t(readErr as NodeJS.ErrnoException).code === \"ENOENT\"\n\t\t\t) {\n\t\t\t\t// Intentionally ignored: missing tsconfig.json is not an E009 error\n\t\t\t} else {\n\t\t\t\tthrow readErr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// E010 — forge-ts config drift detection via lock file\n\tconst e010Bypassed = isRuleBypassed(config.rootDir, \"E010\");\n\tconst lockManifest = readLockFile(config.rootDir);\n\tif (lockManifest) {\n\t\tconst lockViolations = validateAgainstLock(config, lockManifest);\n\t\tconst lockFilePath = join(config.rootDir, \".forge-lock.json\");\n\t\tfor (const violation of lockViolations) {\n\t\t\tif (e010Bypassed) {\n\t\t\t\twarnings.push({\n\t\t\t\t\tcode: \"E010\",\n\t\t\t\t\tmessage: `[BYPASSED] Config drift: ${violation.message}`,\n\t\t\t\t\tfilePath: lockFilePath,\n\t\t\t\t\tline: 1,\n\t\t\t\t\tcolumn: 0,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\terrors.push({\n\t\t\t\t\tcode: \"E010\",\n\t\t\t\t\tmessage: `Config drift: ${violation.message}`,\n\t\t\t\t\tfilePath: lockFilePath,\n\t\t\t\t\tline: 1,\n\t\t\t\t\tcolumn: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// E011 — Biome config weakening detection\n\tconst e011Bypassed = isRuleBypassed(config.rootDir, \"E011\");\n\tif (config.guards.biome.enabled && lockManifest?.config.biome) {\n\t\tconst biomePath = join(config.rootDir, \"biome.json\");\n\t\tconst biomePathC = join(config.rootDir, \"biome.jsonc\");\n\t\tconst actualBiomePath = existsSync(biomePath)\n\t\t\t? biomePath\n\t\t\t: existsSync(biomePathC)\n\t\t\t\t? biomePathC\n\t\t\t\t: null;\n\t\tif (actualBiomePath) {\n\t\t\ttry {\n\t\t\t\tconst biomeRaw = readFileSync(actualBiomePath, \"utf-8\");\n\t\t\t\tlet biomeParsed: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tbiomeParsed = JSON.parse(biomeRaw) as Record<string, unknown>;\n\t\t\t\t} catch {\n\t\t\t\t\t// Biome file exists but is invalid JSON/JSONC — emit one E011\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E011\",\n\t\t\t\t\t\tmessage: `Biome config \"${actualBiomePath}\": failed to parse — file may contain invalid JSON.`,\n\t\t\t\t\t\tfilePath: actualBiomePath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e011Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t\tbiomeParsed = undefined as unknown as Record<string, unknown>;\n\t\t\t\t}\n\t\t\t\tif (biomeParsed) {\n\t\t\t\t\t// Extract current biome rules from linter.rules\n\t\t\t\t\tconst currentBiomeRules = extractBiomeRules(biomeParsed);\n\t\t\t\t\t// Compare against locked biome rules snapshot\n\t\t\t\t\tconst lockedBiomeRules =\n\t\t\t\t\t\t(lockManifest.config.biome as { rules?: Record<string, string> }).rules ?? {};\n\t\t\t\t\tfor (const [ruleName, lockedLevel] of Object.entries(lockedBiomeRules)) {\n\t\t\t\t\t\tconst currentLevel = currentBiomeRules[ruleName] ?? \"off\";\n\t\t\t\t\t\tif (isWeakerBiomeLevel(currentLevel, lockedLevel)) {\n\t\t\t\t\t\t\tconst diag = {\n\t\t\t\t\t\t\t\tcode: \"E011\",\n\t\t\t\t\t\t\t\tmessage: `Biome rule \"${ruleName}\" was weakened from \"${lockedLevel}\" to \"${currentLevel}\".`,\n\t\t\t\t\t\t\t\tfilePath: actualBiomePath,\n\t\t\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tif (e011Bypassed) {\n\t\t\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (readErr) {\n\t\t\t\t// biome.json not found after existsSync — skip\n\t\t\t\tif (\n\t\t\t\t\treadErr instanceof Error &&\n\t\t\t\t\t\"code\" in readErr &&\n\t\t\t\t\t(readErr as NodeJS.ErrnoException).code === \"ENOENT\"\n\t\t\t\t) {\n\t\t\t\t\t// Intentionally ignored\n\t\t\t\t} else {\n\t\t\t\t\tthrow readErr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// E012 — package.json engine field tampering\n\tconst e012Bypassed = isRuleBypassed(config.rootDir, \"E012\");\n\tif (config.guards.packageJson.enabled) {\n\t\tconst pkgJsonPath = join(config.rootDir, \"package.json\");\n\t\ttry {\n\t\t\tconst pkgRaw = readFileSync(pkgJsonPath, \"utf-8\");\n\t\t\tconst pkg = JSON.parse(pkgRaw) as Record<string, unknown>;\n\n\t\t\t// Check required fields\n\t\t\tfor (const field of config.guards.packageJson.requiredFields) {\n\t\t\t\tif (pkg[field] === undefined) {\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E012\",\n\t\t\t\t\t\tmessage: `package.json: required field \"${field}\" is missing.`,\n\t\t\t\t\t\tfilePath: pkgJsonPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e012Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check engines.node against minNodeVersion\n\t\t\tconst engines = pkg.engines as Record<string, string> | undefined;\n\t\t\tconst nodeEngine = engines?.node;\n\t\t\tif (!nodeEngine) {\n\t\t\t\t// Only emit if \"engines\" is in requiredFields (missing engines already caught above)\n\t\t\t\t// But also check specifically for missing engines.node\n\t\t\t\tif (engines !== undefined) {\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E012\",\n\t\t\t\t\t\tmessage: `package.json: \"engines.node\" field is missing.`,\n\t\t\t\t\t\tfilePath: pkgJsonPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e012Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Simple semver comparison: extract major.minor from the engines string\n\t\t\t\tconst minVersion = parseSemverMajorMinor(config.guards.packageJson.minNodeVersion);\n\t\t\t\tconst engineVersion = parseSemverMajorMinor(nodeEngine);\n\t\t\t\tif (minVersion && engineVersion && compareMajorMinor(engineVersion, minVersion) < 0) {\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E012\",\n\t\t\t\t\t\tmessage: `package.json: \"engines.node\" specifies \"${nodeEngine}\" which is lower than the minimum required \"${config.guards.packageJson.minNodeVersion}\".`,\n\t\t\t\t\t\tfilePath: pkgJsonPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e012Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (readErr) {\n\t\t\t// package.json not found — skip\n\t\t\tif (\n\t\t\t\treadErr instanceof Error &&\n\t\t\t\t\"code\" in readErr &&\n\t\t\t\t(readErr as NodeJS.ErrnoException).code === \"ENOENT\"\n\t\t\t) {\n\t\t\t\t// Intentionally ignored\n\t\t\t} else if (readErr instanceof SyntaxError) {\n\t\t\t\t// Invalid JSON — skip gracefully\n\t\t\t} else {\n\t\t\t\tthrow readErr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// W007 — Stale guide FORGE:AUTO sections (references to removed/renamed symbols)\n\t// W008 — Undocumented public symbol in guides (exported but not mentioned)\n\tconst guidesDir = join(config.outDir, \"guides\");\n\tlet guideFiles: string[] = [];\n\tlet guideContents: Map<string, string> | undefined;\n\n\t// Only attempt guide checks if the guides directory exists\n\tif (existsSync(guidesDir)) {\n\t\ttry {\n\t\t\tconst entries = readdirSync(guidesDir);\n\t\t\tguideFiles = entries.filter((f) => f.endsWith(\".md\") || f.endsWith(\".mdx\"));\n\t\t} catch {\n\t\t\t// If we cannot read the directory, skip guide rules\n\t\t}\n\t}\n\n\tif (guideFiles.length > 0) {\n\t\tguideContents = new Map<string, string>();\n\t\tfor (const file of guideFiles) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(join(guidesDir, file), \"utf-8\");\n\t\t\t\tguideContents.set(file, content);\n\t\t\t} catch {\n\t\t\t\t// Skip unreadable files\n\t\t\t}\n\t\t}\n\n\t\t// W007 — Check FORGE:AUTO sections for references to symbols that no longer exist\n\t\tconst autoStartRe = /<!--\\s*FORGE:AUTO-START\\s+(\\S+)\\s*-->/g;\n\t\tconst autoEndRe = /<!--\\s*FORGE:AUTO-END\\s+(\\S+)\\s*-->/;\n\t\t// Match symbol references inside auto sections: `symbolName` in backticks or bare names\n\t\t// after typical markdown patterns (links, bold, code).\n\t\t// Simplified heuristic: extract all backtick-quoted identifiers inside FORGE:AUTO blocks.\n\t\tconst symbolRefRe = /`([A-Za-z_$][A-Za-z0-9_$]*)`/g;\n\n\t\tfor (const [file, content] of guideContents) {\n\t\t\tconst filePath = join(guidesDir, file);\n\t\t\t// Find each FORGE:AUTO block\n\t\t\tautoStartRe.lastIndex = 0;\n\t\t\tfor (\n\t\t\t\tlet match = autoStartRe.exec(content);\n\t\t\t\tmatch !== null;\n\t\t\t\tmatch = autoStartRe.exec(content)\n\t\t\t) {\n\t\t\t\tconst startIdx = match.index + match[0].length;\n\t\t\t\t// Find the matching end marker\n\t\t\t\tconst restContent = content.slice(startIdx);\n\t\t\t\tconst endMatch = autoEndRe.exec(restContent);\n\t\t\t\tif (!endMatch) continue;\n\t\t\t\tconst autoBlock = restContent.slice(0, endMatch.index);\n\n\t\t\t\t// Extract all backtick-quoted identifiers from the auto block\n\t\t\t\tsymbolRefRe.lastIndex = 0;\n\t\t\t\tfor (\n\t\t\t\t\tlet refMatch = symbolRefRe.exec(autoBlock);\n\t\t\t\t\trefMatch !== null;\n\t\t\t\t\trefMatch = symbolRefRe.exec(autoBlock)\n\t\t\t\t) {\n\t\t\t\t\tconst refName = refMatch[1];\n\t\t\t\t\t// Check if this name exists in the known symbols set\n\t\t\t\t\tif (!knownSymbols.has(refName)) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"W007\",\n\t\t\t\t\t\t\t`Guide \"${file}\" FORGE:AUTO section references symbol \"${refName}\" which no longer exists in the symbol graph.`,\n\t\t\t\t\t\t\tfilePath,\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsymbolName: refName,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// W008 — Check that all exported symbols from index.ts are mentioned in at least one guide\n\t\tconst allGuideText = [...guideContents.values()].join(\"\\n\");\n\t\tconst indexExportedSymbols = allSymbols.filter(\n\t\t\t(s) => s.exported && /[/\\\\]index\\.ts$/.test(s.filePath),\n\t\t);\n\t\tfor (const sym of indexExportedSymbols) {\n\t\t\tif (!allGuideText.includes(sym.name)) {\n\t\t\t\temit(\n\t\t\t\t\t\"W008\",\n\t\t\t\t\t`Exported symbol \"${sym.name}\" from \"${sym.filePath}\" is not mentioned in any guide page.`,\n\t\t\t\t\tsym.filePath,\n\t\t\t\t\tsym.line,\n\t\t\t\t\tsym.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsymbolName: sym.name,\n\t\t\t\t\t\tsymbolKind: sym.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst success = errors.length === 0;\n\treturn { success, symbols: allSymbols, errors, warnings, duration: Date.now() - start };\n}\n","import type { ForgeResult } from \"@forge-ts/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Options that control how {@link formatResults} renders its output.\n * @public\n */\nexport interface FormatOptions {\n\t/** Emit ANSI colour escape sequences when `true`. */\n\tcolors: boolean;\n\t/**\n\t * When `true`, include the symbol's type signature alongside each\n\t * diagnostic so the reader has immediate context.\n\t */\n\tverbose: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// ANSI helpers\n// ---------------------------------------------------------------------------\n\n/** @internal */\nconst RESET = \"\\x1b[0m\";\n/** @internal */\nconst RED = \"\\x1b[31m\";\n/** @internal */\nconst YELLOW = \"\\x1b[33m\";\n/** @internal */\nconst BOLD = \"\\x1b[1m\";\n/** @internal */\nconst DIM = \"\\x1b[2m\";\n\n/** @internal */\nfunction colorize(text: string, color: string, useColors: boolean): string {\n\treturn useColors ? `${color}${text}${RESET}` : text;\n}\n\n/** @internal */\nfunction bold(text: string, useColors: boolean): string {\n\treturn useColors ? `${BOLD}${text}${RESET}` : text;\n}\n\n/** @internal */\nfunction dim(text: string, useColors: boolean): string {\n\treturn useColors ? `${DIM}${text}${RESET}` : text;\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\n/** @internal */\ninterface Diagnostic {\n\tcode: string;\n\tmessage: string;\n\tfilePath: string;\n\tline: number;\n\tcolumn: number;\n}\n\n/** @internal */\nfunction isError(code: string): boolean {\n\treturn code.startsWith(\"E\");\n}\n\n/** @internal */\nfunction renderDiagnostic(diag: Diagnostic, opts: FormatOptions): string {\n\tconst label = isError(diag.code)\n\t\t? colorize(`error[${diag.code}]`, RED, opts.colors)\n\t\t: colorize(`warning[${diag.code}]`, YELLOW, opts.colors);\n\n\tconst location = dim(`${diag.line}:${diag.column}`, opts.colors);\n\treturn ` ${label} ${diag.message} ${location}`;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Formats a {@link ForgeResult} into a human-readable string suitable for\n * printing to a terminal.\n *\n * Diagnostics are grouped by source file. Each file heading shows the\n * relative-ish path, followed by indented error and warning lines. A summary\n * line is appended at the end.\n *\n * @param result - The result produced by {@link enforce}.\n * @param options - Rendering options (colours, verbosity).\n * @returns A formatted string ready to write to stdout or stderr.\n * @example\n * ```typescript\n * import { enforce } from \"@forge-ts/enforcer\";\n * import { formatResults } from \"@forge-ts/enforcer\";\n * import { loadConfig } from \"@forge-ts/core\";\n * const config = await loadConfig();\n * const result = await enforce(config);\n * console.log(formatResults(result, { colors: true, verbose: false }));\n * ```\n * @public\n */\nexport function formatResults(result: ForgeResult, options: FormatOptions): string {\n\tconst allDiags: Diagnostic[] = [\n\t\t...result.errors.map((e) => ({ ...e })),\n\t\t...result.warnings.map((w) => ({ ...w })),\n\t];\n\n\tif (allDiags.length === 0) {\n\t\tconst msg = `No issues found across ${result.symbols.length} symbol(s).`;\n\t\treturn bold(msg, options.colors);\n\t}\n\n\t// Group by filePath\n\tconst byFile = new Map<string, Diagnostic[]>();\n\tfor (const diag of allDiags) {\n\t\tconst list = byFile.get(diag.filePath);\n\t\tif (list) {\n\t\t\tlist.push(diag);\n\t\t} else {\n\t\t\tbyFile.set(diag.filePath, [diag]);\n\t\t}\n\t}\n\n\tconst lines: string[] = [];\n\n\tfor (const [filePath, diags] of byFile) {\n\t\tlines.push(bold(filePath, options.colors));\n\n\t\t// Sort: errors before warnings, then by line\n\t\tconst sorted = [...diags].sort((a, b) => {\n\t\t\tconst aIsErr = isError(a.code) ? 0 : 1;\n\t\t\tconst bIsErr = isError(b.code) ? 0 : 1;\n\t\t\tif (aIsErr !== bIsErr) return aIsErr - bIsErr;\n\t\t\treturn a.line - b.line;\n\t\t});\n\n\t\tfor (const diag of sorted) {\n\t\t\tlines.push(renderDiagnostic(diag, options));\n\n\t\t\tif (options.verbose) {\n\t\t\t\t// Find the matching symbol to show its signature\n\t\t\t\tconst sym = result.symbols.find(\n\t\t\t\t\t(s) => s.filePath === diag.filePath && s.line === diag.line,\n\t\t\t\t);\n\t\t\t\tif (sym?.signature) {\n\t\t\t\t\tlines.push(dim(` signature: ${sym.signature}`, options.colors));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlines.push(\"\");\n\t}\n\n\t// Summary line\n\tconst errorCount = result.errors.length;\n\tconst warnCount = result.warnings.length;\n\tconst fileCount = byFile.size;\n\n\tconst errorPart =\n\t\terrorCount > 0\n\t\t\t? colorize(`${errorCount} error${errorCount !== 1 ? \"s\" : \"\"}`, RED, options.colors)\n\t\t\t: `0 errors`;\n\tconst warnPart =\n\t\twarnCount > 0\n\t\t\t? colorize(`${warnCount} warning${warnCount !== 1 ? \"s\" : \"\"}`, YELLOW, options.colors)\n\t\t\t: `0 warnings`;\n\tconst filePart = `${fileCount} file${fileCount !== 1 ? \"s\" : \"\"}`;\n\n\tlines.push(`${errorPart}, ${warnPart} in ${filePart}`);\n\n\treturn lines.join(\"\\n\");\n}\n"],"mappings":"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","names":["diag","extractSignificantWords"]}
1
+ {"version":3,"sources":["../src/deprecation-tracker.ts","../src/enforcer.ts","../src/formatter.ts"],"sourcesContent":["import type { ForgeSymbol } from \"@forge-ts/core\";\n\n/** A detected usage of a deprecated symbol. */\nexport interface DeprecatedUsage {\n\t/** The deprecated symbol being consumed. */\n\tdeprecatedSymbol: string;\n\t/** The package that exports the deprecated symbol. */\n\tsourcePackage: string;\n\t/** The file importing the deprecated symbol. */\n\tconsumingFile: string;\n\t/** Line number of the import. */\n\tline: number;\n\t/** The deprecation message. */\n\tdeprecationMessage: string;\n}\n\n/**\n * Scans symbols for imports of deprecated exports from other packages.\n *\n * @param symbols - All symbols from the walker across the entire project.\n * @returns Array of deprecated usages found.\n */\nexport function findDeprecatedUsages(symbols: ForgeSymbol[]): DeprecatedUsage[] {\n\t// Build a set of deprecated symbol names with their source info\n\tconst deprecatedExports = new Map<string, { sourceFile: string; message: string }>();\n\n\tfor (const symbol of symbols) {\n\t\tif (symbol.exported && symbol.documentation?.deprecated) {\n\t\t\tdeprecatedExports.set(symbol.name, {\n\t\t\t\tsourceFile: symbol.filePath,\n\t\t\t\tmessage: symbol.documentation.deprecated,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (deprecatedExports.size === 0) return [];\n\n\t// For each symbol that has a {@link} or references a deprecated name,\n\t// check if it's from a different package\n\tconst usages: DeprecatedUsage[] = [];\n\n\t// Check links\n\tfor (const symbol of symbols) {\n\t\tconst links = symbol.documentation?.links ?? [];\n\t\tfor (const link of links) {\n\t\t\tconst deprecated = deprecatedExports.get(link.target);\n\t\t\tif (deprecated && deprecated.sourceFile !== symbol.filePath) {\n\t\t\t\t// Different file references a deprecated symbol\n\t\t\t\tconst sourcePackage = extractPackageName(deprecated.sourceFile);\n\t\t\t\tconst consumingPackage = extractPackageName(symbol.filePath);\n\n\t\t\t\tif (sourcePackage !== consumingPackage) {\n\t\t\t\t\tusages.push({\n\t\t\t\t\t\tdeprecatedSymbol: link.target,\n\t\t\t\t\t\tsourcePackage,\n\t\t\t\t\t\tconsumingFile: symbol.filePath,\n\t\t\t\t\t\tline: link.line,\n\t\t\t\t\t\tdeprecationMessage: deprecated.message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn usages;\n}\n\n/** Extract package name from file path (e.g., \"packages/core/src/...\" -> \"core\"). */\nfunction extractPackageName(filePath: string): string {\n\tconst match = filePath.match(/packages\\/([^/]+)\\//);\n\treturn match?.[1] ?? \"root\";\n}\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport {\n\tcreateWalker,\n\ttype EnforceRules,\n\ttype ForgeConfig,\n\ttype ForgeError,\n\ttype ForgeResult,\n\ttype ForgeSymbol,\n\ttype ForgeWarning,\n\tfilterByVisibility,\n\tisRuleBypassed,\n\treadLockFile,\n\tvalidateAgainstLock,\n} from \"@forge-ts/core\";\nimport { findDeprecatedUsages } from \"./deprecation-tracker.js\";\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Checks whether a symbol has at least a summary in its documentation.\n * @internal\n */\nfunction hasSummary(symbol: ForgeSymbol): boolean {\n\treturn (\n\t\tsymbol.documentation?.summary !== undefined && symbol.documentation.summary.trim().length > 0\n\t);\n}\n\n/**\n * Splits a signature parameter list on top-level commas, respecting angle\n * bracket nesting so that `Record<string, string[]>` is not split.\n * @internal\n */\nfunction splitParams(raw: string): string[] {\n\tconst parts: string[] = [];\n\tlet depth = 0;\n\tlet current = \"\";\n\tfor (const ch of raw) {\n\t\tif (ch === \"<\" || ch === \"(\") {\n\t\t\tdepth++;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \">\" || ch === \")\") {\n\t\t\tdepth--;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \",\" && depth === 0) {\n\t\t\tparts.push(current);\n\t\t\tcurrent = \"\";\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\tif (current.trim()) {\n\t\tparts.push(current);\n\t}\n\treturn parts;\n}\n\n/**\n * Returns the names of parameters that are declared on a function/method symbol\n * but lack a corresponding `@param` tag in its documentation.\n *\n * Since the AST walker populates `documentation.params` from parsed TSDoc, we\n * compare the set of documented param names against the names that appear in\n * the symbol's type signature. When no signature is available the check is\n * skipped (returns empty array).\n *\n * @internal\n */\nfunction undocumentedParams(symbol: ForgeSymbol): string[] {\n\tconst sig = symbol.signature;\n\tif (!sig) return [];\n\n\t// Parse parameter names out of the signature string.\n\t// Signatures look like: \"(a: string, b: number) => void\"\n\t// Must handle nested generics: \"(tags: Record<string, string[]>) => void\"\n\tconst parenMatch = sig.match(/^\\(([^)]*)\\)/);\n\tif (!parenMatch || !parenMatch[1].trim()) return [];\n\n\tconst rawParams = splitParams(parenMatch[1])\n\t\t.map((p) =>\n\t\t\tp\n\t\t\t\t.trim()\n\t\t\t\t.split(\":\")[0]\n\t\t\t\t.trim()\n\t\t\t\t.replace(/^\\.{3}/, \"\")\n\t\t\t\t.replace(/\\?$/, \"\")\n\t\t\t\t.trim(),\n\t\t)\n\t\t.filter((p) => p.length > 0 && p !== \"this\");\n\n\tif (rawParams.length === 0) return [];\n\n\tconst documentedNames = new Set((symbol.documentation?.params ?? []).map((p) => p.name));\n\treturn rawParams.filter((name) => !documentedNames.has(name));\n}\n\n/**\n * Returns `true` when a function/method symbol has a non-void return type but\n * no `@returns` block in its documentation.\n * @internal\n */\nfunction missingReturns(symbol: ForgeSymbol): boolean {\n\tconst sig = symbol.signature;\n\tif (!sig) return false;\n\n\t// Extract return type: everything after the last \"=>\"\n\tconst arrowIdx = sig.lastIndexOf(\"=>\");\n\tif (arrowIdx === -1) return false;\n\tconst returnType = sig.slice(arrowIdx + 2).trim();\n\n\tconst isVoidLike =\n\t\treturnType === \"void\" ||\n\t\treturnType === \"never\" ||\n\t\treturnType === \"undefined\" ||\n\t\treturnType.startsWith(\"Promise<void>\") ||\n\t\treturnType.startsWith(\"Promise<never>\") ||\n\t\treturnType.startsWith(\"Promise<undefined>\");\n\n\tif (isVoidLike) return false;\n\treturn symbol.documentation?.returns === undefined;\n}\n\n/**\n * Returns `true` when a `@deprecated` tag is present but carries no\n * explanatory text.\n * @internal\n */\nfunction deprecatedWithoutReason(symbol: ForgeSymbol): boolean {\n\tconst deprecated = symbol.documentation?.deprecated;\n\tif (deprecated === undefined) return false;\n\t// The walker stores `\"true\"` when the tag has no content.\n\treturn deprecated === \"true\" || deprecated.trim().length === 0;\n}\n\n/**\n * Extracts generic type parameter names from a symbol's signature.\n * Handles patterns like `<T>`, `<T, U>`, `<T extends Record<string, unknown>>`, etc.\n * Respects nested angle brackets so constraints are not prematurely closed.\n * @internal\n */\nfunction extractGenericTypeParams(signature: string | undefined): string[] {\n\tif (!signature || !signature.startsWith(\"<\")) return [];\n\t// Find the matching closing '>' respecting nesting\n\tlet depth = 0;\n\tlet endIdx = -1;\n\tfor (let i = 0; i < signature.length; i++) {\n\t\tif (signature[i] === \"<\") depth++;\n\t\telse if (signature[i] === \">\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) {\n\t\t\t\tendIdx = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (endIdx === -1) return [];\n\tconst inner = signature.slice(1, endIdx);\n\t// Split on top-level commas (depth 0)\n\tconst params: string[] = [];\n\tlet paramDepth = 0;\n\tlet current = \"\";\n\tfor (const ch of inner) {\n\t\tif (ch === \"<\" || ch === \"(\") {\n\t\t\tparamDepth++;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \">\" || ch === \")\") {\n\t\t\tparamDepth--;\n\t\t\tcurrent += ch;\n\t\t} else if (ch === \",\" && paramDepth === 0) {\n\t\t\tparams.push(current);\n\t\t\tcurrent = \"\";\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\tif (current.trim()) params.push(current);\n\treturn params.map((p) => p.trim().split(/\\s+/)[0].trim()).filter((p) => p.length > 0);\n}\n\n/**\n * Returns `true` when a property signature looks optional —\n * i.e. includes `| undefined` in the type.\n * @internal\n */\nfunction isOptionalProperty(child: ForgeSymbol): boolean {\n\tconst sig = child.signature;\n\tif (!sig) return false;\n\tif (sig.includes(\"| undefined\") || sig.includes(\"undefined |\")) return true;\n\treturn false;\n}\n\n/**\n * Extracts a flat map of biome rule names to their configured level\n * from a parsed biome.json structure.\n * Walks `linter.rules.<group>.<ruleName>` and normalises both string\n * and object (`{ level: \"error\" }`) forms.\n * @internal\n */\nfunction extractBiomeRules(biome: Record<string, unknown>): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\tconst linter = biome.linter as Record<string, unknown> | undefined;\n\tif (!linter) return result;\n\tconst rules = linter.rules as Record<string, unknown> | undefined;\n\tif (!rules) return result;\n\tfor (const [group, groupRules] of Object.entries(rules)) {\n\t\tif (\n\t\t\tgroup === \"recommended\" ||\n\t\t\tgroup === \"all\" ||\n\t\t\ttypeof groupRules !== \"object\" ||\n\t\t\tgroupRules === null\n\t\t)\n\t\t\tcontinue;\n\t\tfor (const [ruleName, ruleValue] of Object.entries(groupRules as Record<string, unknown>)) {\n\t\t\tconst fullName = `${group}/${ruleName}`;\n\t\t\tif (typeof ruleValue === \"string\") {\n\t\t\t\tresult[fullName] = ruleValue;\n\t\t\t} else if (typeof ruleValue === \"object\" && ruleValue !== null && \"level\" in ruleValue) {\n\t\t\t\tresult[fullName] = String((ruleValue as Record<string, unknown>).level);\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Returns `true` when `current` is a weaker biome level than `locked`.\n * Ranking: error > warn > off.\n * @internal\n */\nfunction isWeakerBiomeLevel(current: string, locked: string): boolean {\n\tconst rank: Record<string, number> = { off: 0, warn: 1, error: 2 };\n\tconst currentRank = rank[current] ?? 0;\n\tconst lockedRank = rank[locked] ?? 0;\n\treturn currentRank < lockedRank;\n}\n\n/**\n * Extracts major.minor from a semver-like string.\n * Handles patterns like \">=22.0.0\", \"^22.0.0\", \"~22.0.0\", \"22.0.0\", \"22.0\".\n * @internal\n */\nfunction parseSemverMajorMinor(version: string): [number, number] | null {\n\tconst match = version.match(/(\\d+)\\.(\\d+)/);\n\tif (!match) return null;\n\treturn [Number(match[1]), Number(match[2])];\n}\n\n/**\n * Compares two [major, minor] tuples.\n * Returns negative if a < b, 0 if equal, positive if a > b.\n * @internal\n */\nfunction compareMajorMinor(a: [number, number], b: [number, number]): number {\n\tif (a[0] !== b[0]) return a[0] - b[0];\n\treturn a[1] - b[1];\n}\n\n// ---------------------------------------------------------------------------\n// Rule map\n// ---------------------------------------------------------------------------\n\n/**\n * Maps E-code strings to their corresponding {@link EnforceRules} key.\n * @internal\n */\nconst RULE_MAP: Record<string, keyof EnforceRules> = {\n\tE001: \"require-summary\",\n\tE002: \"require-param\",\n\tE003: \"require-returns\",\n\tE004: \"require-example\",\n\tE005: \"require-package-doc\",\n\tE006: \"require-class-member-doc\",\n\tE007: \"require-interface-member-doc\",\n\tW006: \"require-tsdoc-syntax\",\n\tE013: \"require-remarks\",\n\tE014: \"require-default-value\",\n\tE015: \"require-type-param\",\n\tW005: \"require-see\",\n\tE016: \"require-release-tag\",\n\tW007: \"require-fresh-guides\",\n\tW008: \"require-guide-coverage\",\n\tE017: \"require-internal-boundary\",\n\tE018: \"require-route-response\",\n\tW009: \"require-inheritdoc-source\",\n\tW010: \"require-migration-path\",\n\tW011: \"require-since\",\n\tE019: \"require-no-ts-ignore\",\n\tE020: \"require-no-any-in-api\",\n\tW012: \"require-fresh-link-text\",\n\tW013: \"require-fresh-examples\",\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the TSDoc enforcement pass against a project.\n *\n * The enforcer walks all exported symbols that meet the configured minimum\n * visibility threshold and emits diagnostics for any documentation deficiencies\n * it finds.\n *\n * ### Error codes\n * | Code | Severity | Condition |\n * |------|----------|-----------|\n * | E001 | error | Exported symbol is missing a TSDoc summary. |\n * | E002 | error | Function/method parameter lacks a `@param` tag. |\n * | E003 | error | Non-void function/method lacks a `@returns` tag. |\n * | E004 | error | Exported function/method is missing an `@example` block. |\n * | E005 | error | Package entry point (index.ts) is missing `@packageDocumentation`. |\n * | E006 | error | Public/protected class member is missing a TSDoc comment. |\n * | E007 | error | Interface/type alias property is missing a TSDoc comment. |\n * | W001 | warning | TSDoc comment contains parse errors. |\n * | W002 | warning | Function body throws but has no `@throws` tag. |\n * | W003 | warning | `@deprecated` tag is present without explanation. |\n * | W006 | warning | TSDoc parser-level syntax error (invalid tag, malformed block, etc.). |\n * | E009 | error | tsconfig.json required strict-mode flag is missing or disabled (guard). |\n * | E010 | error | Config drift: a rule severity is weaker than the locked value. |\n * | E013 | error | Exported function/class is missing a `@remarks` block. |\n * | E014 | warn | Optional property of interface/type is missing `@defaultValue`. |\n * | E015 | error | Generic symbol is missing `@typeParam` for a type parameter. |\n * | W005 | warn | Symbol references other symbols via `{@link}` but has no `@see` tags. |\n * | W007 | warn | Guide FORGE:AUTO section references a symbol that no longer exists. |\n * | W008 | warn | Exported public symbol is not mentioned in any guide page. |\n * | E017 | error | `@internal` symbol re-exported through public barrel (index.ts). |\n * | E018 | warn | `@route`-tagged function missing `@response` tag. |\n * | W009 | warn | `{@inheritDoc}` references a symbol that does not exist. |\n * | W010 | warn | `@breaking` tag present without `@migration` path. |\n * | W011 | warn | New public export missing `@since` version tag. |\n *\n * When `config.enforce.strict` is `true` all warnings are promoted to errors.\n *\n * @param config - The resolved {@link ForgeConfig} for the project.\n * @returns A {@link ForgeResult} describing which symbols passed or failed.\n * @example\n * ```typescript\n * import { loadConfig } from \"@forge-ts/core\";\n * import { enforce } from \"@forge-ts/enforcer\";\n * const config = await loadConfig();\n * const result = await enforce(config);\n * if (!result.success) {\n * console.error(`${result.errors.length} errors found`);\n * }\n * ```\n * @public\n */\nexport async function enforce(config: ForgeConfig): Promise<ForgeResult> {\n\tconst start = Date.now();\n\tconst errors: ForgeError[] = [];\n\tconst warnings: ForgeWarning[] = [];\n\n\tconst walker = createWalker(config);\n\tconst allSymbols = walker.walk();\n\tconst symbols = filterByVisibility(allSymbols, config.enforce.minVisibility);\n\n\t// ---------------------------------------------------------------------------\n\t// Ignore file: read symbol names to skip enforcement on (Knip integration)\n\t// ---------------------------------------------------------------------------\n\tconst ignoreSet = new Set<string>();\n\tif (config.enforce.ignoreFile) {\n\t\tconst ignoreFilePath = resolve(config.rootDir, config.enforce.ignoreFile);\n\t\tif (existsSync(ignoreFilePath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(ignoreFilePath, \"utf-8\");\n\t\t\t\tfor (const rawLine of content.split(\"\\n\")) {\n\t\t\t\t\tconst trimmed = rawLine.trim();\n\t\t\t\t\tif (trimmed.length > 0 && !trimmed.startsWith(\"#\")) {\n\t\t\t\t\t\tignoreSet.add(trimmed);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore read errors gracefully\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Emit a diagnostic. The configured per-rule severity determines whether\n\t * the diagnostic is an error or warning; \"off\" suppresses it entirely.\n\t * When `strict` is enabled every warning is promoted to an error.\n\t */\n\tfunction emit(\n\t\tcode: string,\n\t\tmessage: string,\n\t\tfilePath: string,\n\t\tline: number,\n\t\tcolumn: number,\n\t\tguidance?: { suggestedFix?: string; symbolName?: string; symbolKind?: string },\n\t): void {\n\t\tconst ruleKey = RULE_MAP[code];\n\n\t\t// For rule codes tracked in the map, honour the per-rule severity.\n\t\tif (ruleKey !== undefined) {\n\t\t\tconst configuredSeverity = config.enforce.rules[ruleKey];\n\t\t\tif (configuredSeverity === \"off\") return;\n\t\t\tconst effectiveSeverity = config.enforce.strict ? \"error\" : configuredSeverity;\n\t\t\tconst diag = { code, message, filePath, line, column, ...guidance };\n\t\t\tif (effectiveSeverity === \"error\") {\n\t\t\t\terrors.push(diag);\n\t\t\t} else {\n\t\t\t\twarnings.push(diag);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// For codes not in the map (W003, E008, etc.) fall back to the old\n\t\t// behaviour: always emit, respect strict mode for warnings.\n\t\tconst diag = { code, message, filePath, line, column, ...guidance };\n\t\t// Codes starting with \"W\" are warnings by default.\n\t\tif (code.startsWith(\"W\") && !config.enforce.strict) {\n\t\t\twarnings.push(diag);\n\t\t} else {\n\t\t\terrors.push(diag);\n\t\t}\n\t}\n\n\tfor (const symbol of symbols) {\n\t\tif (!symbol.exported) continue;\n\n\t\t// Skip enforcement for symbols in the ignore file (Knip dead-export integration)\n\t\tif (ignoreSet.has(symbol.name)) continue;\n\n\t\t// Skip enforcement for symbols with @forgeIgnore tag\n\t\tif (symbol.documentation?.tags?.forgeIgnore !== undefined) continue;\n\n\t\t// Skip specific rules for the \"file\" symbol (which just carries @packageDocumentation)\n\t\tif (symbol.kind === \"file\") continue;\n\n\t\tconst isFunctionLike = symbol.kind === \"function\" || symbol.kind === \"method\";\n\n\t\t// E001 — Missing summary\n\t\tif (!hasSummary(symbol)) {\n\t\t\temit(\n\t\t\t\t\"E001\",\n\t\t\t\t`Exported symbol \"${symbol.name}\" is missing a TSDoc summary comment.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `/**\\n * [Description of ${symbol.name}]\\n */`,\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// E002 — Undocumented parameters\n\t\tif (isFunctionLike) {\n\t\t\tconst missing = undocumentedParams(symbol);\n\t\t\tfor (const paramName of missing) {\n\t\t\t\temit(\n\t\t\t\t\t\"E002\",\n\t\t\t\t\t`Parameter \"${paramName}\" of \"${symbol.name}\" is not documented with a @param tag.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `@param ${paramName} - [Description of ${paramName}]`,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E003 — Missing @returns\n\t\tif (isFunctionLike && missingReturns(symbol)) {\n\t\t\temit(\n\t\t\t\t\"E003\",\n\t\t\t\t`\"${symbol.name}\" has a non-void return type but is missing a @returns tag.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `@returns [Description of the return value]`,\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// E004 — Missing @example\n\t\tif (isFunctionLike && symbol.documentation) {\n\t\t\tconst hasExample = (symbol.documentation.examples ?? []).length > 0;\n\t\t\tif (!hasExample) {\n\t\t\t\temit(\n\t\t\t\t\t\"E004\",\n\t\t\t\t\t`Exported function \"${symbol.name}\" is missing an @example block. Add a fenced code block showing usage.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `@example\\n * \\`\\`\\`typescript\\n * // Usage of ${symbol.name}\\n * ${symbol.name}();\\n * \\`\\`\\``,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E006 — Class member missing documentation\n\t\t// E007 — Interface/type member missing documentation\n\t\tif (symbol.kind === \"class\" || symbol.kind === \"interface\") {\n\t\t\tconst errorCode = symbol.kind === \"class\" ? \"E006\" : \"E007\";\n\t\t\tfor (const child of symbol.children ?? []) {\n\t\t\t\tif (child.kind === \"property\" || child.kind === \"method\") {\n\t\t\t\t\tif (!hasSummary(child)) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\terrorCode,\n\t\t\t\t\t\t\t`Member \"${child.name}\" of ${symbol.kind} \"${symbol.name}\" is missing a TSDoc comment.`,\n\t\t\t\t\t\t\tchild.filePath,\n\t\t\t\t\t\t\tchild.line,\n\t\t\t\t\t\t\tchild.column,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsuggestedFix: `/**\\n * [Description of ${child.name}]\\n */`,\n\t\t\t\t\t\t\t\tsymbolName: child.name,\n\t\t\t\t\t\t\t\tsymbolKind: child.kind,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// E013 — Missing @remarks on exported functions/classes\n\t\tif (symbol.kind === \"function\" || symbol.kind === \"class\") {\n\t\t\tconst hasRemarks = symbol.documentation?.tags?.remarks !== undefined;\n\t\t\tif (!hasRemarks) {\n\t\t\t\temit(\n\t\t\t\t\t\"E013\",\n\t\t\t\t\t`Exported ${symbol.kind} \"${symbol.name}\" is missing a @remarks block.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `@remarks [Detailed description of ${symbol.name}]`,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E014 — Missing @defaultValue on optional properties of interfaces/types\n\t\tif (symbol.kind === \"interface\" || symbol.kind === \"type\") {\n\t\t\tfor (const child of symbol.children ?? []) {\n\t\t\t\tif (child.kind !== \"property\") continue;\n\t\t\t\tif (!isOptionalProperty(child)) continue;\n\t\t\t\tconst hasDefaultValue = child.documentation?.tags?.defaultValue !== undefined;\n\t\t\t\tif (!hasDefaultValue) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"E014\",\n\t\t\t\t\t\t`Optional property \"${child.name}\" of ${symbol.kind} \"${symbol.name}\" is missing @defaultValue.`,\n\t\t\t\t\t\tchild.filePath,\n\t\t\t\t\t\tchild.line,\n\t\t\t\t\t\tchild.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuggestedFix: `@defaultValue [Default value of ${child.name}]`,\n\t\t\t\t\t\t\tsymbolName: child.name,\n\t\t\t\t\t\t\tsymbolKind: child.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// E015 — Missing @typeParam on generic symbols\n\t\tif (symbol.kind === \"function\" || symbol.kind === \"class\" || symbol.kind === \"interface\") {\n\t\t\tconst typeParamNames = extractGenericTypeParams(symbol.signature);\n\t\t\tif (typeParamNames.length > 0) {\n\t\t\t\tconst documentedTypeParams = new Set(\n\t\t\t\t\t(symbol.documentation?.tags?.typeParam ?? []).map((tp) =>\n\t\t\t\t\t\ttp.split(/\\s/)[0].replace(/-$/, \"\").trim(),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tfor (const typeParamName of typeParamNames) {\n\t\t\t\t\tif (!documentedTypeParams.has(typeParamName)) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"E015\",\n\t\t\t\t\t\t\t`Type parameter \"${typeParamName}\" of \"${symbol.name}\" is not documented with @typeParam.`,\n\t\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\t\tsymbol.line,\n\t\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsuggestedFix: `@typeParam ${typeParamName} - [Description of ${typeParamName}]`,\n\t\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// W005 — {@link} references present but no @see tags\n\t\tif (symbol.documentation?.links && symbol.documentation.links.length > 0) {\n\t\t\tconst hasSee =\n\t\t\t\tsymbol.documentation.tags?.see !== undefined && symbol.documentation.tags.see.length > 0;\n\t\t\tif (!hasSee) {\n\t\t\t\temit(\n\t\t\t\t\t\"W005\",\n\t\t\t\t\t`\"${symbol.name}\" references other symbols via {@link} but has no @see tags.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: \"@see [Related symbol name]\",\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E016 — Missing release tag on exported symbols\n\t\t{\n\t\t\tconst releaseTags = [\"public\", \"beta\", \"internal\", \"alpha\"];\n\t\t\tconst hasReleaseTag = releaseTags.some(\n\t\t\t\t(tag) => symbol.documentation?.tags?.[tag] !== undefined,\n\t\t\t);\n\t\t\tif (!hasReleaseTag) {\n\t\t\t\temit(\n\t\t\t\t\t\"E016\",\n\t\t\t\t\t`Exported symbol \"${symbol.name}\" is missing a release tag (@public, @beta, or @internal).`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: \"@public\",\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E017 — @internal symbol re-exported through public barrel (index.ts)\n\t\tif (\n\t\t\tsymbol.documentation?.tags?.internal !== undefined &&\n\t\t\t/[/\\\\]index\\.ts$/.test(symbol.filePath)\n\t\t) {\n\t\t\temit(\n\t\t\t\t\"E017\",\n\t\t\t\t`@internal symbol \"${symbol.name}\" is re-exported through public barrel \"${symbol.filePath}\".`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `Remove \"${symbol.name}\" from the public barrel file (index.ts) or remove the @internal tag.`,\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// E018 — @route-tagged function missing @response\n\t\tif (symbol.documentation?.tags?.route && !symbol.documentation?.tags?.response) {\n\t\t\temit(\n\t\t\t\t\"E018\",\n\t\t\t\t`Route handler \"${symbol.name}\" is missing a @response tag. Document expected HTTP responses.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: \"@response 200 - Success response\",\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// W010 — @breaking without @migration\n\t\tif (symbol.documentation?.tags?.breaking && !symbol.documentation?.tags?.migration) {\n\t\t\temit(\n\t\t\t\t\"W010\",\n\t\t\t\t`\"${symbol.name}\" has a @breaking tag but no @migration path. Provide migration guidance.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: \"@migration [Describe how to migrate from the old API]\",\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// W011 — New public export missing @since\n\t\t{\n\t\t\tconst releaseTags = [\"public\", \"beta\", \"alpha\"];\n\t\t\tconst hasReleaseTag = releaseTags.some(\n\t\t\t\t(tag) => symbol.documentation?.tags?.[tag] !== undefined,\n\t\t\t);\n\t\t\tif (hasReleaseTag && !symbol.documentation?.tags?.since) {\n\t\t\t\temit(\n\t\t\t\t\t\"W011\",\n\t\t\t\t\t`Exported symbol \"${symbol.name}\" has a release tag but is missing @since version.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: \"@since 1.0.0\",\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// E020 — `any` type in public API signature\n\t\tif (symbol.documentation?.tags?.internal === undefined && symbol.signature) {\n\t\t\tconst anyRegex = /\\bany\\b/g;\n\t\t\tif (anyRegex.test(symbol.signature)) {\n\t\t\t\temit(\n\t\t\t\t\t\"E020\",\n\t\t\t\t\t`Exported symbol \"${symbol.name}\" has \\`any\\` in its signature. Use a specific type or generic.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tsymbol.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// W003 — @deprecated without reason\n\t\tif (deprecatedWithoutReason(symbol)) {\n\t\t\temit(\n\t\t\t\t\"W003\",\n\t\t\t\t`\"${symbol.name}\" is marked @deprecated but provides no explanation.`,\n\t\t\t\tsymbol.filePath,\n\t\t\t\tsymbol.line,\n\t\t\t\tsymbol.column,\n\t\t\t\t{\n\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// W006 — TSDoc parser syntax messages\n\t\tif (symbol.documentation?.parseMessages) {\n\t\t\tfor (const msg of symbol.documentation.parseMessages) {\n\t\t\t\temit(\n\t\t\t\t\t\"W006\",\n\t\t\t\t\t`TSDoc syntax: ${msg.text} [${msg.messageId}]`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tmsg.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// W006 — TSDoc parser syntax messages on child symbols\n\t\tif (symbol.children) {\n\t\t\tfor (const child of symbol.children) {\n\t\t\t\tif (child.documentation?.parseMessages) {\n\t\t\t\t\tfor (const msg of child.documentation.parseMessages) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"W006\",\n\t\t\t\t\t\t\t`TSDoc syntax: ${msg.text} [${msg.messageId}]`,\n\t\t\t\t\t\t\tchild.filePath,\n\t\t\t\t\t\t\tmsg.line,\n\t\t\t\t\t\t\tchild.column,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsymbolName: child.name,\n\t\t\t\t\t\t\t\tsymbolKind: child.kind,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// W013 — Stale @example blocks (arg count mismatch with function signature)\n\tfor (const symbol of symbols) {\n\t\tif (!symbol.exported) continue;\n\t\tif (ignoreSet.has(symbol.name)) continue;\n\t\tif (symbol.documentation?.tags?.forgeIgnore !== undefined) continue;\n\n\t\tconst isFn = symbol.kind === \"function\" || symbol.kind === \"method\";\n\t\tif (!isFn) continue;\n\n\t\tconst examples = symbol.documentation?.examples ?? [];\n\t\tif (examples.length === 0) continue;\n\n\t\t// Extract parameter count from signature\n\t\tconst sig = symbol.signature;\n\t\tif (!sig) continue;\n\n\t\tconst parenMatch = sig.match(/^\\(([^)]*)\\)/);\n\t\tif (!parenMatch) continue;\n\n\t\tconst rawParamStr = parenMatch[1].trim();\n\t\tlet paramCount = 0;\n\t\tif (rawParamStr.length > 0) {\n\t\t\tconst params = splitParams(rawParamStr)\n\t\t\t\t.map((p) =>\n\t\t\t\t\tp\n\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t.split(\":\")[0]\n\t\t\t\t\t\t.trim()\n\t\t\t\t\t\t.replace(/^\\.{3}/, \"\")\n\t\t\t\t\t\t.replace(/\\?$/, \"\")\n\t\t\t\t\t\t.trim(),\n\t\t\t\t)\n\t\t\t\t.filter((p) => p.length > 0 && p !== \"this\");\n\t\t\tparamCount = params.length;\n\t\t}\n\n\t\t// Build a regex to find calls to this function in example code\n\t\tconst funcCallRegex = new RegExp(`\\\\b${symbol.name}\\\\s*\\\\(`, \"g\");\n\n\t\tfor (const example of examples) {\n\t\t\tfuncCallRegex.lastIndex = 0;\n\t\t\tlet callMatch = funcCallRegex.exec(example.code);\n\t\t\twhile (callMatch) {\n\t\t\t\t// Count arguments by finding the matching closing paren\n\t\t\t\tconst startIdx = callMatch.index + callMatch[0].length;\n\t\t\t\tlet depth = 1;\n\t\t\t\tlet idx = startIdx;\n\t\t\t\twhile (idx < example.code.length && depth > 0) {\n\t\t\t\t\tconst ch = example.code[idx];\n\t\t\t\t\tif (ch === \"(\" || ch === \"<\" || ch === \"[\" || ch === \"{\") depth++;\n\t\t\t\t\telse if (ch === \")\" || ch === \">\" || ch === \"]\" || ch === \"}\") depth--;\n\t\t\t\t\tidx++;\n\t\t\t\t}\n\t\t\t\t// Extract the arguments substring\n\t\t\t\tconst argsStr = example.code.slice(startIdx, idx - 1).trim();\n\t\t\t\tlet argCount = 0;\n\t\t\t\tif (argsStr.length > 0) {\n\t\t\t\t\t// Split on top-level commas\n\t\t\t\t\targCount = splitParams(argsStr).length;\n\t\t\t\t}\n\n\t\t\t\tif (argCount !== paramCount) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"W013\",\n\t\t\t\t\t\t`@example in \"${symbol.name}\" may be stale — function signature has ${paramCount} parameter(s) but example call has ${argCount} argument(s).`,\n\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\texample.line,\n\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcallMatch = funcCallRegex.exec(example.code);\n\t\t\t}\n\t\t}\n\t}\n\n\t// E019 — ts-ignore / ts-expect-error in non-test files\n\t// Scan each unique non-test source file that contains symbols for suppression directives.\n\t{\n\t\tconst tsIgnoreRegex = /\\/\\/\\s*@ts-(ignore|expect-error)/g;\n\t\tconst testPathRegex = /(\\.(test|spec)\\.ts$|__tests__[/\\\\])/;\n\t\tconst scannedFiles = new Set<string>();\n\t\tfor (const symbol of allSymbols) {\n\t\t\tif (scannedFiles.has(symbol.filePath)) continue;\n\t\t\tscannedFiles.add(symbol.filePath);\n\t\t\tif (testPathRegex.test(symbol.filePath)) continue;\n\t\t\ttry {\n\t\t\t\tconst fileContent = readFileSync(symbol.filePath, \"utf-8\");\n\t\t\t\tconst lines = fileContent.split(\"\\n\");\n\t\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\t\ttsIgnoreRegex.lastIndex = 0;\n\t\t\t\t\tif (tsIgnoreRegex.test(lines[i])) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"E019\",\n\t\t\t\t\t\t\t`Non-test file \"${symbol.filePath}\" contains @ts-ignore at line ${i + 1}. Remove the suppression or move the code to a test file.`,\n\t\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\t\ti + 1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Skip unreadable files\n\t\t\t}\n\t\t}\n\t}\n\n\t// E005 — Missing @packageDocumentation on index.ts entry points\n\t// Group symbols by file to check if any index.ts file lacks @packageDocumentation.\n\tconst indexFiles = new Map<string, ForgeSymbol[]>();\n\tfor (const symbol of allSymbols) {\n\t\tif (symbol.filePath.endsWith(\"index.ts\")) {\n\t\t\tconst bucket = indexFiles.get(symbol.filePath) ?? [];\n\t\t\tbucket.push(symbol);\n\t\t\tindexFiles.set(symbol.filePath, bucket);\n\t\t}\n\t}\n\tfor (const [filePath, fileSymbols] of indexFiles) {\n\t\tconst hasPackageDoc = fileSymbols.some(\n\t\t\t(s) => s.documentation?.tags?.packageDocumentation !== undefined,\n\t\t);\n\t\tif (!hasPackageDoc) {\n\t\t\temit(\n\t\t\t\t\"E005\",\n\t\t\t\t`Package entry point \"${filePath}\" is missing a @packageDocumentation TSDoc comment.`,\n\t\t\t\tfilePath,\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t\t{\n\t\t\t\t\tsuggestedFix: `/**\\n * @packageDocumentation\\n * [Package overview description]\\n */`,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\t// E008 — Dead {@link} references\n\t// Build a set of all known symbol names (simple and qualified).\n\tconst knownSymbols = new Set<string>();\n\tfor (const s of allSymbols) {\n\t\tknownSymbols.add(s.name);\n\t\tif (s.children) {\n\t\t\tfor (const child of s.children) {\n\t\t\t\tknownSymbols.add(`${s.name}.${child.name}`);\n\t\t\t\tknownSymbols.add(child.name);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check all {@link} references across every symbol (not just filtered ones).\n\tfor (const symbol of allSymbols) {\n\t\tconst docLinks = symbol.documentation?.links ?? [];\n\t\tfor (const link of docLinks) {\n\t\t\tif (!knownSymbols.has(link.target)) {\n\t\t\t\temit(\n\t\t\t\t\t\"E008\",\n\t\t\t\t\t`{@link ${link.target}} in \"${symbol.name}\" references a symbol that does not exist in this project.`,\n\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\tlink.line,\n\t\t\t\t\tsymbol.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsuggestedFix: `Remove or update the {@link ${link.target}} reference to point to an existing symbol.`,\n\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// W012 — Orphaned {@link} display text detection\n\t// Build a map of symbol name → summary for comparison with link display text.\n\t{\n\t\tconst COMMON_WORDS = new Set([\n\t\t\t\"the\",\n\t\t\t\"a\",\n\t\t\t\"an\",\n\t\t\t\"is\",\n\t\t\t\"are\",\n\t\t\t\"was\",\n\t\t\t\"were\",\n\t\t\t\"be\",\n\t\t\t\"been\",\n\t\t\t\"being\",\n\t\t\t\"have\",\n\t\t\t\"has\",\n\t\t\t\"had\",\n\t\t\t\"do\",\n\t\t\t\"does\",\n\t\t\t\"did\",\n\t\t\t\"will\",\n\t\t\t\"would\",\n\t\t\t\"could\",\n\t\t\t\"should\",\n\t\t\t\"may\",\n\t\t\t\"might\",\n\t\t\t\"shall\",\n\t\t\t\"can\",\n\t\t\t\"need\",\n\t\t\t\"must\",\n\t\t\t\"to\",\n\t\t\t\"of\",\n\t\t\t\"in\",\n\t\t\t\"for\",\n\t\t\t\"on\",\n\t\t\t\"with\",\n\t\t\t\"at\",\n\t\t\t\"by\",\n\t\t\t\"from\",\n\t\t\t\"as\",\n\t\t\t\"into\",\n\t\t\t\"through\",\n\t\t\t\"during\",\n\t\t\t\"before\",\n\t\t\t\"after\",\n\t\t\t\"above\",\n\t\t\t\"below\",\n\t\t\t\"between\",\n\t\t\t\"out\",\n\t\t\t\"off\",\n\t\t\t\"over\",\n\t\t\t\"under\",\n\t\t\t\"and\",\n\t\t\t\"but\",\n\t\t\t\"or\",\n\t\t\t\"nor\",\n\t\t\t\"not\",\n\t\t\t\"so\",\n\t\t\t\"yet\",\n\t\t\t\"both\",\n\t\t\t\"either\",\n\t\t\t\"neither\",\n\t\t\t\"each\",\n\t\t\t\"every\",\n\t\t\t\"all\",\n\t\t\t\"any\",\n\t\t\t\"few\",\n\t\t\t\"more\",\n\t\t\t\"most\",\n\t\t\t\"other\",\n\t\t\t\"some\",\n\t\t\t\"such\",\n\t\t\t\"no\",\n\t\t\t\"only\",\n\t\t\t\"own\",\n\t\t\t\"same\",\n\t\t\t\"than\",\n\t\t\t\"too\",\n\t\t\t\"very\",\n\t\t\t\"this\",\n\t\t\t\"that\",\n\t\t\t\"these\",\n\t\t\t\"those\",\n\t\t\t\"it\",\n\t\t\t\"its\",\n\t\t]);\n\n\t\tconst symbolSummaryMap = new Map<string, string>();\n\t\tfor (const s of allSymbols) {\n\t\t\tif (s.documentation?.summary) {\n\t\t\t\tsymbolSummaryMap.set(s.name, s.documentation.summary);\n\t\t\t}\n\t\t\tif (s.children) {\n\t\t\t\tfor (const child of s.children) {\n\t\t\t\t\tif (child.documentation?.summary) {\n\t\t\t\t\t\tsymbolSummaryMap.set(child.name, child.documentation.summary);\n\t\t\t\t\t\tsymbolSummaryMap.set(`${s.name}.${child.name}`, child.documentation.summary);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction extractSignificantWords(text: string): Set<string> {\n\t\t\treturn new Set(\n\t\t\t\ttext\n\t\t\t\t\t.toLowerCase()\n\t\t\t\t\t.split(/\\W+/)\n\t\t\t\t\t.filter((w) => w.length > 0 && !COMMON_WORDS.has(w)),\n\t\t\t);\n\t\t}\n\n\t\tfor (const symbol of allSymbols) {\n\t\t\tconst docLinks = symbol.documentation?.links ?? [];\n\t\t\tfor (const link of docLinks) {\n\t\t\t\tif (!link.text) continue;\n\t\t\t\tif (!knownSymbols.has(link.target)) continue;\n\t\t\t\tconst targetSummary = symbolSummaryMap.get(link.target);\n\t\t\t\tif (!targetSummary) continue;\n\t\t\t\tconst linkWords = extractSignificantWords(link.text);\n\t\t\t\tconst summaryWords = extractSignificantWords(targetSummary);\n\t\t\t\tif (linkWords.size === 0 || summaryWords.size === 0) continue;\n\t\t\t\tlet overlap = 0;\n\t\t\t\tfor (const word of linkWords) {\n\t\t\t\t\tif (summaryWords.has(word)) overlap++;\n\t\t\t\t}\n\t\t\t\tif (overlap === 0) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"W012\",\n\t\t\t\t\t\t`{@link ${link.target} | ${link.text}} in \"${symbol.name}\" has display text that appears stale relative to target summary \"${targetSummary}\".`,\n\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\tlink.line,\n\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// W009 — {@inheritDoc} source doesn't exist\n\tfor (const symbol of allSymbols) {\n\t\tconst inheritDocTargets = symbol.documentation?.tags?.inheritDoc;\n\t\tif (inheritDocTargets && inheritDocTargets.length > 0) {\n\t\t\tfor (const target of inheritDocTargets) {\n\t\t\t\tif (!knownSymbols.has(target)) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"W009\",\n\t\t\t\t\t\t`{@inheritDoc ${target}} in \"${symbol.name}\" references a symbol that does not exist in this project.`,\n\t\t\t\t\t\tsymbol.filePath,\n\t\t\t\t\t\tsymbol.line,\n\t\t\t\t\t\tsymbol.column,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsuggestedFix: `Remove or update the {@inheritDoc ${target}} reference to point to an existing symbol.`,\n\t\t\t\t\t\t\tsymbolName: symbol.name,\n\t\t\t\t\t\t\tsymbolKind: symbol.kind,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// W004 — Cross-package deprecated symbol usage\n\tconst deprecatedUsages = findDeprecatedUsages(allSymbols);\n\tfor (const usage of deprecatedUsages) {\n\t\temit(\n\t\t\t\"W004\",\n\t\t\t`Import of deprecated symbol \"${usage.deprecatedSymbol}\" from package \"${usage.sourcePackage}\": ${usage.deprecationMessage}`,\n\t\t\tusage.consumingFile,\n\t\t\tusage.line,\n\t\t\t0,\n\t\t\t{\n\t\t\t\tsuggestedFix: `Replace usage of \"${usage.deprecatedSymbol}\" with its recommended replacement.`,\n\t\t\t\tsymbolName: usage.deprecatedSymbol,\n\t\t\t\tsymbolKind: \"variable\",\n\t\t\t},\n\t\t);\n\t}\n\n\t// E009 — tsconfig strictness regression\n\tconst e009Bypassed = isRuleBypassed(config.rootDir, \"E009\");\n\tif (config.guards.tsconfig.enabled) {\n\t\tconst tsconfigPath = join(config.rootDir, \"tsconfig.json\");\n\t\ttry {\n\t\t\tconst raw = readFileSync(tsconfigPath, \"utf-8\");\n\t\t\tlet parsed: { compilerOptions?: Record<string, unknown> } | undefined;\n\t\t\ttry {\n\t\t\t\tparsed = JSON.parse(raw) as { compilerOptions?: Record<string, unknown> };\n\t\t\t} catch (parseErr) {\n\t\t\t\tif (e009Bypassed) {\n\t\t\t\t\twarnings.push({\n\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\tmessage: `[BYPASSED] tsconfig.json: failed to parse — ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,\n\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\tmessage: `tsconfig.json: failed to parse — ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,\n\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (parsed) {\n\t\t\t\tconst compilerOptions = parsed.compilerOptions ?? {};\n\t\t\t\tconst requiredFlags = config.guards.tsconfig.requiredFlags;\n\t\t\t\tfor (const flag of requiredFlags) {\n\t\t\t\t\tconst value = compilerOptions[flag];\n\t\t\t\t\tif (value !== true) {\n\t\t\t\t\t\tif (e009Bypassed) {\n\t\t\t\t\t\t\twarnings.push({\n\t\t\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\t\t\tmessage: `[BYPASSED] tsconfig.json: required flag \"${flag}\" is ${value === false ? \"disabled\" : \"missing\"} — expected true`,\n\t\t\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\terrors.push({\n\t\t\t\t\t\t\t\tcode: \"E009\",\n\t\t\t\t\t\t\t\tmessage: `tsconfig.json: required flag \"${flag}\" is ${value === false ? \"disabled\" : \"missing\"} — expected true`,\n\t\t\t\t\t\t\t\tfilePath: tsconfigPath,\n\t\t\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (readErr) {\n\t\t\t// tsconfig.json not found — skip E009 gracefully\n\t\t\tif (\n\t\t\t\treadErr instanceof Error &&\n\t\t\t\t\"code\" in readErr &&\n\t\t\t\t(readErr as NodeJS.ErrnoException).code === \"ENOENT\"\n\t\t\t) {\n\t\t\t\t// Intentionally ignored: missing tsconfig.json is not an E009 error\n\t\t\t} else {\n\t\t\t\tthrow readErr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// E010 — forge-ts config drift detection via lock file\n\tconst e010Bypassed = isRuleBypassed(config.rootDir, \"E010\");\n\tconst lockManifest = readLockFile(config.rootDir);\n\tif (lockManifest) {\n\t\tconst lockViolations = validateAgainstLock(config, lockManifest);\n\t\tconst lockFilePath = join(config.rootDir, \".forge-lock.json\");\n\t\tfor (const violation of lockViolations) {\n\t\t\tif (e010Bypassed) {\n\t\t\t\twarnings.push({\n\t\t\t\t\tcode: \"E010\",\n\t\t\t\t\tmessage: `[BYPASSED] Config drift: ${violation.message}`,\n\t\t\t\t\tfilePath: lockFilePath,\n\t\t\t\t\tline: 1,\n\t\t\t\t\tcolumn: 0,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\terrors.push({\n\t\t\t\t\tcode: \"E010\",\n\t\t\t\t\tmessage: `Config drift: ${violation.message}`,\n\t\t\t\t\tfilePath: lockFilePath,\n\t\t\t\t\tline: 1,\n\t\t\t\t\tcolumn: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// E011 — Biome config weakening detection\n\tconst e011Bypassed = isRuleBypassed(config.rootDir, \"E011\");\n\tif (config.guards.biome.enabled && lockManifest?.config.biome) {\n\t\tconst biomePath = join(config.rootDir, \"biome.json\");\n\t\tconst biomePathC = join(config.rootDir, \"biome.jsonc\");\n\t\tconst actualBiomePath = existsSync(biomePath)\n\t\t\t? biomePath\n\t\t\t: existsSync(biomePathC)\n\t\t\t\t? biomePathC\n\t\t\t\t: null;\n\t\tif (actualBiomePath) {\n\t\t\ttry {\n\t\t\t\tconst biomeRaw = readFileSync(actualBiomePath, \"utf-8\");\n\t\t\t\tlet biomeParsed: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tbiomeParsed = JSON.parse(biomeRaw) as Record<string, unknown>;\n\t\t\t\t} catch {\n\t\t\t\t\t// Biome file exists but is invalid JSON/JSONC — emit one E011\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E011\",\n\t\t\t\t\t\tmessage: `Biome config \"${actualBiomePath}\": failed to parse — file may contain invalid JSON.`,\n\t\t\t\t\t\tfilePath: actualBiomePath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e011Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t\tbiomeParsed = undefined as unknown as Record<string, unknown>;\n\t\t\t\t}\n\t\t\t\tif (biomeParsed) {\n\t\t\t\t\t// Extract current biome rules from linter.rules\n\t\t\t\t\tconst currentBiomeRules = extractBiomeRules(biomeParsed);\n\t\t\t\t\t// Compare against locked biome rules snapshot\n\t\t\t\t\tconst lockedBiomeRules =\n\t\t\t\t\t\t(lockManifest.config.biome as { rules?: Record<string, string> }).rules ?? {};\n\t\t\t\t\tfor (const [ruleName, lockedLevel] of Object.entries(lockedBiomeRules)) {\n\t\t\t\t\t\tconst currentLevel = currentBiomeRules[ruleName] ?? \"off\";\n\t\t\t\t\t\tif (isWeakerBiomeLevel(currentLevel, lockedLevel)) {\n\t\t\t\t\t\t\tconst diag = {\n\t\t\t\t\t\t\t\tcode: \"E011\",\n\t\t\t\t\t\t\t\tmessage: `Biome rule \"${ruleName}\" was weakened from \"${lockedLevel}\" to \"${currentLevel}\".`,\n\t\t\t\t\t\t\t\tfilePath: actualBiomePath,\n\t\t\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tif (e011Bypassed) {\n\t\t\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (readErr) {\n\t\t\t\t// biome.json not found after existsSync — skip\n\t\t\t\tif (\n\t\t\t\t\treadErr instanceof Error &&\n\t\t\t\t\t\"code\" in readErr &&\n\t\t\t\t\t(readErr as NodeJS.ErrnoException).code === \"ENOENT\"\n\t\t\t\t) {\n\t\t\t\t\t// Intentionally ignored\n\t\t\t\t} else {\n\t\t\t\t\tthrow readErr;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// E012 — package.json engine field tampering\n\tconst e012Bypassed = isRuleBypassed(config.rootDir, \"E012\");\n\tif (config.guards.packageJson.enabled) {\n\t\tconst pkgJsonPath = join(config.rootDir, \"package.json\");\n\t\ttry {\n\t\t\tconst pkgRaw = readFileSync(pkgJsonPath, \"utf-8\");\n\t\t\tconst pkg = JSON.parse(pkgRaw) as Record<string, unknown>;\n\n\t\t\t// Check required fields\n\t\t\tfor (const field of config.guards.packageJson.requiredFields) {\n\t\t\t\tif (pkg[field] === undefined) {\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E012\",\n\t\t\t\t\t\tmessage: `package.json: required field \"${field}\" is missing.`,\n\t\t\t\t\t\tfilePath: pkgJsonPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e012Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check engines.node against minNodeVersion\n\t\t\tconst engines = pkg.engines as Record<string, string> | undefined;\n\t\t\tconst nodeEngine = engines?.node;\n\t\t\tif (!nodeEngine) {\n\t\t\t\t// Only emit if \"engines\" is in requiredFields (missing engines already caught above)\n\t\t\t\t// But also check specifically for missing engines.node\n\t\t\t\tif (engines !== undefined) {\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E012\",\n\t\t\t\t\t\tmessage: `package.json: \"engines.node\" field is missing.`,\n\t\t\t\t\t\tfilePath: pkgJsonPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e012Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Simple semver comparison: extract major.minor from the engines string\n\t\t\t\tconst minVersion = parseSemverMajorMinor(config.guards.packageJson.minNodeVersion);\n\t\t\t\tconst engineVersion = parseSemverMajorMinor(nodeEngine);\n\t\t\t\tif (minVersion && engineVersion && compareMajorMinor(engineVersion, minVersion) < 0) {\n\t\t\t\t\tconst diag = {\n\t\t\t\t\t\tcode: \"E012\",\n\t\t\t\t\t\tmessage: `package.json: \"engines.node\" specifies \"${nodeEngine}\" which is lower than the minimum required \"${config.guards.packageJson.minNodeVersion}\".`,\n\t\t\t\t\t\tfilePath: pkgJsonPath,\n\t\t\t\t\t\tline: 1,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t};\n\t\t\t\t\tif (e012Bypassed) {\n\t\t\t\t\t\twarnings.push({ ...diag, message: `[BYPASSED] ${diag.message}` });\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors.push(diag);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (readErr) {\n\t\t\t// package.json not found — skip\n\t\t\tif (\n\t\t\t\treadErr instanceof Error &&\n\t\t\t\t\"code\" in readErr &&\n\t\t\t\t(readErr as NodeJS.ErrnoException).code === \"ENOENT\"\n\t\t\t) {\n\t\t\t\t// Intentionally ignored\n\t\t\t} else if (readErr instanceof SyntaxError) {\n\t\t\t\t// Invalid JSON — skip gracefully\n\t\t\t} else {\n\t\t\t\tthrow readErr;\n\t\t\t}\n\t\t}\n\t}\n\n\t// W007 — Stale guide FORGE:AUTO sections (references to removed/renamed symbols)\n\t// W008 — Undocumented public symbol in guides (exported but not mentioned)\n\tconst guidesDir = join(config.outDir, \"guides\");\n\tlet guideFiles: string[] = [];\n\tlet guideContents: Map<string, string> | undefined;\n\n\t// Only attempt guide checks if the guides directory exists\n\tif (existsSync(guidesDir)) {\n\t\ttry {\n\t\t\tconst entries = readdirSync(guidesDir);\n\t\t\tguideFiles = entries.filter((f) => f.endsWith(\".md\") || f.endsWith(\".mdx\"));\n\t\t} catch {\n\t\t\t// If we cannot read the directory, skip guide rules\n\t\t}\n\t}\n\n\tif (guideFiles.length > 0) {\n\t\tguideContents = new Map<string, string>();\n\t\tfor (const file of guideFiles) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(join(guidesDir, file), \"utf-8\");\n\t\t\t\tguideContents.set(file, content);\n\t\t\t} catch {\n\t\t\t\t// Skip unreadable files\n\t\t\t}\n\t\t}\n\n\t\t// W007 — Check FORGE:AUTO sections for references to symbols that no longer exist\n\t\tconst autoStartRe = /<!--\\s*FORGE:AUTO-START\\s+(\\S+)\\s*-->/g;\n\t\tconst autoEndRe = /<!--\\s*FORGE:AUTO-END\\s+(\\S+)\\s*-->/;\n\t\t// Match symbol references inside auto sections: `symbolName` in backticks or bare names\n\t\t// after typical markdown patterns (links, bold, code).\n\t\t// Simplified heuristic: extract all backtick-quoted identifiers inside FORGE:AUTO blocks.\n\t\tconst symbolRefRe = /`([A-Za-z_$][A-Za-z0-9_$]*)`/g;\n\n\t\tfor (const [file, content] of guideContents) {\n\t\t\tconst filePath = join(guidesDir, file);\n\t\t\t// Find each FORGE:AUTO block\n\t\t\tautoStartRe.lastIndex = 0;\n\t\t\tfor (\n\t\t\t\tlet match = autoStartRe.exec(content);\n\t\t\t\tmatch !== null;\n\t\t\t\tmatch = autoStartRe.exec(content)\n\t\t\t) {\n\t\t\t\tconst startIdx = match.index + match[0].length;\n\t\t\t\t// Find the matching end marker\n\t\t\t\tconst restContent = content.slice(startIdx);\n\t\t\t\tconst endMatch = autoEndRe.exec(restContent);\n\t\t\t\tif (!endMatch) continue;\n\t\t\t\tconst autoBlock = restContent.slice(0, endMatch.index);\n\n\t\t\t\t// Extract all backtick-quoted identifiers from the auto block\n\t\t\t\tsymbolRefRe.lastIndex = 0;\n\t\t\t\tfor (\n\t\t\t\t\tlet refMatch = symbolRefRe.exec(autoBlock);\n\t\t\t\t\trefMatch !== null;\n\t\t\t\t\trefMatch = symbolRefRe.exec(autoBlock)\n\t\t\t\t) {\n\t\t\t\t\tconst refName = refMatch[1];\n\t\t\t\t\t// Check if this name exists in the known symbols set\n\t\t\t\t\tif (!knownSymbols.has(refName)) {\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"W007\",\n\t\t\t\t\t\t\t`Guide \"${file}\" FORGE:AUTO section references symbol \"${refName}\" which no longer exists in the symbol graph.`,\n\t\t\t\t\t\t\tfilePath,\n\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tsymbolName: refName,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// W008 — Check that all exported symbols from index.ts are mentioned in at least one guide\n\t\tconst allGuideText = [...guideContents.values()].join(\"\\n\");\n\t\tconst indexExportedSymbols = allSymbols.filter(\n\t\t\t(s) => s.exported && /[/\\\\]index\\.ts$/.test(s.filePath),\n\t\t);\n\t\tfor (const sym of indexExportedSymbols) {\n\t\t\tif (!allGuideText.includes(sym.name)) {\n\t\t\t\temit(\n\t\t\t\t\t\"W008\",\n\t\t\t\t\t`Exported symbol \"${sym.name}\" from \"${sym.filePath}\" is not mentioned in any guide page.`,\n\t\t\t\t\tsym.filePath,\n\t\t\t\t\tsym.line,\n\t\t\t\t\tsym.column,\n\t\t\t\t\t{\n\t\t\t\t\t\tsymbolName: sym.name,\n\t\t\t\t\t\tsymbolKind: sym.kind,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst success = errors.length === 0;\n\treturn { success, symbols: allSymbols, errors, warnings, duration: Date.now() - start };\n}\n","import type { ForgeResult } from \"@forge-ts/core\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Options that control how {@link formatResults} renders its output.\n * @public\n */\nexport interface FormatOptions {\n\t/** Emit ANSI colour escape sequences when `true`. */\n\tcolors: boolean;\n\t/**\n\t * When `true`, include the symbol's type signature alongside each\n\t * diagnostic so the reader has immediate context.\n\t */\n\tverbose: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// ANSI helpers\n// ---------------------------------------------------------------------------\n\n/** @internal */\nconst RESET = \"\\x1b[0m\";\n/** @internal */\nconst RED = \"\\x1b[31m\";\n/** @internal */\nconst YELLOW = \"\\x1b[33m\";\n/** @internal */\nconst BOLD = \"\\x1b[1m\";\n/** @internal */\nconst DIM = \"\\x1b[2m\";\n\n/** @internal */\nfunction colorize(text: string, color: string, useColors: boolean): string {\n\treturn useColors ? `${color}${text}${RESET}` : text;\n}\n\n/** @internal */\nfunction bold(text: string, useColors: boolean): string {\n\treturn useColors ? `${BOLD}${text}${RESET}` : text;\n}\n\n/** @internal */\nfunction dim(text: string, useColors: boolean): string {\n\treturn useColors ? `${DIM}${text}${RESET}` : text;\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\n/** @internal */\ninterface Diagnostic {\n\tcode: string;\n\tmessage: string;\n\tfilePath: string;\n\tline: number;\n\tcolumn: number;\n}\n\n/** @internal */\nfunction isError(code: string): boolean {\n\treturn code.startsWith(\"E\");\n}\n\n/** @internal */\nfunction renderDiagnostic(diag: Diagnostic, opts: FormatOptions): string {\n\tconst label = isError(diag.code)\n\t\t? colorize(`error[${diag.code}]`, RED, opts.colors)\n\t\t: colorize(`warning[${diag.code}]`, YELLOW, opts.colors);\n\n\tconst location = dim(`${diag.line}:${diag.column}`, opts.colors);\n\treturn ` ${label} ${diag.message} ${location}`;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Formats a {@link ForgeResult} into a human-readable string suitable for\n * printing to a terminal.\n *\n * Diagnostics are grouped by source file. Each file heading shows the\n * relative-ish path, followed by indented error and warning lines. A summary\n * line is appended at the end.\n *\n * @param result - The result produced by {@link enforce}.\n * @param options - Rendering options (colours, verbosity).\n * @returns A formatted string ready to write to stdout or stderr.\n * @example\n * ```typescript\n * import { enforce } from \"@forge-ts/enforcer\";\n * import { formatResults } from \"@forge-ts/enforcer\";\n * import { loadConfig } from \"@forge-ts/core\";\n * const config = await loadConfig();\n * const result = await enforce(config);\n * console.log(formatResults(result, { colors: true, verbose: false }));\n * ```\n * @public\n */\nexport function formatResults(result: ForgeResult, options: FormatOptions): string {\n\tconst allDiags: Diagnostic[] = [\n\t\t...result.errors.map((e) => ({ ...e })),\n\t\t...result.warnings.map((w) => ({ ...w })),\n\t];\n\n\tif (allDiags.length === 0) {\n\t\tconst msg = `No issues found across ${result.symbols.length} symbol(s).`;\n\t\treturn bold(msg, options.colors);\n\t}\n\n\t// Group by filePath\n\tconst byFile = new Map<string, Diagnostic[]>();\n\tfor (const diag of allDiags) {\n\t\tconst list = byFile.get(diag.filePath);\n\t\tif (list) {\n\t\t\tlist.push(diag);\n\t\t} else {\n\t\t\tbyFile.set(diag.filePath, [diag]);\n\t\t}\n\t}\n\n\tconst lines: string[] = [];\n\n\tfor (const [filePath, diags] of byFile) {\n\t\tlines.push(bold(filePath, options.colors));\n\n\t\t// Sort: errors before warnings, then by line\n\t\tconst sorted = [...diags].sort((a, b) => {\n\t\t\tconst aIsErr = isError(a.code) ? 0 : 1;\n\t\t\tconst bIsErr = isError(b.code) ? 0 : 1;\n\t\t\tif (aIsErr !== bIsErr) return aIsErr - bIsErr;\n\t\t\treturn a.line - b.line;\n\t\t});\n\n\t\tfor (const diag of sorted) {\n\t\t\tlines.push(renderDiagnostic(diag, options));\n\n\t\t\tif (options.verbose) {\n\t\t\t\t// Find the matching symbol to show its signature\n\t\t\t\tconst sym = result.symbols.find(\n\t\t\t\t\t(s) => s.filePath === diag.filePath && s.line === diag.line,\n\t\t\t\t);\n\t\t\t\tif (sym?.signature) {\n\t\t\t\t\tlines.push(dim(` signature: ${sym.signature}`, options.colors));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlines.push(\"\");\n\t}\n\n\t// Summary line\n\tconst errorCount = result.errors.length;\n\tconst warnCount = result.warnings.length;\n\tconst fileCount = byFile.size;\n\n\tconst errorPart =\n\t\terrorCount > 0\n\t\t\t? colorize(`${errorCount} error${errorCount !== 1 ? \"s\" : \"\"}`, RED, options.colors)\n\t\t\t: `0 errors`;\n\tconst warnPart =\n\t\twarnCount > 0\n\t\t\t? colorize(`${warnCount} warning${warnCount !== 1 ? \"s\" : \"\"}`, YELLOW, options.colors)\n\t\t\t: `0 warnings`;\n\tconst filePart = `${fileCount} file${fileCount !== 1 ? \"s\" : \"\"}`;\n\n\tlines.push(`${errorPart}, ${warnPart} in ${filePart}`);\n\n\treturn lines.join(\"\\n\");\n}\n"],"mappings":"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","names":["diag","extractSignificantWords"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge-ts/enforcer",
3
- "version": "0.19.2",
3
+ "version": "0.19.4",
4
4
  "type": "module",
5
5
  "description": "TSDoc enforcement linter for forge-ts",
6
6
  "license": "MIT",
@@ -24,7 +24,7 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@forge-ts/core": "0.19.2"
27
+ "@forge-ts/core": "0.19.4"
28
28
  },
29
29
  "devDependencies": {
30
30
  "tsup": "^8.3.5",