continuous-refactoring 0.1.0__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.
Files changed (67) hide show
  1. continuous_refactoring-0.1.0/.gitignore +17 -0
  2. continuous_refactoring-0.1.0/LICENSE +21 -0
  3. continuous_refactoring-0.1.0/PKG-INFO +272 -0
  4. continuous_refactoring-0.1.0/README.md +249 -0
  5. continuous_refactoring-0.1.0/pyproject.toml +66 -0
  6. continuous_refactoring-0.1.0/src/continuous_refactoring/__init__.py +74 -0
  7. continuous_refactoring-0.1.0/src/continuous_refactoring/__main__.py +8 -0
  8. continuous_refactoring-0.1.0/src/continuous_refactoring/agent.py +733 -0
  9. continuous_refactoring-0.1.0/src/continuous_refactoring/artifacts.py +431 -0
  10. continuous_refactoring-0.1.0/src/continuous_refactoring/cli.py +687 -0
  11. continuous_refactoring-0.1.0/src/continuous_refactoring/commit_messages.py +68 -0
  12. continuous_refactoring-0.1.0/src/continuous_refactoring/config.py +377 -0
  13. continuous_refactoring-0.1.0/src/continuous_refactoring/decisions.py +197 -0
  14. continuous_refactoring-0.1.0/src/continuous_refactoring/effort.py +159 -0
  15. continuous_refactoring-0.1.0/src/continuous_refactoring/failure_report.py +329 -0
  16. continuous_refactoring-0.1.0/src/continuous_refactoring/git.py +134 -0
  17. continuous_refactoring-0.1.0/src/continuous_refactoring/loop.py +1137 -0
  18. continuous_refactoring-0.1.0/src/continuous_refactoring/migration_manifest_codec.py +190 -0
  19. continuous_refactoring-0.1.0/src/continuous_refactoring/migration_tick.py +468 -0
  20. continuous_refactoring-0.1.0/src/continuous_refactoring/migrations.py +251 -0
  21. continuous_refactoring-0.1.0/src/continuous_refactoring/phases.py +690 -0
  22. continuous_refactoring-0.1.0/src/continuous_refactoring/planning.py +588 -0
  23. continuous_refactoring-0.1.0/src/continuous_refactoring/prompts.py +900 -0
  24. continuous_refactoring-0.1.0/src/continuous_refactoring/refactor_attempts.py +424 -0
  25. continuous_refactoring-0.1.0/src/continuous_refactoring/review_cli.py +136 -0
  26. continuous_refactoring-0.1.0/src/continuous_refactoring/routing.py +133 -0
  27. continuous_refactoring-0.1.0/src/continuous_refactoring/routing_pipeline.py +313 -0
  28. continuous_refactoring-0.1.0/src/continuous_refactoring/scope_candidates.py +421 -0
  29. continuous_refactoring-0.1.0/src/continuous_refactoring/scope_expansion.py +219 -0
  30. continuous_refactoring-0.1.0/src/continuous_refactoring/targeting.py +274 -0
  31. continuous_refactoring-0.1.0/tests/conftest.py +523 -0
  32. continuous_refactoring-0.1.0/tests/fixtures/claude_stream_json/selection.stdout.log +15 -0
  33. continuous_refactoring-0.1.0/tests/test_claude_stream_json.py +300 -0
  34. continuous_refactoring-0.1.0/tests/test_cli_init_taste.py +288 -0
  35. continuous_refactoring-0.1.0/tests/test_cli_review.py +539 -0
  36. continuous_refactoring-0.1.0/tests/test_cli_taste_warning.py +230 -0
  37. continuous_refactoring-0.1.0/tests/test_cli_upgrade.py +158 -0
  38. continuous_refactoring-0.1.0/tests/test_commit_messages.py +60 -0
  39. continuous_refactoring-0.1.0/tests/test_config.py +774 -0
  40. continuous_refactoring-0.1.0/tests/test_continuous_refactoring.py +1180 -0
  41. continuous_refactoring-0.1.0/tests/test_decisions.py +222 -0
  42. continuous_refactoring-0.1.0/tests/test_e2e.py +224 -0
  43. continuous_refactoring-0.1.0/tests/test_effort.py +54 -0
  44. continuous_refactoring-0.1.0/tests/test_failure_report.py +266 -0
  45. continuous_refactoring-0.1.0/tests/test_focus_on_live_migrations.py +598 -0
  46. continuous_refactoring-0.1.0/tests/test_git.py +116 -0
  47. continuous_refactoring-0.1.0/tests/test_loop_migration_tick.py +1286 -0
  48. continuous_refactoring-0.1.0/tests/test_main_entrypoint.py +23 -0
  49. continuous_refactoring-0.1.0/tests/test_migrations.py +1003 -0
  50. continuous_refactoring-0.1.0/tests/test_no_driver_branching.py +303 -0
  51. continuous_refactoring-0.1.0/tests/test_phases.py +1290 -0
  52. continuous_refactoring-0.1.0/tests/test_planning.py +579 -0
  53. continuous_refactoring-0.1.0/tests/test_prompts.py +621 -0
  54. continuous_refactoring-0.1.0/tests/test_prompts_scope_selection.py +153 -0
  55. continuous_refactoring-0.1.0/tests/test_routing.py +256 -0
  56. continuous_refactoring-0.1.0/tests/test_run.py +2666 -0
  57. continuous_refactoring-0.1.0/tests/test_run_once.py +512 -0
  58. continuous_refactoring-0.1.0/tests/test_run_once_regression.py +313 -0
  59. continuous_refactoring-0.1.0/tests/test_scope_candidates.py +193 -0
  60. continuous_refactoring-0.1.0/tests/test_scope_expansion.py +252 -0
  61. continuous_refactoring-0.1.0/tests/test_scope_loop_integration.py +257 -0
  62. continuous_refactoring-0.1.0/tests/test_scope_selection.py +48 -0
  63. continuous_refactoring-0.1.0/tests/test_targeting.py +685 -0
  64. continuous_refactoring-0.1.0/tests/test_taste_interview.py +285 -0
  65. continuous_refactoring-0.1.0/tests/test_taste_refine.py +171 -0
  66. continuous_refactoring-0.1.0/tests/test_taste_upgrade.py +207 -0
  67. continuous_refactoring-0.1.0/tests/test_wake_up.py +114 -0
