forgexa-cli 1.57.5__tar.gz → 1.57.6__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 (29) hide show
  1. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/PKG-INFO +1 -1
  2. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/__init__.py +1 -1
  3. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/daemon.py +95 -20
  4. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli.egg-info/PKG-INFO +1 -1
  5. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/pyproject.toml +1 -1
  6. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/README.md +0 -0
  7. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/_build_config.py +0 -0
  8. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/_local_bind.py +0 -0
  9. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/agent_core.py +0 -0
  10. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/autoupgrade.py +0 -0
  11. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/main.py +0 -0
  12. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/py.typed +0 -0
  13. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/runtime_evidence.py +0 -0
  14. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli/zcode_protocol.py +0 -0
  15. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli.egg-info/SOURCES.txt +0 -0
  16. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli.egg-info/dependency_links.txt +0 -0
  17. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli.egg-info/entry_points.txt +0 -0
  18. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli.egg-info/requires.txt +0 -0
  19. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/forgexa_cli.egg-info/top_level.txt +0 -0
  20. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/setup.cfg +0 -0
  21. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_auth_and_runtime_commands.py +0 -0
  22. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_autoupgrade.py +0 -0
  23. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_check_command.py +0 -0
  24. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_expiry_warnings_and_revoke.py +0 -0
  25. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_local_bind_commands.py +0 -0
  26. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_runtime_credentials.py +0 -0
  27. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_session_credentials.py +0 -0
  28. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/tests/test_silent_install.py +0 -0
  29. {forgexa_cli-1.57.5 → forgexa_cli-1.57.6}/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.57.5
3
+ Version: 1.57.6
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.57.5"
2
+ __version__ = "1.57.6"
@@ -1150,7 +1150,7 @@ except (ImportError, ModuleNotFoundError):
1150
1150
  # DAEMON_VERSION is the protocol/logic version of the daemon code.
1151
1151
  # Kept in sync with pyproject.toml version via bump-version.sh.
1152
1152
  # CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
1153
- DAEMON_VERSION = "1.57.5"
1153
+ DAEMON_VERSION = "1.57.6"
1154
1154
 
1155
1155
 
1156
1156
  def _detect_client_type() -> str:
@@ -1736,6 +1736,7 @@ def _filter_local_bind_task_result(result: "TaskResult") -> None:
1736
1736
  result.stdout = ""
1737
1737
  result.stderr = ""
1738
1738
  result.observations = []
1739
+ result.metrics.pop("validation_issues", None)
1739
1740
  critic_review = result.critic_review
1740
1741
  if isinstance(critic_review, dict) and isinstance(critic_review.get("result"), dict):
1741
1742
  result.critic_review = {
@@ -1755,8 +1756,11 @@ def _filter_local_bind_task_result(result: "TaskResult") -> None:
1755
1756
  }
1756
1757
  if result.error:
1757
1758
  result.error = (
1758
- "Local task failed. Review this task in Forgexa Desktop on the "
1759
- "running device."
1759
+ "Task verification is incomplete: acceptance criteria remain uncovered. "
1760
+ "Review the validation log in Forgexa Desktop; resolve the criteria and "
1761
+ "commit or stash local changes before retrying."
1762
+ if result.failure_code == "acceptance_criteria_uncovered"
1763
+ else "Local task failed. Review this task in Forgexa Desktop on the running device."
1760
1764
  )
1761
1765
 
