forgexa-cli 1.22.3__tar.gz → 1.22.4__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 (21) hide show
  1. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/PKG-INFO +1 -1
  2. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/__init__.py +1 -1
  3. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/daemon.py +48 -7
  4. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/PKG-INFO +1 -1
  5. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/pyproject.toml +1 -1
  6. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/README.md +0 -0
  7. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/_build_config.py +0 -0
  8. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/autoupgrade.py +0 -0
  9. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/main.py +0 -0
  10. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/py.typed +0 -0
  11. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/SOURCES.txt +0 -0
  12. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/dependency_links.txt +0 -0
  13. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/entry_points.txt +0 -0
  14. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/requires.txt +0 -0
  15. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/top_level.txt +0 -0
  16. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/setup.cfg +0 -0
  17. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_auth_and_runtime_commands.py +0 -0
  18. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_autoupgrade.py +0 -0
  19. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_check_command.py +0 -0
  20. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_silent_install.py +0 -0
  21. {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_upgrade_observability.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forgexa-cli
3
- Version: 1.22.3
3
+ Version: 1.22.4
4
4
  Summary: Forgexa CLI — command-line client and AI agent runtime for the Forgexa platform
5
5
  Author-email: Jason Sun <dev.winds@gmail.com>
6
6
  License-Expression: MIT
@@ -1,2 +1,2 @@
1
1
  """forgexa-cli — Forgexa command-line client."""
2
- __version__ = "1.22.3"
2
+ __version__ = "1.22.4"
@@ -555,7 +555,7 @@ except (ImportError, ModuleNotFoundError):
555
555
  # DAEMON_VERSION is the protocol/logic version of the daemon code.
556
556
  # Kept in sync with pyproject.toml version via bump-version.sh.
557
557
  # CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
558
- DAEMON_VERSION = "1.22.3"
558
+ DAEMON_VERSION = "1.22.4"
559
559
 
560
560
 
561
561
  def _detect_client_type() -> str:
@@ -2617,7 +2617,10 @@ class WorkspaceManager:
2617
2617
 
2618
2618
  async def _remove_broken_worktree(self, main_repo: Path, ws_path: Path, workspace_key: str):
2619
2619
  """Remove a broken worktree directory and clean up stale worktree refs."""
2620
- # Try to prune from main repo first
2620
+ # `git worktree prune` keeps an entry while its directory exists, even
2621
+ # when that directory's .git pointer is corrupt.
2622
+ self._safe_rmtree(ws_path)
2623
+
2621
2624
  if main_repo.exists():
2622
2625
  try:
2623
2626
  await self._git("worktree", "prune", cwd=main_repo)
@@ -2627,9 +2630,6 @@ class WorkspaceManager:
2627
2630
  wt_ref = main_repo / ".git" / "worktrees" / workspace_key
2628
2631
  if wt_ref.exists():
2629
2632
  self._safe_rmtree(wt_ref)
2630
- # Remove the broken worktree directory using _safe_rmtree so that
2631
- # read-only git objects on Windows are properly handled.
2632
- self._safe_rmtree(ws_path)
2633
2633
 
2634
2634
  async def _safe_rmtree_main(self, main_repo: Path) -> None:
2635
2635
  """Remove _main repo, first evicting all linked worktrees to prevent orphans.
@@ -2677,8 +2677,10 @@ class WorkspaceManager:
2677
2677
  self,
2678
2678
  main_repo: Path,
2679
2679
  branch_name: str,
2680
+ *,
2681
+ healthy_only: bool = True,
2680
2682
  ) -> Path | None:
2681
- """Return an existing healthy linked worktree already on branch_name."""
2683
+ """Return a linked worktree already on branch_name."""
2682
2684
  try:
2683
2685
  raw = await self._git("worktree", "list", "--porcelain", cwd=main_repo)
2684
2686
  except RuntimeError:
@@ -2704,7 +2706,9 @@ class WorkspaceManager:
2704
2706
  for candidate_path, candidate_branch in entries:
2705
2707
  if candidate_path == main_repo or candidate_branch != target_ref:
2706
2708
  continue
2707
- if candidate_path.exists() and await self._is_healthy_worktree(candidate_path, main_repo=main_repo):
2709
+ if not candidate_path.exists():
2710
+ continue
2711
+ if not healthy_only or await self._is_healthy_worktree(candidate_path, main_repo=main_repo):
2708
2712
  return candidate_path
2709
2713
 
2710
2714
  return None
@@ -3827,6 +3831,43 @@ class WorkspaceManager:
3827
3831
  cwd=main_repo,
3828
3832
  )
3829
3833
  except Exception as exc:
3834
+ existing_branch_worktree = await self._find_existing_worktree_for_branch(
3835
+ main_repo, branch_name,
3836
+ )
3837
+ if existing_branch_worktree is not None:
3838
+ logger.info(
3839
+ "Fresh start reusing worktree %s after resetting %s to origin/%s",
3840
+ existing_branch_worktree, branch_name, default_branch,
3841
+ )
3842
+ await self._git(
3843
+ "checkout", "-B", branch_name, f"origin/{default_branch}",
3844
+ cwd=existing_branch_worktree,
3845
+ )
3846
+ return existing_branch_worktree
3847
+
3848
+ stale_branch_worktree = await self._find_existing_worktree_for_branch(
3849
+ main_repo, branch_name, healthy_only=False,
3850
+ )
3851
+ if stale_branch_worktree is not None:
3852
+ logger.warning(
3853
+ "Fresh start found broken worktree %s holding branch %s; removing it before retrying",
3854
+ stale_branch_worktree, branch_name,
3855
+ )
3856
+ try:
3857
+ await self._remove_broken_worktree(
3858
+ main_repo, stale_branch_worktree, stale_branch_worktree.name,
3859
+ )
3860
+ await self._git(
3861
+ "branch", "-f", branch_name, f"origin/{default_branch}",
3862
+ cwd=main_repo,
3863
+ )
3864
+ await self._git(
3865
+ "worktree", "add", str(ws_path), branch_name,
3866
+ cwd=main_repo,
3867
+ )
3868
+ return ws_path
3869
+ except Exception as recovery_exc:
3870
+ exc = recovery_exc
3830
3871
  self._safe_rmtree(ws_path)
3831
3872
  raise RuntimeError(
3832
3873
  f"Failed to create clean fresh worktree for branch '{branch_name}'. "
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forgexa-cli
3
- Version: 1.22.3
3
+ Version: 1.22.4
4
4
  Summary: Forgexa CLI — command-line client and AI agent runtime for the Forgexa platform
5
5
  Author-email: Jason Sun <dev.winds@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "forgexa-cli"
3
- version = "1.22.3"
3
+ version = "1.22.4"
4
4
  description = "Forgexa CLI — command-line client and AI agent runtime for the Forgexa platform"
5
5
  requires-python = ">=3.9"
6
6
  license = "MIT"
File without changes
File without changes