diff --git a/features/issue_6323_coverage_boost.feature b/features/issue_6323_coverage_boost.feature new file mode 100644 index 000000000..b228c6128 --- /dev/null +++ b/features/issue_6323_coverage_boost.feature @@ -0,0 +1,56 @@ +Feature: Issue 6323 coverage — _format_size edge cases and formatting helper paths + + Background: + Given a project context CLI in-memory database is initialized + + @tdd_issue @tdd_issue_6323 + Scenario Outline: _format_size covers all size display branches + When I invoke the _format_size helper with "" + Then the _format_size result should be "" + + Examples: + | input | expected | + | None | (no limit) | + | 0 | 0 bytes | + | 1 | 1 byte | + | 500 | 500 bytes | + | 1024 | 1 KB | + | 1536 | 1.5 KB | + | 1572864 | 1.5 MB | + | 1073741824 | 1 GB | + | 2684354560 | 2.5 GB | + | 1099511627776 | 1 TB | + | 1649267441664 | 1.5 TB | + + @tdd_issue @tdd_issue_6323 + Scenario: format_output wraps a dict message correctly in the json envelope + When I invoke format_output json with dict message level "warn" text "dict-msg-test" + Then the json envelope contains dict message with level "warn" text "dict-msg-test" + + @tdd_issue @tdd_issue_6323 + Scenario: format_output raises ValueError for a dict message missing required keys + When I invoke format_output json with malformed dict message + Then a ValueError is raised for the malformed message + + @tdd_issue @tdd_issue_6323 + Scenario: format_output plain output with empty-level dict message omits bracket prefix + When I invoke format_output plain with empty-level dict message text "no-prefix-plain" + Then the plain output contains "no-prefix-plain" without bracket prefix + + @tdd_issue @tdd_issue_6323 + Scenario: context show rich renders Execution Environment panel when policy blob has env set + Given a project "local/cov-ee" exists for context CLI + And issue 6323 project context sample is configured for "local/cov-ee" + And the context tier service has sample usage data for "local/cov-ee" + When I run context show rich on "local/cov-ee" with execution environment and integer depth gradient + Then the context show command should succeed + And the context show output contains "Execution Environment" + + @tdd_issue @tdd_issue_6323 + Scenario: context show rich handles depth gradient keys that cannot be parsed as integers + Given a project "local/cov-dg" exists for context CLI + And issue 6323 project context sample is configured for "local/cov-dg" + And the context tier service has sample usage data for "local/cov-dg" + When I run context show rich on "local/cov-dg" with non-integer depth gradient keys + Then the context show command should succeed + And the context show output contains "ACMS Pipeline" diff --git a/features/steps/project_context_cli_steps.py b/features/steps/project_context_cli_steps.py index 8362e15b7..982cae682 100644 --- a/features/steps/project_context_cli_steps.py +++ b/features/steps/project_context_cli_steps.py @@ -797,3 +797,201 @@ def step_issue6323_assert_json(context: Any, project: str, view: str) -> None: def step_issue6323_assert_yaml(context: Any, project: str, view: str) -> None: parsed = _issue6323_parse_yaml(context) _issue6323_assert_payload(parsed, context.issue6323_expected, project, view) + + +# -------------------------------------------------------------------------- +# Issue 6323 coverage boost — _format_size edge cases +# -------------------------------------------------------------------------- + + +@when('I invoke the _format_size helper with "{input_val}"') +def step_invoke_format_size_helper(context: Any, input_val: str) -> None: + from cleveragents.cli.commands.project_context import _format_size + + val: int | None = None if input_val == "None" else int(input_val) + context.format_size_result = _format_size(val) + + +@then('the _format_size result should be "{expected}"') +def step_assert_format_size_helper_result(context: Any, expected: str) -> None: + assert context.format_size_result == expected, ( + f"Expected {expected!r}, got {context.format_size_result!r}" + ) + + +# -------------------------------------------------------------------------- +# Issue 6323 coverage boost — format_output dict message paths +# -------------------------------------------------------------------------- + + +@when('I invoke format_output json with dict message level "{level}" text "{text}"') +def step_invoke_format_output_dict_msg(context: Any, level: str, text: str) -> None: + import io + import sys + + from cleveragents.cli.formatting import format_output + + buf = io.StringIO() + old = sys.stdout + sys.stdout = buf + try: + format_output( + {"k": "v"}, + "json", + command="cov-test", + status="ok", + exit_code=0, + messages=[{"level": level, "text": text}], + ) + finally: + sys.stdout = old + context.cov_json_output = buf.getvalue() + + +@then('the json envelope contains dict message with level "{level}" text "{text}"') +def step_assert_json_envelope_dict_msg(context: Any, level: str, text: str) -> None: + parsed = json.loads(context.cov_json_output.strip()) + msgs = parsed.get("messages", []) + assert any( + isinstance(m, dict) and m.get("level") == level and m.get("text") == text + for m in msgs + ), f"Expected dict message with level={level!r} text={text!r} in {msgs!r}" + + +@when("I invoke format_output json with malformed dict message") +def step_invoke_format_output_malformed_dict(context: Any) -> None: + import io + import sys + + from cleveragents.cli.formatting import format_output + + buf = io.StringIO() + old = sys.stdout + sys.stdout = buf + context.cov_raised = None + try: + format_output( + {"k": "v"}, + "json", + command="cov-test", + status="ok", + exit_code=0, + messages=[{"bad_key": "missing level and text"}], + ) + except ValueError as exc: + context.cov_raised = str(exc) + finally: + sys.stdout = old + + +@then("a ValueError is raised for the malformed message") +def step_assert_value_error_malformed_msg(context: Any) -> None: + assert context.cov_raised is not None, "Expected ValueError but none was raised" + + +@when('I invoke format_output plain with empty-level dict message text "{text}"') +def step_invoke_format_output_plain_empty_level(context: Any, text: str) -> None: + import io + import sys + + from cleveragents.cli.formatting import format_output + + buf = io.StringIO() + old = sys.stdout + sys.stdout = buf + try: + format_output( + {}, + "plain", + command="cov-test", + status="ok", + exit_code=0, + messages=[{"level": "", "text": text}], + ) + finally: + sys.stdout = old + context.cov_plain_output = buf.getvalue() + + +@then('the plain output contains "{text}" without bracket prefix') +def step_assert_plain_no_bracket_prefix(context: Any, text: str) -> None: + output = context.cov_plain_output + assert text in output, f"Expected {text!r} in plain output {output!r}" + for line in output.strip().split("\n"): + if text in line: + assert not line.startswith("["), ( + f"Line should not start with '[': {line!r}" + ) + + +# -------------------------------------------------------------------------- +# Issue 6323 coverage boost — rich output paths (execution env, depth gradient) +# -------------------------------------------------------------------------- + +_COV_ACMS_BASE: dict[str, Any] = { + "hot_max_tokens": 8192, + "warm_max_decisions": 50, + "cold_max_decisions": 200, + "summarize": True, + "temporal_scope": "current", + "auto_refresh": True, + "default_breadth": 3, + "default_depth": 3, + "skeleton_ratio": 0.15, + "strategies": [], +} + + +@when( + 'I run context show rich on "{project}" with execution environment' + " and integer depth gradient" +) +def step_ctx_show_rich_ee_int_gradient(context: Any, project: str) -> None: + from cleveragents.cli.commands.project_context import context_show + + acms = dict(_COV_ACMS_BASE) + acms["depth_gradient"] = {"1": 0.8, "2": 0.5} + with ( + patch( + "cleveragents.cli.commands.project_context._load_policy_json", + return_value={ + "execution_environment": "host", + "execution_env_priority": "high", + }, + ), + patch( + "cleveragents.cli.commands.project_context._read_acms_config", + return_value=acms, + ), + ): + _run_with_container( + context, context_show, project=project, view=None, output_format="rich" + ) + + +@when('I run context show rich on "{project}" with non-integer depth gradient keys') +def step_ctx_show_rich_str_gradient(context: Any, project: str) -> None: + from cleveragents.cli.commands.project_context import context_show + + acms = dict(_COV_ACMS_BASE) + acms["depth_gradient"] = {"hop_a": 0.8, "hop_b": 0.5} + with ( + patch( + "cleveragents.cli.commands.project_context._load_policy_json", + return_value=None, + ), + patch( + "cleveragents.cli.commands.project_context._read_acms_config", + return_value=acms, + ), + ): + _run_with_container( + context, context_show, project=project, view=None, output_format="rich" + ) + + +@then('the context show output contains "{text}"') +def step_ctx_show_output_contains(context: Any, text: str) -> None: + assert text in context.ctx_output, ( + f"Expected {text!r} in context show output.\nGot:\n{context.ctx_output}" + )