Skip to content

Week 8 — v0.2.0 launch surface - #26

Merged
omsherikar merged 19 commits into
mainfrom
feat/week-8-launch
May 14, 2026
Merged

Week 8 — v0.2.0 launch surface#26
omsherikar merged 19 commits into
mainfrom
feat/week-8-launch

Conversation

@omsherikar

@omsherikar omsherikar commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Final hardening + launch surface for Refactron v0.2.0. Six days (50–55) of preparation across security, docs, packaging, the PyPI wrapper, and CI release automation. Day 56 (the actual git push origin v0.2.0) is user-driven by design.

No engine changes. src/contracts.ts, the verification gate, transforms, and adapter code are untouched per Inviolable Rule #1.

What's in this PR

Area Change
Security npm audit cleared (vitest 1 → 3); SECURITY.md with disclosure policy + threat model
Docs site 13 new Mintlify pages: Safety Model (3-gate diagram), 10 transform pages + index, CLI Reference, Configuration, FAQ, Why No LLM
README 302 → 125 lines; alpha disclaimers dropped; one-line + GIF + 4-cmd install + 3-gate diagram + transform table + limitations + perf table + citations
Demo GIF tape/demo.tape written; docs/assets/demo.gif generation deferred to local vhs render
npm packaging author + publishConfig added; version bumped to 0.2.0; SECURITY.md added to files; typescript moved to dependencies (was breaking refactron run on every fresh install)
PyPI wrapper New refactron-py/ package — thin shim that detects Node and shells out to the npm CLI; os.execvp for clean signal pass-through
CI release.yml extended to publish PyPI alongside npm via Trusted Publishing (OIDC, no token)
Launch artifacts Show HN response templates, pre-ship checklist, ADR-010

Smokes

  • macOS host: npm install ./refactron-0.2.0.tgzrefactron --version0.2.0analyze + run --dry-run + document --apply PASS
  • Python 3.13 venv: wheel install + refactron --version0.2.0 PASS
  • twine check on both sdist + wheel: PASSED
  • npm publish --dry-run: 237 kB tarball, expected file list (no leakage of tests/, dev-docs/, fixtures/, tape/, docs/, refactron-py/)
  • Binary gate: typecheck, lint, format:check, build, vitest all green (Python-subprocess parallel-load flake passes in isolation — known)

Ship-day prerequisites (Day 56, user-driven)

  • Render demo GIF locally: brew install vhs && vhs tape/demo.tape
  • PyPI Trusted Publisher entry: pypi.org/manage/account/publishing/ → Add pending publisher (owner=Refactron-ai, repo=Refactron_Lib_TS, workflow=release.yml, environment=pypi-production)
  • GitHub environment pypi-production created (Settings → Environments)
  • NPM_TOKEN secret on the npm-production environment (skip if already set from a prior publish)
  • After merge: git tag v0.2.0 && git push origin v0.2.0 → release.yml takes over

What's deferred (post-launch)

Gauntlets #2#5, OAuth refresh-token, 500k LOC bench, conference talks, Ruby/Go/Rust adapters. All explicitly listed in dev-docs/decisions/10-week-8-launch.md.

Test plan

  • Manual smoke against refactron-0.2.0.tgz on macOS
  • PyPI wheel smoke in fresh venv
  • twine check on sdist + wheel
  • npm publish --dry-run file-list audit
  • npm audit --audit-level=high exit 0
  • Reviewer: skim dev-docs/launch/pre-ship-checklist.md to confirm the user-only items make sense
  • Reviewer: skim dev-docs/decisions/10-week-8-launch.md for the seven launch decisions

Summary by CodeRabbit

  • New Features

    • Added Python package distribution via PyPI with the refactron-py wrapper for pip installation.
    • Documented complete transform catalog with 10 supported Python and TypeScript transforms.
  • Documentation

    • Redesigned README with v0.2 positioning, 3-gate safety model, and transform examples.
    • Added CLI reference, configuration guide, FAQ, and safety model concept pages.
    • Updated SECURITY.md with threat model, vulnerability reporting process, and supported versions.
  • Infrastructure

    • Updated release automation to publish to both npm and PyPI.
    • Added pre-ship checklist and launch documentation.

Review Change Stack

