forgexa-cli 1.82.0__tar.gz → 1.82.2__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 (33) hide show
  1. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/PKG-INFO +1 -1
  2. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/__init__.py +1 -1
  3. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/agent_core.py +20 -2
  4. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/daemon.py +30 -13
  5. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli.egg-info/PKG-INFO +1 -1
  6. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/pyproject.toml +1 -1
  7. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/README.md +0 -0
  8. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/_build_config.py +0 -0
  9. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/_local_bind.py +0 -0
  10. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/autoupgrade.py +0 -0
  11. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/aws_evidence.py +0 -0
  12. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/aws_logs_evidence.py +0 -0
  13. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/main.py +0 -0
  14. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/observability_contract.py +0 -0
  15. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/observability_evidence.py +0 -0
  16. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/py.typed +0 -0
  17. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/runtime_evidence.py +0 -0
  18. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli/zcode_protocol.py +0 -0
  19. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli.egg-info/SOURCES.txt +0 -0
  20. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli.egg-info/dependency_links.txt +0 -0
  21. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli.egg-info/entry_points.txt +0 -0
  22. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli.egg-info/requires.txt +0 -0
  23. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/forgexa_cli.egg-info/top_level.txt +0 -0
  24. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/setup.cfg +0 -0
  25. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_auth_and_runtime_commands.py +0 -0
  26. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_autoupgrade.py +0 -0
  27. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_check_command.py +0 -0
  28. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_expiry_warnings_and_revoke.py +0 -0
  29. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_local_bind_commands.py +0 -0
  30. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_runtime_credentials.py +0 -0
  31. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_session_credentials.py +0 -0
  32. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/tests/test_silent_install.py +0 -0
  33. {forgexa_cli-1.82.0 → forgexa_cli-1.82.2}/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.82.0
3
+ Version: 1.82.2
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.82.0"
2
+ __version__ = "1.82.2"
@@ -239,6 +239,7 @@ def _assess_implementation_contributions(contract: dict, report: object) -> dict
239
239
  task_types = {task["id"]: task.get("type") for task in contract.get("tasks") or []}
240
240
  verification_ids = [task_id for task_id, task_type in task_types.items() if task_type in ("testing", "verify")]
241
241
  verification_statuses = {row["task_id"]: row["status"] for row in report["task_checks"]}
242
+ pending_verification_ids = [task_id for task_id in verification_ids if verification_statuses.get(task_id) != "covered"]
242
243
  checks = []
243
244
  issues = []
244
245
  pending = []
@@ -267,8 +268,25 @@ def _assess_implementation_contributions(contract: dict, report: object) -> dict
267
268
  "task_id": task_id, "status": row.get("status"),
268
269
  "description": row.get("description") or "Runtime acceptance remains pending",
269
270
  "files": [], "evidence": row.get("evidence") or [],
270
- } for task_id in verification_ids if verification_statuses.get(task_id) != "covered")
271
- result = assess_implementation_audit({**contract, "version": 1}, {**report, "task_checks": checks})
271
+ } for task_id in pending_verification_ids)
272
+ implementation_statuses = {row["task_id"]: row["status"] for row in checks}
273
+ acceptance_checks = []
274
+ for row in report["acceptance_checks"]:
275
+ if (
276
+ pending_verification_ids and row["status"] in ("blocked", "unverified")
277
+ and row.get("plan_revision") is None
278
+ and all(task_types.get(task_id) in ("coding", "fix") and implementation_statuses.get(task_id) == "covered"
279
+ for task_id in row["task_ids"])
280
+ ):
281
+ row = {**row, "task_ids": [*row["task_ids"], *pending_verification_ids]}
282
+ pending.extend({
283
+ "task_id": task_id, "status": row["status"], "description": row["description"],
284
+ "files": row.get("files") or [], "evidence": row["evidence"],
285
+ } for task_id in pending_verification_ids)
286
+ acceptance_checks.append(row)
287
+ result = assess_implementation_audit({**contract, "version": 1}, {
288
+ **report, "task_checks": checks, "acceptance_checks": acceptance_checks,
289
+ })
272
290
  result["report"] = report