1762
1766
  def _prepare_ai_job_output(
@@ -5726,7 +5730,9 @@ class ProcessManager:
5726
5730
  @staticmethod
5727
5731
  def agent_failure_kind(result: "TaskResult") -> str | None:
5728
5732
  """Classify a fallback-eligible failure without conflating its cause."""
5729
- if result.failure_code in {"all_agents_rate_limited", "all_agents_unavailable"}:
5733
+ if result.failure_code in {
5734
+ "all_agents_rate_limited", "all_agents_unavailable", "acceptance_criteria_uncovered",
5735
+ }:
5730
5736
  return None
5731
5737
  if result.failure_code == "agent_platform_unsupported":
5732
5738
  return "agent_unavailable"
@@ -13052,7 +13058,7 @@ class RuntimeDaemon:
13052
13058
  # are *optional*: if they exist they are validated, but their
13053
13059
  # absence is not an error (the agent only writes regression
13054
13060
  # tests + test-report.md).
13055
- _skip_test_artifacts = False
13061
+ _skip_test_artifacts = req_type == "task"
13056
13062
  _requires_structured_artifacts = False
13057
13063
  # Scope-adaptive pipeline (Phase 1): a content_only change
13058
13064
  # scope (analysis-predicted, machine-verified server-side)
@@ -13074,19 +13080,28 @@ class RuntimeDaemon:
13074
13080
  # importable (standalone vendored daemon execution).
13075
13081
  _skip_test_artifacts = True
13076
13082
 
13077
- # The type-profile test_coverage skip (e.g. "task") is a
13078
- # lightweight-verify default — NOT an exemption from the e2e
13079
- # grounding chain or from a frozen enforce-mode artifact
13080
- # contract that was injected into the prompt. Both apply to
13081
- # every requirement type: SI-1616 (task verify) failed the e2e
13082
- # evidence chain because the skip semantics diverged between
13083
- # server daemons (profile skip applied) and standalone desktop
13084
- # daemons (profile import fails → nothing skipped).
13083
+ # Keep e2e evidence validation active for any requirement type.
13084
+ # An enforced policy requires artifacts only when the analysis
13085
+ # contract expects test intent or the analysis supplied one.
13086
+ _analysis_dir = (
13087
+ input_data.get("analysis_output_dir")
13088
+ or (input_data.get("context") or {}).get("analysis_output_dir")
13089
+ or ""
13090
+ )
13091
+ _has_test_intent = bool(_analysis_dir) and (
13092
+ workspace_path / str(_analysis_dir) / "test-intent.json"
13093
+ ).is_file()
13085
13094
  if (
13086
13095
  _skip_test_artifacts
13087
13096
  and _change_scope != "content_only"
13088
13097
  and (
13089
- (qa_policy or {}).get("enforcement") == "enforce"
13098
+ (
13099
+ (qa_policy or {}).get("enforcement") == "enforce"
13100
+ and (
13101
+ "test-intent.json" in _get_analysis_outputs_for_type(req_type, _change_scope)
13102
+ or _has_test_intent
13103
+ )
13104
+ )
13090
13105
  or _testing_intents_have_e2e(workspace_path, input_data)
13091
13106
  )
13092
13107
  ):
@@ -13261,15 +13276,30 @@ class RuntimeDaemon:
13261
13276
  ))
13262
13277
 
13263
13278
  # --- coverage-matrix.json validation ---
13279
+ if req_type == "task":
13280
+ result.metrics.pop("acceptance_criteria_manual_review_required", None)
13264
13281
  cm_path = base / "coverage-matrix.json"
13265
13282
  if cm_path.exists():
13266
13283
  try:
13267
- cm_data = _json.loads(cm_path.read_text(encoding="utf-8"))
13268
- ac_list = cm_data.get("acceptance_criteria", [])
13269
- uncovered = [ac for ac in ac_list if ac.get("status") != "covered"]
13270
- if uncovered:
13271
- ids = ", ".join(ac.get("id", "?") for ac in uncovered[:5])
13272
- issues.append(f"Uncovered acceptance criteria in coverage-matrix.json: {ids}")
13284
+ cm_content = cm_path.read_text(encoding="utf-8")
13285
+ cm_data = _json.loads(cm_content)
13286
+ if req_type == "task":
13287
+ coverage = runtime_evidence.parse_acceptance_criteria_coverage_artifacts(
13288
+ _json.dumps(_tc_data) if _tc_data is not None else None,
13289
+ cm_content,
13290
+ )
13291
+ links = coverage.get("coverage_links") or []
13292
+ if coverage.get("collection_status") != "completed" or not links:
13293
+ reason = coverage.get("failure_reason") or "coverage_matrix_empty"
13294
+ issues.append(f"coverage-matrix.json has invalid acceptance criteria: {reason}")
13295
+ else:
13296
+ result.metrics["acceptance_criteria_manual_review_required"] = True
13297
+ else:
13298
+ ac_list = cm_data.get("acceptance_criteria", [])
13299
+ uncovered = [ac for ac in ac_list if ac.get("status") != "covered"]
13300
+ if uncovered:
13301
+ ids = ", ".join(ac.get("id", "?") for ac in uncovered[:5])
13302
+ issues.append(f"Uncovered acceptance criteria in coverage-matrix.json: {ids}")
13273
13303
  except (_json.JSONDecodeError, UnicodeDecodeError) as e:
