refactorai-cli 0.5.7__tar.gz → 0.5.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.
Files changed (51) hide show
  1. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/PKG-INFO +2 -2
  2. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/pyproject.toml +2 -2
  3. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/__init__.py +1 -1
  4. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/pre_push_cmds.py +3 -2
  5. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/run_cmds.py +52 -3
  6. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/local_constitution.py +4 -0
  7. refactorai_cli-0.5.8/refactorai_cli/local_paths.py +76 -0
  8. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/refactor_branch_store.py +2 -2
  9. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/watch_supervisor.py +2 -2
  10. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli.egg-info/PKG-INFO +2 -2
  11. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli.egg-info/requires.txt +1 -1
  12. refactorai_cli-0.5.7/refactorai_cli/local_paths.py +0 -40
  13. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/README.md +0 -0
  14. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/auth.py +0 -0
  15. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/client.py +0 -0
  16. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/cloud_rr.py +0 -0
  17. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/__init__.py +0 -0
  18. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/account_cmds.py +0 -0
  19. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/auth_cmds.py +0 -0
  20. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/branch_cmds.py +0 -0
  21. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/cloud_cmds.py +0 -0
  22. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/engine_cmds.py +0 -0
  23. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/hook_cmds.py +0 -0
  24. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/model_cmds.py +0 -0
  25. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/request_cmds.py +0 -0
  26. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/rules_cmds.py +0 -0
  27. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/runtime_cmds.py +0 -0
  28. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/runtime_proxy_cmds.py +0 -0
  29. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/setup_cmds.py +0 -0
  30. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/toolchains_cmds.py +0 -0
  31. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commands/watch_cmds.py +0 -0
  32. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commit_queue.py +0 -0
  33. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/commit_telemetry.py +0 -0
  34. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/control_plane.py +0 -0
  35. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/credentials.py +0 -0
  36. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/dotenv_loader.py +0 -0
  37. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/git_scope.py +0 -0
  38. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/local_engine_runtime.py +0 -0
  39. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/main.py +0 -0
  40. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/model_policy.py +0 -0
  41. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/pre_push_gate.py +0 -0
  42. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/review_runner.py +0 -0
  43. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/runtime_manager.py +0 -0
  44. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/settings.py +0 -0
  45. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/setup_flow.py +0 -0
  46. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli/watch_state.py +0 -0
  47. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli.egg-info/SOURCES.txt +0 -0
  48. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli.egg-info/dependency_links.txt +0 -0
  49. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli.egg-info/entry_points.txt +0 -0
  50. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/refactorai_cli.egg-info/top_level.txt +0 -0
  51. {refactorai_cli-0.5.7 → refactorai_cli-0.5.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.5.7
3
+ Version: 0.5.8
4
4
  Summary: Local-first CLI for the refactor platform
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -8,7 +8,7 @@ Requires-Dist: typer>=0.12.0
8
8
  Requires-Dist: httpx>=0.27.0
9
9
  Requires-Dist: rich>=13.7.0
10
10
  Requires-Dist: PyYAML>=6.0.1
11
- Requires-Dist: refactorai-core>=3.2.12
11
+ Requires-Dist: refactorai-core>=3.2.13
12
12
 
13
13
  # refactorai-cli
14
14
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "refactorai-cli"
3
- version = "0.5.7"
3
+ version = "0.5.8"
4
4
  description = "Local-first CLI for the refactor platform"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -12,7 +12,7 @@ dependencies = [
12
12
  "httpx>=0.27.0",
13
13
  "rich>=13.7.0",
14
14
  "PyYAML>=6.0.1",
15
- "refactorai-core>=3.2.12",
15
+ "refactorai-core>=3.2.13",
16
16
  ]
17
17
 
18
18
  [project.scripts]
@@ -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.7"
8
+ __version__ = "0.5.8"
@@ -72,9 +72,10 @@ def _count_requests(project_root: Path) -> tuple[int, int]:
72
72
 
73
73
  def _record_skip(project_root: Path, *, reasons: list[str], reason: str) -> None:
74
74
  try:
75
- from refactor_core.paths import ensure_dir, project_store_dir
75
+ from refactor_core.paths import ensure_dir
76
+ from refactor_core.store import resolve_store_dir
76
77
 
77
- audit_path = ensure_dir(project_store_dir(project_root)) / "pre_push_audit.jsonl"
78
+ audit_path = ensure_dir(resolve_store_dir(project_root)) / "pre_push_audit.jsonl"
78
79
  entry = {
79
80
  "at": datetime.now(timezone.utc).isoformat(),
80
81
  "event": "pre_push_bypass",
@@ -90,8 +90,9 @@ from refactor_core.store import (
90
90
  create_run,
91
91
  head_run_dir,
92
92
  list_runs,
93
- project_store_dir,
94
93
  prune_runs,
94
+ resolve_project_id as resolve_store_project_id,
95
+ resolve_store_dir,
95
96
  read_findings,
96
97
  read_report,
97
98
  read_sandbox_install_history,
@@ -913,6 +914,50 @@ def _load_project() -> tuple[Path, object, object]:
913
914
  return consti_path.parent, constitution, config
914
915
 
915
916
 
917
+ def _print_store_context(project_root) -> None:
918
+ """Surface the resolved project id + central store dir for this run.
919
+
920
+ Makes the id-keyed store observable so a wrong/duplicate binding (or an
921
+ unexpectedly unbound folder) is obvious at a glance instead of surfacing as a
922
+ confusing "resumed old requests" symptom later.
923
+ """
924
+ try:
925
+ pid = resolve_store_project_id(project_root)
926
+ store_dir = resolve_store_dir(project_root)
927
+ except Exception:
928
+ return
929
+ label = pid or "(unbound / local)"
930
+ console.print(f"[dim]project id:[/dim] {label} [dim]· store:[/dim] {store_dir}")
931
+
932
+
933
+ def _report_store_binding(project_root) -> None:
934
+ """Doctor diagnostic: resolved project id, store dir, and binding mismatch.
935
+
936
+ A mismatch between the id resolved from ``refactor.config`` and the id stamped
937
+ on the on-disk store record is the fingerprint of a re-linked/duplicated
938
+ project; surfacing it here turns a silent state bug into an obvious check.
939
+ """
940
+ try:
941
+ from refactor_core.store import project_record
942
+
943
+ pid = resolve_store_project_id(project_root)
944
+ store_dir = resolve_store_dir(project_root)
945
+ except Exception:
946
+ return
947
+ console.print(f"[bold]project id[/bold]: {pid or '(unbound / local)'}")
948
+ console.print(f"[bold]store[/bold]: {store_dir}")
949
+ try:
950
+ record = project_record(project_root) or {}
951
+ record_id = str(record.get("project_id", "") or "")
952
+ except Exception:
953
+ record_id = ""
954
+ if pid and record_id and record_id != pid:
955
+ console.print(
956
+ f"[yellow]store binding[/yellow]: on-disk record id '{record_id}' differs "
957
+ f"from resolved '{pid}'. The store will re-key to the resolved id."
958
+ )
959
+
960
+
916
961
  def _warn_raw_key(constitution, config) -> None:
917
962
  if has_raw_secret_literal(constitution) or bool(raw_secret_matches_config(config)):
918
963
  console.print(
@@ -1127,7 +1172,7 @@ def init(
1127
1172
  "(mode=cloud_byok, env-key-first via provider_key; credential_ref is optional fallback)."
1128
1173
  )
1129
1174
  console.print(
1130
- f"[green]Registered[/green] project in central store: {project_store_dir(project_root)}"
1175
+ f"[green]Registered[/green] project in central store: {resolve_store_dir(project_root)}"
1131
1176
  )
1132
1177
  console.print(
1133
1178
  f"Only {CONSTITUTION_FILENAME} and {CONFIG_FILENAME} are added to your repo; "
@@ -2796,6 +2841,7 @@ def review(
2796
2841
  constitution_hash=constitution.content_hash,
2797
2842
  project_id=resolve_project_id(project_root) or None,
2798
2843
  )
2844
+ _print_store_context(project_root)
2799
2845
  _maybe_build_graph(project_root, project_config)
2800
2846
 
2801
2847
  # Commit-scoped review (docs/41 `R28`). Works in every execution mode: local
@@ -3136,6 +3182,7 @@ def code(
3136
3182
  constitution_hash=constitution.content_hash,
3137
3183
  project_id=resolve_project_id(project_root) or None,
3138
3184
  )
3185
+ _print_store_context(project_root)
3139
3186
  _maybe_build_graph(project_root, project_config)
3140
3187
 
3141
3188
  # Commit-scoped resolve (docs/41 `R28`, Phase 4), symmetric to `review` and
@@ -4381,7 +4428,7 @@ def gc(
4381
4428
  removed = prune_runs(project_root, keep=keep)
4382
4429
  console.print(
4383
4430
  f"[green]Pruned[/green] {len(removed)} run(s); kept {before - len(removed)} "
4384
- f"under {project_store_dir(project_root)}."
4431
+ f"under {resolve_store_dir(project_root)}."
4385
4432
  )
4386
4433
 
4387
4434
 
@@ -4616,6 +4663,7 @@ def _cloud_doctor(
4616
4663
  """
4617
4664
  console.print(f"[bold]project[/bold]: {project_root}")
4618
4665
  console.print(f"[bold]mode[/bold]: {execution_mode}")
4666
+ _report_store_binding(project_root)
4619
4667
 
4620
4668
  try:
4621
4669
  auth_ctx = ensure_authenticated(project_root)
@@ -4849,6 +4897,7 @@ def doctor(
4849
4897
  console.print(f"[bold]mode[/bold]: {mode}")
4850
4898
  console.print(f"[bold]provider[/bold]: {provider_name}")
4851
4899
  console.print(f"[bold]supported[/bold]: {', '.join(supported_providers())}")
4900
+ _report_store_binding(project_root)
4852
4901
 
4853
4902
  try:
4854
4903
  auth_ctx = ensure_authenticated(project_root)
@@ -46,11 +46,15 @@ def _search_root(start: Path | None = None) -> Path:
46
46
 
47
47
 
48
48
  def find_config(start: Path | None = None) -> Path | None:
49
+ # Stop at the enclosing git repo root so we never adopt a parent directory's
50
+ # refactor.config (mirror of refactor_core.constitution discovery guard).
49
51
  current = _search_root(start)
50
52
  for candidate in [current, *current.parents]:
51
53
  config = candidate / CONFIG_FILENAME
52
54
  if config.is_file():
53
55
  return config
56
+ if (candidate / ".git").exists():
57
+ return None
54
58
  return None
55
59
 
56
60
 
@@ -0,0 +1,76 @@
1
+ """Local path helpers for the standalone CLI package.
2
+
3
+ These mirror the path helpers that were previously imported from ``refactor_core``
4
+ so the public ``refactorai-cli`` package can install without requiring a separate
5
+ ``refactor-core`` wheel on PyPI.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+ import re
12
+ from pathlib import Path
13
+
14
+
15
+ def refactor_home() -> Path:
16
+ override = os.environ.get("REFACTOR_HOME")
17
+ if override:
18
+ return Path(override).expanduser()
19
+ return Path.home() / ".refactor"
20
+
21
+
22
+ def encode_project_path(project_root: Path | str) -> str:
23
+ resolved = str(Path(project_root).resolve())
24
+ return resolved.lstrip("/").replace("/", "-") or "root"
25
+
26
+
27
+ def sanitize_project_id(project_id: str | None) -> str:
28
+ """Filesystem-safe project id, or ``""`` (mirror of core helper)."""
29
+ value = str(project_id or "").strip()
30
+ if not value or value in {".", ".."}:
31
+ return ""
32
+ safe = re.sub(r"[^A-Za-z0-9._-]+", "-", value).strip("-")
33
+ if safe in {"", ".", ".."}:
34
+ return ""
35
+ return safe[:128]
36
+
37
+
38
+ def project_store_dir_by_id(project_id: str) -> Path:
39
+ safe = sanitize_project_id(project_id)
40
+ if not safe:
41
+ raise ValueError("project_store_dir_by_id requires a non-empty project_id")
42
+ return refactor_home() / "projects" / safe
43
+
44
+
45
+ def ensure_dir(path: Path, *, mode: int = 0o700) -> Path:
46
+ path.mkdir(parents=True, exist_ok=True, mode=mode)
47
+ return path
48
+
49
+
50
+ def credentials_path() -> Path:
51
+ return refactor_home() / "credentials.json"
52
+
53
+
54
+ def validation_cache_dir() -> Path:
55
+ return refactor_home() / "cache" / "validation"
56
+
57
+
58
+ def project_store_dir(project_root: Path | str) -> Path:
59
+ """Legacy path-encoded store dir (backward-compat reads + migration only)."""
60
+ return refactor_home() / "projects" / encode_project_path(project_root)
61
+
62
+
63
+ def resolve_store_dir(project_root: Path | str, *, project_id: str | None = None) -> Path:
64
+ """Return the project's central store dir, keyed by ``project_id``.
65
+
66
+ Delegates to ``refactor_core.store.resolve_store_dir`` (the single source of
67
+ truth, which also migrates any legacy path-encoded dir) when the core package
68
+ is importable. Falls back to the legacy path-encoded dir for pip-only installs
69
+ without ``refactor_core`` on disk, preserving this module's standalone role.
70
+ """
71
+ try:
72
+ from refactor_core.store import resolve_store_dir as _core_resolve
73
+
74
+ return _core_resolve(project_root, project_id=project_id)
75
+ except Exception:
76
+ return project_store_dir(project_root)
@@ -16,7 +16,7 @@ from dataclasses import dataclass
16
16
  from datetime import datetime, timezone
17
17
  from pathlib import Path
18
18
 
19
- from refactorai_cli.local_paths import ensure_dir, project_store_dir
19
+ from refactorai_cli.local_paths import ensure_dir, resolve_store_dir
20
20
 
21
21
  _DIR = "refactor_branches"
22
22
 
@@ -67,7 +67,7 @@ def refactor_branch_name(
67
67
 
68
68
 
69
69
  def _dir(project_root: Path | str) -> Path:
70
- return project_store_dir(project_root) / _DIR
70
+ return resolve_store_dir(project_root) / _DIR
71
71
 
72
72
 
73
73
  def _path(project_root: Path | str, branch: str) -> Path:
@@ -50,9 +50,9 @@ def lock_path(project_root: Path | str) -> Path:
50
50
  directory = commit_queue.runs_dir(project_root)
51
51
  if directory is None:
52
52
  # Outside a git dir (or tests): fall back to the central project store.
53
- from refactorai_cli.local_paths import project_store_dir
53
+ from refactorai_cli.local_paths import resolve_store_dir
54
54
 
55
- directory = project_store_dir(project_root)
55
+ directory = resolve_store_dir(project_root)
56
56
  return Path(directory) / LOCK_FILENAME
57
57
 
58
58
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.5.7
3
+ Version: 0.5.8
4
4
  Summary: Local-first CLI for the refactor platform
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -8,7 +8,7 @@ Requires-Dist: typer>=0.12.0
8
8
  Requires-Dist: httpx>=0.27.0
9
9
  Requires-Dist: rich>=13.7.0
10
10
  Requires-Dist: PyYAML>=6.0.1
11
- Requires-Dist: refactorai-core>=3.2.12
11
+ Requires-Dist: refactorai-core>=3.2.13
12
12
 
13
13
  # refactorai-cli
14
14
 
@@ -2,4 +2,4 @@ typer>=0.12.0
2
2
  httpx>=0.27.0
3
3
  rich>=13.7.0
4
4
  PyYAML>=6.0.1
5
- refactorai-core>=3.2.12
5
+ refactorai-core>=3.2.13
@@ -1,40 +0,0 @@
1
- """Local path helpers for the standalone CLI package.
2
-
3
- These mirror the path helpers that were previously imported from ``refactor_core``
4
- so the public ``refactorai-cli`` package can install without requiring a separate
5
- ``refactor-core`` wheel on PyPI.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import os
11
- from pathlib import Path
12
-
13
-
14
- def refactor_home() -> Path:
15
- override = os.environ.get("REFACTOR_HOME")
16
- if override:
17
- return Path(override).expanduser()
18
- return Path.home() / ".refactor"
19
-
20
-
21
- def encode_project_path(project_root: Path | str) -> str:
22
- resolved = str(Path(project_root).resolve())
23
- return resolved.lstrip("/").replace("/", "-") or "root"
24
-
25
-
26
- def ensure_dir(path: Path, *, mode: int = 0o700) -> Path:
27
- path.mkdir(parents=True, exist_ok=True, mode=mode)
28
- return path
29
-
30
-
31
- def credentials_path() -> Path:
32
- return refactor_home() / "credentials.json"
33
-
34
-
35
- def validation_cache_dir() -> Path:
36
- return refactor_home() / "cache" / "validation"
37
-
38
-
39
- def project_store_dir(project_root: Path | str) -> Path:
40
- return refactor_home() / "projects" / encode_project_path(project_root)
File without changes
File without changes