Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
f3879a5
remove completed migrations
bigH Apr 29, 2026
267f777
continuous refactor: src/continuous_refactoring/scope_expansion.py
bigH Apr 29, 2026
160cc52
continuous refactor: tests/test_scope_selection.py
bigH Apr 29, 2026
ad11bff
continuous refactor: src/continuous_refactoring/planning.py
bigH Apr 29, 2026
0f78543
continuous refactor: src/continuous_refactoring/refactor_attempts.py
bigH Apr 29, 2026
e55ee15
continuous refactor: tests/test_no_driver_branching.py
bigH Apr 29, 2026
13443a1
continuous refactor: tests/test_effort.py
bigH Apr 29, 2026
0b9eaa7
continuous refactor: src/continuous_refactoring/migration_tick.py
bigH Apr 29, 2026
bbab5bc
continuous refactor: tests/test_cli_init_taste.py
bigH Apr 29, 2026
28cc67b
continuous refactor: tests/test_scope_candidates.py
bigH Apr 29, 2026
d9dd3cb
continuous refactor: src/continuous_refactoring/decisions.py
bigH Apr 29, 2026
ef84cc5
continuous refactor: src/continuous_refactoring/scope_candidates.py
bigH Apr 29, 2026
d4964cb
continuous refactor: tests/test_cli_version.py
bigH Apr 29, 2026
0a089f1
continuous refactor: tests/test_cli_upgrade.py
bigH Apr 29, 2026
780d22c
continuous refactor: src/continuous_refactoring/failure_report.py
bigH Apr 29, 2026
c79414a
continuous refactor: src/continuous_refactoring/routing_pipeline.py
bigH Apr 29, 2026
e10192e
continuous refactor: tests/test_loop_migration_tick.py
bigH Apr 29, 2026
b498e66
continuous refactor: tests/test_decisions.py
bigH Apr 29, 2026
f48ed63
continuous refactor: tests/test_focus_on_live_migrations.py
bigH Apr 29, 2026
b48c03d
continuous refactor: tests/test_taste_interview.py
bigH Apr 29, 2026
a17bdfb
continuous refactor: tests/test_git.py
bigH Apr 29, 2026
db88b62
continuous refactor: tests/test_run.py
bigH Apr 29, 2026
008550c
continuous refactor: src/continuous_refactoring/targeting.py
bigH Apr 29, 2026
b821b80
continuous refactor: tests/test_run_once.py
bigH Apr 29, 2026
1df1602
continuous refactor: tests/test_cli_taste_warning.py
bigH Apr 29, 2026
a66e13c
continuous refactor: tests/test_targeting.py
bigH Apr 29, 2026
0615c1d
continuous refactor: tests/test_routing.py
bigH Apr 29, 2026
d20b9a2
partially planned migrations
bigH Apr 29, 2026
1590ee8
remove approaches dir added by an earlier bug (I'm guessing)
bigH Apr 29, 2026
7776f93
working plan for migration resumption
bigH Apr 30, 2026
3226f55
final polish of progress resumption
bigH May 1, 2026
8b3e1dc
final final improvements
bigH May 1, 2026
e7f5646
remove plans
bigH May 1, 2026
aaeb3b8
plug the article
bigH May 1, 2026
8c5eae4
continuous refactor: planning/src-continuous-refactoring-migrations-p…
bigH May 2, 2026
8d78a8d
continuous refactor: planning/src-continuous-refactoring-migrations-p…
bigH May 2, 2026
7b78ece
rotate through migrations if failures occur
bigH May 3, 2026
2ab0f60
fix up migrations
bigH May 4, 2026
84c0a1a
continuous refactor: planning/src-continuous-refactoring-git-py-20260…
bigH May 4, 2026
68e71d0
continuous refactor: planning/src-continuous-refactoring-git-py-20260…
bigH May 4, 2026
6068d06
continuous refactor: migrations
bigH May 7, 2026
96ffad0
continuous refactor: planning failure evidence
bigH May 7, 2026
cbd3144
remove trash migrations
bigH May 7, 2026
297bf6f
continuous refactor: tests/test_config.py
bigH May 7, 2026
1d0d30d
continuous refactor: tests/test_taste_interview.py
bigH May 7, 2026
42a96bc
continuous refactor: src/continuous_refactoring/scope_candidates.py
bigH May 7, 2026
016c313
continuous refactor: plan src-continuous-refactoring-commit-messag-20…
bigH May 7, 2026
4720796
continuous refactor: planning/src-continuous-refactoring-commit-messa…
bigH May 7, 2026
fd66e7e
continuous refactor: planning/src-continuous-refactoring-commit-messa…
bigH May 7, 2026
ff0be0e
continuous refactor: planning/src-continuous-refactoring-commit-messa…
bigH May 7, 2026
20a02d7
continuous refactor: planning/src-continuous-refactoring-commit-messa…
bigH May 7, 2026
2a44ae8
trash migrations
bigH May 7, 2026
c3e2382
continuous refactor: src/continuous_refactoring/scope_expansion.py
bigH May 7, 2026
adf516e
continuous refactor: tests/test_failure_report.py
bigH May 7, 2026
e57d3bf
continuous refactor: src/continuous_refactoring/migration_tick.py
bigH May 7, 2026
b15432d
continuous refactor: plan src-continuous-refactoring-migration-con-20…
bigH May 7, 2026
19ee577
continuous refactor: planning/src-continuous-refactoring-migration-co…
bigH May 7, 2026
db32953
continuous refactor: planning/src-continuous-refactoring-migration-co…
bigH May 7, 2026
a9e1bf7
continuous refactor: planning/src-continuous-refactoring-migration-co…
bigH May 7, 2026
563956b
continuous refactor: planning/src-continuous-refactoring-migration-co…
bigH May 7, 2026
a579b38
continuous refactor: planning/src-continuous-refactoring-migration-co…
bigH May 7, 2026
0bbf40b
continuous refactor: planning/src-continuous-refactoring-migration-co…
bigH May 7, 2026
d1ad940
continuous refactor: migration/src-continuous-refactoring-migration-c…
bigH May 7, 2026
6f4f07a
continuous refactor: migration/src-continuous-refactoring-migration-c…
bigH May 7, 2026
04237ec
update docs
bigH May 7, 2026
75f3a45
proper log mirroring
bigH May 7, 2026
5af6cbb
continuous refactor: migration/src-continuous-refactoring-migration-c…
bigH May 12, 2026
beefbf2
continuous refactor: migration/src-continuous-refactoring-migration-c…
bigH May 12, 2026
3c9d9a2
completed migrations
bigH May 12, 2026
ae76e70
continuous refactor: random files
bigH May 12, 2026
508e0a2
continuous refactor: plan random-files-20260512T161021
bigH May 12, 2026
8107b88
better targeting
bigH May 14, 2026
2568cd4
continuous refactor: planning/random-files-20260512T161021/pick-best
bigH May 14, 2026
2953858
continuous refactor: planning/random-files-20260512T161021/expand
bigH May 14, 2026
bab7881
continuous refactor: planning/random-files-20260512T161021/review
bigH May 14, 2026
ce3c1cd
continuous refactor: planning/random-files-20260512T161021/final-review
bigH May 14, 2026
0b17221
continuous refactor: plan random-files-20260513T231424
bigH May 14, 2026
f87d776
remove weird migration
bigH May 14, 2026
08ee364
seemingly bad test...
bigH May 14, 2026
06b1581
continuous refactor: plan random-files-20260514T002058
bigH May 14, 2026
ebee450
continuous refactor: planning/random-files-20260514T002058/pick-best
bigH May 14, 2026
2e6262e
continuous refactor: planning/random-files-20260514T002058/expand
bigH May 14, 2026
fc6f04f
continuous refactor: planning/random-files-20260514T002058/review
bigH May 14, 2026
d665c1a
continuous refactor: planning/random-files-20260514T002058/revise
bigH May 14, 2026
eb92c32
continuous refactor: planning/random-files-20260514T002058/review-2
bigH May 14, 2026
3b4b9b1
continuous refactor: planning/random-files-20260514T002058/final-review
bigH May 14, 2026
6334404
continuous refactor: plan random-files-20260514T002712
bigH May 14, 2026
239a300
continuous refactor: planning/random-files-20260514T002712/pick-best
bigH May 14, 2026
2a80988
continuous refactor: planning/random-files-20260514T002712/expand
bigH May 14, 2026
c78f5e3
continuous refactor: planning/random-files-20260514T002712/review
bigH May 14, 2026
54a355b
continuous refactor: planning/random-files-20260514T002712/revise
bigH May 14, 2026
ca9c929
continuous refactor: planning/random-files-20260514T002712/review-2
bigH May 17, 2026
92bd7cd
continuous refactor: planning/random-files-20260514T002712/final-review
bigH May 17, 2026
0c9b977
continuous refactor: migration/random-files-20260514T002712/phase-1-b…
bigH May 17, 2026
d86138b
continuous refactor: migration/random-files-20260514T002712/phase-2-b…
bigH May 17, 2026
fdcdbfe
continuous refactor: migration/random-files-20260514T002712/phase-3-p…
bigH May 17, 2026
964f872
remove completed migrations
bigH May 18, 2026
7b7381c
approve migration
bigH May 18, 2026
016a77d
continuous refactor: migration/random-files-20260512T161021/phase-1-m…
bigH May 19, 2026
18c0448
continuous refactor: migration/random-files-20260512T161021/phase-2-n…
bigH May 19, 2026
d7cebed
continuous refactor: migration/random-files-20260512T161021/phase-3-t…
bigH May 19, 2026
dfe4c26
close out migration early
bigH May 19, 2026
b479b67
no need for this one
bigH May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.scratchpad/
tmpdir/
.pytest_cache/

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
65 changes: 53 additions & 12 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,33 @@ Treat `AGENTS.md` as part of the codebase's invariants, not documentation. A dri
- Test one: `uv run pytest tests/test_x.py::test_name`
- Entry: `continuous-refactoring --help` / `continuous-refactoring --version`
(or `python -m continuous_refactoring`)
- Init: `continuous-refactoring init [--path PATH]
[--live-migrations-dir DIR] [--in-repo-taste [PATH]] [--force]`
- Taste: `continuous-refactoring taste [--global]
[--interview|--upgrade|--refine]
[--with codex|claude --model <model> --effort <low|medium|high|xhigh>]
[--force]`
- Run once: `continuous-refactoring run-once --with codex|claude
--model <model> [common targeting/validation flags]`
- Run loop: `continuous-refactoring run --with codex|claude --model <model>
[--max-attempts N] [--max-refactors N] [--focus-on-live-migrations]
[--commit-message-prefix TEXT] [--max-consecutive-failures N] [--sleep N]`
Requires targeting flags or `--scope-instruction` unless
`--focus-on-live-migrations`; `--max-refactors` is required unless using
`--targets` or `--focus-on-live-migrations`.
- Upgrade config: `continuous-refactoring upgrade`
- Inspect migrations: `continuous-refactoring migration list
[--status planning|ready|in-progress|skipped|done]
[--awaiting-review]` /
`continuous-refactoring migration doctor <slug-or-path>` /
`continuous-refactoring migration doctor --all`
- Review migrations: `continuous-refactoring migration review <slug-or-path>
--with codex|claude --model <model> --effort <low|medium|high|xhigh>`
(top-level `review list` / `review perform <slug> --with ... --model ...
--effort ...` remain compatibility wrappers)
- Refine migration planning: `continuous-refactoring migration refine <slug-or-path>
(--message <text>|--file <path>) --with codex|claude --model <model>
--effort <low|medium|high|xhigh> [--show-agent-logs]`

No lint, no typecheck, no formatter, no pre-commit. GitHub Actions `Test`
runs `uv run pytest`. **Pytest is the only code gate.** GitHub Actions
Expand All @@ -29,32 +56,38 @@ runs `uv run pytest`. **Pytest is the only code gate.** GitHub Actions

- `src/continuous_refactoring/` — flat module layout, no subpackages
- `tests/` — flat, `test_<module>.py` per source module plus behavior bundles (`test_e2e.py`, `test_run.py`, `test_run_once.py`)
- `migrations/` — live multi-phase plans (dog-food output)
- `<live-migrations-dir>/` — configurable live multi-phase plans (dog-food output); a checkout may not have `migrations/`
- `.scratchpad/` — ephemeral agent state, gitignored
- Durable user state: `~/.local/share/continuous-refactoring/…` (XDG)

## 5. Project vocabulary

- **Target** — a source path the driver is working on this iteration.
- **Target** — the refactoring unit the driver is working on this iteration: a JSONL target, one matched tracked file, literal path set, random tracked-file bundle, or fallback scoped prompt.
- **Taste** — project or global prose that shapes every prompt. Project taste is XDG by default, or a repo-relative path stored as `repo_taste_path` after `init --in-repo-taste [PATH]`.
- **Scope expansion** — deciding the set of files edited together with the target (`scope_expansion.py`).
- **Classifier / routing** — picks which agent handles a target (`routing.py`).
- **Migration** — a multi-phase plan living under `migrations/<slug>/`.
- **Classifier / routing** — chooses a target route: `cohesive-cleanup` vs `needs-plan` (`routing.py`).
- **Migration** — a multi-phase plan living under `<live-migrations-dir>/<slug>/`.
- **Visible migration directory** — direct child migration dir that is not hidden, dotted, symlinked, or internal/transactional; enumerate through `iter_visible_migration_dirs()`.
- **Consistency finding** — structured migration integrity result with shared `info | warning | error` severity and `planning-snapshot | ready-publish | execution-gate | doctor` mode.
- **Planning state** — durable resume/audit cursor at `<migration>/.planning/state.json`; it records accepted planning steps and their repo-relative stage outputs.
- **Planning stage output** — accepted planning stdout stored under `<migration>/.planning/stages/<step>.stdout.md`; repeated accepted steps use suffixed refs such as `<step>-2.stdout.md`. Failed current-step output stays in run artifacts only.
- **Planning feedback** — explicit user refinement feedback recorded in `.planning/state.json`; it reuses the `revise` planning step and is published only through staged planning/refine transactions.
- **Planning workspace** — off-live candidate migration snapshot built under project state, then copied to a live-dir transaction before publish.
- **Phase** — one step of a migration; state transitions in `phases.py`.
- **Precondition** — what must already be true before a phase may execute; stored on each manifest phase as `precondition`.
- **Definition of Done** — what must be true for a phase to count as completed; written in each phase markdown doc under `## Definition of Done`.
- **Phase cursor** — `manifest.current_phase` stores the active phase `name`; human-facing references use the relative phase file path; phase names must be unique within a migration.
- **Wake-up rule** — schedule for when the driver reconsiders an idle target.
- **Eligibility cooldown** — `manifest.cooldown_until` gates re-checks after a migration was deferred or blocked; `last_touch` records activity only.
- **Settle protocol** — `<file>.done` + sha256 handshake confirming an interactive agent is finished.
- **Status block** — the driver's end-of-attempt summary written to artifacts.
- **Call role** — `classifier | planner | editor | reviewer` slot filled in a prompt.
- **Status block** — the agent-emitted final-message block parsed by `decisions.py`.
- **Call role** — prompt slot recorded in artifacts, including `classify`, `refactor`, dotted planning roles such as `planning.<step>`, `planning.state`, `planning.publish`, and phase roles such as `phase.ready-check` or `phase.execute`.
- **Effort budget** — shared nominal tiers `low < medium < high < xhigh`; `--default-effort` is the normal call effort, `--max-allowed-effort` caps target overrides and phase escalation.
- **Failure snapshot** — per-attempt failure record at `…/projects/<uuid>/failures/<run_id>-attempt-NNN-retry-NN-<role>.md`. One file per failed attempt; sort to find the latest.

## 6. Code conventions

- `from __future__ import annotations` at the top of every src file.
- `from __future__ import annotations` at the top of every src file, after an optional module docstring.
- Frozen dataclasses for value types; `Literal[…]` for state machines.
- Explicit `__all__` per module.
- Full-path imports (`from continuous_refactoring.X import Y`). **Never relative.**
Expand All @@ -70,10 +103,10 @@ runs `uv run pytest`. **Pytest is the only code gate.** GitHub Actions

## 8. Testing idioms

- `pytest>=8.0` only. No coverage, no hypothesis, no markers.
- `pytest>=8.0` only. No coverage, no hypothesis, no custom pytest markers; `pytest.mark.parametrize` is normal.
- Monkeypatching is idiomatic — not a smell.
- `tests/conftest.py` provides:
- `write_fake_codex` — drops a Python stub for `codex` on PATH. Controlled by `FAKE_CODEX_STDOUT`, `FAKE_CODEX_LAST_MESSAGE`, `FAKE_CODEX_TOUCH_FILE`, `FAKE_CODEX_EXIT_CODE`.
- `write_fake_codex` — drops a Python stub for `codex` on PATH. Controlled by `FAKE_CODEX_STDOUT`, `FAKE_CODEX_STDERR`, `FAKE_CODEX_LAST_MESSAGE`, `FAKE_CODEX_TOUCH_FILE`, `FAKE_CODEX_TOUCH_CONTENT`, `FAKE_CODEX_EXIT_CODE`.
- `_prepare_run_env` — `git init -b main` in `tmp_path`; redirects `TMPDIR` and `XDG_DATA_HOME` to the sandbox.
- `make_run_once_args` / `make_run_loop_args` — build argparse `Namespace`s so tests bypass the CLI layer.
- Claude stream-json parsing is covered with recorded NDJSON at `tests/fixtures/claude_stream_json/selection.stdout.log`.
Expand All @@ -93,9 +126,16 @@ active phase explicitly names `loop.py` in scope.
- **Driver owns commits** (`refactor_attempts.py:_finalize_commit()`, called from `loop.py`) — if an agent commits mid-attempt, driver does `git reset --soft head_before` and re-commits with its own message.
- **Migration scheduling split** (`migrations.py`, `loop.py`, `phases.py`) — `last_touch` is activity bookkeeping, not the 6-hour retry gate. Deferred/blocked migrations set `cooldown_until`; successful phase completion clears deferral markers so the next ready phase can run immediately.
- **Migration tick deferral writes** (`migration_tick.py`) — ready-check deferrals are queued while scanning candidates and saved only when the tick finds no executable phase or blocks for human review. Do not save a deferred manifest before checking later candidates; that dirties the worktree and can make ready-checks reject runnable phases.
- **Migration visibility + consistency gate** (`migration_consistency.py`, `migration_tick.py`, `loop.py`, `review_cli.py`) — candidate scans use `iter_visible_migration_dirs()` so hidden/dotted/internal/symlink dirs are invisible to tick/review list. Before ready-check, `execution-gate` consistency errors block phase execution; `info`/`warning` never block.
- **Manifest codec boundary** (`migration_manifest_codec.py`, `migrations.py`) — codec owns legacy `ready_when`, legacy integer `current_phase`, duplicate phase-name rejection, and saved JSON formatting. `load_manifest()` / `save_manifest()` own filesystem and JSON boundary errors.
- **Review CLI boundary** (`cli.py`, `review_cli.py`) — `cli.py` owns parser wiring and run dispatch; migration review internals live in `review_cli.py`, which stays internal and out of package-root `_SUBMODULES`.
- **Human-review gating** (`planning.py`, `migration_tick.py`, `review_cli.py`) — migrations with `awaiting_human_review=true` must be invisible to automated migration ticks/ready-checks until `review perform` clears the flag.
- **Planning state codec boundary** (`planning_state.py`, `planning.py`) — `.planning/state.json` is valid only when completed steps replay through the branching planning graph to `next_step`; recorded outputs must be repo-relative files inside the migration directory. User refinement feedback is durable state, and append-only `revision_base_step_counts` anchors let unexecuted ready migrations reuse `revise` after terminal ready decisions; legacy `revision_base_step_count` decodes as one anchor. Persist accepted step stdout after the step is validated; do not add durable fields for failed current-step output.
- **Planning publish transaction** (`planning_publish.py`) — publish copies the complete workspace snapshot to `__transactions__/<token>/staged`, validates it, checks same-device and `base_snapshot_id`, moves live to `rollback`, moves staged live, validates live, then deletes rollback. On post-rollback failure, move bad live to `failed` before restoring rollback. Transaction directories are invisible to scheduling/list candidates but visible to `migration doctor --all`. Do not bypass the lock or dirty-live check.
- **One-step planning engine** (`planning.py`) — product planning entry points call `run_next_planning_step()` so one action runs exactly `PlanningState.next_step`, records accepted stdout/state in an off-live workspace, and publishes through `planning_publish.py`. Failed current-step output is never durable resume input. `run_planning` is intentionally not package-exported.
- **Planning resume scheduling** (`migration_tick.py`, `loop.py`, `routing_pipeline.py`) — normal automation runs one eligible `status: planning` step before ready/in-progress phase ticks and before source-target routing. Missing or invalid `.planning/state.json` blocks automation with planning failure evidence; `status: planning` must never enter phase ready-check or phase execution.
- **Focused planning reselection** (`loop.py`, `migration_tick.py`) — focused mode tracks planning migrations abandoned with `new-target` only in memory for the current run, skips them while another planning or phase candidate is eligible, and retries them only when no alternative remains. Do not persist this as `cooldown_until`; planning step failure is not a durable readiness deferral.
- **Review CLI boundary** (`cli.py`, `review_cli.py`) — `cli.py` owns parser wiring; staged migration review internals live in `review_cli.py`, publish only through `planning_publish.py`, and stay internal/out of package-root `_SUBMODULES`. Top-level `review perform` is only a compatibility wrapper around this path.
- **Migration CLI boundary** (`cli.py`, `migration_cli.py`) — `cli.py` owns parser wiring only; `migration_cli.py` owns namespace dispatch, read-only list/doctor behavior, and the contained slug/path resolver used by mutation commands. Mutating subcommands delegate their internals to focused modules such as `review_cli.py` or the planning refine entry point. Resolver targets must stay direct visible children of the configured live migrations root and reject symlink, outside, parent-traversal, and ambiguous paths.
- **Human-review gating** (`planning.py`, `migration_tick.py`, `review_cli.py`) — migrations with `awaiting_human_review=true` must be invisible to automated migration ticks/ready-checks until canonical `migration review` clears the flag through staged publish; top-level `review perform` routes to the same compatibility path. `migration refine` may reopen an unexecuted ready migration to planning, but it is user feedback, not review approval.
- **Migration terminology split** (`migrations.py`, `planning.py`, `prompts.py`) — manifest `precondition` gates phase start; phase markdown `## Definition of Done` governs completion.
- **Run-level baseline validation** (`loop.py`) — `run-once`, `run`, and `--focus-on-live-migrations` run the configured validation command after the clean-worktree check and before routing/refactoring. A red baseline stops as `baseline_failed`, not migration human review.
- **Phase execution validation gate** (`phases.py`, `prompts.py`, `loop.py`) — a migration phase is complete only after host-side full validation passes. `execute_phase()` retries validation-red attempts from `head_before` up to the effective `--max-attempts` budget, and the phase prompt must include the literal configured validation command plus the phase file's Definition of Done as the completion contract.
Expand All @@ -108,6 +148,7 @@ active phase explicitly names `loop.py` in scope.
## 11. Surprising CLI semantics

- Targeting is **first-match-wins** across `--targets > --globs > --extensions > --paths`. Multiple flags silently use the highest.
- `run` requires targeting or `--scope-instruction`, and also requires `--max-refactors` unless `--targets` or `--focus-on-live-migrations` is set.
- `--max-attempts 0` means **unlimited**, not zero. A WARN fires at startup.
- `run-once` and `run` both create local commits only; the driver never publishes branch updates.

Expand Down Expand Up @@ -150,7 +191,7 @@ active phase explicitly names `loop.py` in scope.
## 15. Read-first pointers

- `README.md` — feature tour and CLI reference.
- `migrations/<live>/plan.md` — active structural work.
- `<live-migrations-dir>/<live>/plan.md` — active structural work, when this checkout has a live migrations dir.
- `src/continuous_refactoring/__init__.py` — public surface and uniqueness check.
- `tests/conftest.py` — test env patterns and fake agents.
- `src/continuous_refactoring/prompts.py` — prompt templates and taste injection.
Loading
Loading