13274
13304
  issues.append(f"coverage-matrix.json is not valid JSON: {e}")
13275
13305
  elif _requires_structured_artifacts or _requires_e2e_artifacts:
@@ -14693,6 +14723,29 @@ class RuntimeDaemon:
14693
14723
  )
14694
14724
  return result # All validations passed
14695
14725
 
14726
+ if getattr(task, "workspace_resolution", None) == "local_bind":
14727
+ _append_local_bind_output_log(task.task_id, [
14728
+ "[daemon] Output validation found these issues:",
14729
+ *[f"[daemon] {issue}" for issue in issues],
14730
+ ])
14731
+
14732
+ if (
14733
+ task.node_type == "testing"
14734
+ and (task.input_data or {}).get("requirement_type") == "task"
14735
+ and all(
14736
+ issue.startswith("Uncovered acceptance criteria in coverage-matrix.json:")
14737
+ for issue in issues
14738
+ )
14739
+ ):
14740
+ result.status = "failed"
14741
+ result.failure_code = "acceptance_criteria_uncovered"
14742
+ result.error = f"Task verification is incomplete: {issues[0]}"
14743
+ result.metrics["validation_issues"] = issues
14744
+ self._record_testing_telemetry(
14745
+ workspace_path, task, result, retries_used=attempt
14746
+ )
14747
+ return result
14748
+
14696
14749
  issues_text = "\n".join(f"- {iss}" for iss in issues)
14697
14750
  logger.warning(
14698
14751
  "Validation gate: %d issues found for task %s (attempt %d/%d):\n%s",
@@ -14786,6 +14839,27 @@ class RuntimeDaemon:
14786
14839
  )
14787
14840
  remaining = self._validate_outputs(workspace_path, task, result)
14788
14841
  if remaining:
14842
+ if getattr(task, "workspace_resolution", None) == "local_bind":
14843
+ _append_local_bind_output_log(task.task_id, [
14844
+ "[daemon] Output validation remains incomplete:",
14845
+ *[f"[daemon] {issue}" for issue in remaining],
14846
+ ])
14847
+ if (
14848
+ task.node_type == "testing"
14849
+ and (task.input_data or {}).get("requirement_type") == "task"
14850
+ and all(
14851
+ issue.startswith("Uncovered acceptance criteria in coverage-matrix.json:")
14852
+ for issue in remaining
14853
+ )
14854
+ ):
14855
+ result.status = "failed"
14856
+ result.failure_code = "acceptance_criteria_uncovered"
14857
+ result.error = f"Task verification is incomplete: {remaining[0]}"
14858
+ result.metrics["validation_issues"] = remaining
14859
+ self._record_testing_telemetry(
14860
+ workspace_path, task, result, retries_used=max_retries
14861
+ )
14862
+ return result
14789
14863
  # Distinguish blocking artifact-contract failures from advisory syntax
14790
14864
  # warnings. Evidence coverage and references are release-blocking even
14791
14865
  # when the file itself exists.
@@ -14799,6 +14873,7 @@ class RuntimeDaemon:
14799
14873
  "not found",
14800
14874
  "is empty",
14801
14875
  "not valid json",
14876
+ "invalid acceptance criteria",
14802
14877
  "case_evidence",
14803
14878
  "test-evidence.json has no",
14804
14879
  "evidence item",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forgexa-cli
3
- Version: 1.57.5
3
+ Version: 1.57.6
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.57.5"
3
+ version = "1.57.6"
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