forgexa-cli 1.15.2__tar.gz → 1.15.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.
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/PKG-INFO +1 -1
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli/__init__.py +1 -1
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli/daemon.py +86 -5
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli.egg-info/PKG-INFO +1 -1
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/pyproject.toml +1 -1
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/README.md +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli/_build_config.py +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli/main.py +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli/py.typed +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli.egg-info/SOURCES.txt +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli.egg-info/dependency_links.txt +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli.egg-info/entry_points.txt +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli.egg-info/requires.txt +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/forgexa_cli.egg-info/top_level.txt +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/setup.cfg +0 -0
- {forgexa_cli-1.15.2 → forgexa_cli-1.15.4}/tests/test_auth_and_runtime_commands.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""forgexa-cli — Forgexa command-line client."""
|
|
2
|
-
__version__ = "1.15.
|
|
2
|
+
__version__ = "1.15.4"
|
|
@@ -523,7 +523,7 @@ except (ImportError, ModuleNotFoundError):
|
|
|
523
523
|
# DAEMON_VERSION is the protocol/logic version of the daemon code.
|
|
524
524
|
# Kept in sync with pyproject.toml version via bump-version.sh.
|
|
525
525
|
# CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
|
|
526
|
-
DAEMON_VERSION = "1.15.
|
|
526
|
+
DAEMON_VERSION = "1.15.4"
|
|
527
527
|
|
|
528
528
|
|
|
529
529
|
def _detect_client_type() -> str:
|
|
@@ -7986,9 +7986,41 @@ class RuntimeDaemon:
|
|
|
7986
7986
|
else:
|
|
7987
7987
|
base = workspace_path
|
|
7988
7988
|
|
|
7989
|
+
# --- Read e2e intents from test-intent.json (all requirement types) ---
|
|
7990
|
+
# Not gated by _requires_structured_artifacts so that bugfix with e2e
|
|
7991
|
+
# intents gets the same E2E chain validation as feature/improvement.
|
|
7992
|
+
_e2e_intent_ids: set[str] = set()
|
|
7993
|
+
_analysis_dir = (
|
|
7994
|
+
_input.get("analysis_output_dir")
|
|
7995
|
+
or (_input.get("context") or {}).get("analysis_output_dir")
|
|
7996
|
+
or ""
|
|
7997
|
+
)
|
|
7998
|
+
if _analysis_dir:
|
|
7999
|
+
_ti_path = workspace_path / _analysis_dir / "test-intent.json"
|
|
8000
|
+
if _ti_path.exists():
|
|
8001
|
+
try:
|
|
8002
|
+
_ti_data = _json.loads(
|
|
8003
|
+
_ti_path.read_text(encoding="utf-8")
|
|
8004
|
+
)
|
|
8005
|
+
for _ti in _ti_data.get("intents", []):
|
|
8006
|
+
if (_ti.get("automation_target") or "").lower() == "e2e":
|
|
8007
|
+
_ti_id = (
|
|
8008
|
+
_ti.get("id")
|
|
8009
|
+
or _ti.get("test_id")
|
|
8010
|
+
or _ti.get("intent_id")
|
|
8011
|
+
)
|
|
8012
|
+
if _ti_id:
|
|
8013
|
+
_e2e_intent_ids.add(str(_ti_id))
|
|
8014
|
+
except (_json.JSONDecodeError, UnicodeDecodeError):
|
|
8015
|
+
# test-intent.json parse errors are reported
|
|
8016
|
+
# by the analysis node validation; stay silent here.
|
|
8017
|
+
pass
|
|
8018
|
+
# True when e2e intents exist — drives test-cases.json / cm requirement
|
|
8019
|
+
_requires_e2e_artifacts = bool(_e2e_intent_ids)
|
|
8020
|
+
|
|
7989
8021
|
# --- test-cases.json validation ---
|
|
7990
|
-
# Required for feature/improvement
|
|
7991
|
-
#
|
|
8022
|
+
# Required for feature/improvement (always), or any type with e2e intents
|
|
8023
|
+
# (e.g. a UI bugfix whose test-intent.json has automation_target='e2e').
|
|
7992
8024
|
tc_path = base / "test-cases.json"
|
|
7993
8025
|
if tc_path.exists():
|
|
7994
8026
|
try:
|
|
@@ -8012,9 +8044,58 @@ class RuntimeDaemon:
|
|
|
8012
8044
|
p0_cases = [c for c in cases if c.get("priority") == "P0"]
|
|
8013
8045
|
if not p0_cases:
|
|
8014
8046
|
issues.append("No P0 priority test cases found in test-cases.json")
|
|
8047
|
+
|
|
8048
|
+
# --- E2E conditional chain validation ---
|
|
8049
|
+
# Fires for any type when test-intent.json contains
|
|
8050
|
+
# automation_target='e2e' intents (feature, improvement,
|
|
8051
|
+
# bugfix, ...). Pure backend types without e2e intents
|
|
8052
|
+
# are unaffected.
|
|
8053
|
+
if _e2e_intent_ids:
|
|
8054
|
+
# Check 1: every e2e intent must have >=1 e2e test case
|
|
8055
|
+
_e2e_case_refs: set[str] = set()
|
|
8056
|
+
for _tc in cases:
|
|
8057
|
+
if (_tc.get("test_type") or "").lower() == "e2e":
|
|
8058
|
+
_ref = str(
|
|
8059
|
+
_tc.get("intent_id")
|
|
8060
|
+
or _tc.get("test_intent_id")
|
|
8061
|
+
or ""
|
|
8062
|
+
)
|
|
8063
|
+
if _ref:
|
|
8064
|
+
_e2e_case_refs.add(_ref)
|
|
8065
|
+
_missing_e2e = _e2e_intent_ids - _e2e_case_refs
|
|
8066
|
+
if _missing_e2e:
|
|
8067
|
+
issues.append(
|
|
8068
|
+
f"test-cases.json missing e2e test cases for intents: "
|
|
8069
|
+
f"{sorted(_missing_e2e)}. Each test intent with "
|
|
8070
|
+
f"automation_target='e2e' must have at least one "
|
|
8071
|
+
f"test_type='e2e' test case."
|
|
8072
|
+
)
|
|
8073
|
+
|
|
8074
|
+
# Check 2: every e2e test case must have non-empty
|
|
8075
|
+
# script_content (and script_path file must exist if set)
|
|
8076
|
+
for _tc in cases:
|
|
8077
|
+
if (_tc.get("test_type") or "").lower() != "e2e":
|
|
8078
|
+
continue
|
|
8079
|
+
_tc_id = _tc.get("id", "?")
|
|
8080
|
+
_script = (_tc.get("script_content") or "").strip()
|
|
8081
|
+
if not _script:
|
|
8082
|
+
issues.append(
|
|
8083
|
+
f"E2E test case {_tc_id} has empty 'script_content'. "
|
|
8084
|
+
f"You MUST generate the Playwright TypeScript script "
|
|
8085
|
+
f"and embed the full content in script_content."
|
|
8086
|
+
)
|
|
8087
|
+
else:
|
|
8088
|
+
_sp = (_tc.get("script_path") or "").strip()
|
|
8089
|
+
if _sp:
|
|
8090
|
+
_sp_full = workspace_path / _sp
|
|
8091
|
+
if not _sp_full.exists():
|
|
8092
|
+
issues.append(
|
|
8093
|
+
f"E2E test case {_tc_id} script_path "
|
|
8094
|
+
f"'{_sp}' does not exist on disk."
|
|
8095
|
+
)
|
|
8015
8096
|
except (_json.JSONDecodeError, UnicodeDecodeError) as e:
|
|
8016
8097
|
issues.append(f"test-cases.json is not valid JSON: {e}")
|
|
8017
|
-
elif _requires_structured_artifacts:
|
|
8098
|
+
elif _requires_structured_artifacts or _requires_e2e_artifacts:
|
|
8018
8099
|
issues.append(f"test-cases.json not found in {doc_dir or 'workspace root'}")
|
|
8019
8100
|
|
|
8020
8101
|
# --- coverage-matrix.json validation ---
|
|
@@ -8029,7 +8110,7 @@ class RuntimeDaemon:
|
|
|
8029
8110
|
issues.append(f"Uncovered acceptance criteria in coverage-matrix.json: {ids}")
|
|
8030
8111
|
except (_json.JSONDecodeError, UnicodeDecodeError) as e:
|
|
8031
8112
|
issues.append(f"coverage-matrix.json is not valid JSON: {e}")
|
|
8032
|
-
elif _requires_structured_artifacts:
|
|
8113
|
+
elif _requires_structured_artifacts or _requires_e2e_artifacts:
|
|
8033
8114
|
issues.append(f"coverage-matrix.json not found in {doc_dir or 'workspace root'}")
|
|
8034
8115
|
|
|
8035
8116
|
# --- test-report.md validation ---
|
|
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
|