omsherikar added 18 commits May 15, 2026 00:06
- npm audit fix: postcss XSS (GHSA-qx2v-qp2m-jg93) auto-resolved (6 -> 5)
- Bumped vitest 1.6.1 -> 3.2.4 and @vitest/coverage-v8 1.6.1 -> 3.2.4
  to clear esbuild dev-server CVE chain (GHSA-67mh-4wv8-2f99)
- Before: 6 moderate / 0 high / 0 critical
- After:  0 moderate / 0 high / 0 critical
- typecheck, lint, build, full test suite all green under vitest 3
- Private reporting via email + GitHub Security Advisories, 72h ack
- Supported versions: 0.2.x; 0.1.x-beta deprecated
- Threat model: deterministic engine, no LLM in critical path;
  document step runs only on verified diffs; redaction + fallback
- Subprocess safety: documents the testCmd sh -c exception explicitly
- Atomic-write guarantees: write-file-atomic semantics
Fresh thin shim that detects Node.js >=18, ensures the npm `refactron`
CLI is available (auto-installing globally via npm if missing), then
hands off via os.execvp so signals and exit codes pass through cleanly.
Falls back to subprocess.run on Windows where execvp may misbehave.

Replaces the legacy v1.0.15 standalone Python implementation on the
PyPI `refactron` namespace, preserving the existing pip-install path
for the v2.0 npm-backed CLI.
…t runtime

Day 55 final smoke caught ERR_MODULE_NOT_FOUND on 'typescript' when running
'refactron run' from a fresh global install:

  src/verify/checks/syntax-typescript.ts:  import * as ts from 'typescript'
  src/verify/checks/imports-typescript.ts: import * as ts from 'typescript'

Both verify checks load eagerly (Python adapter projects hit them too), so a
missing typescript package broke 'run' for every fresh install. Moved
typescript from devDependencies to dependencies. Smoke now passes:
analyze + run --dry-run + document --apply all green on a tmpdir-installed
0.2.0 tarball.
The Mintlify site is published at docs.refactron.dev (subdomain), not
refactron.dev/docs. Update README, refactron-py README + pyproject Project-URL,
and the pre-ship checklist accordingly. Schema namespace URLs at
refactron.dev/schema/* are unrelated and stay as-is.
Adds a publish-pypi job to the existing tag-triggered release workflow:
- validate-tag now also requires refactron-py/pyproject.toml version to match
- publish-pypi builds the wrapper sdist + wheel and uploads via OIDC
  (no API token; uses pypa/gh-action-pypi-publish + the pypi-production env)
- github-release waits on both publish-npm and publish-pypi

Requires one-time PyPI setup: Account Settings -> Publishing -> Add pending
publisher with owner=Refactron-ai, repo=Refactron_Lib_TS, workflow=release.yml,
environment=pypi-production.
Copilot AI review requested due to automatic review settings May 14, 2026 20:11
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@omsherikar has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 33 minutes and 53 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 93c8a6c9-ac56-44f4-a6a1-9121e26ab9ff

📥 Commits

Reviewing files that changed from the base of the PR and between b518999 and ed5e4d7.

⛔ Files ignored due to path filters (1)
  • docs/assets/demo.gif is excluded by !**/*.gif
📒 Files selected for processing (1)
  • tape/demo.tape
📝 Walkthrough

Walkthrough

This PR delivers v0.2.0 as a complete release: a Python package wrapper (refactron-py) providing pip install refactron for Python users, updated release workflow to publish on PyPI, comprehensive user documentation (CLI reference, safety model, transform catalog, FAQ), revised security and support policies, and coordinated launch operations including pre-ship checklist, Show HN responses, and demo generation guide.

Changes

v0.2.0 Release Infrastructure

Layer / File(s) Summary
Python package wrapper for npm CLI
refactron-py/__init__.py, refactron-py/pyproject.toml, refactron-py/README.md, refactron-py/LICENSE, refactron-py/refactron/cli.py
Thin Python package that detects Node.js 18+, installs the npm refactron CLI globally if needed (via npm install -g refactron), and forwards all arguments using os.execvp with subprocess fallback. Enables pip install refactron for Python-first users.
Release workflow & version updates
.github/workflows/release.yml, package.json, .gitignore, .npmignore
Workflow validates git tags against both package.json and refactron-py/pyproject.toml, adds new publish-pypi job building and uploading the Python package, updates github-release job to depend on both npm and PyPI publishing. Version bumped to 0.2.0, typescript moved to dependencies at ^5.4.0, vitest/coverage upgraded to ^3.2.4, SECURITY.md added to published files, and .npmignore/.gitignore updated for Python build artifacts.

