Skip to content

crimes@0.12.0 — universal pack

Theme: Works on any repo, honest about what’s covered.

This release introduces the pack model: each detector belongs to a pack (universal, language-js, future language-py, future cross-language), and the scan orchestrator routes detectors through a discriminated DetectorContext matching their pack. Universal-pack detectors run on every discovered file in every repo without needing an AST. Language packs run only on files they claim by extension.

crimes scan on a Python, Go, Rust, or any other non-JS repo now produces real findings (large files, raster asset weight, duplicate filenames, hardcoded localhost / local paths, docs link checking, missing agent context, TODO/FIXME density, commented-out code) plus a coverage banner explaining the gap, instead of an empty report that reads as a clean bill of health.

  • Finding.pack (required)"universal" | "language-js". Future packs land additively.
  • Finding.detector_id (required) — qualified detector id (large_function.js); Finding.type keeps the abstract form (large_function).
  • ScanReport.coverage (optional) — per-pack file-count breakdown. packs_loaded names every pack that ran and is always led by "universal", which claims every file; a repo no language pack recognises reports ["universal"].

Consumers that pinned schema_version === "0.2.0" must accept "0.3.0". Existing fingerprints (formula <type>::<file>::<symbol>) are unchanged — baselines, suppressions, triage entries, and feedback records all continue to work without migration.

  • large_file
  • oversized_raster, raster_should_be_vector, svg_with_embedded_raster
  • finder_duplicate_filename
  • hardcoded_local_path, hardcoded_localhost
  • docs_code_drift
  • missing_agent_context
  • todo_density
  • commented_out_code — universal regex variant for non-JS files; AST-aware variant stays in language-js.

Every other detector stays in language-js and behaves identically to 0.11.1 on TS/JS files.

  • crimes scan --explain-coverage — per-pack file-count breakdown after the scan output, with a paragraph explaining what the universal-only files lost (no AST → no large_function, circular_dependency, etc.).
  • Coverage banner in human scan output when >50% of discovered files are universal-only.
  • crimes context <unsupported.rs> — universal-pack findings + git/IA context with agent_guidance_reason pointing at the language-pack gap. Previously returned an empty report.
  • packages/core/src/pack.ts — new Pack type.
  • packages/core/src/detector.tsDetectorContext is now a discriminated union (universal | language-js); Detector.pack is required.
  • packages/core/src/discovery/ — file discovery moved from @crimes/language-js; @crimes/language-js no longer exports discoverFiles.
  • packages/core/src/discovery/language-pack-router.ts — extension → pack claim registry. Language packs register their claimed extensions at module load time.
  • packages/core/src/finding-finalise.ts — central pass that populates Finding.pack + Finding.detector_id after every detector emission. Detectors return PreFinding[]; the finaliser widens to Finding and mints the qualified detector_id.
  • Default config.include expanded to discover non-JS source files (.py, .rs, .go, .rb, .java, .swift, .kt, .scala, .c, .cpp, .h, .hpp, .cs, .php, .ex, .exs, .lua, shell, .md, .mdx) so the universal pack delivers on the release promise.
  • Python pack (packages/language-py/) — 0.13.0.
  • Cross-language detectors and coverage.by_package for monorepos — 0.14.0.
  • Other language packs (Go, Rust, Java, …) — future minor releases.

Spec: docs/superpowers/specs/2026-05-22-wider-codebase-support-design.md.