taste-lint 0.0.1
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/LICENSE.md +9 -0
- package/README.md +141 -0
- package/data/config.schema.json +123 -0
- package/data/corpus/blode-co-review.jsonl +80 -0
- package/data/corpus/copywriting.jsonl +139 -0
- package/data/corpus/typography.jsonl +53 -0
- package/data/rule-drafts/README.md +9 -0
- package/data/rule-drafts/interaction/interaction-layout-shift.yaml +54 -0
- package/data/rule-drafts/typography/typography-long-content-safety.yaml +60 -0
- package/data/rules/authoring/authoring-approval-every-step.yaml +44 -0
- package/data/rules/authoring/authoring-fixed-agent-quota.yaml +44 -0
- package/data/rules/authoring/authoring-generic-coding-advice.yaml +44 -0
- package/data/rules/authoring/authoring-generic-verification.yaml +45 -0
- package/data/rules/authoring/authoring-plan-vague-acceptance.yaml +43 -0
- package/data/rules/copywriting/copywriting-announced-honesty.yaml +43 -0
- package/data/rules/copywriting/copywriting-anthropomorphism.yaml +29 -0
- package/data/rules/copywriting/copywriting-artificial-balance.yaml +35 -0
- package/data/rules/copywriting/copywriting-bare-confirm-label.yaml +23 -0
- package/data/rules/copywriting/copywriting-boilerplate-offer.yaml +38 -0
- package/data/rules/copywriting/copywriting-canned-phrasing.yaml +53 -0
- package/data/rules/copywriting/copywriting-changed-supplied-facts.yaml +31 -0
- package/data/rules/copywriting/copywriting-claim-without-evidence.yaml +59 -0
- package/data/rules/copywriting/copywriting-click-here-links.yaml +22 -0
- package/data/rules/copywriting/copywriting-conditions-first.yaml +50 -0
- package/data/rules/copywriting/copywriting-confirmshaming.yaml +43 -0
- package/data/rules/copywriting/copywriting-cta-names-outcome.yaml +54 -0
- package/data/rules/copywriting/copywriting-dead-weight-hedges.yaml +58 -0
- package/data/rules/copywriting/copywriting-drafting-instruction-echo.yaml +31 -0
- package/data/rules/copywriting/copywriting-emoji-in-ui.yaml +20 -0
- package/data/rules/copywriting/copywriting-empty-state-no-action.yaml +51 -0
- package/data/rules/copywriting/copywriting-error-descriptions.yaml +53 -0
- package/data/rules/copywriting/copywriting-excessive-hedging.yaml +48 -0
- package/data/rules/copywriting/copywriting-fabricated-specificity.yaml +35 -0
- package/data/rules/copywriting/copywriting-filler-words.yaml +55 -0
- package/data/rules/copywriting/copywriting-flat-description.yaml +37 -0
- package/data/rules/copywriting/copywriting-friction-cta.yaml +53 -0
- package/data/rules/copywriting/copywriting-generic-audience.yaml +55 -0
- package/data/rules/copywriting/copywriting-generic-framing.yaml +35 -0
- package/data/rules/copywriting/copywriting-generic-language.yaml +35 -0
- package/data/rules/copywriting/copywriting-generic-validation.yaml +46 -0
- package/data/rules/copywriting/copywriting-idea-repetition.yaml +34 -0
- package/data/rules/copywriting/copywriting-latinisms.yaml +25 -0
- package/data/rules/copywriting/copywriting-leaked-error-message.yaml +23 -0
- package/data/rules/copywriting/copywriting-live-region-feedback.yaml +24 -0
- package/data/rules/copywriting/copywriting-machine-prose.yaml +73 -0
- package/data/rules/copywriting/copywriting-mechanism-over-outcome.yaml +33 -0
- package/data/rules/copywriting/copywriting-meta-commentary.yaml +48 -0
- package/data/rules/copywriting/copywriting-missing-reasoning-link.yaml +33 -0
- package/data/rules/copywriting/copywriting-nominalisations.yaml +45 -0
- package/data/rules/copywriting/copywriting-over-explanation.yaml +34 -0
- package/data/rules/copywriting/copywriting-passive-voice.yaml +53 -0
- package/data/rules/copywriting/copywriting-permission-benefit.yaml +43 -0
- package/data/rules/copywriting/copywriting-profile-register-mismatch.yaml +31 -0
- package/data/rules/copywriting/copywriting-promotional-docs-voice.yaml +58 -0
- package/data/rules/copywriting/copywriting-prompt-restatement.yaml +35 -0
- package/data/rules/copywriting/copywriting-punctuation-tics.yaml +35 -0
- package/data/rules/copywriting/copywriting-reader-first.yaml +59 -0
- package/data/rules/copywriting/copywriting-register-shift.yaml +58 -0
- package/data/rules/copywriting/copywriting-repetitive-transitions.yaml +48 -0
- package/data/rules/copywriting/copywriting-requirements-language.yaml +50 -0
- package/data/rules/copywriting/copywriting-searchable-headings.yaml +52 -0
- package/data/rules/copywriting/copywriting-semantic-links.yaml +23 -0
- package/data/rules/copywriting/copywriting-structural-symmetry.yaml +35 -0
- package/data/rules/copywriting/copywriting-success-state-specific.yaml +43 -0
- package/data/rules/copywriting/copywriting-temporal-words.yaml +55 -0
- package/data/rules/copywriting/copywriting-toast-successfully.yaml +22 -0
- package/data/rules/copywriting/copywriting-unexplained-action.yaml +33 -0
- package/data/rules/copywriting/copywriting-unnatural-polish.yaml +48 -0
- package/data/rules/copywriting/copywriting-unraised-objection.yaml +43 -0
- package/data/rules/copywriting/copywriting-unverifiable-proof.yaml +23 -0
- package/data/rules/copywriting/copywriting-vague-error.yaml +58 -0
- package/data/rules/copywriting/copywriting-vague-personal-request.yaml +43 -0
- package/data/rules/copywriting/copywriting-visual-direction-instruction.yaml +43 -0
- package/data/rules/craft/craft-affordance-mismatch.yaml +23 -0
- package/data/rules/craft/craft-decoration-no-role.yaml +27 -0
- package/data/rules/craft/craft-faux-product-chrome.yaml +22 -0
- package/data/rules/craft/craft-hover-only-affordance.yaml +23 -0
- package/data/rules/craft/craft-i18n-rtl-untested.yaml +23 -0
- package/data/rules/craft/craft-i18n-untested.yaml +28 -0
- package/data/rules/craft/craft-image-dimensions-and-priority.yaml +23 -0
- package/data/rules/craft/craft-inline-styles.yaml +24 -0
- package/data/rules/craft/craft-lazy-load-offscreen.yaml +28 -0
- package/data/rules/craft/craft-near-duplicate-scale.yaml +29 -0
- package/data/rules/craft/craft-token-drift.yaml +22 -0
- package/data/rules/craft/craft-viewport-scaling.yaml +25 -0
- package/data/rules/craft/craft-virtualize-large-lists.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-color-only-meaning.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-data-table-semantics.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-disabled-control-tooltip.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-document-language.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-icon-controls-labeled.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-image-alt-text.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-media-captions.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-semantic-html-first.yaml +23 -0
- package/data/rules/interaction/interaction-a11y-skip-link-heading-order.yaml +24 -0
- package/data/rules/interaction/interaction-a11y-tooltip-no-interactive.yaml +23 -0
- package/data/rules/interaction/interaction-broken-focus-trap.yaml +25 -0
- package/data/rules/interaction/interaction-dont-block-paste-ime.yaml +23 -0
- package/data/rules/interaction/interaction-error-association.yaml +24 -0
- package/data/rules/interaction/interaction-focus-visible.yaml +25 -0
- package/data/rules/interaction/interaction-inline-errors-first-focus.yaml +24 -0
- package/data/rules/interaction/interaction-input-affix-hit-target.yaml +23 -0
- package/data/rules/interaction/interaction-keyboard-operable.yaml +23 -0
- package/data/rules/interaction/interaction-labels-and-autocomplete.yaml +23 -0
- package/data/rules/interaction/interaction-lost-data-on-error.yaml +23 -0
- package/data/rules/interaction/interaction-mobile-input-font-size.yaml +24 -0
- package/data/rules/interaction/interaction-no-disable-while-submitting.yaml +23 -0
- package/data/rules/interaction/interaction-no-empty-state.yaml +26 -0
- package/data/rules/interaction/interaction-no-error-boundary.yaml +27 -0
- package/data/rules/interaction/interaction-no-error-state.yaml +26 -0
- package/data/rules/interaction/interaction-no-suspense-boundary.yaml +23 -0
- package/data/rules/interaction/interaction-not-restored.yaml +25 -0
- package/data/rules/interaction/interaction-on-dynamic-content.yaml +25 -0
- package/data/rules/interaction/interaction-optimistic-without-rollback.yaml +23 -0
- package/data/rules/interaction/interaction-out-of-order-responses.yaml +27 -0
- package/data/rules/interaction/interaction-target-size.yaml +26 -0
- package/data/rules/interaction/interaction-use-form-status-misuse.yaml +23 -0
- package/data/rules/product/product-nested-modals.yaml +26 -0
- package/data/rules/product/product-select-for-few-options.yaml +24 -0
- package/data/rules/schema/rule.schema.json +262 -0
- package/data/rules/tuning.json +1 -0
- package/data/rules/typography/typography-dashes.yaml +28 -0
- package/data/rules/typography/typography-ellipsis.yaml +27 -0
- package/data/rules/typography/typography-hover-weight-shift.yaml +24 -0
- package/data/rules/typography/typography-midpoint-separators.yaml +21 -0
- package/data/rules/typography/typography-multiplication-sign.yaml +27 -0
- package/data/rules/typography/typography-nbsp-value-unit.yaml +27 -0
- package/data/rules/typography/typography-readable-scale.yaml +23 -0
- package/data/rules/typography/typography-straight-quotes.yaml +37 -0
- package/data/rules/typography/typography-title-case-heading.yaml +49 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +6317 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +736 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5330 -0
- package/dist/index.js.map +1 -0
- package/package.json +87 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":["isRecord","invalid","describe","EM_DASH","make","MODULE","rule","at","make","object","make","describe","ATTR_STRING_NAMES","pkg.version","pkg.version"],"sources":["../package.json","../src/lib/stats.ts","../src/rules/taxonomy.ts","../src/types.ts","../src/eval/corpus.ts","../src/eval/coverage.ts","../src/extract/tailwind.ts","../src/lib/errors.ts","../src/lib/glob.ts","../src/lib/config.ts","../src/lib/record.ts","../src/map/cache.ts","../src/map/jev.ts","../src/lib/tokens.ts","../src/rules/question.ts","../src/map/limiter.ts","../src/map/state.ts","../src/map/batch.ts","../src/extract/units.ts","../src/reduce/finding.ts","../src/reduce/mechanical.ts","../src/map/plan.ts","../src/map/judge.ts","../src/reduce/bands.ts","../src/reduce/fixes.ts","../src/rules/validate-sections.ts","../src/rules/validate.ts","../src/rules/code/rule.ts","../src/rules/code/architecture.ts","../src/rules/code/classes.ts","../src/analysis/repository.ts","../src/rules/code/documents.ts","../src/rules/code/repository.ts","../src/rules/code/skill-classes.ts","../src/rules/code/typography.ts","../src/rules/code/index.ts","../src/rules/load.ts","../src/eval/metrics.ts","../src/commands/eval.ts","../src/lib/frontmatter.ts","../src/extract/markdown.ts","../src/extract/tsx.ts","../src/extract/index.ts","../src/commands/extract.ts","../src/lib/spawn.ts","../src/extract/capture.ts","../src/extract/style-capture-text.ts","../src/extract/rendered.ts","../src/lib/writing-context.ts","../src/reduce/dedupe.ts","../src/reduce/scorecard.ts","../src/reduce/suppress.ts","../src/lint.ts","../src/report/json.ts","../src/report/sarif.ts","../src/report/tty.ts","../src/commands/lint.ts","../src/rules/discover.ts","../src/commands/rules.ts","../src/scan/profiles.ts","../src/scan/storage.ts","../src/scan/report.ts","../src/scan/architecture.ts","../src/scan/git.ts","../src/scan/samples.ts","../src/scan/run.ts","../src/commands/scan.ts","../src/eval/promotion.ts","../src/eval/tune.ts","../src/commands/tune.ts","../src/cli.ts"],"sourcesContent":["","// Statistics helpers copied from agent-evals routing.ts so the two tools\n// report the same numbers for the same inputs, with one correction: McNemar's\n// continuity correction is clamped at zero, so equal discordant counts give\n// p = 1 rather than a spurious difference.\n\n// Deterministic PRNG (mulberry32).\nexport const makePRNG = (seed: number): (() => number) => {\n let a = seed >>> 0;\n return (): number => {\n a |= 0;\n a = (a + 0x6d_2b_79_f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296;\n };\n};\n\n// Wilson score interval for a binomial proportion (95% by default).\nexport const wilson = (\n successes: number,\n n: number,\n z = 1.96\n): [number, number] => {\n if (n === 0) {\n // No trials: the uninformative interval, never a confident zero.\n return [0, 1];\n }\n const phat = successes / n;\n const denom = 1 + (z * z) / n;\n const center = (phat + (z * z) / (2 * n)) / denom;\n const margin =\n (z / denom) * Math.sqrt((phat * (1 - phat)) / n + (z * z) / (4 * n * n));\n return [Math.max(0, center - margin), Math.min(1, center + margin)];\n};\n\n// Abramowitz-Stegun erfc approximation (max abs error ~1.2e-7).\nconst erfc = (x: number): number => {\n const z = Math.abs(x);\n const t = 1 / (1 + 0.5 * z);\n const c = [\n -1.26551223, 1.00002368, 0.37409196, 0.09678418, -0.18628806, 0.27886807,\n -1.13520398, 1.48851587, -0.82215223, 0.17087277,\n ];\n let poly = c.at(-1) as number;\n for (let i = c.length - 2; i >= 0; i -= 1) {\n poly = (c[i] as number) + t * poly;\n }\n const r = t * Math.exp(-z * z + poly);\n return x >= 0 ? r : 2 - r;\n};\n\n// McNemar paired test for two correctness vectors over the same item set.\nexport const mcnemar = (\n aCorrect: boolean[],\n bCorrect: boolean[]\n): {\n discordant: number;\n n01: number;\n n10: number;\n pValue: number;\n statistic: number;\n} => {\n if (aCorrect.length !== bCorrect.length) {\n throw new Error(\n \"mcnemar: aCorrect and bCorrect must be equal-length arrays\"\n );\n }\n let n01 = 0;\n let n10 = 0;\n for (let i = 0; i < aCorrect.length; i += 1) {\n const a = !!aCorrect[i];\n const b = !!bCorrect[i];\n if (a && !b) {\n n01 += 1;\n } else if (!a && b) {\n n10 += 1;\n }\n }\n const discordant = n01 + n10;\n // Continuity-corrected; equal discordant counts give 0, not (-1)^2.\n const statistic =\n discordant === 0\n ? 0\n : Math.max(0, Math.abs(n01 - n10) - 1) ** 2 / discordant;\n const pValue =\n statistic === 0 ? 1 : Math.min(1, erfc(Math.sqrt(statistic / 2)));\n return { discordant, n01, n10, pValue, statistic };\n};\n\nexport interface BinaryMetrics {\n tp: number;\n fp: number;\n fn: number;\n tn: number;\n precision: number;\n recall: number;\n f1: number;\n precisionCI: [number, number];\n recallCI: [number, number];\n}\n\n// Precision, recall and F1 for one rule over labelled (label, predicted) pairs.\nexport const binaryMetrics = (\n pairs: { label: boolean; predicted: boolean }[]\n): BinaryMetrics => {\n let tp = 0;\n let fp = 0;\n let fn = 0;\n let tn = 0;\n for (const { label, predicted } of pairs) {\n if (label && predicted) {\n tp += 1;\n } else if (!label && predicted) {\n fp += 1;\n } else if (label && !predicted) {\n fn += 1;\n } else {\n tn += 1;\n }\n }\n const precision = tp + fp === 0 ? 0 : tp / (tp + fp);\n const recall = tp + fn === 0 ? 0 : tp / (tp + fn);\n const f1 =\n precision + recall === 0\n ? 0\n : (2 * precision * recall) / (precision + recall);\n return {\n f1,\n fn,\n fp,\n precision,\n precisionCI: wilson(tp, tp + fp),\n recall,\n recallCI: wilson(tp, tp + fn),\n tn,\n tp,\n };\n};\n\n// Calibration table: observed positive rate per predicted-probability bucket.\nexport const calibrationTable = (\n pairs: { label: boolean; probability: number }[],\n buckets = 10\n): { lo: number; hi: number; n: number; positives: number; meanP: number }[] =>\n Array.from({ length: buckets }, (_, i) => {\n const lo = i / buckets;\n const hi = (i + 1) / buckets;\n const rows = pairs.filter(\n (p) =>\n p.probability >= lo &&\n (p.probability < hi || (i === buckets - 1 && p.probability <= 1))\n );\n return {\n hi,\n lo,\n meanP:\n rows.length === 0\n ? 0\n : rows.reduce((s, r) => s + r.probability, 0) / rows.length,\n n: rows.length,\n positives: rows.filter((r) => r.label).length,\n };\n });\n","// The 33 failure-mode categories, copied from\n// mblode/taste-training apps/web/content/categories.ts. Every rule carries one\n// of these ids so a finding links back to the lesson that teaches the fix.\n\nimport type { Domain } from \"../types.js\";\n\nexport interface Category {\n id: string;\n domain: Domain;\n label: string;\n}\n\nexport const CATEGORIES: readonly Category[] = [\n {\n domain: \"architecture\",\n id: \"repository-contracts\",\n label: \"Repository contracts\",\n },\n { domain: \"dx\", id: \"package-contracts\", label: \"Package contracts\" },\n {\n domain: \"authoring\",\n id: \"instruction-quality\",\n label: \"Instruction quality\",\n },\n { domain: \"typography\", id: \"type-quality\", label: \"Type quality\" },\n {\n domain: \"typography\",\n id: \"typographic-detail\",\n label: \"Typographic detail\",\n },\n { domain: \"typography\", id: \"reading-comfort\", label: \"Reading comfort\" },\n { domain: \"typography\", id: \"type-hierarchy\", label: \"Type hierarchy\" },\n { domain: \"typography\", id: \"type-voice\", label: \"Type voice\" },\n { domain: \"typography\", id: \"type-pairing\", label: \"Type pairing\" },\n {\n domain: \"craft\",\n id: \"grouping-proximity\",\n label: \"Grouping and proximity\",\n },\n { domain: \"craft\", id: \"elevation-and-edges\", label: \"Elevation and edges\" },\n { domain: \"craft\", id: \"colour-system\", label: \"Colour system\" },\n { domain: \"craft\", id: \"visual-hierarchy\", label: \"Visual hierarchy\" },\n { domain: \"craft\", id: \"generic-decoration\", label: \"Generic decoration\" },\n { domain: \"craft\", id: \"look-constraints\", label: \"Look constraints\" },\n { domain: \"craft\", id: \"optical-adjustment\", label: \"Optical adjustment\" },\n { domain: \"craft\", id: \"resilience\", label: \"Resilience\" },\n { domain: \"craft\", id: \"last-mile-polish\", label: \"Last-mile polish\" },\n {\n domain: \"copywriting\",\n id: \"reader-first-framing\",\n label: \"Reader-first framing\",\n },\n {\n domain: \"copywriting\",\n id: \"evidence-over-claims\",\n label: \"Evidence over claims\",\n },\n { domain: \"copywriting\", id: \"actionable-cta\", label: \"Actionable CTA\" },\n {\n domain: \"copywriting\",\n id: \"actionable-microcopy\",\n label: \"Actionable microcopy\",\n },\n { domain: \"copywriting\", id: \"page-structure\", label: \"Page structure\" },\n {\n domain: \"copywriting\",\n id: \"reference-reading\",\n label: \"Reference reading\",\n },\n { domain: \"copywriting\", id: \"machine-prose\", label: \"Machine prose\" },\n { domain: \"interaction\", id: \"form-usability\", label: \"Form usability\" },\n { domain: \"interaction\", id: \"state-coverage\", label: \"State coverage\" },\n {\n domain: \"interaction\",\n id: \"focus-and-a11y\",\n label: \"Focus and accessibility\",\n },\n { domain: \"motion\", id: \"easing-and-duration\", label: \"Easing and duration\" },\n { domain: \"motion\", id: \"spatial-continuity\", label: \"Spatial continuity\" },\n {\n domain: \"motion\",\n id: \"stagger-and-orchestration\",\n label: \"Stagger and orchestration\",\n },\n { domain: \"motion\", id: \"motion-restraint\", label: \"Motion restraint\" },\n { domain: \"product\", id: \"control-choice\", label: \"Control choice\" },\n {\n domain: \"product\",\n id: \"consequence-scoping\",\n label: \"Consequence scoping\",\n },\n { domain: \"product\", id: \"design-decisions\", label: \"Design decisions\" },\n { domain: \"product\", id: \"agent-trust\", label: \"Agent trust\" },\n];\n\nexport const CATEGORY_BY_ID: ReadonlyMap<string, Category> = new Map(\n CATEGORIES.map((c) => [c.id, c])\n);\n","// Shared type definitions. See docs/DESIGN.md for the contracts.\n\nimport type { SourceFacts } from \"./analysis/repository.js\";\n\nexport const DOMAINS = [\n \"typography\",\n \"craft\",\n \"copywriting\",\n \"interaction\",\n \"motion\",\n \"product\",\n \"architecture\",\n \"dx\",\n \"authoring\",\n] as const;\nexport type Domain = (typeof DOMAINS)[number];\n\nexport const UNIT_KINDS = [\n \"paragraph\",\n \"heading\",\n \"jsx-text\",\n \"attr-string\",\n \"class-list\",\n \"element\",\n /** The whole file, for mechanical-only regex rules over raw source. */\n \"source\",\n /** A file that did not parse; carries the error and nothing else. */\n \"file\",\n] as const;\n/** Kinds that are not a piece of copy and never count as units in a report. */\nexport const STRUCTURAL_KINDS: readonly UnitKind[] = [\"source\", \"file\"];\nexport type UnitKind = (typeof UNIT_KINDS)[number];\n\nexport const TIERS = [\"mechanical\", \"jev\", \"both\"] as const;\nexport type Tier = (typeof TIERS)[number];\n\nexport const SEVERITIES = [\"major\", \"minor\"] as const;\nexport type Severity = (typeof SEVERITIES)[number];\n/** Lower is more severe; the single owner of severity ordering. */\nexport const SEVERITY_RANK: Record<Severity, number> = { major: 0, minor: 1 };\n\nexport const RULE_STATUSES = [\"active\", \"draft\", \"review-only\"] as const;\nexport type RuleStatus = (typeof RULE_STATUSES)[number];\n\nexport const DOC_TYPES = [\n \"tutorial\",\n \"howto\",\n \"reference\",\n \"explanation\",\n \"agent-instructions\",\n \"lesson\",\n \"marketing\",\n \"ui\",\n \"readme\",\n \"skill\",\n \"plan\",\n \"personal\",\n \"pr\",\n \"slides\",\n \"unknown\",\n] as const;\nexport type DocType = (typeof DOC_TYPES)[number];\n\nexport const ROLES = [\n \"heading\",\n \"body\",\n \"list-item\",\n \"cell\",\n \"button\",\n \"link\",\n \"label\",\n \"placeholder\",\n \"aria\",\n \"literal-copy\",\n \"caption\",\n \"unknown\",\n] as const;\nexport type Role = (typeof ROLES)[number];\n\nexport const CONTEXT_KEYS = [\n \"section\",\n \"headingAbove\",\n \"docType\",\n \"element\",\n \"role\",\n \"neighbours\",\n \"writingFacts\",\n \"writingProfile\",\n \"writingInstructions\",\n] as const;\nexport type ContextKey = (typeof CONTEXT_KEYS)[number];\n\nexport type Band = \"act\" | \"review\" | \"silent\";\n\nexport interface RuleSource {\n repo: string;\n path: string;\n line: number;\n ruleId?: string;\n}\n\nexport interface Mechanical {\n /** JavaScript regex source. Compiled with `flags` (default \"gu\"). */\n regex?: string;\n flags?: string;\n /** Case-insensitive whole-phrase list. Word-boundary checked. */\n phrases?: string[];\n /** Minimum matches before the rule fires (default 1). */\n minMatches?: number;\n /** The rule fires only when this regex matches nowhere in the unit. */\n absent?: string;\n}\n\nexport interface CriterionSide {\n what: string;\n examples: string[];\n}\n\nexport interface Question {\n instructions: string;\n criteria?: { true: CriterionSide; false: CriterionSide };\n /** Context keys to include in the state for this question. */\n context?: ContextKey[];\n}\n\nexport interface Thresholds {\n review: number;\n act: number;\n}\n\nexport interface Fix {\n hint: string;\n /** Named function in src/reduce/fixes.ts; present means `--fix` can apply it. */\n function?: string;\n}\n\nexport interface Preconditions {\n notInCode?: boolean;\n docType?: DocType[];\n role?: Role[];\n /** Skip Markdown units when the project curls quotes at build time. */\n smartQuotesAtBuild?: false;\n}\n\nexport interface Rule {\n id: string;\n title: string;\n categoryId: string;\n domain: Domain;\n source: RuleSource;\n /** Resolved: include derived from `unit` unless the rule names it. */\n scope: { include: string[]; exclude: string[] };\n unit: UnitKind[];\n /** Derived: mechanical only, question only, or both. */\n tier: Tier;\n mechanical?: Mechanical;\n question?: Question;\n thresholds: Thresholds;\n severity: Severity;\n fix: Fix;\n preconditions?: Preconditions;\n status: RuleStatus;\n handWritten: string[];\n /** Absolute path of the YAML file the rule was loaded from, or `code:<module>`. */\n file: string;\n /**\n * A code rule's check, in place of `mechanical`. Counts, compares and\n * measures; throws UnresolvedError to abstain. Data rules never set it.\n */\n check?: (unit: Unit) => MechanicalHit;\n}\n\nexport interface TuningEntry {\n act?: number;\n status?: RuleStatus;\n precisionLower?: number;\n n?: number;\n ts?: string;\n}\nexport type Tuning = Record<string, TuningEntry>;\n\nexport interface ResolvedTypography {\n fontSizePx?: number;\n lineHeight?: number;\n lineHeightPx?: number;\n letterSpacingEm?: number;\n fontWeight?: number;\n uppercase?: boolean;\n italic?: boolean;\n family?: \"mono\" | \"sans\" | \"serif\";\n colourClasses: string[];\n unresolved: string[];\n}\n\nexport interface NeighbourSummary {\n text: string;\n element?: string;\n typography?: ResolvedTypography;\n}\n\nexport interface WritingContext {\n facts?: string;\n profile?: string;\n instructions?: string;\n}\n\nexport interface UnitContext {\n section?: string;\n writingFacts?: string;\n writingProfile?: string;\n writingInstructions?: string;\n headingAbove?: string;\n docType: DocType;\n element?: string;\n attr?: string;\n component?: string;\n role: Role;\n /** The className has parts this extractor could not read statically. */\n dynamic?: boolean;\n /** The className is a template literal with `${...}` inside a class. */\n interpolated?: boolean;\n parseError?: string;\n mdxFallback?: boolean;\n}\n\nexport interface Unit {\n facts?: SourceFacts;\n /** Stable hash of file, kind and source offset. */\n id: string;\n kind: UnitKind;\n /** Normalised rendered text, whitespace collapsed. */\n text: string;\n /** Relative to the scanned root, forward slashes. */\n file: string;\n line: number;\n column: number;\n endLine: number;\n endColumn: number;\n sourceStart: number;\n sourceEnd: number;\n inCode: boolean;\n /** Ranges inside `text` that are code and must be skipped by regexes. */\n codeSpans: [number, number][];\n /**\n * Source ranges (UTF-16 offsets into the file) holding prose a\n * deterministic fix may rewrite: JSX text pieces, the inside of string\n * literals, Markdown text nodes. Never quotes, braces, inline code or\n * expressions. Absent means the unit cannot be fixed in place.\n */\n fixRanges?: [number, number][];\n context: UnitContext;\n typography?: ResolvedTypography;\n neighbours?: { prev?: NeighbourSummary; next?: NeighbourSummary };\n /** Class list for class-list and element units. */\n classes?: string[];\n}\n\nexport interface MechanicalHit {\n fired: boolean;\n evidence: string;\n /** Offset into `unit.text` of the first match; a source unit's finding line. */\n offset?: number;\n}\n\nexport interface Finding {\n ruleId: string;\n categoryId: string;\n domain: Domain;\n severity: Severity;\n band: Band;\n probability: number;\n tier: Tier;\n unitId: string;\n file: string;\n line: number;\n column: number;\n endLine: number;\n endColumn: number;\n message: string;\n evidence: string;\n fixHint: string;\n suppressed: boolean;\n also?: string[];\n}\n\nexport interface Unknown {\n ruleId: string;\n unitId: string;\n file: string;\n line: number;\n reason: string;\n}\n\nexport interface Scorecard {\n byCategory: Record<\n string,\n {\n domain: Domain;\n units: number;\n act: number;\n review: number;\n suppressed: number;\n unknown: number;\n }\n >;\n byDomain: Record<\n string,\n {\n units: number;\n act: number;\n review: number;\n suppressed: number;\n unknown: number;\n }\n >;\n byRule: Record<\n string,\n { act: number; review: number; silent: number; unknown: number }\n >;\n}\n\nexport interface Progress {\n phase: \"evaluating\" | \"complete\";\n completed: number;\n planned: number;\n cachedAnswers: number;\n failed: number;\n attempts: number;\n elapsedMs: number;\n}\n\nexport interface Usage {\n /** HTTP attempts when reported by the evaluator; absent for legacy evaluators. */\n attempts?: number;\n sharedAnswers?: number;\n requests: number;\n cached: number;\n inputTokens: number;\n costUsd: number;\n errors: number;\n}\n\nexport type RunStatus = \"complete\" | \"incomplete\" | \"dry-run\";\n\nexport interface RunSummary {\n act: number;\n review: number;\n unknown: number;\n failing: number;\n failOn: Severity;\n ruleFindings: number;\n}\n\nexport interface Coverage {\n byRule: Record<\n string,\n {\n eligible: number;\n skipped: number;\n negative: number;\n pending: number;\n unknown: number;\n answered: number;\n }\n >;\n byCategory: Record<string, { eligibleUnits: number; eligiblePairs: number }>;\n}\n\nexport interface ScanScope {\n files: number;\n units: number;\n byDocType: Record<string, number>;\n excluded: number;\n diagnostics: string[];\n}\n\nexport interface LintResult {\n summary?: RunSummary;\n ruleFindings?: Finding[];\n ruleScorecard?: Scorecard;\n coverage?: Coverage;\n scope?: ScanScope;\n reportPath?: string;\n rerun?: string;\n status: RunStatus;\n findings: Finding[];\n unknowns: Unknown[];\n scorecard: Scorecard;\n usage: Usage;\n units: number;\n rules: string[];\n estimated?: { requests: number; inputTokens: number; costUsd: number };\n exitCode: number;\n}\n\n// Jev wire format (POST /v1/systemone).\n\nexport type EntryValue =\n | string\n | number\n | boolean\n | null\n | EntryValue[]\n | { [key: string]: EntryValue };\n\nexport interface SystemOneNoul {\n type: \"noul\";\n instructions: EntryValue;\n criteria?: { true?: EntryValue; false?: EntryValue } | null;\n}\n\nexport interface SystemOneRequest {\n model: string;\n state: EntryValue;\n questions: Record<string, SystemOneNoul>;\n}\n\nexport interface SystemOneResponse {\n attempts?: number;\n model: string;\n answers: Record<string, { type?: string; noul?: number }>;\n usage: { input_tokens: number; output_tokens: number };\n}\n\nexport type Evaluate = (\n request: SystemOneRequest,\n onAttempt?: () => void\n) => Promise<SystemOneResponse>;\n\nexport interface RecorderHandle {\n append: (record: Record<string, unknown>) => Record<string, unknown>;\n summary: (obj: Record<string, unknown>) => Record<string, unknown>;\n file: string;\n}\n\nexport interface CorpusItem {\n id: string;\n kind: UnitKind;\n text: string;\n context?: Partial<UnitContext>;\n neighbours?: Unit[\"neighbours\"];\n classes?: string[];\n categoryId: string;\n labels: Record<string, boolean>;\n labelSource: \"manifest\" | \"manifest-weak\" | \"hand\" | \"sweep\" | \"ai\";\n labelModel?: string;\n labelPromptHash?: string;\n source: { repo: string; path: string; id?: string; option?: string };\n split: \"dev\" | \"holdout\";\n}\n\nexport interface ArchitecturePolicy {\n boundaries?: { from: string; disallow: string; reason: string }[];\n deprecatedImports?: Record<string, string>;\n generated?: string[];\n}\n\nexport interface Config {\n architecture?: ArchitecturePolicy;\n root: string;\n docTypes: { glob: string; type: DocType }[];\n components: { unwrap: string[]; skip: string[] };\n tailwind: { theme: Record<string, string> };\n smartQuotesAtBuild: boolean;\n exclude: string[];\n}\n","// Fail-closed corpus loader. One JSON object per line under data/corpus.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { makePRNG } from \"../lib/stats.js\";\nimport { CATEGORY_BY_ID } from \"../rules/taxonomy.js\";\nimport { DOC_TYPES, ROLES, UNIT_KINDS } from \"../types.js\";\nimport type { CorpusItem, Rule, Unit } from \"../types.js\";\n\nconst ID = /^[a-z0-9][a-z0-9-]*$/;\n\nexport const resolveCorpusDir = (explicit?: string): string => {\n if (explicit) {\n const abs = path.resolve(explicit);\n if (!fs.existsSync(abs)) {\n throw new Error(`Corpus directory not found: ${abs}`);\n }\n return abs;\n }\n let dir = import.meta.dirname;\n for (let i = 0; i < 5; i += 1) {\n const candidate = path.join(dir, \"data\", \"corpus\");\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n dir = path.dirname(dir);\n }\n throw new Error(\n \"Could not locate data/corpus. Reinstall taste-lint or pass --corpus.\"\n );\n};\n\n// Deterministic 80/20 split by id hash.\nexport const splitFor = (id: string): \"dev\" | \"holdout\" => {\n let h = 2_166_136_261;\n for (const ch of id) {\n h ^= ch.codePointAt(0) ?? 0;\n h = Math.imul(h, 16_777_619) >>> 0;\n }\n return makePRNG(h)() < 0.8 ? \"dev\" : \"holdout\";\n};\n\nexport interface LoadCorpusOptions {\n includeWeak?: boolean;\n /**\n * Every rule id the catalogue knows, drafts included. Labels are validated\n * against this set; `rules` says which of them are under evaluation, and\n * labels for the others are dropped rather than rejected, so `--only` and\n * `tune` can run over a corpus labelled for the whole catalogue.\n */\n knownRuleIds?: Set<string>;\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\nexport const loadCorpus = (\n corpusDir: string,\n rules: Rule[],\n options: LoadCorpusOptions = {}\n): CorpusItem[] => {\n const ruleIds = new Set(rules.map((r) => r.id));\n const known = options.knownRuleIds ?? ruleIds;\n const items: CorpusItem[] = [];\n const seen = new Set<string>();\n const files = fs\n .readdirSync(corpusDir)\n .filter((f) => f.endsWith(\".jsonl\"))\n .toSorted();\n for (const name of files) {\n const file = path.join(corpusDir, name);\n const lines = fs.readFileSync(file, \"utf-8\").split(\"\\n\");\n for (const [i, line] of lines.entries()) {\n if (line.trim() === \"\") {\n continue;\n }\n const where = `${file}:${i + 1}`;\n let raw: unknown;\n try {\n raw = JSON.parse(line);\n } catch {\n throw new Error(`Invalid corpus line ${where}: not JSON`);\n }\n if (typeof raw !== \"object\" || raw === null) {\n throw new Error(`Invalid corpus line ${where}: not an object`);\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.id !== \"string\" || !ID.test(r.id)) {\n throw new Error(`Invalid corpus line ${where}: id must be kebab-case`);\n }\n if (seen.has(r.id)) {\n throw new Error(`Duplicate corpus id ${r.id} at ${where}`);\n }\n seen.add(r.id);\n if (\n typeof r.kind !== \"string\" ||\n !UNIT_KINDS.includes(r.kind as (typeof UNIT_KINDS)[number])\n ) {\n throw new Error(`Invalid corpus line ${where}: unknown kind`);\n }\n if (typeof r.text !== \"string\") {\n throw new TypeError(\n `Invalid corpus line ${where}: text must be a string`\n );\n }\n if (\n typeof r.categoryId !== \"string\" ||\n !CATEGORY_BY_ID.has(r.categoryId)\n ) {\n throw new Error(`Invalid corpus line ${where}: unknown categoryId`);\n }\n if (!isRecord(r.labels) || Object.keys(r.labels).length === 0) {\n throw new Error(\n `Invalid corpus line ${where}: labels must map rule ids to booleans`\n );\n }\n const labels: Record<string, boolean> = {};\n for (const [ruleId, label] of Object.entries(r.labels)) {\n if (typeof label !== \"boolean\") {\n throw new TypeError(\n `Invalid corpus line ${where}: label for ${ruleId} must be boolean`\n );\n }\n if (!known.has(ruleId)) {\n throw new Error(\n `Invalid corpus line ${where}: unknown rule ${ruleId}`\n );\n }\n if (ruleIds.has(ruleId)) {\n labels[ruleId] = label;\n }\n }\n const labelSource = r.labelSource;\n if (\n ![\"manifest\", \"manifest-weak\", \"hand\", \"sweep\", \"ai\"].includes(\n labelSource as string\n )\n ) {\n throw new Error(`Invalid corpus line ${where}: labelSource`);\n }\n if (\n labelSource === \"ai\" &&\n (typeof r.labelModel !== \"string\" ||\n !r.labelModel.trim() ||\n typeof r.labelPromptHash !== \"string\" ||\n !/^[a-f0-9]{64}$/.test(r.labelPromptHash))\n ) {\n throw new Error(\n `Invalid corpus line ${where}: AI labels require model and prompt hash`\n );\n }\n if (\n !isRecord(r.source) ||\n typeof r.source.repo !== \"string\" ||\n typeof r.source.path !== \"string\"\n ) {\n throw new Error(\n `Invalid corpus line ${where}: source needs repo and path`\n );\n }\n if (r.split !== undefined && r.split !== \"dev\" && r.split !== \"holdout\") {\n throw new Error(\n `Invalid corpus line ${where}: split must be dev or holdout`\n );\n }\n if (\n r.classes !== undefined &&\n (!Array.isArray(r.classes) ||\n r.classes.some((c) => typeof c !== \"string\"))\n ) {\n throw new Error(\n `Invalid corpus line ${where}: classes must be strings`\n );\n }\n if (r.context !== undefined) {\n if (!isRecord(r.context)) {\n throw new Error(\n `Invalid corpus line ${where}: context must be an object`\n );\n }\n const { docType, role } = r.context;\n if (\n (docType !== undefined &&\n !DOC_TYPES.includes(docType as (typeof DOC_TYPES)[number])) ||\n (role !== undefined &&\n !ROLES.includes(role as (typeof ROLES)[number]))\n ) {\n throw new Error(\n `Invalid corpus line ${where}: unknown context docType or role`\n );\n }\n }\n if (r.neighbours !== undefined) {\n const n = r.neighbours;\n const ok =\n isRecord(n) &&\n ([\"prev\", \"next\"] as const).every(\n (k) =>\n n[k] === undefined ||\n (isRecord(n[k]) &&\n typeof (n[k] as Record<string, unknown>).text === \"string\")\n );\n if (!ok) {\n throw new Error(\n `Invalid corpus line ${where}: neighbours must carry text`\n );\n }\n }\n // Rows outside the evaluation are dropped only after they validated.\n if (labelSource === \"manifest-weak\" && !options.includeWeak) {\n continue;\n }\n if (Object.keys(labels).length === 0) {\n continue;\n }\n items.push({\n categoryId: r.categoryId,\n classes: r.classes as string[] | undefined,\n context: (r.context as CorpusItem[\"context\"]) ?? {},\n id: r.id,\n kind: r.kind as CorpusItem[\"kind\"],\n labelModel: r.labelModel as string | undefined,\n labelPromptHash: r.labelPromptHash as string | undefined,\n labelSource: labelSource as CorpusItem[\"labelSource\"],\n labels,\n neighbours: r.neighbours as CorpusItem[\"neighbours\"],\n source: r.source as CorpusItem[\"source\"],\n split: (r.split as CorpusItem[\"split\"] | undefined) ?? splitFor(r.id),\n text: r.text,\n });\n }\n }\n if (items.length === 0) {\n throw new Error(\n `Corpus under ${corpusDir} has no items labelled for the rules under evaluation`\n );\n }\n return items;\n};\n\n// Turn a corpus item into a Unit so the same plan and batch code runs.\nexport const unitFromItem = (item: CorpusItem): Unit => {\n const classes = item.classes;\n return {\n classes,\n codeSpans: [],\n column: 1,\n context: {\n docType: item.context?.docType ?? \"unknown\",\n role: item.context?.role ?? \"body\",\n ...item.context,\n },\n endColumn: 1,\n endLine: 1,\n file: `corpus/${item.id}${item.kind === \"class-list\" || item.kind === \"element\" ? \".tsx\" : item.kind === \"paragraph\" || item.kind === \"heading\" ? \".md\" : \".tsx\"}`,\n id: item.id,\n inCode: false,\n kind: item.kind,\n line: 1,\n neighbours: item.neighbours,\n sourceEnd: item.text.length,\n sourceStart: 0,\n text: item.text,\n typography: undefined,\n };\n};\n","import type { CorpusItem, Rule } from \"../types.js\";\n\nconst counts = (items: CorpusItem[], ruleId: string) => ({\n negative: items.filter((item) => item.labels[ruleId] === false).length,\n positive: items.filter((item) => item.labels[ruleId] === true).length,\n});\n\n// Describe reference evidence before scoring. Counts do not establish accuracy.\nexport const corpusCoverage = (items: CorpusItem[], rules: Rule[]) => {\n const sources = new Map<string, Set<string>>();\n const texts = new Map<string, Set<string>>();\n for (const item of items) {\n const key = JSON.stringify([item.source.repo, item.source.path]);\n const splits = sources.get(key) ?? new Set<string>();\n splits.add(item.split);\n sources.set(key, splits);\n for (const ruleId of Object.keys(item.labels)) {\n const identity = JSON.stringify([\n ruleId,\n item.text.trim().replaceAll(/\\s+/gu, \" \"),\n ]);\n const seen = texts.get(identity) ?? new Set<string>();\n seen.add(item.split);\n texts.set(identity, seen);\n }\n }\n return {\n items: items.length,\n labelSources: Object.fromEntries(\n [...new Set(items.map((item) => item.labelSource))].map((source) => [\n source,\n items.filter((item) => item.labelSource === source).length,\n ])\n ),\n overlappingSources: [...sources]\n .filter(([, splits]) => splits.size > 1)\n .map(([source]) => JSON.parse(source) as [string, string]),\n overlappingTexts: [...texts.values()].filter((splits) => splits.size > 1)\n .length,\n rules: rules.map((rule) => {\n const labeled = items.filter((item) => rule.id in item.labels);\n return {\n ...counts(labeled, rule.id),\n dev: counts(\n labeled.filter((item) => item.split === \"dev\"),\n rule.id\n ),\n documentTypes: [\n ...new Set(labeled.map((item) => item.context?.docType ?? \"unknown\")),\n ].toSorted(),\n holdout: counts(\n labeled.filter((item) => item.split === \"holdout\"),\n rule.id\n ),\n repositories: [\n ...new Set(labeled.map((item) => item.source.repo)),\n ].toSorted(),\n ruleId: rule.id,\n };\n }),\n };\n};\n\nexport const renderCoverage = (\n coverage: ReturnType<typeof corpusCoverage>\n): string =>\n [\n `Reference coverage: ${coverage.items} items; ${coverage.rules.filter((rule) => rule.positive > 0 && rule.negative > 0).length}/${coverage.rules.length} rules have both positive and negative labels.`,\n `Split overlap: ${coverage.overlappingSources.length} source files; ${coverage.overlappingTexts} rule/text pairs. Overlap weakens held-out evidence.`,\n ...coverage.rules\n .filter((rule) => rule.positive + rule.negative > 0)\n .map(\n (rule) =>\n `${rule.ruleId}: ${rule.positive} positive, ${rule.negative} negative; holdout ${rule.holdout.positive} positive, ${rule.holdout.negative} negative; ${rule.documentTypes.length} document types; ${rule.repositories.length} repositories`\n ),\n \"Coverage counts are diagnostic, not a promotion verdict.\",\n \"\",\n ].join(\"\\n\");\n","// Resolve Tailwind v4 utility classes to typography values. Only the static\n// default scale and arbitrary values are resolved. Anything else is listed as\n// unresolved so a rule that needs the value can abstain instead of guessing.\n\nimport type { Config, ResolvedTypography } from \"../types.js\";\n\nconst ROOT_PX = 16;\n\nconst FONT_SIZES: Record<string, [number, number]> = {\n \"2xl\": [24, 32],\n \"3xl\": [30, 36],\n \"4xl\": [36, 40],\n \"5xl\": [48, 48],\n \"6xl\": [60, 60],\n \"7xl\": [72, 72],\n \"8xl\": [96, 96],\n \"9xl\": [128, 128],\n base: [16, 24],\n lg: [18, 28],\n sm: [14, 20],\n xl: [20, 28],\n xs: [12, 16],\n};\n\nconst LEADING: Record<string, number> = {\n loose: 2,\n none: 1,\n normal: 1.5,\n relaxed: 1.625,\n snug: 1.375,\n tight: 1.25,\n};\n\nconst TRACKING: Record<string, number> = {\n normal: 0,\n tight: -0.025,\n tighter: -0.05,\n wide: 0.025,\n wider: 0.05,\n widest: 0.1,\n};\n\nconst WEIGHTS: Record<string, number> = {\n black: 900,\n bold: 700,\n extrabold: 800,\n extralight: 200,\n light: 300,\n medium: 500,\n normal: 400,\n semibold: 600,\n thin: 100,\n};\n\nconst COLOUR_NAMES = new Set([\n \"inherit\",\n \"current\",\n \"transparent\",\n \"black\",\n \"white\",\n \"slate\",\n \"gray\",\n \"zinc\",\n \"neutral\",\n \"stone\",\n \"red\",\n \"orange\",\n \"amber\",\n \"yellow\",\n \"lime\",\n \"green\",\n \"emerald\",\n \"teal\",\n \"cyan\",\n \"sky\",\n \"blue\",\n \"indigo\",\n \"violet\",\n \"purple\",\n \"fuchsia\",\n \"pink\",\n \"rose\",\n \"foreground\",\n \"background\",\n \"muted\",\n \"muted-foreground\",\n \"primary\",\n \"primary-foreground\",\n \"secondary\",\n \"secondary-foreground\",\n \"accent\",\n \"accent-foreground\",\n \"destructive\",\n \"card-foreground\",\n \"popover-foreground\",\n]);\n\nconst parseLength = (raw: string): number | null => {\n const m = raw.match(/^(-?\\d*\\.?\\d+)(px|rem|em)?$/);\n if (!m) {\n return null;\n }\n const value = Number(m[1]);\n if (m[2] === \"rem\" || m[2] === \"em\") {\n return value * ROOT_PX;\n }\n return value;\n};\n\nconst parseEm = (raw: string): number | null => {\n const m = raw.match(/^(-?\\d*\\.?\\d+)(em|px)?$/);\n if (!m) {\n return null;\n }\n const value = Number(m[1]);\n return m[2] === \"px\" ? value / ROOT_PX : value;\n};\n\nconst stripVariants = (cls: string): { base: string; variants: string[] } => {\n // Variants are colon-separated prefixes; arbitrary values may contain colons\n // inside brackets, so split only outside brackets.\n const parts: string[] = [];\n let depth = 0;\n let current = \"\";\n for (const ch of cls) {\n if (ch === \"[\") {\n depth += 1;\n } else if (ch === \"]\") {\n depth -= 1;\n }\n if (ch === \":\" && depth === 0) {\n parts.push(current);\n current = \"\";\n } else {\n current += ch;\n }\n }\n parts.push(current);\n const base = parts.pop() ?? \"\";\n return { base, variants: parts };\n};\n\nconst isColour = (token: string): boolean => {\n if (\n token.startsWith(\"[#\") ||\n token.startsWith(\"[rgb\") ||\n token.startsWith(\"[hsl\") ||\n token.startsWith(\"[oklch\") ||\n token.startsWith(\"[var(\")\n ) {\n return true;\n }\n return COLOUR_NAMES.has(token.replace(/-\\d{2,3}$/, \"\"));\n};\n\nexport const resolveTypography = (\n classes: string[],\n config?: Config\n): ResolvedTypography => {\n const out: ResolvedTypography = { colourClasses: [], unresolved: [] };\n const theme = config?.tailwind.theme ?? {};\n // A size class brings a default line height; an explicit leading wins, and a\n // later size class replaces an earlier size's default (cn(\"text-sm\", \"text-lg\")).\n let lineHeightFromSize = false;\n const applyLeading = (token: string, cls: string): void => {\n lineHeightFromSize = false;\n resolveLeading(out, token, cls);\n };\n for (const cls of classes) {\n const { base, variants } = stripVariants(cls);\n // Responsive and state variants are recorded but not judged in v1.\n if (variants.some((v) => ![\"dark\"].includes(v))) {\n continue;\n }\n if (base.startsWith(\"text-\")) {\n const token = base.slice(\"text-\".length);\n const [sizeToken, leadingToken] = token.split(\"/\");\n if (isColour(sizeToken)) {\n out.colourClasses.push(cls);\n continue;\n }\n if (\n [\n \"left\",\n \"center\",\n \"right\",\n \"justify\",\n \"start\",\n \"end\",\n \"wrap\",\n \"nowrap\",\n \"balance\",\n \"pretty\",\n \"ellipsis\",\n \"clip\",\n ].includes(sizeToken)\n ) {\n continue;\n }\n const known = FONT_SIZES[sizeToken];\n if (known) {\n out.fontSizePx = known[0];\n if (\n !leadingToken &&\n (lineHeightFromSize ||\n (out.lineHeightPx === undefined && out.lineHeight === undefined))\n ) {\n out.lineHeightPx = known[1];\n out.lineHeight = undefined;\n lineHeightFromSize = true;\n }\n } else if (sizeToken.startsWith(\"[\") && sizeToken.endsWith(\"]\")) {\n const px = parseLength(sizeToken.slice(1, -1));\n if (px === null) {\n out.unresolved.push(cls);\n } else {\n out.fontSizePx = px;\n }\n } else if (theme[sizeToken]) {\n const px = parseLength(theme[sizeToken]);\n if (px === null) {\n out.unresolved.push(cls);\n } else {\n out.fontSizePx = px;\n }\n } else {\n out.unresolved.push(cls);\n }\n if (leadingToken) {\n applyLeading(leadingToken, cls);\n }\n continue;\n }\n if (base.startsWith(\"leading-\")) {\n applyLeading(base.slice(\"leading-\".length), cls);\n continue;\n }\n if (base.startsWith(\"tracking-\")) {\n const token = base.slice(\"tracking-\".length);\n if (TRACKING[token] !== undefined) {\n out.letterSpacingEm = TRACKING[token];\n } else if (token.startsWith(\"[\") && token.endsWith(\"]\")) {\n const em = parseEm(token.slice(1, -1));\n if (em === null) {\n out.unresolved.push(cls);\n } else {\n out.letterSpacingEm = em;\n }\n } else {\n out.unresolved.push(cls);\n }\n continue;\n }\n if (base.startsWith(\"font-\")) {\n const token = base.slice(\"font-\".length);\n if (WEIGHTS[token] !== undefined) {\n out.fontWeight = WEIGHTS[token];\n } else if (token === \"mono\" || token === \"sans\" || token === \"serif\") {\n out.family = token;\n } else if (token.startsWith(\"[\") && token.endsWith(\"]\")) {\n const n = Number(token.slice(1, -1));\n if (Number.isFinite(n) && n >= 100 && n <= 900) {\n out.fontWeight = n;\n } else {\n out.unresolved.push(cls);\n }\n } else {\n out.unresolved.push(cls);\n }\n continue;\n }\n if (base === \"uppercase\") {\n out.uppercase = true;\n continue;\n }\n if (\n base === \"normal-case\" ||\n base === \"lowercase\" ||\n base === \"capitalize\"\n ) {\n out.uppercase = false;\n continue;\n }\n if (base === \"italic\") {\n out.italic = true;\n }\n }\n if (\n out.fontSizePx !== undefined &&\n out.lineHeightPx !== undefined &&\n out.lineHeight === undefined\n ) {\n out.lineHeight =\n Math.round((out.lineHeightPx / out.fontSizePx) * 1000) / 1000;\n }\n return out;\n};\n\nconst resolveLeading = (\n out: ResolvedTypography,\n token: string,\n cls: string\n): void => {\n if (LEADING[token] !== undefined) {\n out.lineHeight = LEADING[token];\n out.lineHeightPx = undefined;\n return;\n }\n if (/^\\d+$/.test(token)) {\n out.lineHeightPx = Number(token) * 4;\n out.lineHeight = undefined;\n return;\n }\n if (token.startsWith(\"[\") && token.endsWith(\"]\")) {\n const inner = token.slice(1, -1);\n if (/^\\d*\\.?\\d+$/.test(inner)) {\n out.lineHeight = Number(inner);\n out.lineHeightPx = undefined;\n return;\n }\n const px = parseLength(inner);\n if (px !== null) {\n out.lineHeightPx = px;\n out.lineHeight = undefined;\n return;\n }\n }\n out.unresolved.push(cls);\n};\n\n// Split a className string into classes.\nexport const splitClasses = (value: string): string[] =>\n value.split(/\\s+/u).filter(Boolean);\n","// Expected input failures carry stable codes; provider bodies never enter them.\nexport class InputError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n public readonly details: Record<string, unknown> = {}\n ) {\n super(message);\n this.name = \"InputError\";\n }\n}\n","import { spawnSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { InputError } from \"./errors.js\";\n\nconst DEFAULT_EXCLUDE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.next/**\",\n \"**/.git/**\",\n \"**/results/**\",\n \"**/coverage/**\",\n];\n\n// Convert a glob to a RegExp over a forward-slash relative path.\nconst globToRegExp = (glob: string): RegExp => {\n let out = \"^\";\n for (let i = 0; i < glob.length; i += 1) {\n const ch = glob[i];\n if (ch === \"*\") {\n if (glob[i + 1] === \"*\") {\n // `**/` matches zero or more directories; `**` alone matches anything.\n if (glob[i + 2] === \"/\") {\n out += \"(?:.*/)?\";\n i += 2;\n } else {\n out += \".*\";\n i += 1;\n }\n } else {\n out += \"[^/]*\";\n }\n } else if (ch === \"?\") {\n out += \"[^/]\";\n } else if (ch === \"{\") {\n const close = glob.indexOf(\"}\", i);\n if (close === -1) {\n out += \"\\\\{\";\n } else {\n const alts = glob\n .slice(i + 1, close)\n .split(\",\")\n .map((a) =>\n a\n .replaceAll(/[.+^$()|[\\]\\\\]/g, \"\\\\$&\")\n .replaceAll(\"*\", \"[^/]*\")\n .replaceAll(\"?\", \"[^/]\")\n );\n out += `(?:${alts.join(\"|\")})`;\n i = close;\n }\n } else if (/[.+^$()|[\\]\\\\]/.test(ch)) {\n out += `\\\\${ch}`;\n } else {\n out += ch;\n }\n }\n return new RegExp(`${out}$`);\n};\n\nexport const matchesAny = (relative: string, globs: string[]): boolean =>\n globs.some((g) => globToRegExp(g).test(relative));\n\nexport const toPosix = (p: string): string => p.split(path.sep).join(\"/\");\n\n// Walk `targets` (files or directories) under `root` and return relative\n// forward-slash paths matching `include` and not `exclude`.\nexport const collectFiles = (\n root: string,\n targets: string[],\n include: string[],\n exclude: string[] = [],\n diagnostics?: { excluded: number; messages: string[] }\n): string[] => {\n const excludes = [...DEFAULT_EXCLUDE, ...exclude];\n const ignoredResult = spawnSync(\n \"git\",\n [\n \"ls-files\",\n \"--others\",\n \"--ignored\",\n \"--exclude-standard\",\n \"--directory\",\n \"-z\",\n \"--\",\n \".\",\n ],\n { cwd: root, encoding: \"utf-8\", maxBuffer: 16 * 1024 * 1024 }\n );\n // Non-Git directories still support the explicit exclusion policy.\n const ignored = new Set(\n ignoredResult.status === 0 ? ignoredResult.stdout.split(\"\\0\") : []\n );\n const isIgnored = (relative: string): boolean => {\n if (ignored.has(relative)) {\n return true;\n }\n for (\n let directory = relative;\n directory !== \".\";\n directory = path.posix.dirname(directory)\n ) {\n if (ignored.has(`${directory}/`)) {\n return true;\n }\n }\n return false;\n };\n const out = new Set<string>();\n const visited = new Set<string>();\n const visit = (abs: string, explicit = false): void => {\n const rel = toPosix(path.relative(root, abs));\n // Exclude before stat: ignored build trees may contain dangling symlinks.\n if (\n rel &&\n (isIgnored(rel) ||\n matchesAny(rel, excludes) ||\n matchesAny(`${rel}/`, excludes))\n ) {\n if (diagnostics) {\n diagnostics.excluded += 1;\n }\n return;\n }\n let stat: fs.Stats;\n try {\n stat = fs.statSync(abs);\n } catch (error) {\n const code =\n (error as NodeJS.ErrnoException).code === \"ENOENT\"\n ? \"TARGET_NOT_FOUND\"\n : \"TARGET_UNREADABLE\";\n throw new InputError(\n code,\n `Cannot read target ${abs}. Check that it exists and is readable.`,\n { path: abs }\n );\n }\n if (stat.isDirectory()) {\n const real = fs.realpathSync(abs);\n if (visited.has(real)) {\n return;\n }\n visited.add(real);\n let entries: string[];\n try {\n entries = fs.readdirSync(abs);\n } catch {\n throw new InputError(\n \"TARGET_UNREADABLE\",\n `Cannot read directory ${abs}.`,\n { path: abs }\n );\n }\n for (const entry of entries) {\n visit(path.join(abs, entry));\n }\n visited.delete(real);\n return;\n }\n if (matchesAny(rel, include)) {\n out.add(rel);\n } else if (explicit) {\n throw new InputError(\n \"UNSUPPORTED_TARGET\",\n `Unsupported target ${abs}. Use Markdown, MDX, TSX, JSX, CSS or SCSS.`,\n { path: abs }\n );\n }\n };\n for (const target of targets) {\n visit(path.resolve(root, target), true);\n }\n return [...out].toSorted();\n};\n","// Project configuration: taste-lint.config.json at the scan root plus\n// auto-detection of facts that change how rules apply.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { DOC_TYPES } from \"../types.js\";\nimport type { ArchitecturePolicy, Config, DocType } from \"../types.js\";\nimport { InputError } from \"./errors.js\";\nimport { matchesAny, toPosix } from \"./glob.js\";\n\nconst DEFAULT_UNWRAP = [\n \"Callout\",\n \"Depth\",\n \"Exercise\",\n \"ExerciseHint\",\n \"ExerciseSolution\",\n \"Slide\",\n \"Note\",\n \"Tip\",\n \"Warning\",\n \"Aside\",\n \"Kbd\",\n \"Term\",\n];\nconst DEFAULT_SKIP = [\n \"CodeBlock\",\n \"CodeFigure\",\n \"ExerciseRun\",\n \"JudgementExercise\",\n \"LocateExercise\",\n \"RankExercise\",\n \"RepairExercise\",\n];\n\nconst DEFAULT_DOC_TYPES: { glob: string; type: DocType }[] = [\n { glob: \"**/README.md\", type: \"readme\" },\n { glob: \"**/SKILL.md\", type: \"skill\" },\n { glob: \"**/docs/plans/**/*.md\", type: \"plan\" },\n { glob: \"**/AGENTS.md\", type: \"agent-instructions\" },\n { glob: \"**/CLAUDE.md\", type: \"agent-instructions\" },\n { glob: \"**/skills/**/*.md\", type: \"agent-instructions\" },\n { glob: \"**/.claude/**/*.md\", type: \"agent-instructions\" },\n { glob: \"**/content/**/*.mdx\", type: \"lesson\" },\n { glob: \"**/docs/**/*.md\", type: \"explanation\" },\n // Marketing paths before the catch-all so app/(marketing)/page.tsx is not `ui`.\n { glob: \"**/(marketing)/**\", type: \"marketing\" },\n { glob: \"**/landing/**\", type: \"marketing\" },\n { glob: \"**/*.{tsx,jsx}\", type: \"ui\" },\n];\n\nconst CONFIG_FILES = [\"taste-lint.config.json\"];\nconst SMARTYPANTS_FILES = [\n \"next.config.ts\",\n \"next.config.mjs\",\n \"next.config.js\",\n \"apps/web/next.config.ts\",\n \"apps/web/next.config.mjs\",\n \"apps/web/next.config.js\",\n \"mdx.config.ts\",\n \"mdx.config.mjs\",\n \"contentlayer.config.ts\",\n \"astro.config.mjs\",\n \"astro.config.ts\",\n];\n\nconst detectSmartQuotesAtBuild = (root: string): boolean =>\n SMARTYPANTS_FILES.some((file) => {\n const abs = path.join(root, file);\n try {\n return fs.readFileSync(abs, \"utf-8\").includes(\"smartypants\");\n } catch {\n return false;\n }\n });\n\nexport interface UserConfig {\n architecture?: ArchitecturePolicy;\n $schema?: string;\n exclude?: string[];\n smartQuotesAtBuild?: boolean;\n docTypes?: { glob: string; type: DocType }[];\n components?: { skip?: string[]; unwrap?: string[] };\n tailwind?: { theme?: Record<string, string> };\n}\n\nconst invalid = (key: string, expected: string): never => {\n throw new InputError(\n \"INVALID_CONFIG\",\n `taste-lint.config.json: ${key} must be ${expected}.`,\n { expected, field: key }\n );\n};\n\nexport function validateConfig(raw: unknown): asserts raw is UserConfig {\n const object = (value: unknown, key: string): Record<string, unknown> => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return invalid(key, \"an object\");\n }\n return value as Record<string, unknown>;\n };\n const keys = (\n value: Record<string, unknown>,\n allowed: string[],\n prefix: string\n ) => {\n for (const key of Object.keys(value)) {\n if (!allowed.includes(key)) {\n invalid(`${prefix}${key}`, `one of ${allowed.join(\", \")}`);\n }\n }\n };\n const strings = (value: unknown, key: string) => {\n if (!Array.isArray(value) || value.some((v) => typeof v !== \"string\")) {\n invalid(key, \"an array of strings\");\n }\n };\n const value = object(raw, \"config\");\n keys(\n value,\n [\n \"$schema\",\n \"exclude\",\n \"smartQuotesAtBuild\",\n \"docTypes\",\n \"components\",\n \"tailwind\",\n \"architecture\",\n ],\n \"\"\n );\n if (value.architecture !== undefined) {\n const policy = object(value.architecture, \"architecture\");\n keys(\n policy,\n [\"boundaries\", \"deprecatedImports\", \"generated\"],\n \"architecture.\"\n );\n if (policy.generated !== undefined) {\n strings(policy.generated, \"architecture.generated\");\n }\n if (policy.deprecatedImports !== undefined) {\n const deprecated = object(\n policy.deprecatedImports,\n \"architecture.deprecatedImports\"\n );\n for (const [key, replacement] of Object.entries(deprecated)) {\n if (typeof replacement !== \"string\" || !replacement.trim()) {\n invalid(\n `architecture.deprecatedImports.${key}`,\n \"a nonempty replacement\"\n );\n }\n }\n }\n if (policy.boundaries !== undefined) {\n if (!Array.isArray(policy.boundaries)) {\n invalid(\"architecture.boundaries\", \"an array\");\n }\n for (const [i, rawBoundary] of (\n policy.boundaries as unknown[]\n ).entries()) {\n const boundary = object(rawBoundary, `architecture.boundaries[${i}]`);\n keys(\n boundary,\n [\"from\", \"disallow\", \"reason\"],\n `architecture.boundaries[${i}].`\n );\n for (const key of [\"from\", \"disallow\", \"reason\"]) {\n if (\n typeof boundary[key] !== \"string\" ||\n !(boundary[key] as string).trim()\n ) {\n invalid(\n `architecture.boundaries[${i}].${key}`,\n \"a nonempty string\"\n );\n }\n }\n }\n }\n }\n if (value.$schema !== undefined && typeof value.$schema !== \"string\") {\n invalid(\"$schema\", \"a string\");\n }\n if (value.exclude !== undefined) {\n strings(value.exclude, \"exclude\");\n }\n if (\n value.smartQuotesAtBuild !== undefined &&\n typeof value.smartQuotesAtBuild !== \"boolean\"\n ) {\n invalid(\"smartQuotesAtBuild\", \"a boolean\");\n }\n if (value.docTypes !== undefined) {\n if (!Array.isArray(value.docTypes)) {\n invalid(\"docTypes\", \"an array\");\n }\n for (const [i, entry] of (value.docTypes as unknown[]).entries()) {\n const row = object(entry, `docTypes[${i}]`);\n keys(row, [\"glob\", \"type\"], `docTypes[${i}].`);\n if (typeof row.glob !== \"string\") {\n invalid(`docTypes[${i}].glob`, \"a string\");\n }\n if (!DOC_TYPES.includes(row.type as DocType)) {\n invalid(`docTypes[${i}].type`, DOC_TYPES.join(\", \"));\n }\n }\n }\n if (value.components !== undefined) {\n const c = object(value.components, \"components\");\n keys(c, [\"skip\", \"unwrap\"], \"components.\");\n for (const key of [\"skip\", \"unwrap\"]) {\n if (c[key] !== undefined) {\n strings(c[key], `components.${key}`);\n }\n }\n }\n if (value.tailwind !== undefined) {\n const t = object(value.tailwind, \"tailwind\");\n keys(t, [\"theme\"], \"tailwind.\");\n if (t.theme !== undefined) {\n const theme = object(t.theme, \"tailwind.theme\");\n for (const [key, val] of Object.entries(theme)) {\n if (typeof val !== \"string\") {\n invalid(`tailwind.theme.${key}`, \"a string\");\n }\n }\n }\n }\n}\n\nexport const loadConfig = (\n root: string,\n defaults: Config[\"docTypes\"] = []\n): Config => {\n const absRoot = path.resolve(root);\n try {\n if (!fs.statSync(absRoot).isDirectory()) {\n throw new Error(\"not a directory\");\n }\n } catch {\n throw new InputError(\n \"INVALID_ROOT\",\n `Scan root ${absRoot} must be an existing readable directory.`,\n { path: absRoot }\n );\n }\n let user: UserConfig = {};\n for (const name of CONFIG_FILES) {\n const file = path.join(absRoot, name);\n if (fs.existsSync(file)) {\n let raw: unknown;\n try {\n raw = JSON.parse(fs.readFileSync(file, \"utf-8\"));\n } catch {\n throw new InputError(\n \"INVALID_CONFIG\",\n `Cannot parse ${file}: expected JSON.`,\n { path: file }\n );\n }\n validateConfig(raw);\n user = raw;\n break;\n }\n }\n return {\n architecture: user.architecture,\n components: {\n skip: [...DEFAULT_SKIP, ...(user.components?.skip ?? [])],\n unwrap: [...DEFAULT_UNWRAP, ...(user.components?.unwrap ?? [])],\n },\n docTypes: [...(user.docTypes ?? []), ...defaults, ...DEFAULT_DOC_TYPES],\n exclude: user.exclude ?? [],\n root: absRoot,\n smartQuotesAtBuild:\n typeof user.smartQuotesAtBuild === \"boolean\"\n ? user.smartQuotesAtBuild\n : detectSmartQuotesAtBuild(absRoot),\n tailwind: { theme: user.tailwind?.theme ?? {} },\n };\n};\n\n// Results, logs and the answer cache live under the current working directory.\nexport const defaultResultsDir = (): string =>\n path.join(process.cwd(), \"results\");\n\nexport const docTypeFor = (config: Config, relativeFile: string): DocType => {\n const rel = toPosix(relativeFile);\n for (const { glob, type } of config.docTypes) {\n if (matchesAny(rel, [glob])) {\n return type;\n }\n }\n return \"unknown\";\n};\n","// JSONL result recorder. Writes results/<layer>-<ISO8601>.jsonl, one JSON\n// object per line, plus a final {kind:'summary'} line. Every record carries\n// ts, eval=layer, git_sha, and whatever the caller adds.\n\nimport { execFileSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { RecorderHandle } from \"../types.js\";\n\nconst gitSha = (repoDir?: string): string => {\n try {\n return execFileSync(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: repoDir,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n } catch {\n return \"unknown\";\n }\n};\n\nconst isoStamp = (): string =>\n // Filesystem-safe ISO 8601: replace ':' so the filename is portable.\n new Date().toISOString().replaceAll(\":\", \"-\");\n\nexport const makeRecorder = (\n layer: string,\n options: { resultsDir?: string; skillsDir?: string } = {}\n): RecorderHandle => {\n // Results live under the current working directory (the scanned repo or taste-lint).\n const resultsDir = options.resultsDir ?? path.join(process.cwd(), \"results\");\n fs.mkdirSync(resultsDir, { recursive: true });\n const file = path.join(resultsDir, `${layer}-${isoStamp()}.jsonl`);\n // Stamp SHA from skills repo if provided.\n const sha = gitSha(options.skillsDir);\n\n const writeLine = (obj: Record<string, unknown>): void => {\n fs.appendFileSync(file, `${JSON.stringify(obj)}\\n`);\n };\n\n const append = (record: Record<string, unknown>): Record<string, unknown> => {\n const line: Record<string, unknown> = {\n eval: layer,\n git_sha: sha,\n ts: new Date().toISOString(),\n ...record,\n };\n writeLine(line);\n return line;\n };\n\n const summary = (obj: Record<string, unknown>): Record<string, unknown> => {\n const line: Record<string, unknown> = {\n eval: layer,\n git_sha: sha,\n kind: \"summary\",\n ts: new Date().toISOString(),\n ...obj,\n };\n writeLine(line);\n return line;\n };\n\n return { append, file, summary };\n};\n","// Per (question, state) answer cache under results/cache. Changing one rule's\n// wording invalidates only that rule's entries.\n\nimport { createHash, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { SystemOneNoul } from \"../types.js\";\n\nexport interface CacheEntry {\n noul: number;\n model: string;\n ts: string;\n}\n\nexport const cacheKey = (\n question: SystemOneNoul,\n state: string,\n model: string\n): string =>\n createHash(\"sha256\")\n .update(JSON.stringify(question))\n .update(\"\\n\")\n .update(model)\n .update(\"\\n\")\n .update(state)\n .digest(\"hex\");\n\nexport class AnswerCache {\n constructor(\n private readonly dir: string,\n private readonly enabled = true\n ) {}\n\n private file(key: string): string {\n return path.join(this.dir, key.slice(0, 2), `${key}.json`);\n }\n\n get(key: string): CacheEntry | null {\n if (!this.enabled) {\n return null;\n }\n try {\n const raw = JSON.parse(\n fs.readFileSync(this.file(key), \"utf-8\")\n ) as CacheEntry;\n // A hand-edited or corrupt entry must not reach the bands.\n if (\n typeof raw.noul !== \"number\" ||\n !Number.isFinite(raw.noul) ||\n raw.noul < 0 ||\n raw.noul > 1\n ) {\n return null;\n }\n return raw;\n } catch {\n return null;\n }\n }\n\n set(key: string, entry: CacheEntry): void {\n const file = this.file(key);\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const temporary = `${file}.${randomUUID()}.tmp`;\n try {\n fs.writeFileSync(temporary, JSON.stringify(entry));\n fs.renameSync(temporary, file);\n } finally {\n fs.rmSync(temporary, { force: true });\n }\n }\n}\n","// Fetch client for Jev. Two transports speak the same request: TypeSafe's own\n// POST /v1/systemone, and Vercel AI Gateway's evaluation route (the wire\n// call the AI SDK's experimental_evaluate makes; it is an SDK contract, not a\n// documented API, so it is pinned here in one place). Responses are validated\n// fail-closed and never logged; errors surface as a short category plus HTTP\n// status.\n\nimport type {\n Evaluate,\n SystemOneRequest,\n SystemOneResponse,\n} from \"../types.js\";\n\nexport type Transport = \"typesafe\" | \"gateway\";\nexport const DEFAULT_BASE_URL = \"https://api.typesafe.ai\";\nexport const GATEWAY_BASE_URL = \"https://ai-gateway.vercel.sh/v4/ai\";\nexport const DEFAULT_MODEL = \"jev-latest\";\n/** The gateway's id for Jev; a `--model` with a slash in it is passed through. */\nexport const GATEWAY_MODEL = \"typesafe-ai/jev\";\nexport const KEY_HINT =\n \"Set AI_GATEWAY_API_KEY to your Vercel AI Gateway key, then rerun. Create a key at https://vercel.com/docs/ai-gateway/authentication-and-byok/api-keys. Use --mechanical-only for lint/scan without a key.\";\nconst MAX_RETRY_AFTER_MS = 30_000;\n\nexport class ProviderError extends Error {\n constructor(\n public readonly category:\n | \"provider_error\"\n | \"invalid_response\"\n | \"timeout\"\n | \"auth\",\n public readonly status?: number\n ) {\n super(\n category === \"auth\"\n ? `The provider rejected the API key (HTTP ${status ?? 401}). Check AI_GATEWAY_API_KEY (or TYPESAFE_API_KEY when using the direct transport).`\n : `Jev request failed: ${category}${status ? ` (HTTP ${status})` : \"\"}`\n );\n this.name = \"ProviderError\";\n }\n}\n\nexport const validateResponse = (\n raw: unknown,\n request: SystemOneRequest\n): SystemOneResponse => {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ProviderError(\"invalid_response\");\n }\n const r = raw as Record<string, unknown>;\n if (typeof r.answers !== \"object\" || r.answers === null) {\n throw new ProviderError(\"invalid_response\");\n }\n const answers = r.answers as Record<string, unknown>;\n const out: SystemOneResponse[\"answers\"] = {};\n for (const id of Object.keys(request.questions)) {\n const a = answers[id];\n if (typeof a !== \"object\" || a === null) {\n throw new ProviderError(\"invalid_response\");\n }\n // TypeSafe answers `noul`; the gateway answers `probability`.\n const answer = a as Record<string, unknown>;\n if (\n answer.type !== undefined &&\n answer.type !== \"noul\" &&\n answer.type !== \"boolean\"\n ) {\n throw new ProviderError(\"invalid_response\");\n }\n const noul = answer.noul ?? answer.probability;\n if (\n typeof noul !== \"number\" ||\n !Number.isFinite(noul) ||\n noul < 0 ||\n noul > 1\n ) {\n throw new ProviderError(\"invalid_response\");\n }\n out[id] = { noul, type: \"noul\" };\n }\n const usage = (r.usage as Record<string, unknown> | undefined) ?? {};\n const count = (snake: string, camel: string): number => {\n const v = usage[snake] ?? usage[camel];\n if (v === undefined) {\n return 0;\n }\n if (typeof v !== \"number\" || !Number.isSafeInteger(v) || v < 0) {\n throw new ProviderError(\"invalid_response\");\n }\n return v;\n };\n const inputTokens = count(\"input_tokens\", \"inputTokens\");\n const outputTokens = count(\"output_tokens\", \"outputTokens\");\n return {\n answers: out,\n model: typeof r.model === \"string\" ? r.model : request.model,\n usage: { input_tokens: inputTokens, output_tokens: outputTokens },\n };\n};\n\nexport interface FetchEvaluateOptions {\n apiKey: string;\n transport?: Transport;\n baseUrl?: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n retries?: number;\n /** Sleep hook so tests can run without waiting. */\n sleep?: (ms: number) => Promise<void>;\n}\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n\n// An explicit API option retains its direct-TypeSafe contract. Otherwise prefer\n// the user's Gateway key; the legacy TypeSafe environment key remains a fallback.\nexport const evaluateFromEnv = (\n apiKey?: string,\n env: NodeJS.ProcessEnv = process.env\n): Evaluate | undefined => {\n if (apiKey) {\n return makeFetchEvaluate({ apiKey });\n }\n if (env.AI_GATEWAY_API_KEY) {\n return makeFetchEvaluate({\n apiKey: env.AI_GATEWAY_API_KEY,\n transport: \"gateway\",\n });\n }\n return env.TYPESAFE_API_KEY\n ? makeFetchEvaluate({ apiKey: env.TYPESAFE_API_KEY })\n : undefined;\n};\n\n// The gateway takes the model in a header and calls the noul primitive\n// `boolean`; everything else in the request is the same.\nconst gatewayCall = (\n request: SystemOneRequest\n): { body: string; headers: Record<string, string> } => ({\n body: JSON.stringify({\n questions: Object.fromEntries(\n Object.entries(request.questions).map(([id, q]) => [\n id,\n { ...q, type: \"boolean\" },\n ])\n ),\n state: request.state,\n }),\n headers: {\n \"ai-evaluation-model-specification-version\": \"4\",\n \"ai-gateway-protocol-version\": \"0.0.1\",\n \"ai-model-id\": request.model.includes(\"/\") ? request.model : GATEWAY_MODEL,\n },\n});\n\nexport const makeFetchEvaluate = (options: FetchEvaluateOptions): Evaluate => {\n const {\n apiKey,\n transport = \"typesafe\",\n baseUrl = transport === \"gateway\" ? GATEWAY_BASE_URL : DEFAULT_BASE_URL,\n fetch: doFetch = globalThis.fetch,\n timeoutMs = 10_000,\n retries = 3,\n sleep = defaultSleep,\n } = options;\n const url = `${baseUrl.replace(/\\/$/, \"\")}${transport === \"gateway\" ? \"/evaluation-model\" : \"/v1/systemone\"}`;\n return async (request, onAttempt) => {\n const call =\n transport === \"gateway\"\n ? gatewayCall(request)\n : { body: JSON.stringify(request), headers: {} };\n let attempt = 0;\n for (;;) {\n attempt += 1;\n onAttempt?.();\n let response: Response;\n try {\n response = await doFetch(url, {\n body: call.body,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n ...call.headers,\n },\n method: \"POST\",\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (error) {\n const isTimeout =\n (error as Error).name === \"TimeoutError\" ||\n (error as Error).name === \"AbortError\";\n if (attempt <= retries) {\n await sleep(backoff(attempt));\n continue;\n }\n throw new ProviderError(isTimeout ? \"timeout\" : \"provider_error\");\n }\n if (response.status === 401 || response.status === 403) {\n throw new ProviderError(\"auth\", response.status);\n }\n if (response.status === 429 || response.status >= 500) {\n if (attempt <= retries) {\n // Honour Retry-After up to a ceiling so one header cannot park a run.\n const retryAfter = Number(response.headers.get(\"retry-after\"));\n await sleep(\n Number.isFinite(retryAfter) && retryAfter > 0\n ? Math.min(retryAfter * 1000, MAX_RETRY_AFTER_MS)\n : backoff(attempt)\n );\n continue;\n }\n throw new ProviderError(\"provider_error\", response.status);\n }\n if (!response.ok) {\n throw new ProviderError(\"provider_error\", response.status);\n }\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n throw new ProviderError(\"invalid_response\", response.status);\n }\n return { ...validateResponse(body, request), attempts: attempt };\n }\n };\n};\n\nconst backoff = (attempt: number): number =>\n Math.min(8000, 250 * 2 ** (attempt - 1)) + Math.floor(Math.random() * 100);\n","// SIMPLIFIED: 3.5 characters per token. Conservative for English prose (about\n// 4 per token) and optimistic for hyphen-dense class lists (nearer 2 to 3),\n// which is why STATE_TOKEN_CAP and REQUEST_TOKEN_CAP leave headroom under the\n// provider limits. Used only for budgeting and dry-run estimates; the summary\n// line reports the provider's real usage.input_tokens after a run.\nexport const estimateTokens = (text: string, charsPerToken = 3.5): number =>\n Math.ceil(text.length / charsPerToken);\n\n/** Class-list and element states are hyphen-dense and tokenise shorter. */\nexport const charsPerTokenFor = (kind: string): number =>\n kind === \"class-list\" || kind === \"element\" ? 3 : 3.5;\n\nconst PRICE_PER_MILLION_INPUT_USD = 0.042;\n\nexport const costUsd = (inputTokens: number): number =>\n (inputTokens / 1_000_000) * PRICE_PER_MILLION_INPUT_USD;\n","// Build the Jev wire-format question from a rule. The structured criteria\n// form ({ what, examples }) is what the API documents under primitives/advanced.\n\nimport type { Rule, SystemOneNoul } from \"../types.js\";\n\nexport const buildQuestion = (rule: Rule): SystemOneNoul => {\n if (!rule.question) {\n throw new Error(`Rule ${rule.id} has no question`);\n }\n const q = rule.question;\n const out: SystemOneNoul = {\n instructions: q.instructions,\n type: \"noul\",\n };\n if (q.criteria) {\n out.criteria = {\n false: {\n examples: q.criteria.false.examples,\n what: q.criteria.false.what,\n },\n true: { examples: q.criteria.true.examples, what: q.criteria.true.what },\n };\n }\n return out;\n};\n","// SIMPLIFIED: single-process token bucket plus a concurrency gate. Fine for\n// one CLI run under the 1,200 requests per minute limit; a shared limiter is\n// needed before several runs share one key in CI.\n\nexport class Limiter {\n private tokens: number;\n private last = Date.now();\n private inFlight = 0;\n private readonly waiters: (() => void)[] = [];\n\n constructor(\n private readonly perSecond: number,\n private readonly concurrency: number,\n private readonly now: () => number = () => Date.now(),\n private readonly sleep: (ms: number) => Promise<void> = (ms) =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n })\n ) {\n this.tokens = perSecond;\n this.last = now();\n }\n\n private refill(): void {\n const t = this.now();\n const elapsed = (t - this.last) / 1000;\n this.tokens = Math.min(\n this.perSecond,\n this.tokens + elapsed * this.perSecond\n );\n this.last = t;\n }\n\n async acquire(): Promise<() => void> {\n while (this.inFlight >= this.concurrency) {\n await new Promise<void>((resolve) => {\n this.waiters.push(resolve);\n });\n }\n this.inFlight += 1;\n for (;;) {\n this.refill();\n if (this.tokens >= 1) {\n this.tokens -= 1;\n break;\n }\n await this.sleep(Math.ceil(((1 - this.tokens) / this.perSecond) * 1000));\n }\n return () => {\n this.inFlight -= 1;\n const next = this.waiters.shift();\n next?.();\n };\n }\n}\n","// Build the Jev state string for a unit from only the context keys the\n// batched questions asked for. Numbers never enter the state.\n\nimport { charsPerTokenFor, estimateTokens } from \"../lib/tokens.js\";\nimport type { ContextKey, Rule, Unit } from \"../types.js\";\n\nexport const STATE_TOKEN_CAP = 1500;\n\nexport const buildState = (\n unit: Unit,\n rules: Rule[]\n): { state: string; truncated: boolean } => {\n const keys = new Set<ContextKey>();\n for (const rule of rules) {\n for (const key of rule.question?.context ?? []) {\n keys.add(key);\n }\n }\n const lines: string[] = [];\n let truncated = false;\n const perToken = charsPerTokenFor(unit.kind);\n const budgetFor = (label: string): number =>\n Math.max(\n 0,\n STATE_TOKEN_CAP -\n estimateTokens(lines.join(\"\\n\"), perToken) -\n estimateTokens(label, perToken)\n );\n const clip = (label: string, value: string): string => {\n const budget = budgetFor(label);\n if (estimateTokens(value, perToken) <= budget) {\n return value;\n }\n truncated = true;\n return `${value.slice(0, Math.max(0, Math.floor(budget * perToken)))} [truncated]`;\n };\n if (keys.has(\"neighbours\") && unit.neighbours?.next) {\n lines.push(\n `FIRST: ${clip(\"FIRST: \", unit.text)}`,\n `SECOND: ${clip(\"SECOND: \", unit.neighbours.next.text)}`\n );\n } else {\n lines.push(`TEXT: ${clip(\"TEXT: \", unit.text)}`);\n }\n if (keys.has(\"headingAbove\") && unit.context.headingAbove) {\n lines.push(`HEADING: ${clip(\"HEADING: \", unit.context.headingAbove)}`);\n }\n if (keys.has(\"docType\")) {\n lines.push(`DOC TYPE: ${unit.context.docType}`);\n }\n if (keys.has(\"element\") && unit.context.element) {\n lines.push(\n `ELEMENT: ${unit.context.element}${unit.context.attr ? ` (${unit.context.attr})` : \"\"}`\n );\n }\n if (keys.has(\"role\")) {\n lines.push(`ROLE: ${unit.context.role}`);\n }\n if (keys.has(\"section\") && unit.context.section) {\n lines.push(`SECTION: ${clip(\"SECTION: \", unit.context.section)}`);\n }\n for (const [key, label] of [\n [\"writingFacts\", \"SUPPLIED FACTS\"],\n [\"writingProfile\", \"VOICE PROFILE\"],\n [\"writingInstructions\", \"DRAFTING INSTRUCTIONS\"],\n ] as const) {\n if (keys.has(key) && unit.context[key]) {\n lines.push(`${label}: ${clip(`${label}: `, unit.context[key]!)}`);\n }\n }\n return { state: lines.join(\"\\n\"), truncated };\n};\n","// Turn Jev jobs into requests, consulting the cache, and run them with the\n// limiter. Records only categories and token counts, never bodies.\n\nimport { charsPerTokenFor, estimateTokens } from \"../lib/tokens.js\";\nimport { buildQuestion } from \"../rules/question.js\";\nimport type {\n Evaluate,\n Progress,\n RecorderHandle,\n SystemOneNoul,\n} from \"../types.js\";\nimport type { AnswerCache } from \"./cache.js\";\nimport { cacheKey } from \"./cache.js\";\nimport { ProviderError } from \"./jev.js\";\nimport { Limiter } from \"./limiter.js\";\nimport type { JevJob } from \"./plan.js\";\nimport { buildState } from \"./state.js\";\n\nexport const REQUEST_TOKEN_CAP = 60_000;\n\nexport interface PreparedRequest {\n job: JevJob;\n state: string;\n /** The state was clipped to the token cap; recorded with each request. */\n truncated: boolean;\n /** Questions still needing an answer, keyed by rule id. */\n questions: Record<string, SystemOneNoul>;\n keys: Record<string, string>;\n /** Answers already served from cache. */\n cached: Record<string, number>;\n estimatedTokens: number;\n}\n\nexport const prepareRequests = (\n jobs: JevJob[],\n cache: AnswerCache,\n model: string\n): PreparedRequest[] => {\n const out: PreparedRequest[] = [];\n for (const job of jobs) {\n const rules = job.rules.map((r) => r.rule);\n const { state, truncated } = buildState(job.unit, rules);\n const questions: Record<string, SystemOneNoul> = {};\n const keys: Record<string, string> = {};\n const cached: Record<string, number> = {};\n for (const rule of rules) {\n const q = buildQuestion(rule);\n const key = cacheKey(q, state, model);\n const hit = cache.get(key);\n if (hit) {\n cached[rule.id] = hit.noul;\n } else {\n questions[rule.id] = q;\n keys[rule.id] = key;\n }\n }\n const perToken = charsPerTokenFor(job.unit.kind);\n const estimatedTokens =\n estimateTokens(state, perToken) +\n Object.values(questions).reduce(\n (s, q) => s + estimateTokens(JSON.stringify(q)),\n 0\n );\n out.push({\n cached,\n estimatedTokens,\n job,\n keys,\n questions,\n state,\n truncated,\n });\n }\n return out;\n};\n\n// Split a prepared request whose questions exceed the cap into chunks.\nexport const chunkQuestions = (\n prepared: PreparedRequest\n): Record<string, SystemOneNoul>[] => {\n const ids = Object.keys(prepared.questions);\n if (ids.length === 0) {\n return [];\n }\n const chunks: Record<string, SystemOneNoul>[] = [];\n let current: Record<string, SystemOneNoul> = {};\n const perToken = charsPerTokenFor(prepared.job.unit.kind);\n let tokens = estimateTokens(prepared.state, perToken);\n for (const id of ids) {\n const q = prepared.questions[id];\n const qTokens = estimateTokens(JSON.stringify(q));\n if (\n Object.keys(current).length > 0 &&\n tokens + qTokens > REQUEST_TOKEN_CAP\n ) {\n chunks.push(current);\n current = {};\n tokens = estimateTokens(prepared.state, perToken);\n }\n current[id] = q;\n tokens += qTokens;\n }\n chunks.push(current);\n return chunks;\n};\n\nexport interface RunOutcome {\n /** Probabilities per unit id per rule id. */\n answers: Map<string, Record<string, number>>;\n requests: number;\n attempts: number;\n sharedAnswers: number;\n cached: number;\n inputTokens: number;\n errors: number;\n /** Rule ids that could not be answered for a unit, with the error category. */\n failed: { unitId: string; ruleIds: string[]; category: string }[];\n}\n\nexport interface RunOptions {\n work?: ReturnType<typeof requestWork>;\n evaluate: Evaluate;\n cache: AnswerCache;\n model: string;\n recorder?: RecorderHandle;\n limiter?: Limiter;\n onProgress?: (progress: Progress) => void;\n}\n\n// Exact same state, questions and model share one logical request. Provenance\n// stays on each consumer; never merge findings from different source locations.\nexport const requestWork = (prepared: PreparedRequest[]) => {\n const grouped = new Map<\n string,\n {\n prepared: PreparedRequest;\n questions: Record<string, SystemOneNoul>;\n consumers: PreparedRequest[];\n }\n >();\n for (const p of prepared) {\n for (const questions of chunkQuestions(p)) {\n const ids = Object.keys(questions).toSorted();\n const key = JSON.stringify(ids.map((id) => [id, p.keys[id]]));\n const existing = grouped.get(key);\n if (existing) {\n existing.consumers.push(p);\n } else {\n grouped.set(key, { consumers: [p], prepared: p, questions });\n }\n }\n }\n return [...grouped.values()];\n};\n\nexport const cachedAnswers = (\n prepared: PreparedRequest[]\n): Map<string, Record<string, number>> => {\n const answers = new Map<string, Record<string, number>>();\n for (const p of prepared) {\n answers.set(p.job.unit.id, { ...answers.get(p.job.unit.id), ...p.cached });\n }\n return answers;\n};\n\nexport const runRequests = async (\n prepared: PreparedRequest[],\n options: RunOptions\n): Promise<RunOutcome> => {\n const { evaluate, cache, model, recorder, onProgress } = options;\n const limiter = options.limiter ?? new Limiter(20, 8);\n const answers = cachedAnswers(prepared);\n const outcome: RunOutcome = {\n answers,\n attempts: 0,\n cached: prepared.reduce((n, p) => n + Object.keys(p.cached).length, 0),\n errors: 0,\n failed: [],\n inputTokens: 0,\n requests: 0,\n sharedAnswers: 0,\n };\n const work = options.work ?? requestWork(prepared);\n const started = Date.now();\n let completed = 0;\n let aborted = false;\n const progress = () =>\n onProgress?.({\n attempts: outcome.attempts,\n cachedAnswers: outcome.cached,\n completed,\n elapsedMs: Date.now() - started,\n failed: outcome.errors,\n phase: completed === work.length ? \"complete\" : \"evaluating\",\n planned: work.length,\n });\n progress();\n // Bounded workers avoid thousands of promises waiting on the limiter.\n let cursor = 0;\n let artifactFailure: unknown;\n const worker = async () => {\n while (cursor < work.length && artifactFailure === undefined) {\n const records: Record<string, unknown>[] = [];\n const { prepared: p, questions, consumers } = work[cursor];\n cursor += 1;\n const release = aborted\n ? () => {\n /* No permit was acquired after cancellation. */\n }\n : await limiter.acquire();\n try {\n if (aborted) {\n throw new ProviderError(\"auth\", 401);\n }\n const remaining: Record<string, SystemOneNoul> = {};\n for (const id of Object.keys(questions)) {\n const hit = cache.get(p.keys[id]);\n if (hit) {\n for (const c of consumers) {\n answers.get(c.job.unit.id)![id] = hit.noul;\n }\n outcome.cached += consumers.length;\n } else {\n remaining[id] = questions[id];\n }\n }\n if (Object.keys(remaining).length > 0) {\n let attempts = 0;\n const onAttempt = () => {\n attempts += 1;\n outcome.attempts += 1;\n progress();\n };\n let response;\n try {\n response = await evaluate(\n { model, questions: remaining, state: p.state },\n onAttempt\n );\n } finally {\n if (attempts === 0) {\n outcome.attempts += 1;\n }\n }\n outcome.requests += 1;\n outcome.inputTokens += response.usage.input_tokens;\n for (const [id, answer] of Object.entries(response.answers)) {\n for (const c of consumers) {\n answers.get(c.job.unit.id)![id] = answer.noul as number;\n }\n }\n outcome.sharedAnswers +=\n (consumers.length - 1) * Object.keys(remaining).length;\n records.push({\n attempts: attempts || 1,\n input_tokens: response.usage.input_tokens,\n kind: \"request\",\n rule_ids: Object.keys(remaining),\n shared_units: consumers.length,\n status: \"ok\",\n truncated: p.truncated,\n unit_id: p.job.unit.id,\n });\n try {\n for (const [id, answer] of Object.entries(response.answers)) {\n cache.set(p.keys[id], {\n model: response.model,\n noul: answer.noul as number,\n ts: new Date().toISOString(),\n });\n }\n } catch {\n records.push({\n kind: \"cache_write_failed\",\n unit_id: p.job.unit.id,\n });\n }\n }\n } catch (error) {\n outcome.errors += 1;\n const category =\n error instanceof ProviderError ? error.category : \"provider_error\";\n for (const c of consumers) {\n const missing = Object.keys(questions).filter(\n (id) => answers.get(c.job.unit.id)![id] === undefined\n );\n if (missing.length) {\n outcome.failed.push({\n category,\n ruleIds: missing,\n unitId: c.job.unit.id,\n });\n }\n }\n records.push({\n error: category,\n http_status:\n error instanceof ProviderError ? (error.status ?? null) : null,\n kind: \"request\",\n rule_ids: Object.keys(questions),\n status: \"error\",\n truncated: p.truncated,\n unit_id: p.job.unit.id,\n });\n if (category === \"auth\") {\n aborted = true;\n }\n } finally {\n release();\n completed += 1;\n progress();\n }\n try {\n for (const record of records) {\n recorder?.append(record);\n }\n } catch (error) {\n artifactFailure = error;\n }\n }\n };\n await Promise.all(\n Array.from({ length: Math.min(8, work.length) }, () => worker())\n );\n if (artifactFailure !== undefined) {\n throw artifactFailure;\n }\n return outcome;\n};\n","import { createHash } from \"node:crypto\";\n\nimport type { DocType, Role, Unit, UnitContext, UnitKind } from \"../types.js\";\n\n// 1-based line and column lookups over a source string. Offsets are UTF-16\n// code unit indexes, which is what both mdast and oxc-parser report.\nexport class LineIndex {\n private readonly starts: number[] = [0];\n\n constructor(source: string) {\n for (let i = 0; i < source.length; i += 1) {\n if (source.codePointAt(i) === 10) {\n this.starts.push(i + 1);\n }\n }\n }\n\n positionAt(offset: number): { line: number; column: number } {\n let lo = 0;\n let hi = this.starts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (this.starts[mid] <= offset) {\n lo = mid;\n } else {\n hi = mid - 1;\n }\n }\n return { column: offset - this.starts[lo] + 1, line: lo + 1 };\n }\n\n offsetAt(line: number, column: number): number {\n const start = this.starts[Math.min(line, this.starts.length) - 1] ?? 0;\n return start + column - 1;\n }\n}\n\nexport const normaliseText = (text: string): string =>\n text.replaceAll(/[ \\t\\n\\r\\f\\v]+/gu, \" \").trim();\n\nexport const unitId = (\n file: string,\n kind: UnitKind,\n sourceStart: number\n): string =>\n createHash(\"sha256\")\n .update(`${file}\\u0000${kind}\\u0000${sourceStart}`)\n .digest(\"hex\")\n .slice(0, 16);\n\n// Element roles shared by the TSX and rendered extractors so the same tag\n// gets the same role whichever way it was reached.\nexport const ROLE_BY_TAG: Record<string, Role> = {\n a: \"link\",\n button: \"button\",\n caption: \"caption\",\n figcaption: \"caption\",\n h1: \"heading\",\n h2: \"heading\",\n h3: \"heading\",\n h4: \"heading\",\n h5: \"heading\",\n h6: \"heading\",\n label: \"label\",\n legend: \"label\",\n li: \"list-item\",\n option: \"label\",\n p: \"body\",\n span: \"body\",\n summary: \"heading\",\n td: \"cell\",\n th: \"heading\",\n};\n\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: \"&\",\n apos: \"'\",\n gt: \">\",\n hellip: \"…\",\n laquo: \"«\",\n ldquo: \"“\",\n lsquo: \"‘\",\n lt: \"<\",\n mdash: String.fromCodePoint(0x20_14),\n middot: \"·\",\n nbsp: \" \",\n ndash: String.fromCodePoint(0x20_13),\n quot: '\"',\n raquo: \"»\",\n rdquo: \"”\",\n rsquo: \"’\",\n times: \"×\",\n};\n\n// One pass over numeric and the named character references copy uses, so\n// `&lt;` stays `<` and `’` becomes a right quote. Unknown names\n// are left as written.\nexport const decodeEntities = (text: string): string =>\n text.replaceAll(\n /&(#x[0-9a-f]+|#\\d+|[a-z][a-z0-9]*);/giu,\n (whole: string, ref: string) => {\n if (ref.startsWith(\"#x\") || ref.startsWith(\"#X\")) {\n const code = Number.parseInt(ref.slice(2), 16);\n return Number.isFinite(code) && code <= 0x10_ff_ff\n ? String.fromCodePoint(code)\n : whole;\n }\n if (ref.startsWith(\"#\")) {\n const code = Number(ref.slice(1));\n return Number.isFinite(code) && code <= 0x10_ff_ff\n ? String.fromCodePoint(code)\n : whole;\n }\n return NAMED_ENTITIES[ref] ?? whole;\n }\n );\n\nexport interface UnitDraft {\n kind: UnitKind;\n text: string;\n sourceStart: number;\n sourceEnd: number;\n inCode?: boolean;\n codeSpans?: [number, number][];\n fixRanges?: [number, number][];\n context: Partial<UnitContext> & { role: Role; docType: DocType };\n typography?: Unit[\"typography\"];\n neighbours?: Unit[\"neighbours\"];\n classes?: string[];\n}\n\nexport const makeUnit = (\n file: string,\n index: LineIndex,\n draft: UnitDraft\n): Unit => {\n const start = index.positionAt(draft.sourceStart);\n const end = index.positionAt(Math.max(draft.sourceStart, draft.sourceEnd));\n return {\n classes: draft.classes,\n codeSpans: draft.codeSpans ?? [],\n column: start.column,\n context: draft.context as UnitContext,\n endColumn: end.column,\n endLine: end.line,\n file,\n fixRanges: draft.fixRanges,\n id: unitId(file, draft.kind, draft.sourceStart),\n inCode: draft.inCode ?? false,\n kind: draft.kind,\n line: start.line,\n neighbours: draft.neighbours,\n sourceEnd: draft.sourceEnd,\n sourceStart: draft.sourceStart,\n text: draft.text,\n typography: draft.typography,\n };\n};\n\n// Replace code spans with spaces so regexes cannot match inside them while\n// offsets into the text stay valid. Spans are UTF-16 offsets, like `text`.\nexport const maskCodeSpans = (\n text: string,\n spans: [number, number][]\n): string => {\n let out = text;\n for (const [s, e] of spans) {\n const end = Math.min(e, out.length);\n if (s < end) {\n out = out.slice(0, s) + \" \".repeat(end - s) + out.slice(end);\n }\n }\n return out;\n};\n","// Build a Finding from a rule and a unit. Severity comes from the rule; the\n// band and probability come from the caller.\n\nimport type { Band, Finding, Rule, Unit } from \"../types.js\";\n\nexport const toFinding = (\n rule: Rule,\n unit: Unit,\n probability: number,\n b: Band,\n candidateEvidence?: string\n): Finding => ({\n band: b,\n categoryId: rule.categoryId,\n column: unit.column,\n domain: rule.domain,\n endColumn: unit.endColumn,\n endLine: unit.endLine,\n evidence: candidateEvidence\n ? `${candidateEvidence}; p=${probability.toFixed(2)}`\n : `p=${probability.toFixed(2)}`,\n file: unit.file,\n fixHint: rule.fix.hint,\n line: unit.line,\n message: rule.title,\n probability,\n ruleId: rule.id,\n severity: rule.severity,\n suppressed: false,\n tier: rule.tier,\n unitId: unit.id,\n});\n","// Mechanical checks over units. Data rules (regex, phrases, absent) run\n// through `runMechanical`; code rules carry their own `check` and share the\n// helpers exported here. Everything that counts, compares or measures lives\n// in this layer; Jev only sees text.\n\nimport { maskCodeSpans } from \"../extract/units.js\";\nimport type {\n Mechanical,\n MechanicalHit,\n ResolvedTypography,\n Unit,\n} from \"../types.js\";\n\nconst escapeRegExp = (s: string): string =>\n s.replaceAll(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst phraseRegex = (phrases: string[]): RegExp =>\n new RegExp(\n `(?<![\\\\p{L}\\\\p{N}])(?:${phrases.map(escapeRegExp).join(\"|\")})(?![\\\\p{L}\\\\p{N}])`,\n \"giu\"\n );\n\nexport const describe = (t?: ResolvedTypography): string => {\n if (!t) {\n return \"unresolved\";\n }\n const parts: string[] = [];\n if (t.fontSizePx !== undefined) {\n parts.push(`${t.fontSizePx}px`);\n }\n if (t.fontWeight !== undefined) {\n parts.push(`weight ${t.fontWeight}`);\n }\n if (t.lineHeight !== undefined) {\n parts.push(`leading ${t.lineHeight}`);\n }\n if (t.letterSpacingEm !== undefined) {\n parts.push(`tracking ${t.letterSpacingEm}em`);\n }\n if (t.uppercase) {\n parts.push(\"uppercase\");\n }\n return parts.join(\", \") || \"unresolved\";\n};\n\nexport const none: MechanicalHit = { evidence: \"\", fired: false };\n\nexport const hit = (evidence: string): MechanicalHit => ({\n evidence,\n fired: true,\n});\n\n// A check that cannot decide throws this; the planner records an abstention\n// (`unknown`), never a pass or a fail.\nexport class UnresolvedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UnresolvedError\";\n }\n}\n\nexport const needTypography = (unit: Unit): ResolvedTypography => {\n if (!unit.typography) {\n throw new UnresolvedError(\"no class list\");\n }\n return unit.typography;\n};\n\nexport const countWords = (sentence: string): number =>\n sentence.split(/[ \\t\\n\\r\\f\\v]+/u).filter(Boolean).length;\n\n// A resolved size, or `undefined` when the element inherits. A size class\n// that could not be resolved is an abstention, not a guess.\nexport const sizeOrAbstain = (t: ResolvedTypography): number | undefined => {\n if (t.fontSizePx === undefined) {\n if (t.unresolved.some((c) => c.startsWith(\"text-\"))) {\n throw new UnresolvedError(`unresolved ${t.unresolved.join(\" \")}`);\n }\n return undefined;\n }\n return t.fontSizePx;\n};\n\n// Typography checks judge text; an element with classes and no text of its\n// own (an icon wrapper) is not theirs to judge.\nexport const needText = (unit: Unit): boolean => unit.text.trim().length > 0;\n\n// The utility without its variant prefixes, split outside brackets, so\n// `hover:ease-in` counts as `ease-in`.\nexport const baseClass = (cls: string): string => {\n let depth = 0;\n let cut = 0;\n for (let i = 0; i < cls.length; i += 1) {\n const ch = cls[i];\n if (ch === \"[\") {\n depth += 1;\n } else if (ch === \"]\") {\n depth -= 1;\n } else if (ch === \":\" && depth === 0) {\n cut = i + 1;\n }\n }\n return cls.slice(cut);\n};\n\n// A data rule's regex or phrase list over the unit's text, with code spans\n// masked. `absent` turns \"has A\" into \"has A and never B\".\nexport const runMechanical = (\n mechanical: Mechanical,\n unit: Unit\n): MechanicalHit => {\n const text = maskCodeSpans(unit.text, unit.codeSpans);\n const minMatches = mechanical.minMatches ?? 1;\n const matches: { text: string; offset: number }[] = [];\n if (mechanical.regex) {\n const flags = mechanical.flags ?? \"gu\";\n const re = new RegExp(\n mechanical.regex,\n flags.includes(\"g\") ? flags : `${flags}g`\n );\n for (const m of text.matchAll(re)) {\n matches.push({ offset: m.index ?? 0, text: m[0] });\n }\n }\n if (mechanical.phrases) {\n for (const m of text.matchAll(phraseRegex(mechanical.phrases))) {\n matches.push({ offset: m.index ?? 0, text: m[0] });\n }\n }\n if (matches.length < minMatches) {\n return none;\n }\n if (\n mechanical.absent &&\n new RegExp(mechanical.absent, mechanical.flags ?? \"gu\").test(text)\n ) {\n return none;\n }\n const shown = matches\n .slice(0, 3)\n .map((m) => JSON.stringify(m.text.replaceAll(/\\s+/gu, \" \").slice(0, 80)))\n .join(\", \");\n return {\n evidence: `${matches.length} match${matches.length === 1 ? \"\" : \"es\"}: ${shown}`,\n fired: true,\n offset: Math.min(...matches.map((m) => m.offset)),\n };\n};\n","// Decide which rules apply to which units and build one Jev job per unit.\n\nimport { LineIndex } from \"../extract/units.js\";\nimport { matchesAny } from \"../lib/glob.js\";\nimport { estimateTokens, charsPerTokenFor } from \"../lib/tokens.js\";\nimport { toFinding } from \"../reduce/finding.js\";\nimport { runMechanical, UnresolvedError } from \"../reduce/mechanical.js\";\nimport type {\n Config,\n Finding,\n MechanicalHit,\n Rule,\n Unit,\n Unknown,\n} from \"../types.js\";\nimport { buildState, STATE_TOKEN_CAP } from \"./state.js\";\n\nexport interface JevJob {\n unit: Unit;\n /** Rules whose question must be asked for this unit, with candidate evidence. */\n rules: { rule: Rule; hit?: MechanicalHit }[];\n}\n\nexport interface Plan {\n mechanical: Finding[];\n jobs: JevJob[];\n unknowns: Unknown[];\n eligible: Map<string, Set<string>>;\n negatives: Map<string, Set<string>>;\n skipped: Map<string, Record<string, string>>;\n}\n\n// Rendered units come from a URL, not a file, so only the unit kind gates them.\nconst inScope = (rule: Rule, unit: Unit): boolean =>\n unit.kind === \"element\" ||\n (matchesAny(unit.file, rule.scope.include) &&\n !matchesAny(unit.file, rule.scope.exclude));\n\nconst passesPreconditions = (\n rule: Rule,\n unit: Unit,\n config: Config\n): boolean => {\n const p = rule.preconditions;\n if (!p) {\n return true;\n }\n if (p.notInCode && unit.inCode) {\n return false;\n }\n if (p.docType && !p.docType.includes(unit.context.docType)) {\n return false;\n }\n if (p.role && !p.role.includes(unit.context.role)) {\n return false;\n }\n if (\n p.smartQuotesAtBuild === false &&\n config.smartQuotesAtBuild &&\n (unit.kind === \"paragraph\" || unit.kind === \"heading\") &&\n /\\.(md|mdx)$/.test(unit.file)\n ) {\n return false;\n }\n return true;\n};\n\n// A mechanical hit is certain (p = 1) and acts unless the rule is review-only.\n// A source unit spans the file, so the finding points at the first match.\nexport const mechanicalFinding = (\n rule: Rule,\n unit: Unit,\n hit: MechanicalHit\n): Finding => {\n const finding = {\n ...toFinding(\n rule,\n unit,\n 1,\n rule.status === \"review-only\" ? \"review\" : \"act\"\n ),\n evidence: hit.evidence,\n };\n if (unit.kind === \"source\" && hit.offset !== undefined) {\n const at = new LineIndex(unit.text).positionAt(hit.offset);\n return {\n ...finding,\n column: at.column,\n endColumn: at.column,\n endLine: at.line,\n line: at.line,\n };\n }\n return finding;\n};\n\nexport const planRequests = (\n units: Unit[],\n rules: Rule[],\n config: Config\n): Plan => {\n const eligible = new Map<string, Set<string>>();\n const negatives = new Map<string, Set<string>>();\n const skipped = new Map<string, Record<string, string>>();\n const mechanical: Finding[] = [];\n const jobs: JevJob[] = [];\n const unknowns: Unknown[] = [];\n for (const unit of units) {\n if (unit.kind === \"file\") {\n continue;\n }\n const skippedRules: Record<string, string> = {};\n skipped.set(unit.id, skippedRules);\n const candidates = rules.filter((r) => {\n if (!inScope(r, unit) || !r.unit.includes(unit.kind)) {\n skippedRules[r.id] = \"out_of_scope\";\n return false;\n }\n return true;\n });\n if (candidates.length === 0) {\n continue;\n }\n const job: JevJob = { rules: [], unit };\n for (const rule of candidates) {\n if (!passesPreconditions(rule, unit, config)) {\n skippedRules[rule.id] = \"precondition\";\n continue;\n }\n const applied = eligible.get(unit.id) ?? new Set<string>();\n applied.add(rule.id);\n eligible.set(unit.id, applied);\n if (\n rule.question?.context?.includes(\"section\") &&\n (!unit.context.section || buildState(unit, [rule]).truncated)\n ) {\n unknowns.push({\n file: unit.file,\n line: unit.line,\n reason: unit.context.section\n ? \"Section comparison exceeds the context budget\"\n : \"Missing section context\",\n ruleId: rule.id,\n unitId: unit.id,\n });\n continue;\n }\n const writingKeys = [\n \"writingFacts\",\n \"writingProfile\",\n \"writingInstructions\",\n ] as const;\n const requiredWriting = writingKeys.filter((key) =>\n rule.question?.context?.includes(key)\n );\n if (requiredWriting.length) {\n const missing = requiredWriting.filter((key) => !unit.context[key]);\n const total = [\n unit.text,\n ...writingKeys.map((key) => unit.context[key] ?? \"\"),\n ].join(\"\\n\");\n if (\n missing.length ||\n estimateTokens(total, charsPerTokenFor(unit.kind)) >\n STATE_TOKEN_CAP - 200\n ) {\n unknowns.push({\n file: unit.file,\n line: unit.line,\n reason: missing.length\n ? `Missing explicit writing context: ${missing.join(\", \")}`\n : \"Writing comparison exceeds the context budget\",\n ruleId: rule.id,\n unitId: unit.id,\n });\n continue;\n }\n }\n if (rule.tier === \"jev\") {\n job.rules.push({ rule });\n continue;\n }\n let hit: MechanicalHit;\n try {\n hit = rule.check\n ? rule.check(unit)\n : runMechanical(\n rule.mechanical as NonNullable<Rule[\"mechanical\"]>,\n unit\n );\n } catch (error) {\n if (error instanceof UnresolvedError) {\n unknowns.push({\n file: unit.file,\n line: unit.line,\n reason: error.message,\n ruleId: rule.id,\n unitId: unit.id,\n });\n continue;\n }\n throw error;\n }\n if (!hit.fired) {\n const ids = negatives.get(unit.id) ?? new Set<string>();\n ids.add(rule.id);\n negatives.set(unit.id, ids);\n continue;\n }\n if (rule.tier === \"mechanical\") {\n mechanical.push(mechanicalFinding(rule, unit, hit));\n } else {\n job.rules.push({ hit, rule });\n }\n }\n if (job.rules.length > 0) {\n const contextual = job.rules.filter(({ rule }) =>\n rule.question?.context?.includes(\"section\")\n );\n const local = job.rules.filter(\n ({ rule }) => !rule.question?.context?.includes(\"section\")\n );\n if (local.length) {\n jobs.push({ ...job, rules: local });\n }\n for (const candidate of contextual) {\n jobs.push({ ...job, rules: [candidate] });\n }\n }\n }\n return { eligible, jobs, mechanical, negatives, skipped, unknowns };\n};\n","// The one stage lint and eval share: plan which rules apply, run the\n// mechanical checks, answer the Jev questions (from cache, or live when an\n// evaluate is supplied and this is not a dry run), and report abstentions.\n\nimport { costUsd, estimateTokens, charsPerTokenFor } from \"../lib/tokens.js\";\nimport type {\n Config,\n Coverage,\n Progress,\n Evaluate,\n Finding,\n RecorderHandle,\n Rule,\n Unit,\n Unknown,\n Usage,\n} from \"../types.js\";\nimport {\n cachedAnswers,\n prepareRequests,\n requestWork,\n runRequests,\n} from \"./batch.js\";\nimport type { PreparedRequest } from \"./batch.js\";\nimport type { AnswerCache } from \"./cache.js\";\nimport { planRequests } from \"./plan.js\";\nimport type { JevJob, Plan } from \"./plan.js\";\n\nexport interface JudgeOptions {\n config: Config;\n model: string;\n cache: AnswerCache;\n /** Absent means answers come from the cache only (a dry run). */\n evaluate?: Evaluate;\n mechanicalOnly?: boolean;\n recorder?: RecorderHandle;\n onProgress?: (progress: Progress) => void;\n /** Narrow or drop a job before it is prepared (eval keeps labelled rules only). */\n jobFilter?: (job: JevJob) => JevJob | null;\n}\n\nexport interface Judgement {\n coverage: Coverage;\n negatives: Plan[\"negatives\"];\n skipped: Plan[\"skipped\"];\n mechanical: Finding[];\n jobs: JevJob[];\n /** Requests still needing at least one answer after the cache. */\n pending: PreparedRequest[];\n estimatedRequests: number;\n estimatedTokens: number;\n answers: Map<string, Record<string, number>>;\n unknowns: Unknown[];\n usage: Usage;\n}\n\nexport const prepareJudgement = (\n units: Unit[],\n rules: Rule[],\n options: JudgeOptions\n) => {\n const plan = planRequests(\n units,\n options.mechanicalOnly\n ? rules.filter((r) => r.tier === \"mechanical\")\n : rules,\n options.config\n );\n if (options.mechanicalOnly) {\n for (const unit of units) {\n const skipped = plan.skipped.get(unit.id) ?? {};\n for (const rule of rules) {\n if (rule.tier !== \"mechanical\") {\n skipped[rule.id] = \"mechanical_only\";\n }\n }\n plan.skipped.set(unit.id, skipped);\n }\n }\n let jobs = options.mechanicalOnly ? [] : plan.jobs;\n if (options.jobFilter) {\n jobs = jobs\n .map((job) => options.jobFilter?.(job) ?? null)\n .filter((job): job is JevJob => job !== null);\n }\n const prepared = prepareRequests(jobs, options.cache, options.model);\n const pending = prepared.filter((p) => Object.keys(p.questions).length > 0);\n return {\n jobs,\n pending,\n plan,\n prepared,\n rules,\n units,\n work: requestWork(prepared),\n };\n};\n\nexport const executeJudgement = async (\n preview: ReturnType<typeof prepareJudgement>,\n options: JudgeOptions\n): Promise<Judgement> => {\n const { plan, jobs, prepared, pending, units, rules } = preview;\n const unknowns: Unknown[] = [...plan.unknowns];\n const usage: Usage = {\n cached: 0,\n costUsd: 0,\n errors: 0,\n inputTokens: 0,\n requests: 0,\n };\n let answers: Map<string, Record<string, number>>;\n if (options.evaluate && pending.length > 0) {\n const outcome = await runRequests(prepared, {\n cache: options.cache,\n evaluate: options.evaluate,\n model: options.model,\n onProgress: options.onProgress,\n recorder: options.recorder,\n work: preview.work,\n });\n answers = outcome.answers;\n usage.requests = outcome.requests;\n usage.attempts = outcome.attempts;\n usage.sharedAnswers = outcome.sharedAnswers;\n usage.cached = outcome.cached;\n usage.inputTokens = outcome.inputTokens;\n usage.costUsd = costUsd(outcome.inputTokens);\n usage.errors = outcome.errors;\n // A question the provider never answered is an abstention with a reason,\n // not a silent pass.\n const unitById = new Map(units.map((u) => [u.id, u]));\n for (const failed of outcome.failed) {\n const unit = unitById.get(failed.unitId);\n for (const ruleId of failed.ruleIds) {\n unknowns.push({\n file: unit?.file ?? \"\",\n line: unit?.line ?? 0,\n reason: failed.category,\n ruleId,\n unitId: failed.unitId,\n });\n }\n }\n } else {\n // Dry run, or everything came from cache: cached answers still count.\n answers = cachedAnswers(prepared);\n usage.cached = prepared.reduce(\n (s, p) => s + Object.keys(p.cached).length,\n 0\n );\n }\n const coverage: Coverage = { byCategory: {}, byRule: {} };\n const categoryUnits = new Map<string, Set<string>>();\n for (const rule of rules) {\n const eligible = units.filter((u) => plan.eligible.get(u.id)?.has(rule.id));\n const negative = eligible.filter((u) =>\n plan.negatives.get(u.id)?.has(rule.id)\n ).length;\n const unknown = unknowns.filter((u) => u.ruleId === rule.id).length;\n const answered =\n eligible.filter((u) => answers.get(u.id)?.[rule.id] !== undefined)\n .length + plan.mechanical.filter((f) => f.ruleId === rule.id).length;\n coverage.byRule[rule.id] = {\n answered,\n eligible: eligible.length,\n negative,\n pending: Math.max(0, eligible.length - negative - unknown - answered),\n skipped: units.length - eligible.length,\n unknown,\n };\n const set = categoryUnits.get(rule.categoryId) ?? new Set<string>();\n for (const unit of eligible) {\n set.add(unit.id);\n }\n categoryUnits.set(rule.categoryId, set);\n const category = coverage.byCategory[rule.categoryId] ?? {\n eligiblePairs: 0,\n eligibleUnits: 0,\n };\n category.eligiblePairs += eligible.length;\n category.eligibleUnits = set.size;\n coverage.byCategory[rule.categoryId] = category;\n }\n const work = preview.work;\n return {\n answers,\n coverage,\n estimatedRequests: work.length,\n estimatedTokens: work.reduce(\n (sum, w) =>\n sum +\n estimateTokens(\n w.prepared.state,\n charsPerTokenFor(w.prepared.job.unit.kind)\n ) +\n Object.values(w.questions).reduce(\n (n, q) => n + estimateTokens(JSON.stringify(q)),\n 0\n ),\n 0\n ),\n jobs,\n mechanical: plan.mechanical,\n negatives: plan.negatives,\n pending,\n skipped: plan.skipped,\n unknowns,\n usage,\n };\n};\n\nexport const judge = (\n units: Unit[],\n rules: Rule[],\n options: JudgeOptions\n): Promise<Judgement> =>\n executeJudgement(prepareJudgement(units, rules, options), options);\n","import type { JevJob } from \"../map/plan.js\";\nimport type { Band, Finding, Rule } from \"../types.js\";\nimport { toFinding } from \"./finding.js\";\n\nexport const band = (\n probability: number,\n thresholds: Rule[\"thresholds\"]\n): Band => {\n if (probability >= thresholds.act) {\n return \"act\";\n }\n if (probability >= thresholds.review) {\n return \"review\";\n }\n return \"silent\";\n};\n\n// Turn Jev answers into findings. Silent answers produce nothing.\nexport const jevFindings = (\n jobs: JevJob[],\n answers: Map<string, Record<string, number>>\n): { findings: Finding[]; silent: { ruleId: string; unitId: string }[] } => {\n const findings: Finding[] = [];\n const silent: { ruleId: string; unitId: string }[] = [];\n for (const job of jobs) {\n const unitAnswers = answers.get(job.unit.id) ?? {};\n for (const { rule, hit } of job.rules) {\n const p = unitAnswers[rule.id];\n if (p === undefined) {\n continue;\n }\n let b = band(p, rule.thresholds);\n if (b === \"act\" && rule.status === \"review-only\") {\n b = \"review\";\n }\n if (b === \"silent\") {\n silent.push({ ruleId: rule.id, unitId: job.unit.id });\n continue;\n }\n findings.push(toFinding(rule, job.unit, p, b, hit?.evidence));\n }\n }\n return { findings, silent };\n};\n","// Deterministic fixes. Each runs over one prose range of a unit (see\n// `Unit.fixRanges`), never over quotes, braces or inline code, and each\n// matches exactly what its rule's `mechanical.regex` flags.\n\nexport type FixFunction = (prose: string) => string;\n\n// Curl straight quotes. Opening marks follow whitespace, an opening bracket,\n// a dash or the start; everything else closes. A single quote before a digit\n// (the '90s) or a letter run is an apostrophe, always the right single quote.\nconst EM_DASH = String.fromCodePoint(0x20_14);\nconst EN_DASH = String.fromCodePoint(0x20_13);\nconst OPENING_DOUBLE = new RegExp(\n String.raw`(^|[\\s([{${EM_DASH}${EN_DASH}-])\"`,\n \"gu\"\n);\nconst OPENING_SINGLE = /(^|[\\s([{])'(?=[^\\s\\d])/gu;\n\nexport const smartQuotes: FixFunction = (prose) =>\n prose\n .replaceAll(OPENING_DOUBLE, \"$1\\u201C\")\n .replaceAll('\"', \"\\u201D\")\n .replaceAll(OPENING_SINGLE, \"$1\\u2018\")\n .replaceAll(\"'\", \"\\u2019\");\n\n// Three periods to an ellipsis character (typography-ellipsis).\nexport const ellipsis: FixFunction = (prose) => prose.replaceAll(\"...\", \"…\");\n\n// A lowercase x between whole numbers to a multiplication sign, with the same\n// guards as typography-multiplication-sign so `0x1F` and `3.5x` stay put.\nexport const multiplicationSign: FixFunction = (prose) =>\n prose.replaceAll(/(?<![\\w.])([1-9]\\d*)\\s?x\\s?(\\d+)(?![\\w.%])/gu, \"$1×$2\");\n\n// A no-break space between a number and its unit; the unit list mirrors\n// typography-nbsp-value-unit.\nexport const nbspValueUnit: FixFunction = (prose) =>\n prose.replaceAll(\n /(\\d) (?=(?:px|pt|em|rem|ms|min|KB|MB|GB|TB|kg|km|cm|mm|fps|%)(?![\\p{L}\\d]))/gu,\n \"$1 \"\n );\n\nexport const FIXES: Record<string, FixFunction> = {\n ellipsis,\n multiplicationSign,\n nbspValueUnit,\n smartQuotes,\n};\n","// Field-level validators for one rule file. Every helper fails closed with the\n// file path; `validateRule` in validate.ts composes them.\n\nimport { FIXES } from \"../reduce/fixes.js\";\nimport { CONTEXT_KEYS, DOC_TYPES, ROLES } from \"../types.js\";\nimport type {\n CriterionSide,\n Fix,\n Mechanical,\n Preconditions,\n Question,\n Rule,\n UnitKind,\n} from \"../types.js\";\n\nconst EM_DASH = String.fromCodePoint(0x20_14);\nexport type Raw = Record<string, unknown>;\n\nexport const fail = (file: string, message: string): never => {\n throw new Error(`Invalid rule ${file}: ${message}`);\n};\n\nexport const isRecord = (v: unknown): v is Raw =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n// A key the validator does not read would otherwise be a silent no-op; a typo\n// such as `threshold` must fail, not fall back to the default.\nexport const knownKeys = (\n file: string,\n where: string,\n raw: Raw,\n allowed: readonly string[]\n): void => {\n for (const key of Object.keys(raw)) {\n if (!allowed.includes(key)) {\n fail(file, `${where} has unknown key ${key}`);\n }\n }\n};\n\n// A number when present; absent falls back. A present non-number fails.\nexport const optNumber = (\n file: string,\n raw: Raw,\n key: string,\n fallback: number\n): number => {\n const v = raw[key];\n if (v === undefined) {\n return fallback;\n }\n if (typeof v !== \"number\" || !Number.isFinite(v)) {\n fail(file, `${key} must be a number`);\n }\n return v as number;\n};\n\nexport const str = (file: string, raw: Raw, key: string): string => {\n const v = raw[key];\n if (typeof v !== \"string\" || v.trim() === \"\") {\n fail(file, `${key} must be a nonempty string`);\n }\n return v as string;\n};\n\nexport const optStrList = (\n file: string,\n raw: Raw,\n key: string\n): string[] | undefined => {\n const v = raw[key];\n if (v === undefined) {\n return undefined;\n }\n if (!Array.isArray(v) || v.some((s) => typeof s !== \"string\")) {\n fail(file, `${key} must be a list of strings`);\n }\n return v as string[];\n};\n\nexport const oneOf = <T extends string>(\n file: string,\n key: string,\n v: unknown,\n allowed: readonly T[]\n): T => {\n if (typeof v !== \"string\" || !allowed.includes(v as T)) {\n fail(file, `${key} must be one of ${allowed.join(\", \")}`);\n }\n return v as T;\n};\n\nexport const noEmDash = (file: string, key: string, v: string): void => {\n if (v.includes(EM_DASH)) {\n fail(file, `${key} contains an em dash; use a comma, colon or period`);\n }\n};\n\nconst side = (file: string, key: string, v: unknown): CriterionSide => {\n if (!isRecord(v)) {\n fail(file, `${key} must be an object with what and examples`);\n }\n knownKeys(file, key, v as Raw, [\"what\", \"examples\"]);\n const what = str(file, v as Raw, \"what\");\n noEmDash(file, `${key}.what`, what);\n const examples = optStrList(file, v as Raw, \"examples\") ?? [];\n if (examples.length === 0) {\n fail(file, `${key}.examples needs at least one example`);\n }\n for (const example of examples) {\n noEmDash(file, `${key}.examples`, example);\n }\n return { examples, what };\n};\n\nexport const question = (file: string, v: unknown): Question => {\n if (!isRecord(v)) {\n fail(file, \"question must be an object\");\n }\n const raw = v as Raw;\n knownKeys(file, \"question\", raw, [\"instructions\", \"criteria\", \"context\"]);\n const instructions = str(file, raw, \"instructions\");\n noEmDash(file, \"question.instructions\", instructions);\n let criteria: Question[\"criteria\"];\n if (raw.criteria !== undefined) {\n if (!isRecord(raw.criteria)) {\n fail(file, \"question.criteria must be an object\");\n }\n const c = raw.criteria as Raw;\n knownKeys(file, \"question.criteria\", c, [\"true\", \"false\"]);\n criteria = {\n false: side(file, \"question.criteria.false\", c.false),\n true: side(file, \"question.criteria.true\", c.true),\n };\n }\n const context = optStrList(file, raw, \"context\") as Question[\"context\"];\n for (const key of context ?? []) {\n oneOf(file, \"question.context\", key, CONTEXT_KEYS);\n }\n return { context, criteria, instructions };\n};\n\nexport const mechanical = (file: string, v: unknown): Mechanical => {\n if (!isRecord(v)) {\n fail(file, \"mechanical must be an object\");\n }\n const raw = v as Raw;\n knownKeys(file, \"mechanical\", raw, [\n \"regex\",\n \"flags\",\n \"phrases\",\n \"minMatches\",\n \"absent\",\n ]);\n const out: Mechanical = {};\n if (raw.flags !== undefined && typeof raw.flags !== \"string\") {\n fail(file, \"mechanical.flags must be a string\");\n }\n if (raw.regex !== undefined) {\n out.regex = str(file, raw, \"regex\");\n out.flags = (raw.flags as string | undefined) ?? \"gu\";\n try {\n const compiled = new RegExp(out.regex, out.flags);\n void compiled;\n } catch (error) {\n fail(\n file,\n `mechanical.regex does not compile: ${(error as Error).message}`\n );\n }\n }\n if (raw.phrases !== undefined) {\n out.phrases = optStrList(file, raw, \"phrases\");\n if (out.phrases?.length === 0) {\n fail(file, \"mechanical.phrases must not be empty\");\n }\n for (const phrase of out.phrases ?? []) {\n noEmDash(file, \"mechanical.phrases\", phrase);\n }\n }\n if (raw.minMatches !== undefined) {\n if (!Number.isInteger(raw.minMatches) || (raw.minMatches as number) < 1) {\n fail(file, \"mechanical.minMatches must be a positive integer\");\n }\n out.minMatches = raw.minMatches as number;\n }\n if (raw.absent !== undefined) {\n out.absent = str(file, raw, \"absent\");\n try {\n const compiled = new RegExp(out.absent, out.flags ?? \"gu\");\n void compiled;\n } catch (error) {\n fail(\n file,\n `mechanical.absent does not compile: ${(error as Error).message}`\n );\n }\n if (!out.regex) {\n fail(file, \"mechanical.absent needs a regex to pair with\");\n }\n }\n if (!(out.regex || out.phrases)) {\n fail(file, \"mechanical needs regex or phrases\");\n }\n return out;\n};\n\nexport const preconditions = (file: string, v: unknown): Preconditions => {\n if (!isRecord(v)) {\n fail(file, \"preconditions must be an object\");\n }\n const raw = v as Raw;\n knownKeys(file, \"preconditions\", raw, [\n \"notInCode\",\n \"docType\",\n \"role\",\n \"smartQuotesAtBuild\",\n ]);\n const out: Preconditions = {};\n if (raw.notInCode !== undefined) {\n if (raw.notInCode !== true) {\n fail(file, \"preconditions.notInCode may only be true\");\n }\n out.notInCode = true;\n }\n if (raw.docType !== undefined) {\n out.docType = (optStrList(file, raw, \"docType\") ?? []).map((d) =>\n oneOf(file, \"preconditions.docType\", d, DOC_TYPES)\n );\n }\n if (raw.role !== undefined) {\n out.role = (optStrList(file, raw, \"role\") ?? []).map((r) =>\n oneOf(file, \"preconditions.role\", r, ROLES)\n );\n }\n if (raw.smartQuotesAtBuild !== undefined) {\n if (raw.smartQuotesAtBuild !== false) {\n fail(file, \"preconditions.smartQuotesAtBuild may only be false\");\n }\n out.smartQuotesAtBuild = false;\n }\n return out;\n};\n\n// Which files a unit kind can come from. A rule names `scope.include` only\n// when the unit alone does not say (a `source` rule over .ts, .css or .html).\nconst INCLUDE_BY_KIND: Record<UnitKind, string[]> = {\n \"attr-string\": [\"**/*.tsx\", \"**/*.jsx\", \"**/*.mdx\"],\n \"class-list\": [\"**/*.tsx\", \"**/*.jsx\"],\n element: [\"**/*.tsx\", \"**/*.jsx\"],\n file: [],\n heading: [\"**/*.md\", \"**/*.mdx\"],\n \"jsx-text\": [\"**/*.tsx\", \"**/*.jsx\"],\n paragraph: [\"**/*.md\", \"**/*.mdx\"],\n source: [],\n};\n\n// Every rule skips tests, stories and changelogs; a rule adds to this list,\n// never repeats it.\nexport const RULE_EXCLUDE = [\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/*.stories.*\",\n \"**/CHANGELOG.md\",\n];\n\nexport const scopeFor = (\n file: string,\n unit: UnitKind[],\n v: unknown\n): Rule[\"scope\"] => {\n let include: string[] | undefined;\n let exclude: string[] = [];\n if (v !== undefined) {\n if (!isRecord(v)) {\n fail(file, \"scope must be an object\");\n }\n knownKeys(file, \"scope\", v as Raw, [\"include\", \"exclude\"]);\n include = optStrList(file, v as Raw, \"include\");\n exclude = optStrList(file, v as Raw, \"exclude\") ?? [];\n }\n if (!include) {\n if (unit.includes(\"source\")) {\n fail(file, \"a source rule needs scope.include (which file types)\");\n }\n include = [...new Set(unit.flatMap((kind) => INCLUDE_BY_KIND[kind]))];\n }\n if (include.length === 0) {\n fail(file, \"scope.include needs at least one glob\");\n }\n return { exclude: [...new Set([...RULE_EXCLUDE, ...exclude])], include };\n};\n\nexport const fix = (file: string, v: unknown): Fix => {\n if (!isRecord(v)) {\n fail(file, \"fix must be an object\");\n }\n const raw = v as Raw;\n knownKeys(file, \"fix\", raw, [\"hint\", \"function\"]);\n const hint = str(file, raw, \"hint\");\n noEmDash(file, \"fix.hint\", hint);\n const out: Fix = { hint };\n if (raw.function !== undefined) {\n out.function = str(file, raw, \"function\");\n if (!(out.function in FIXES)) {\n fail(\n file,\n `fix.function ${out.function} is not registered in src/reduce/fixes.ts`\n );\n }\n }\n return out;\n};\n","// Fail-closed rule validation. Any problem throws with the file path so a bad\n// rule aborts the run before a single request is made. Field validators live\n// in validate-sections.ts.\n\nimport { RULE_STATUSES, SEVERITIES, UNIT_KINDS } from \"../types.js\";\nimport type { Rule, Severity } from \"../types.js\";\nimport { CATEGORY_BY_ID } from \"./taxonomy.js\";\nimport {\n fail,\n fix,\n isRecord,\n knownKeys,\n mechanical,\n noEmDash,\n oneOf,\n optNumber,\n optStrList,\n preconditions,\n question,\n scopeFor,\n str,\n} from \"./validate-sections.js\";\nimport type { Raw } from \"./validate-sections.js\";\n\nconst KEBAB = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nexport const DEFAULT_THRESHOLDS: Rule[\"thresholds\"] = {\n act: 0.7,\n review: 0.35,\n};\n\n// The tier is a fact about the rule, not a choice: a mechanical part alone\n// decides in code, a question alone asks Jev, both together make the\n// mechanical part a candidate filter.\nexport const tierOf = (\n mech: Rule[\"mechanical\"] | Rule[\"check\"],\n q: Rule[\"question\"]\n): Rule[\"tier\"] => {\n if (mech) {\n return q ? \"both\" : \"mechanical\";\n }\n return \"jev\";\n};\n\nexport const validateRule = (\n raw: unknown,\n file: string,\n expectedId: string\n): Rule => {\n if (!isRecord(raw)) {\n fail(file, \"rule must be a mapping\");\n }\n const r = raw as Raw;\n knownKeys(file, \"rule\", r, [\n \"id\",\n \"title\",\n \"categoryId\",\n \"source\",\n \"scope\",\n \"unit\",\n \"mechanical\",\n \"question\",\n \"thresholds\",\n \"severity\",\n \"fix\",\n \"preconditions\",\n \"status\",\n \"handWritten\",\n ]);\n const id = str(file, r, \"id\");\n if (!KEBAB.test(id)) {\n fail(file, \"id must be kebab-case\");\n }\n if (id !== expectedId) {\n fail(file, `id ${id} does not match filename ${expectedId}`);\n }\n const title = str(file, r, \"title\");\n noEmDash(file, \"title\", title);\n const categoryId = str(file, r, \"categoryId\");\n const category = CATEGORY_BY_ID.get(categoryId);\n if (!category) {\n fail(file, `unknown categoryId ${categoryId}`);\n }\n const domain = category?.domain as Rule[\"domain\"];\n if (!id.startsWith(`${domain}-`)) {\n fail(file, `id must start with ${domain}- (the domain of ${categoryId})`);\n }\n if (!isRecord(r.source)) {\n fail(file, \"source must be an object\");\n }\n const s = r.source as Raw;\n knownKeys(file, \"source\", s, [\"repo\", \"path\", \"line\", \"ruleId\"]);\n const source: Rule[\"source\"] = {\n line: optNumber(file, s, \"line\", 1),\n path: str(file, s, \"path\"),\n repo: str(file, s, \"repo\"),\n };\n if (s.ruleId !== undefined) {\n source.ruleId = str(file, s, \"ruleId\");\n }\n const unit = (optStrList(file, r, \"unit\") ?? []).map((u) =>\n oneOf(file, \"unit\", u, UNIT_KINDS)\n );\n if (unit.length === 0) {\n fail(file, \"unit needs at least one kind\");\n }\n const scope = scopeFor(file, unit, r.scope);\n const mech =\n r.mechanical === undefined ? undefined : mechanical(file, r.mechanical);\n const q = r.question === undefined ? undefined : question(file, r.question);\n // Jev never sees a whole file: a source rule is mechanical and nothing else.\n if (unit.includes(\"source\") && (q || !mech || unit.length > 1)) {\n fail(\n file,\n \"unit source needs a mechanical section, no question and no other unit kind\"\n );\n }\n const status = oneOf(file, \"status\", r.status ?? \"active\", RULE_STATUSES);\n if (!(mech || q) && status !== \"draft\") {\n fail(\n file,\n \"needs a mechanical section or a question unless status is draft (a check that counts or measures is a code rule in src/rules/code)\"\n );\n }\n let thresholds = DEFAULT_THRESHOLDS;\n if (r.thresholds !== undefined) {\n if (!isRecord(r.thresholds)) {\n fail(file, \"thresholds must be an object\");\n }\n const t = r.thresholds as Raw;\n knownKeys(file, \"thresholds\", t, [\"act\", \"review\"]);\n const act = optNumber(file, t, \"act\", DEFAULT_THRESHOLDS.act);\n const review = optNumber(file, t, \"review\", DEFAULT_THRESHOLDS.review);\n if (!(review >= 0 && review < act && act <= 1)) {\n fail(file, \"thresholds need 0 <= review < act <= 1\");\n }\n thresholds = { act, review };\n }\n const severity = oneOf<Severity>(file, \"severity\", r.severity, SEVERITIES);\n const f = fix(file, r.fix);\n const pre =\n r.preconditions === undefined\n ? undefined\n : preconditions(file, r.preconditions);\n const handWritten = optStrList(file, r, \"handWritten\") ?? [];\n return {\n categoryId,\n domain,\n file,\n fix: f,\n handWritten,\n id,\n mechanical: mech,\n preconditions: pre,\n question: q,\n scope,\n severity,\n source,\n status,\n thresholds: { ...thresholds },\n tier: tierOf(mech, q),\n title,\n unit,\n };\n};\n","// The one constructor every code rule goes through: fills the defaults a YAML\n// rule would carry and attaches the check.\n\nimport type {\n MechanicalHit,\n Question,\n Rule,\n RuleSource,\n Severity,\n Unit,\n UnitKind,\n} from \"../../types.js\";\nimport { CATEGORY_BY_ID } from \"../taxonomy.js\";\nimport { scopeFor } from \"../validate-sections.js\";\nimport { DEFAULT_THRESHOLDS, tierOf } from \"../validate.js\";\n\nexport interface CodeRuleSpec {\n id: string;\n title: string;\n categoryId: string;\n source: RuleSource;\n unit: UnitKind[];\n severity?: Severity;\n /** Only when the unit kinds do not say which files (see scopeFor). */\n scope?: { include?: string[]; exclude?: string[] };\n preconditions?: Rule[\"preconditions\"];\n status?: Rule[\"status\"];\n hint: string;\n check: (unit: Unit) => MechanicalHit;\n /** Present when the check is a candidate filter and Jev decides (`tier: both`). */\n question?: Question;\n thresholds?: Rule[\"thresholds\"];\n}\n\nexport const codeRule = (spec: CodeRuleSpec, module: string): Rule => {\n const file = `code:${module}`;\n const category = CATEGORY_BY_ID.get(spec.categoryId);\n if (!category) {\n throw new Error(\n `Invalid rule ${file}: unknown categoryId ${spec.categoryId}`\n );\n }\n return {\n categoryId: spec.categoryId,\n check: spec.check,\n domain: category.domain as Rule[\"domain\"],\n file,\n fix: { hint: spec.hint },\n handWritten: [],\n id: spec.id,\n preconditions: spec.preconditions,\n question: spec.question,\n scope: scopeFor(file, spec.unit, spec.scope),\n severity: spec.severity ?? \"minor\",\n source: spec.source,\n status: spec.status ?? (spec.question ? \"review-only\" : \"active\"),\n thresholds: spec.thresholds ?? { ...DEFAULT_THRESHOLDS },\n tier: tierOf(spec.check, spec.question),\n title: spec.title,\n unit: spec.unit,\n };\n};\n","import { matchesAny } from \"../../lib/glob.js\";\nimport { none, UnresolvedError } from \"../../reduce/mechanical.js\";\nimport type { MechanicalHit, Unit } from \"../../types.js\";\nimport { codeRule } from \"./rule.js\";\n\nconst make = (\n name: string,\n title: string,\n check: (u: Unit) => MechanicalHit,\n hint: string\n) =>\n codeRule(\n {\n categoryId: \"repository-contracts\",\n check,\n hint,\n id: `architecture-${name}`,\n scope: { include: [\"**/*.{ts,tsx,js,jsx,mjs,cjs,mts,cts}\"] },\n source: {\n line: 1,\n path: \"skills/codebase-architecture/references/guardrail-tooling.md\",\n repo: \"mblode/agent-skills\",\n },\n status: \"review-only\",\n title,\n unit: [\"source\"],\n },\n \"src/rules/code/architecture.ts\"\n );\n\nexport const ARCHITECTURE_RULES = [\n make(\n \"declared-import-boundary\",\n \"Import violates a declared module boundary\",\n (u) => {\n const boundaries = u.facts?.repository.policy?.boundaries?.filter((b) =>\n matchesAny(u.file, [b.from])\n );\n if (!boundaries?.length) {\n return none;\n }\n if (!u.facts?.imports) {\n throw new UnresolvedError(\n u.facts?.parseError ?? \"Import facts unavailable\"\n );\n }\n for (const item of u.facts.imports) {\n const resolved = item.name.startsWith(\".\")\n ? u.facts.repository.resolve(u.file, item.name)\n : undefined;\n const boundary = boundaries.find(\n (b) =>\n matchesAny(item.name, [b.disallow]) ||\n (resolved !== undefined && matchesAny(resolved, [b.disallow]))\n );\n if (boundary) {\n return {\n evidence: `${item.name}: ${boundary.reason}`,\n fired: true,\n offset: item.offset,\n };\n }\n }\n return none;\n },\n \"Use the declared public interface or change the explicit architecture policy with its owner. Patterns match import specifiers and repository-relative paths for relative imports.\"\n ),\n make(\n \"deprecated-import\",\n \"Import uses a declared deprecated API\",\n (u) => {\n const deprecated = u.facts?.repository.policy?.deprecatedImports;\n if (!deprecated || Object.keys(deprecated).length === 0) {\n return none;\n }\n if (!u.facts?.imports) {\n throw new UnresolvedError(\n u.facts?.parseError ?? \"Import facts unavailable\"\n );\n }\n for (const item of u.facts.imports) {\n const replacement = deprecated[item.name];\n if (replacement) {\n return {\n evidence: `${item.name}: use ${replacement}`,\n fired: true,\n offset: item.offset,\n };\n }\n }\n return none;\n },\n \"Use the replacement named in the repository's deprecation contract.\"\n ),\n make(\n \"generated-regeneration-hint\",\n \"Declared generated file has no regeneration guidance\",\n (u) => {\n const generated = u.facts?.repository.policy?.generated;\n if (!generated?.length || !matchesAny(u.file, generated)) {\n return none;\n }\n const banner = u.text.split(\"\\n\").slice(0, 12).join(\"\\n\");\n return /generat/i.test(banner) &&\n /(?:regenerat|npm run|pnpm |yarn |bun |codegen|protoc)/i.test(banner)\n ? none\n : {\n evidence:\n \"Declared generated output lacks a regeneration hint in its header\",\n fired: true,\n offset: 0,\n };\n },\n \"Have the generator emit a banner naming the regeneration command or canonical instructions.\"\n ),\n];\n","// Motion utilities (from the ui-animation skill's flag-on-sight table) and\n// design-system hygiene (the shadcn/lint rules) over an element's own class\n// list. Variants are stripped so `hover:ease-in` counts as `ease-in`.\n\nimport { baseClass, hit, none } from \"../../reduce/mechanical.js\";\nimport type { Rule, Unit } from \"../../types.js\";\nimport { codeRule } from \"./rule.js\";\n\nconst MODULE = \"src/rules/code/classes.ts\";\nconst ANIMATION = \"skills/ui-animation/references\";\n\nconst bases = (unit: Unit): string[] => (unit.classes ?? []).map(baseClass);\n\nconst animates = (list: string[]): boolean =>\n list.some(\n (c) =>\n c.startsWith(\"transition\") ||\n c.startsWith(\"duration-\") ||\n (c.startsWith(\"animate-\") && c !== \"animate-none\")\n );\n\nconst durationMs = (cls: string): number | undefined => {\n const named = cls.match(/^duration-(\\d+)$/u);\n if (named) {\n return Number(named[1]);\n }\n const arbitrary = cls.match(/^duration-\\[(\\d+(?:\\.\\d+)?)(ms|s)\\]$/u);\n if (arbitrary) {\n return Number(arbitrary[1]) * (arbitrary[2] === \"s\" ? 1000 : 1);\n }\n return undefined;\n};\n\nconst PALETTE =\n /^(?:bg|text|border|ring|fill|stroke|from|via|to|outline|shadow|accent|caret|decoration|divide|placeholder)-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-\\d{2,3}(?:\\/\\d{1,3})?$/u;\n\nconst rule = (spec: Parameters<typeof codeRule>[0]): Rule =>\n codeRule(spec, MODULE);\n\nconst motion = (\n spec: Omit<Parameters<typeof codeRule>[0], \"unit\" | \"source\"> & {\n source: { path: string; line: number };\n }\n): Rule =>\n rule({\n ...spec,\n source: { ...spec.source, repo: \"mblode/agent-skills\" },\n unit: [\"class-list\"],\n });\n\n// The registry's own components are exempt: they are the design system.\nconst shadcn = (\n spec: Omit<\n Parameters<typeof codeRule>[0],\n \"unit\" | \"source\" | \"scope\" | \"status\"\n > & {\n ruleId: string;\n }\n): Rule =>\n rule({\n ...spec,\n scope: { exclude: [\"**/components/ui/**\"] },\n source: {\n line: 1,\n path: \"README.md\",\n repo: \"shadcn-ui/lint\",\n ruleId: spec.ruleId,\n },\n status: \"review-only\",\n unit: [\"class-list\"],\n });\n\nexport const CLASS_RULES: Rule[] = [\n motion({\n categoryId: \"easing-and-duration\",\n check: (unit) => {\n const list = bases(unit);\n return list.includes(\"ease-in\") && animates(list) ? hit(\"ease-in\") : none;\n },\n hint: \"Swap ease-in for a strong ease-out (ease-out or a custom curve). The same duration reads as faster because the movement is visible at once.\",\n id: \"motion-ease-in-on-transition\",\n source: { line: 27, path: `${ANIMATION}/debugging-symptoms.md` },\n title: \"Transition eases in, so it starts slow while the user is watching\",\n }),\n motion({\n categoryId: \"easing-and-duration\",\n check: (unit) => {\n const list = bases(unit);\n if (!list.includes(\"ease-linear\") || !animates(list)) {\n return none;\n }\n const constant = list.some(\n (c) => c === \"animate-spin\" || c.includes(\"marquee\")\n );\n return constant ? none : hit(\"ease-linear\");\n },\n hint: \"Nothing physical moves at constant speed. Use ease-out for enter and exit and ease-in-out for on-screen movement; keep ease-linear for spinners, marquees and scrubbed scroll.\",\n id: \"motion-linear-easing-on-transition\",\n source: { line: 37, path: `${ANIMATION}/debugging-symptoms.md` },\n title: \"Linear easing on motion that is not a spinner or marquee\",\n }),\n motion({\n categoryId: \"easing-and-duration\",\n check: (unit) => {\n const list = bases(unit);\n if (!list.some((c) => c.startsWith(\"transition\"))) {\n return none;\n }\n const slow = list.filter((c) => (durationMs(c) ?? 0) > 300);\n return slow.length > 0 ? hit(slow.join(\" \")) : none;\n },\n hint: \"Cut the duration. A 180ms dropdown feels more responsive than a 400ms one; only a very steep curve earns a long duration.\",\n id: \"motion-duration-over-300ms\",\n source: { line: 29, path: `${ANIMATION}/debugging-symptoms.md` },\n title: \"Transition longer than 300ms on product UI\",\n }),\n motion({\n categoryId: \"motion-restraint\",\n check: (unit) =>\n bases(unit).includes(\"transition-all\") ? hit(\"transition-all\") : none,\n hint: \"Name the properties: transition-transform, transition-opacity or transition-colors. transition-all also animates width, height and margin off the GPU.\",\n id: \"motion-transition-all\",\n source: { line: 58, path: `${ANIMATION}/review-format.md` },\n title: \"transition-all animates every property, layout included\",\n }),\n motion({\n categoryId: \"spatial-continuity\",\n check: (unit) => {\n const list = bases(unit);\n const zero = list.filter((c) => c === \"scale-0\" || c === \"zoom-in-0\");\n return zero.length > 0 && animates(list) ? hit(zero.join(\" \")) : none;\n },\n hint: \"Start from scale-95 (0.9 to 0.96) plus opacity. Nothing real appears from nothing; a near-full start reads as already there.\",\n id: \"motion-scale-from-zero\",\n source: { line: 46, path: `${ANIMATION}/debugging-symptoms.md` },\n title: \"Entrance from scale zero\",\n }),\n motion({\n categoryId: \"motion-restraint\",\n // Any animate-* utility with no motion-reduce or motion-safe variant on the\n // element: the animation runs for users who asked for less motion.\n check: (unit) => {\n const classes = unit.classes ?? [];\n const animated = classes\n .map(baseClass)\n .filter((c) => c.startsWith(\"animate-\") && c !== \"animate-none\");\n if (animated.length === 0) {\n return none;\n }\n const guarded = classes.some(\n (c) => c.startsWith(\"motion-reduce:\") || c.startsWith(\"motion-safe:\")\n );\n return guarded ? none : hit(animated.join(\" \"));\n },\n hint: \"Gate the animation with motion-safe:animate-* or pair it with motion-reduce:animate-none so users who asked for less motion get less.\",\n id: \"motion-animate-without-reduced-motion\",\n source: { line: 57, path: `${ANIMATION}/live-tuning.md` },\n title: \"Animation with no reduced-motion variant\",\n }),\n shadcn({\n categoryId: \"colour-system\",\n check: (unit) => {\n const found = bases(unit).filter((c) => PALETTE.test(c));\n return found.length > 0 ? hit(found.join(\" \")) : none;\n },\n hint: \"Use the theme token (bg-primary, text-muted-foreground, border-destructive). A raw bg-pink-500 escapes the colour system and ignores dark mode.\",\n id: \"craft-raw-colour-class\",\n ruleId: \"shadcn/no-raw-colors\",\n title: \"Palette colour with a numeric shade instead of a theme token\",\n }),\n shadcn({\n categoryId: \"look-constraints\",\n // Selector variants such as `[&>svg]:` are variants, not values. The\n // typography pack reads arbitrary values on purpose; this is the\n // design-system view of the same class.\n check: (unit) => {\n const found = bases(unit).filter((c) => /-\\[[^\\]]+\\]/u.test(c));\n return found.length > 0 ? hit(found.join(\" \")) : none;\n },\n hint: \"Step the scale (p-3, text-sm, rounded-md) or register the value in the theme so the next component can reach it by name. p-[13px] is a nudge, not a decision.\",\n id: \"craft-arbitrary-value-class\",\n ruleId: \"shadcn/no-arbitrary-values\",\n title: \"Arbitrary value in a utility class\",\n }),\n shadcn({\n categoryId: \"look-constraints\",\n check: (unit) =>\n unit.context.interpolated ? hit((unit.classes ?? []).join(\" \")) : none,\n hint: \"Tailwind only generates classes it can read in full. Map the variable to complete class names (a lookup object or cva variants) instead of interpolating a colour into bg-...-500.\",\n id: \"craft-interpolated-class-string\",\n ruleId: \"shadcn/require-static-classes\",\n title: \"Class name built from a template expression\",\n }),\n];\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { fromMarkdown } from \"mdast-util-from-markdown\";\nimport { gfmFromMarkdown } from \"mdast-util-gfm\";\nimport { gfm } from \"micromark-extension-gfm\";\nimport { parseSync } from \"oxc-parser\";\n\nimport type { ArchitecturePolicy } from \"../types.js\";\n\nexport interface DocumentNode {\n type: string;\n value?: string;\n url?: string;\n identifier?: string;\n depth?: number;\n lang?: string | null;\n children?: DocumentNode[];\n position?: { start: { offset?: number }; end: { offset?: number } };\n}\n\nexport interface ImportFact {\n name: string;\n offset: number;\n typeOnly: boolean;\n}\n\nexport interface SourceFacts {\n document?: DocumentNode;\n imports?: ImportFact[];\n parseError?: string;\n repository: Pick<\n Repository,\n \"root\" | \"read\" | \"resolve\" | \"exists\" | \"manifest\" | \"policy\"\n >;\n}\n\nexport const descendants = (node: DocumentNode): DocumentNode[] => [\n node,\n ...(node.children ?? []).flatMap(descendants),\n];\nexport const nodeText = (node: DocumentNode): string =>\n node.value ?? (node.children ?? []).map(nodeText).join(\"\");\n\nexport class Repository {\n readonly root: string;\n private readonly contents = new Map<string, string | undefined>();\n\n readonly policy?: ArchitecturePolicy;\n\n constructor(root: string, policy?: ArchitecturePolicy) {\n this.policy = policy;\n this.root = fs.realpathSync(root);\n }\n\n resolve(file: string, target: string): string | undefined {\n const abs = path.resolve(this.root, path.dirname(file), target);\n const relative = path.relative(this.root, abs);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n return undefined;\n }\n return relative.split(path.sep).join(\"/\");\n }\n\n read(file: string): string | undefined {\n if (this.contents.has(file)) {\n return this.contents.get(file);\n }\n let text: string | undefined;\n try {\n const abs = fs.realpathSync(path.resolve(this.root, file));\n const relative = path.relative(this.root, abs);\n if (!relative.startsWith(\"..\") && !path.isAbsolute(relative)) {\n text = fs.readFileSync(abs, \"utf-8\");\n }\n } catch {\n text = undefined;\n }\n this.contents.set(file, text);\n return text;\n }\n\n exists(file: string): boolean {\n try {\n const real = fs.realpathSync(path.resolve(this.root, file));\n const relative = path.relative(this.root, real);\n return !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n } catch {\n return false;\n }\n }\n\n manifest(\n file: string\n ): { file: string; value: Record<string, unknown> } | undefined {\n let dir = path.dirname(file);\n while (true) {\n const name = path.posix.join(dir, \"package.json\");\n const source = this.read(name);\n if (source !== undefined) {\n try {\n const value: unknown = JSON.parse(source);\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return { file: name, value: value as Record<string, unknown> };\n }\n } catch {\n return undefined;\n }\n }\n if (dir === \".\") {\n return undefined;\n }\n dir = path.dirname(dir);\n }\n }\n}\n\ntype Ast = Record<string, unknown>;\nconst importsFrom = (value: unknown, output: ImportFact[]): void => {\n if (!value || typeof value !== \"object\") {\n return;\n }\n if (Array.isArray(value)) {\n for (const child of value) {\n importsFrom(child, output);\n }\n return;\n }\n const node = value as Ast;\n const source = node.source as Ast | undefined;\n if (\n [\n \"ImportDeclaration\",\n \"ExportNamedDeclaration\",\n \"ExportAllDeclaration\",\n \"ImportExpression\",\n ].includes(String(node.type)) &&\n typeof source?.value === \"string\"\n ) {\n const specifiers = node.specifiers as Ast[] | undefined;\n output.push({\n name: source.value,\n offset: Number(node.start ?? 0),\n typeOnly:\n node.importKind === \"type\" ||\n node.exportKind === \"type\" ||\n Boolean(\n specifiers?.length && specifiers.every((s) => s.importKind === \"type\")\n ),\n });\n }\n for (const [key, child] of Object.entries(node)) {\n if (key !== \"comments\") {\n importsFrom(child, output);\n }\n }\n};\n\nexport const sourceFacts = (\n file: string,\n text: string,\n repository: Repository\n): SourceFacts => {\n const facts: SourceFacts = { repository };\n if (/\\.mdx?$/.test(file)) {\n facts.document = fromMarkdown(\n text.replace(/^---\\r?\\n[\\s\\S]*?\\r?\\n---(?=\\r?\\n|$)/, (m) =>\n m.replaceAll(/[^\\r\\n]/g, \" \")\n ),\n { extensions: [gfm()], mdastExtensions: [gfmFromMarkdown()] }\n ) as DocumentNode;\n }\n if (/\\.[cm]?[jt]sx?$/.test(file)) {\n try {\n const parsed = parseSync(file, text);\n if (parsed.errors.length) {\n facts.parseError = \"Source could not be parsed\";\n } else {\n facts.imports = [];\n importsFrom(parsed.program, facts.imports);\n }\n } catch {\n facts.parseError = \"Source could not be parsed\";\n }\n }\n return facts;\n};\n","import { parse } from \"yaml\";\n\nimport { descendants, nodeText } from \"../../analysis/repository.js\";\nimport type { DocumentNode } from \"../../analysis/repository.js\";\nimport { none, UnresolvedError } from \"../../reduce/mechanical.js\";\nimport type { MechanicalHit, Unit } from \"../../types.js\";\nimport { codeRule } from \"./rule.js\";\n\nconst at = (node: DocumentNode, evidence: string): MechanicalHit => ({\n evidence,\n fired: true,\n offset: node.position?.start.offset ?? 0,\n});\nconst document = (unit: Unit): DocumentNode => {\n if (!unit.facts?.document) {\n throw new UnresolvedError(\"Markdown structure unavailable\");\n }\n return unit.facts.document;\n};\nconst nodes = (unit: Unit) => descendants(document(unit));\nconst make = (\n name: string,\n title: string,\n source: string,\n include: string[],\n check: (unit: Unit) => MechanicalHit,\n hint: string,\n authoring = false\n) =>\n codeRule(\n {\n categoryId: authoring ? \"instruction-quality\" : \"reference-reading\",\n check,\n hint,\n id: `${authoring ? \"authoring\" : \"copywriting\"}-${name}`,\n scope: { include },\n source: {\n line: 1,\n path: `skills/${source}`,\n repo: \"mblode/agent-skills\",\n },\n status: \"review-only\",\n title,\n unit: [\"source\"],\n },\n \"src/rules/code/documents.ts\"\n );\nconst README = [\"**/README.md\"];\nconst INSTRUCTIONS = [\"**/AGENTS.md\", \"**/CLAUDE.md\", \"**/SKILL.md\"];\nconst DOCS = [\"**/*.md\"];\nconst README_SOURCE = \"readme-creator/references/quality-checklist.md\";\n\nexport const DOCUMENT_RULES = [\n make(\n \"readme-scaffold\",\n \"README still contains scaffold instructions\",\n README_SOURCE,\n README,\n (u) => {\n const n = nodes(u).find(\n (candidate) =>\n candidate.type === \"paragraph\" &&\n /This is a \\[?Next\\.js.*bootstrapped with|This template provides a minimal setup to get React working in Vite/i.test(\n nodeText(candidate)\n )\n );\n return n ? at(n, \"Default scaffold introduction\") : none;\n },\n \"Replace scaffold instructions with what the product does and how a consumer uses it.\"\n ),\n make(\n \"readme-description\",\n \"README has no introductory description\",\n README_SOURCE,\n README,\n (u) => {\n const children = document(u).children ?? [];\n const stop = children.findIndex(\n (n) => n.type === \"heading\" && (n.depth ?? 0) > 1\n );\n const intro = children.slice(0, stop === -1 ? children.length : stop);\n const prose = intro.some(\n (n) => n.type === \"paragraph\" && nodeText(n).trim().length > 0\n );\n return prose\n ? none\n : {\n evidence: \"No introductory prose before the first section\",\n fired: true,\n offset: 0,\n };\n },\n \"Explain what a reader can do with the product before listing setup steps.\"\n ),\n make(\n \"readme-quickstart-elision\",\n \"Quickstart example contains an unfinished placeholder\",\n README_SOURCE,\n README,\n (u) => {\n let heading = \"\";\n for (const n of document(u).children ?? []) {\n if (n.type === \"heading\") {\n heading = nodeText(n);\n }\n if (\n n.type === \"code\" &&\n /quick\\s?start|getting started/i.test(heading) &&\n /^\\s*(?:\\.\\.\\.|\\/\\/\\s*(?:TODO|your code here)|#\\s*TODO)\\s*$/m.test(\n n.value ?? \"\"\n )\n ) {\n return at(n, \"Quickstart contains an elided implementation\");\n }\n }\n return none;\n },\n \"Provide a complete first-run example; move intentionally partial examples to a tutorial.\"\n ),\n make(\n \"document-empty-heading\",\n \"A section has no content\",\n \"docs-writing/rules/structure-no-filler-sections.md\",\n DOCS,\n (u) => {\n const children = document(u).children ?? [];\n for (const [i, n] of children.entries()) {\n if (n.type !== \"heading\") {\n continue;\n }\n const next = children[i + 1];\n if (\n !next ||\n (next.type === \"heading\" && (next.depth ?? 0) <= (n.depth ?? 0))\n ) {\n return at(n, `Empty section: ${nodeText(n)}`);\n }\n }\n return none;\n },\n \"Add the section's content or remove its heading.\"\n ),\n make(\n \"document-heading-order\",\n \"Heading skips a structural level\",\n \"docs-writing/rules/format-semantic-html.md\",\n DOCS,\n (u) => {\n let previous = 0;\n for (const n of nodes(u).filter(\n (candidate) => candidate.type === \"heading\"\n )) {\n const depth = n.depth ?? 1;\n if (previous > 0 && depth > previous + 1) {\n return at(n, `Heading level jumps from ${previous} to ${depth}`);\n }\n previous = depth;\n }\n return none;\n },\n \"Nest heading levels in order so the document outline reflects its structure.\"\n ),\n make(\n \"document-broken-local-link\",\n \"Document links to a missing local file\",\n \"docs-writing/rules/review-verify-links.md\",\n DOCS,\n (u) => {\n const repo = u.facts!.repository;\n for (const n of nodes(u).filter((candidate) =>\n [\"link\", \"image\", \"definition\"].includes(candidate.type)\n )) {\n const url = n.url ?? \"\";\n if (!url || /^(?:[a-z][\\w+.-]*:|\\/|#)/i.test(url)) {\n continue;\n }\n let target: string;\n try {\n target = decodeURIComponent(url.split(/[?#]/)[0]);\n } catch {\n return at(n, \"Malformed URL encoding in local link\");\n }\n // Extensionless docs routes and generated web URLs need the site's resolver.\n if (!/\\.(?:md|mdx|png|jpe?g|svg|gif|webp|pdf)$/i.test(target)) {\n continue;\n }\n const resolved = repo.resolve(u.file, target);\n if (resolved === undefined) {\n throw new UnresolvedError(\"Link points outside the repository\");\n }\n if (!repo.exists(resolved)) {\n return at(n, `Missing local target: ${target}`);\n }\n }\n return none;\n },\n \"Correct the link or provide the referenced file. Generated site routes need a route-aware check.\"\n ),\n make(\n \"instruction-missing-script\",\n \"Instruction invokes an undefined package script\",\n \"agents-md/references/quick-checklist.md\",\n INSTRUCTIONS,\n (u) => {\n const manifest = u.facts!.repository.manifest(u.file);\n if (!manifest) {\n throw new UnresolvedError(\n \"No readable package manifest for this instruction file\"\n );\n }\n const scripts = manifest.value.scripts as\n | Record<string, unknown>\n | undefined;\n for (const n of nodes(u).filter((candidate) =>\n [\"code\", \"inlineCode\"].includes(candidate.type)\n )) {\n for (const m of (n.value ?? \"\").matchAll(/\\bnpm run ([\\w:-]+)\\b/g)) {\n if (/--(?:workspace|prefix)|\\bcd\\s/.test(n.value ?? \"\")) {\n continue;\n }\n if (!scripts || !(m[1] in scripts)) {\n return at(n, `Script ${m[1]} is absent from ${manifest.file}`);\n }\n }\n }\n return none;\n },\n \"Name a script in the applicable package manifest, or state the workspace where the command runs.\",\n true\n ),\n make(\n \"skill-frontmatter\",\n \"Skill frontmatter is missing or invalid\",\n \"agent-skills-creator/references/format-specification.md\",\n [\"**/SKILL.md\"],\n (u) => {\n const match = u.text.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---(?:\\r?\\n|$)/);\n if (!match) {\n return { evidence: \"Missing YAML frontmatter\", fired: true, offset: 0 };\n }\n try {\n const value: unknown = parse(match[1]);\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return {\n evidence: \"Frontmatter must be an object\",\n fired: true,\n offset: 0,\n };\n }\n const fields = value as Record<string, unknown>;\n if (\n typeof fields.name !== \"string\" ||\n !fields.name.trim() ||\n typeof fields.description !== \"string\" ||\n !fields.description.trim()\n ) {\n return {\n evidence: \"Skill needs nonempty name and description\",\n fired: true,\n offset: 0,\n };\n }\n } catch {\n return {\n evidence: \"Frontmatter is not valid YAML\",\n fired: true,\n offset: 0,\n };\n }\n return none;\n },\n \"Supply valid YAML with name and description; run the skill repository's full validator for its remaining conventions.\",\n true\n ),\n make(\n \"readme-license-link\",\n \"README license link points to a missing file\",\n README_SOURCE,\n README,\n (u) => {\n for (const n of nodes(u).filter(\n (candidate) => candidate.type === \"link\"\n )) {\n if (!/^(?:\\.\\/)?LICENSE(?:\\.[\\w-]+)?$/i.test(n.url ?? \"\")) {\n continue;\n }\n const target = u.facts!.repository.resolve(u.file, n.url!);\n if (target && !u.facts!.repository.exists(target)) {\n return at(n, `Missing license target: ${n.url}`);\n }\n }\n return none;\n },\n \"Link to the project's actual license file.\"\n ),\n make(\n \"readme-install-name\",\n \"README installs an old or unrelated package name\",\n README_SOURCE,\n README,\n (u) => {\n const manifest = u.facts!.repository.manifest(u.file);\n if (\n !manifest ||\n manifest.value.private === true ||\n typeof manifest.value.name !== \"string\"\n ) {\n throw new UnresolvedError(\n \"Published package identity is not established\"\n );\n }\n let section = \"\";\n for (const n of document(u).children ?? []) {\n if (n.type === \"heading\") {\n section = nodeText(n);\n }\n if (n.type !== \"code\" || !/^install(?:ation)?$/i.test(section)) {\n continue;\n }\n const command = (n.value ?? \"\").match(\n /^\\s*(?:npm (?:install|i)|pnpm add|yarn add|bun add)\\s+((?:@[\\w.-]+\\/)?[\\w.-]+)(?:@[^\\s]+)?\\s*$/m\n );\n if (command && command[1] !== manifest.value.name) {\n return at(\n n,\n `Install names ${command[1]}; manifest names ${manifest.value.name}`\n );\n }\n }\n return none;\n },\n \"Check the intended distribution package. Keep companion-package and workspace instructions explicit.\"\n ),\n];\n","import { builtinModules } from \"node:module\";\n\nimport { none, UnresolvedError } from \"../../reduce/mechanical.js\";\nimport type { MechanicalHit, Unit } from \"../../types.js\";\nimport { codeRule } from \"./rule.js\";\n\nconst at = (evidence: string, offset = 0): MechanicalHit => ({\n evidence,\n fired: true,\n offset,\n});\nconst object = (value: unknown): Record<string, unknown> =>\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\nconst json = (u: Unit): Record<string, unknown> => {\n try {\n return object(JSON.parse(u.text));\n } catch {\n throw new UnresolvedError(\"JSON is not parseable\");\n }\n};\nconst builtins = new Set([\n ...builtinModules,\n ...builtinModules.map((n) => `node:${n}`),\n]);\nconst make = (\n domain: \"architecture\" | \"dx\",\n id: string,\n title: string,\n include: string[],\n source: string,\n check: (u: Unit) => MechanicalHit,\n hint: string\n) =>\n codeRule(\n {\n categoryId:\n domain === \"dx\" ? \"package-contracts\" : \"repository-contracts\",\n check,\n hint,\n id: `${domain}-${id}`,\n scope: { include },\n source: {\n line: 1,\n path: `skills/${source}`,\n repo: \"mblode/agent-skills\",\n },\n status: \"review-only\",\n title,\n unit: [\"source\"],\n },\n \"src/rules/code/repository.ts\"\n );\nconst GUARD = \"codebase-architecture/references/guardrail-tooling.md\";\nconst PKG = [\"**/package.json\"];\nconst CODE = [\"**/*.{ts,tsx,js,jsx,mjs,cjs,mts,cts}\"];\n\nexport const REPOSITORY_RULES = [\n make(\n \"dx\",\n \"package-entry-target\",\n \"Package entry points to a missing artifact\",\n PKG,\n \"scaffold-cli/references/post-scaffold.md\",\n (u) => {\n const value = json(u);\n const entries: string[] = [];\n for (const key of [\"main\", \"module\", \"types\", \"typings\"]) {\n if (typeof value[key] === \"string\") {\n entries.push(value[key]);\n }\n }\n if (typeof value.bin === \"string\") {\n entries.push(value.bin);\n } else {\n entries.push(\n ...Object.values(object(value.bin)).filter(\n (v): v is string => typeof v === \"string\"\n )\n );\n }\n const visit = (v: unknown): void => {\n if (typeof v === \"string\") {\n entries.push(v);\n } else if (v && typeof v === \"object\") {\n for (const child of Object.values(v)) {\n visit(child);\n }\n }\n };\n visit(value.exports);\n for (const entry of entries) {\n if (entry.includes(\"*\")) {\n continue;\n }\n const resolved = u.facts!.repository.resolve(u.file, entry);\n if (resolved === undefined) {\n return at(`Entry escapes repository: ${entry}`);\n }\n if (!u.facts!.repository.exists(resolved)) {\n if (\n /^(?:\\.\\/)?(?:dist|build|lib)\\//.test(entry) &&\n object(value.scripts).build\n ) {\n throw new UnresolvedError(\n `Build output not available: ${entry}. Build or inspect the packed artifact.`\n );\n }\n return at(`Missing package entry: ${entry}`);\n }\n }\n return none;\n },\n \"Build and inspect the package, then make bin, exports, and declaration paths match its actual artifacts.\"\n ),\n make(\n \"dx\",\n \"package-bin-shebang\",\n \"CLI executable has no Node shebang\",\n PKG,\n \"scaffold-cli/references/scaffold-source.md\",\n (u) => {\n const value = json(u);\n const bins =\n typeof value.bin === \"string\"\n ? [value.bin]\n : Object.values(object(value.bin)).filter(\n (v): v is string => typeof v === \"string\"\n );\n for (const bin of bins) {\n if (!/\\.[cm]?js$/.test(bin)) {\n continue;\n }\n const resolved = u.facts!.repository.resolve(u.file, bin);\n const text =\n resolved === undefined\n ? undefined\n : u.facts!.repository.read(resolved);\n if (text === undefined) {\n throw new UnresolvedError(`CLI artifact unavailable: ${bin}`);\n }\n if (!/^#![^\\n]*\\bnode\\b/.test(text)) {\n return at(`Node CLI lacks shebang: ${bin}`);\n }\n if (/^#![^\\n]*\\n#!/.test(text)) {\n return at(`Duplicate CLI shebang: ${bin}`);\n }\n }\n return none;\n },\n \"Emit exactly one Node shebang in the published executable.\"\n ),\n make(\n \"dx\",\n \"exports-mixed-keys\",\n \"Package exports mixes conditions and subpaths\",\n PKG,\n \"dx-audit/rules/api-stable-contract.md\",\n (u) => {\n const keys = Object.keys(object(json(u).exports));\n return keys.some((k) => k.startsWith(\".\")) &&\n keys.some((k) => !k.startsWith(\".\"))\n ? at(\"Exports mixes subpath keys with condition keys at the same level\")\n : none;\n },\n \"Put conditions inside each exported subpath, or use a conditions-only root export.\"\n ),\n make(\n \"architecture\",\n \"undeclared-import\",\n \"Import has no declared package dependency\",\n CODE,\n GUARD,\n (u) => {\n if (!u.facts?.imports) {\n throw new UnresolvedError(\n u.facts?.parseError ?? \"Import facts unavailable\"\n );\n }\n const manifest = u.facts.repository.manifest(u.file);\n if (!manifest) {\n throw new UnresolvedError(\"No readable package manifest\");\n }\n const value = manifest.value;\n const declared = new Set([\n value.name,\n ...[\n \"dependencies\",\n \"devDependencies\",\n \"peerDependencies\",\n \"optionalDependencies\",\n ].flatMap((key) => Object.keys(object(value[key]))),\n ]);\n for (const item of u.facts.imports) {\n if (\n /^(?:\\.|\\/|#|~|[a-z]+:)/i.test(item.name) ||\n builtins.has(item.name)\n ) {\n continue;\n }\n const name = item.name.startsWith(\"@\")\n ? item.name.split(\"/\").slice(0, 2).join(\"/\")\n : item.name.split(\"/\")[0];\n if (declared.has(name)) {\n continue;\n }\n const tsconfig = u.facts.repository.resolve(\n manifest.file,\n \"tsconfig.json\"\n );\n if (tsconfig && u.facts.repository.exists(tsconfig)) {\n throw new UnresolvedError(\n `Undeclared ${name} may resolve through TypeScript aliases; resolve the project graph`\n );\n }\n return at(\n `Import ${name} is absent from ${manifest.file}`,\n item.offset\n );\n }\n return none;\n },\n \"Declare the dependency in the consuming package, or configure its alias resolution.\"\n ),\n make(\n \"architecture\",\n \"cross-package-relative-import\",\n \"Relative import bypasses a package boundary\",\n CODE,\n GUARD,\n (u) => {\n if (!u.facts?.imports) {\n throw new UnresolvedError(\n u.facts?.parseError ?? \"Import facts unavailable\"\n );\n }\n const own = u.facts.repository.manifest(u.file);\n if (!own) {\n throw new UnresolvedError(\"No readable package manifest\");\n }\n for (const item of u.facts.imports.filter((i) =>\n i.name.startsWith(\".\")\n )) {\n const target = u.facts.repository.resolve(u.file, item.name);\n if (!target) {\n continue;\n }\n const other = u.facts.repository.manifest(target);\n if (other && other.file !== own.file) {\n return at(\n `Relative import crosses from ${own.file} to ${other.file}: ${item.name}`,\n item.offset\n );\n }\n }\n return none;\n },\n \"Import through the sibling package's public entry and declare the dependency, unless an explicit workspace convention permits this edge.\"\n ),\n make(\n \"architecture\",\n \"missing-tsconfig-reference\",\n \"TypeScript project reference points to a missing target\",\n [\"**/tsconfig*.json\"],\n GUARD,\n (u) => {\n // JSONC needs the TypeScript parser; do not mistake it for invalid configuration.\n const value = json(u);\n for (const entry of Array.isArray(value.references)\n ? value.references\n : []) {\n const target = object(entry).path;\n if (typeof target !== \"string\") {\n continue;\n }\n const resolved = u.facts!.repository.resolve(u.file, target);\n if (!resolved) {\n throw new UnresolvedError(\"Project reference outside repository\");\n }\n if (!u.facts!.repository.exists(resolved)) {\n return at(`Missing TypeScript reference: ${target}`);\n }\n }\n return none;\n },\n \"Correct the project reference or restore the referenced project.\"\n ),\n make(\n \"architecture\",\n \"missing-local-config-extends\",\n \"Config extends a missing local file\",\n [\"**/tsconfig*.json\"],\n GUARD,\n (u) => {\n const value = json(u);\n const bases = Array.isArray(value.extends)\n ? value.extends\n : [value.extends];\n for (const base of bases) {\n if (typeof base !== \"string\" || !base.startsWith(\".\")) {\n continue;\n }\n const resolved = u.facts!.repository.resolve(u.file, base);\n if (resolved === undefined) {\n throw new UnresolvedError(\"Extended config outside repository\");\n }\n if (\n !u.facts!.repository.exists(resolved) &&\n !u.facts!.repository.exists(`${resolved}.json`)\n ) {\n return at(`Missing extended config: ${base}`);\n }\n }\n return none;\n },\n \"Update extends to the existing configuration path.\"\n ),\n];\n","import { none, hit } from \"../../reduce/mechanical.js\";\nimport type { Unit } from \"../../types.js\";\nimport { codeRule } from \"./rule.js\";\n\nconst make = (\n id: string,\n title: string,\n categoryId: string,\n source: string,\n check: (u: Unit) => ReturnType<typeof hit>,\n hint: string\n) =>\n codeRule(\n {\n categoryId,\n check,\n hint,\n id,\n source: {\n line: 1,\n path: `skills/${source}`,\n repo: \"mblode/agent-skills\",\n },\n status: \"review-only\",\n title,\n unit: [\"class-list\"],\n },\n \"src/rules/code/skill-classes.ts\"\n );\n\nexport const SKILL_CLASS_RULES = [\n make(\n \"typography-justify-without-hyphens\",\n \"Justified text explicitly disables hyphenation\",\n \"reading-comfort\",\n \"typography-audit/rules/layout-justified-text.md\",\n (u) => {\n const list = u.classes ?? [];\n return list.includes(\"text-justify\") && list.includes(\"hyphens-none\")\n ? hit(\"text-justify with hyphens-none\")\n : none;\n },\n \"Prefer start alignment, or enable language-aware hyphenation and verify the rendered measure.\"\n ),\n make(\n \"typography-disabled-kerning\",\n \"Text explicitly disables font kerning\",\n \"typographic-detail\",\n \"typography-audit/rules/opentype-kerning.md\",\n (u) =>\n u.text.trim() && u.classes?.includes(\"[font-kerning:none]\")\n ? hit(\"font-kerning: none\")\n : none,\n \"Use the font's kerning unless the design has a deliberate exception.\"\n ),\n make(\n \"typography-stretched-glyphs\",\n \"Text glyphs are horizontally stretched\",\n \"type-quality\",\n \"typography-audit/rules/font-condensed-extended.md\",\n (u) => {\n if (\n !u.text.trim() ||\n ![\"body\", \"heading\", \"label\"].includes(u.context.role)\n ) {\n return none;\n }\n const distorted = u.classes?.find((c) =>\n /^scale-x-(?:50|75|90|95|105|110|125|150|200)$/.test(c)\n );\n return distorted ? hit(distorted) : none;\n },\n \"Use a condensed/extended font or supported width axis; inspect intentional animation transforms separately.\"\n ),\n make(\n \"motion-layout-property-transition\",\n \"Transition explicitly animates layout properties\",\n \"motion-restraint\",\n \"ui-animation/references/performance-deep-dive.md\",\n (u) => {\n const cls = u.classes?.find((c) =>\n /^transition-\\[(?:[^\\]]*,)?(?:width|height|top|left|right|bottom|margin|padding)(?:,|\\])/.test(\n c\n )\n );\n return cls ? hit(cls) : none;\n },\n \"Prefer transform/opacity for frequent motion; measure deliberate container resizing before changing it.\"\n ),\n];\n","// Typography and sentence-length checks over resolved values and text. The\n// arithmetic is here; Jev only ever sees words.\n\nimport {\n countWords,\n describe,\n hit,\n needText,\n needTypography,\n none,\n sizeOrAbstain,\n UnresolvedError,\n} from \"../../reduce/mechanical.js\";\nimport type { Rule } from \"../../types.js\";\nimport { codeRule } from \"./rule.js\";\n\nconst MODULE = \"src/rules/code/typography.ts\";\nconst AUDIT = \"skills/typography-audit/rules\";\nconst BODY_ROLES = new Set([\"body\", \"list-item\", \"cell\"]);\n\n// Colour classes that quiet an element rather than emphasise it.\nconst isMutedColour = (cls: string): boolean =>\n /(?:^|:)text-(?:muted|secondary|foreground|inherit|current)(?:-|$|\\/)/u.test(\n cls\n );\n\nconst rule = (spec: Parameters<typeof codeRule>[0]): Rule =>\n codeRule(spec, MODULE);\n\nexport const TYPOGRAPHY_RULES: Rule[] = [\n rule({\n categoryId: \"reading-comfort\",\n check: (unit) => {\n const t = needTypography(unit);\n const size = sizeOrAbstain(t);\n if (size === undefined || !BODY_ROLES.has(unit.context.role)) {\n return none;\n }\n const words = countWords(unit.text);\n if (words < 6) {\n return none;\n }\n return size < 15\n ? hit(`${describe(t)} on ${words} words of body text`)\n : none;\n },\n hint: \"Body text reads at 15 to 19px on a phone and 18 to 24px on desktop. Keep 12 and 13px for captions and metadata nobody has to act on.\",\n id: \"typography-body-below-15px\",\n source: {\n line: 7,\n path: `${AUDIT}/size-body-text.md`,\n repo: \"mblode/agent-skills\",\n },\n title: \"Running text set below 15px\",\n unit: [\"class-list\", \"element\"],\n }),\n rule({\n categoryId: \"reading-comfort\",\n check: (unit) => {\n const t = needTypography(unit);\n if (t.letterSpacingEm === undefined || !needText(unit) || t.uppercase) {\n return none;\n }\n if (unit.context.role === \"heading\" || unit.context.role === \"button\") {\n return none;\n }\n const size = sizeOrAbstain(t);\n return t.letterSpacingEm > 0 && size !== undefined && size >= 13\n ? hit(describe(t))\n : none;\n },\n hint: \"Remove the tracking from body text. Letter-spacing belongs to uppercase and small caps; if small text is hard to read, make it bigger.\",\n id: \"typography-letterspaced-body\",\n source: {\n line: 7,\n path: `${AUDIT}/spacing-letterspacing-body.md`,\n repo: \"mblode/agent-skills\",\n },\n title: \"Positive letter-spacing on lowercase body text\",\n unit: [\"class-list\", \"element\"],\n }),\n rule({\n categoryId: \"reading-comfort\",\n // Weight 100 to 300 on text at or below 18px. An inherited size is not judged.\n check: (unit) => {\n const t = needTypography(unit);\n if (t.fontWeight === undefined || !needText(unit)) {\n return none;\n }\n const size = sizeOrAbstain(t);\n return t.fontWeight <= 300 && size !== undefined && size <= 18\n ? hit(describe(t))\n : none;\n },\n hint: \"Set body text at regular (400) or medium (500). Light weights lose contrast at text sizes; use them only at display sizes.\",\n id: \"typography-light-weight-small-body\",\n source: {\n line: 7,\n path: `${AUDIT}/font-weight-body.md`,\n repo: \"mblode/agent-skills\",\n },\n title: \"Thin or light weight on text-sized copy\",\n unit: [\"class-list\", \"element\"],\n }),\n rule({\n categoryId: \"reading-comfort\",\n // Body outside the rule's 1.4 to 1.6 band, display above 1.2. The code\n // allows 0.05 either side (1.35 to 1.7, display 1.25) so a rounded Tailwind\n // default such as text-sm's 1.429 never fires.\n check: (unit) => {\n const t = needTypography(unit);\n if (t.lineHeight === undefined || t.fontSizePx === undefined) {\n return none;\n }\n if (t.fontSizePx >= 32) {\n return t.lineHeight > 1.25\n ? hit(`${describe(t)} on display text`)\n : none;\n }\n if (unit.context.role !== \"body\" && unit.context.role !== \"list-item\") {\n return none;\n }\n if (countWords(unit.text) < 8) {\n return none;\n }\n return t.lineHeight < 1.35 || t.lineHeight > 1.7\n ? hit(`${describe(t)} on running text`)\n : none;\n },\n hint: \"Body reads at 1.4 to 1.6, wider columns a little more. Display type over 32px wants 1.1 to 1.2 so a headline reads as one object.\",\n id: \"typography-line-height-out-of-band\",\n source: {\n line: 7,\n path: `${AUDIT}/size-line-height.md`,\n repo: \"mblode/agent-skills\",\n },\n title: \"Line height outside the comfortable band for its size\",\n unit: [\"class-list\", \"element\"],\n }),\n rule({\n categoryId: \"type-hierarchy\",\n // This element and its next text-bearing sibling both resolve a size, the\n // weights match, and the ratio is above 1.0 and at most 1.2. Jev then\n // decides whether the pair is a heading over its body or two peers.\n check: (unit) => {\n const t = needTypography(unit);\n const next = unit.neighbours?.next?.typography;\n if (!next) {\n return none;\n }\n if (t.fontSizePx === undefined || next.fontSizePx === undefined) {\n if (\n [...t.unresolved, ...next.unresolved].some((c) =>\n c.startsWith(\"text-\")\n )\n ) {\n throw new UnresolvedError(\"font size unresolved on one of the pair\");\n }\n return none;\n }\n const [big, small] =\n t.fontSizePx >= next.fontSizePx\n ? [t.fontSizePx, next.fontSizePx]\n : [next.fontSizePx, t.fontSizePx];\n const ratio = big / small;\n const sameWeight = (t.fontWeight ?? 400) === (next.fontWeight ?? 400);\n return ratio > 1 && ratio <= 1.2 && sameWeight\n ? hit(\n `${describe(t)} over ${describe(next)}, ratio ${ratio.toFixed(2)}`\n )\n : none;\n },\n hint: \"Make the sizes clearly different (a step of 20 to 25 percent or more) or add a second cue such as weight or colour. Two roles two pixels apart read as a mistake.\",\n id: \"typography-hierarchy-size-only\",\n question: {\n context: [\"neighbours\"],\n criteria: {\n false: {\n examples: [\n \"FIRST: Start free trial. SECOND: See how it works.\",\n \"FIRST: Every file change, in order. SECOND: Restored versions keep their history.\",\n ],\n what: \"The two texts have the same role.\",\n },\n true: {\n examples: [\n \"FIRST: Notification rules. SECOND: Choose which sync events reach your inbox and which stay in the activity feed.\",\n \"FIRST: Billing. SECOND: Invoices, payment method and tax details for this workspace.\",\n ],\n what: \"FIRST is a title or label for SECOND.\",\n },\n },\n instructions:\n \"You are given FIRST and SECOND, two short texts that sit one above the other on a screen. Return true when FIRST introduces, names or summarises SECOND, so a reader would expect FIRST to look like a heading or label and SECOND to look like body text. Return false when FIRST and SECOND are peers (two list items, two sentences of one paragraph, two options, two buttons) or when either is a control label. Judge only the words; no layout information is provided.\",\n },\n source: {\n line: 7,\n path: `${AUDIT}/hierarchy-size-contrast.md`,\n repo: \"mblode/agent-skills\",\n },\n thresholds: { act: 0.75, review: 0.4 },\n title: \"Two roles told apart by a small size step alone\",\n unit: [\"class-list\", \"element\"],\n }),\n rule({\n categoryId: \"typographic-detail\",\n // tabular-nums inherits and the unit sees only its own classes, so a\n // table-level class reads as a miss: review-only until ancestors reach it.\n check: (unit) => {\n if (unit.context.role !== \"cell\" || !/\\d/.test(unit.text)) {\n return none;\n }\n const classes = unit.classes ?? [];\n return classes.some(\n (c) => c.endsWith(\"tabular-nums\") || c.includes(\"tnum\")\n )\n ? none\n : hit(`numeric cell \"${unit.text}\" without tabular-nums`);\n },\n hint: \"Add tabular-nums (font-variant-numeric) to numeric columns so digits share one width and align.\",\n id: \"typography-numeric-cell-proportional-figures\",\n source: {\n line: 7,\n path: `${AUDIT}/opentype-tabular-figures.md`,\n repo: \"mblode/agent-skills\",\n },\n status: \"review-only\",\n title: \"Numbers in a table cell without tabular figures\",\n unit: [\"class-list\"],\n }),\n rule({\n categoryId: \"type-hierarchy\",\n // Three or more emphasis axes changed at once: weight, caps, colour, size,\n // italic. A muted colour quiets the element and is not an axis.\n check: (unit) => {\n const t = needTypography(unit);\n if (!needText(unit)) {\n return none;\n }\n const axes = [\n (t.fontWeight ?? 400) >= 600,\n t.uppercase === true,\n t.colourClasses.some((c) => !isMutedColour(c)),\n (t.fontSizePx ?? 16) >= 24,\n t.italic === true,\n ].filter(Boolean).length;\n return axes >= 3\n ? hit(\n `${axes} emphasis axes at once (${describe(t)}${t.colourClasses.length ? `, ${t.colourClasses.join(\" \")}` : \"\"})`\n )\n : none;\n },\n hint: \"Change one axis at a time. Emphasis is relative, so quieten the competition before making the winner louder.\",\n id: \"typography-stacked-emphasis\",\n source: {\n line: 7,\n path: `${AUDIT}/hierarchy-weight-contrast.md`,\n repo: \"mblode/agent-skills\",\n },\n title: \"Bold, caps, colour and size stacked on one element\",\n unit: [\"class-list\", \"element\"],\n }),\n rule({\n categoryId: \"reading-comfort\",\n check: (unit) => {\n const t = needTypography(unit);\n if (!t.uppercase || !needText(unit)) {\n return none;\n }\n return (t.letterSpacingEm ?? 0) <= 0 ? hit(describe(t)) : none;\n },\n hint: \"Add 0.05 to 0.2em of tracking to uppercase text (tracking-wide or tracking-wider), more when it is small.\",\n id: \"typography-uppercase-without-tracking\",\n source: {\n line: 7,\n path: `${AUDIT}/spacing-letterspacing-uppercase.md`,\n repo: \"mblode/agent-skills\",\n },\n title: \"Uppercase text with no added letter-spacing\",\n unit: [\"class-list\", \"element\"],\n }),\n rule({\n categoryId: \"machine-prose\",\n // One sentence over 25 words; the count happens here, never in Jev.\n check: (unit) => {\n const long = unit.text\n .split(/(?<=[.!?])\\s+/u)\n .map((s) => [s, countWords(s)] as const)\n .filter(([, n]) => n > 25);\n if (long.length === 0) {\n return none;\n }\n const [sentence, n] = long[0];\n return hit(\n `${n} words: \"${sentence.slice(0, 80)}${sentence.length > 80 ? \"...\" : \"\"}\"`\n );\n },\n hint: 'Break at the strongest claim. More than one \"and\" or \"but\" usually marks the split.',\n id: \"copywriting-long-sentence\",\n preconditions: {\n docType: [\n \"readme\",\n \"personal\",\n \"tutorial\",\n \"howto\",\n \"reference\",\n \"explanation\",\n \"lesson\",\n \"marketing\",\n \"ui\",\n \"unknown\",\n ],\n notInCode: true,\n },\n source: {\n line: 7,\n path: \"skills/docs-writing/rules/clarity-one-idea-per-sentence.md\",\n repo: \"mblode/agent-skills\",\n },\n title: \"Sentence over 25 words\",\n unit: [\"paragraph\", \"jsx-text\"],\n }),\n];\n","// Code rules: the same `Rule` shape the YAML loader produces, with the check\n// attached instead of a `mechanical` section. A rule that counts, compares or\n// measures lives here; a rule a regex or a Jev question can express lives in\n// data/rules. Both load through `loadRules` and obey the same tuning overlay.\n\nimport type { Rule } from \"../../types.js\";\nimport { ARCHITECTURE_RULES } from \"./architecture.js\";\nimport { CLASS_RULES } from \"./classes.js\";\nimport { DOCUMENT_RULES } from \"./documents.js\";\nimport { REPOSITORY_RULES } from \"./repository.js\";\nimport { SKILL_CLASS_RULES } from \"./skill-classes.js\";\nimport { TYPOGRAPHY_RULES } from \"./typography.js\";\n\nexport { codeRule } from \"./rule.js\";\nexport type { CodeRuleSpec } from \"./rule.js\";\n\nexport const CODE_RULES: Rule[] = [\n ...TYPOGRAPHY_RULES,\n ...CLASS_RULES,\n ...DOCUMENT_RULES,\n ...REPOSITORY_RULES,\n ...SKILL_CLASS_RULES,\n ...ARCHITECTURE_RULES,\n];\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { parse } from \"yaml\";\n\nimport { InputError } from \"../lib/errors.js\";\nimport { RULE_STATUSES } from \"../types.js\";\nimport type { Rule, Tuning, TuningEntry } from \"../types.js\";\nimport { CODE_RULES } from \"./code/index.js\";\nimport { validateRule } from \"./validate.js\";\n\n// Walk up from this module to find the packaged data directory, so the CLI\n// works both from the repo and from an installed tarball.\nexport const resolveRulesDir = (explicit?: string): string => {\n if (explicit) {\n const abs = path.resolve(explicit);\n if (!fs.existsSync(abs)) {\n throw new Error(`Rules directory not found: ${abs}`);\n }\n return abs;\n }\n let dir = import.meta.dirname;\n for (let i = 0; i < 5; i += 1) {\n const candidate = path.join(dir, \"data\", \"rules\");\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n dir = path.dirname(dir);\n }\n throw new Error(\n \"Could not locate data/rules. Reinstall taste-lint or pass --rules.\"\n );\n};\n\n// tuning.json is the one file `tune --write` edits; a typo here would flip a\n// rule's status or threshold silently, so every entry is checked.\nexport const readTuning = (rulesDir: string): Tuning => {\n const file = path.join(rulesDir, \"tuning.json\");\n if (!fs.existsSync(file)) {\n return {};\n }\n const raw = JSON.parse(fs.readFileSync(file, \"utf-8\")) as unknown;\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new Error(`Invalid tuning file ${file}: must be an object`);\n }\n const bad = (id: string, why: string): never => {\n throw new Error(`Invalid tuning file ${file}: ${id} ${why}`);\n };\n const out: Tuning = {};\n for (const [id, entry] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) {\n bad(id, \"must be an object\");\n }\n const e = entry as Record<string, unknown>;\n const allowed = new Set([\"act\", \"status\", \"precisionLower\", \"n\", \"ts\"]);\n for (const key of Object.keys(e)) {\n if (!allowed.has(key)) {\n bad(id, `has unknown key ${key}`);\n }\n }\n const tuned: TuningEntry = {};\n if (e.act !== undefined) {\n if (typeof e.act !== \"number\" || !(e.act > 0 && e.act <= 1)) {\n bad(id, \"act must be a number in (0, 1]\");\n }\n tuned.act = e.act as number;\n }\n if (e.status !== undefined) {\n if (!RULE_STATUSES.includes(e.status as (typeof RULE_STATUSES)[number])) {\n bad(id, `status must be one of ${RULE_STATUSES.join(\", \")}`);\n }\n tuned.status = e.status as TuningEntry[\"status\"];\n }\n if (e.precisionLower !== undefined) {\n if (typeof e.precisionLower !== \"number\") {\n bad(id, \"precisionLower must be a number\");\n }\n tuned.precisionLower = e.precisionLower as number;\n }\n if (e.n !== undefined) {\n if (!Number.isInteger(e.n)) {\n bad(id, \"n must be an integer\");\n }\n tuned.n = e.n as number;\n }\n if (e.ts !== undefined) {\n if (typeof e.ts !== \"string\") {\n bad(id, \"ts must be a string\");\n }\n tuned.ts = e.ts as string;\n }\n out[id] = tuned;\n }\n return out;\n};\n\nexport interface LoadOptions {\n /** Include rules with status draft (default false). */\n allowDraft?: boolean;\n /** Restrict to these rule ids. */\n only?: string[];\n}\n\nexport const loadRules = (\n rulesDir: string,\n options: LoadOptions = {}\n): Rule[] => {\n const tuning = readTuning(rulesDir);\n const rules: Rule[] = [];\n const seen = new Set<string>();\n const domains = fs\n .readdirSync(rulesDir, { withFileTypes: true })\n .filter((d) => d.isDirectory() && d.name !== \"schema\")\n .map((d) => d.name)\n .toSorted();\n for (const domain of domains) {\n const dir = path.join(rulesDir, domain);\n for (const name of fs.readdirSync(dir).toSorted()) {\n if (!name.endsWith(\".yaml\")) {\n continue;\n }\n const file = path.join(dir, name);\n const expectedId = name.slice(0, -\".yaml\".length);\n let raw: unknown;\n try {\n raw = parse(fs.readFileSync(file, \"utf-8\"));\n } catch (error) {\n throw new Error(\n `Invalid rule ${file}: YAML did not parse (${(error as Error).message})`,\n { cause: error }\n );\n }\n const rule = validateRule(raw, file, expectedId);\n if (rule.domain !== domain) {\n throw new Error(\n `Invalid rule ${file}: domain ${rule.domain} does not match folder ${domain}`\n );\n }\n rules.push(rule);\n }\n }\n // Code rules join the same list; a fresh object per load so the overlay\n // below never mutates the module constant.\n for (const code of CODE_RULES) {\n rules.push({ ...code, thresholds: { ...code.thresholds } });\n }\n for (const rule of rules) {\n if (seen.has(rule.id)) {\n throw new Error(`Duplicate rule id ${rule.id}`);\n }\n seen.add(rule.id);\n const overlay = tuning[rule.id];\n if (overlay) {\n if (overlay.act !== undefined) {\n if (!(overlay.act > rule.thresholds.review && overlay.act <= 1)) {\n throw new Error(\n `Invalid tuning for ${rule.id}: act must be above review and at most 1`\n );\n }\n rule.thresholds = { ...rule.thresholds, act: overlay.act };\n }\n if (overlay.status) {\n rule.status = overlay.status;\n }\n }\n }\n for (const id of Object.keys(tuning)) {\n if (!seen.has(id)) {\n throw new Error(`tuning.json names unknown rule ${id}`);\n }\n }\n let out = rules;\n if (!options.allowDraft) {\n out = out.filter((r) => r.status !== \"draft\");\n }\n if (options.only) {\n const wanted = new Set(options.only);\n const missing = options.only.filter((id) => !seen.has(id));\n if (missing.length > 0) {\n throw new InputError(\n \"INVALID_RULE\",\n `Unknown rule ids: ${missing.join(\", \")}`,\n { rules: missing }\n );\n }\n out = out.filter((r) => wanted.has(r.id));\n }\n return out;\n};\n","// `taste-lint eval`: run each rule over its labelled items and report.\n\nimport path from \"node:path\";\n\nimport { resolveTypography } from \"../extract/tailwind.js\";\nimport { defaultResultsDir } from \"../lib/config.js\";\nimport { makeRecorder } from \"../lib/record.js\";\nimport { binaryMetrics, calibrationTable } from \"../lib/stats.js\";\nimport type { BinaryMetrics } from \"../lib/stats.js\";\nimport { AnswerCache } from \"../map/cache.js\";\nimport { DEFAULT_MODEL, evaluateFromEnv, KEY_HINT } from \"../map/jev.js\";\nimport { judge } from \"../map/judge.js\";\nimport type { JevJob } from \"../map/plan.js\";\nimport { band } from \"../reduce/bands.js\";\nimport { loadRules, resolveRulesDir } from \"../rules/load.js\";\nimport type { Config, CorpusItem, Evaluate, Rule, Unit } from \"../types.js\";\nimport { loadCorpus, resolveCorpusDir, unitFromItem } from \"./corpus.js\";\nimport { corpusCoverage } from \"./coverage.js\";\n\nexport interface EvalOptions {\n corpusDir?: string;\n rulesDir?: string;\n only?: string[];\n split?: \"dev\" | \"holdout\" | \"all\";\n includeWeak?: boolean;\n dryRun?: boolean;\n noCache?: boolean;\n resultsDir?: string;\n model?: string;\n apiKey?: string;\n}\n\nexport interface EvalContext {\n evaluate?: Evaluate;\n}\n\nexport interface RuleEval {\n ruleId: string;\n n: number;\n /** Labelled items the rule could not judge (unresolved value, failed request). */\n unknown: number;\n skipped?: number;\n metrics: BinaryMetrics;\n reviewRate: number;\n calibration: ReturnType<typeof calibrationTable>;\n /** Per item: label, probability. */\n pairs: { id: string; label: boolean; probability: number }[];\n}\n\nexport interface EvalResult {\n referenceCoverage?: ReturnType<typeof corpusCoverage>;\n labelSources?: Record<string, number>;\n report: string;\n exitCode: number;\n rules: RuleEval[];\n usage: {\n requests: number;\n cached: number;\n inputTokens: number;\n costUsd: number;\n errors: number;\n };\n}\n\nconst corpusConfig = (): Config => ({\n components: { skip: [], unwrap: [] },\n docTypes: [],\n exclude: [],\n root: process.cwd(),\n smartQuotesAtBuild: false,\n tailwind: { theme: {} },\n});\n\n// Score every labelled item for every rule it is labelled with. Returns per\n// (item, rule) probability, using mechanical=1/0 for mechanical rules.\nexport const scoreItems = async (\n items: CorpusItem[],\n rules: Rule[],\n options: {\n evaluate?: Evaluate;\n cache: AnswerCache;\n model: string;\n dryRun?: boolean;\n recorder?: ReturnType<typeof makeRecorder>;\n }\n): Promise<{\n probabilities: Map<string, Record<string, number>>;\n /** (item id, rule id) pairs with no probability and a reason. */\n unknowns: { itemId: string; ruleId: string; reason: string }[];\n skipped: { itemId: string; ruleId: string; reason: string }[];\n usage: EvalResult[\"usage\"];\n pendingRequests: number;\n}> => {\n const config = corpusConfig();\n const itemById = new Map(items.map((i) => [i.id, i]));\n const units: Unit[] = items.map((item) => {\n const unit = unitFromItem(item);\n if (unit.classes && unit.classes.length > 0) {\n unit.typography = resolveTypography(unit.classes, config);\n }\n return unit;\n });\n // Each item is judged only for the rules it is labelled for.\n const labelledFor = (job: JevJob): JevJob | null => {\n const labels = itemById.get(job.unit.id)?.labels ?? {};\n const kept = job.rules.filter(({ rule }) => rule.id in labels);\n return kept.length > 0 ? { rules: kept, unit: job.unit } : null;\n };\n const judgement = await judge(units, rules, {\n cache: options.cache,\n config,\n evaluate: options.dryRun ? undefined : options.evaluate,\n jobFilter: labelledFor,\n model: options.model,\n\n recorder: options.recorder,\n });\n\n const probabilities = new Map<string, Record<string, number>>();\n for (const item of items) {\n probabilities.set(item.id, {});\n }\n for (const f of judgement.mechanical) {\n probabilities.get(f.unitId)![f.ruleId] = 1;\n }\n for (const [unitId, answers] of judgement.answers) {\n Object.assign(probabilities.get(unitId)!, answers);\n }\n const unknowns = judgement.unknowns\n .filter((u) => u.ruleId in (itemById.get(u.unitId)?.labels ?? {}))\n .map((u) => ({ itemId: u.unitId, reason: u.reason, ruleId: u.ruleId }));\n const abstained = new Set(\n unknowns.map((u) => `${u.itemId}\\u0000${u.ruleId}`)\n );\n // A labelled rule with no probability after judging did not fire (a\n // mechanical rule, or a `both` rule whose candidate filter passed), so it\n // scores 0 unless it abstained or is still pending.\n const scheduled = new Set(\n judgement.pending.flatMap((p) =>\n Object.keys(p.questions).map(\n (ruleId) => `${p.job.unit.id}\\u0000${ruleId}`\n )\n )\n );\n for (const item of items) {\n for (const rule of rules) {\n const key = `${item.id}\\u0000${rule.id}`;\n if (\n rule.id in item.labels &&\n rule.tier !== \"jev\" &&\n probabilities.get(item.id)![rule.id] === undefined &&\n !abstained.has(key) &&\n !scheduled.has(key) &&\n judgement.negatives.get(item.id)?.has(rule.id)\n ) {\n probabilities.get(item.id)![rule.id] = 0;\n }\n }\n }\n return {\n pendingRequests: judgement.estimatedRequests,\n probabilities,\n skipped: items.flatMap((item) =>\n Object.entries(judgement.skipped.get(item.id) ?? {})\n .filter(([id]) => id in item.labels)\n .map(([ruleId, reason]) => ({ itemId: item.id, reason, ruleId }))\n ),\n unknowns,\n usage: judgement.usage,\n };\n};\n\nexport const evaluateRules = (\n items: CorpusItem[],\n rules: Rule[],\n probabilities: Map<string, Record<string, number>>,\n unknowns: { itemId: string; ruleId: string }[] = [],\n skipped: { itemId: string; ruleId: string }[] = []\n): RuleEval[] =>\n rules.map((rule) => {\n const pairs: RuleEval[\"pairs\"] = [];\n let review = 0;\n let unknown = 0;\n for (const item of items) {\n if (!(rule.id in item.labels)) {\n continue;\n }\n const p = probabilities.get(item.id)?.[rule.id];\n if (p === undefined) {\n if (\n unknowns.some((u) => u.itemId === item.id && u.ruleId === rule.id)\n ) {\n unknown += 1;\n }\n continue;\n }\n pairs.push({ id: item.id, label: item.labels[rule.id], probability: p });\n if (band(p, rule.thresholds) === \"review\") {\n review += 1;\n }\n }\n const metrics = binaryMetrics(\n pairs.map((p) => ({\n label: p.label,\n predicted: p.probability >= rule.thresholds.act,\n }))\n );\n return {\n calibration: calibrationTable(pairs),\n metrics,\n n: pairs.length,\n pairs,\n reviewRate: pairs.length === 0 ? 0 : review / pairs.length,\n ruleId: rule.id,\n skipped: skipped.filter((s) => s.ruleId === rule.id).length,\n unknown,\n };\n });\n\nconst pct = (v: number): string => `${(v * 100).toFixed(0)}%`;\n\nexport const renderEval = (\n evals: RuleEval[],\n usage: EvalResult[\"usage\"],\n dryRun: boolean,\n pending: number\n): string => {\n const out: string[] = [];\n for (const e of evals) {\n if (e.n === 0) {\n out.push(\n `${e.ruleId}: no evaluated labelled items; ${e.skipped ?? 0} skipped, ${e.unknown} unknown`\n );\n continue;\n }\n const m = e.metrics;\n const precision =\n m.tp + m.fp === 0\n ? \"precision n/a (no positive predictions)\"\n : `precision ${pct(m.precision)} [${pct(m.precisionCI[0])}, ${pct(m.precisionCI[1])}]`;\n const recall =\n m.tp + m.fn === 0\n ? \"recall n/a (no positive labels)\"\n : `recall ${pct(m.recall)} [${pct(m.recallCI[0])}, ${pct(m.recallCI[1])}]`;\n const unknown = e.unknown > 0 ? ` unknown ${e.unknown}` : \"\";\n out.push(\n `${e.ruleId}: n=${e.n} skipped ${e.skipped ?? 0}${unknown} ${precision} ${recall} f1 ${m.f1.toFixed(2)} review ${pct(e.reviewRate)} (tp ${m.tp} fp ${m.fp} fn ${m.fn} tn ${m.tn})`\n );\n const rows = e.calibration.filter((b) => b.n > 0);\n if (rows.length > 0) {\n out.push(\" bucket n observed mean p\");\n for (const b of rows) {\n out.push(\n ` ${b.lo.toFixed(1)}-${b.hi.toFixed(1)} ${String(b.n).padStart(5)} ${pct(b.positives / b.n).padStart(8)} ${b.meanP.toFixed(2).padStart(6)}`\n );\n }\n }\n }\n if (dryRun) {\n out.push(\n `Dry run: ${pending} request${pending === 1 ? \"\" : \"s\"} would be sent; ${usage.cached} answers served from cache. No calls were made.`\n );\n } else {\n out.push(\n `Jev: ${usage.requests} requests, ${usage.cached} cached, ${usage.inputTokens} input tokens, $${usage.costUsd.toFixed(4)}${usage.errors ? `, ${usage.errors} errors` : \"\"}`\n );\n }\n return `${out.join(\"\\n\")}\\n`;\n};\n\nexport const runEval = async (\n options: EvalOptions,\n ctx: EvalContext = {}\n): Promise<EvalResult> => {\n const rulesDir = resolveRulesDir(options.rulesDir);\n const rules = loadRules(rulesDir, { allowDraft: false, only: options.only });\n const knownRuleIds = new Set(\n loadRules(rulesDir, { allowDraft: true }).map((r) => r.id)\n );\n const corpusDir = resolveCorpusDir(options.corpusDir);\n let items = loadCorpus(corpusDir, rules, {\n includeWeak: options.includeWeak,\n knownRuleIds,\n });\n if (options.split && options.split !== \"all\") {\n items = items.filter((i) => i.split === options.split);\n }\n if (!items.length) {\n throw new Error(\"No corpus items in the selected split.\");\n }\n const model = options.model ?? DEFAULT_MODEL;\n const resultsDir = options.resultsDir ?? defaultResultsDir();\n const cache = new AnswerCache(\n path.join(resultsDir, \"cache\"),\n !options.noCache\n );\n let evaluate = ctx.evaluate;\n if (!evaluate && !options.dryRun) {\n evaluate = evaluateFromEnv(options.apiKey);\n if (!evaluate) {\n throw new Error(`${KEY_HINT} Or pass --dry-run.`);\n }\n }\n const recorder = options.dryRun\n ? undefined\n : makeRecorder(\"eval\", { resultsDir });\n const { probabilities, unknowns, skipped, usage, pendingRequests } =\n await scoreItems(items, rules, {\n cache,\n dryRun: options.dryRun,\n evaluate,\n model,\n recorder,\n });\n const labelSources: Record<string, number> = {};\n for (const item of items) {\n labelSources[item.labelSource] = (labelSources[item.labelSource] ?? 0) + 1;\n }\n const evals = evaluateRules(items, rules, probabilities, unknowns, skipped);\n recorder?.summary({\n rules: evals.map((e) => ({\n id: e.ruleId,\n n: e.n,\n precision: e.metrics.precision,\n recall: e.metrics.recall,\n })),\n usage,\n });\n return {\n exitCode: usage.errors > 0 ? 2 : 0,\n labelSources,\n referenceCoverage: corpusCoverage(items, rules),\n report:\n (labelSources.ai\n ? `AI-labeled reference: ${labelSources.ai} items. Metrics measure agreement with AI labels, not human judgments.\\n`\n : \"\") +\n renderEval(evals, usage, Boolean(options.dryRun), pendingRequests),\n rules: evals,\n usage,\n };\n};\n","import type { Command } from \"commander\";\n\nimport { loadCorpus, resolveCorpusDir } from \"../eval/corpus.js\";\nimport { corpusCoverage, renderCoverage } from \"../eval/coverage.js\";\nimport { runEval } from \"../eval/metrics.js\";\nimport { DEFAULT_MODEL } from \"../map/jev.js\";\nimport { loadRules, resolveRulesDir } from \"../rules/load.js\";\n\nexport function registerEvalCommand(program: Command): void {\n const command = program\n .command(\"eval\")\n .enablePositionalOptions()\n .description(\n \"Run every rule over its labelled corpus and report precision, recall and calibration\"\n )\n .option(\n \"--corpus <path>\",\n \"Corpus directory (default: packaged data/corpus)\"\n )\n .option(\"--rules <path>\", \"Rules directory\")\n .option(\"--output <format>\", \"text or json\", \"text\")\n .option(\"--only <ids>\", \"Comma-separated rule ids\")\n .option(\"--split <name>\", \"dev, holdout or all\", \"all\")\n .option(\"--include-weak\", \"Include manifest-weak labels\")\n .option(\"--dry-run\", \"Plan without calling Jev\")\n .option(\"--no-cache\", \"Ignore cached answers\")\n .option(\"--results-dir <path>\", \"Where logs and cache live\")\n .option(\"--model <id>\", \"Jev model id\", DEFAULT_MODEL)\n .action(async (options) => {\n if (![\"text\", \"json\"].includes(options.output)) {\n throw new Error(\"--output must be text or json\");\n }\n if (![\"dev\", \"holdout\", \"all\"].includes(options.split)) {\n throw new Error(\"--split must be dev, holdout or all\");\n }\n const result = await runEval({\n corpusDir: options.corpus,\n dryRun: options.dryRun,\n includeWeak: options.includeWeak,\n model: options.model,\n noCache: !options.cache,\n only: options.only\n ?.split(\",\")\n .map((s: string) => s.trim())\n .filter(Boolean),\n resultsDir: options.resultsDir,\n rulesDir: options.rules,\n split: options.split,\n });\n process.stdout.write(\n options.output === \"json\"\n ? `${JSON.stringify(result, null, 2)}\\n`\n : result.report\n );\n process.exitCode = result.exitCode;\n });\n command\n .command(\"coverage\")\n .description(\n \"Inspect label balance, document coverage and split overlap without API calls\"\n )\n .option(\"--corpus <path>\", \"Corpus directory\")\n .option(\"--rules <path>\", \"Rules directory\")\n .option(\"--include-weak\", \"Include weak labels\")\n .option(\"--output <format>\", \"text or json\", \"text\")\n .action((options) => {\n if (![\"text\", \"json\"].includes(options.output)) {\n throw new Error(\"--output must be text or json\");\n }\n const rulesDir = resolveRulesDir(options.rules);\n const rules = loadRules(rulesDir);\n const items = loadCorpus(resolveCorpusDir(options.corpus), rules, {\n includeWeak: options.includeWeak,\n knownRuleIds: new Set(\n loadRules(rulesDir, { allowDraft: true }).map((rule) => rule.id)\n ),\n });\n const coverage = corpusCoverage(items, rules);\n process.stdout.write(\n options.output === \"json\"\n ? `${JSON.stringify(coverage, null, 2)}\\n`\n : renderCoverage(coverage)\n );\n });\n}\n","// YAML frontmatter slice. The fences are found by hand so `blanked` keeps\n// line numbers intact (frontmatter lines become empty lines and mdast\n// positions still point at the original file); the mapping itself is parsed\n// by the `yaml` dependency the rule loader already uses.\n\nimport { parse } from \"yaml\";\n\nexport type Frontmatter = Record<string, string | undefined>;\n\nexport interface FrontmatterResult {\n fm: Frontmatter;\n body: string;\n /** The source with frontmatter lines blanked, same length in lines. */\n blanked: string;\n error: string | null;\n}\n\n// A BOM becomes a space rather than disappearing, so every offset in\n// `blanked` still lines up with the caller's source string.\nconst stripBom = (text: string): string =>\n text.codePointAt(0) === 0xfe_ff ? ` ${text.slice(1)}` : text;\n\n// Frontmatter consumers read scalars; nested values are kept as JSON text.\nconst scalar = (value: unknown): string | undefined => {\n if (value === null || value === undefined) {\n return undefined;\n }\n if (typeof value === \"string\") {\n // A folded or literal block keeps its final newline; consumers want the text.\n return value.replace(/\\n+$/u, \"\");\n }\n if (typeof value === \"object\") {\n return JSON.stringify(value);\n }\n return String(value);\n};\n\nexport const parseFrontmatter = (text: string): FrontmatterResult => {\n const src = stripBom(text);\n const lines = src.split(\"\\n\");\n if (lines.length === 0 || lines[0].trim() !== \"---\") {\n return { blanked: src, body: src, error: \"missing opening fence\", fm: {} };\n }\n let closeIdx = -1;\n for (let i = 1; i < lines.length; i += 1) {\n if (lines[i].trim() === \"---\") {\n closeIdx = i;\n break;\n }\n }\n if (closeIdx === -1) {\n return { blanked: src, body: src, error: \"missing closing fence\", fm: {} };\n }\n const blanked = [\n ...Array.from({ length: closeIdx + 1 }, () => \"\"),\n ...lines.slice(closeIdx + 1),\n ].join(\"\\n\");\n const body = lines.slice(closeIdx + 1).join(\"\\n\");\n const fm: Frontmatter = {};\n let problem: string | null = null;\n try {\n const parsed: unknown = parse(lines.slice(1, closeIdx).join(\"\\n\"));\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n !Array.isArray(parsed)\n ) {\n for (const [key, value] of Object.entries(parsed)) {\n fm[key] = scalar(value);\n }\n } else if (parsed !== null && parsed !== undefined) {\n problem = \"frontmatter is not a mapping\";\n }\n } catch (error) {\n problem = `frontmatter did not parse: ${(error as Error).message}`;\n }\n return { blanked, body, error: problem, fm };\n};\n","// Markdown and MDX extractor. Produces paragraph, heading and attr-string\n// units with mdast positions mapped back to the original source.\n\nimport type {\n Blockquote,\n Heading,\n ListItem,\n Node,\n Paragraph,\n Parent,\n Root,\n TableCell,\n} from \"mdast\";\nimport { fromMarkdown } from \"mdast-util-from-markdown\";\nimport { gfmFromMarkdown } from \"mdast-util-gfm\";\nimport type {\n MdxJsxAttribute,\n MdxJsxFlowElement,\n MdxJsxTextElement,\n} from \"mdast-util-mdx\";\nimport { mdxFromMarkdown } from \"mdast-util-mdx\";\nimport { gfm } from \"micromark-extension-gfm\";\nimport { mdxjs } from \"micromark-extension-mdxjs\";\n\nimport { parseFrontmatter } from \"../lib/frontmatter.js\";\nimport type { Config, DocType, Role, Unit } from \"../types.js\";\nimport { LineIndex, makeUnit, normaliseText } from \"./units.js\";\nimport type { UnitDraft } from \"./units.js\";\n\nconst ATTR_STRING_NAMES = new Set([\n \"title\",\n \"caption\",\n \"label\",\n \"alt\",\n \"description\",\n \"placeholder\",\n]);\n\ninterface Rendered {\n text: string;\n /** UTF-16 ranges inside `text` that came from inline code. */\n codeSpans: [number, number][];\n /** Source ranges of the text nodes, the only prose a fix may touch. */\n fixRanges: [number, number][];\n}\n\ntype AnyNode = Node & {\n children?: AnyNode[];\n value?: string;\n name?: string | null;\n};\n\ntype Offsets = (node: Node) => { start: number; end: number } | null;\n\nconst parseTree = (source: string, mdx: boolean): Root => {\n const extensions = mdx ? [gfm(), mdxjs()] : [gfm()];\n const mdastExtensions = mdx\n ? [gfmFromMarkdown(), mdxFromMarkdown()]\n : [gfmFromMarkdown()];\n return fromMarkdown(source, { extensions, mdastExtensions });\n};\n\n// Render phrasing content to text, recording inline code as code spans and\n// dropping expressions and images. `onInline` sees each inline MDX element so\n// its string attributes become units too.\nconst renderPhrasing = (\n nodes: AnyNode[],\n out: Rendered,\n offsets: Offsets,\n onInline?: (node: MdxJsxTextElement) => void\n): void => {\n for (const node of nodes) {\n switch (node.type) {\n case \"text\": {\n out.text += node.value ?? \"\";\n const range = offsets(node);\n if (range && range.end > range.start && (node.value ?? \"\").trim()) {\n out.fixRanges.push([range.start, range.end]);\n }\n break;\n }\n case \"inlineCode\": {\n const start = out.text.length;\n out.text += node.value ?? \"\";\n out.codeSpans.push([start, out.text.length]);\n break;\n }\n case \"break\": {\n out.text += \" \";\n break;\n }\n case \"mdxJsxTextElement\": {\n onInline?.(node as MdxJsxTextElement);\n renderPhrasing(node.children ?? [], out, offsets, onInline);\n break;\n }\n case \"emphasis\":\n case \"strong\":\n case \"delete\":\n case \"link\":\n case \"linkReference\": {\n renderPhrasing(node.children ?? [], out, offsets, onInline);\n break;\n }\n default: {\n // image, imageReference, html, footnoteReference, mdxTextExpression:\n // nothing rendered.\n break;\n }\n }\n }\n};\n\n// Collapse whitespace in the rendered text while keeping code span offsets\n// pointing at the same characters. Everything indexes UTF-16 code units.\nconst collapse = (rendered: Rendered): Rendered => {\n let text = \"\";\n const source = rendered.text;\n // Indexed by UTF-16 code unit, matching the span offsets; a for...of over\n // the string would step by code point and shift every span after an emoji.\n const map: number[] = Array.from({ length: source.length + 1 }, () => 0);\n let pendingSpace = false;\n for (let i = 0; i < source.length; i += 1) {\n const ch = source.charAt(i);\n map[i] = text.length;\n if (/[ \\t\\n\\r\\f\\v]/u.test(ch)) {\n pendingSpace = text.length > 0;\n continue;\n }\n if (pendingSpace) {\n text += \" \";\n pendingSpace = false;\n map[i] = text.length;\n }\n text += ch;\n }\n map[source.length] = text.length;\n const codeSpans = rendered.codeSpans.map(\n ([s, e]) => [map[s] ?? 0, map[e] ?? text.length] as [number, number]\n );\n return { codeSpans, fixRanges: rendered.fixRanges, text };\n};\n\n// The inside of a quoted attribute value, so a fix never touches the quotes.\nconst quotedValueRange = (\n source: string,\n start: number,\n end: number\n): [number, number] | null => {\n const slice = source.slice(start, end);\n const eq = slice.indexOf(\"=\");\n if (eq === -1) {\n return null;\n }\n const quote = slice[eq + 1];\n if ((quote !== '\"' && quote !== \"'\") || slice.at(-1) !== quote) {\n return null;\n }\n const inner: [number, number] = [start + eq + 2, end - 1];\n return inner[1] > inner[0] ? inner : null;\n};\n\nexport interface MarkdownExtractOptions {\n config: Config;\n docType: DocType;\n}\n\nexport const extractMarkdown = (\n file: string,\n source: string,\n options: MarkdownExtractOptions\n): Unit[] => {\n const { config, docType } = options;\n const index = new LineIndex(source);\n const isMdx = file.endsWith(\".mdx\");\n // `blanked` keeps every offset aligned with `source` (a BOM becomes a space).\n const { blanked } = parseFrontmatter(source);\n let tree: Root;\n let mdxFallback = false;\n try {\n tree = parseTree(blanked, isMdx);\n } catch {\n if (!isMdx) {\n return [fileUnit(file, index, source, docType, \"markdown did not parse\")];\n }\n try {\n tree = parseTree(blanked, false);\n mdxFallback = true;\n } catch (error) {\n return [\n fileUnit(\n file,\n index,\n source,\n docType,\n `parse error: ${(error as Error).message}`\n ),\n ];\n }\n }\n const units: Unit[] = [];\n let headingAbove: string | undefined;\n\n const push = (draft: UnitDraft): void => {\n if (draft.text.length === 0) {\n return;\n }\n if (mdxFallback) {\n draft.context.mdxFallback = true;\n }\n units.push(makeUnit(file, index, draft));\n };\n\n const offsets: Offsets = (node) => {\n const pos = node.position;\n if (!pos) {\n return null;\n }\n return {\n end: index.offsetAt(pos.end.line, pos.end.column),\n start: index.offsetAt(pos.start.line, pos.start.column),\n };\n };\n\n const attrUnits = (\n node: MdxJsxFlowElement | MdxJsxTextElement,\n component: string\n ): void => {\n for (const attr of node.attributes) {\n if (attr.type !== \"mdxJsxAttribute\") {\n continue;\n }\n const a = attr as MdxJsxAttribute;\n if (!ATTR_STRING_NAMES.has(a.name) || typeof a.value !== \"string\") {\n continue;\n }\n const range = offsets(a as unknown as Node) ?? offsets(node);\n if (!range) {\n continue;\n }\n const inner = quotedValueRange(source, range.start, range.end);\n push({\n context: {\n attr: a.name,\n component,\n docType,\n headingAbove,\n role: \"caption\",\n },\n fixRanges: inner ? [inner] : undefined,\n kind: \"attr-string\",\n sourceEnd: range.end,\n sourceStart: range.start,\n text: normaliseText(a.value),\n });\n }\n };\n\n const render = (\n nodes: AnyNode[],\n component: string | undefined\n ): Rendered => {\n const out: Rendered = { codeSpans: [], fixRanges: [], text: \"\" };\n renderPhrasing(nodes, out, offsets, (inline) => {\n const name = inline.name ?? \"fragment\";\n if (!config.components.skip.includes(name)) {\n attrUnits(inline, component ?? name);\n }\n });\n return collapse(out);\n };\n\n const textUnit = (\n node: Parent,\n kind: \"paragraph\" | \"heading\",\n role: Role,\n component?: string\n ): void => {\n const range = offsets(node);\n if (!range) {\n return;\n }\n const rendered = render(node.children as AnyNode[], component);\n if (rendered.text.trim() === \"\") {\n return;\n }\n push({\n codeSpans: rendered.codeSpans,\n context: { component, docType, headingAbove, role },\n fixRanges: rendered.fixRanges,\n kind,\n sourceEnd: range.end,\n sourceStart: range.start,\n text: rendered.text,\n });\n };\n\n const walk = (nodes: AnyNode[], role: Role, component?: string): void => {\n for (const node of nodes) {\n switch (node.type) {\n case \"heading\": {\n const h = node as Heading;\n textUnit(h, \"heading\", \"heading\", component);\n const out: Rendered = { codeSpans: [], fixRanges: [], text: \"\" };\n renderPhrasing(h.children as AnyNode[], out, offsets);\n headingAbove = normaliseText(out.text).slice(0, 120);\n break;\n }\n case \"paragraph\": {\n textUnit(node as Paragraph, \"paragraph\", role, component);\n break;\n }\n case \"list\": {\n walk(node.children ?? [], \"list-item\", component);\n break;\n }\n case \"listItem\": {\n walk(\n (node as ListItem).children as AnyNode[],\n \"list-item\",\n component\n );\n break;\n }\n case \"blockquote\": {\n walk((node as Blockquote).children as AnyNode[], role, component);\n break;\n }\n case \"table\":\n case \"tableRow\": {\n walk(node.children ?? [], \"cell\", component);\n break;\n }\n case \"tableCell\": {\n textUnit(node as TableCell, \"paragraph\", \"cell\", component);\n break;\n }\n case \"mdxJsxFlowElement\": {\n const el = node as MdxJsxFlowElement;\n const name = el.name ?? \"fragment\";\n if (config.components.skip.includes(name)) {\n break;\n }\n attrUnits(el, name);\n const tag = config.components.unwrap.includes(name)\n ? component\n : name;\n walk(el.children as AnyNode[], role, tag);\n break;\n }\n case \"code\":\n case \"html\":\n case \"yaml\":\n case \"toml\":\n case \"thematicBreak\":\n case \"mdxjsEsm\":\n case \"mdxFlowExpression\":\n case \"definition\":\n case \"footnoteDefinition\": {\n break;\n }\n default: {\n if (node.children) {\n walk(node.children, role, component);\n }\n }\n }\n }\n };\n\n walk(tree.children as AnyNode[], \"body\");\n let section: Unit[] = [];\n const finishSection = () => {\n const text = section.map((unit) => unit.text).join(\"\\n\");\n for (const unit of section) {\n unit.context.section = text;\n }\n section = [];\n };\n for (const unit of units) {\n if (unit.kind === \"heading\") {\n finishSection();\n }\n section.push(unit);\n }\n finishSection();\n return units;\n};\n\nconst fileUnit = (\n file: string,\n index: LineIndex,\n source: string,\n docType: DocType,\n parseError: string\n): Unit =>\n makeUnit(file, index, {\n context: { docType, parseError, role: \"unknown\" },\n kind: \"file\",\n sourceEnd: source.length,\n sourceStart: 0,\n text: \"\",\n });\n","// TSX and JSX extractor built on oxc-parser. Produces jsx-text, attr-string\n// and class-list units. Only static text and static class strings are\n// extracted; anything computed is flagged dynamic and skipped.\n\nimport { parseSync } from \"oxc-parser\";\n\nimport type {\n Config,\n DocType,\n NeighbourSummary,\n Role,\n Unit,\n} from \"../types.js\";\nimport { resolveTypography, splitClasses } from \"./tailwind.js\";\nimport {\n decodeEntities,\n LineIndex,\n makeUnit,\n normaliseText,\n ROLE_BY_TAG,\n} from \"./units.js\";\nimport type { UnitDraft } from \"./units.js\";\n\ntype Node = Record<string, unknown> & {\n type: string;\n start: number;\n end: number;\n};\n\nconst ATTR_STRING_NAMES = new Set([\n \"aria-label\",\n \"aria-description\",\n \"placeholder\",\n \"title\",\n \"alt\",\n \"label\",\n \"description\",\n \"helperText\",\n \"errorMessage\",\n]);\n\nconst COPY_KEYS = new Set([\n \"message\",\n \"title\",\n \"description\",\n \"label\",\n \"placeholder\",\n \"error\",\n \"hint\",\n \"cta\",\n \"what\",\n \"fix\",\n \"summary\",\n]);\n\nconst CLASS_FUNCTIONS = new Set([\n \"cn\",\n \"clsx\",\n \"cva\",\n \"twMerge\",\n \"classNames\",\n \"tw\",\n]);\nconst SKIP_CALLEES = new Set([\n \"console\",\n \"Sentry\",\n \"logger\",\n \"log\",\n \"t\",\n \"i18n\",\n \"invariant\",\n \"assert\",\n]);\n\nconst ROLE_BY_COMPONENT: Record<string, Role> = {\n Button: \"button\",\n CardDescription: \"body\",\n CardTitle: \"heading\",\n DialogDescription: \"body\",\n DialogTitle: \"heading\",\n Label: \"label\",\n Link: \"link\",\n};\n\nconst isNode = (v: unknown): v is Node =>\n typeof v === \"object\" && v !== null && typeof (v as Node).type === \"string\";\n\nconst elementName = (opening: Node): string => {\n const name = opening.name as Node;\n if (name.type === \"JSXIdentifier\") {\n return name.name as string;\n }\n if (name.type === \"JSXMemberExpression\") {\n const object = name.object as Node;\n const property = name.property as Node;\n return `${(object.name as string) ?? \"?\"}.${(property.name as string) ?? \"?\"}`;\n }\n if (name.type === \"JSXNamespacedName\") {\n return `${((name.namespace as Node).name as string) ?? \"\"}:${((name.name as Node).name as string) ?? \"\"}`;\n }\n return \"unknown\";\n};\n\nconst roleFor = (name: string): Role => {\n if (ROLE_BY_TAG[name]) {\n return ROLE_BY_TAG[name];\n }\n if (ROLE_BY_COMPONENT[name]) {\n return ROLE_BY_COMPONENT[name];\n }\n if (/^[a-z]/.test(name)) {\n return \"body\";\n }\n return \"unknown\";\n};\n\n// Static string value of an attribute or expression, or null when dynamic.\nconst staticString = (node: Node | null | undefined): string | null => {\n if (!node) {\n return null;\n }\n if (node.type === \"Literal\" && typeof node.value === \"string\") {\n return node.value;\n }\n if (node.type === \"JSXExpressionContainer\") {\n return staticString(node.expression as Node);\n }\n if (node.type === \"TemplateLiteral\") {\n const expressions = node.expressions as Node[];\n if (expressions.length > 0) {\n return null;\n }\n return (node.quasis as Node[])\n .map((q) => (q.value as { cooked?: string }).cooked ?? \"\")\n .join(\"\");\n }\n if (\n node.type === \"TSAsExpression\" ||\n node.type === \"TSSatisfiesExpression\" ||\n node.type === \"ParenthesizedExpression\"\n ) {\n return staticString(node.expression as Node);\n }\n return null;\n};\n\n// Classes from a className value: literal, template statics, cn()-style calls.\ninterface ClassInfo {\n classes: string[];\n dynamic: boolean;\n /** A template literal interpolates into a class (`bg-${color}`). */\n interpolated: boolean;\n}\n\nconst staticClasses = (node: Node | null | undefined): ClassInfo => {\n if (!node) {\n return { classes: [], dynamic: false, interpolated: false };\n }\n if (node.type === \"Literal\" && typeof node.value === \"string\") {\n return {\n classes: splitClasses(node.value),\n dynamic: false,\n interpolated: false,\n };\n }\n if (node.type === \"JSXExpressionContainer\") {\n return staticClasses(node.expression as Node);\n }\n if (node.type === \"TemplateLiteral\") {\n const quasis = (node.quasis as Node[]).map(\n (q) => (q.value as { cooked?: string }).cooked ?? \"\"\n );\n const interpolated = (node.expressions as Node[]).length > 0;\n // A token touching `${...}` is a fragment (`bg-` of `bg-${c}-500`), not a class.\n const classes = quasis.flatMap((q, i) => {\n const tokens = splitClasses(q);\n if (i < quasis.length - 1 && !/\\s$/u.test(q)) {\n tokens.pop();\n }\n if (i > 0 && !/^\\s/u.test(q)) {\n tokens.shift();\n }\n return tokens;\n });\n return { classes, dynamic: interpolated, interpolated };\n }\n if (node.type === \"CallExpression\") {\n const callee = node.callee as Node;\n const calleeName =\n callee.type === \"Identifier\"\n ? (callee.name as string)\n : callee.type === \"MemberExpression\"\n ? ((callee.property as Node).name as string)\n : \"\";\n if (!CLASS_FUNCTIONS.has(calleeName)) {\n return { classes: [], dynamic: true, interpolated: false };\n }\n let dynamic = false;\n let interpolated = false;\n const classes: string[] = [];\n for (const arg of node.arguments as Node[]) {\n const inner = staticClasses(arg);\n classes.push(...inner.classes);\n dynamic ||= inner.dynamic;\n interpolated ||= inner.interpolated;\n if (\n arg.type !== \"Literal\" &&\n arg.type !== \"TemplateLiteral\" &&\n arg.type !== \"CallExpression\"\n ) {\n dynamic = true;\n }\n }\n return { classes, dynamic, interpolated };\n }\n return { classes: [], dynamic: true, interpolated: false };\n};\n\nconst attributeByName = (opening: Node, name: string): Node | undefined => {\n for (const attr of opening.attributes as Node[]) {\n if (attr.type !== \"JSXAttribute\") {\n continue;\n }\n const attrName = attr.name as Node;\n const n =\n attrName.type === \"JSXNamespacedName\"\n ? `${(attrName.namespace as Node).name as string}:${(attrName.name as Node).name as string}`\n : (attrName.name as string);\n if (n === name) {\n return attr;\n }\n }\n return undefined;\n};\n\n// The inside of a string literal (no quotes), unwrapping expression\n// containers and casts. Template literals and anything computed give null.\nconst literalInner = (\n node: Node | null | undefined\n): [number, number] | null => {\n if (!node) {\n return null;\n }\n if (\n node.type === \"JSXExpressionContainer\" ||\n node.type === \"TSAsExpression\" ||\n node.type === \"TSSatisfiesExpression\" ||\n node.type === \"ParenthesizedExpression\"\n ) {\n return literalInner(node.expression as Node);\n }\n if (\n node.type === \"Literal\" &&\n typeof node.value === \"string\" &&\n node.end - node.start >= 2\n ) {\n return [node.start + 1, node.end - 1];\n }\n return null;\n};\n\ninterface DirectText {\n text: string;\n start: number;\n end: number;\n /** Source ranges of the prose pieces only: text nodes and literal insides. */\n fixRanges: [number, number][];\n}\n\n// Direct text of an element: JSXText plus static string expressions, in order.\n// The range starts at the first non-blank character so findings point at the\n// word, not the newline before it.\nconst directText = (element: Node): DirectText | null => {\n let text = \"\";\n let start = -1;\n let end = -1;\n // Inline children that contributed text; they widen the range only when the\n // element has direct text of its own, so a container of block children\n // never becomes a unit of all its descendants' prose.\n let childStart = -1;\n let childEnd = -1;\n const fixRanges: [number, number][] = [];\n for (const child of element.children as Node[]) {\n let piece: string | null = null;\n let range: [number, number] | null = null;\n if (child.type === \"JSXText\") {\n const raw = child.value as string;\n piece = decodeEntities(raw);\n if (raw.trim() !== \"\") {\n const lead = raw.length - raw.trimStart().length;\n const trail = raw.length - raw.trimEnd().length;\n range = [child.start + lead, child.end - trail];\n }\n } else if (child.type === \"JSXExpressionContainer\") {\n piece = staticString(child.expression as Node);\n range = literalInner(child);\n }\n if (piece !== null && piece.trim() !== \"\") {\n const [s, e] = range ?? [child.start, child.end];\n if (start === -1) {\n start = s;\n }\n end = e;\n if (range) {\n fixRanges.push(range);\n }\n }\n if (piece !== null) {\n text += piece;\n } else if (child.type === \"JSXElement\" || child.type === \"JSXFragment\") {\n // Inline child elements (a <b> inside a <p>) contribute their text so the\n // sentence stays whole; they are also extracted as their own units, so\n // their prose is not a fix range here.\n const inner = directText(child);\n if (inner) {\n text += inner.text;\n if (childStart === -1) {\n childStart = child.start;\n }\n childEnd = child.end;\n }\n } else {\n text += \" \";\n }\n }\n const normalised = normaliseText(text);\n if (normalised === \"\" || start === -1) {\n return null;\n }\n if (childStart !== -1) {\n start = Math.min(start, childStart);\n end = Math.max(end, childEnd);\n }\n return { end, fixRanges, start, text: normalised };\n};\n\nexport interface TsxExtractOptions {\n config: Config;\n docType: DocType;\n}\n\nexport const extractTsx = (\n file: string,\n source: string,\n options: TsxExtractOptions\n): Unit[] => {\n const { config, docType } = options;\n const index = new LineIndex(source);\n const lang = file.endsWith(\".jsx\") ? \"jsx\" : \"tsx\";\n const parsed = parseSync(file, source, { lang, sourceType: \"module\" });\n if (parsed.errors.length > 0) {\n const first = parsed.errors[0];\n return [\n makeUnit(file, index, {\n context: { docType, parseError: first.message, role: \"unknown\" },\n kind: \"file\",\n sourceEnd: source.length,\n sourceStart: 0,\n text: \"\",\n }),\n ];\n }\n const units: Unit[] = [];\n const push = (draft: UnitDraft): void => {\n if (draft.kind !== \"class-list\" && draft.text.length === 0) {\n return;\n }\n units.push(makeUnit(file, index, draft));\n };\n\n const elementSummary = (element: Node): NeighbourSummary | null => {\n if (element.type !== \"JSXElement\") {\n return null;\n }\n const text = directText(element);\n if (!text) {\n return null;\n }\n const opening = element.openingElement as Node;\n const classAttr = attributeByName(opening, \"className\");\n const classes = classAttr\n ? staticClasses(classAttr.value as Node)\n : { classes: [], dynamic: false, interpolated: false };\n return {\n element: elementName(opening),\n text: text.text,\n typography:\n classes.classes.length > 0\n ? resolveTypography(classes.classes, config)\n : undefined,\n };\n };\n\n const visitElement = (element: Node, skipContext: boolean): void => {\n const opening = element.openingElement as Node;\n const name = elementName(opening);\n const role = roleFor(name);\n const text = directText(element);\n const classAttr = attributeByName(opening, \"className\");\n const classInfo = classAttr ? staticClasses(classAttr.value as Node) : null;\n\n if (text && !skipContext) {\n push({\n context: { docType, element: name, role },\n fixRanges: text.fixRanges,\n kind: \"jsx-text\",\n sourceEnd: text.end,\n sourceStart: text.start,\n text: text.text,\n });\n }\n for (const attr of opening.attributes as Node[]) {\n if (attr.type !== \"JSXAttribute\") {\n continue;\n }\n const attrName = (attr.name as Node).name as string | undefined;\n if (!attrName || !ATTR_STRING_NAMES.has(attrName)) {\n continue;\n }\n const value = staticString(attr.value as Node);\n if (value === null || value.trim() === \"\") {\n continue;\n }\n const inner = literalInner(attr.value as Node);\n push({\n context: {\n attr: attrName,\n docType,\n element: name,\n role:\n attrName === \"placeholder\"\n ? \"placeholder\"\n : attrName.startsWith(\"aria-\")\n ? \"aria\"\n : \"label\",\n },\n fixRanges: inner ? [inner] : undefined,\n kind: \"attr-string\",\n sourceEnd: attr.end,\n sourceStart: attr.start,\n text: normaliseText(value),\n });\n }\n // Every element with classes gets a class-list unit; motion and\n // design-system checks apply to icon wrappers and containers too, while\n // the typography functions decline units with no text of their own.\n if (classInfo && (classInfo.classes.length > 0 || classInfo.interpolated)) {\n push({\n classes: classInfo.classes,\n context: {\n docType,\n dynamic: classInfo.dynamic || undefined,\n element: name,\n interpolated: classInfo.interpolated || undefined,\n role,\n },\n kind: \"class-list\",\n sourceEnd: classAttr?.end ?? element.end,\n sourceStart: classAttr?.start ?? element.start,\n text: text?.text ?? \"\",\n typography: resolveTypography(classInfo.classes, config),\n });\n }\n // Neighbours: text-bearing element children in order.\n const children = (element.children as Node[]).filter(\n (c) => c.type === \"JSXElement\"\n );\n const summaries = children.map((c) => elementSummary(c));\n for (let i = 0; i < children.length; i += 1) {\n const child = children[i];\n const summary = summaries[i];\n if (summary) {\n const prev =\n summaries.slice(0, i).findLast((s) => s !== null) ?? undefined;\n const next =\n summaries.slice(i + 1).find((s) => s !== null) ?? undefined;\n neighbourMap.set(child, {\n next: next ?? undefined,\n prev: prev ?? undefined,\n });\n }\n }\n for (const child of element.children as Node[]) {\n walk(child, skipContext);\n }\n // JSX passed through props (render props, slots) carries copy too.\n walk(opening.attributes, skipContext);\n };\n\n const neighbourMap = new WeakMap<\n Node,\n { prev?: NeighbourSummary; next?: NeighbourSummary }\n >();\n\n const attachNeighbours = (): void => {\n // Second pass: class-list units get neighbours from the map keyed by element.\n const byStart = new Map(\n units\n .filter((unit) => unit.kind === \"class-list\")\n .map((unit) => [unit.sourceStart, unit])\n );\n for (const entry of elementNeighbours) {\n const unit = byStart.get(entry.classStart);\n if (unit) {\n unit.neighbours = { next: entry.next, prev: entry.prev };\n }\n }\n };\n const elementNeighbours: {\n classStart: number;\n prev?: NeighbourSummary;\n next?: NeighbourSummary;\n }[] = [];\n\n const walk = (node: unknown, skipContext: boolean): void => {\n if (Array.isArray(node)) {\n for (const item of node) {\n walk(item, skipContext);\n }\n return;\n }\n if (!isNode(node)) {\n return;\n }\n switch (node.type) {\n case \"JSXElement\": {\n const neighbours = neighbourMap.get(node);\n if (neighbours) {\n const classAttr = attributeByName(\n node.openingElement as Node,\n \"className\"\n );\n if (classAttr) {\n elementNeighbours.push({\n classStart: classAttr.start,\n ...neighbours,\n });\n }\n }\n visitElement(node, skipContext);\n return;\n }\n case \"JSXFragment\": {\n for (const child of node.children as Node[]) {\n walk(child, skipContext);\n }\n return;\n }\n case \"CallExpression\": {\n const callee = node.callee as Node;\n const root =\n callee.type === \"Identifier\"\n ? (callee.name as string)\n : callee.type === \"MemberExpression\"\n ? (((callee.object as Node).name as string) ?? \"\")\n : \"\";\n const skip = skipContext || SKIP_CALLEES.has(root);\n walk(node.callee, skip);\n walk(node.arguments, skip);\n return;\n }\n case \"ThrowStatement\": {\n walk(node.argument, true);\n return;\n }\n case \"Property\": {\n const key = node.key as Node;\n const keyName =\n key.type === \"Identifier\"\n ? (key.name as string)\n : key.type === \"Literal\"\n ? String(key.value)\n : \"\";\n const value = node.value as Node;\n if (\n !skipContext &&\n COPY_KEYS.has(keyName) &&\n value.type === \"Literal\" &&\n typeof value.value === \"string\"\n ) {\n const text = normaliseText(value.value);\n if (text.length > 0) {\n push({\n context: { attr: keyName, docType, role: \"literal-copy\" },\n fixRanges: [[value.start + 1, value.end - 1]],\n kind: \"jsx-text\",\n sourceEnd: value.end,\n sourceStart: value.start,\n text,\n });\n }\n return;\n }\n walk(value, skipContext);\n break;\n }\n case \"ImportDeclaration\":\n case \"TSTypeAnnotation\":\n case \"TSTypeAliasDeclaration\":\n case \"TSInterfaceDeclaration\": {\n return;\n }\n default: {\n for (const [key, value] of Object.entries(node)) {\n if (\n key === \"type\" ||\n key === \"start\" ||\n key === \"end\" ||\n key === \"range\" ||\n key === \"loc\"\n ) {\n continue;\n }\n if (Array.isArray(value) || isNode(value)) {\n walk(value, skipContext);\n }\n }\n }\n }\n };\n\n walk(parsed.program, false);\n attachNeighbours();\n return units;\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { Repository, sourceFacts } from \"../analysis/repository.js\";\nimport { docTypeFor } from \"../lib/config.js\";\nimport type { Config, Unit } from \"../types.js\";\nimport { extractMarkdown } from \"./markdown.js\";\nimport { extractTsx } from \"./tsx.js\";\nimport { LineIndex, makeUnit } from \"./units.js\";\n\nexport const extractFile = (config: Config, relativeFile: string): Unit[] => {\n const repository = new Repository(config.root, config.architecture);\n const source = fs.readFileSync(path.join(config.root, relativeFile), \"utf-8\");\n return extractSource(config, relativeFile, source, repository);\n};\n\nexport const extractSource = (\n config: Config,\n file: string,\n source: string,\n repository: Repository\n): Unit[] => {\n const docType = docTypeFor(config, file);\n const units = /\\.(md|mdx)$/.test(file)\n ? extractMarkdown(file, source, { config, docType })\n : /\\.(tsx|jsx)$/.test(file)\n ? extractTsx(file, source, { config, docType })\n : [];\n const whole = makeUnit(file, new LineIndex(source), {\n context: { docType, role: \"unknown\" },\n kind: \"source\",\n sourceEnd: source.length,\n sourceStart: 0,\n text: source,\n });\n Object.defineProperty(whole, \"facts\", {\n enumerable: false,\n value: sourceFacts(file, source, repository),\n });\n return [...units, whole];\n};\n\nexport const SUPPORTED_GLOBS = [\n \"**/*.md\",\n \"**/*.mdx\",\n \"**/*.tsx\",\n \"**/*.jsx\",\n \"**/*.css\",\n \"**/*.scss\",\n \"**/*.ts\",\n \"**/*.js\",\n \"**/*.mjs\",\n \"**/*.cjs\",\n \"**/*.mts\",\n \"**/*.cts\",\n \"**/*.json\",\n \"**/*.yaml\",\n \"**/*.yml\",\n];\n","import type { Command } from \"commander\";\n\nimport { extractFile, SUPPORTED_GLOBS } from \"../extract/index.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { collectFiles } from \"../lib/glob.js\";\n\nexport function registerExtractCommand(program: Command): void {\n program\n .command(\"extract\")\n .description(\"Print the units taste-lint would lint, as JSONL\")\n .argument(\"<paths...>\", \"Files or directories, relative to --root\")\n .option(\"--root <path>\", \"Project root\", process.cwd())\n .option(\"--kind <kinds>\", \"Comma-separated unit kinds to keep\")\n .action((paths: string[], options: { root: string; kind?: string }) => {\n const config = loadConfig(options.root);\n const kinds = options.kind?.split(\",\").map((s) => s.trim());\n const files = collectFiles(\n config.root,\n paths,\n SUPPORTED_GLOBS,\n config.exclude\n );\n let count = 0;\n for (const file of files) {\n for (const unit of extractFile(config, file)) {\n if (kinds && !kinds.includes(unit.kind)) {\n continue;\n }\n count += 1;\n process.stdout.write(`${JSON.stringify(unit)}\\n`);\n }\n }\n process.stderr.write(`${count} units from ${files.length} files\\n`);\n });\n}\n","import { spawn } from \"node:child_process\";\n\nexport function spawnCapture(\n cmd: string,\n argv: string[],\n options: { input?: string; timeoutMs?: number; cwd?: string } = {}\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd, argv, {\n cwd: options.cwd,\n killSignal: \"SIGKILL\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n timeout: options.timeoutMs ?? 120_000,\n });\n let stdout = \"\";\n let stderr = \"\";\n // Decode as a stream so a multi-byte character split across chunks\n // (curly quotes in page text) never becomes U+FFFD.\n child.stdout.setEncoding(\"utf-8\");\n child.stderr.setEncoding(\"utf-8\");\n child.stdout.on(\"data\", (d: string) => {\n stdout += d;\n });\n child.stderr.on(\"data\", (d: string) => {\n stderr += d;\n });\n child.on(\"error\", (err: Error) => reject(err));\n child.on(\"close\", (code: number | null) => {\n if (code !== 0) {\n reject(\n new Error(\n `${cmd} did not complete successfully (exit ${code ?? \"signal\"}).`\n )\n );\n return;\n }\n resolve({ stderr, stdout });\n });\n if (options.input !== undefined) {\n child.stdin.write(options.input);\n }\n child.stdin.end();\n });\n}\n","// The style-capture CaptureResult (v1) shape and its fail-closed guard, shared\n// by the rendered extractor and the CLI text-block parser.\n\nexport interface BoundingBox {\n bottom: number;\n height: number;\n left: number;\n right: number;\n top: number;\n width: number;\n x: number;\n y: number;\n}\n\nexport interface ElementSnapshot {\n attributes: Record<string, string>;\n boundingBox: BoundingBox;\n children: string[];\n classList: string[];\n id: string;\n parentId: string | null;\n selector: string;\n styles: Record<string, string>;\n tagName: string;\n text?: string;\n}\n\nexport interface CaptureResult {\n elements: Record<string, ElementSnapshot>;\n metadata: { url: string; title?: string; capturedAt?: string };\n order: string[];\n rootElementId: string;\n rootOuterHtml: string;\n settings?: unknown;\n version: 1;\n}\n\n// Fail closed on anything that is not the v1 shape the walk below relies on.\nexport const assertCapture = (raw: unknown): CaptureResult => {\n const c = raw as Partial<CaptureResult> | null;\n if (\n typeof c !== \"object\" ||\n c === null ||\n c.version !== 1 ||\n typeof c.elements !== \"object\" ||\n c.elements === null ||\n !Array.isArray(c.order) ||\n !c.order.every((id) => typeof id === \"string\")\n ) {\n throw new Error(\n \"Unsupported capture: expected style-capture CaptureResult version 1 with elements and order\"\n );\n }\n return c as CaptureResult;\n};\n","// Parse the `<style_capture>` text block the style-capture CLI prints into\n// the CaptureResult shape the rendered extractor consumes. The CLI has no\n// JSON flag, so this is the bridge: css_capture gives one `selector{...}`\n// block per element in document order, and html_capture gives the subtree\n// whose text we walk by nth-child position.\n\nimport { assertCapture } from \"./capture.js\";\nimport type { CaptureResult, ElementSnapshot } from \"./capture.js\";\nimport { decodeEntities } from \"./units.js\";\n\nconst VOID = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"source\",\n \"track\",\n \"wbr\",\n]);\n\ninterface HtmlNode {\n tag: string;\n children: HtmlNode[];\n text: string[];\n attributes: Record<string, string>;\n}\n\nconst decode = decodeEntities;\n\nconst parseAttributes = (raw: string): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const m of raw.matchAll(\n /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'>]+)))?/g\n )) {\n out[m[1].toLowerCase()] = decode(m[2] ?? m[3] ?? m[4] ?? \"\");\n }\n return out;\n};\n\n// SIMPLIFIED: a tolerant tag/text tokenizer, not an HTML5 parser. Fine for\n// the cleaned subtree style-capture emits (no scripts, no raw text elements).\n// Quoted attribute values may contain `>`; an unquoted `>` inside a value or\n// a <template>/<textarea> subtree means it is time to swap in parse5.\nconst parseHtmlTree = (html: string): HtmlNode => {\n const root: HtmlNode = {\n attributes: {},\n children: [],\n tag: \"#root\",\n text: [],\n };\n const stack: HtmlNode[] = [root];\n const re =\n /<!--[\\s\\S]*?-->|<\\/([a-zA-Z][^\\s>]*)\\s*>|<([a-zA-Z][^\\s/>]*)((?:\"[^\"]*\"|'[^']*'|[^>])*?)(\\/?)>|([^<]+)/g;\n for (const m of html.matchAll(re)) {\n const [, close, open, attrs, selfClose, text] = m;\n const top = stack.at(-1) as HtmlNode;\n if (text !== undefined) {\n const t = decode(text);\n if (t.trim() !== \"\") {\n top.text.push(t);\n }\n continue;\n }\n if (close) {\n const tag = close.toLowerCase();\n for (let i = stack.length - 1; i > 0; i -= 1) {\n if (stack[i].tag === tag) {\n stack.length = i;\n break;\n }\n }\n continue;\n }\n if (open) {\n const tag = open.toLowerCase();\n const node: HtmlNode = {\n attributes: parseAttributes(attrs ?? \"\"),\n children: [],\n tag,\n text: [],\n };\n top.children.push(node);\n if (!selfClose && !VOID.has(tag)) {\n stack.push(node);\n }\n }\n }\n return root;\n};\n\n// Selectors split on `>`; the CLI writes them with or without spaces.\nconst segmentsOf = (selector: string): string[] =>\n selector.split(\">\").map((s) => s.trim());\n\nconst tagOf = (segment: string): string =>\n segment.match(/^[a-zA-Z][a-zA-Z0-9-]*/)?.[0] ?? \"div\";\n\nconst nth = (segment: string): number =>\n Number(segment.match(/:nth-child\\((\\d+)\\)/)?.[1] ?? \"1\");\n\nexport const parseStyleCaptureText = (text: string): CaptureResult => {\n const header = text.match(/<style_capture\\b([^>]*)>/);\n if (!header) {\n throw new Error(\"Not a style-capture block: missing <style_capture>\");\n }\n const url = header[1].match(/url=\"([^\"]*)\"/)?.[1] ?? \"unknown\";\n const html =\n text.match(/<html_capture>([\\s\\S]*?)<\\/html_capture>/)?.[1] ?? \"\";\n const css = text.match(/<css_capture>([\\s\\S]*?)<\\/css_capture>/)?.[1] ?? \"\";\n const tree = parseHtmlTree(html);\n const rootHtmlNode = tree.children[0];\n const elements: Record<string, ElementSnapshot> = {};\n const order: string[] = [];\n const bySelector = new Map<string, string>();\n let rootSelector: string | null = null;\n let index = 0;\n for (const block of css.matchAll(/([^{}]+)\\{([^}]*)\\}/g)) {\n const segments = segmentsOf(block[1]);\n const selector = segments.join(\">\");\n const styles: Record<string, string> = {};\n for (const decl of block[2].split(\";\")) {\n const colon = decl.indexOf(\":\");\n if (colon > 0) {\n styles[decl.slice(0, colon).trim()] = decl.slice(colon + 1).trim();\n }\n }\n const id = `e${index}`;\n index += 1;\n rootSelector ??= selector;\n const rootDepth = segmentsOf(rootSelector).length;\n // Walk the HTML tree by nth-child positions below the root.\n let node: HtmlNode | undefined = rootHtmlNode;\n for (const segment of segments.slice(rootDepth)) {\n node = node?.children[nth(segment) - 1];\n }\n const parentSelector =\n segments.length > rootDepth ? segments.slice(0, -1).join(\">\") : null;\n const parentId = parentSelector\n ? (bySelector.get(parentSelector) ?? null)\n : null;\n const segment = segments.at(-1) ?? selector;\n elements[id] = {\n attributes: node?.attributes ?? {},\n boundingBox: {\n bottom: 0,\n height: 0,\n left: 0,\n right: 0,\n top: 0,\n width: 0,\n x: 0,\n y: 0,\n },\n children: [],\n classList: (node?.attributes.class ?? \"\").split(/\\s+/u).filter(Boolean),\n id,\n parentId,\n selector,\n styles,\n tagName: tagOf(segment).toUpperCase(),\n text: node ? node.text.join(\" \") : \"\",\n };\n if (parentId) {\n elements[parentId].children.push(id);\n }\n bySelector.set(selector, id);\n order.push(id);\n }\n if (order.length === 0) {\n throw new Error(\"style-capture block has no css_capture elements\");\n }\n return {\n elements,\n metadata: { url },\n order,\n rootElementId: order[0],\n rootOuterHtml: html,\n version: 1,\n };\n};\n\n// Accept either a CaptureResult JSON file or the CLI's text block.\nexport const parseCaptureInput = (raw: string): CaptureResult => {\n const trimmed = raw.trimStart();\n if (trimmed.startsWith(\"{\")) {\n return assertCapture(JSON.parse(trimmed));\n }\n return parseStyleCaptureText(trimmed);\n};\n","// Rendered extractor: consume a style-capture CaptureResult (v1) and produce\n// `element` units with typography resolved from computed styles. Real values\n// replace class parsing, so measure, loaded font family and true weights are\n// available to the mechanical checks.\n\nimport { spawnCapture } from \"../lib/spawn.js\";\nimport type { NeighbourSummary, ResolvedTypography, Unit } from \"../types.js\";\nimport { assertCapture } from \"./capture.js\";\nimport type { CaptureResult, ElementSnapshot } from \"./capture.js\";\nimport { parseCaptureInput } from \"./style-capture-text.js\";\nimport { LineIndex, makeUnit, normaliseText, ROLE_BY_TAG } from \"./units.js\";\n\nexport type { BoundingBox, CaptureResult, ElementSnapshot } from \"./capture.js\";\n\nconst px = (value: string | undefined): number | undefined => {\n if (!value) {\n return undefined;\n }\n const m = value.match(/^(-?\\d*\\.?\\d+)px$/);\n return m ? Number(m[1]) : undefined;\n};\n\nexport const typographyFromStyles = (\n styles: Record<string, string>\n): ResolvedTypography & {\n fontFamily?: string;\n colour?: string;\n background?: string;\n textWrap?: string;\n fontSynthesis?: string;\n numeric?: string;\n} => {\n const fontSizePx = px(styles[\"font-size\"]);\n const lineHeightPx = px(styles[\"line-height\"]);\n const letterSpacingPx = px(styles[\"letter-spacing\"]);\n const weightRaw = styles[\"font-weight\"];\n const fontWeight =\n weightRaw === \"bold\"\n ? 700\n : weightRaw === \"normal\"\n ? 400\n : Number(weightRaw) || undefined;\n return {\n background: styles[\"background-color\"],\n colour: styles.color,\n colourClasses: [],\n fontFamily: styles[\"font-family\"],\n fontSizePx,\n fontSynthesis: styles[\"font-synthesis\"],\n fontWeight,\n italic:\n styles[\"font-style\"] === \"italic\" || styles[\"font-style\"] === \"oblique\",\n letterSpacingEm:\n letterSpacingPx !== undefined && fontSizePx\n ? Math.round((letterSpacingPx / fontSizePx) * 1000) / 1000\n : letterSpacingPx === undefined && styles[\"letter-spacing\"] === \"normal\"\n ? 0\n : undefined,\n lineHeight:\n fontSizePx && lineHeightPx\n ? Math.round((lineHeightPx / fontSizePx) * 1000) / 1000\n : undefined,\n lineHeightPx,\n numeric: styles[\"font-variant-numeric\"],\n textWrap: styles[\"text-wrap\"] ?? styles[\"text-wrap-style\"],\n unresolved: [],\n uppercase: styles[\"text-transform\"] === \"uppercase\",\n };\n};\n\n// Text directly inside an element. style-capture carries per-element text\n// only from the CLI text block; captures that omit it yield units without\n// prose, still useful for typography values.\nconst directTextOf = (el: ElementSnapshot): string => {\n if (typeof el.text === \"string\") {\n return normaliseText(el.text);\n }\n const attr = el.attributes[\"data-taste-lint-text\"];\n return attr ? normaliseText(attr) : \"\";\n};\n\nexport const extractCapture = (raw: CaptureResult, label: string): Unit[] => {\n const capture = assertCapture(raw);\n const file = `rendered:${label}`;\n // Synthetic source: one line per element in document order, so findings\n // point at a stable line number that maps to `order`.\n const lines = capture.order.map((id) => {\n const el = capture.elements[id];\n return el ? `${el.selector} ${directTextOf(el)}` : id;\n });\n const source = lines.join(\"\\n\");\n const index = new LineIndex(source);\n const units: Unit[] = [];\n const summaries = new Map<string, NeighbourSummary | null>();\n const summaryFor = (id: string): NeighbourSummary | null => {\n if (summaries.has(id)) {\n return summaries.get(id) ?? null;\n }\n const el = capture.elements[id];\n if (!el) {\n summaries.set(id, null);\n return null;\n }\n const text = directTextOf(el);\n const summary = text\n ? {\n element: el.tagName.toLowerCase(),\n text,\n typography: typographyFromStyles(el.styles),\n }\n : null;\n summaries.set(id, summary);\n return summary;\n };\n const nearestSummary = (\n siblings: string[],\n at: number,\n step: -1 | 1\n ): NeighbourSummary | undefined => {\n for (let i = at + step; i >= 0 && i < siblings.length; i += step) {\n const summary = summaryFor(siblings[i]);\n if (summary) {\n return summary;\n }\n }\n return undefined;\n };\n let offset = 0;\n for (const [i, id] of capture.order.entries()) {\n const el = capture.elements[id];\n const line = lines[i];\n const start = offset;\n offset += line.length + 1;\n if (!el) {\n continue;\n }\n const text = directTextOf(el);\n const tag = el.tagName.toLowerCase();\n if (!text || [\"script\", \"style\", \"noscript\", \"svg\", \"path\"].includes(tag)) {\n continue;\n }\n const siblings = el.parentId\n ? (capture.elements[el.parentId]?.children ?? [])\n : [];\n const at = siblings.indexOf(id);\n // An element its parent does not list has no siblings to compare against.\n const prev = at === -1 ? undefined : nearestSummary(siblings, at, -1);\n const next = at === -1 ? undefined : nearestSummary(siblings, at, 1);\n units.push(\n makeUnit(file, index, {\n classes: el.classList,\n context: {\n docType: \"ui\",\n element: tag,\n role:\n ROLE_BY_TAG[tag] ??\n (el.attributes.role === \"button\" ? \"button\" : \"body\"),\n },\n kind: \"element\",\n neighbours: { next, prev },\n sourceEnd: start + line.length,\n sourceStart: start,\n text,\n typography: typographyFromStyles(el.styles),\n })\n );\n }\n return units;\n};\n\n// Drive the style-capture CLI and parse its text block. Requires the\n// `style-capture` package (via npx) and a local Chromium for Playwright.\nexport const runStyleCapture = async (\n url: string,\n selector: string\n): Promise<CaptureResult> => {\n const { stdout } = await spawnCapture(\n \"npx\",\n [\"--yes\", \"style-capture\", url, selector, \"--mode\", \"full\"],\n { timeoutMs: 180_000 }\n );\n return parseCaptureInput(stdout);\n};\n","import fs from \"node:fs\";\n\nimport type { WritingContext } from \"../types.js\";\nimport { InputError } from \"./errors.js\";\n\nexport const validateWritingContext = (value: unknown): WritingContext => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new InputError(\n \"INVALID_WRITING_CONTEXT\",\n \"Writing context must be an object with facts, profile, or instructions strings.\"\n );\n }\n const record = value as Record<string, unknown>;\n for (const [key, text] of Object.entries(record)) {\n if (\n ![\"facts\", \"profile\", \"instructions\"].includes(key) ||\n typeof text !== \"string\" ||\n !text.trim()\n ) {\n throw new InputError(\n \"INVALID_WRITING_CONTEXT\",\n \"Writing context accepts only nonempty facts, profile, and instructions strings.\"\n );\n }\n }\n if (Object.keys(record).length === 0) {\n throw new InputError(\n \"INVALID_WRITING_CONTEXT\",\n \"Provide at least one writing context field.\"\n );\n }\n return record as WritingContext;\n};\n\nexport const readWritingContext = (file: string): WritingContext => {\n let value: unknown;\n try {\n value = JSON.parse(fs.readFileSync(file, \"utf-8\"));\n } catch {\n throw new InputError(\n \"INVALID_WRITING_CONTEXT\",\n \"Cannot read writing context: provide a readable JSON file.\"\n );\n }\n return validateWritingContext(value);\n};\n","// Collapse duplicate findings and merge same-category findings on one unit.\n\nimport type { Finding } from \"../types.js\";\nimport { SEVERITY_RANK } from \"../types.js\";\n\nconst BAND_RANK: Record<Finding[\"band\"], number> = {\n act: 0,\n review: 1,\n silent: 2,\n};\n\nexport const sortFindings = (findings: Finding[]): Finding[] =>\n findings.toSorted((a, b) => {\n if (a.file !== b.file) {\n return a.file < b.file ? -1 : 1;\n }\n if (a.line !== b.line) {\n return a.line - b.line;\n }\n if (BAND_RANK[a.band] !== BAND_RANK[b.band]) {\n return BAND_RANK[a.band] - BAND_RANK[b.band];\n }\n if (SEVERITY_RANK[a.severity] !== SEVERITY_RANK[b.severity]) {\n return SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];\n }\n return b.probability - a.probability;\n });\n\nexport const dedupeExact = (findings: Finding[]): Finding[] => {\n const exact = new Map<string, Finding>();\n for (const f of findings) {\n const key = `${f.unitId}\\u0000${f.ruleId}`;\n const existing = exact.get(key);\n if (!existing || f.probability > existing.probability) {\n exact.set(key, f);\n }\n }\n // Preserve insertion order for the v1 grouping tie-break contract.\n return [...exact.values()];\n};\n\nexport const dedupe = (findings: Finding[]): Finding[] => {\n // Merge findings that share unit and category: keep the strongest, list\n // the others under `also`. Suppressed findings pass through on their own so\n // a suppression on one rule never hides a live finding from another.\n const byUnitCategory = new Map<string, Finding[]>();\n const out: Finding[] = [];\n for (const f of dedupeExact(findings)) {\n if (f.suppressed) {\n out.push(f);\n continue;\n }\n const key = `${f.unitId}\\u0000${f.categoryId}`;\n const list = byUnitCategory.get(key) ?? [];\n list.push(f);\n byUnitCategory.set(key, list);\n }\n for (const list of byUnitCategory.values()) {\n const sorted = list.toSorted((a, b) => {\n if (BAND_RANK[a.band] !== BAND_RANK[b.band]) {\n return BAND_RANK[a.band] - BAND_RANK[b.band];\n }\n return b.probability - a.probability;\n });\n const [head, ...rest] = sorted;\n out.push(\n rest.length > 0 ? { ...head, also: rest.map((r) => r.ruleId) } : head\n );\n }\n return sortFindings(out);\n};\n","import { CATEGORIES } from \"../rules/taxonomy.js\";\nimport type { Finding, Rule, Scorecard, Unit, Unknown } from \"../types.js\";\nimport { STRUCTURAL_KINDS } from \"../types.js\";\n\nexport const buildScorecard = (\n units: Unit[],\n rules: Rule[],\n findings: Finding[],\n unknowns: Unknown[],\n silent: { ruleId: string }[]\n): Scorecard => {\n const byCategory: Scorecard[\"byCategory\"] = {};\n const byDomain: Scorecard[\"byDomain\"] = {};\n const byRule: Scorecard[\"byRule\"] = {};\n for (const c of CATEGORIES) {\n if (!rules.some((r) => r.categoryId === c.id)) {\n continue;\n }\n byCategory[c.id] = {\n act: 0,\n domain: c.domain,\n review: 0,\n suppressed: 0,\n units: 0,\n unknown: 0,\n };\n byDomain[c.domain] ??= {\n act: 0,\n review: 0,\n suppressed: 0,\n units: 0,\n unknown: 0,\n };\n }\n for (const r of rules) {\n byRule[r.id] = { act: 0, review: 0, silent: 0, unknown: 0 };\n }\n const unitCount = units.filter(\n (u) => !STRUCTURAL_KINDS.includes(u.kind)\n ).length;\n for (const c of Object.values(byCategory)) {\n c.units = unitCount;\n }\n for (const d of Object.values(byDomain)) {\n d.units = unitCount;\n }\n for (const f of findings) {\n const cat = byCategory[f.categoryId];\n const dom = byDomain[f.domain];\n const rule = byRule[f.ruleId];\n if (f.suppressed) {\n if (cat) {\n cat.suppressed += 1;\n }\n if (dom) {\n dom.suppressed += 1;\n }\n continue;\n }\n if (cat) {\n cat[f.band === \"act\" ? \"act\" : \"review\"] += 1;\n }\n if (dom) {\n dom[f.band === \"act\" ? \"act\" : \"review\"] += 1;\n }\n if (rule) {\n rule[f.band === \"act\" ? \"act\" : \"review\"] += 1;\n }\n }\n const ruleById = new Map(rules.map((r) => [r.id, r]));\n for (const u of unknowns) {\n const rule = ruleById.get(u.ruleId);\n if (!rule) {\n continue;\n }\n byRule[u.ruleId].unknown += 1;\n const cat = byCategory[rule.categoryId];\n if (cat) {\n cat.unknown += 1;\n }\n const dom = byDomain[rule.domain];\n if (dom) {\n dom.unknown += 1;\n }\n }\n for (const s of silent) {\n if (byRule[s.ruleId]) {\n byRule[s.ruleId].silent += 1;\n }\n }\n return { byCategory, byDomain, byRule };\n};\n","// `taste-lint-ignore: <rule-id>[, reason]` on the line above a unit, or anywhere\n// on the unit's first line, suppresses that rule for the unit. Also honours\n// agent-skills' `ui-audit-ignore:<rule-id>` for ported rule ids.\n\nimport type { Finding, Rule } from \"../types.js\";\n\nconst PATTERN = /(?:taste-lint-ignore|ui-audit-ignore)\\s*:\\s*([a-z0-9-]+)/giu;\n\nexport const suppressionsFor = (\n sourceLines: string[],\n line: number\n): Set<string> => {\n const ids = new Set<string>();\n for (const n of [line - 2, line - 1]) {\n const text = sourceLines[n];\n if (!text) {\n continue;\n }\n for (const m of text.matchAll(PATTERN)) {\n ids.add(m[1].toLowerCase());\n }\n }\n return ids;\n};\n\nexport const applySuppressions = (\n findings: Finding[],\n rules: Rule[],\n sources: Map<string, string[]>\n): Finding[] => {\n const byId = new Map(rules.map((r) => [r.id, r]));\n return findings.map((f) => {\n const lines = sources.get(f.file);\n if (!lines) {\n return f;\n }\n const ids = suppressionsFor(lines, f.line);\n const rule = byId.get(f.ruleId);\n const portedId = rule?.source.ruleId?.toLowerCase();\n if (\n ids.has(f.ruleId) ||\n (portedId && ids.has(portedId)) ||\n ids.has(\"all\")\n ) {\n return { ...f, suppressed: true };\n }\n return f;\n });\n};\n","// The lint pipeline: extract units, plan, run mechanical checks, batch Jev\n// requests, reduce to findings, score. Model calls happen only through\n// `ctx.evaluate`, so tests and dry runs never touch the network.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { Repository } from \"./analysis/repository.js\";\nimport { extractSource, SUPPORTED_GLOBS } from \"./extract/index.js\";\nimport { defaultResultsDir, loadConfig } from \"./lib/config.js\";\nimport { InputError } from \"./lib/errors.js\";\nimport { collectFiles } from \"./lib/glob.js\";\nimport { makeRecorder } from \"./lib/record.js\";\nimport { costUsd } from \"./lib/tokens.js\";\nimport { validateWritingContext } from \"./lib/writing-context.js\";\nimport { chunkQuestions } from \"./map/batch.js\";\nimport { AnswerCache } from \"./map/cache.js\";\nimport { DEFAULT_MODEL, evaluateFromEnv, KEY_HINT } from \"./map/jev.js\";\nimport { prepareJudgement, executeJudgement } from \"./map/judge.js\";\nimport { jevFindings } from \"./reduce/bands.js\";\nimport { dedupe, dedupeExact } from \"./reduce/dedupe.js\";\nimport { FIXES } from \"./reduce/fixes.js\";\nimport type { FixFunction } from \"./reduce/fixes.js\";\nimport { buildScorecard } from \"./reduce/scorecard.js\";\nimport { applySuppressions } from \"./reduce/suppress.js\";\nimport { loadRules, resolveRulesDir } from \"./rules/load.js\";\nimport type {\n WritingContext,\n DocType,\n Evaluate,\n Progress,\n ScanScope,\n Finding,\n LintResult,\n RecorderHandle,\n Rule,\n Severity,\n Unit,\n} from \"./types.js\";\nimport { SEVERITY_RANK, STRUCTURAL_KINDS } from \"./types.js\";\n\nexport interface LintOptions {\n docTypes?: { glob: string; type: DocType }[];\n advisoryRules?: string[];\n writingContext?: WritingContext;\n root: string;\n targets: string[];\n rulesDir?: string;\n only?: string[];\n exclude?: string[];\n dryRun?: boolean;\n printRequests?: boolean;\n mechanicalOnly?: boolean;\n noCache?: boolean;\n limitUnits?: number;\n failOn?: Severity;\n fix?: boolean;\n resultsDir?: string;\n model?: string;\n apiKey?: string;\n /** Extra units supplied by the caller (rendered mode). */\n extraUnits?: Unit[];\n}\n\nexport interface LintContext {\n evaluate?: Evaluate;\n stdout?: (text: string) => void;\n stderr?: (text: string) => void;\n onProgress?: (progress: Progress) => void;\n onEvidence?: (\n units: Unit[],\n answers: Map<string, Record<string, number>>,\n negatives: Map<string, Set<string>>\n ) => void;\n}\n\nexport { defaultResultsDir } from \"./lib/config.js\";\n\nexport const runLint = async (\n options: LintOptions,\n ctx: LintContext = {}\n): Promise<\n LintResult & {\n rulesLoaded: Rule[];\n units: number;\n manifest: Record<string, unknown>;\n }\n> => {\n const stderr = ctx.stderr ?? ((t: string) => process.stderr.write(t));\n const stdout = ctx.stdout ?? ((t: string) => process.stdout.write(t));\n const config = loadConfig(options.root, options.docTypes);\n const rulesDir = resolveRulesDir(options.rulesDir);\n const rules = loadRules(rulesDir, { only: options.only });\n for (const rule of rules) {\n if (options.advisoryRules?.includes(rule.id)) {\n rule.status = \"review-only\";\n }\n }\n const model = options.model ?? DEFAULT_MODEL;\n const resultsDir = options.resultsDir ?? defaultResultsDir();\n\n const scan = { excluded: 0, messages: [] as string[] };\n const files =\n options.targets.length > 0\n ? collectFiles(\n config.root,\n options.targets,\n SUPPORTED_GLOBS,\n [...config.exclude, ...(options.exclude ?? [])],\n scan\n )\n : [];\n let units: Unit[] = [];\n const sources = new Map<string, string[]>();\n const repository = new Repository(config.root, config.architecture);\n for (const file of files) {\n const source = fs.readFileSync(path.join(config.root, file), \"utf-8\");\n units.push(...extractSource(config, file, source, repository));\n sources.set(file, source.split(\"\\n\"));\n }\n if (options.extraUnits) {\n units.push(...options.extraUnits);\n }\n if (options.writingContext) {\n const writing = validateWritingContext(options.writingContext);\n for (const unit of units) {\n if (unit.context.docType === \"personal\") {\n Object.assign(unit.context, {\n writingFacts: writing.facts,\n writingInstructions: writing.instructions,\n writingProfile: writing.profile,\n });\n }\n }\n }\n if (options.limitUnits !== undefined) {\n units = units.slice(0, options.limitUnits);\n }\n\n const scope: ScanScope = {\n byDocType: {},\n diagnostics: scan.messages,\n excluded: scan.excluded,\n files: files.length,\n units: units.filter((u) => !STRUCTURAL_KINDS.includes(u.kind)).length,\n };\n for (const u of units) {\n if (!STRUCTURAL_KINDS.includes(u.kind)) {\n scope.byDocType[u.context.docType] =\n (scope.byDocType[u.context.docType] ?? 0) + 1;\n }\n }\n const parseFailures = new Set(\n units\n .filter(\n (unit) =>\n unit.context.parseError ||\n unit.context.mdxFallback ||\n unit.facts?.parseError\n )\n .map((unit) => unit.file)\n );\n for (const file of parseFailures) {\n scope.diagnostics.push(\n `Could not fully parse ${file}; analysis is incomplete.`\n );\n }\n if (units.length === 0) {\n scope.diagnostics.push(\n \"No supported units were selected. Check targets and exclusions; no clean-scan verdict is available.\"\n );\n }\n\n const cache = new AnswerCache(\n path.join(resultsDir, \"cache\"),\n !options.noCache\n );\n const manifest: Record<string, unknown> = {\n config_root: config.root,\n model,\n provider_policy: { retries: 3, timeoutMs: 10_000 },\n rules: rules.map((r) => r.id),\n scope,\n smart_quotes_at_build: config.smartQuotesAtBuild,\n targets: options.targets,\n };\n\n const judgeOptions = {\n cache,\n config,\n mechanicalOnly: options.mechanicalOnly,\n model,\n };\n const prepared = prepareJudgement(units, rules, judgeOptions);\n let evaluate = ctx.evaluate;\n let recorder: RecorderHandle | undefined;\n if (\n !options.dryRun &&\n !options.mechanicalOnly &&\n prepared.pending.length > 0\n ) {\n evaluate ??= evaluateFromEnv(options.apiKey);\n if (!evaluate) {\n throw new InputError(\n \"MISSING_CREDENTIALS\",\n `${KEY_HINT} Or run with --dry-run or --mechanical-only.`\n );\n }\n } else {\n evaluate = undefined;\n }\n if (options.printRequests) {\n for (const p of prepared.pending) {\n for (const questions of chunkQuestions(p)) {\n const ordered = Object.fromEntries(\n Object.keys(questions)\n .toSorted()\n .map((k) => [k, questions[k]])\n );\n stdout(\n `${JSON.stringify({ model, questions: ordered, state: p.state, unit: `${p.job.unit.file}:${p.job.unit.line}` })}\\n`\n );\n }\n }\n }\n if (evaluate && prepared.pending.length > 0) {\n recorder = makeRecorder(\"lint\", { resultsDir, skillsDir: config.root });\n recorder.append({ kind: \"manifest\", ...manifest });\n }\n const judgement = await executeJudgement(prepared, {\n ...judgeOptions,\n evaluate,\n onProgress: ctx.onProgress,\n recorder,\n });\n ctx.onEvidence?.(units, judgement.answers, judgement.negatives);\n const status: LintResult[\"status\"] = options.dryRun\n ? \"dry-run\"\n : judgement.usage.errors > 0 || parseFailures.size > 0 || units.length === 0\n ? \"incomplete\"\n : \"complete\";\n const jf = jevFindings(judgement.jobs, judgement.answers);\n let findings: Finding[] = [...judgement.mechanical, ...jf.findings];\n const { unknowns, usage } = judgement;\n recorder?.summary({ findings: findings.length, status, usage });\n\n const ruleFindings = dedupeExact(applySuppressions(findings, rules, sources));\n findings = dedupe(ruleFindings);\n\n if (options.fix && !options.dryRun) {\n applyFixes(config.root, ruleFindings, rules, units, stderr);\n }\n\n const scorecard = buildScorecard(units, rules, findings, unknowns, jf.silent);\n const failOn = options.failOn ?? \"minor\";\n const failing = ruleFindings.filter(\n (f) =>\n f.band === \"act\" &&\n !f.suppressed &&\n SEVERITY_RANK[f.severity] <= SEVERITY_RANK[failOn]\n );\n let exitCode = 0;\n if (status === \"incomplete\") {\n exitCode = 2;\n } else if (failing.length > 0) {\n exitCode = 1;\n }\n const summary = {\n act: findings.filter((f) => f.band === \"act\" && !f.suppressed).length,\n failOn,\n failing: failing.length,\n review: findings.filter((f) => f.band === \"review\" && !f.suppressed).length,\n ruleFindings: ruleFindings.filter((f) => !f.suppressed).length,\n unknown: unknowns.length,\n };\n return {\n coverage: judgement.coverage,\n estimated: options.dryRun\n ? {\n costUsd: costUsd(judgement.estimatedTokens),\n inputTokens: judgement.estimatedTokens,\n requests: judgement.estimatedRequests,\n }\n : undefined,\n exitCode,\n findings,\n manifest,\n ruleFindings,\n ruleScorecard: buildScorecard(\n units,\n rules,\n ruleFindings,\n unknowns,\n jf.silent\n ),\n rules: rules.map((r) => r.id),\n rulesLoaded: rules,\n scope,\n scorecard,\n status,\n summary,\n units: units.filter((u) => !STRUCTURAL_KINDS.includes(u.kind)).length,\n unknowns,\n usage,\n };\n};\n\ninterface Edit {\n start: number;\n end: number;\n fns: FixFunction[];\n}\n\n// Apply deterministic fixes to the prose ranges of each act-band finding.\n// Only `unit.fixRanges` is ever rewritten, so quotes, braces, expressions and\n// inline code around the prose are untouched. Fixes landing on the same range\n// compose; ranges are otherwise disjoint by construction.\nexport const applyFixes = (\n root: string,\n findings: Finding[],\n rules: Rule[],\n units: Unit[],\n stderr: (t: string) => void\n): void => {\n const ruleById = new Map(rules.map((r) => [r.id, r]));\n const unitById = new Map(units.map((u) => [u.id, u]));\n const byFile = new Map<string, Map<string, Edit>>();\n let skipped = 0;\n for (const f of findings) {\n const rule = ruleById.get(f.ruleId);\n const unit = unitById.get(f.unitId);\n const fn = rule?.fix.function ? FIXES[rule.fix.function] : undefined;\n if (!(rule && unit && fn) || f.suppressed || f.band !== \"act\") {\n continue;\n }\n if (!unit.fixRanges || unit.fixRanges.length === 0) {\n skipped += 1;\n continue;\n }\n const edits = byFile.get(f.file) ?? new Map<string, Edit>();\n for (const [start, end] of unit.fixRanges) {\n const key = `${start}:${end}`;\n const edit = edits.get(key) ?? { end, fns: [], start };\n if (!edit.fns.includes(fn)) {\n edit.fns.push(fn);\n }\n edits.set(key, edit);\n }\n byFile.set(f.file, edits);\n }\n for (const [file, edits] of byFile) {\n const abs = path.join(root, file);\n let source = fs.readFileSync(abs, \"utf-8\");\n const ordered = [...edits.values()].toSorted((a, b) => b.start - a.start);\n for (const edit of ordered) {\n let after = source.slice(edit.start, edit.end);\n for (const fn of edit.fns) {\n after = fn(after);\n }\n source = source.slice(0, edit.start) + after + source.slice(edit.end);\n }\n fs.writeFileSync(abs, source);\n stderr(\n `fixed ${ordered.length} range${ordered.length === 1 ? \"\" : \"s\"} in ${file}\\n`\n );\n }\n if (skipped > 0) {\n stderr(\n `${skipped} finding${skipped === 1 ? \"\" : \"s\"} left for a hand fix: the unit has no prose range taste-lint can rewrite safely\\n`\n );\n }\n};\n","import type { LintResult } from \"../types.js\";\n\nexport const renderJson = (\n result: LintResult,\n manifest: Record<string, unknown>\n): string =>\n `${JSON.stringify(\n {\n coverage: result.coverage,\n estimated: result.estimated,\n exitCode: result.exitCode,\n findings: result.findings,\n manifest,\n reportPath: result.reportPath,\n rerun: result.rerun,\n ruleFindings: result.ruleFindings,\n ruleScorecard: result.ruleScorecard,\n rules: result.rules,\n scope: result.scope,\n scorecard: result.scorecard,\n status: result.status,\n summary: result.summary,\n units: result.units,\n unknowns: result.unknowns,\n usage: result.usage,\n version: 1,\n },\n null,\n 2\n )}\\n`;\n","// SARIF 2.1.0 for GitHub code scanning and editors.\n\nimport type { Finding, LintResult, Rule } from \"../types.js\";\n\nconst level = (f: Finding): \"error\" | \"warning\" | \"note\" => {\n if (f.band === \"review\") {\n return \"note\";\n }\n return f.severity === \"minor\" ? \"warning\" : \"error\";\n};\n\nexport const renderSarif = (\n result: Pick<LintResult, \"findings\" | \"ruleFindings\">,\n rules: Rule[],\n version: string\n): string => {\n const findings = result.ruleFindings ?? result.findings;\n const used = new Set(findings.map((f) => f.ruleId));\n const ruleList = rules.filter((r) => used.has(r.id));\n const index = new Map(ruleList.map((r, i) => [r.id, i]));\n const sarif = {\n $schema: \"https://json.schemastore.org/sarif-2.1.0.json\",\n runs: [\n {\n results: findings\n .filter((f) => !f.suppressed)\n .map((f) => ({\n level: level(f),\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri: f.file },\n region: {\n endColumn: f.endColumn,\n endLine: f.endLine,\n startColumn: f.column,\n startLine: f.line,\n },\n },\n },\n ],\n message: {\n text: `${f.message}. ${f.evidence} Fix: ${f.fixHint}`,\n },\n partialFingerprints: {\n unitId: f.unitId,\n ...(\"fingerprint\" in f && typeof f.fingerprint === \"string\"\n ? { \"tasteLint/v1\": f.fingerprint }\n : {}),\n },\n properties: {\n band: f.band,\n probability: f.probability,\n severity: f.severity,\n },\n ruleId: f.ruleId,\n ruleIndex: index.get(f.ruleId),\n })),\n tool: {\n driver: {\n informationUri: \"https://github.com/mblode/taste-lint\",\n name: \"taste-lint\",\n rules: ruleList.map((r) => ({\n fullDescription: { text: r.question?.instructions ?? r.fix.hint },\n helpUri: `https://github.com/${r.source.repo}/blob/main/${r.source.path}#L${r.source.line}`,\n id: r.id,\n properties: {\n categoryId: r.categoryId,\n domain: r.domain,\n severity: r.severity,\n tier: r.tier,\n },\n shortDescription: { text: r.title },\n })),\n version,\n },\n },\n },\n ],\n version: \"2.1.0\",\n };\n return `${JSON.stringify(sarif, null, 2)}\\n`;\n};\n","import { styleText } from \"node:util\";\n\nimport type { Finding, LintResult, Scorecard } from \"../types.js\";\n\ntype Colour = Parameters<typeof styleText>[0];\n\nconst paint = (colour: Colour, text: string): string => {\n try {\n return styleText(colour, text);\n } catch {\n return text;\n }\n};\n\nconst severityTag = (f: Finding): string => {\n const label = f.severity.toUpperCase() + (f.band === \"review\" ? \"?\" : \"\");\n const colour: Colour = f.severity === \"major\" ? \"red\" : \"yellow\";\n return paint(f.band === \"review\" ? \"cyan\" : colour, `[${label}]`);\n};\n\nexport const formatFinding = (f: Finding): string => {\n const head = `${severityTag(f)} ${f.ruleId} (p=${f.probability.toFixed(2)}) ${f.file}:${f.line}:${f.column}`;\n const lines = [\n head,\n ` ${f.message}${f.also ? ` (also ${f.also.join(\", \")})` : \"\"}`,\n ];\n if (f.evidence) {\n lines.push(` ${f.evidence}`);\n }\n if (f.fixHint) {\n lines.push(` Fix: ${f.fixHint}`);\n }\n if (f.suppressed) {\n lines.push(\" (suppressed)\");\n }\n return lines.join(\"\\n\");\n};\n\nconst scorecardTable = (scorecard: Scorecard): string => {\n const rows = Object.entries(scorecard.byCategory).map(\n ([id, c]) =>\n ` ${id.padEnd(26)} ${String(c.act).padStart(4)} act ${String(c.review).padStart(4)} review ${String(c.suppressed).padStart(3)} suppressed ${String(c.unknown).padStart(4)} unknown`\n );\n return [\"Scorecard\", ...rows].join(\"\\n\");\n};\n\nexport const renderTty = (\n result: LintResult,\n options: { verbose?: boolean } = {}\n): string => {\n const out: string[] = [];\n const candidates = result.findings.filter(\n (f) => options.verbose || !f.suppressed\n );\n const actExamples = candidates.filter((f) => f.band === \"act\").slice(0, 20);\n const reviewExamples = candidates\n .filter((f) => f.band === \"review\")\n .slice(0, 10);\n const visible = options.verbose\n ? candidates\n : [...actExamples, ...reviewExamples];\n if (result.summary) {\n out.push(\n `Summary: ${result.summary.act} act, ${result.summary.review} review, ${result.summary.unknown} unknown; ${result.summary.failing} failing rule findings (fail-on ${result.summary.failOn}).`\n );\n }\n if (result.scope) {\n out.push(\n `Scope: ${result.scope.files} files; ${Object.entries(\n result.scope.byDocType\n )\n .map(([type, n]) => `${type}: ${n}`)\n .join(\", \")}; ${result.scope.excluded} excluded paths.`,\n ...result.scope.diagnostics\n );\n }\n const counts = new Map<string, number>();\n for (const f of result.ruleFindings ?? candidates) {\n if (!f.suppressed) {\n counts.set(f.ruleId, (counts.get(f.ruleId) ?? 0) + 1);\n }\n }\n out.push(\n `Top rules: ${[...counts]\n .toSorted((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n .slice(0, 5)\n .map(([id, n]) => `${id}: ${n}`)\n .join(\", \")}`\n );\n if (visible.length < candidates.length) {\n out.push(\n `${candidates.length - visible.length} findings omitted from this view; use --verbose for every finding.`\n );\n }\n if (result.reportPath) {\n out.push(`Complete report: ${result.reportPath}`);\n }\n if (result.rerun) {\n out.push(`Retry unresolved work: ${result.rerun}`);\n }\n let currentFile = \"\";\n for (const f of visible) {\n if (f.file !== currentFile) {\n currentFile = f.file;\n out.push(\"\", paint(\"bold\", f.file));\n }\n out.push(formatFinding(f));\n }\n if (result.unknowns.length > 0) {\n out.push(\n \"\",\n `${result.unknowns.length} unknown (unresolved value or precondition); use --verbose to list`\n );\n if (options.verbose) {\n for (const u of result.unknowns) {\n out.push(` ${u.ruleId} ${u.file}:${u.line}: ${u.reason}`);\n }\n }\n }\n out.push(\"\", scorecardTable(result.scorecard));\n const act = result.findings.filter(\n (f) => f.band === \"act\" && !f.suppressed\n ).length;\n const review = result.findings.filter(\n (f) => f.band === \"review\" && !f.suppressed\n ).length;\n out.push(\n \"\",\n `Units: ${result.units} | Rules: ${result.rules.length} | Act: ${act} | Review: ${review} | Unknown: ${result.unknowns.length}`\n );\n if (result.status === \"dry-run\" && result.estimated) {\n out.push(\n `Dry run: ${result.estimated.requests} request${result.estimated.requests === 1 ? \"\" : \"s\"} would be sent, about ${result.estimated.inputTokens} input tokens, about $${result.estimated.costUsd.toFixed(4)}. No calls were made.`\n );\n } else {\n out.push(\n `Jev: ${result.usage.requests} request${result.usage.requests === 1 ? \"\" : \"s\"}, ${result.usage.cached} cached answers, ${result.usage.inputTokens} input tokens, $${result.usage.costUsd.toFixed(4)}${result.usage.errors ? `, ${result.usage.errors} errors` : \"\"}`\n );\n }\n if (result.scope?.files === 0 && result.units === 0) {\n out.push(\"NO SCAN - no supported units selected\");\n } else if (result.status === \"incomplete\") {\n out.push(\n paint(\n \"red\",\n \"INCOMPLETE - analysis did not finish; see diagnostics and unknowns\"\n )\n );\n } else if (result.exitCode === 1) {\n out.push(\n paint(\n \"red\",\n `FAIL - ${result.summary?.failing ?? act} rule findings meet the failure threshold`\n )\n );\n } else {\n out.push(\n paint(\n \"green\",\n act > 0\n ? \"PASS - act findings are below the configured failure threshold\"\n : \"PASS - no act-band findings\"\n )\n );\n }\n return `${out.join(\"\\n\")}\\n`;\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { Command } from \"commander\";\n\nimport { SUPPORTED_GLOBS } from \"../extract/index.js\";\nimport { extractCapture, runStyleCapture } from \"../extract/rendered.js\";\nimport { parseCaptureInput } from \"../extract/style-capture-text.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { InputError } from \"../lib/errors.js\";\nimport { collectFiles } from \"../lib/glob.js\";\nimport { readWritingContext } from \"../lib/writing-context.js\";\nimport { defaultResultsDir, runLint } from \"../lint.js\";\nimport { DEFAULT_MODEL } from \"../map/jev.js\";\nimport { renderJson } from \"../report/json.js\";\nimport { renderSarif } from \"../report/sarif.js\";\nimport { renderTty } from \"../report/tty.js\";\nimport type { Severity } from \"../types.js\";\n\nconst quote = (value: string) => `'${value.replaceAll(\"'\", \"'\\\"'\\\"'\")}'`;\n\nexport function registerLintCommand(program: Command): void {\n program\n .command(\"lint\")\n .description(\"Lint files (or a rendered page) against the taste rules\")\n .argument(\"[paths...]\", \"Files or directories to lint, relative to --root\")\n .option(\"--root <path>\", \"Project root for globs and config\", process.cwd())\n .option(\"--rules <path>\", \"Rules directory (default: packaged data/rules)\")\n .option(\"--only <ids>\", \"Comma-separated rule ids\")\n .option(\n \"--exclude <globs>\",\n \"Comma-separated globs to skip (added to taste-lint.config.json exclude)\"\n )\n .option(\"--dry-run\", \"Plan and estimate cost without calling Jev\")\n .option(\n \"--print-requests\",\n \"With --dry-run and --output tty, print request JSONL to stderr\"\n )\n .option(\n \"--writing-context <file>\",\n \"Explicit JSON facts/profile/instructions for personal writing; sent to Jev on live runs\"\n )\n .option(\"--mechanical-only\", \"Skip every Jev-backed rule\")\n .option(\n \"--no-cache\",\n \"Ignore cached answers (new answers are still recorded)\"\n )\n .option(\"--limit-units <n>\", \"Only consider the first n units\")\n .option(\n \"--fail-on <severity>\",\n \"Lowest severity that fails the run: major or minor\",\n \"minor\"\n )\n .option(\"--fix\", \"Apply deterministic fixes for act-band findings\")\n .option(\"--output <format>\", \"tty, json or sarif\", \"tty\")\n .option(\n \"--results-dir <path>\",\n \"Where logs and cache live\",\n defaultResultsDir()\n )\n .option(\"--model <id>\", \"Jev model id\", DEFAULT_MODEL)\n .option(\"--progress\", \"Print periodic progress on stderr even when piped\")\n .option(\"--verbose\", \"Show suppressed findings and unknowns\")\n .option(\"--url <url>\", \"Lint a rendered page through style-capture\")\n .option(\"--selector <css>\", \"Root selector for --url\", \"body\")\n .option(\"--capture <file>\", \"Lint a saved style-capture CaptureResult JSON\")\n .action(\n async (\n paths: string[],\n options: {\n writingContext?: string;\n root: string;\n rules?: string;\n only?: string;\n exclude?: string;\n dryRun?: boolean;\n printRequests?: boolean;\n mechanicalOnly?: boolean;\n cache: boolean;\n limitUnits?: string;\n failOn: string;\n fix?: boolean;\n output: string;\n resultsDir: string;\n model: string;\n verbose?: boolean;\n progress?: boolean;\n url?: string;\n selector: string;\n capture?: string;\n }\n ) => {\n if (![\"major\", \"minor\"].includes(options.failOn)) {\n throw new InputError(\n \"INVALID_ARGUMENT\",\n \"--fail-on must be major or minor\"\n );\n }\n if (![\"tty\", \"json\", \"sarif\"].includes(options.output)) {\n throw new InputError(\n \"INVALID_ARGUMENT\",\n \"--output must be tty, json or sarif\"\n );\n }\n if (paths.length === 0 && !options.url && !options.capture) {\n throw new InputError(\n \"INVALID_ARGUMENT\",\n \"Pass at least one path, --url or --capture\"\n );\n }\n const limitUnits =\n options.limitUnits === undefined\n ? undefined\n : Number(options.limitUnits);\n if (\n limitUnits !== undefined &&\n (!Number.isInteger(limitUnits) || limitUnits < 0)\n ) {\n throw new InputError(\n \"INVALID_ARGUMENT\",\n \"--limit-units must be a non-negative integer\"\n );\n }\n if (\n options.printRequests &&\n (!options.dryRun || options.output !== \"tty\")\n ) {\n throw new InputError(\n \"INVALID_ARGUMENT\",\n \"--print-requests requires --dry-run and --output tty; request JSONL is written to stderr.\"\n );\n }\n if (options.progress || process.stderr.isTTY) {\n process.stderr.write(\"Scanning requested paths...\\n\");\n }\n const config = { root: path.resolve(options.root) };\n // Rendered capture is the only path with remote work before runLint.\n if (options.url || options.capture) {\n const resolved = loadConfig(config.root);\n collectFiles(resolved.root, paths, SUPPORTED_GLOBS, [\n ...resolved.exclude,\n ...(options.exclude\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean) ?? []),\n ]);\n }\n let extraUnits;\n if (options.capture) {\n extraUnits = extractCapture(\n parseCaptureInput(fs.readFileSync(options.capture, \"utf-8\")),\n options.capture\n );\n } else if (options.url) {\n extraUnits = extractCapture(\n await runStyleCapture(options.url, options.selector),\n options.url\n );\n }\n let lastProgress = 0;\n const result = await runLint(\n {\n dryRun: options.dryRun,\n exclude: options.exclude\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n extraUnits,\n failOn: options.failOn as Severity,\n fix: options.fix,\n limitUnits,\n mechanicalOnly: options.mechanicalOnly,\n model: options.model,\n noCache: !options.cache,\n only: options.only\n ?.split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n printRequests: options.printRequests,\n resultsDir: options.resultsDir,\n root: options.root,\n rulesDir: options.rules,\n targets: paths,\n writingContext: options.writingContext\n ? readWritingContext(options.writingContext)\n : undefined,\n },\n {\n onProgress: (progress) => {\n if (!(options.progress || process.stderr.isTTY)) {\n return;\n }\n const now = Date.now();\n if (\n lastProgress &&\n now - lastProgress < 2000 &&\n progress.phase !== \"complete\"\n ) {\n return;\n }\n lastProgress = now;\n process.stderr.write(\n `${progress.phase}: ${progress.completed}/${progress.planned} requests, ${progress.attempts} HTTP attempts, ${progress.cachedAnswers} cached answers, ${progress.failed} failed, ${(progress.elapsedMs / 1000).toFixed(1)}s\\n`\n );\n },\n stdout: (text) => process.stderr.write(text),\n }\n );\n const reportPath =\n result.status === \"dry-run\"\n ? undefined\n : path.resolve(\n options.resultsDir,\n `lint-${new Date().toISOString().replaceAll(\":\", \"-\")}.json`\n );\n const retryArgs = [\n // Context is explicit and must survive retry, never inferred from home.\n process.execPath,\n path.resolve(process.argv[1]),\n \"lint\",\n \"--root\",\n config.root,\n \"--results-dir\",\n path.resolve(options.resultsDir),\n \"--model\",\n options.model,\n \"--fail-on\",\n options.failOn,\n \"--output\",\n options.output,\n ];\n if (options.rules) {\n retryArgs.push(\"--rules\", path.resolve(options.rules));\n }\n if (options.only) {\n retryArgs.push(\"--only\", options.only);\n }\n if (options.exclude) {\n retryArgs.push(\"--exclude\", options.exclude);\n }\n if (options.limitUnits) {\n retryArgs.push(\"--limit-units\", options.limitUnits);\n }\n if (options.url) {\n retryArgs.push(\"--url\", options.url, \"--selector\", options.selector);\n }\n if (options.capture) {\n retryArgs.push(\"--capture\", path.resolve(options.capture));\n }\n if (options.writingContext) {\n retryArgs.push(\n \"--writing-context\",\n path.resolve(options.writingContext)\n );\n }\n retryArgs.push(\"--\", ...paths);\n const rerun =\n result.status === \"incomplete\"\n ? retryArgs.map(quote).join(\" \")\n : undefined;\n const reported = { ...result, reportPath, rerun };\n const json = renderJson(reported, result.manifest);\n if (reportPath) {\n fs.mkdirSync(options.resultsDir, { recursive: true });\n fs.writeFileSync(reportPath, json);\n }\n if (options.output === \"json\") {\n process.stdout.write(json);\n } else if (options.output === \"sarif\") {\n process.stdout.write(\n renderSarif(\n reported,\n result.rulesLoaded,\n program.version() ?? \"0.0.0\"\n )\n );\n } else {\n process.stdout.write(\n renderTty(reported, { verbose: options.verbose })\n );\n }\n process.exitCode = result.exitCode;\n }\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { parse } from \"yaml\";\n\nimport { InputError } from \"../lib/errors.js\";\nimport type { Rule } from \"../types.js\";\n\nexport interface DiscoveredSource {\n path: string;\n skill: string;\n kind: \"entrypoint\" | \"rule\" | \"guidance\";\n title: string;\n sections: { title: string; line: number }[];\n citedBy: string[];\n status: \"cited\" | \"needs-triage\";\n diagnostic?: string;\n}\n\n// Discovery never executes source instructions or turns a document into a rule.\nexport const discoverSkills = (\n root: string,\n rules: Rule[]\n): DiscoveredSource[] => {\n const absolute = path.resolve(root);\n if (!fs.existsSync(absolute) || !fs.statSync(absolute).isDirectory()) {\n throw new InputError(\n \"INVALID_SKILL_SOURCE\",\n `Skill source must be a directory: ${absolute}`\n );\n }\n const entries: DiscoveredSource[] = [];\n const visit = (dir: string, owner?: string, skillRoot?: string): void => {\n const skill = fs.existsSync(path.join(dir, \"SKILL.md\"))\n ? path.basename(dir)\n : owner;\n const base = skill !== owner ? dir : skillRoot;\n for (const entry of fs\n .readdirSync(dir, { withFileTypes: true })\n .toSorted((a, b) => a.name.localeCompare(b.name))) {\n if (\n entry.isSymbolicLink() ||\n [\n \"node_modules\",\n \".git\",\n \"dist\",\n \"evals\",\n \"evaluations\",\n \"scripts\",\n \"agents\",\n ].includes(entry.name)\n ) {\n continue;\n }\n const file = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n visit(file, skill, base);\n continue;\n }\n if (\n !skill ||\n !base ||\n !entry.name.endsWith(\".md\") ||\n /evaluation-scenarios/.test(entry.name)\n ) {\n continue;\n }\n const text = fs.readFileSync(file, \"utf-8\");\n const sections = text\n .split(\"\\n\")\n .flatMap((line, i) =>\n /^#{1,3} /.test(line)\n ? [{ line: i + 1, title: line.replace(/^#+ /, \"\") }]\n : []\n );\n let title = sections[0]?.title ?? entry.name;\n let diagnostic: string | undefined;\n const front = text.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/);\n if (front) {\n try {\n const value = parse(front[1]) as { title?: unknown } | null;\n if (typeof value?.title === \"string\") {\n title = value.title;\n }\n } catch {\n diagnostic =\n \"Frontmatter could not be parsed; retained for manual triage\";\n }\n }\n const relative = path.relative(base, file).split(path.sep).join(\"/\");\n const canonical = `skills/${skill}/${relative}`;\n const citedBy = rules\n .filter((r) => r.source.path === canonical)\n .map((r) => r.id);\n const kind =\n entry.name === \"SKILL.md\"\n ? \"entrypoint\"\n : /^rules(?:-arch|-ax)?\\//.test(relative) &&\n !entry.name.startsWith(\"_\")\n ? \"rule\"\n : \"guidance\";\n entries.push({\n citedBy,\n diagnostic,\n kind,\n path: file,\n sections,\n skill,\n status: citedBy.length ? \"cited\" : \"needs-triage\",\n title,\n });\n }\n };\n visit(absolute);\n return entries;\n};\n","import type { Command } from \"commander\";\n\nimport { discoverSkills } from \"../rules/discover.js\";\nimport { loadRules, resolveRulesDir } from \"../rules/load.js\";\n\nexport function registerRulesCommand(program: Command): void {\n const rules = program\n .command(\"rules\")\n .description(\"Inspect and validate the rule files\");\n rules\n .command(\"discover <sources...>\")\n .description(\n \"Inventory skill entrypoints, rule folders, and guidance without activating rules\"\n )\n .option(\"--rules <path>\", \"Rules directory used for citation coverage\")\n .action((sources: string[], options: { rules?: string }) => {\n const loaded = loadRules(resolveRulesDir(options.rules));\n const inventory = sources.flatMap((source) =>\n discoverSkills(source, loaded)\n );\n process.stdout.write(\n `${JSON.stringify({ inventory, note: \"Citations are provenance, not complete semantic coverage. Uncited sources need triage.\", sources }, null, 2)}\\n`\n );\n });\n rules\n .command(\"list\")\n .description(\"List rules with tier, status and category\")\n .option(\"--rules <path>\", \"Rules directory\")\n .option(\"--allow-draft\", \"Include draft rules\")\n .action((options: { rules?: string; allowDraft?: boolean }) => {\n const list = loadRules(resolveRulesDir(options.rules), {\n allowDraft: options.allowDraft ?? false,\n });\n for (const r of list) {\n process.stdout.write(\n `${r.id.padEnd(44)} ${r.tier.padEnd(10)} ${r.status.padEnd(11)} ${r.severity.padEnd(8)} ${r.categoryId}\\n`\n );\n }\n process.stdout.write(`${list.length} rules\\n`);\n });\n rules\n .command(\"check\")\n .description(\"Validate every rule file; exits 1 on the first invalid rule\")\n .option(\"--rules <path>\", \"Rules directory\")\n .option(\"--allow-draft\", \"Accept rules with status draft\")\n .action((options: { rules?: string; allowDraft?: boolean }) => {\n const dir = resolveRulesDir(options.rules);\n const all = loadRules(dir, { allowDraft: true });\n const drafts = all.filter((r) => r.status === \"draft\");\n const active = all.length - drafts.length;\n if (drafts.length > 0 && !options.allowDraft) {\n process.stderr.write(\n `FAIL: ${drafts.length} draft rule${drafts.length === 1 ? \"\" : \"s\"} (${drafts.map((r) => r.id).join(\", \")}). Finish the question or pass --allow-draft.\\n`\n );\n process.exitCode = 1;\n return;\n }\n process.stdout.write(\n `PASS: ${active} active rule${active === 1 ? \"\" : \"s\"}${drafts.length ? `, ${drafts.length} draft` : \"\"} in ${dir}\\n`\n );\n });\n}\n","import { InputError } from \"../lib/errors.js\";\nimport { matchesAny } from \"../lib/glob.js\";\nimport type { DocType, Rule } from \"../types.js\";\n\nconst artifacts = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/.next/**\",\n \"**/results/**\",\n \"**/docs/archive/**\",\n \"**/.captain/**\",\n];\nconst internal = [\n \"**/.claude/**\",\n \"**/.agents/**\",\n \"**/skills/**\",\n \"**/AGENTS.md\",\n \"**/CLAUDE.md\",\n \"**/SKILL.md\",\n];\nexport const PROFILE_NAMES = [\n \"product\",\n \"writing\",\n \"instructions\",\n \"architecture\",\n \"all\",\n] as const;\nexport type ProfileName = (typeof PROFILE_NAMES)[number];\nexport interface ScanProfile {\n name: ProfileName;\n objective: string;\n include: string[];\n exclude: string[];\n docTypes: { glob: string; type: DocType }[];\n advisory: string[];\n}\nexport const profileFor = (name: string): ScanProfile => {\n if (!PROFILE_NAMES.includes(name as ProfileName)) {\n throw new InputError(\n \"INVALID_PROFILE\",\n `Choose a scan profile: ${PROFILE_NAMES.join(\", \")}`\n );\n }\n const common = {\n advisory: [],\n docTypes: [],\n exclude: artifacts,\n name: name as ProfileName,\n };\n switch (name) {\n case \"product\": {\n return {\n ...common,\n exclude: [\n ...artifacts,\n ...internal,\n \"**/*.{test,spec,stories}.{tsx,jsx}\",\n ],\n include: [\"**/*.{tsx,jsx,css,scss}\"],\n objective:\n \"Review application interface copy, typography, interaction and motion\",\n };\n }\n case \"writing\": {\n return {\n ...common,\n advisory: [\"copywriting-long-sentence\", \"typography-straight-quotes\"],\n docTypes: [\n { glob: \"**/content/writing/**/*.{md,mdx}\", type: \"personal\" },\n ],\n exclude: [...artifacts, ...internal, \"**/docs/plans/**\"],\n include: [\n \"**/content/**/*.{md,mdx}\",\n \"**/README.md\",\n \"**/public/**/*.md\",\n \"**/docs/**/*.{md,mdx}\",\n ],\n objective: \"Review published prose and consumer documentation\",\n };\n }\n case \"instructions\": {\n return {\n ...common,\n advisory: [\"copywriting-long-sentence\", \"typography-straight-quotes\"],\n include: [...internal, \"**/docs/plans/**/*.md\"],\n objective:\n \"Review repository instructions, skill authoring, and implementation plans\",\n };\n }\n case \"architecture\": {\n return {\n ...common,\n exclude: [...artifacts, ...internal],\n include: [\"**/*.{ts,tsx,js,jsx,mjs,cjs,mts,cts,json}\"],\n objective: \"Check declared package and repository contracts\",\n };\n }\n default: {\n return {\n ...common,\n exclude: [],\n include: [\"**/*\"],\n objective: \"Audit all supported inputs with the full rule catalog\",\n };\n }\n }\n};\nexport const profileRules = (profile: ScanProfile, rules: Rule[]): Rule[] =>\n rules.filter((rule) => {\n if (profile.name === \"all\") {\n return true;\n }\n if (profile.name === \"architecture\") {\n return [\"architecture\", \"dx\"].includes(rule.domain);\n }\n if (profile.name === \"instructions\") {\n return (\n rule.domain === \"authoring\" ||\n rule.id.startsWith(\"copywriting-document-\")\n );\n }\n if (profile.name === \"writing\") {\n return [\"copywriting\", \"typography\"].includes(rule.domain);\n }\n return (\n ![\"architecture\", \"dx\", \"authoring\"].includes(rule.domain) &&\n !rule.id.startsWith(\"copywriting-readme-\") &&\n !rule.id.startsWith(\"copywriting-document-\")\n );\n });\nexport const profileIncludes = (profile: ScanProfile, file: string): boolean =>\n matchesAny(file, profile.include) && !matchesAny(file, profile.exclude);\n","import { randomUUID, createHash } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { InputError } from \"../lib/errors.js\";\n\nexport const hash = (value: unknown): string =>\n createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\nexport const object = (value: unknown): value is Record<string, unknown> =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\nexport const readJson = (file: string): unknown => {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf-8\"));\n } catch {\n throw new InputError(\n \"INVALID_SCAN_INPUT\",\n `Cannot read JSON input: ${file}`\n );\n }\n};\nexport const writeJson = (file: string, value: unknown): void => {\n fs.mkdirSync(path.dirname(path.resolve(file)), { recursive: true });\n const temp = `${file}.${randomUUID()}.tmp`;\n try {\n fs.writeFileSync(temp, `${JSON.stringify(value, null, 2)}\\n`, {\n flag: \"wx\",\n });\n fs.renameSync(temp, file);\n } finally {\n fs.rmSync(temp, { force: true });\n }\n};\n","import { normaliseText } from \"../extract/units.js\";\nimport { InputError } from \"../lib/errors.js\";\nimport type { Finding, LintResult, Unit } from \"../types.js\";\nimport type { ScanProfile } from \"./profiles.js\";\nimport { hash, object, readJson } from \"./storage.js\";\n\nexport interface ScanFinding extends Finding {\n fingerprint: string;\n excerpt: string;\n lifecycle: \"new\" | \"existing\" | \"resolved\" | \"unverified\";\n decision?: { status: \"dismissed\" | \"accepted\" | \"open\"; reason: string };\n origin: \"taste-lint\" | \"dependency-cruiser\";\n}\nexport interface ScanReport {\n version: 1;\n kind: \"taste-lint-scan\";\n root: string;\n diagnostics: string[];\n architecture?: { contentHash: string; modules: number; incomplete: boolean };\n signature: string;\n profile: ScanProfile;\n files: string[];\n status: LintResult[\"status\"];\n findings: ScanFinding[];\n resolved: ScanFinding[];\n unknowns: LintResult[\"unknowns\"];\n coverage: LintResult[\"coverage\"];\n usage: LintResult[\"usage\"];\n estimated: LintResult[\"estimated\"];\n reporting: { since?: string; visible: string[] };\n summary: {\n total: number;\n new: number;\n existing: number;\n dismissed: number;\n resolved: number;\n unverified: number;\n visible: number;\n failing: number;\n review: number;\n unknown: number;\n };\n exitCode: number;\n}\nexport const identify = (findings: Finding[], units: Unit[]): ScanFinding[] => {\n const byId = new Map(units.map((u) => [u.id, u]));\n const occurrences = new Map<string, number>();\n return findings.map((finding) => {\n const unit = byId.get(finding.unitId);\n const text =\n unit?.kind === \"source\"\n ? (unit.text.split(\"\\n\")[finding.line - 1] ?? finding.evidence)\n : (unit?.text ?? finding.evidence);\n const key = hash([\n finding.ruleId,\n finding.file,\n unit?.kind,\n normaliseText(text),\n ]);\n const occurrence = occurrences.get(key) ?? 0;\n occurrences.set(key, occurrence + 1);\n return {\n ...finding,\n excerpt: text.slice(0, 1200),\n fingerprint: hash([key, occurrence]),\n lifecycle: \"new\",\n origin: \"taste-lint\",\n };\n });\n};\nexport const readReport = (file: string): ScanReport => {\n const raw = readJson(file);\n if (\n !object(raw) ||\n raw.kind !== \"taste-lint-scan\" ||\n raw.version !== 1 ||\n typeof raw.signature !== \"string\" ||\n typeof raw.root !== \"string\" ||\n ![\"complete\", \"incomplete\", \"dry-run\"].includes(String(raw.status)) ||\n !Array.isArray(raw.findings) ||\n !Array.isArray(raw.files) ||\n !object(raw.profile) ||\n !object(raw.reporting) ||\n !Array.isArray(raw.reporting.visible) ||\n !raw.reporting.visible.every((id) => typeof id === \"string\") ||\n !raw.files.every((item) => typeof item === \"string\") ||\n new Set(raw.findings.map((f) => (object(f) ? f.fingerprint : undefined)))\n .size !== raw.findings.length ||\n !raw.findings.every(\n (f) =>\n object(f) &&\n typeof f.fingerprint === \"string\" &&\n /^[a-f0-9]{64}$/.test(f.fingerprint) &&\n typeof f.file === \"string\" &&\n typeof f.ruleId === \"string\" &&\n typeof f.excerpt === \"string\" &&\n typeof f.fixHint === \"string\" &&\n Number.isInteger(f.line) &&\n Number.isInteger(f.endLine) &&\n typeof f.message === \"string\"\n )\n ) {\n throw new InputError(\n \"INVALID_SCAN_REPORT\",\n \"Expected a version 1 taste-lint scan report.\"\n );\n }\n return raw as unknown as ScanReport;\n};\nexport type Decisions = Record<\n string,\n { status: \"dismissed\" | \"accepted\" | \"open\"; reason: string }\n>;\nexport const readDecisions = (file?: string, signature?: string): Decisions => {\n if (!file) {\n return {};\n }\n const raw = readJson(file);\n if (!object(raw) || raw.version !== 1 || !object(raw.decisions)) {\n throw new InputError(\n \"INVALID_DECISIONS\",\n \"Expected version 1 decisions with a decisions map.\"\n );\n }\n if (signature && raw.signature !== signature) {\n throw new InputError(\n \"INCOMPATIBLE_DECISIONS\",\n \"Review decisions belong to a different scan policy. Review them again for this profile and rule set.\"\n );\n }\n for (const [key, value] of Object.entries(raw.decisions)) {\n if (\n !/^[a-f0-9]{64}$/.test(key) ||\n !object(value) ||\n ![\"dismissed\", \"accepted\", \"open\"].includes(String(value.status)) ||\n typeof value.reason !== \"string\" ||\n !value.reason.trim()\n ) {\n throw new InputError(\n \"INVALID_DECISIONS\",\n \"Every decision needs a fingerprint, accepted/dismissed status, and reason.\"\n );\n }\n }\n return raw.decisions as Decisions;\n};\nexport const reconcile = (\n current: ScanFinding[],\n previous: ScanReport | undefined,\n complete: boolean,\n unknowns: LintResult[\"unknowns\"],\n decisions: Decisions\n): ScanFinding[] => {\n const old = new Map(previous?.findings.map((f) => [f.fingerprint, f]));\n const ids = new Set(current.map((f) => f.fingerprint));\n for (const finding of current) {\n finding.lifecycle = old.has(finding.fingerprint) ? \"existing\" : \"new\";\n finding.decision =\n decisions[finding.fingerprint] ?? old.get(finding.fingerprint)?.decision;\n }\n return [...old.values()]\n .filter((f) => !ids.has(f.fingerprint))\n .map((f) => ({\n ...f,\n lifecycle:\n complete &&\n !unknowns.some((u) => u.file === f.file && u.ruleId === f.ruleId)\n ? \"resolved\"\n : \"unverified\",\n }));\n};\nexport const renderScan = (report: ScanReport, limit = 20): string => {\n const visible = new Set(report.reporting.visible);\n const groups = new Map<string, ScanFinding[]>();\n for (const finding of report.findings.filter((f) =>\n visible.has(f.fingerprint)\n )) {\n const list = groups.get(finding.ruleId) ?? [];\n list.push(finding);\n groups.set(finding.ruleId, list);\n }\n const ranked = [...groups.values()].toSorted(\n (a, b) =>\n Number(b[0].band === \"act\") - Number(a[0].band === \"act\") ||\n b.length - a.length ||\n a[0].ruleId.localeCompare(b[0].ruleId)\n );\n const s = report.summary;\n const coverage = Object.values(report.coverage?.byRule ?? {});\n return [\n `${report.profile.name}: ${report.status}; ${report.files.length} files`,\n `${s.visible} visible checks (${s.failing} failing, ${s.review} review); ${s.total} total; ${s.dismissed} dismissed; ${s.unknown} unknown`,\n ...report.diagnostics,\n `Rule coverage: ${coverage.filter((r) => r.eligible === 0).length} with no applicable inputs; ${coverage.filter((r) => r.eligible > 0 && r.negative === r.eligible).length} with all applicable checks negative; ${coverage.filter((r) => r.pending > 0).length} with pending evaluations`,\n `${s.new} new; ${s.existing} existing; ${s.resolved} resolved; ${s.unverified} unverified`,\n ...ranked\n .slice(0, limit)\n .map(\n (group) =>\n `${group[0].ruleId}: ${group.length} checks in ${new Set(group.map((f) => f.file)).size} files\\n ${group[0].file}:${group[0].line} ${group[0].message}\\n ${group[0].fixHint}`\n ),\n ...(ranked.length > limit\n ? [\n `${ranked.length - limit} further rule groups are available in the JSON report.`,\n ]\n : []),\n ...(report.estimated\n ? [\n `Estimated live work: ${report.estimated.requests} requests, $${report.estimated.costUsd.toFixed(4)}`,\n ]\n : []),\n \"\",\n ].join(\"\\n\");\n};\n","import path from \"node:path\";\n\nimport { InputError } from \"../lib/errors.js\";\nimport type { ScanFinding } from \"./report.js\";\nimport { hash, object, readJson } from \"./storage.js\";\n\nconst invalid = (): never => {\n throw new InputError(\n \"INVALID_GRAPH_REPORT\",\n \"Expected dependency-cruiser JSON with modules and summary.violations, using repository-relative paths.\"\n );\n};\nconst local = (value: unknown): value is string =>\n typeof value === \"string\" &&\n !!value &&\n !path.isAbsolute(value) &&\n !value.includes(\"\\\\\") &&\n !value.split(\"/\").includes(\"..\") &&\n !value.includes(\"\\0\");\n\n// Consume dependency-cruiser's documented ICruiseResult/IViolation boundary.\n// Graph construction and repository configuration execution stay in that tool.\nexport const importArchitecture = (\n file: string\n): {\n findings: ScanFinding[];\n digest: string;\n modules: string[];\n incomplete: boolean;\n contentHash: string;\n} => {\n const raw = readJson(file);\n if (\n !object(raw) ||\n !Array.isArray(raw.modules) ||\n !object(raw.summary) ||\n !Array.isArray(raw.summary.violations)\n ) {\n return invalid();\n }\n const modules: string[] = [];\n let incomplete = false;\n for (const mod of raw.modules) {\n if (!object(mod) || !local(mod.source)) {\n return invalid();\n }\n modules.push(mod.source);\n if (\n mod.couldNotResolve === true ||\n (Array.isArray(mod.dependencies) &&\n mod.dependencies.some((d) => object(d) && d.couldNotResolve === true))\n ) {\n incomplete = true;\n }\n }\n if (\n object(raw.summary.environment) &&\n Array.isArray(raw.summary.environment.issues) &&\n raw.summary.environment.issues.length\n ) {\n incomplete = true;\n }\n incomplete ||= modules.length === 0;\n const findings: ScanFinding[] = [];\n for (const v of raw.summary.violations) {\n if (\n !object(v) ||\n !object(v.rule) ||\n typeof v.rule.name !== \"string\" ||\n !local(v.from) ||\n typeof v.to !== \"string\" ||\n ![\"error\", \"warn\", \"info\", \"ignore\"].includes(String(v.rule.severity))\n ) {\n return invalid();\n }\n if (v.rule.severity === \"ignore\") {\n continue;\n }\n const ruleId = `dependency-cruiser/${v.rule.name}`;\n const excerpt = `${v.from} -> ${v.to}`;\n findings.push({\n band: v.rule.severity === \"error\" ? \"act\" : \"review\",\n categoryId: \"repository-contracts\",\n column: 1,\n domain: \"architecture\",\n endColumn: 1,\n endLine: 1,\n evidence: excerpt,\n excerpt,\n file: v.from,\n fingerprint: hash([ruleId, v.from, v.to, v.cycle, v.via]),\n fixHint:\n typeof v.rule.comment === \"string\"\n ? v.rule.comment\n : \"Follow the declared dependency policy; rerun dependency-cruiser with the same configuration.\",\n lifecycle: \"new\",\n line: 1,\n message: v.rule.name,\n origin: \"dependency-cruiser\",\n probability: 1,\n ruleId,\n severity: v.rule.severity === \"error\" ? \"major\" : \"minor\",\n suppressed: false,\n tier: \"mechanical\",\n unitId: hash([v.from, v.to]),\n });\n }\n return {\n contentHash: hash(raw),\n digest: hash([\n raw.summary.optionsUsed ?? {},\n raw.summary.ruleSetUsed ?? {},\n raw.summary.environment && object(raw.summary.environment)\n ? raw.summary.environment.version\n : undefined,\n ]),\n findings,\n incomplete,\n modules,\n };\n};\n","import { execFileSync } from \"node:child_process\";\n\nimport { InputError } from \"../lib/errors.js\";\n\nconst git = (root: string, args: string[]): string => {\n try {\n return execFileSync(\"git\", [\"-C\", root, ...args], {\n encoding: \"utf-8\",\n maxBuffer: 32 * 1024 * 1024,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch {\n throw new InputError(\n \"INVALID_GIT_BASE\",\n \"Cannot compare Git revisions. Use a valid base in the scan repository.\"\n );\n }\n};\nexport interface ChangedLines {\n ranges: Map<string, [number, number][]>;\n untracked: Set<string>;\n base: string;\n}\nexport const changedLines = (root: string, ref: string): ChangedLines => {\n const base = git(root, [\n \"rev-parse\",\n \"--verify\",\n \"--end-of-options\",\n `${ref}^{commit}`,\n ]).trim();\n const names = git(root, [\n \"diff\",\n \"--relative\",\n \"--no-ext-diff\",\n \"--no-textconv\",\n \"--no-renames\",\n \"--name-only\",\n \"-z\",\n base,\n \"--\",\n ])\n .split(\"\\0\")\n .filter(Boolean);\n const ranges = new Map<string, [number, number][]>();\n for (const file of names) {\n const patch = git(root, [\n \"diff\",\n \"--relative\",\n \"--no-ext-diff\",\n \"--no-textconv\",\n \"--no-renames\",\n \"--unified=0\",\n base,\n \"--\",\n file,\n ]);\n const lines: [number, number][] = [];\n for (const match of patch.matchAll(\n /^@@ -\\d+(?:,\\d+)? \\+(\\d+)(?:,(\\d+))? @@/gm\n )) {\n const start = Number(match[1]);\n const length = Number(match[2] ?? 1);\n if (length > 0) {\n lines.push([start, start + length - 1]);\n }\n }\n ranges.set(file, lines);\n }\n const untracked = new Set(\n git(root, [\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"])\n .split(\"\\0\")\n .filter(Boolean)\n );\n return { base, ranges, untracked };\n};\nexport const touchesChange = (\n diff: ChangedLines,\n file: string,\n start: number,\n end: number\n): boolean =>\n diff.untracked.has(file) ||\n (diff.ranges.get(file) ?? []).some(([a, b]) => start <= b && end >= a);\n","import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport { loadCorpus, splitFor } from \"../eval/corpus.js\";\nimport { InputError } from \"../lib/errors.js\";\nimport { loadRules, resolveRulesDir } from \"../rules/load.js\";\nimport { buildQuestion } from \"../rules/question.js\";\nimport type { CorpusItem, Rule, SystemOneNoul, Unit } from \"../types.js\";\nimport { hash, object, readJson } from \"./storage.js\";\n\nexport interface LabelSample {\n id: string;\n ruleId: string;\n criterion: string;\n rubric?: SystemOneNoul;\n label: boolean | null;\n item: Omit<CorpusItem, \"labels\" | \"labelSource\">;\n}\nexport const makeSamples = (\n units: Unit[],\n rules: Rule[],\n answers: Map<string, Record<string, number>>,\n negatives: Map<string, Set<string>>,\n perStratum = 3,\n sourceRepo = \"scan\"\n): LabelSample[] => {\n const buckets = new Map<string, LabelSample[]>();\n const seen = new Set<string>();\n const semanticRules = rules.filter((rule) => rule.question);\n for (const unit of units) {\n for (const rule of semanticRules) {\n const probability =\n answers.get(unit.id)?.[rule.id] ??\n (negatives.get(unit.id)?.has(rule.id) ? 0 : undefined);\n if (probability === undefined) {\n continue;\n }\n const { docType, role, headingAbove } = unit.context;\n const context = {\n docType,\n headingAbove,\n role,\n ...Object.fromEntries(\n (rule.question!.context ?? [])\n .filter((key) => key !== \"neighbours\")\n .map((key) => [key, unit.context[key as keyof typeof unit.context]])\n ),\n };\n const rubric = buildQuestion(rule);\n const neighbours = rule.question!.context?.includes(\"neighbours\")\n ? unit.neighbours\n : undefined;\n const evidence = [\n rule.id,\n unit.text,\n context,\n neighbours,\n unit.classes,\n rubric,\n ];\n const unique = hash(evidence);\n if (seen.has(unique)) {\n continue;\n }\n seen.add(unique);\n const id = `scan-${hash([sourceRepo, unit.file, ...evidence]).slice(0, 24)}`;\n const sample: LabelSample = {\n criterion: rule.question!.instructions,\n id,\n item: {\n categoryId: rule.categoryId,\n classes: unit.classes,\n context,\n id,\n kind: unit.kind,\n neighbours,\n source: { path: unit.file, repo: sourceRepo },\n split: splitFor(`${sourceRepo}/${unit.file}`),\n text: unit.text,\n },\n label: null,\n rubric,\n ruleId: rule.id,\n };\n const bucket = `${rule.id}:${docType}:${probability < rule.thresholds.review ? \"negative\" : probability < rule.thresholds.act ? \"review\" : \"high\"}`;\n const list = buckets.get(bucket) ?? [];\n list.push(sample);\n buckets.set(bucket, list);\n }\n }\n return [...buckets.values()]\n .flatMap((list) =>\n list.toSorted((a, b) => a.id.localeCompare(b.id)).slice(0, perStratum)\n )\n .toSorted((a, b) => a.id.localeCompare(b.id));\n};\nexport const labelsToCorpus = (\n file: string,\n destination: string,\n rulesDir?: string\n): number => {\n const raw = readJson(file);\n if (\n !object(raw) ||\n (raw.version !== 1 && raw.version !== 2) ||\n !Array.isArray(raw.samples)\n ) {\n throw new InputError(\n \"INVALID_LABELS\",\n \"Expected a version 1 or 2 blind sample file.\"\n );\n }\n if (raw.completed !== undefined && raw.completed !== raw.samples.length) {\n throw new InputError(\n \"INVALID_LABELS\",\n \"Labeling is incomplete. Review every sample before importing.\"\n );\n }\n const annotation = raw.annotation;\n const ai = object(annotation) && annotation.source === \"ai\";\n if (\n annotation !== undefined &&\n (!ai ||\n typeof annotation.model !== \"string\" ||\n !annotation.model.trim() ||\n typeof annotation.promptHash !== \"string\" ||\n !/^[a-f0-9]{64}$/.test(annotation.promptHash))\n ) {\n throw new InputError(\n \"INVALID_LABELS\",\n \"AI annotation requires a model and prompt hash.\"\n );\n }\n const ids = new Set<string>();\n const items: CorpusItem[] = [];\n for (const row of raw.samples) {\n if (\n !object(row) ||\n typeof row.id !== \"string\" ||\n ids.has(row.id) ||\n typeof row.ruleId !== \"string\" ||\n (raw.version === 2 &&\n (!object(row.rubric) ||\n row.rubric.type !== \"noul\" ||\n typeof row.criterion !== \"string\" ||\n row.rubric.instructions !== row.criterion)) ||\n !object(row.item) ||\n row.item.id !== row.id ||\n (row.label !== null && typeof row.label !== \"boolean\")\n ) {\n throw new InputError(\n \"INVALID_LABELS\",\n \"Samples require unique IDs and boolean or null labels.\"\n );\n }\n ids.add(row.id);\n if (row.label === null) {\n continue;\n }\n items.push({\n ...row.item,\n labelSource: ai ? \"ai\" : \"hand\",\n ...(ai\n ? {\n labelModel: annotation.model,\n labelPromptHash: annotation.promptHash,\n }\n : {}),\n labels: { [row.ruleId]: row.label },\n } as CorpusItem);\n }\n if (!items.length) {\n throw new InputError(\n \"INVALID_LABELS\",\n \"No labels supplied. Set label to true or false after review.\"\n );\n }\n const temporary = fs.mkdtempSync(path.join(os.tmpdir(), \"taste-labels-\"));\n try {\n fs.writeFileSync(\n path.join(temporary, \"labels.jsonl\"),\n items.map((item) => JSON.stringify(item)).join(\"\\n\")\n );\n loadCorpus(\n temporary,\n loadRules(resolveRulesDir(rulesDir), { allowDraft: true })\n );\n } finally {\n fs.rmSync(temporary, { force: true, recursive: true });\n }\n // Destination is an explicit export, never the packaged corpus implicitly.\n fs.writeFileSync(\n destination,\n `${items.map((item) => JSON.stringify(item)).join(\"\\n\")}\\n`,\n { flag: \"wx\" }\n );\n return items.length;\n};\n","import fs from \"node:fs\";\n\nimport { SUPPORTED_GLOBS } from \"../extract/index.js\";\nimport { loadConfig } from \"../lib/config.js\";\nimport { InputError } from \"../lib/errors.js\";\nimport { collectFiles } from \"../lib/glob.js\";\nimport { runLint } from \"../lint.js\";\nimport type { LintContext } from \"../lint.js\";\nimport { loadRules, resolveRulesDir } from \"../rules/load.js\";\nimport { SEVERITY_RANK } from \"../types.js\";\nimport type { Rule, Unit } from \"../types.js\";\nimport { importArchitecture } from \"./architecture.js\";\nimport { changedLines, touchesChange } from \"./git.js\";\nimport { profileFor, profileIncludes, profileRules } from \"./profiles.js\";\nimport { identify, readReport, readDecisions, reconcile } from \"./report.js\";\nimport type { ScanReport } from \"./report.js\";\nimport { makeSamples } from \"./samples.js\";\nimport type { LabelSample } from \"./samples.js\";\nimport { hash } from \"./storage.js\";\n\nexport interface ScanOptions {\n root: string;\n targets: string[];\n profile?: string;\n rulesDir?: string;\n only?: string[];\n exclude?: string[];\n dryRun?: boolean;\n mechanicalOnly?: boolean;\n resultsDir?: string;\n model?: string;\n baseline?: string;\n decisions?: string;\n since?: string;\n newOnly?: boolean;\n dependencyCruiser?: string;\n samples?: boolean;\n}\nexport const runScan = async (\n options: ScanOptions,\n ctx: LintContext = {}\n): Promise<{ report: ScanReport; rules: Rule[]; samples: LabelSample[] }> => {\n if (options.newOnly && !options.baseline) {\n throw new InputError(\"INVALID_ARGUMENT\", \"--new-only requires --baseline.\");\n }\n const root = fs.realpathSync(loadConfig(options.root).root);\n const profile = profileFor(options.profile ?? \"product\");\n const config = loadConfig(root, profile.docTypes);\n const exclude = [\n ...config.exclude,\n ...(options.exclude ?? []),\n ...profile.exclude,\n ];\n const files = collectFiles(\n root,\n options.targets,\n SUPPORTED_GLOBS,\n exclude\n ).filter((file) => profileIncludes(profile, file));\n const rules = profileRules(\n profile,\n loadRules(resolveRulesDir(options.rulesDir), { only: options.only })\n );\n for (const rule of rules) {\n if (profile.advisory.includes(rule.id)) {\n rule.status = \"review-only\";\n }\n }\n if (!rules.length) {\n throw new InputError(\n \"EMPTY_RULE_SELECTION\",\n \"No rules match the selected profile and IDs.\"\n );\n }\n const graph = options.dependencyCruiser\n ? importArchitecture(options.dependencyCruiser)\n : undefined;\n const signature = hash({\n config: { ...config, root: undefined },\n exclude,\n graph: graph?.digest,\n mechanicalOnly: !!options.mechanicalOnly,\n model: options.model ?? \"jev-latest\",\n profile,\n root,\n rules: rules.map(({ file: _file, check, ...rule }) => ({\n ...rule,\n check: check?.toString(),\n })),\n targets: options.targets.toSorted(),\n });\n const baseline = options.baseline ? readReport(options.baseline) : undefined;\n if (\n baseline &&\n (baseline.signature !== signature ||\n baseline.root !== root ||\n baseline.status !== \"complete\")\n ) {\n throw new InputError(\n \"INCOMPATIBLE_BASELINE\",\n \"Baseline must be a complete scan of this root with the same profile, targets, rules, model and evaluation mode.\"\n );\n }\n const decisions = readDecisions(options.decisions, signature);\n const diff = options.since ? changedLines(root, options.since) : undefined;\n let units: Unit[] = [];\n let samples: LabelSample[] = [];\n const result = await runLint(\n {\n advisoryRules: profile.advisory,\n docTypes: profile.docTypes,\n dryRun: options.dryRun,\n exclude,\n mechanicalOnly: options.mechanicalOnly,\n model: options.model,\n only: rules.map((r) => r.id),\n resultsDir: options.resultsDir,\n root,\n rulesDir: options.rulesDir,\n targets: files,\n },\n {\n ...ctx,\n onEvidence: (u, answers, negatives) => {\n units = u;\n if (options.samples) {\n samples = makeSamples(u, rules, answers, negatives, 3, root);\n }\n ctx.onEvidence?.(u, answers, negatives);\n },\n }\n );\n const findings = identify(\n (result.ruleFindings ?? []).filter((f) => !f.suppressed),\n units\n );\n for (const finding of graph?.findings ?? []) {\n if (files.includes(finding.file)) {\n findings.push(finding);\n }\n }\n const unresolvedFiles = new Set(\n units\n .filter((u) => u.context.parseError || u.facts?.parseError)\n .map((u) => u.file)\n );\n const complete =\n result.status === \"complete\" && files.length > 0 && !graph?.incomplete;\n const resolved = reconcile(\n findings,\n baseline,\n complete,\n result.unknowns,\n decisions\n );\n for (const finding of resolved) {\n if (\n unresolvedFiles.has(finding.file) ||\n (finding.origin === \"dependency-cruiser\" &&\n !graph?.modules.includes(finding.file))\n ) {\n finding.lifecycle = \"unverified\";\n }\n }\n const visible = findings.filter(\n (f) =>\n f.decision?.status !== \"dismissed\" &&\n (!options.newOnly || f.lifecycle === \"new\") &&\n (!diff ||\n (f.origin === \"dependency-cruiser\"\n ? diff.untracked.has(f.file) ||\n (diff.ranges.get(f.file)?.length ?? 0) > 0\n : touchesChange(diff, f.file, f.line, f.endLine)))\n );\n const failing = visible.filter(\n (f) => f.band === \"act\" && SEVERITY_RANK[f.severity] <= SEVERITY_RANK.minor\n ).length;\n const report: ScanReport = {\n architecture: graph\n ? {\n contentHash: graph.contentHash,\n incomplete: graph.incomplete,\n modules: graph.modules.length,\n }\n : undefined,\n coverage: result.coverage,\n diagnostics: [\n ...(result.scope?.diagnostics ?? []),\n ...(graph?.incomplete\n ? [\n \"Imported dependency graph contains unresolved edges or environment issues.\",\n ]\n : []),\n ],\n estimated: result.estimated,\n exitCode:\n result.status === \"incomplete\" || files.length === 0 || graph?.incomplete\n ? 2\n : failing > 0\n ? 1\n : 0,\n files,\n findings,\n kind: \"taste-lint-scan\",\n profile,\n reporting: {\n since: diff?.base,\n visible: visible.map((f) => f.fingerprint),\n },\n resolved,\n root,\n signature,\n status: !files.length || graph?.incomplete ? \"incomplete\" : result.status,\n summary: {\n dismissed: findings.filter((f) => f.decision?.status === \"dismissed\")\n .length,\n existing: findings.filter((f) => f.lifecycle === \"existing\").length,\n failing,\n new: findings.filter((f) => f.lifecycle === \"new\").length,\n resolved: resolved.filter((f) => f.lifecycle === \"resolved\").length,\n review: visible.filter((f) => f.band === \"review\").length,\n total: findings.length,\n unknown: result.unknowns.length,\n unverified: resolved.filter((f) => f.lifecycle === \"unverified\").length,\n visible: visible.length,\n },\n unknowns: result.unknowns,\n usage: result.usage,\n version: 1,\n };\n return { report, rules, samples };\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport type { Command } from \"commander\";\n\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { InputError } from \"../lib/errors.js\";\nimport { renderSarif } from \"../report/sarif.js\";\nimport { PROFILE_NAMES, profileFor } from \"../scan/profiles.js\";\nimport { readReport, readDecisions, renderScan } from \"../scan/report.js\";\nimport { runScan } from \"../scan/run.js\";\nimport type { ScanOptions } from \"../scan/run.js\";\nimport { labelsToCorpus } from \"../scan/samples.js\";\nimport { writeJson } from \"../scan/storage.js\";\n\nexport const registerScanCommand = (program: Command): void => {\n const scan = program\n .command(\"scan\")\n .enablePositionalOptions()\n .description(\n \"Run a scoped scan with stable findings, baselines, and review exports\"\n )\n .argument(\"[paths...]\", \"Targets within the root; defaults to .\")\n .option(\"--root <path>\", \"Repository root\", process.cwd())\n .option(\n \"--profile <name>\",\n `Scan objective: ${PROFILE_NAMES.join(\", \")}`,\n \"product\"\n )\n .option(\"--rules <path>\", \"Rules directory\")\n .option(\n \"--only <ids>\",\n \"Comma-separated rule IDs within the selected profile\"\n )\n .option(\"--exclude <globs>\", \"Additional comma-separated exclusions\")\n .option(\"--dry-run\", \"Preview scope and cost without provider calls\")\n .option(\"--mechanical-only\", \"Run deterministic checks only\")\n .option(\"--model <id>\", \"Evaluation model\", \"jev-latest\")\n .option(\n \"--results-dir <path>\",\n \"Answer cache and sanitized request records\"\n )\n .option(\"--baseline <file>\", \"Compare a compatible completed scan\")\n .option(\n \"--new-only\",\n \"Report and gate only new findings against the baseline\"\n )\n .option(\n \"--since <ref>\",\n \"Report changed lines against a Git commit; retain analysis context\"\n )\n .option(\n \"--decisions <file>\",\n \"Apply accepted or dismissed review decisions\"\n )\n .option(\n \"--dependency-cruiser <file>\",\n \"Import dependency-cruiser JSON violations\"\n )\n .option(\n \"--samples <file>\",\n \"Export blind labeling samples, including source text, without predicted scores\"\n )\n .option(\n \"--save <file>\",\n \"Save a scan report; only completed scans can serve as baselines\"\n )\n .option(\"--output <format>\", \"tty, json, or sarif\", \"tty\")\n .option(\"--progress\", \"Print provider progress to stderr\")\n .action(\n async (\n targets: string[],\n options: Omit<ScanOptions, \"only\" | \"exclude\" | \"samples\"> & {\n rules?: string;\n only?: string;\n exclude?: string;\n samples?: string;\n save?: string;\n output: string;\n progress?: boolean;\n }\n ) => {\n if (![\"tty\", \"json\", \"sarif\"].includes(options.output)) {\n throw new InputError(\n \"INVALID_ARGUMENT\",\n \"--output must be tty, json, or sarif.\"\n );\n }\n if (\n options.save &&\n options.baseline &&\n path.resolve(options.save) === path.resolve(options.baseline)\n ) {\n throw new InputError(\n \"INVALID_ARGUMENT\",\n \"Save the next report to a different path so the baseline remains intact.\"\n );\n }\n let last = 0;\n const { report, rules, samples } = await runScan(\n {\n ...options,\n exclude: options.exclude?.split(\",\").filter(Boolean),\n only: options.only?.split(\",\").filter(Boolean),\n rulesDir: options.rules,\n samples: !!options.samples,\n targets: targets.length ? targets : [\".\"],\n },\n {\n onProgress: (p) => {\n if (\n options.progress &&\n (Date.now() - last > 2000 || p.phase === \"complete\")\n ) {\n last = Date.now();\n process.stderr.write(\n `${p.phase}: ${p.completed}/${p.planned} requests, ${p.failed} failed\\n`\n );\n }\n },\n }\n );\n if (options.save) {\n writeJson(options.save, report);\n }\n if (options.samples) {\n writeJson(options.samples, {\n instructions:\n \"Blind review: set label true for a violation, false for acceptable, or leave null when uncertain. No predicted probabilities are included. Split is grouped by source file.\",\n samples,\n version: 2,\n });\n }\n const visible = new Set(report.reporting.visible);\n const findings = report.findings.filter((f) =>\n visible.has(f.fingerprint)\n );\n const output =\n options.output === \"json\"\n ? `${JSON.stringify(report, null, 2)}\\n`\n : options.output === \"sarif\"\n ? renderSarif(\n { findings, ruleFindings: findings },\n rules,\n pkg.version\n )\n : renderScan(report);\n process.stdout.write(output);\n process.exitCode = report.exitCode;\n }\n );\n scan\n .command(\"profiles\")\n .description(\"Describe scan objectives, selection, and advisory rules\")\n .action(() => {\n process.stdout.write(\n `${JSON.stringify(PROFILE_NAMES.map(profileFor), null, 2)}\\n`\n );\n });\n scan\n .command(\"review <report> <fingerprint>\")\n .description(\n \"Record a review decision with a reason, or explicitly reopen it\"\n )\n .requiredOption(\"--decisions <file>\", \"Review decisions JSON\")\n .requiredOption(\"--status <status>\", \"accepted, dismissed, or open\")\n .option(\"--reason <text>\", \"Reason for accepting or dismissing\")\n .action(\n (\n file: string,\n fingerprint: string,\n options: { decisions: string; status: string; reason?: string }\n ) => {\n const report = readReport(file);\n if (!report.findings.some((f) => f.fingerprint === fingerprint)) {\n throw new InputError(\n \"INVALID_FINDING\",\n \"Fingerprint does not belong to the supplied report.\"\n );\n }\n if (\n ![\"accepted\", \"dismissed\", \"open\"].includes(options.status) ||\n (options.status !== \"open\" && !options.reason?.trim())\n ) {\n throw new InputError(\n \"INVALID_DECISION\",\n \"Choose accepted/dismissed with a reason, or open.\"\n );\n }\n const decisions = fs.existsSync(options.decisions)\n ? readDecisions(options.decisions, report.signature)\n : {};\n decisions[fingerprint] =\n options.status === \"open\"\n ? { reason: \"Reopened by reviewer\", status: \"open\" }\n : {\n reason: options.reason!,\n status: options.status as \"accepted\" | \"dismissed\",\n };\n writeJson(options.decisions, {\n decisions,\n signature: report.signature,\n version: 1,\n });\n process.stdout.write(`Review decision saved: ${options.status}\\n`);\n }\n );\n scan\n .command(\"export <report>\")\n .description(\n \"Export a remediation handoff without modifying code or opening PRs\"\n )\n .requiredOption(\"--out <file>\", \"Remediation JSON destination\")\n .action((file: string, options: { out: string }) => {\n const report = readReport(file);\n const visible = new Set(report.reporting.visible);\n writeJson(options.out, {\n scanSignature: report.signature,\n source: path.resolve(file),\n tasks: report.findings\n .filter(\n (f) =>\n visible.has(f.fingerprint) && f.decision?.status !== \"dismissed\"\n )\n .map((f) => ({\n automaticFix: false,\n confidence: f.probability,\n correction: f.fixHint,\n evidence: f.excerpt,\n id: f.fingerprint,\n location: { file: f.file, line: f.line },\n ruleId: f.ruleId,\n severity: f.severity,\n status: f.decision?.status ?? \"unreviewed\",\n verification: [\n `Inspect the complete context at ${f.file}:${f.line} and confirm the finding.`,\n \"Apply the smallest correction that preserves intended behavior.\",\n \"Run relevant project checks and rerun the same scan profile; verify this fingerprint is resolved.\",\n ],\n })),\n version: 1,\n });\n process.stdout.write(`Remediation handoff saved to ${options.out}\\n`);\n });\n scan\n .command(\"labels <samples>\")\n .description(\n \"Convert reviewed labels into an eval corpus JSONL with provenance\"\n )\n .requiredOption(\"--out <file>\", \"New corpus JSONL file\")\n .option(\"--rules <path>\", \"Rules directory used to validate labels\")\n .action((file: string, options: { out: string; rules?: string }) => {\n process.stdout.write(\n `Exported ${labelsToCorpus(file, options.out, options.rules)} labels.\\n`\n );\n });\n};\n","import { binaryMetrics } from \"../lib/stats.js\";\nimport type { CorpusItem } from \"../types.js\";\nimport { corpusCoverage } from \"./coverage.js\";\nimport type { RuleEval } from \"./metrics.js\";\n\nexport interface PromotionEvidence {\n eligible: boolean;\n n: number;\n precisionLower: number;\n reason: string;\n}\n\n// Threshold selection owns dev data. This gate only validates that fixed choice.\nexport const promotionEvidence = (\n items: CorpusItem[],\n ruleId: string,\n pairs: RuleEval[\"pairs\"],\n threshold: number,\n floor: number,\n minItems: number\n): PromotionEvidence => {\n const labeled = items.filter((item) => ruleId in item.labels);\n const holdout = labeled.filter((item) => item.split === \"holdout\");\n const coverage = corpusCoverage(labeled, []);\n const metrics = binaryMetrics(\n pairs.map((pair) => ({\n label: pair.label,\n predicted: pair.probability >= threshold,\n }))\n );\n const rejection =\n coverage.overlappingSources.length || coverage.overlappingTexts\n ? \"Dev and holdout share source files or duplicate text; rebuild independent splits.\"\n : pairs.length !== holdout.length\n ? \"Some holdout labels were skipped or unresolved.\"\n : pairs.length < minItems\n ? `Need at least ${minItems} evaluated holdout items.`\n : !pairs.some((pair) => pair.label) ||\n !pairs.some((pair) => !pair.label)\n ? \"Holdout needs both positive and negative labels.\"\n : metrics.precisionCI[0] < floor\n ? \"Held-out precision lower bound does not clear the floor.\"\n : undefined;\n return {\n eligible: rejection === undefined,\n n: pairs.length,\n precisionLower: metrics.precisionCI[0],\n reason: rejection ?? \"Independent holdout clears the precision floor.\",\n };\n};\n","// `taste-lint tune`: pick the lowest act threshold per rule whose act-band\n// precision lower bound clears the floor. `tune ab`: McNemar between two\n// question wordings over the same dev items.\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { parse } from \"yaml\";\n\nimport { defaultResultsDir } from \"../lib/config.js\";\nimport { mcnemar, wilson } from \"../lib/stats.js\";\nimport { AnswerCache } from \"../map/cache.js\";\nimport { DEFAULT_MODEL, evaluateFromEnv, KEY_HINT } from \"../map/jev.js\";\nimport { loadRules, readTuning, resolveRulesDir } from \"../rules/load.js\";\nimport { validateRule } from \"../rules/validate.js\";\nimport type { Evaluate, Rule, Tuning } from \"../types.js\";\nimport { loadCorpus, resolveCorpusDir } from \"./corpus.js\";\nimport { evaluateRules, scoreItems } from \"./metrics.js\";\nimport type { RuleEval } from \"./metrics.js\";\nimport { promotionEvidence } from \"./promotion.js\";\nimport type { PromotionEvidence } from \"./promotion.js\";\n\nexport interface TuneOptions {\n corpusDir?: string;\n rulesDir?: string;\n only?: string[];\n floor?: number;\n write?: boolean;\n resultsDir?: string;\n model?: string;\n apiKey?: string;\n minItems?: number;\n}\n\nexport interface TuneContext {\n evaluate?: Evaluate;\n}\n\nexport interface TuneDecision {\n ruleId: string;\n validation?: PromotionEvidence;\n n: number;\n current: number;\n chosen: number | null;\n precisionLower: number;\n recall: number;\n action: \"keep\" | \"raise\" | \"lower\" | \"demote\" | \"insufficient\";\n}\n\nconst THRESHOLDS = Array.from(\n { length: 10 },\n (_, i) => Math.round((0.5 + i * 0.05) * 100) / 100\n);\n\nexport const decideThreshold = (\n pairs: { label: boolean; probability: number }[],\n currentAct: number,\n floor: number,\n minItems: number,\n review = 0\n): Omit<TuneDecision, \"ruleId\"> => {\n const n = pairs.length;\n if (n < minItems) {\n return {\n action: \"insufficient\",\n chosen: null,\n current: currentAct,\n n,\n precisionLower: 0,\n recall: 0,\n };\n }\n for (const t of THRESHOLDS.filter((threshold) => threshold > review)) {\n const predictedPositive = pairs.filter((p) => p.probability >= t);\n const tp = predictedPositive.filter((p) => p.label).length;\n const positives = pairs.filter((p) => p.label).length;\n const [lower] = wilson(tp, predictedPositive.length);\n if (predictedPositive.length > 0 && lower >= floor) {\n const recall = positives === 0 ? 0 : tp / positives;\n const action =\n t === currentAct ? \"keep\" : t > currentAct ? \"raise\" : \"lower\";\n return {\n action,\n chosen: t,\n current: currentAct,\n n,\n precisionLower: lower,\n recall,\n };\n }\n }\n return {\n action: \"demote\",\n chosen: null,\n current: currentAct,\n n,\n precisionLower: 0,\n recall: 0,\n };\n};\n\nconst resolveEvaluate = (\n options: { apiKey?: string },\n ctx: TuneContext\n): Evaluate => {\n const evaluate = ctx.evaluate ?? evaluateFromEnv(options.apiKey);\n if (!evaluate) {\n throw new Error(`${KEY_HINT} Tuning needs live answers.`);\n }\n return evaluate;\n};\n\nexport const runTune = async (\n options: TuneOptions,\n ctx: TuneContext = {}\n): Promise<{ report: string; exitCode: number; decisions: TuneDecision[] }> => {\n const floor = options.floor ?? 0.8;\n const minItems = options.minItems ?? 10;\n // A NaN floor would demote every rule and --write would record it.\n if (!(Number.isFinite(floor) && floor > 0 && floor < 1)) {\n throw new Error(\"--floor must be a number between 0 and 1 (exclusive)\");\n }\n if (!Number.isInteger(minItems) || minItems < 1) {\n throw new Error(\"--min-items must be a positive integer\");\n }\n const rulesDir = resolveRulesDir(options.rulesDir);\n const rules = loadRules(rulesDir, {\n allowDraft: false,\n only: options.only,\n }).filter((r) => r.tier !== \"mechanical\");\n const knownRuleIds = new Set(\n loadRules(rulesDir, { allowDraft: true }).map((r) => r.id)\n );\n const allItems = loadCorpus(resolveCorpusDir(options.corpusDir), rules, {\n knownRuleIds,\n });\n const items = allItems.filter((item) => item.split === \"dev\");\n const model = options.model ?? DEFAULT_MODEL;\n const resultsDir = options.resultsDir ?? defaultResultsDir();\n const cache = new AnswerCache(path.join(resultsDir, \"cache\"));\n const evaluate = resolveEvaluate(options, ctx);\n const { probabilities, unknowns, skipped, usage } = await scoreItems(\n allItems,\n rules,\n {\n cache,\n evaluate,\n model,\n }\n );\n if (usage.errors > 0) {\n return {\n decisions: [],\n exitCode: 2,\n report:\n \"Tuning incomplete: provider requests failed. No thresholds were changed.\\n\",\n };\n }\n const evals = evaluateRules(items, rules, probabilities, unknowns, skipped);\n const decisions: TuneDecision[] = evals.map((e) => {\n const rule = rules.find((r) => r.id === e.ruleId) as Rule;\n return {\n ruleId: e.ruleId,\n ...decideThreshold(\n e.pairs,\n rule.thresholds.act,\n floor,\n minItems,\n rule.thresholds.review\n ),\n };\n });\n const holdout = evaluateRules(\n allItems.filter((item) => item.split === \"holdout\"),\n rules,\n probabilities,\n unknowns,\n skipped\n );\n for (const decision of decisions) {\n if (decision.chosen !== null) {\n decision.validation = promotionEvidence(\n allItems,\n decision.ruleId,\n holdout.find((evaluation) => evaluation.ruleId === decision.ruleId)!\n .pairs,\n decision.chosen,\n floor,\n minItems\n );\n }\n }\n const lines = decisions.map((d) => {\n switch (d.action) {\n case \"insufficient\": {\n return `${d.ruleId}: insufficient data (${d.n} labelled dev items, need ${minItems})`;\n }\n case \"demote\": {\n return `${d.ruleId}: no threshold clears precision floor ${floor} on ${d.n} items; demote to review-only`;\n }\n default: {\n return `${d.ruleId}: act ${d.current} -> ${d.chosen} (${d.action}); precision lower bound ${(d.precisionLower * 100).toFixed(0)}%, recall ${(d.recall * 100).toFixed(0)}%, n=${d.n}`;\n }\n }\n });\n for (const decision of decisions) {\n if (decision.validation) {\n lines.push(\n `${decision.ruleId}: ${decision.validation.eligible ? \"promotion eligible\" : \"review-only\"}; ${decision.validation.reason}`\n );\n }\n }\n if (options.write) {\n const file = path.join(rulesDir, \"tuning.json\");\n const existing: Tuning = readTuning(rulesDir);\n const ts = new Date().toISOString();\n for (const d of decisions) {\n if (d.action === \"insufficient\") {\n continue;\n }\n existing[d.ruleId] =\n d.action === \"demote\" || !d.validation?.eligible\n ? { n: d.n, status: \"review-only\", ts }\n : {\n act: d.chosen as number,\n n: d.n,\n precisionLower: d.validation.precisionLower,\n status: \"active\",\n ts,\n };\n }\n fs.writeFileSync(file, `${JSON.stringify(existing, null, 2)}\\n`);\n lines.push(`Wrote ${file}`);\n } else {\n lines.push(\"Dry decision; pass --write to update data/rules/tuning.json\");\n }\n return { decisions, exitCode: 0, report: `${lines.join(\"\\n\")}\\n` };\n};\n\nexport interface TuneAbOptions {\n ruleId: string;\n variantFile: string;\n corpusDir?: string;\n rulesDir?: string;\n resultsDir?: string;\n model?: string;\n apiKey?: string;\n}\n\nexport const runTuneAb = async (\n options: TuneAbOptions,\n ctx: TuneContext = {}\n): Promise<{ report: string; exitCode: number }> => {\n const rulesDir = resolveRulesDir(options.rulesDir);\n const [rule] = loadRules(rulesDir, {\n allowDraft: true,\n only: [options.ruleId],\n });\n if (!rule || rule.tier === \"mechanical\") {\n throw new Error(`Rule ${options.ruleId} is not a Jev-backed rule`);\n }\n const variantRaw = parse(\n fs.readFileSync(options.variantFile, \"utf-8\")\n ) as Record<string, unknown>;\n const merged = { ...ruleToRaw(rule), ...variantRaw, id: rule.id };\n const variant = validateRule(merged, options.variantFile, rule.id);\n const knownRuleIds = new Set(\n loadRules(rulesDir, { allowDraft: true }).map((r) => r.id)\n );\n const items = loadCorpus(resolveCorpusDir(options.corpusDir), [rule], {\n knownRuleIds,\n }).filter((i) => i.split === \"dev\" && rule.id in i.labels);\n const model = options.model ?? DEFAULT_MODEL;\n const resultsDir = options.resultsDir ?? defaultResultsDir();\n const cache = new AnswerCache(path.join(resultsDir, \"cache\"));\n const evaluate = resolveEvaluate(options, ctx);\n const a = await scoreItems(items, [rule], { cache, evaluate, model });\n const b = await scoreItems(items, [variant], { cache, evaluate, model });\n if (a.usage.errors > 0 || b.usage.errors > 0) {\n return {\n exitCode: 2,\n report:\n \"A/B comparison incomplete: provider requests failed. No paired test was computed.\\n\",\n };\n }\n const paired = items.filter(\n (item) =>\n a.probabilities.get(item.id)?.[rule.id] !== undefined &&\n b.probabilities.get(item.id)?.[rule.id] !== undefined\n );\n if (paired.length === 0) {\n return {\n exitCode: 2,\n report: \"A/B comparison has no jointly evaluated items.\\n\",\n };\n }\n const [ea] = evaluateRules(paired, [rule], a.probabilities);\n const [eb] = evaluateRules(paired, [variant], b.probabilities);\n const test = mcnemar(correctVector(ea, rule), correctVector(eb, variant));\n const report = [\n `${rule.id} on ${paired.length} paired dev items; ${items.length - paired.length} excluded because one or both variants abstained or skipped`,\n `A (current): precision ${(ea.metrics.precision * 100).toFixed(0)}% recall ${(ea.metrics.recall * 100).toFixed(0)}%`,\n `B (variant): precision ${(eb.metrics.precision * 100).toFixed(0)}% recall ${(eb.metrics.recall * 100).toFixed(0)}%`,\n `McNemar: n01=${test.n01} (A right, B wrong) n10=${test.n10} (A wrong, B right) discordant=${test.discordant} p=${test.pValue.toFixed(3)}`,\n test.discordant < 10\n ? \"Fewer than 10 discordant pairs: underpowered, add labelled items before deciding.\"\n : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n return { exitCode: 0, report: `${report}\\n` };\n};\n\nconst correctVector = (e: RuleEval, r: Rule): boolean[] =>\n e.pairs.map((p) => p.probability >= r.thresholds.act === p.label);\n\n// Back to the YAML shape: the loader derives tier, domain and scope, and a\n// code rule's check and file are not data.\nconst ruleToRaw = (rule: Rule): Record<string, unknown> => {\n const { check, domain, file, scope, tier, ...rest } = rule;\n void check;\n void domain;\n void file;\n void scope;\n void tier;\n return rest as unknown as Record<string, unknown>;\n};\n","import type { Command } from \"commander\";\n\nimport { runTune, runTuneAb } from \"../eval/tune.js\";\nimport { DEFAULT_MODEL } from \"../map/jev.js\";\n\nexport function registerTuneCommand(program: Command): void {\n const tune = program\n .command(\"tune\")\n .description(\n \"Pick act thresholds per rule from the dev split; --write updates data/rules/tuning.json\"\n )\n .option(\"--corpus <path>\", \"Corpus directory\")\n .option(\"--rules <path>\", \"Rules directory\")\n .option(\"--only <ids>\", \"Comma-separated rule ids\")\n .option(\"--floor <p>\", \"Required lower bound on act-band precision\", \"0.8\")\n .option(\n \"--min-items <n>\",\n \"Labelled dev items a rule needs before a decision\",\n \"10\"\n )\n .option(\"--write\", \"Write tuning.json\")\n .option(\"--results-dir <path>\", \"Where logs and cache live\")\n .option(\"--model <id>\", \"Jev model id\", DEFAULT_MODEL)\n .action(async (options) => {\n const result = await runTune({\n corpusDir: options.corpus,\n floor: Number(options.floor),\n minItems: Number(options.minItems),\n model: options.model,\n only: options.only\n ?.split(\",\")\n .map((s: string) => s.trim())\n .filter(Boolean),\n resultsDir: options.resultsDir,\n rulesDir: options.rules,\n write: options.write,\n });\n process.stdout.write(result.report);\n process.exitCode = result.exitCode;\n });\n tune\n .command(\"ab\")\n .description(\n \"Compare two question wordings for one rule over the dev split (McNemar)\"\n )\n .requiredOption(\"--rule <id>\", \"Rule id\")\n .requiredOption(\"--variant <file>\", \"YAML file with a replacement question\")\n .option(\"--corpus <path>\", \"Corpus directory\")\n .option(\"--rules <path>\", \"Rules directory\")\n .option(\"--results-dir <path>\", \"Where logs and cache live\")\n .option(\"--model <id>\", \"Jev model id\", DEFAULT_MODEL)\n .action(async (options) => {\n const result = await runTuneAb({\n corpusDir: options.corpus,\n model: options.model,\n resultsDir: options.resultsDir,\n ruleId: options.rule,\n rulesDir: options.rules,\n variantFile: options.variant,\n });\n process.stdout.write(result.report);\n process.exitCode = result.exitCode;\n });\n}\n","import { Command, CommanderError } from \"commander\";\n\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { registerEvalCommand } from \"./commands/eval.js\";\nimport { registerExtractCommand } from \"./commands/extract.js\";\nimport { registerLintCommand } from \"./commands/lint.js\";\nimport { registerRulesCommand } from \"./commands/rules.js\";\nimport { registerScanCommand } from \"./commands/scan.js\";\nimport { registerTuneCommand } from \"./commands/tune.js\";\nimport { InputError } from \"./lib/errors.js\";\nimport { ProviderError } from \"./map/jev.js\";\n\n// Configure before registering subcommands: Commander copies the exit hook\n// when a child is created, so setting it after registration misses parse errors.\nconst jsonOutput =\n process.argv.includes(\"--output=json\") ||\n process.argv[process.argv.indexOf(\"--output\") + 1] === \"json\";\nconst program = new Command();\nprogram.exitOverride();\nprogram.enablePositionalOptions();\nprogram.configureOutput({\n writeErr: (text) => {\n if (!jsonOutput) {\n process.stderr.write(text);\n }\n },\n});\n\nprogram\n .name(\"taste-lint\")\n .description(\n \"Taste linter: copy and typography rules answered as calibrated probabilities by TypeSafe Jev\"\n )\n .version(pkg.version)\n .addHelpText(\n \"after\",\n `\nQuickstart:\n export AI_GATEWAY_API_KEY=\"your-vercel-ai-gateway-key\"\n taste-lint scan .\n\nPreview: taste-lint scan . --dry-run\nWithout a key: taste-lint scan . --mechanical-only\nGet a key: https://vercel.com/docs/ai-gateway/authentication-and-byok/api-keys\n`\n );\n\nregisterLintCommand(program);\nregisterScanCommand(program);\nregisterExtractCommand(program);\nregisterRulesCommand(program);\nregisterEvalCommand(program);\nregisterTuneCommand(program);\n\n// The command surface as JSON, so an agent discovers flags, defaults and\n// subcommands without scraping --help.\nconst describe = (cmd: Command): Record<string, unknown> => ({\n command: cmd.name(),\n description: cmd.description(),\n options: cmd.options.map((opt) => ({\n default: opt.defaultValue,\n description: opt.description,\n flag: opt.long,\n })),\n ...(cmd.commands.length > 0 ? { commands: cmd.commands.map(describe) } : {}),\n});\nprogram\n .command(\"schema\")\n .description(\"Print the command surface as JSON\")\n .action(() => {\n process.stdout.write(`${JSON.stringify(program.commands.map(describe))}\\n`);\n });\n\n// Data and structured errors go to stdout; progress goes to stderr.\ntry {\n await program.parseAsync();\n} catch (error) {\n if (error instanceof CommanderError && error.exitCode === 0) {\n process.exitCode = 0;\n } else {\n const message = (error as Error).message;\n if (jsonOutput) {\n process.stdout.write(\n `${JSON.stringify({\n code:\n error instanceof ProviderError\n ? error.category\n : error instanceof InputError\n ? error.code\n : error instanceof CommanderError\n ? \"INVALID_ARGUMENT\"\n : \"UNEXPECTED\",\n details: error instanceof InputError ? error.details : {},\n error: true,\n message,\n })}\\n`\n );\n } else if (!(error instanceof CommanderError)) {\n process.stderr.write(`${message}\\n`);\n }\n process.exitCode = 1;\n }\n}\n"],"mappings":"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"}
|