@@ -0,0 +1,17 @@
1
+ .scratchpad/
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # Default venv for uv
9
+ .venv/
10
+
11
+ # Build artifacts
12
+ dist/
13
+ build/
14
+ *.egg-info/
15
+
16
+ # C extensions
17
+ *.so
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hiren Hiranandani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,272 @@
1
+ Metadata-Version: 2.4
2
+ Name: continuous-refactoring
3
+ Version: 0.1.0
4
+ Summary: Continuous refactoring loop for AI coding agents
5
+ Project-URL: Repository, https://github.com/bigH/continuous-refactoring
6
+ Project-URL: Issues, https://github.com/bigH/continuous-refactoring/issues
7
+ Project-URL: Changelog, https://github.com/bigH/continuous-refactoring/releases
8
+ Author: Hiren Hiranandani
9
+ Maintainer: Hiren Hiranandani
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,automation,claude,codex,refactoring
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Topic :: Software Development
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+
24
+ # continuous-refactoring
25
+
26
+ Small, test-gated cleanup commits by an AI coding agent.
27
+
28
+ Think of it as a supervised janitor loop: the agent proposes a cleanup, your tests decide if it stays.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ uv tool install continuous-refactoring
34
+ ```
35
+
36
+ For a checkout:
37
+
38
+ ```bash
39
+ uv sync
40
+ uv pip install -e .
41
+ ```
42
+
43
+ That gives you the `continuous-refactoring` command.
44
+
45
+ Maintainers: see the [release checklist](https://github.com/bigH/continuous-refactoring/blob/main/docs/release.md).
46
+
47
+ ## Fastest way to get one refactor
48
+
49
+ Once installed:
50
+
51
+ ```bash
52
+ continuous-refactoring init
53
+ continuous-refactoring run-once \
54
+ --with codex --model gpt-5 \
55
+ --extensions .py
56
+ ```
57
+
58
+ That gives you one pass on the current branch. If validation passes, it leaves you with a local commit to inspect.
59
+
60
+ ## Got tokens to burn?
61
+
62
+ ```bash
63
+ continuous-refactoring run \
64
+ --with codex --model gpt-5 --default-effort high \
65
+ --extensions .py \
66
+ --max-refactors 10 \
67
+ --max-attempts 2
68
+ ```
69
+
70
+ That keeps sweeping targets until it runs out, hits your caps, or starts failing.
71
+
72
+ ## What it does
73
+
74
+ - Resolves a target from `--targets`, `--globs`, `--extensions`, or `--paths`, with optional natural-language scoping via `--scope-instruction`.
75
+ - Runs the agent with a refactoring prompt + your "taste" guidelines.
76
+ - Runs your validation command (default: `uv run pytest`).
77
+ - If green and there's a diff, it commits locally and leaves the branch for you to inspect.
78
+ - Repeats until it runs out of targets, hits the retry budget, or stacks too many failures.
79
+
80
+ ## Requirements
81
+
82
+ - Python 3.10+
83
+ - [uv](https://github.com/astral-sh/uv)
84
+ - `codex` or `claude` CLI on your `PATH` (whichever backend you pick)
85
+ - A git repo with a clean worktree
86
+
87
+ ## Quickstart
88
+
89
+ ```bash
90
+ # 1. Register the repo (creates a project dir under ~/.local/share/continuous-refactoring)
91
+ continuous-refactoring init
92
+
93
+ # 2. (Optional) Write your refactoring taste — either edit the file, have an agent interview you,
94
+ # or refine an existing draft collaboratively
95
+ continuous-refactoring taste --interview --with codex --model gpt-5 --effort high
96
+ continuous-refactoring taste --refine --with codex --model gpt-5 --effort high
97
+
98
+ # 3. Do one pass
99
+ continuous-refactoring run-once \
100
+ --with codex --model gpt-5 \
101
+ --extensions .py
102
+
103
+ # 4. Or run the loop over a batch of targets
104
+ continuous-refactoring run \
105
+ --with claude --model claude-opus-4-6 --default-effort high \
106
+ --globs 'src/**/*.py' \
107
+ --max-refactors 10 \
108
+ --max-attempts 2 \
109
+ --sleep 5
110
+ ```
111
+
112
+ ## Subcommands
113
+
114
+ | Command | What it does |
115
+ |---|---|
116
+ | `init` | Registers this directory as a project, creates a default `taste.md`, and can store `--live-migrations-dir`. |
117
+ | `taste` | Prints the active taste file path. Add `--interview` to have an agent author it, `--refine` to iteratively improve an existing taste doc, `--upgrade` to refresh stale taste dimensions, `--global` for the shared file, and `--force` to let `--interview` overwrite custom content after writing a `.bak`. |
118
+ | `run-once` | Single pass on one resolved target. No retry. If there is a diff and validation passes, it commits locally and prints the diffstat. |
119
+ | `run` | The loop. Iterates targets, retries on failure, and commits successful targets locally. |
120
+ | `upgrade` | Checks that the global config manifest is current, rewrites it idempotently, and warns if the global taste file is stale. |
121
+ | `review list` | Lists migrations flagged for human review (`awaiting_human_review`). |
122
+ | `review perform <migration>` | Starts an interactive agent session to resolve a flagged migration's review. Requires `--with`, `--model`, and `--effort`. |
123
+
124
+ ## Targeting / Useful flags
125
+
126
+ ### Target selection
127
+
128
+ Target resolution is first-match-wins:
129
+ `--targets` > `--globs` > `--extensions` > `--paths`
130
+
131
+ These flags are not mutually exclusive, but only the highest-priority populated source is used.
132
+
133
+ - `--targets path/to/targets.jsonl` — explicit list; one JSON object per line with `description`, `files`, optional `scoping`, `model-override`, `effort-override`. Effort overrides use `low`, `medium`, `high`, or `xhigh`.
134
+ - `--globs 'src/**/*.py:tests/**/*.py'` — colon-separated globs; each matched file becomes its own target.
135
+ - `--extensions .py,.ts` — shorthand that expands to `**/*.py`, `**/*.ts`; each matched file becomes its own target.
136
+ - `--paths a.py:b.py` — literal paths, all treated as one target.
137
+ - `--scope-instruction "clean up the auth module"` — extra free-text scoping. If file-based targeting resolves nothing, this becomes the useful fallback context.
138
+
139
+ If you provide none of `--targets`, `--globs`, `--extensions`, or `--paths`, then `run` and `run-once` require `--scope-instruction`.
140
+
141
+ ### Migrations & taste flags
142
+
143
+ - `init --live-migrations-dir PATH` — enables the larger-refactoring workflow for this project. The path is stored repo-relative in the project registry and created if missing.
144
+ - `taste --refine` — opens a collaborative editing session for the taste file. The agent keeps refining until you tell it to write, then the session ends automatically after the settled write.
145
+ - `taste --upgrade` — re-interviews for taste dimensions added since your last version. No-op when already current; use `taste --refine` if you want to rework the doc anyway.
146
+ - `taste --force` — only applies to `--interview`; it allows a customized taste file to be overwritten after backing it up to `taste.md.bak`.
147
+
148
+ ### Shared `run` / `run-once` flags
149
+
150
+ - `--with`, `--model` — required agent backend/model selection.
151
+ - `--default-effort` — default effort for run calls. Defaults to `low`. Valid labels are `low`, `medium`, `high`, `xhigh`.
152
+ - `--max-allowed-effort` — cap for target overrides and migration escalation. Defaults to `xhigh`.
153
+ - `--repo-root PATH` — repository root; defaults to the current directory.
154
+ - `--validation-command` — defaults to `uv run pytest`. Swap it for whatever keeps your repo honest.
155
+ - `--timeout` — per-agent-call timeout in seconds.
156
+ - `--show-agent-logs` / `--show-command-logs` — mirror output to your terminal instead of just logging.
157
+ - `--refactoring-prompt` — override the default refactoring prompt.
158
+ - `--fix-prompt` — override the retry amendment prompt. Useful for `run`; accepted by `run-once` for flag symmetry.
159
+
160
+ ### `run`-only flags
161
+
162
+ - `--max-attempts N` — per-target retry budget. `1` = no retry, `0` = unlimited (which means permanently broken targets will never give up).
163
+ - `--max-refactors N` — cap the number of targets per run. Required unless you use `--targets`.
164
+ - `--max-consecutive-failures N` — bail after N targets fail in a row. Default 3.
165
+ - `--sleep SECONDS` — pause between completed targets. Useful when you want a long batch without hammering the repo or your agent budget.
166
+ - `--commit-message-prefix TEXT` — subject prefix for successful refactor or migration-plan commits. Default `continuous refactor`.
167
+
168
+ ## Safety behaviors
169
+
170
+ - Refuses to start with a dirty worktree.
171
+ - Runs on the current branch. Commits land there.
172
+ - Successful commits include a `Why:` body section from the agent's reported rationale, plus validation context when available.
173
+ - `run-once`, `run`, and focused live-migration runs baseline your validation command before touching anything. If the baseline is already red, they stop.
174
+ - On a failed attempt, resets back to the pre-attempt HEAD and cleans workspace changes before retrying or moving on.
175
+ - Watchdog kills any agent or test process that's been silent for 5 minutes.
176
+
177
+ ## Where the artifacts live
178
+
179
+ Each run writes to `$TMPDIR/continuous-refactoring/<run-id>/`:
180
+
181
+ - `summary.json` — rolling status, counts, per-attempt stats
182
+ - `events.jsonl` — structured event log
183
+ - `run.log` — human-readable log
184
+ - `attempt-NNN/[retry-NN/]refactor/` — per-attempt agent + test stdout/stderr
185
+
186
+ Mixed-effort runs are auditable: summaries and call events record the default effort, max allowed effort, requested effort, effective effort, source, and whether the request was capped.
187
+
188
+ The path prints at startup. Grep it when something goes sideways.
189
+
190
+ ## Taste files
191
+
192
+ The taste file is a short bullet list of your refactoring preferences. It gets injected into every agent prompt.
193
+
194
+ - Project taste: `~/.local/share/continuous-refactoring/projects/<uuid>/taste.md`
195
+ - Global taste: `~/.local/share/continuous-refactoring/global/taste.md`
196
+
197
+ Project taste wins over global. Use `taste --interview` to bootstrap one, `taste --refine` to rework it with an agent, or edit the file directly any time.
198
+
199
+ ## Larger refactorings
200
+
201
+ When a cleanup is too big for a single commit — needs a plan, touches many files, or should ship in stages — use the migrations model.
202
+
203
+ ### Enabling it
204
+
205
+ ```bash
206
+ continuous-refactoring init --live-migrations-dir migrations/
207
+ ```
208
+
209
+ This tells the CLI where to store migration artifacts. The path is repo-relative, stored in the XDG project registry (no project config file is created). When this directory is unset, the one-shot cleanup path remains byte-identical to the default behavior.
210
+
211
+ ### How it works
212
+
213
+ Each `run` / `run-once` tick now checks for eligible migration work before falling back to single-commit cleanups:
214
+
215
+ 1. **Classify** — a classifier agent reads the target and decides: `cohesive-cleanup` (one-shot path) or `needs-plan` (migration path).
216
+ 2. **Plan** — for `needs-plan` targets, a six-stage planning workflow runs: generate approaches → pick best → expand into phases → review → revise → final review. Artifacts land under `<live-migrations-dir>/<migration-name>/`.
217
+ 3. **Execute** — each phase is a self-contained unit of work. The tick picks the oldest eligible migration, checks whether its current phase precondition is satisfied, and executes it on the current branch. Phase completion is judged against the phase file's `## Definition of Done`; commit message identifies the migration as `migration/<name>/<phase-file>.md`.
218
+
219
+ ### Migration directory layout
220
+
221
+ ```
222
+ <live-migrations-dir>/
223
+ <migration-name>/
224
+ manifest.json # status, phases, wake-up schedule
225
+ plan.md # the expanded plan
226
+ approaches/ # candidate approaches considered during planning
227
+ phase-1-<name>.md # per-phase specification
228
+ phase-2-<name>.md
229
+ ...
230
+ __intentional_skips__/ # migrations rejected at final review
231
+ ```
232
+
233
+ ### Wake-up rules
234
+
235
+ Migrations don't run on every tick. The scheduler now separates **activity** from
236
+ **retry cooldown**:
237
+
238
+ - `last_touch` records the latest migration activity.
239
+ - `cooldown_until` gates repeated checks only after the migration was deferred or
240
+ blocked.
241
+
242
+ A migration is eligible when **all** of:
243
+
244
+ - Any `cooldown_until` has elapsed.
245
+ - Either `wake_up_on` is unset, `wake_up_on` has elapsed, or the migration has
246
+ been stale for ≥7 days.
247
+
248
+ That means successful phase execution does **not** make the next phase wait 6
249
+ hours. Phases whose preconditions are already satisfied can advance back-to-back
250
+ in the same run until the migration is actually blocked. The 6-hour cooldown
251
+ still applies after `ready: no`, future wake-ups, unverifiable phases, or
252
+ similar deferrals so the loop does not hammer stuck migrations.
253
+
254
+ ### Phase model
255
+
256
+ Each migration moves through phases sequentially.
257
+
258
+ - The manifest stores each phase's **precondition** — what must already be true before execution may start.
259
+ - Each phase markdown file stores its **Definition of Done** under `## Definition of Done` — what must be true for that phase to count as completed.
260
+ - A phase may declare optional `required_effort` and `effort_reason` in the manifest. The driver escalates up to `--max-allowed-effort`; if a phase needs more, the phase is deferred without failing the run and can be picked up by a later higher-budget run.
261
+
262
+ Before executing a phase, a ready-check agent verifies that the current phase precondition is met. Phase preconditions are for phase-local facts only; the harness owns baseline-green validation before work and full validation after phase execution. Possible outcomes:
263
+
264
+ - **ready: yes** — phase executes; on green tests, the phase is marked done, any prior deferral markers are cleared, and the migration advances immediately to the next phase.
265
+ - **ready: no** — manifest activity is bumped, a retry cooldown is started, and a future `wake_up_on` is recorded when needed; the tick moves on.
266
+ - **ready: unverifiable** — the migration is flagged `awaiting_human_review` and put on cooldown. Automated migration ticks skip flagged migrations until review clears the flag. Use `review list` to find it and `review perform <migration> --with ... --model ... --effort ...` to resolve it interactively.
267
+
268
+ Human-facing migration references use the relative phase spec path, for example `phase-2-failure-report.md`. The manifest cursor stores the phase `name`, not a numeric index.
269
+
270
+ ### What the CLI doesn't do
271
+
272
+ Rollout mechanics — feature flag names, deploy tooling, metric dashboards, canary analysis — are the coding agent's responsibility, not a CLI-visible concern. The CLI manages the planning and phased execution workflow; the agent writes whatever rollout code the plan calls for.
@@ -0,0 +1,249 @@
1
+ # continuous-refactoring
2
+
3
+ Small, test-gated cleanup commits by an AI coding agent.
4
+
5
+ Think of it as a supervised janitor loop: the agent proposes a cleanup, your tests decide if it stays.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ uv tool install continuous-refactoring
11
+ ```
12
+
13
+ For a checkout:
14
+
15
+ ```bash
16
+ uv sync
17
+ uv pip install -e .
18
+ ```
19
+
20
+ That gives you the `continuous-refactoring` command.
21
+
22
+ Maintainers: see the [release checklist](https://github.com/bigH/continuous-refactoring/blob/main/docs/release.md).
23
+
24
+ ## Fastest way to get one refactor
25
+
26
+ Once installed:
27
+
28
+ ```bash
29
+ continuous-refactoring init
30
+ continuous-refactoring run-once \
31
+ --with codex --model gpt-5 \
32
+ --extensions .py
33
+ ```
34
+
35
+ That gives you one pass on the current branch. If validation passes, it leaves you with a local commit to inspect.
36
+
37
+ ## Got tokens to burn?
38
+
39
+ ```bash
40
+ continuous-refactoring run \
41
+ --with codex --model gpt-5 --default-effort high \
42
+ --extensions .py \
43
+ --max-refactors 10 \
44
+ --max-attempts 2
45
+ ```
46
+
47
+ That keeps sweeping targets until it runs out, hits your caps, or starts failing.
48
+
49
+ ## What it does
50
+
51
+ - Resolves a target from `--targets`, `--globs`, `--extensions`, or `--paths`, with optional natural-language scoping via `--scope-instruction`.
52
+ - Runs the agent with a refactoring prompt + your "taste" guidelines.
53
+ - Runs your validation command (default: `uv run pytest`).
54
+ - If green and there's a diff, it commits locally and leaves the branch for you to inspect.
55
+ - Repeats until it runs out of targets, hits the retry budget, or stacks too many failures.
56
+
57
+ ## Requirements
58
+
59
+ - Python 3.10+
60
+ - [uv](https://github.com/astral-sh/uv)
61
+ - `codex` or `claude` CLI on your `PATH` (whichever backend you pick)
62
+ - A git repo with a clean worktree
63
+
64
+ ## Quickstart
65
+
66
+ ```bash
67
+ # 1. Register the repo (creates a project dir under ~/.local/share/continuous-refactoring)
68
+ continuous-refactoring init
69
+
70
+ # 2. (Optional) Write your refactoring taste — either edit the file, have an agent interview you,
71
+ # or refine an existing draft collaboratively
72
+ continuous-refactoring taste --interview --with codex --model gpt-5 --effort high
73
+ continuous-refactoring taste --refine --with codex --model gpt-5 --effort high
74
+
75
+ # 3. Do one pass
76
+ continuous-refactoring run-once \
77
+ --with codex --model gpt-5 \
78
+ --extensions .py
79
+
80
+ # 4. Or run the loop over a batch of targets
81
+ continuous-refactoring run \
82
+ --with claude --model claude-opus-4-6 --default-effort high \
83
+ --globs 'src/**/*.py' \
84
+ --max-refactors 10 \
85
+ --max-attempts 2 \
86
+ --sleep 5
87
+ ```
88
+
89
+ ## Subcommands
90
+
91
+ | Command | What it does |
92
+ |---|---|
93
+ | `init` | Registers this directory as a project, creates a default `taste.md`, and can store `--live-migrations-dir`. |
94
+ | `taste` | Prints the active taste file path. Add `--interview` to have an agent author it, `--refine` to iteratively improve an existing taste doc, `--upgrade` to refresh stale taste dimensions, `--global` for the shared file, and `--force` to let `--interview` overwrite custom content after writing a `.bak`. |
95
+ | `run-once` | Single pass on one resolved target. No retry. If there is a diff and validation passes, it commits locally and prints the diffstat. |
96
+ | `run` | The loop. Iterates targets, retries on failure, and commits successful targets locally. |
97
+ | `upgrade` | Checks that the global config manifest is current, rewrites it idempotently, and warns if the global taste file is stale. |
98
+ | `review list` | Lists migrations flagged for human review (`awaiting_human_review`). |
99
+ | `review perform <migration>` | Starts an interactive agent session to resolve a flagged migration's review. Requires `--with`, `--model`, and `--effort`. |
100
+
101
+ ## Targeting / Useful flags
102
+
103
+ ### Target selection
104
+
105
+ Target resolution is first-match-wins:
106
+ `--targets` > `--globs` > `--extensions` > `--paths`
107
+
108
+ These flags are not mutually exclusive, but only the highest-priority populated source is used.
109
+
110
+ - `--targets path/to/targets.jsonl` — explicit list; one JSON object per line with `description`, `files`, optional `scoping`, `model-override`, `effort-override`. Effort overrides use `low`, `medium`, `high`, or `xhigh`.
111
+ - `--globs 'src/**/*.py:tests/**/*.py'` — colon-separated globs; each matched file becomes its own target.
112
+ - `--extensions .py,.ts` — shorthand that expands to `**/*.py`, `**/*.ts`; each matched file becomes its own target.
113
+ - `--paths a.py:b.py` — literal paths, all treated as one target.
114
+ - `--scope-instruction "clean up the auth module"` — extra free-text scoping. If file-based targeting resolves nothing, this becomes the useful fallback context.
115
+
116
+ If you provide none of `--targets`, `--globs`, `--extensions`, or `--paths`, then `run` and `run-once` require `--scope-instruction`.
117
+
118
+ ### Migrations & taste flags
119
+
120
+ - `init --live-migrations-dir PATH` — enables the larger-refactoring workflow for this project. The path is stored repo-relative in the project registry and created if missing.
121
+ - `taste --refine` — opens a collaborative editing session for the taste file. The agent keeps refining until you tell it to write, then the session ends automatically after the settled write.
122
+ - `taste --upgrade` — re-interviews for taste dimensions added since your last version. No-op when already current; use `taste --refine` if you want to rework the doc anyway.
123
+ - `taste --force` — only applies to `--interview`; it allows a customized taste file to be overwritten after backing it up to `taste.md.bak`.
124
+
125
+ ### Shared `run` / `run-once` flags
126
+
127
+ - `--with`, `--model` — required agent backend/model selection.
128
+ - `--default-effort` — default effort for run calls. Defaults to `low`. Valid labels are `low`, `medium`, `high`, `xhigh`.
129
+ - `--max-allowed-effort` — cap for target overrides and migration escalation. Defaults to `xhigh`.
130
+ - `--repo-root PATH` — repository root; defaults to the current directory.
131
+ - `--validation-command` — defaults to `uv run pytest`. Swap it for whatever keeps your repo honest.
132
+ - `--timeout` — per-agent-call timeout in seconds.
133
+ - `--show-agent-logs` / `--show-command-logs` — mirror output to your terminal instead of just logging.
134
+ - `--refactoring-prompt` — override the default refactoring prompt.
135
+ - `--fix-prompt` — override the retry amendment prompt. Useful for `run`; accepted by `run-once` for flag symmetry.
136
+
137
+ ### `run`-only flags
138
+
139
+ - `--max-attempts N` — per-target retry budget. `1` = no retry, `0` = unlimited (which means permanently broken targets will never give up).
140
+ - `--max-refactors N` — cap the number of targets per run. Required unless you use `--targets`.
141
+ - `--max-consecutive-failures N` — bail after N targets fail in a row. Default 3.
142
+ - `--sleep SECONDS` — pause between completed targets. Useful when you want a long batch without hammering the repo or your agent budget.
143
+ - `--commit-message-prefix TEXT` — subject prefix for successful refactor or migration-plan commits. Default `continuous refactor`.
144
+
145
+ ## Safety behaviors
146
+
147
+ - Refuses to start with a dirty worktree.
148
+ - Runs on the current branch. Commits land there.
149
+ - Successful commits include a `Why:` body section from the agent's reported rationale, plus validation context when available.
150
+ - `run-once`, `run`, and focused live-migration runs baseline your validation command before touching anything. If the baseline is already red, they stop.
151
+ - On a failed attempt, resets back to the pre-attempt HEAD and cleans workspace changes before retrying or moving on.
152
+ - Watchdog kills any agent or test process that's been silent for 5 minutes.
153
+
154
+ ## Where the artifacts live
155
+
156
+ Each run writes to `$TMPDIR/continuous-refactoring/<run-id>/`:
157
+
158
+ - `summary.json` — rolling status, counts, per-attempt stats
159
+ - `events.jsonl` — structured event log
160
+ - `run.log` — human-readable log
161
+ - `attempt-NNN/[retry-NN/]refactor/` — per-attempt agent + test stdout/stderr
162
+
163
+ Mixed-effort runs are auditable: summaries and call events record the default effort, max allowed effort, requested effort, effective effort, source, and whether the request was capped.
164
+
165
+ The path prints at startup. Grep it when something goes sideways.
166
+
167
+ ## Taste files
168
+
169
+ The taste file is a short bullet list of your refactoring preferences. It gets injected into every agent prompt.
170
+
171
+ - Project taste: `~/.local/share/continuous-refactoring/projects/<uuid>/taste.md`
172
+ - Global taste: `~/.local/share/continuous-refactoring/global/taste.md`
173
+
174
+ Project taste wins over global. Use `taste --interview` to bootstrap one, `taste --refine` to rework it with an agent, or edit the file directly any time.
175
+
176
+ ## Larger refactorings
177
+
178
+ When a cleanup is too big for a single commit — needs a plan, touches many files, or should ship in stages — use the migrations model.
179
+
180
+ ### Enabling it
181
+
182
+ ```bash
183
+ continuous-refactoring init --live-migrations-dir migrations/
184
+ ```
185
+
186
+ This tells the CLI where to store migration artifacts. The path is repo-relative, stored in the XDG project registry (no project config file is created). When this directory is unset, the one-shot cleanup path remains byte-identical to the default behavior.
187
+
188
+ ### How it works
189
+
190
+ Each `run` / `run-once` tick now checks for eligible migration work before falling back to single-commit cleanups:
191
+
192
+ 1. **Classify** — a classifier agent reads the target and decides: `cohesive-cleanup` (one-shot path) or `needs-plan` (migration path).
193
+ 2. **Plan** — for `needs-plan` targets, a six-stage planning workflow runs: generate approaches → pick best → expand into phases → review → revise → final review. Artifacts land under `<live-migrations-dir>/<migration-name>/`.
194
+ 3. **Execute** — each phase is a self-contained unit of work. The tick picks the oldest eligible migration, checks whether its current phase precondition is satisfied, and executes it on the current branch. Phase completion is judged against the phase file's `## Definition of Done`; commit message identifies the migration as `migration/<name>/<phase-file>.md`.
195
+
196
+ ### Migration directory layout
197
+
198
+ ```
199
+ <live-migrations-dir>/
200
+ <migration-name>/
201
+ manifest.json # status, phases, wake-up schedule
202
+ plan.md # the expanded plan
203
+ approaches/ # candidate approaches considered during planning
204
+ phase-1-<name>.md # per-phase specification
205
+ phase-2-<name>.md
206
+ ...
207
+ __intentional_skips__/ # migrations rejected at final review
208
+ ```
209
+
210
+ ### Wake-up rules
211
+
212
+ Migrations don't run on every tick. The scheduler now separates **activity** from
213
+ **retry cooldown**:
214
+
215
+ - `last_touch` records the latest migration activity.
216
+ - `cooldown_until` gates repeated checks only after the migration was deferred or
217
+ blocked.
218
+
219
+ A migration is eligible when **all** of:
220
+
221
+ - Any `cooldown_until` has elapsed.
222
+ - Either `wake_up_on` is unset, `wake_up_on` has elapsed, or the migration has
223
+ been stale for ≥7 days.
224
+
225
+ That means successful phase execution does **not** make the next phase wait 6
226
+ hours. Phases whose preconditions are already satisfied can advance back-to-back
227
+ in the same run until the migration is actually blocked. The 6-hour cooldown
228
+ still applies after `ready: no`, future wake-ups, unverifiable phases, or
229
+ similar deferrals so the loop does not hammer stuck migrations.
230
+
231
+ ### Phase model
232
+
233
+ Each migration moves through phases sequentially.
234
+
235
+ - The manifest stores each phase's **precondition** — what must already be true before execution may start.
236
+ - Each phase markdown file stores its **Definition of Done** under `## Definition of Done` — what must be true for that phase to count as completed.
237
+ - A phase may declare optional `required_effort` and `effort_reason` in the manifest. The driver escalates up to `--max-allowed-effort`; if a phase needs more, the phase is deferred without failing the run and can be picked up by a later higher-budget run.
238
+
239
+ Before executing a phase, a ready-check agent verifies that the current phase precondition is met. Phase preconditions are for phase-local facts only; the harness owns baseline-green validation before work and full validation after phase execution. Possible outcomes:
240
+
241
+ - **ready: yes** — phase executes; on green tests, the phase is marked done, any prior deferral markers are cleared, and the migration advances immediately to the next phase.
242
+ - **ready: no** — manifest activity is bumped, a retry cooldown is started, and a future `wake_up_on` is recorded when needed; the tick moves on.
243
+ - **ready: unverifiable** — the migration is flagged `awaiting_human_review` and put on cooldown. Automated migration ticks skip flagged migrations until review clears the flag. Use `review list` to find it and `review perform <migration> --with ... --model ... --effort ...` to resolve it interactively.
244
+
245
+ Human-facing migration references use the relative phase spec path, for example `phase-2-failure-report.md`. The manifest cursor stores the phase `name`, not a numeric index.
246
+
247
+ ### What the CLI doesn't do
248
+
249
+ Rollout mechanics — feature flag names, deploy tooling, metric dashboards, canary analysis — are the coding agent's responsibility, not a CLI-visible concern. The CLI manages the planning and phased execution workflow; the agent writes whatever rollout code the plan calls for.
@@ -0,0 +1,66 @@
1
+ [project]
2
+ name = "continuous-refactoring"
3
+ version = "0.1.0"
4
+ description = "Continuous refactoring loop for AI coding agents"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = "MIT"
8
+ license-files = ["LICENSE*"]
9
+ authors = [{ name = "Hiren Hiranandani" }]
10
+ maintainers = [{ name = "Hiren Hiranandani" }]
11
+ keywords = ["ai", "refactoring", "codex", "claude", "automation"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Environment :: Console",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Topic :: Software Development",
20
+ "Topic :: Software Development :: Quality Assurance",
21
+ ]
22
+ dependencies = []
23
+
24
+ [project.urls]
25
+ Repository = "https://github.com/bigH/continuous-refactoring"
26
+ Issues = "https://github.com/bigH/continuous-refactoring/issues"
27
+ Changelog = "https://github.com/bigH/continuous-refactoring/releases"
28
+
29
+ [project.scripts]
30
+ continuous-refactoring = "continuous_refactoring:cli_main"
31
+
32
+ [build-system]
33
+ requires = ["hatchling >= 1.27"]
34
+ build-backend = "hatchling.build"
35
+
36
+ [tool.hatch.build.targets.wheel]
37
+ packages = ["src/continuous_refactoring"]
38
+
39
+ [tool.hatch.build.targets.sdist]
40
+ include = [
41
+ "/pyproject.toml",
42
+ "/README.md",
43
+ "/LICENSE*",
44
+ "/src/continuous_refactoring/**",
45
+ "/tests/**",
46
+ ]
47
+ exclude = [
48
+ "/.hiren",
49
+ "/.scratchpad",
50
+ "/.pytest_cache",
51
+ "/.venv",
52
+ "/dist",
53
+ "/build",
54
+ "/approaches",
55
+ "/migrations",
56
+ "/AGENTS.md",
57
+ "/CLAUDE.md",
58
+ "/.python-version",
59
+ "/uv.lock",
60
+ ]
61
+
62
+ [tool.pytest.ini_options]
63
+ testpaths = ["tests"]
64
+
65
+ [dependency-groups]
66
+ dev = ["pytest>=8.0"]