Refactor Workflow Design¶
Workflow and domain design for the refactor action loop.
| Layer | Document |
|---|---|
| Platform | Multi-Branch Loops Design |
| Caller shell | Loop Caller Workflows Design |
| Invariants | Loop Engineering Design |
| Skill spec | Refactor skill & loop design |
Artifacts: on-loop-refactor.yaml · skill refactor · refactor/scripts/detect_refactor.sh
Shared caller keys: Loop Caller Inputs Reference.
Purpose¶
Detect mechanical structure hints on integration branches and open fix PRs after bounded O1/O2 refactors. Each loop run surveys all hints in the detection envelope, then applies every actionable candidate in one Agent→Verify cycle.
Supported use cases¶
- Cron scan of integration branches for H1 hints (
duplication_block,oversized_unit) - Apply all actionable structural refactors from the surveyed hint set with stack validation (A')
- Open an L2 review PR to the watch integration branch
- Coordinate with peer loops via workflow concurrency
Out of scope¶
- PR head healing (
pr_enableddefault off) - Interactive or architecture-improvement intent (O3 proposal path) — use skill
refactormanually - Lint/SAST smell scores as primary detect or repair mission
tech-debtreport input or Apply underreport-*names- Sonar CPD default-on (future caller opt-in for duplication only)
| refactor (in common) | Interactive / loop structural O1/O2 apply | User or on-loop-refactor.yaml |
Separation from refactor skill¶
Detect script path: refactor/scripts/detect_refactor.sh (under common package).
Entry skill (refactor) handles interactive and loop paths: loop runs use structural intent only, survey all hints[], apply every apply candidate, O2 cap. Architecture-improvement language in user prompts is out of scope for this loop.
Modes¶
| Mode | Default | Behavior |
|---|---|---|
integration |
on | Detect on watch branch → fix PR to same branch |
pull_request |
off | not supported for this loop |
Caller inputs¶
Keys are passed in on-loop-refactor.yaml via with: on ci-loop-caller.yaml (alphabetically ordered). Multiline values (agent_checker_instructions, agent_maker_instructions) are defined inline in the caller workflow.
Shared semantics: Loop Caller Inputs Reference. Platform branch/finalize caps: canonical table.
| Input / JSON key | Description | Dogfood value |
|---|---|---|
agent_maker_max_turns |
Max maker agent turns per loop attempt (one Agent→Verify cycle). | 100 |
agent_maker_model |
Maker model ID. Cursor: agent --list-models. |
claude-sonnet-5 |
agent_maker_effort |
Maker reasoning effort. Only engines with an effort flag (claude) consume it | medium |
agent_loop_max_attempts |
Max Agent→Verify retry cycles before finalize records failure. | 3 |
agent_checker_instructions |
Checker APPROVE/REJECT rubric. Local/same-package structural edits only; no architecture/GoF/cross-package diffs. | Inline in caller workflow |
agent_checker_max_turns |
Max checker agent turns per verification. | 100 |
agent_checker_model |
Checker model ID. Cursor: agent --list-models. |
claude-opus-5 |
agent_checker_effort |
Checker reasoning effort. Only engines with an effort flag (claude) consume it | medium |
allowlist |
Comma-separated globs the maker may modify. Tight dogfood scope. | .apm/packages/**,scripts/** |
branch_match |
Comma-separated integration branch patterns to watch. | main |
branch_state |
Branch for .loop/* persistence, state migration, and watch fallback. |
main |
budget_max_runs_per_day |
Daily run cap keyed by loop_name. |
1 |
budget_max_tokens_per_day |
Daily aggregated token cap across loops. | 1000000 |
detect_script |
Domain detect script path. | .agents/skills/refactor/scripts/detect_refactor.sh |
engine |
AI engine (claude, copilot, codex, cursor). |
claude |
delivery |
Platform delivery after APPROVE (open_pr for dogfood). |
open_pr |
infer_files_pattern |
Extended regex to infer file paths from checker text. | See caller workflow |
level |
Autonomy level (L1, L2, L3). L2 opens review PR. |
L2 |
loop_name |
Loop identifier; state file .loop/state-refactor.json. |
refactor |
max_targets_per_schedule |
Max hints processed per cron tick. | 1 |
may_edit |
Agent worktree edit gate (true for dogfood). |
true |
no_changes_verdict |
APPROVE or REJECT when maker produces no file diff. |
REJECT |
pr_body |
Optional static prefix (dogfood: ""). |
"" |
pr_title |
PR title when finalize strategy is open_pr. |
chore(refactor): structural improvement (loop-refactor) |
agent_maker_instructions |
Domain instructions: invoke refactor survey-then-apply-all path; stack validation via A'. |
Inline in caller workflow |
pr_enabled |
Enumerate open PR heads. Refactor loop uses integration branches only. | false |
agent_maker_skill_name |
Skill package to invoke. | refactor |
Domain detect environment (detect_domain_env_json)¶
| JSON key / env var | Description | Dogfood value |
|---|---|---|
REFACTOR_DUP_MIN_LINES |
Minimum consecutive non-empty lines for duplication_block |
8 |
REFACTOR_OVERSIZED_FILE_LINES |
File line count threshold for oversized_unit (size only) |
400 |
REFACTOR_SCAN_GLOBS |
Comma-separated globs for scan roots | .apm/packages/**,scripts/** |
| write_target | Agent artifact when may_edit is true (fix for dogfood). | fix |
Detect¶
Integration mode only¶
Per watch branch, loop-detect checks out the branch and invokes detect_refactor.sh with targets["integration:<branch>"].last_sha.
Detect script outputs facts (not semantic repair decisions):
| Field | Role |
|---|---|
hints[] |
Mechanical H1 hints (duplication_block, oversized_unit) |
hint.kind |
Closed set only |
hint.path |
Primary file path for the hint |
hint.detail |
Locator (line range, duplicate peer path, line count) |
commit_range |
Passed through prompt context when scope is range |
skip |
true when no hints after allowlist filter |
Skill (refactor) maps every hints[] entry to survey rows; at L2/L3 applies all candidates marked apply in one run.
loop-detect emits per-branch target_json:
from.ref= HEAD on watch branchto.branch= watch branchfinalize=open_pr
Stable filters (detect only)¶
- Circuit breaker on
targets[key].consecutive_failures - Budget (platform)
- Prune generated trees,
docs/report/**,node_modules/**, secrets paths
No infra/env classification — not applicable.
State fields (per target key)¶
| Field | Role |
|---|---|
last_sha |
Scan cursor; advances when fix PR merges (on-loop-state-promote) |
pending |
Written at finalize on open_pr; promoted to last_sha on merge |
outcome |
pr-created, rejected, no-op, … |
consecutive_failures |
Circuit breaker |
Execute¶
- Worktree from
target.fromon integration branch - Checker diff baseline:
to.branch verifier_context: detect hint summary (kind, path, detail)- Intent: always
structural— O2 cap; no architecture Phase A/B - Survey all hints; apply every apply candidate; follow
refactorskill contract via calleragent_maker_instructions(A')
Finalize¶
PR body is composed by loop-finalize from agent ## Overview / ## Summary (skill-owned) plus mechanical sections. Dogfood sets pr_body: "". See Loop PR Body Skill Contract.
Always open_pr to to.branch at L2.
No domain_persistence_script.
Merge-gated cursor: Same platform rule as all L2 open_pr loops — pending at finalize, last_sha on fix PR merge via on-loop-state-promote.yaml.
State delivery¶
See State delivery philosophy for platform rules.
Target (dogfood): merge-gated pending + on-loop-state-promote — same as docs-updater.
Persistence: state-refactor.json on branch_state via finalize inside ci-loop-agent.
Implementation Checklist¶
Shared platform: Multi-Branch — Shared platform checklist.
Loop-specific¶
- [x]
refactor/scripts/detect_refactor.sh(H1 facts output) - [x]
on-loop-refactor.yamldogfood caller viaci-loop-caller - [x]
verifier_contexton execute path (build_verifier_context_from_result.hintsbranch) - [x]
refactorskill + references - [x] Bats suite for detect script (TEST-00)
Cross-Loop Note¶
refactor is orthogonal to ci-sweeper and tech-debt. It does not consume tech-debt reports. If CI fails during a refactor PR, ci-sweeper owns repair.