refactorai-cli 0.5.2__tar.gz → 0.5.5__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 (50) hide show
  1. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/PKG-INFO +1 -1
  2. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/pyproject.toml +1 -1
  3. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/__init__.py +1 -1
  4. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/watch_cmds.py +21 -0
  5. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commit_telemetry.py +88 -2
  6. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli.egg-info/PKG-INFO +1 -1
  7. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/README.md +0 -0
  8. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/auth.py +0 -0
  9. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/client.py +0 -0
  10. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/cloud_rr.py +0 -0
  11. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/__init__.py +0 -0
  12. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/account_cmds.py +0 -0
  13. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/auth_cmds.py +0 -0
  14. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/branch_cmds.py +0 -0
  15. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/cloud_cmds.py +0 -0
  16. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/engine_cmds.py +0 -0
  17. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/hook_cmds.py +0 -0
  18. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/model_cmds.py +0 -0
  19. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/pre_push_cmds.py +0 -0
  20. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/request_cmds.py +0 -0
  21. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/rules_cmds.py +0 -0
  22. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/run_cmds.py +0 -0
  23. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/runtime_cmds.py +0 -0
  24. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/runtime_proxy_cmds.py +0 -0
  25. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/setup_cmds.py +0 -0
  26. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commands/toolchains_cmds.py +0 -0
  27. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/commit_queue.py +0 -0
  28. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/control_plane.py +0 -0
  29. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/credentials.py +0 -0
  30. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/dotenv_loader.py +0 -0
  31. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/git_scope.py +0 -0
  32. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/local_constitution.py +0 -0
  33. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/local_engine_runtime.py +0 -0
  34. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/local_paths.py +0 -0
  35. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/main.py +0 -0
  36. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/model_policy.py +0 -0
  37. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/pre_push_gate.py +0 -0
  38. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/refactor_branch_store.py +0 -0
  39. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/review_runner.py +0 -0
  40. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/runtime_manager.py +0 -0
  41. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/settings.py +0 -0
  42. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/setup_flow.py +0 -0
  43. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/watch_state.py +0 -0
  44. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli/watch_supervisor.py +0 -0
  45. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli.egg-info/SOURCES.txt +0 -0
  46. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli.egg-info/dependency_links.txt +0 -0
  47. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli.egg-info/entry_points.txt +0 -0
  48. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli.egg-info/requires.txt +0 -0
  49. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/refactorai_cli.egg-info/top_level.txt +0 -0
  50. {refactorai_cli-0.5.2 → refactorai_cli-0.5.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.5.2
3
+ Version: 0.5.5
4
4
  Summary: Local-first CLI for the refactor platform
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "refactorai-cli"
3
- version = "0.5.2"
3
+ version = "0.5.5"
4
4
  description = "Local-first CLI for the refactor platform"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -5,4 +5,4 @@ the shared `refactor_core` pipeline from a project folder while staying
5
5
  authenticated to the hosted platform via a developer key.
6
6
  """
7
7
 
8
- __version__ = "0.5.2"
8
+ __version__ = "0.5.5"
@@ -330,6 +330,21 @@ def _report_node(project_root: Path, node) -> None:
330
330
  pass
331
331
 
332
332
 
333
+ def _report_refactor_requests(project_root: Path) -> None:
334
+ """Best-effort sync of the local RR store to the platform Inbox (docs/44).
335
+
336
+ Fail-open like commit telemetry: no-ops unless the repo is bound to a project
337
+ and never raises. Called after any pass/action that can change RR state so the
338
+ cloud Inbox mirrors the developer's local requests.
339
+ """
340
+ try:
341
+ from refactorai_cli import commit_telemetry
342
+
343
+ commit_telemetry.post_refactor_requests(project_root)
344
+ except Exception:
345
+ pass
346
+
347
+
333
348
  def process_pending(
334
349
  project_root: Path,
335
350
  state: WatchState,
@@ -382,6 +397,8 @@ def process_pending(
382
397
  refresh_finalize(project_root, state)
383
398
  if on_update:
384
399
  on_update(state)
400
+ if reviewed:
401
+ _report_refactor_requests(project_root)
385
402
  return reviewed
386
403
 
387
404
 
@@ -574,6 +591,9 @@ def _run_action(
574
591
  refactor_branch_store.set_outcome(project_root, branch, refactor_branch_store.OUTCOME_DROPPED)
575
592
  _sync_current_branch(project_root, state)
576
593
  refresh_finalize(project_root, state)
594
+ # `[r]`/`[m]`/`[d]` can change RR status; mirror the local store to the Inbox.
595
+ if action in ("code", "merge", "drop"):
596
+ _report_refactor_requests(project_root)
577
597
  console.print("\n[dim]watch: returning to the Refactor Terminal...[/dim]")
578
598
  live.start()
579
599
 
@@ -609,6 +629,7 @@ def _run_revert_action(live, project_root: Path, node, state: WatchState) -> Non
609
629
  build_action_command("revert", node.sha, rr_id=rr_id), project_root
610
630
  )
611
631
  refresh_finalize(project_root, state)
632
+ _report_refactor_requests(project_root)
612
633
  else:
613
634
  console.print("[dim]watch: nothing reverted (out of range).[/dim]")
614
635
  else:
@@ -47,6 +47,25 @@ _GATE_MAP = {
47
47
  "blocked": "high",
48
48
  }
49
49
 
50
+ # Local RR lifecycle states -> server RefactorRequest.status. The server Inbox
51
+ # treats {pending,in_progress,deferred,failed} as open; applied is terminal-done;
52
+ # denied is a human "won't fix" (mapped to suppressed); reverted re-opens the
53
+ # finding locally, so it maps back to pending.
54
+ _RR_STATUS_MAP = {
55
+ "pending": "pending",
56
+ "in_progress": "in_progress",
57
+ "deferred": "deferred",
58
+ "failed": "failed",
59
+ "applied": "applied",
60
+ "denied": "suppressed",
61
+ "reverted": "pending",
62
+ }
63
+ # Local RR states that imply a resolution outcome on the server row.
64
+ _RR_OUTCOME_MAP = {
65
+ "applied": "applied",
66
+ "denied": "suppressed",
67
+ }
68
+
50
69
 
51
70
  def telemetry_disabled() -> bool:
52
71
  return str(os.environ.get(ENV_DISABLE, "")).strip().lower() in _TRUTHY
@@ -130,6 +149,46 @@ def build_commit_event_from_queue(event: dict) -> dict:
130
149
  }
131
150
 
132
151
 
152
+ def build_refactor_request(rr) -> dict:
153
+ """Map a local ``refactor_core`` RefactorRequest to the RR ingest body.
154
+
155
+ Accepts the dataclass instance (uses attributes) and normalizes the local
156
+ lifecycle status/outcome to the server's enum. Attempts are flattened to a
157
+ compact per-proposal snapshot so the Inbox can show attempt history.
158
+ """
159
+ status = _RR_STATUS_MAP.get(str(getattr(rr, "status", "") or "").strip().lower(), "pending")
160
+ outcome = _RR_OUTCOME_MAP.get(str(getattr(rr, "status", "") or "").strip().lower())
161
+ attempts: list[dict] = []
162
+ for att in getattr(rr, "attempts", None) or []:
163
+ to_dict = getattr(att, "to_dict", None)
164
+ if callable(to_dict):
165
+ try:
166
+ attempts.append(to_dict())
167
+ continue
168
+ except Exception:
169
+ pass
170
+ if isinstance(att, dict):
171
+ attempts.append(att)
172
+ return {
173
+ "rr_id": str(getattr(rr, "rr_id", "") or ""),
174
+ "file_path": str(getattr(rr, "file_path", "") or ""),
175
+ "symbol": getattr(rr, "symbol", None),
176
+ "category": str(getattr(rr, "category", "") or ""),
177
+ "severity": str(getattr(rr, "severity", "medium") or "medium"),
178
+ "rationale": str(getattr(rr, "rationale", "") or ""),
179
+ "recommendation": str(getattr(rr, "recommendation", "") or ""),
180
+ "operation_type": str(getattr(rr, "operation_type", "content_patch") or "content_patch"),
181
+ "status": status,
182
+ "outcome": outcome,
183
+ "attempt_count": int(getattr(rr, "attempt_count", 0) or 0),
184
+ "detail": None,
185
+ "attempts": attempts,
186
+ "refactor_branch": str(getattr(rr, "refactor_branch", "") or ""),
187
+ "commit_sha": str(getattr(rr, "commit_sha", "") or ""),
188
+ "reverted": bool(getattr(rr, "reverted", False)),
189
+ }
190
+
191
+
133
192
  def _auth_and_project(project_root: Path | str, config: dict | None) -> tuple[object | None, str]:
134
193
  if telemetry_disabled():
135
194
  return None, ""
@@ -165,7 +224,9 @@ def post_commit_event(
165
224
  auth, project_id = _auth_and_project(project_root, config)
166
225
  if not auth or not project_id:
167
226
  return False
168
- url = f"{platform_url()}/v1/projects/{project_id}/commit-events"
227
+ # Developer-key ingest path (the JWT-gated endpoint cannot be called from
228
+ # local CLI telemetry, which only has a developer key).
229
+ url = f"{platform_url()}/v1/projects/{project_id}/commit-events/ingest"
169
230
  return _post(url, auth.key.key, body, timeout)
170
231
 
171
232
 
@@ -182,11 +243,36 @@ def post_heartbeat(
182
243
  auth, project_id = _auth_and_project(project_root, config)
183
244
  if not auth or not project_id:
184
245
  return False
185
- url = f"{platform_url()}/v1/projects/{project_id}/watch/heartbeat"
246
+ # Developer-key ingest path paired with `post_commit_event`.
247
+ url = f"{platform_url()}/v1/projects/{project_id}/watch/heartbeat/ingest"
186
248
  body = {"host": host, "branch": branch, "watch_version": watch_version}
187
249
  return _post(url, auth.key.key, body, timeout)
188
250
 
189
251
 
252
+ def post_refactor_requests(
253
+ project_root: Path | str, *, config: dict | None = None, timeout: float = 8.0
254
+ ) -> bool:
255
+ """Sync the full local RR store to the platform. Best-effort + fail-open.
256
+
257
+ Sends the complete local snapshot (so terminal RRs land as their resolved
258
+ status) and asks the server to reconcile any previously-synced open RRs that
259
+ are no longer present locally (e.g. cleared by a fresh review). Never raises.
260
+ """
261
+ auth, project_id = _auth_and_project(project_root, config)
262
+ if not auth or not project_id:
263
+ return False
264
+ try:
265
+ from refactor_core.refactor_requests import list_requests
266
+
267
+ requests = list_requests(Path(project_root))
268
+ except Exception:
269
+ return False
270
+ items = [build_refactor_request(rr) for rr in requests]
271
+ url = f"{platform_url()}/v1/projects/{project_id}/refactor-requests/ingest"
272
+ body = {"reconcile": True, "requests": items}
273
+ return _post(url, auth.key.key, body, timeout)
274
+
275
+
190
276
  def emit_node(project_root: Path | str, node, *, config: dict | None = None) -> bool:
191
277
  """Build + post a commit event from a watch ``CommitNode``. Never raises."""
192
278
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.5.2
3
+ Version: 0.5.5
4
4
  Summary: Local-first CLI for the refactor platform
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
File without changes
File without changes