forgexa-cli 1.29.3__tar.gz → 1.29.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 (27) hide show
  1. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/PKG-INFO +1 -1
  2. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/__init__.py +1 -1
  3. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/daemon.py +63 -1
  4. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli.egg-info/PKG-INFO +1 -1
  5. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/pyproject.toml +1 -1
  6. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/README.md +0 -0
  7. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/_build_config.py +0 -0
  8. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/_local_bind.py +0 -0
  9. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/agent_core.py +0 -0
  10. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/autoupgrade.py +0 -0
  11. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/main.py +0 -0
  12. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli/py.typed +0 -0
  13. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli.egg-info/SOURCES.txt +0 -0
  14. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli.egg-info/dependency_links.txt +0 -0
  15. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli.egg-info/entry_points.txt +0 -0
  16. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli.egg-info/requires.txt +0 -0
  17. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/forgexa_cli.egg-info/top_level.txt +0 -0
  18. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/setup.cfg +0 -0
  19. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_auth_and_runtime_commands.py +0 -0
  20. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_autoupgrade.py +0 -0
  21. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_check_command.py +0 -0
  22. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_expiry_warnings_and_revoke.py +0 -0
  23. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_local_bind_commands.py +0 -0
  24. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_runtime_credentials.py +0 -0
  25. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_session_credentials.py +0 -0
  26. {forgexa_cli-1.29.3 → forgexa_cli-1.29.4}/tests/test_silent_install.py +0 -0
  27. {forgexa_cli-1.29.3 → forgexa_cli-1.29.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.29.3
3
+ Version: 1.29.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.29.3"
2
+ __version__ = "1.29.4"
@@ -910,7 +910,7 @@ except (ImportError, ModuleNotFoundError):
910
910
  # DAEMON_VERSION is the protocol/logic version of the daemon code.
911
911
  # Kept in sync with pyproject.toml version via bump-version.sh.
912
912
  # CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
913
- DAEMON_VERSION = "1.29.3"
913
+ DAEMON_VERSION = "1.29.4"
914
914
 
915
915
 
916
916
  def _detect_client_type() -> str:
@@ -10100,6 +10100,13 @@ class RuntimeDaemon:
10100
10100
  source_branch = input_ctx.get("source_branch", "")
10101
10101
  base_integration_sha = input_ctx.get("base_integration_sha")
10102
10102
  default_branch = input_ctx.get("default_branch", "main")
10103
+ requirement_key = str(input_ctx.get("requirement_key") or "").strip()
10104
+ if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]*", requirement_key):
10105
+ requirement_key = ""
10106
+ prior_requirement_source_shas = [
10107
+ sha for sha in input_ctx.get("prior_requirement_source_shas", [])
10108
+ if isinstance(sha, str) and re.fullmatch(r"[0-9a-fA-F]{40}", sha)
10109
+ ]
10103
10110
  agent_type = input_ctx.get("agent_type", "claude")
10104
10111
  fallback_chain = input_ctx.get("fallback_chain", [])
10105
10112
  timeout_seconds = min(int(input_ctx.get("timeout_seconds", 300)), 300)
@@ -10283,6 +10290,53 @@ class RuntimeDaemon:
10283
10290
  except RuntimeError:
10284
10291
  diff_u = ""
10285
10292
  conflicted_files = [f.strip() for f in diff_u.strip().splitlines() if f.strip()]
10293
+ replayed_artifact_paths: list[str] = []
10294
+
10295
+ artifact_prefix = f"docs/requirements/{requirement_key}/"
10296
+ if (
10297
+ conflicted_files
10298
+ and requirement_key
10299
+ and prior_requirement_source_shas
10300
+ and all(path.startswith(artifact_prefix) for path in conflicted_files)
10301
+ ):
10302
+ try:
10303
+ conflict_status = await git("status", "--porcelain", cwd=workspace_path)
10304
+ except RuntimeError:
10305
+ conflict_status = ""
10306
+ add_add_paths = {
10307
+ line[3:].strip()
10308
+ for line in conflict_status.splitlines()
10309
+ if line.startswith("AA ")
10310
+ }
10311
+ if all(path in add_add_paths for path in conflicted_files):
10312
+ for prior_source_sha in prior_requirement_source_shas:
10313
+ try:
10314
+ await git(
10315
+ "merge-base", "--is-ancestor", prior_source_sha, base_ref,
10316
+ cwd=workspace_path,
10317
+ )
10318
+ except RuntimeError:
10319
+ continue
10320
+ for conflict_path in conflicted_files:
10321
+ await git(
10322
+ "checkout", "--theirs", "--", conflict_path,
10323
+ cwd=workspace_path,
10324
+ )
10325
+ await git("add", "--", conflict_path, cwd=workspace_path)
10326
+ await git(
10327
+ "-c", f"user.name={_git_name}",
10328
+ "-c", f"user.email={_git_email}",
10329
+ "commit", "--no-edit",
10330
+ cwd=workspace_path,
10331
+ )
10332
+ replayed_artifact_paths = list(conflicted_files)
10333
+ conflicted_files = []
10334
+ merge_conflicted = False
10335
+ logger.info(
10336
+ "deployment_merge: job %s replaced %d replayed requirement artifacts",
10337
+ job_id, len(replayed_artifact_paths),
10338
+ )
10339
+ break
10286
10340
 
10287
10341
  resolved_agent_id: str | None = None
10288
10342
  if merge_conflicted or conflicted_files:
@@ -10592,6 +10646,9 @@ class RuntimeDaemon:
10592
10646
  if resolved_agent_id:
10593
10647
  outcome = "ai_resolved"
10594
10648
  step_msg = f"AI resolved merge via {resolved_agent_id}"
10649
+ elif replayed_artifact_paths:
10650
+ outcome = "clean_merged"
10651
+ step_msg = "Replaced replayed requirement artifacts"
10595
10652
  else:
10596
10653
  outcome = "clean_merged"
10597
10654
  step_msg = "Merge completed cleanly"
@@ -10613,6 +10670,11 @@ class RuntimeDaemon:
10613
10670
  "merge_commit_sha": candidate_sha,
10614
10671
  "base_integration_sha": base_ref,
10615
10672
  "source_commit_sha": source_commit_sha,
10673
+ "ai_resolution_notes": (
10674
+ f"Replaced {len(replayed_artifact_paths)} replayed requirement artifacts "
10675
+ f"under {artifact_prefix} from the new source commit."
10676
+ if replayed_artifact_paths else None
10677
+ ),
10616
10678
  })
10617
10679
 
10618
10680
  except Exception as exc:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forgexa-cli
3
- Version: 1.29.3
3
+ Version: 1.29.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.29.3"
3
+ version = "1.29.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