> ## Documentation Index
> Fetch the complete documentation index at: https://docs.refactron.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Release history for Refactron — newest first.

Refactron follows [Semantic Versioning](https://semver.org/). The full,
unabridged log lives in [`CHANGELOG.md`](https://github.com/Refactron-ai/Refactron_Lib_TS/blob/main/CHANGELOG.md).

<Update label="0.2.4" description="June 17, 2026">
  Reliability and observability release. Five real fixes, one feature (tier
  taxonomy), one license change. No new transforms, no API breakage — every
  existing call site keeps working.

  **Added**

  * **Tier taxonomy on every transform** (debt / modernization / style). `analyze`
    output groups findings and remediation minutes by tier — the headline "N
    findings" splits into "57 debt, 102 modernization, 2,569 style" instead of
    one undifferentiated count.
  * **`byTier` and `minutesByTier` fields** in `analyze --json` output, with the
    invariant `debt + modernization + style === totalMinutes`.
  * **BY TIER section** in the boxed TUI analyze output.

  **Changed**

  * **License: MIT → Apache 2.0.** Same permissive freedoms; adds an explicit
    patent grant from contributors. See `LICENSE`, `NOTICE`, and the FAQ.

  **Fixed**

  * **`run --transforms=all` silently dropped 8 transforms.** The CLI's local
    list had drifted out of sync with the engine's canonical order when the
    v0.2.3 catalog expansion landed. CLI now imports `TRANSFORM_ORDER` directly;
    drift is pinned by a test. (#48, PR #49)
  * **`--files=<glob>` was ignored on `--apply`.** The glob only narrowed the
    dry-run preview; the apply path silently rewrote every matching finding.
    Filter is now applied to `plan.changes` before the split, so both paths
    honour it. (#50, PR #52)
  * **Documenter broke files with multi-line return-type signatures.** On
    `def f() -> type[Union[…]]:` shapes that span multiple lines, the inserter
    latched onto the first inner line of the type subscript as if it were the
    body. The walker now tracks bracket depth and skips inline Protocol stubs.
    (#51, PR #52)
  * **`apply` and `rollback` dropped POSIX file modes.** Both paths now
    round-trip mode bits.
  * **`class_to_dataclass` injected imports before `from __future__`.** New
    imports now land after the `__future__` block, preserving PEP 236 ordering.
  * **Silent refusals in four transform sidecars.** `pep585_generics`,
    `pep604_optional_union`, `datetime_utc_alias`, `callback_to_async_await`
    now emit a `precondition` record on every refusal — no more "detected, but
    nothing changed" with no explanation.
  * **`manual_typecheck_to_hints` was the silent sidecar Bug #3 missed.** Every
    refusal path now records why; gating prevents noise from unrelated
    siblings; the nested-def scan stops at function boundaries. On Ansible: 16
    silent files → 0; 4 records → 87 covering all 20 affected files. (#57, PR #58)

  **Known follow-ups**

  * `manual_typecheck_to_hints` now records refusals but on Ansible still
    rewrites 0 of 20 files. Expanding the rewriter to handle docstring + body
    and dispatcher + fallthrough is tracked as #59.
  * Eight new transform candidates derived from a deeper Ansible scan are filed
    as #62–#69 for v0.3 / v0.4 prioritisation.
</Update>

<Update label="0.2.3" description="May 27, 2026">
  Ten new deterministic transforms — six for Python, four for TypeScript — roughly
  doubling Refactron's transform coverage. Adds the `pythonVersion` config key
  so version-gated rewrites can be opted in safely.

  **Added — Python**

  * **`super_no_args`** — `super(ClassName, self).method(...)` → `super().method(...)`. Refuses sibling/parent class names and nested-class shadows to preserve MRO.
  * **`lru_cache_to_cache`** — `@functools.lru_cache(maxsize=None)` → `@functools.cache` (≥ 3.9); also rewrites the `from functools import …` line.
  * **`pep585_generics`** — `typing.List` / `Dict` / `Tuple` / `Iterable` / … → `list` / `dict` / `tuple` / `collections.abc.Iterable` / … (≥ 3.9, or `from __future__ import annotations`). Refuses files with Pydantic v1 or `get_type_hints` to avoid runtime-eval crashes.
  * **`pep604_optional_union`** — `Optional[X]` → `X | None`; `Union[A, B]` → `A | B` (≥ 3.10, or `from __future__ import annotations`).
  * **`datetime_utc_alias`** — `datetime.timezone.utc` → `datetime.UTC` (≥ 3.11). No `__future__` override — `UTC` is a runtime attribute.
  * **`yield_from_for_loop`** — `for x in y: yield x` → `yield from y`. Refuses inside `async def` (a CPython compile-stage SyntaxError LibCST's parser does not catch).

  **Added — TypeScript**

  * **`indexof_to_includes`** — `arr.indexOf(x) !== -1` and friends → `arr.includes(x)`. Type-aware via ts-morph (String / Array / ReadonlyArray receivers). Gated on tsconfig target ≥ ES2016.
  * **`object_assign_to_spread`** — `Object.assign({}, a, b)` → `{ ...a, ...b }`. First arg must be an object literal; refuses spread-element sources. Gated on tsconfig target ≥ ES2018.
  * **`string_concat_to_template_literal`** — `"…" + x + "…"` → `` `…${x}…` ``. Refuses `any` / `unknown` / non-primitive operands. Gated on tsconfig target ≥ ES2015.
  * **`vue_set_delete_to_assignment`** — `Vue.set` / `this.$set` → direct assignment; `Vue.delete` / `this.$delete` → `delete obj.k`. `.js` / `.ts` only — `.vue` SFC parsing is deferred to v0.4. Refuses `delete` in expression context (return-value semantics differ). On Vue 2 codebases this is a semantic change (`Vue.set` is required for new reactive keys) — caveat ships in the suggestion text.

  **Added — Configuration**

  * **`pythonVersion`** — pin the Python target version (`"3.9"`, `"3.11"`, …) for the four version-gated Python transforms. Auto-detected from `pyproject.toml`'s `requires-python` when unset; falls back to refusing version-gated transforms rather than guessing.

  **Changed**

  * **Engine composition** — multi-transform composition is now order-stable: when several transforms touch the same file, each emits its own `FileChange` carrying the cumulative content, and the last one per path is what's written to disk. Fixes a silent-data-loss bug where only the LAST transform's rewrite survived under `run --apply` (PR #38).
</Update>

<Update label="0.2.2" description="May 18, 2026">
  Quality-of-life release for the analyze → run → document pipeline: boxed CLI
  output, a real `rollback` command, and a much more efficient `document`.

  **Added**

  * **Bordered table output** — `analyze` renders one box per file plus boxed TRANSFORMS / BY TRANSFORM / SUMMARY blocks; `run --dry-run` matches, with a CHANGES table and a four-sided diff box per file.
  * **`rollback` command** — undo an applied refactor or `document` run; journal-based LIFO undo, drift-safe, `--all` / `--force` / `--dry-run`.
  * **`run --apply` live progress** — gate-by-gate status and per-file verify/apply detail; batch-first with a per-file fallback when the batch fails.
  * **`run --apply` short-circuit** — exits early when no test runner is detected, instead of silently skipping the test gate.
  * **Full report saved to disk** — `analyze` / `run --dry-run` write the complete report to `.refactron/reports/`.
  * **`document` enrichments** — inline comments, a per-run modernization report under `docs/refactron/`, and a post-apply syntax re-check.

  **Changed**

  * **`document` is far more efficient** — docstring requests are batched with bounded concurrency and token-aware rate limiting; the LLM call count is now `O(source tokens / batch budget)`, not `O(symbols)`.

  **Fixed**

  * `document` produced zero docstrings on large files — batches were sized by input tokens only, so the combined response overran the completion cap and truncated. Batches are now also capped by response size, and a truncated reply is salvaged entry-by-entry.
  * `document` six-quote docstring bug (`""""""…""""""`); rate-limited runs that ground on for minutes; report / CHANGELOG paths normalized to forward slashes on Windows.
  * `analyze` — old-string-format findings now anchor on the operator, not the opening quote; `manual_typecheck_to_hints` no longer flags already-annotated parameters; the misleading "Fixable N/N" became an honest auto-fix-candidate count.
  * `deprecated_api_requests_to_httpx` no longer emits runtime-broken code — it refuses files using `requests` API that is not a safe `httpx` drop-in.
</Update>

<Update label="0.2.1" description="May 16, 2026">
  Patch release — a large-file crash fix and two transform-coverage improvements.

  **Fixed**

  * `analyze` crashed on files larger than \~32 KB — tree-sitter's native binding rejects oversized string input. Parsing now uses the streaming callback-input form; a single unparseable file is skipped rather than aborting the run.
  * `var_to_const_let` dropped whole files — reassignment checks matched identifiers by text across the entire file. Reference resolution is now scope-correct, and for-loop `var i` initializers are covered.

  **Changed**

  * `format_to_fstring` now converts the full printf grammar — `%d`, `%.2f`, `%x`, `%o`, `%e`, `%g`, width/precision specifiers, and `%%`. Mapping `%(name)s`, non-literal targets, and dynamic `*` widths are still conservatively skipped.
</Update>

<Update label="0.2.0" description="May 15, 2026">
  First public release of the v2.0 deterministic-refactoring rebuild.

  **Added**

  * **Engine** — 10 deterministic AST transforms (5 Python via LibCST, 5 TypeScript via ts-morph) with cross-file preconditions.
  * **3-gate verification** — syntax + imports + tests on a shadow tree, with atomic batch write or rollback.
  * **Documentation engine** — the only LLM-touching component, running only on already-verified diffs; 5 providers (Ollama, Groq, OpenAI, Anthropic, managed backend).
  * **`.refactronrc.json` config** — cosmiconfig + Ajv schema validation.
  * **Authentication** — OAuth device flow with `REFACTRON_TOKEN` support and long-lived API keys.
  * A Mintlify documentation site and reproducible performance benchmarks under `bench/`.
</Update>
