Week 8 — v0.2.0 launch surface - #26
Conversation
- 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
… register in mint.json
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.
|
Warning Rate limit exceeded
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 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR delivers v0.2.0 as a complete release: a Python package wrapper ( Changesv0.2.0 Release Infrastructure
User-Facing Documentation
Launch Coordination & Release Notes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (4)
.github/workflows/release.yml (1)
24-31: ⚡ Quick winUse structured TOML parsing for
pyproject.tomlversion 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 winVerify provider and model defaults match configuration doc.
Line 98 lists
--providerdefault asbackend, and line 99 shows model default as "provider default". Check consistency withrefactronrc.mdx.From
refactronrc.mdx:
- Line 19:
documentation.providerdefault is"backend"✓- Line 20:
documentation.modeldefault 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 winConsider removing the version pin from the install command.
The hardcoded
@0.2.0will become stale in future releases. Usingnpm 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 winConsider adding a release workflow verification item.
The checklist verifies npm credentials and PyPI authorization but doesn't explicitly check that the
.github/workflows/release.ymlworkflow 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (36)
.github/workflows/release.yml.gitignore.npmignoreCHANGELOG.mdREADME.mdSECURITY.mddev-docs/decisions/10-week-8-launch.mddev-docs/launch/deploy-docs.mddev-docs/launch/pre-ship-checklist.mddev-docs/launch/recording-the-demo.mddev-docs/launch/show-hn-responses.mddocs/assets/.gitkeepdocs/cli/reference.mdxdocs/concepts/safety-model.mdxdocs/concepts/why-no-llm.mdxdocs/configuration/refactronrc.mdxdocs/faq.mdxdocs/mint.jsondocs/transforms/callback-to-async-await.mdxdocs/transforms/class-to-dataclass.mdxdocs/transforms/commonjs-to-esm.mdxdocs/transforms/deprecated-api-requests-to-httpx.mdxdocs/transforms/format-to-fstring.mdxdocs/transforms/implicit-any.mdxdocs/transforms/index.mdxdocs/transforms/manual-typecheck-to-hints.mdxdocs/transforms/promise-chains-to-async.mdxdocs/transforms/promise-constructor-to-async.mdxdocs/transforms/var-to-const-let.mdxpackage.jsonrefactron-py/LICENSErefactron-py/README.mdrefactron-py/pyproject.tomlrefactron-py/refactron/__init__.pyrefactron-py/refactron/cli.pytape/demo.tape
| 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>"`. |
There was a problem hiding this comment.
🧩 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.tsand.js(no.mjs) - Jest: Documentation lists
jest.config.{ts,js,cjs,json}but code only checks.jsand.ts(no.cjsor.json) - Pytest: Code also checks
setup.cfg(line 45 ofsrc/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. |
There was a problem hiding this comment.
🧩 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:
- 1: https://instagram-engineering.com/static-analysis-at-scale-an-instagram-story-8f498ab71a0c
- 2: https://instagram-engineering.com/static-analysis-at-scale-an-instagram-story-8f498ab71a0c?gi=120f09852a77
Fix broken and mislabeled URLs for LibCST and Meta engineering posts.
Line 61 contains two URL issues:
[Static analysis at scale: Meta's approach](https://engineering.fb.com/)— URL is incomplete (no path)[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. |
There was a problem hiding this comment.
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.
| - 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.
| 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." | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's explore the repository structure
find . -type f -name "*.py" | head -20Repository: Refactron-ai/Refactron_Lib_TS
Length of output: 1024
🏁 Script executed:
# Locate the cli.py file
fd -t f cli.pyRepository: 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
fiRepository: 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 -20Repository: 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.pyRepository: 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.
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
npm auditcleared (vitest 1 → 3);SECURITY.mdwith disclosure policy + threat modeltape/demo.tapewritten;docs/assets/demo.gifgeneration deferred to localvhsrenderauthor+publishConfigadded; version bumped to0.2.0;SECURITY.mdadded tofiles;typescriptmoved todependencies(was breakingrefactron runon every fresh install)refactron-py/package — thin shim that detects Node and shells out to the npm CLI;os.execvpfor clean signal pass-throughrelease.ymlextended to publish PyPI alongside npm via Trusted Publishing (OIDC, no token)Smokes
npm install ./refactron-0.2.0.tgz→refactron --version→0.2.0→analyze+run --dry-run+document --applyPASSrefactron --version→0.2.0PASSnpm publish --dry-run: 237 kB tarball, expected file list (no leakage oftests/,dev-docs/,fixtures/,tape/,docs/,refactron-py/)Ship-day prerequisites (Day 56, user-driven)
brew install vhs && vhs tape/demo.tapepypi.org/manage/account/publishing/→ Add pending publisher (owner=Refactron-ai, repo=Refactron_Lib_TS, workflow=release.yml, environment=pypi-production)pypi-productioncreated (Settings → Environments)NPM_TOKENsecret on thenpm-productionenvironment (skip if already set from a prior publish)git tag v0.2.0 && git push origin v0.2.0→ release.yml takes overWhat'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
refactron-0.2.0.tgzon macOStwine checkon sdist + wheelnpm publish --dry-runfile-list auditnpm audit --audit-level=highexit 0dev-docs/launch/pre-ship-checklist.mdto confirm the user-only items make sensedev-docs/decisions/10-week-8-launch.mdfor the seven launch decisionsSummary by CodeRabbit
New Features
refactron-pywrapper for pip installation.Documentation
Infrastructure