User-Facing Documentation

Layer / File(s) Summary
Safety model & design philosophy
docs/concepts/safety-model.mdx, docs/concepts/why-no-llm.mdx
Documents Refactron's three-gate verification (syntax, imports, tests), atomic batch write with temp-file+fsync+rename semantics, and cross-file preconditions. Explains design choice to exclude LLMs from the critical refactoring path; optional document command runs post-verification to generate docstrings and changelogs.
CLI reference & configuration
docs/cli/reference.mdx, docs/configuration/refactronrc.mdx
Complete CLI command reference (analyze, run, document, init, login/logout, auth, status, session, rollback, help, clear, exit) with flags, examples, and exit codes. .refactronrc.json schema documenting transforms, exclude, testCmd, confidence, dryRun, documentation provider settings, with example configs and validation behavior (Ajv v8 + cosmiconfig discovery).
Transform catalog & documentation
docs/transforms/index.mdx, docs/transforms/*
Index page and 10 detailed transform documentation pages (Python: callback-to-async-await, class-to-dataclass, deprecated-api-requests-to-httpx, format-to-fstring, manual-typecheck-to-hints; TypeScript: commonjs-to-esm, implicit-any, promise-chains-to-async, promise-constructor-to-async, var-to-const-let). Each includes purpose, detector logic, preconditions, before/after examples, and edge-case handling notes.
FAQ & documentation navigation
docs/faq.mdx, docs/mint.json
FAQ page answering comparisons (vs Cursor/Copilot, ESLint, Comby, jscodeshift), design details, extension approach, monorepo behavior, performance, and licensing. Mintlify navigation restructured with "Concepts", "Configuration", and "FAQ" groups added, "Core Concepts" renamed to "Concepts", and concept/transform pages reorganized.

Launch Coordination & Release Notes

Layer / File(s) Summary
Release notes & security updates
CHANGELOG.md, README.md, SECURITY.md
v0.2.0 changelog lists new engine (deterministic multi-language transforms, cross-file preconditions), verification gates, documentation engine, CLI workflow (analyze, run, document), authentication (OAuth device flow, REFACTRON_TOKEN), .refactronrc.json config, and performance improvements. README rewritten with install + first-refactor flow, 3-gate safety model, transform catalog, honest limitations (self-test paradox exclusion), and performance benchmarks. SECURITY.md updated with threat model ("no LLM in critical path"), subprocess safety (execa array form + testCmd shell exception with trust boundary), atomic-write guarantees, and npm audit zero-vulnerability statement for 0.2.x.
Launch decision & planning (ADR 010)
dev-docs/decisions/10-week-8-launch.md
ADR 010 documents Week 8 launch: version 0.2.0, gauntlet deferral #2#5, PyPI thin-wrapper strategy with NODE_MAJOR=18 detection, Mintlify docs, vhs demo GIF, npm publish settings (access: public, provenance: true), Day 56 user-driven execution with split subagent-verifiable and user-only checklists, and consequences/future work linking to related source-of-truth artifacts.
Pre-ship execution & public engagement
dev-docs/launch/pre-ship-checklist.md, dev-docs/launch/show-hn-responses.md, dev-docs/launch/deploy-docs.md, dev-docs/launch/recording-the-demo.md, tape/demo.tape
Pre-ship checklist with Day-55 subagent-verifiable items (typecheck, lint, build, tests, npm audit, Python build/install) and user-only items (account/2FA, editable install, docs availability, tag readiness). Show HN Q&A templates (11 FAQs + catch-all) grounded in existing artifacts with tone discipline rules. Mintlify manual deployment runbook (preview, deploy, smoke checks, rollback). Demo recording guide explaining vhs setup, tape execution, sizing constraints, and CI deferral rationale. vhs terminal recording script configuring output, recording analyze/run/document/cleanup workflow, and generating demo.gif for README.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A wrapper so fine, a Python embrace,
For those who prefer pip's gentle grace.
Gates three stand tall, verified with might,
Docs bloom in bloom, transforms shine bright.
Show HN awaits—let refactoring take flight! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Week 8 — v0.2.0 launch surface' directly relates to the PR's main objective of preparing Refactron v0.2.0 for launch, covering all major changes including documentation, packaging, CI/CD, and release artifacts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/week-8-launch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
.github/workflows/release.yml (1)

24-31: ⚡ Quick win

Use structured TOML parsing for pyproject.toml version extraction.

The grep/sed extraction is format-sensitive and can fail on harmless TOML layout changes, causing avoidable release-blocking mismatches.

Proposed fix
-          PY=$(grep -m1 '^version' refactron-py/pyproject.toml | sed -E 's/version\s*=\s*"([^"]+)"/\1/')
+          PY=$(python - <<'PY'
+import tomllib
+with open("refactron-py/pyproject.toml", "rb") as f:
+    print(tomllib.load(f)["project"]["version"])
+PY
+)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 24 - 31, Replace the brittle
grep/sed extraction for PY with a robust TOML parse: instead of the current
PY=$(grep ...), run a Python one-liner that loads refactron-py/pyproject.toml
via tomllib (or tomli fallback) and prints the version (e.g. PY=$(python -c
"import sys, json\ntry: import tomllib as tl\nexcept: import tomli as
tl\nprint(tl.loads(open('refactron-py/pyproject.toml','rb').read().decode())['project']['version'])")).
Update the script to set PY from that command and keep the existing tag
comparison logic unchanged so the TAG != $PY check uses the parsed TOML value.
docs/cli/reference.mdx (1)

98-99: ⚡ Quick win

Verify provider and model defaults match configuration doc.

Line 98 lists --provider default as backend, and line 99 shows model default as "provider default". Check consistency with refactronrc.mdx.

From refactronrc.mdx:

  • Line 19: documentation.provider default is "backend"
  • Line 20: documentation.model default is "llama-3.3-70b-versatile"

The CLI reference says "provider default" which is vague. Consider being more specific or ensuring it matches the config file default.

📝 Suggested clarification
-| `--model=<name>` | string | provider default | Override the model name. |
+| `--model=<name>` | string | `llama-3.3-70b-versatile` | Override the model name. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/cli/reference.mdx` around lines 98 - 99, Update the CLI reference to
explicitly match the configuration defaults: change the `--provider` default
from the vague "backend" listing to reference the actual config key
`documentation.provider` (default "backend") and change the `--model` default
from "provider default" to the concrete default value from `refactronrc.mdx`
(the `documentation.model` default "llama-3.3-70b-versatile"), and ensure the
table entries for flags `--provider` and `--model` and any explanatory text
mention these exact config keys (`documentation.provider`,
`documentation.model`) so defaults are unambiguous.
README.md (1)

18-18: ⚡ Quick win

Consider removing the version pin from the install command.

The hardcoded @0.2.0 will become stale in future releases. Using npm install -g refactron (latest) is more maintainable for the README, especially post-launch.

📝 Proposed simplification
-npm install -g refactron@0.2.0
+npm install -g refactron
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 18, Replace the hardcoded pinned install command "npm
install -g refactron@0.2.0" in the README with an unpinned command so it
installs the latest release; update the line containing npm install -g
refactron@0.2.0 to read "npm install -g refactron" to avoid stale version pins.
dev-docs/launch/pre-ship-checklist.md (1)

20-33: ⚡ Quick win

Consider adding a release workflow verification item.

The checklist verifies npm credentials and PyPI authorization but doesn't explicitly check that the .github/workflows/release.yml workflow is functional. Since the ADR mentions OIDC Trusted Publishing and the PR objectives reference a tag-triggered release workflow, verifying the workflow is ready could prevent blocked publishes on Day 56.

💡 Suggested addition

Add after line 23:

- [ ] `.github/workflows/release.yml` passes on a test tag (or manual workflow dispatch confirms gates pass)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dev-docs/launch/pre-ship-checklist.md` around lines 20 - 33, Add a new
checklist item to the User-only pre-ship checklist to verify the release
workflow by confirming `.github/workflows/release.yml` runs successfully (e.g.,
triggers on a test tag or a manual workflow dispatch and all gates/pass checks
complete); update dev-docs/launch/pre-ship-checklist.md near the existing
release/PyPI checks (add after the npm/PyPI lines shown) with a bullet like “[ ]
`.github/workflows/release.yml` passes on a test tag (or manual dispatch
confirms gates pass)” so the team explicitly validates the OIDC/tag-triggered
release pipeline before ship day.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/concepts/safety-model.mdx`:
- Around line 64-68: Update the docs to mirror the actual detection logic in
src/verify/runners/detect.ts: list Vitest as checking vitest.config.ts and
vitest.config.js (remove .mjs), list Jest as checking jest.config.js and
jest.config.ts (remove .cjs and .json), and include setup.cfg in the pytest
detection list alongside pyproject.toml and pytest.ini; also clarify that the
implementation only checks for file existence (not contents or a [tool.pytest.*]
section). Reference the detect logic in src/verify/runners/detect.ts (e.g., the
detectTestRunner/file-checking logic) when making these documentation edits.

In `@docs/concepts/why-no-llm.mdx`:
- Line 61: Replace the two incorrect/mislabeled links on the line referencing
Meta/LibCST: update the first link target (the "Static analysis at scale: Meta's
approach" anchor) to the full Instagram Engineering post URL and change the
second "LibCST launch post" link (which currently points to the Glean article)
to the correct LibCST/Instagram launch post URL
https://instagram-engineering.com/static-analysis-at-scale-an-instagram-story-8f498ab71a0c
so the anchors and targets match the intended posts.

In `@docs/transforms/promise-constructor-to-async.mdx`:
- Line 48: The sentence references the unseen fixture `delayedValue`; either
include the example promise inline (e.g., show `new Promise((resolve) =>
setTimeout(() => resolve(value), ms))`) right after the sentence so readers see
what `delayedValue` contains, or remove the fixture name and reword to describe
the pattern (e.g., "Promises that defer resolution via setTimeout or event
listeners such as `new Promise((resolve) => setTimeout(...))` are left
alone")—update the sentence in docs/transforms/promise-constructor-to-async.mdx
to use one of these two approaches and keep the mention of the `no-async-escape`
precondition and the reason about preserving delay semantics.

In `@refactron-py/refactron/cli.py`:
- Around line 37-45: The current install path calls
subprocess.check_call(["npm","install","-g", NPM_PACKAGE]) which can raise
subprocess.CalledProcessError and produce a traceback; wrap that call in a
try/except catching CalledProcessError (and optionally OSError) and on error
raise SystemExit with a clear user-facing message indicating the npm install
failed, include the original exception message (str(e)) for context, and keep
the existing logic that checks _have("refactron") and returns
shutil.which("refactron") on success; reference the functions/_symbols _have,
NPM_PACKAGE, subprocess.check_call, CalledProcessError, shutil.which, and
SystemExit so the fix is applied in the same block.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 24-31: Replace the brittle grep/sed extraction for PY with a
robust TOML parse: instead of the current PY=$(grep ...), run a Python one-liner
that loads refactron-py/pyproject.toml via tomllib (or tomli fallback) and
prints the version (e.g. PY=$(python -c "import sys, json\ntry: import tomllib
as tl\nexcept: import tomli as
tl\nprint(tl.loads(open('refactron-py/pyproject.toml','rb').read().decode())['project']['version'])")).
Update the script to set PY from that command and keep the existing tag
comparison logic unchanged so the TAG != $PY check uses the parsed TOML value.

In `@dev-docs/launch/pre-ship-checklist.md`:
- Around line 20-33: Add a new checklist item to the User-only pre-ship
checklist to verify the release workflow by confirming
`.github/workflows/release.yml` runs successfully (e.g., triggers on a test tag
or a manual workflow dispatch and all gates/pass checks complete); update
dev-docs/launch/pre-ship-checklist.md near the existing release/PyPI checks (add
after the npm/PyPI lines shown) with a bullet like “[ ]
`.github/workflows/release.yml` passes on a test tag (or manual dispatch
confirms gates pass)” so the team explicitly validates the OIDC/tag-triggered
release pipeline before ship day.

In `@docs/cli/reference.mdx`:
- Around line 98-99: Update the CLI reference to explicitly match the
configuration defaults: change the `--provider` default from the vague "backend"
listing to reference the actual config key `documentation.provider` (default
"backend") and change the `--model` default from "provider default" to the
concrete default value from `refactronrc.mdx` (the `documentation.model` default
"llama-3.3-70b-versatile"), and ensure the table entries for flags `--provider`
and `--model` and any explanatory text mention these exact config keys
(`documentation.provider`, `documentation.model`) so defaults are unambiguous.

In `@README.md`:
- Line 18: Replace the hardcoded pinned install command "npm install -g
refactron@0.2.0" in the README with an unpinned command so it installs the
latest release; update the line containing npm install -g refactron@0.2.0 to
read "npm install -g refactron" to avoid stale version pins.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 509e5b47-1056-48a6-9313-3edadb6849c7

📥 Commits

Reviewing files that changed from the base of the PR and between d1c3ae8 and b518999.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (36)
  • .github/workflows/release.yml
  • .gitignore
  • .npmignore
  • CHANGELOG.md
  • README.md
  • SECURITY.md
  • dev-docs/decisions/10-week-8-launch.md
  • dev-docs/launch/deploy-docs.md
  • dev-docs/launch/pre-ship-checklist.md
  • dev-docs/launch/recording-the-demo.md
  • dev-docs/launch/show-hn-responses.md
  • docs/assets/.gitkeep
  • docs/cli/reference.mdx
  • docs/concepts/safety-model.mdx
  • docs/concepts/why-no-llm.mdx
  • docs/configuration/refactronrc.mdx
  • docs/faq.mdx
  • docs/mint.json
  • docs/transforms/callback-to-async-await.mdx
  • docs/transforms/class-to-dataclass.mdx
  • docs/transforms/commonjs-to-esm.mdx
  • docs/transforms/deprecated-api-requests-to-httpx.mdx
  • docs/transforms/format-to-fstring.mdx
  • docs/transforms/implicit-any.mdx
  • docs/transforms/index.mdx
  • docs/transforms/manual-typecheck-to-hints.mdx
  • docs/transforms/promise-chains-to-async.mdx
  • docs/transforms/promise-constructor-to-async.mdx
  • docs/transforms/var-to-const-let.mdx
  • package.json
  • refactron-py/LICENSE
  • refactron-py/README.md
  • refactron-py/pyproject.toml
  • refactron-py/refactron/__init__.py
  • refactron-py/refactron/cli.py
  • tape/demo.tape

Comment on lines +64 to +68
2. **Detect the test runner** by looking for a config file in the project root:
- `vitest.config.{ts,js,mjs}` → `vitest run`
- `jest.config.{ts,js,cjs,json}` → `jest`
- `pyproject.toml` with `[tool.pytest.*]` or `pytest.ini` → `pytest`
- User can override via `.refactronrc.json` `testCmd: "<command>"`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find test runner detection logic and verify config file patterns

# Search for test runner detection code
rg -n -C5 'vitest\.config|jest\.config|pytest\.ini|pyproject\.toml' --type=ts --type=js -g '!node_modules' -g '!dist'

# Also search for the test command detection function
ast-grep --pattern $'function detectTestRunner($$$) {
  $$$
}'

ast-grep --pattern $'const detectTestRunner = ($$$) => {
  $$$
}'

Repository: Refactron-ai/Refactron_Lib_TS

Length of output: 11561


Update documentation to match actual test runner detection patterns.

The documented config file patterns in lines 64-68 do not match the implementation in src/verify/runners/detect.ts. Corrections needed:

  • Vitest: Documentation lists vitest.config.{ts,js,mjs} but code only checks .ts and .js (no .mjs)
  • Jest: Documentation lists jest.config.{ts,js,cjs,json} but code only checks .js and .ts (no .cjs or .json)
  • Pytest: Code also checks setup.cfg (line 45 of src/verify/runners/detect.ts) which is not documented. Additionally, documentation mentions checking for [tool.pytest.*] section, but the code only checks file existence, not contents.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/concepts/safety-model.mdx` around lines 64 - 68, Update the docs to
mirror the actual detection logic in src/verify/runners/detect.ts: list Vitest
as checking vitest.config.ts and vitest.config.js (remove .mjs), list Jest as
checking jest.config.js and jest.config.ts (remove .cjs and .json), and include
setup.cfg in the pytest detection list alongside pyproject.toml and pytest.ini;
also clarify that the implementation only checks for file existence (not
contents or a [tool.pytest.*] section). Reference the detect logic in
src/verify/runners/detect.ts (e.g., the detectTestRunner/file-checking logic)
when making these documentation edits.

- Roberts, Donald B. *Practical Analysis for Refactoring.* PhD thesis, UIUC, 1999.
- Wang et al. ICSE 2018, "How Practitioners Perceive Automated Bug Report Management Techniques."
- Brunsfeld, Max. "Tree-sitter: a new parsing system for programming tools." Strange Loop 2018.
- Instagram engineering blog, "[Static analysis at scale: Meta's approach](https://engineering.fb.com/)" — and the [LibCST launch post](https://engineering.fb.com/2019/12/12/security/glean/) (2019), the underlying parser Refactron uses for Python.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What is the correct URL for the Meta/Instagram LibCST launch blog post from 2019?

💡 Result:

The correct URL for the Meta/Instagram LibCST launch blog post from 2019 is: https://instagram-engineering.com/static-analysis-at-scale-an-instagram-story-8f498ab71a0c This is the Instagram Engineering post that explicitly mentions that Instagram “recently open-sourced LibCST” and was published in August 2019.[1][2]

Citations:


Fix broken and mislabeled URLs for LibCST and Meta engineering posts.

Line 61 contains two URL issues:

  1. [Static analysis at scale: Meta's approach](https://engineering.fb.com/) — URL is incomplete (no path)
  2. [LibCST launch post](https://engineering.fb.com/2019/12/12/security/glean/) — URL points to a Glean article, not LibCST

The correct LibCST launch post is from August 2019 at: https://instagram-engineering.com/static-analysis-at-scale-an-instagram-story-8f498ab71a0c

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/concepts/why-no-llm.mdx` at line 61, Replace the two
incorrect/mislabeled links on the line referencing Meta/LibCST: update the first
link target (the "Static analysis at scale: Meta's approach" anchor) to the full
Instagram Engineering post URL and change the second "LibCST launch post" link
(which currently points to the Glean article) to the correct LibCST/Instagram
launch post URL
https://instagram-engineering.com/static-analysis-at-scale-an-instagram-story-8f498ab71a0c
so the anchors and targets match the intended posts.


## Edge cases NOT handled (skip via precondition)

- Executor uses `setTimeout` / event listeners to defer resolve (precondition `no-async-escape`). The `delayedValue` fixture is intentionally an example of this — `new Promise((resolve) => setTimeout(() => resolve(value), ms))` is left alone because folding it would lose the delay semantics.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clarify or remove the delayedValue fixture reference.

The sentence references "The delayedValue fixture" without providing context or showing the example. Users reading this page won't know what this fixture contains. Consider either including the example inline or rephrasing to describe the pattern without referencing an unseen fixture.

📝 Suggested clarification
-Executor uses `setTimeout` / event listeners to defer resolve (precondition `no-async-escape`). The `delayedValue` fixture is intentionally an example of this — `new Promise((resolve) => setTimeout(() => resolve(value), ms))` is left alone because folding it would lose the delay semantics.
+Executor uses `setTimeout` / event listeners to defer resolve (precondition `no-async-escape`). For example, `new Promise((resolve) => setTimeout(() => resolve(value), ms))` is left alone because folding it would lose the delay semantics.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Executor uses `setTimeout` / event listeners to defer resolve (precondition `no-async-escape`). The `delayedValue` fixture is intentionally an example of this — `new Promise((resolve) => setTimeout(() => resolve(value), ms))` is left alone because folding it would lose the delay semantics.
- Executor uses `setTimeout` / event listeners to defer resolve (precondition `no-async-escape`). For example, `new Promise((resolve) => setTimeout(() => resolve(value), ms))` is left alone because folding it would lose the delay semantics.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/transforms/promise-constructor-to-async.mdx` at line 48, The sentence
references the unseen fixture `delayedValue`; either include the example promise
inline (e.g., show `new Promise((resolve) => setTimeout(() => resolve(value),
ms))`) right after the sentence so readers see what `delayedValue` contains, or
remove the fixture name and reword to describe the pattern (e.g., "Promises that
defer resolution via setTimeout or event listeners such as `new
Promise((resolve) => setTimeout(...))` are left alone")—update the sentence in
docs/transforms/promise-constructor-to-async.mdx to use one of these two
approaches and keep the mention of the `no-async-escape` precondition and the
reason about preserving delay semantics.

Comment on lines +37 to +45
if _have("npm"):
subprocess.check_call(["npm", "install", "-g", NPM_PACKAGE], stdout=sys.stderr)
if _have("refactron"):
return shutil.which("refactron") # type: ignore[return-value]

raise SystemExit(
"refactron: the underlying Node CLI is not installed. "
"Run `npm install -g refactron` or use `npx refactron` directly."
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# First, let's explore the repository structure
find . -type f -name "*.py" | head -20

Repository: Refactron-ai/Refactron_Lib_TS

Length of output: 1024


🏁 Script executed:

# Locate the cli.py file
fd -t f cli.py

Repository: Refactron-ai/Refactron_Lib_TS

Length of output: 103


🏁 Script executed:

# Read the cli.py file to examine the code at lines 37-45
if [ -f "refactron/cli.py" ]; then
  cat -n refactron/cli.py | sed -n '1,60p'
else
  find . -name "cli.py" -type f | head -5
fi

Repository: Refactron-ai/Refactron_Lib_TS

Length of output: 105


🏁 Script executed:

# Also check git ls-files to find the file structure
git ls-files | grep -E "(cli\.py|refactron)" | head -20

Repository: Refactron-ai/Refactron_Lib_TS

Length of output: 260


🏁 Script executed:

# Read the cli.py file to see the code around lines 37-45
cat -n refactron-py/refactron/cli.py

Repository: Refactron-ai/Refactron_Lib_TS

Length of output: 2919


Handle npm install failures with a user-facing error instead of a traceback.

Line 38 can raise CalledProcessError, which currently escapes and shows a Python traceback on first-run install failures.

Proposed fix
 def _ensure_npm_cli() -> str:
     """Return the absolute path to the `refactron` CLI executable.
 
     If `refactron` is on PATH, use it. Otherwise install via `npm install -g`
     (best-effort) and re-check. If still missing, raise."""
     if _have("refactron"):
         return shutil.which("refactron")  # type: ignore[return-value]
 
     # Try a one-shot global install via npm.
     if _have("npm"):
+        try:
-            subprocess.check_call(["npm", "install", "-g", NPM_PACKAGE], stdout=sys.stderr)
+            subprocess.check_call(["npm", "install", "-g", NPM_PACKAGE], stdout=sys.stderr)
+        except (subprocess.SubprocessError, OSError) as exc:
+            raise SystemExit(
+                "refactron: failed to install the underlying Node CLI via npm. "
+                "Please run `npm install -g refactron` manually and retry."
+            ) from exc
         if _have("refactron"):
             return shutil.which("refactron")  # type: ignore[return-value]
🧰 Tools
🪛 Ruff (0.15.12)

[error] 38-38: subprocess call: check for execution of untrusted input

(S603)


[error] 38-38: Starting a process with a partial executable path

(S607)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@refactron-py/refactron/cli.py` around lines 37 - 45, The current install path
calls subprocess.check_call(["npm","install","-g", NPM_PACKAGE]) which can raise
subprocess.CalledProcessError and produce a traceback; wrap that call in a
try/except catching CalledProcessError (and optionally OSError) and on error
raise SystemExit with a clear user-facing message indicating the npm install
failed, include the original exception message (str(e)) for context, and keep
the existing logic that checks _have("refactron") and returns
shutil.which("refactron") on success; reference the functions/_symbols _have,
NPM_PACKAGE, subprocess.check_call, CalledProcessError, shutil.which, and
SystemExit so the fix is applied in the same block.

Renders refactron login -> REPL -> analyze . -> run --dry-run -> run --apply
-> document --apply -> exit. 590 KB at 960x600, well under the 5 MB README cap.

Tape rewritten to reflect the actual REPL UX: a single 'refactron login'
launch boots the app (auto-shows OAuth UI when not authenticated, drops
straight to REPL when creds exist), then commands are bare verbs inside
the REPL — no second 'refactron' prefix needed.

The .gitkeep placeholder from Day 52's deferred-recording commit is no
longer needed now that the GIF is present.
@omsherikar
omsherikar merged commit 3406bd5 into main May 14, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants