forgexa-cli 1.75.2__tar.gz → 1.76.0__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.
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/PKG-INFO +1 -1
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/__init__.py +1 -1
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/agent_core.py +6 -2
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/daemon.py +41 -10
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli.egg-info/PKG-INFO +1 -1
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/pyproject.toml +1 -1
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/README.md +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/_build_config.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/_local_bind.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/autoupgrade.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/aws_evidence.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/aws_logs_evidence.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/main.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/py.typed +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/runtime_evidence.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli/zcode_protocol.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli.egg-info/SOURCES.txt +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli.egg-info/dependency_links.txt +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli.egg-info/entry_points.txt +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli.egg-info/requires.txt +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/forgexa_cli.egg-info/top_level.txt +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/setup.cfg +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_auth_and_runtime_commands.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_autoupgrade.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_check_command.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_expiry_warnings_and_revoke.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_local_bind_commands.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_runtime_credentials.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_session_credentials.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_silent_install.py +0 -0
- {forgexa_cli-1.75.2 → forgexa_cli-1.76.0}/tests/test_upgrade_observability.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""forgexa-cli — Forgexa command-line client."""
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.76.0"
|
|
@@ -1324,17 +1324,21 @@ def _kill_proc(proc: asyncio.subprocess.Process) -> None:
|
|
|
1324
1324
|
Owned agents start a new session, so their PID remains the process-group
|
|
1325
1325
|
ID even after the leader exits.
|
|
1326
1326
|
"""
|
|
1327
|
+
process_id = getattr(proc, "pid", None)
|
|
1328
|
+
if type(process_id) is not int or process_id <= 1:
|
|
1329
|
+
return
|
|
1330
|
+
|
|
1327
1331
|
try:
|
|
1328
1332
|
if sys.platform != "win32":
|
|
1329
1333
|
import signal as _signal
|
|
1330
1334
|
try:
|
|
1331
|
-
os.killpg(
|
|
1335
|
+
os.killpg(process_id, _signal.SIGKILL)
|
|
1332
1336
|
except (ProcessLookupError, PermissionError, OSError):
|
|
1333
1337
|
pass
|
|
1334
1338
|
else:
|
|
1335
1339
|
import subprocess as _subprocess
|
|
1336
1340
|
_subprocess.run(
|
|
1337
|
-
["taskkill", "/F", "/T", "/PID", str(
|
|
1341
|
+
["taskkill", "/F", "/T", "/PID", str(process_id)],
|
|
1338
1342
|
capture_output=True,
|
|
1339
1343
|
timeout=5,
|
|
1340
1344
|
**_agent_process_group_kwargs(),
|
|
@@ -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.
|
|
1237
|
+
DAEMON_VERSION = "1.76.0"
|
|
1238
1238
|
|
|
1239
1239
|
|
|
1240
1240
|
def _detect_client_type() -> str:
|
|
@@ -14284,11 +14284,36 @@ class RuntimeDaemon:
|
|
|
14284
14284
|
else:
|
|
14285
14285
|
result.metrics["acceptance_criteria_manual_review_required"] = True
|
|
14286
14286
|
else:
|
|
14287
|
-
ac_list =
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14287
|
+
ac_list = (
|
|
14288
|
+
cm_data.get("acceptance_criteria")
|
|
14289
|
+
if isinstance(cm_data, dict) else None
|
|
14290
|
+
)
|
|
14291
|
+
if (
|
|
14292
|
+
not isinstance(ac_list, list)
|
|
14293
|
+
or not ac_list
|
|
14294
|
+
or any(
|
|
14295
|
+
not isinstance(ac, dict)
|
|
14296
|
+
or not isinstance(ac.get("id"), str)
|
|
14297
|
+
or not ac["id"].strip()
|
|
14298
|
+
or ac.get("status") not in (
|
|
14299
|
+
"covered", "partial", "uncovered", "unverifiable",
|
|
14300
|
+
"not_applicable", "blocked",
|
|
14301
|
+
)
|
|
14302
|
+
for ac in ac_list
|
|
14303
|
+
)
|
|
14304
|
+
):
|
|
14305
|
+
issues.append(
|
|
14306
|
+
"coverage-matrix.json has invalid acceptance criteria: "
|
|
14307
|
+
"coverage_matrix_invalid"
|
|
14308
|
+
)
|
|
14309
|
+
else:
|
|
14310
|
+
uncovered = [ac for ac in ac_list if ac["status"] != "covered"]
|
|
14311
|
+
if uncovered:
|
|
14312
|
+
ids = ", ".join(ac["id"] for ac in uncovered[:5])
|
|
14313
|
+
issues.append(
|
|
14314
|
+
"Uncovered acceptance criteria in "
|
|
14315
|
+
f"coverage-matrix.json: {ids}"
|
|
14316
|
+
)
|
|
14292
14317
|
except (_json.JSONDecodeError, UnicodeDecodeError) as e:
|
|
14293
14318
|
issues.append(f"coverage-matrix.json is not valid JSON: {e}")
|
|
14294
14319
|
elif _requires_structured_artifacts or _requires_e2e_artifacts:
|
|
@@ -15732,7 +15757,6 @@ class RuntimeDaemon:
|
|
|
15732
15757
|
|
|
15733
15758
|
if (
|
|
15734
15759
|
task.node_type == "testing"
|
|
15735
|
-
and (task.input_data or {}).get("requirement_type") == "task"
|
|
15736
15760
|
and all(
|
|
15737
15761
|
issue.startswith("Uncovered acceptance criteria in coverage-matrix.json:")
|
|
15738
15762
|
for issue in issues
|
|
@@ -15740,7 +15764,11 @@ class RuntimeDaemon:
|
|
|
15740
15764
|
):
|
|
15741
15765
|
result.status = "failed"
|
|
15742
15766
|
result.failure_code = "acceptance_criteria_uncovered"
|
|
15743
|
-
result.error =
|
|
15767
|
+
result.error = (
|
|
15768
|
+
f"Acceptance verification is incomplete: {issues[0]}. "
|
|
15769
|
+
"Resolve the unmet criteria or missing test prerequisites, "
|
|
15770
|
+
"then rerun verification."
|
|
15771
|
+
)
|
|
15744
15772
|
result.metrics["validation_issues"] = issues
|
|
15745
15773
|
self._record_testing_telemetry(
|
|
15746
15774
|
workspace_path, task, result, retries_used=attempt
|
|
@@ -15850,7 +15878,6 @@ class RuntimeDaemon:
|
|
|
15850
15878
|
])
|
|
15851
15879
|
if (
|
|
15852
15880
|
task.node_type == "testing"
|
|
15853
|
-
and (task.input_data or {}).get("requirement_type") == "task"
|
|
15854
15881
|
and all(
|
|
15855
15882
|
issue.startswith("Uncovered acceptance criteria in coverage-matrix.json:")
|
|
15856
15883
|
for issue in remaining
|
|
@@ -15858,7 +15885,11 @@ class RuntimeDaemon:
|
|
|
15858
15885
|
):
|
|
15859
15886
|
result.status = "failed"
|
|
15860
15887
|
result.failure_code = "acceptance_criteria_uncovered"
|
|
15861
|
-
result.error =
|
|
15888
|
+
result.error = (
|
|
15889
|
+
f"Acceptance verification is incomplete: {remaining[0]}. "
|
|
15890
|
+
"Resolve the unmet criteria or missing test prerequisites, "
|
|
15891
|
+
"then rerun verification."
|
|
15892
|
+
)
|
|
15862
15893
|
result.metrics["validation_issues"] = remaining
|
|
15863
15894
|
self._record_testing_telemetry(
|
|
15864
15895
|
workspace_path, task, result, retries_used=max_retries
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|