# Release Decisions

Approved on 2026-05-30.

These decisions define the first-release direction. They can change only when a
compatibility gate, public benchmark, or real user workflow proves the current
choice insufficient.

## Compatibility Gate

- The blocking rule is coverage-first parity: Rust must not miss duplicate
  lines reported by upstream `jscpd` for the same input and options.
- Rust may report additional duplicates while compatibility is converging.
  Extra findings remain visible in comparison output and should be reduced when
  they are false positives or noisy user-visible ranges.
- Exact 1:1 clone boundaries, pair ordering, and token totals are quality
  metrics, not the default release blocker.

## Runtime Strategy

- Do not embed a JavaScript runtime or spawn upstream JavaScript from Rust to
  implement tokenizers, reporters, stores, or plugins.
- Prefer native Rust implementations backed by maintained crates.
- If a format cannot be supported well without a large custom port, keep it on
  generic tokenization until a fixture or public-repo gate shows missed
  upstream coverage.

## Reporters

- Built-in reporters are first-release scope and should be implemented natively:
  `ai`, `console`, `consoleFull`, `csv`, `html`, `json`, `markdown`, `silent`,
  `sarif`, `threshold`, `xcode`, `xml`, and the commonly used badge reporter.
- Machine-readable reporter contracts are strict release scope: JSON, XML,
  SARIF, CSV, and Markdown should stay structurally compatible with upstream.
- HTML must remain practically compatible and self-contained. Pixel-perfect
  upstream parity is not a first-release blocker.
- Dynamic npm reporter loading is post-MVP. Unknown reporter names should keep
  the upstream-style warning and continue where upstream continues.

## Stores And Cache

- The default in-memory store is the first-release store path.
- `--store <name>` should keep the upstream missing-store fallback shape unless
  a native store backend is deliberately added.
- Dynamic npm store loading is post-MVP.
- Native persistent/cache stores are demand-driven. Add one only if public
  benchmark data shows the in-memory path is not enough for release viability.
- `cache`, config `listeners`, and `tokensToSkip` remain option-surface
  compatibility fields while upstream exposes but does not consume them in the
  current CLI runtime.

## Formats And Tokenization

- JS/TS/JSX/TSX stay on the Oxc-backed native path.
- Markdown, Vue, Svelte, Astro, Apex, and markup keep small native block
  splitters where that unlocks upstream coverage without a full grammar port.
- Long-tail formats use the upstream-synchronized registry plus generic
  tokenization by default.
- Promote a long-tail format only with a focused fixture, `STRICT=coverage`
  comparison, and a clear reason that generic tokenization is insufficient.

## CLI And Upstream Quirks

- Mirror upstream behavior when it is visible, common, and covered by tests.
- Crash-only Commander edge cases are documented first and mirrored only if a
  release gate or user workflow makes exact behavior necessary.
- Keep upstream bug candidates in `docs/upstream-bugs.md` so we can file them
  later with concrete repro commands.

## Blame

- Blame stays native through Git commands or a Git library.
- Prefer per-file failure isolation over inheriting upstream nested-repository
  failure modes.

## Performance

- Performance remains a product requirement. Public benchmark runs should be
  repeated before publication with pinned commits and recorded speedups.
- Refactors, simplifications, compatibility fixes, and dependency swaps must not
  introduce sustained speed regressions. If a change touches discovery,
  tokenization, matching, source loading, reporter hot paths, or server snippet
  checks, rerun the affected benchmark case before treating the core as stable.
- The aspirational target is 50x on representative cases, but release gating
  should use measured thresholds from the selected public benchmark suite. The
  default public release gate currently fails below 45x to preserve the 50x+
  baseline while leaving room for runner noise.

## Approved Complex Feature Choices

These are the current choices for features that are expensive to clone exactly:
the user explicitly approved these tradeoffs on 2026-05-30.

- Dynamic npm reporters, stores, listeners, and plugins: do not implement for
  the first release. Keep option-surface compatibility, native built-ins, and
  upstream-style missing-package warnings.
- Long-tail Prism tokenizer parity: do not port all grammars eagerly. Keep the
  upstream-synchronized format registry plus generic tokenization, then promote
  formats only when fixtures or public-repo gates show missed upstream coverage.
- Extra Rust findings: acceptable while compatibility converges. The release
  blocker is missing upstream duplicated line coverage, not 1:1 pair identity.
- Node/Commander quirks: mirror visible behavior only when covered by gates.
  Document crash-only or incidental quirks in `docs/upstream-bugs.md`.
- HTML reporter: keep self-contained and practically compatible. Pixel-perfect
  parity is not a first-release blocker.
- Persistent cache/store backends: postpone until benchmark data shows the
  in-memory detector is insufficient on release-scale repositories.
- Blame failures: prefer native per-file isolation instead of inheriting
  upstream failure modes around nested or unusual Git repositories.