273
291
  result["issues"].extend(issues)
274
292
  result["report_valid"] = not result["issues"]
@@ -1234,7 +1234,7 @@ except (ImportError, ModuleNotFoundError):
1234
1234
  # DAEMON_VERSION is the protocol/logic version of the daemon code.
1235
1235
  # Kept in sync with pyproject.toml version via bump-version.sh.
1236
1236
  # CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
1237
- DAEMON_VERSION = "1.82.0"
1237
+ DAEMON_VERSION = "1.82.2"
1238
1238
 
1239
1239
 
1240
1240
  def _detect_client_type() -> str:
@@ -2212,6 +2212,7 @@ def _normalize_ai_job_output(
2212
2212
  "qa_scenario_generate_prompt",
2213
2213
  "qa_scenario_preview",
2214
2214
  "qa_script_preview",
2215
+ "qa_recording_suggest",
2215
2216
  "test_script_generate",
2216
2217
  }:
2217
2218
  return raw_output, None
@@ -9951,6 +9952,7 @@ class ServerConnection:
9951
9952
  },
9952
9953
  "implementation_audit": {"protocol_version": 3},
9953
9954
  "task_delivery": {"protocol_version": 1},
9955
+ "recording_suggestions": {"protocol_version": 1, "isolated_workspace": True},
9954
9956
  "task_attachment_staging": {"protocol_version": 1, "runtime_proxy": True, "image_agents": ["claude"]},
9955
9957
  },
9956
9958
  "server_url": self.server_url,
@@ -10376,6 +10378,7 @@ class ServerConnection:
10376
10378
  },
10377
10379
  "implementation_audit": {"protocol_version": 3},
10378
10380
  "task_delivery": {"protocol_version": 1},
10381
+ "recording_suggestions": {"protocol_version": 1, "isolated_workspace": True},
10379
10382
  "local_evidence": {"protocol_version": 1, "structured_summary": True},
10380
10383
  "task_attachment_staging": {"protocol_version": 1, "runtime_proxy": True, "image_agents": ["claude"]},
10381
10384
  },
@@ -13471,6 +13474,7 @@ class RuntimeDaemon:
13471
13474
  result.status == "success"
13472
13475
  and task.node_type in ("review", "coding", "testing")
13473
13476
  and not bool((task.input_data or {}).get("verification_work_item"))
13477
+ and not isinstance((task.input_data or {}).get("approved_plan_baseline"), dict)
13474
13478
  ):
13475
13479
  analysis_dir = (
13476
13480
  (task.input_data or {}).get("analysis_output_dir", "")
@@ -15462,8 +15466,9 @@ class RuntimeDaemon:
15462
15466
  if task_type == "deployment_merge":
15463
15467
  await self._execute_deployment_merge_job(aj, conn)
15464
15468
  return
15465
- project_info = aj.get("project", {})
15466
- requirement_key = aj.get("requirement_key")
15469
+ project_info = ({"id": job_id, "project_key": f"recording-{job_id}", "name": "Recording suggestions", "repo_url": ""}
15470
+ if task_type == "qa_recording_suggest" else aj.get("project", {}))
15471
+ requirement_key = None if task_type == "qa_recording_suggest" else aj.get("requirement_key")
15467
15472
  agent_override = aj.get("agent_override")
15468
15473
  system_prompt = aj.get("system_prompt", "")
15469
15474
  user_prompt = aj.get("user_prompt", "")
@@ -15491,6 +15496,7 @@ class RuntimeDaemon:
15491
15496
  )
15492
15497
  await project_lock.acquire()
15493
15498
  workspace_execution_lock: _WorkspaceFileLock | None = None
15499
+ recording_workspace = None
15494
15500
 
15495
15501
  try:
15496
15502
  # Report progress: starting
