refactorai-cli 0.7.9__tar.gz → 0.7.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/PKG-INFO +47 -3
- refactorai_cli-0.7.11/README.md +130 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/pyproject.toml +2 -2
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/__init__.py +1 -1
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/cloud_rr.py +114 -28
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/run_cmds.py +194 -61
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/runtime_proxy_cmds.py +64 -25
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/setup_cmds.py +14 -1
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/setup_flow.py +187 -1
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli.egg-info/PKG-INFO +47 -3
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli.egg-info/requires.txt +1 -1
- refactorai_cli-0.7.9/README.md +0 -86
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/auth.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/client.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/__init__.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/account_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/auth_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/branch_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/cloud_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/engine_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/hook_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/model_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/policy_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/pre_push_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/request_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/rules_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/runtime_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/toolchains_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/watch_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commands/workspace_cmds.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commit_queue.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/commit_telemetry.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/control_plane.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/credentials.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/dotenv_loader.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/git_scope.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/local_constitution.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/local_engine_runtime.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/local_paths.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/main.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/model_policy.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/pre_push_gate.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/refactor_branch_store.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/review_runner.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/runtime_manager.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/settings.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/watch_ledger.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/watch_state.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli/watch_supervisor.py +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli.egg-info/SOURCES.txt +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli.egg-info/dependency_links.txt +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli.egg-info/entry_points.txt +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/refactorai_cli.egg-info/top_level.txt +0 -0
- {refactorai_cli-0.7.9 → refactorai_cli-0.7.11}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: refactorai-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.11
|
|
4
4
|
Summary: Local-first CLI for the refactor platform
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -8,7 +8,7 @@ Requires-Dist: typer>=0.12.0
|
|
|
8
8
|
Requires-Dist: httpx>=0.27.0
|
|
9
9
|
Requires-Dist: rich>=13.7.0
|
|
10
10
|
Requires-Dist: PyYAML>=6.0.1
|
|
11
|
-
Requires-Dist: refactorai-core>=3.2.
|
|
11
|
+
Requires-Dist: refactorai-core>=3.2.22
|
|
12
12
|
|
|
13
13
|
# refactorai-cli
|
|
14
14
|
|
|
@@ -22,6 +22,50 @@ By default, the CLI targets `https://api.refactorai.codes`.
|
|
|
22
22
|
Use `REFACTOR_PLATFORM_URL` only when you need to override the control-plane URL
|
|
23
23
|
(for self-hosted or local development environments).
|
|
24
24
|
|
|
25
|
+
## Developer flow (init → setup → doctor → watch)
|
|
26
|
+
|
|
27
|
+
The standard flow after creating an account and generating a developer key:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 1. Create the project (prompts for the developer key if needed) and register
|
|
31
|
+
# it with the platform. Writes refactor.consti + refactor.config.
|
|
32
|
+
refactor init
|
|
33
|
+
|
|
34
|
+
# 2. Choose the execution mode and provision only what that mode needs.
|
|
35
|
+
# Mode can be chosen in the web UI or here; the two stay in sync.
|
|
36
|
+
refactor setup --mode local_byok
|
|
37
|
+
|
|
38
|
+
# 3. Verify readiness for the resolved mode.
|
|
39
|
+
refactor doctor
|
|
40
|
+
|
|
41
|
+
# 4. Start the commit loop: commit in your editor, and each commit is reviewed,
|
|
42
|
+
# refactored, verified, and merged, then it waits for the next commit.
|
|
43
|
+
refactor watch
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Execution modes at a glance
|
|
47
|
+
|
|
48
|
+
Two independent axes: where the **engine** runs, and where **verification
|
|
49
|
+
(tests)** runs. See `docs/46-execution-variants-and-developer-flow.md`.
|
|
50
|
+
|
|
51
|
+
| variant | engine | verification (tests) | runtime artifact |
|
|
52
|
+
| --------------- | ----------------- | ------------------------------------ | ---------------- |
|
|
53
|
+
| local_model | local | local | **required** |
|
|
54
|
+
| local_byok | server | local (Podman sandbox / toolchain) | not required |
|
|
55
|
+
| local_managed | server | local (Podman sandbox / toolchain) | not required |
|
|
56
|
+
| cloud_byok | server | server | not required |
|
|
57
|
+
| cloud_managed | server | server | not required |
|
|
58
|
+
|
|
59
|
+
`refactor setup` is mode-aware: `local_byok` provisions the local verification
|
|
60
|
+
environment (Podman first) + auth only — it does **not** download the runtime
|
|
61
|
+
artifact or install a local model. Only `local_model` needs the runtime artifact.
|
|
62
|
+
|
|
63
|
+
The verification environment is chosen by a single OS/machine-aware seam
|
|
64
|
+
(`refactor_core.verification_env`): the Podman sandbox by default, falling back to
|
|
65
|
+
the managed host toolchain when no container runtime is available. `refactor
|
|
66
|
+
doctor` reports the selected environment (and `refactor doctor --sandbox` shows
|
|
67
|
+
its full state), so a run and diagnostics always agree.
|
|
68
|
+
|
|
25
69
|
## Local development install
|
|
26
70
|
|
|
27
71
|
From repository root:
|
|
@@ -71,7 +115,7 @@ refactor login
|
|
|
71
115
|
|
|
72
116
|
# 2A. Preferred: set BYOK directly from project env in refactor.config:
|
|
73
117
|
#
|
|
74
|
-
#
|
|
118
|
+
# execution_variant: cloud_byok
|
|
75
119
|
# provider: openai
|
|
76
120
|
# model_id: gpt-4.1-mini
|
|
77
121
|
# provider_key: ${OPENAI_API_KEY}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# refactorai-cli
|
|
2
|
+
|
|
3
|
+
Public CLI package for Refactor.
|
|
4
|
+
|
|
5
|
+
- PyPI package name: `refactorai-cli`
|
|
6
|
+
- Installed command: `refactor`
|
|
7
|
+
- Python module package: `refactorai_cli`
|
|
8
|
+
|
|
9
|
+
By default, the CLI targets `https://api.refactorai.codes`.
|
|
10
|
+
Use `REFACTOR_PLATFORM_URL` only when you need to override the control-plane URL
|
|
11
|
+
(for self-hosted or local development environments).
|
|
12
|
+
|
|
13
|
+
## Developer flow (init → setup → doctor → watch)
|
|
14
|
+
|
|
15
|
+
The standard flow after creating an account and generating a developer key:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 1. Create the project (prompts for the developer key if needed) and register
|
|
19
|
+
# it with the platform. Writes refactor.consti + refactor.config.
|
|
20
|
+
refactor init
|
|
21
|
+
|
|
22
|
+
# 2. Choose the execution mode and provision only what that mode needs.
|
|
23
|
+
# Mode can be chosen in the web UI or here; the two stay in sync.
|
|
24
|
+
refactor setup --mode local_byok
|
|
25
|
+
|
|
26
|
+
# 3. Verify readiness for the resolved mode.
|
|
27
|
+
refactor doctor
|
|
28
|
+
|
|
29
|
+
# 4. Start the commit loop: commit in your editor, and each commit is reviewed,
|
|
30
|
+
# refactored, verified, and merged, then it waits for the next commit.
|
|
31
|
+
refactor watch
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Execution modes at a glance
|
|
35
|
+
|
|
36
|
+
Two independent axes: where the **engine** runs, and where **verification
|
|
37
|
+
(tests)** runs. See `docs/46-execution-variants-and-developer-flow.md`.
|
|
38
|
+
|
|
39
|
+
| variant | engine | verification (tests) | runtime artifact |
|
|
40
|
+
| --------------- | ----------------- | ------------------------------------ | ---------------- |
|
|
41
|
+
| local_model | local | local | **required** |
|
|
42
|
+
| local_byok | server | local (Podman sandbox / toolchain) | not required |
|
|
43
|
+
| local_managed | server | local (Podman sandbox / toolchain) | not required |
|
|
44
|
+
| cloud_byok | server | server | not required |
|
|
45
|
+
| cloud_managed | server | server | not required |
|
|
46
|
+
|
|
47
|
+
`refactor setup` is mode-aware: `local_byok` provisions the local verification
|
|
48
|
+
environment (Podman first) + auth only — it does **not** download the runtime
|
|
49
|
+
artifact or install a local model. Only `local_model` needs the runtime artifact.
|
|
50
|
+
|
|
51
|
+
The verification environment is chosen by a single OS/machine-aware seam
|
|
52
|
+
(`refactor_core.verification_env`): the Podman sandbox by default, falling back to
|
|
53
|
+
the managed host toolchain when no container runtime is available. `refactor
|
|
54
|
+
doctor` reports the selected environment (and `refactor doctor --sandbox` shows
|
|
55
|
+
its full state), so a run and diagnostics always agree.
|
|
56
|
+
|
|
57
|
+
## Local development install
|
|
58
|
+
|
|
59
|
+
From repository root:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install -e refactorai-core -e refactorai-cli
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Build
|
|
66
|
+
|
|
67
|
+
From repository root:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python -m pip install --upgrade build twine
|
|
71
|
+
python -m build "./refactorai-cli"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Artifacts are created in:
|
|
75
|
+
|
|
76
|
+
- `refactorai-cli/dist/*.whl`
|
|
77
|
+
- `refactorai-cli/dist/*.tar.gz`
|
|
78
|
+
|
|
79
|
+
## Publish
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python -m twine check ./refactorai-cli/dist/*
|
|
83
|
+
python -m twine upload ./refactorai-cli/dist/*
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Install test (local)
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
python -m pip install ./refactorai-cli/dist/refactorai_cli-0.3.4-py3-none-any.whl
|
|
90
|
+
refactor --version
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Cloud BYOK setup (bring your own provider key)
|
|
94
|
+
|
|
95
|
+
Run cloud inference with your own provider credentials (no local runtime
|
|
96
|
+
required). Preferred path is env-key in project config (`provider_key:
|
|
97
|
+
${ENV_VAR}`). Platform-stored credentials (`credential_ref`) are optional
|
|
98
|
+
fallback.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# 1. Authenticate (developer key with the run:byok entitlement).
|
|
102
|
+
refactor login
|
|
103
|
+
|
|
104
|
+
# 2A. Preferred: set BYOK directly from project env in refactor.config:
|
|
105
|
+
#
|
|
106
|
+
# execution_variant: cloud_byok
|
|
107
|
+
# provider: openai
|
|
108
|
+
# model_id: gpt-4.1-mini
|
|
109
|
+
# provider_key: ${OPENAI_API_KEY}
|
|
110
|
+
#
|
|
111
|
+
# 2B. Optional fallback: register a platform-stored credential from env.
|
|
112
|
+
export OPENAI_API_KEY=sk-...
|
|
113
|
+
refactor cloud credentials set --provider openai --from-env OPENAI_API_KEY --label "my key"
|
|
114
|
+
# -> prints a credential_ref, e.g. cred_01J...
|
|
115
|
+
|
|
116
|
+
# 3. If you use platform-stored fallback, set credential_ref in config:
|
|
117
|
+
# credential_ref: cred_01J...
|
|
118
|
+
|
|
119
|
+
# 4. Verify readiness, then run.
|
|
120
|
+
refactor doctor
|
|
121
|
+
refactor review .
|
|
122
|
+
refactor code . --apply
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Manage credentials:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
refactor cloud credentials list
|
|
129
|
+
refactor cloud credentials remove --credential-ref cred_01J...
|
|
130
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "refactorai-cli"
|
|
3
|
-
version = "0.7.
|
|
3
|
+
version = "0.7.11"
|
|
4
4
|
description = "Local-first CLI for the refactor platform"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -12,7 +12,7 @@ dependencies = [
|
|
|
12
12
|
"httpx>=0.27.0",
|
|
13
13
|
"rich>=13.7.0",
|
|
14
14
|
"PyYAML>=6.0.1",
|
|
15
|
-
"refactorai-core>=3.2.
|
|
15
|
+
"refactorai-core>=3.2.22",
|
|
16
16
|
]
|
|
17
17
|
|
|
18
18
|
[project.scripts]
|
|
@@ -148,6 +148,43 @@ def _run_test(
|
|
|
148
148
|
return False, (proc.stdout or proc.stderr or "")[-500:]
|
|
149
149
|
|
|
150
150
|
|
|
151
|
+
def _make_sandbox_verifier(
|
|
152
|
+
sandbox_ctx: dict,
|
|
153
|
+
) -> tuple[Callable[[str | None], tuple[bool, str]] | None, str, str]:
|
|
154
|
+
"""Build a test runner that executes inside the project's sandbox container.
|
|
155
|
+
|
|
156
|
+
docs/46: ``local_byok`` / ``local_managed`` run the engine on the Refactor
|
|
157
|
+
server but verify on the developer's machine. The per-project sandbox
|
|
158
|
+
(created + preflighted by the CLI, mounting ``project_root`` at ``workdir``)
|
|
159
|
+
is reused here so applied diffs and the installed toolchain are both visible.
|
|
160
|
+
|
|
161
|
+
Returns ``(runner, container_name, error)``. ``runner`` is ``None`` when the
|
|
162
|
+
context is incomplete, with a human-readable ``error``.
|
|
163
|
+
"""
|
|
164
|
+
runtime = str(sandbox_ctx.get("runtime") or "podman")
|
|
165
|
+
container = str(sandbox_ctx.get("container_name") or "")
|
|
166
|
+
workdir = str(sandbox_ctx.get("workdir") or "/workspace")
|
|
167
|
+
if not container:
|
|
168
|
+
return None, "", "sandbox context is missing a container name"
|
|
169
|
+
|
|
170
|
+
from refactor_core import sandbox_runtime as _sr
|
|
171
|
+
|
|
172
|
+
def _runner(test_command: str | None) -> tuple[bool, str]:
|
|
173
|
+
if not test_command or not str(test_command).strip():
|
|
174
|
+
return False, "no test command configured; cannot verify behavior preservation"
|
|
175
|
+
command = str(test_command).strip()
|
|
176
|
+
if command == "npm test":
|
|
177
|
+
command = "CI=true npm test -- --watch=false"
|
|
178
|
+
return _sr.exec_in_container(
|
|
179
|
+
runtime=runtime,
|
|
180
|
+
container_name=container,
|
|
181
|
+
command=command,
|
|
182
|
+
workdir=workdir,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
return _runner, container, ""
|
|
186
|
+
|
|
187
|
+
|
|
151
188
|
def _run_command_with_progress(
|
|
152
189
|
execution_root: Path,
|
|
153
190
|
command: str,
|
|
@@ -1505,7 +1542,13 @@ def run_cloud_refactor_requests(
|
|
|
1505
1542
|
progress_cb = progress_cb or (lambda e: None)
|
|
1506
1543
|
approval_cb = approval_cb or (lambda r: False)
|
|
1507
1544
|
|
|
1508
|
-
|
|
1545
|
+
from refactor_core.execution_variant import (
|
|
1546
|
+
platform_inference_mode,
|
|
1547
|
+
resolve_execution_variant,
|
|
1548
|
+
)
|
|
1549
|
+
|
|
1550
|
+
variant = resolve_execution_variant(getattr(constitution, "settings", {}) or {})
|
|
1551
|
+
execution_mode = platform_inference_mode(variant) or "cloud_managed"
|
|
1509
1552
|
auth_ctx = ensure_authenticated(project_root)
|
|
1510
1553
|
test_command, testcmd_note = _resolve_cloud_test_command(
|
|
1511
1554
|
project_root=project_root,
|
|
@@ -1540,7 +1583,31 @@ def run_cloud_refactor_requests(
|
|
|
1540
1583
|
test_command=test_command or "",
|
|
1541
1584
|
execution_env="cloud",
|
|
1542
1585
|
)
|
|
1543
|
-
|
|
1586
|
+
# docs/46: for local-verification variants (local_byok / local_managed) the
|
|
1587
|
+
# CLI passes the ready project sandbox via ``_sandbox_context``. When present,
|
|
1588
|
+
# verification runs INSIDE that container (which mounts project_root and has
|
|
1589
|
+
# the preflight-installed toolchain), so we verify against project_root
|
|
1590
|
+
# directly and skip host toolchain provisioning. _apply_and_verify still backs
|
|
1591
|
+
# up before applying and reverts on red, preserving the "never leave a red
|
|
1592
|
+
# tree" guarantee. Cloud_* variants keep the managed-workspace mirror + host
|
|
1593
|
+
# verification path unchanged.
|
|
1594
|
+
sandbox_ctx = config.get("_sandbox_context") if isinstance(config, dict) else None
|
|
1595
|
+
verify_runner: Callable[[str | None], tuple[bool, str]] | None = None
|
|
1596
|
+
if sandbox_ctx:
|
|
1597
|
+
verify_runner, _verify_container, verify_err = _make_sandbox_verifier(sandbox_ctx)
|
|
1598
|
+
if verify_runner is None:
|
|
1599
|
+
reason = f"sandbox verification unavailable: {verify_err}"
|
|
1600
|
+
_emit(progress_cb, phase="rr", event="preflight_failed", reason=reason)
|
|
1601
|
+
notes.append(reason)
|
|
1602
|
+
return _build_artifact(
|
|
1603
|
+
run_store, run_id, constitution, model_id, outcomes, counts,
|
|
1604
|
+
notes, stopped=True, stop_reason=reason, test_command=test_command,
|
|
1605
|
+
)
|
|
1606
|
+
|
|
1607
|
+
if verify_runner is not None:
|
|
1608
|
+
execution_root = project_root
|
|
1609
|
+
else:
|
|
1610
|
+
execution_root = _prepare_managed_workspace(project_root, progress_cb=progress_cb)
|
|
1544
1611
|
status_before = _git_status_porcelain(project_root)
|
|
1545
1612
|
|
|
1546
1613
|
# Managed host toolchain: when the resolved command's runtime is missing from
|
|
@@ -1557,17 +1624,22 @@ def run_cloud_refactor_requests(
|
|
|
1557
1624
|
apply_byok_payload=apply_byok_payload,
|
|
1558
1625
|
)
|
|
1559
1626
|
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1627
|
+
if verify_runner is not None:
|
|
1628
|
+
# Sandbox verification (docs/46): the container supplies the toolchain, so
|
|
1629
|
+
# no host runtime is provisioned and the host working tree is untouched.
|
|
1630
|
+
toolchain_env, toolchain_note = None, "verification runs in the project sandbox"
|
|
1631
|
+
else:
|
|
1632
|
+
toolchain_env, toolchain_note = _provision_toolchain(
|
|
1633
|
+
execution_root,
|
|
1634
|
+
test_command,
|
|
1635
|
+
config,
|
|
1636
|
+
consent_cb=toolchain_consent_cb,
|
|
1637
|
+
progress_cb=progress_cb,
|
|
1638
|
+
dep_locator_cb=_dep_locator,
|
|
1639
|
+
)
|
|
1640
|
+
toolchain_env = _workspace_env(project_root, toolchain_env)
|
|
1569
1641
|
status_after_toolchain = _git_status_porcelain(project_root)
|
|
1570
|
-
if status_after_toolchain != status_before:
|
|
1642
|
+
if verify_runner is None and status_after_toolchain != status_before:
|
|
1571
1643
|
reason = (
|
|
1572
1644
|
"managed workspace invariant violated: toolchain/dependency setup changed the project "
|
|
1573
1645
|
"working tree before any RR patch was applied; aborting run."
|
|
@@ -1601,7 +1673,7 @@ def run_cloud_refactor_requests(
|
|
|
1601
1673
|
# we did NOT provision a managed runtime (managed provisioning already
|
|
1602
1674
|
# supplies a `python`). Prevents a `python: not found` baseline failure and
|
|
1603
1675
|
# the endless-defer loop it caused.
|
|
1604
|
-
if toolchain_env is None and test_command:
|
|
1676
|
+
if verify_runner is None and toolchain_env is None and test_command:
|
|
1605
1677
|
normalized = _normalize_command_interpreters(test_command)
|
|
1606
1678
|
if normalized and normalized != test_command:
|
|
1607
1679
|
_emit(
|
|
@@ -1620,23 +1692,25 @@ def run_cloud_refactor_requests(
|
|
|
1620
1692
|
# Run-level dependency preflight: always attempt dependency restoration for
|
|
1621
1693
|
# runtimes implied by the configured test command, even when binaries are
|
|
1622
1694
|
# already present on PATH. This prevents import-time baseline failures from
|
|
1623
|
-
# deferring requests one-by-one later in the loop.
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1695
|
+
# deferring requests one-by-one later in the loop. Skipped for sandbox
|
|
1696
|
+
# verification (docs/46): the container's preflight already provisioned deps.
|
|
1697
|
+
if verify_runner is None:
|
|
1698
|
+
for runtime in _command_runtimes(test_command):
|
|
1699
|
+
_restore_dependencies(
|
|
1700
|
+
execution_root,
|
|
1701
|
+
runtime,
|
|
1702
|
+
toolchain_env,
|
|
1703
|
+
progress_cb,
|
|
1704
|
+
config=config,
|
|
1705
|
+
dep_locator_cb=_dep_locator,
|
|
1706
|
+
)
|
|
1633
1707
|
|
|
1634
1708
|
# Fail-fast: if a test command is configured but STILL not runnable after
|
|
1635
1709
|
# provisioning + interpreter normalization, stop up front with an actionable
|
|
1636
1710
|
# message instead of opening a session and deferring every RR behind an
|
|
1637
1711
|
# opaque `python: not found`. (A run with NO test command keeps prior
|
|
1638
1712
|
# behavior: the server decides per-RR whether it can proceed.)
|
|
1639
|
-
if test_command and not _client_preflight_command(
|
|
1713
|
+
if verify_runner is None and test_command and not _client_preflight_command(
|
|
1640
1714
|
project_root, test_command, env=toolchain_env
|
|
1641
1715
|
):
|
|
1642
1716
|
missing = _missing_binaries(test_command, env=toolchain_env)
|
|
@@ -1663,7 +1737,10 @@ def run_cloud_refactor_requests(
|
|
|
1663
1737
|
# Run-level baseline characterization: execute ONCE and reuse for all RR
|
|
1664
1738
|
# steps. If baseline is red, stop the run before opening the RR session so
|
|
1665
1739
|
# requests are not deferred one-by-one for dependency/env failures.
|
|
1666
|
-
|
|
1740
|
+
if verify_runner is not None:
|
|
1741
|
+
baseline_ok, baseline_detail = verify_runner(test_command)
|
|
1742
|
+
else:
|
|
1743
|
+
baseline_ok, baseline_detail = _run_test(execution_root, test_command, env=toolchain_env)
|
|
1667
1744
|
_emit(
|
|
1668
1745
|
progress_cb,
|
|
1669
1746
|
phase="rr",
|
|
@@ -1671,7 +1748,7 @@ def run_cloud_refactor_requests(
|
|
|
1671
1748
|
rr_id="",
|
|
1672
1749
|
passed=baseline_ok,
|
|
1673
1750
|
detail=baseline_detail,
|
|
1674
|
-
execution_env="host+toolchain" if toolchain_env else "host",
|
|
1751
|
+
execution_env="sandbox" if verify_runner is not None else ("host+toolchain" if toolchain_env else "host"),
|
|
1675
1752
|
)
|
|
1676
1753
|
if not baseline_ok:
|
|
1677
1754
|
reason = (
|
|
@@ -1778,7 +1855,7 @@ def run_cloud_refactor_requests(
|
|
|
1778
1855
|
passed, detail = cached_baseline
|
|
1779
1856
|
_emit(progress_cb, phase="rr", event="baseline_test", rr_id=current_rr_id,
|
|
1780
1857
|
passed=passed, detail=detail,
|
|
1781
|
-
execution_env="host+toolchain" if toolchain_env else "host")
|
|
1858
|
+
execution_env="sandbox" if verify_runner is not None else ("host+toolchain" if toolchain_env else "host"))
|
|
1782
1859
|
action = session.step(
|
|
1783
1860
|
_step_payload(token, current_rr_id, "baseline_result", by_id, project_root,
|
|
1784
1861
|
baseline_passed=passed, baseline_detail=detail)
|
|
@@ -1858,6 +1935,7 @@ def run_cloud_refactor_requests(
|
|
|
1858
1935
|
diff_text,
|
|
1859
1936
|
test_command,
|
|
1860
1937
|
env=toolchain_env,
|
|
1938
|
+
verify_cmd=verify_runner,
|
|
1861
1939
|
)
|
|
1862
1940
|
pending.applied = True
|
|
1863
1941
|
if passed:
|
|
@@ -1964,6 +2042,7 @@ def _apply_and_verify(
|
|
|
1964
2042
|
test_command,
|
|
1965
2043
|
*,
|
|
1966
2044
|
env: dict | None = None,
|
|
2045
|
+
verify_cmd: Callable[[str | None], tuple[bool, str]] | None = None,
|
|
1967
2046
|
) -> tuple[bool, str, list[str]]:
|
|
1968
2047
|
"""Apply the diff (with backup), run the test; revert on red.
|
|
1969
2048
|
|
|
@@ -1971,6 +2050,10 @@ def _apply_and_verify(
|
|
|
1971
2050
|
from the diff BEFORE applying (the tree is mutated in place afterward, so it
|
|
1972
2051
|
cannot be recomputed against the modified files). ``env`` optionally supplies
|
|
1973
2052
|
the managed-toolchain environment used to run the test.
|
|
2053
|
+
|
|
2054
|
+
``verify_cmd`` (docs/46) optionally overrides host execution: for
|
|
2055
|
+
``local_byok`` / ``local_managed`` it runs the test inside the project
|
|
2056
|
+
sandbox container so verification happens in the developer's environment.
|
|
1974
2057
|
"""
|
|
1975
2058
|
if not diff_text:
|
|
1976
2059
|
return False, "empty diff", []
|
|
@@ -1987,7 +2070,10 @@ def _apply_and_verify(
|
|
|
1987
2070
|
apply_changes(execution_root, verify_backup_dir, changes)
|
|
1988
2071
|
except Exception as exc:
|
|
1989
2072
|
return False, f"apply failed: {exc}", changed_files
|
|
1990
|
-
|
|
2073
|
+
if verify_cmd is not None:
|
|
2074
|
+
passed, detail = verify_cmd(test_command)
|
|
2075
|
+
else:
|
|
2076
|
+
passed, detail = _run_test(execution_root, test_command, env=env)
|
|
1991
2077
|
if not passed:
|
|
1992
2078
|
try:
|
|
1993
2079
|
revert_from_backup(execution_root, verify_backup_dir)
|