refactorai-cli 0.7.7__tar.gz → 0.7.8__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.7 → refactorai_cli-0.7.8}/PKG-INFO +1 -1
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/pyproject.toml +1 -1
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/__init__.py +1 -1
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/watch_cmds.py +64 -1
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli.egg-info/PKG-INFO +1 -1
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/README.md +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/auth.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/client.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/cloud_rr.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/__init__.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/account_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/auth_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/branch_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/cloud_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/engine_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/hook_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/model_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/policy_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/pre_push_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/request_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/rules_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/run_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/runtime_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/runtime_proxy_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/setup_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/toolchains_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commands/workspace_cmds.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commit_queue.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/commit_telemetry.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/control_plane.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/credentials.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/dotenv_loader.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/git_scope.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/local_constitution.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/local_engine_runtime.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/local_paths.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/main.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/model_policy.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/pre_push_gate.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/refactor_branch_store.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/review_runner.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/runtime_manager.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/settings.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/setup_flow.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/watch_ledger.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/watch_state.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli/watch_supervisor.py +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli.egg-info/SOURCES.txt +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli.egg-info/dependency_links.txt +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli.egg-info/entry_points.txt +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli.egg-info/requires.txt +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/refactorai_cli.egg-info/top_level.txt +0 -0
- {refactorai_cli-0.7.7 → refactorai_cli-0.7.8}/setup.cfg +0 -0
|
@@ -13,6 +13,7 @@ headless). The heavy lifting (state machine, rendering, review parsing) lives in
|
|
|
13
13
|
|
|
14
14
|
from __future__ import annotations
|
|
15
15
|
|
|
16
|
+
import contextlib
|
|
16
17
|
import json
|
|
17
18
|
import os
|
|
18
19
|
import select
|
|
@@ -294,6 +295,36 @@ def _ingest_event(project_root: Path, state: WatchState, event: dict) -> None:
|
|
|
294
295
|
node.rr_preview = preview
|
|
295
296
|
|
|
296
297
|
|
|
298
|
+
def _has_refactor_merge_evidence(project_root: Path, node, fin: FinalizeInfo) -> bool:
|
|
299
|
+
"""True when this finalize branch has concrete evidence of refactor commits.
|
|
300
|
+
|
|
301
|
+
Guards against false "merged" labels when a branch exists but carries no
|
|
302
|
+
applied RR commits (for example, a deferred/no-op run where the branch tip is
|
|
303
|
+
still the same as the source commit).
|
|
304
|
+
"""
|
|
305
|
+
# Strongest signal: persisted per-request commits for this branch.
|
|
306
|
+
if getattr(fin, "commits", None):
|
|
307
|
+
return True
|
|
308
|
+
# Fallback signal: branch tip diverged from the source commit.
|
|
309
|
+
source_sha = str(getattr(fin, "source_sha", "") or getattr(node, "sha", "") or "")
|
|
310
|
+
try:
|
|
311
|
+
branch_tip = git_scope.resolve_sha(project_root, fin.refactor_branch) or ""
|
|
312
|
+
except Exception:
|
|
313
|
+
branch_tip = ""
|
|
314
|
+
return bool(branch_tip and source_sha and not _shas_match(branch_tip, source_sha))
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def _is_still_merged(project_root: Path, fin: FinalizeInfo, primary: str) -> bool:
|
|
318
|
+
"""Best-effort check that a branch is really merged into primary."""
|
|
319
|
+
try:
|
|
320
|
+
# Use deep=True to also preserve squash/rebase merges.
|
|
321
|
+
return git_scope.branch_merged_into(
|
|
322
|
+
project_root, fin.refactor_branch, primary, deep=True
|
|
323
|
+
)
|
|
324
|
+
except Exception:
|
|
325
|
+
return True
|
|
326
|
+
|
|
327
|
+
|
|
297
328
|
def reconcile_merged(project_root: Path, state: WatchState, *, deep: bool = False) -> None:
|
|
298
329
|
"""Detect refactor branches integrated into the primary branch out-of-band.
|
|
299
330
|
|
|
@@ -310,7 +341,18 @@ def reconcile_merged(project_root: Path, state: WatchState, *, deep: bool = Fals
|
|
|
310
341
|
fin = getattr(node, "finalize", None)
|
|
311
342
|
if fin is None or not fin.branch_exists:
|
|
312
343
|
continue
|
|
313
|
-
if fin.outcome
|
|
344
|
+
if fin.outcome == refactor_branch_store.OUTCOME_MERGED:
|
|
345
|
+
# Self-heal stale metadata: if a prior run marked merged incorrectly
|
|
346
|
+
# but the branch is still not merged, clear the terminal outcome.
|
|
347
|
+
if not _is_still_merged(project_root, fin, primary):
|
|
348
|
+
refactor_branch_store.set_outcome(project_root, fin.refactor_branch, "")
|
|
349
|
+
node.finalize = resolve_finalize(project_root, node)
|
|
350
|
+
watch_ledger.record_commit(project_root, node)
|
|
351
|
+
continue
|
|
352
|
+
if fin.outcome == refactor_branch_store.OUTCOME_DROPPED:
|
|
353
|
+
continue
|
|
354
|
+
# Don't infer merged for empty/no-op branches.
|
|
355
|
+
if not _has_refactor_merge_evidence(project_root, node, fin):
|
|
314
356
|
continue
|
|
315
357
|
try:
|
|
316
358
|
merged = git_scope.branch_merged_into(project_root, fin.refactor_branch, primary, deep=deep)
|
|
@@ -632,6 +674,25 @@ def _launch_interactive(cmd: list[str], cwd: Path) -> int:
|
|
|
632
674
|
return 130
|
|
633
675
|
|
|
634
676
|
|
|
677
|
+
def _wait_for_return_key() -> None:
|
|
678
|
+
"""Block until one key is pressed before returning to the watch TUI.
|
|
679
|
+
|
|
680
|
+
Used for short-lived actions like ``diff`` so output does not flash and
|
|
681
|
+
disappear when the live screen resumes.
|
|
682
|
+
"""
|
|
683
|
+
if not sys.stdin.isatty():
|
|
684
|
+
# Fallback for non-tty stdin where `_read_key` cannot detect a raw key.
|
|
685
|
+
with contextlib.suppress(EOFError, KeyboardInterrupt):
|
|
686
|
+
typer.prompt("Press Enter to return to the Refactor Terminal", default="")
|
|
687
|
+
return
|
|
688
|
+
|
|
689
|
+
console.print("[dim]watch: press any key to return to the Refactor Terminal...[/dim]")
|
|
690
|
+
while True:
|
|
691
|
+
key = _read_key(0.1)
|
|
692
|
+
if key:
|
|
693
|
+
return
|
|
694
|
+
|
|
695
|
+
|
|
635
696
|
def _run_json_stream(project_root: Path, state: WatchState, runner: ReviewRunner, once: bool) -> None:
|
|
636
697
|
"""Emit a newline-delimited JSON node-event stream (agents / headless)."""
|
|
637
698
|
emitted: dict[str, str] = {}
|
|
@@ -703,6 +764,8 @@ def _run_action(
|
|
|
703
764
|
console.print(f"\n[bold bright_cyan]watch:[/bold bright_cyan] {action} for "
|
|
704
765
|
f"[yellow]{node.short_sha}[/yellow] ({node.branch or 'detached'})\n")
|
|
705
766
|
_launch_interactive(cmd, project_root)
|
|
767
|
+
if action == "diff":
|
|
768
|
+
_wait_for_return_key()
|
|
706
769
|
if action == "refresh":
|
|
707
770
|
# `[f]` explicitly regenerates requests, so re-review this commit on the
|
|
708
771
|
# next pass (also clears any `[b] back` override).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|