@@ -15553,7 +15559,7 @@ class RuntimeDaemon:
15553
15559
  # 2. Prepare workspace (using project info + requirement branch)
15554
15560
  full_prompt = f"{system_prompt}\n\n{user_prompt}" if system_prompt else user_prompt
15555
15561
  task_timeout = settings.AGENT_TIMEOUT
15556
- if task_type in {"qa_scenario_preview", "qa_script_preview"}:
15562
+ if task_type in {"qa_scenario_preview", "qa_script_preview", "qa_recording_suggest"}:
15557
15563
  try:
15558
15564
  task_timeout = min(
15559
15565
  max(int(input_ctx.get("timeout_seconds", settings.AGENT_TIMEOUT)), 30),
@@ -15583,13 +15589,19 @@ class RuntimeDaemon:
15583
15589
  workspace_source_mode=qa_ws_source.get("mode"),
15584
15590
  workspace_branch=qa_ws_source.get("branch"),
15585
15591
  )
15586
- workspace_execution_lock = await self.workspace_manager.acquire_workspace_execution_lock(
15587
- project_info,
15588
- fake_task,
15589
- )
15590
- workspace_path = await self.workspace_manager.prepare_workspace(
15591
- project_info, fake_task,
15592
- )
15592
+ if task_type == "qa_recording_suggest":
15593
+ import tempfile as _recording_tempfile
15594
+
15595
+ recording_workspace = _recording_tempfile.TemporaryDirectory(prefix="forgexa-recording-suggest-")
15596
+ workspace_path = Path(recording_workspace.name)
15597
+ else:
15598
+ workspace_execution_lock = await self.workspace_manager.acquire_workspace_execution_lock(
15599
+ project_info,
15600
+ fake_task,
15601
+ )
15602
+ workspace_path = await self.workspace_manager.prepare_workspace(
15603
+ project_info, fake_task,
15604
+ )
15593
15605
 
15594
15606
  if task_type == "qa_scenario_generate_prompt" and not input_ctx.get("project_context"):
15595
15607
  local_project_context = _summarize_workspace_source(workspace_path)
@@ -15829,7 +15841,7 @@ class RuntimeDaemon:
15829
15841
  # Pushing here is dangerous because it can propagate stale local branch
15830
15842
  # state even when the AIJob produced no repo changes at all.
15831
15843
  git_info = {}
15832
- if result.status == "success":
15844
+ if result.status == "success" and task_type != "qa_recording_suggest":
15833
15845
  git_info = await self._collect_workspace_git_info(workspace_path)
15834
15846
 
15835
15847
  # 5. Report completion
@@ -15850,7 +15862,7 @@ class RuntimeDaemon:
15850
15862
  scenario_ids=input_ctx.get("scenario_ids", []),
15851
15863
  workspace_path=workspace_path,
15852
15864
  )
15853
- if task_type in {"qa_scenario_generate_prompt", "qa_scenario_preview", "qa_script_preview"}:
15865
+ if task_type in {"qa_scenario_generate_prompt", "qa_scenario_preview", "qa_script_preview", "qa_recording_suggest"}:
15854
15866
  output_content, scenario_items = _prepare_ai_job_output(
15855
15867
  task_type=task_type,
15856
15868
  agent_id=agent.agent_id,
@@ -15913,6 +15925,11 @@ class RuntimeDaemon:
15913
15925
  except Exception:
15914
15926
  pass
15915
15927
  finally:
15928
+ if recording_workspace is not None:
15929
+ try:
15930
+ recording_workspace.cleanup()
15931
+ except OSError:
15932
+ logger.warning("Recording suggestion temporary workspace cleanup failed")
15916
15933
  if workspace_execution_lock is not None:
15917
15934
  workspace_execution_lock.release()
15918
15935
  project_lock.release()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forgexa-cli
3
- Version: 1.82.0
3
+ Version: 1.82.2
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.82.0"
3
+ version = "1.82.2"
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