CHANGELOG.md.
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).
analyzeoutput 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. byTierandminutesByTierfields inanalyze --jsonoutput, with the invariantdebt + modernization + style === totalMinutes.- BY TIER section in the boxed TUI analyze output.
- License: MIT → Apache 2.0. Same permissive freedoms; adds an explicit
patent grant from contributors. See
LICENSE,NOTICE, and the FAQ.
run --transforms=allsilently 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 importsTRANSFORM_ORDERdirectly; 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 toplan.changesbefore 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) applyandrollbackdropped POSIX file modes. Both paths now round-trip mode bits.class_to_dataclassinjected imports beforefrom __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_awaitnow emit apreconditionrecord on every refusal — no more “detected, but nothing changed” with no explanation. manual_typecheck_to_hintswas 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)
manual_typecheck_to_hintsnow 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.
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 — Pythonsuper_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 thefrom functools import …line.pep585_generics—typing.List/Dict/Tuple/Iterable/ … →list/dict/tuple/collections.abc.Iterable/ … (≥ 3.9, orfrom __future__ import annotations). Refuses files with Pydantic v1 orget_type_hintsto avoid runtime-eval crashes.pep604_optional_union—Optional[X]→X | None;Union[A, B]→A | B(≥ 3.10, orfrom __future__ import annotations).datetime_utc_alias—datetime.timezone.utc→datetime.UTC(≥ 3.11). No__future__override —UTCis a runtime attribute.yield_from_for_loop—for x in y: yield x→yield from y. Refuses insideasync def(a CPython compile-stage SyntaxError LibCST’s parser does not catch).
indexof_to_includes—arr.indexOf(x) !== -1and 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}…`. Refusesany/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/.tsonly —.vueSFC parsing is deferred to v0.4. Refusesdeletein expression context (return-value semantics differ). On Vue 2 codebases this is a semantic change (Vue.setis required for new reactive keys) — caveat ships in the suggestion text.
pythonVersion— pin the Python target version ("3.9","3.11", …) for the four version-gated Python transforms. Auto-detected frompyproject.toml’srequires-pythonwhen unset; falls back to refusing version-gated transforms rather than guessing.
- Engine composition — multi-transform composition is now order-stable: when several transforms touch the same file, each emits its own
FileChangecarrying 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 underrun --apply(PR #38).
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 —
analyzerenders one box per file plus boxed TRANSFORMS / BY TRANSFORM / SUMMARY blocks;run --dry-runmatches, with a CHANGES table and a four-sided diff box per file. rollbackcommand — undo an applied refactor ordocumentrun; journal-based LIFO undo, drift-safe,--all/--force/--dry-run.run --applylive progress — gate-by-gate status and per-file verify/apply detail; batch-first with a per-file fallback when the batch fails.run --applyshort-circuit — exits early when no test runner is detected, instead of silently skipping the test gate.- Full report saved to disk —
analyze/run --dry-runwrite the complete report to.refactron/reports/. documentenrichments — inline comments, a per-run modernization report underdocs/refactron/, and a post-apply syntax re-check.
documentis far more efficient — docstring requests are batched with bounded concurrency and token-aware rate limiting; the LLM call count is nowO(source tokens / batch budget), notO(symbols).
documentproduced 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.documentsix-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_hintsno longer flags already-annotated parameters; the misleading “Fixable N/N” became an honest auto-fix-candidate count.deprecated_api_requests_to_httpxno longer emits runtime-broken code — it refuses files usingrequestsAPI that is not a safehttpxdrop-in.
Patch release — a large-file crash fix and two transform-coverage improvements.Fixed
analyzecrashed 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_letdropped whole files — reassignment checks matched identifiers by text across the entire file. Reference resolution is now scope-correct, and for-loopvar iinitializers are covered.
format_to_fstringnow 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.
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.jsonconfig — cosmiconfig + Ajv schema validation.- Authentication — OAuth device flow with
REFACTRON_TOKENsupport and long-lived API keys. - A Mintlify documentation site and reproducible performance benchmarks under
bench/.