fix(cli): restore context show rich panels
CI / push-validation (pull_request) Successful in 20s
CI / helm (pull_request) Successful in 23s
CI / build (pull_request) Successful in 26s
CI / lint (pull_request) Failing after 28s
CI / quality (pull_request) Successful in 42s
CI / e2e_tests (pull_request) Successful in 2m59s
CI / typecheck (pull_request) Successful in 4m0s
CI / integration_tests (pull_request) Successful in 4m0s
CI / security (pull_request) Successful in 4m4s
CI / coverage (pull_request) Has been skipped
CI / unit_tests (pull_request) Failing after 5m41s
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped

ISSUES CLOSED: #6323
This commit is contained in:
2026-04-12 19:19:52 +00:00
parent 636bb4a547
commit 6f2b3ec8b4
3 changed files with 96 additions and 17 deletions
+4 -5
View File
@@ -7,11 +7,12 @@ CLI commands using an in-memory SQLite database.
from __future__ import annotations
import json
import yaml
from contextlib import suppress
from io import StringIO
from typing import Any
from unittest.mock import MagicMock, patch
import yaml
from behave import given, then, when # type: ignore[import-untyped]
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
@@ -690,10 +691,8 @@ def step_issue6323_seed_usage(context: Any, project: str) -> None:
svc._hot.clear()
svc._warm.clear()
svc._cold.clear()
try:
svc._budget.max_tokens_hot = 12_000
except Exception: # pragma: no cover - fallback for unexpected attribute errors
pass
with suppress(Exception):
svc._budget.max_tokens_hot = 12_000 # pragma: no cover - fallback guard
svc.store(
TieredFragment(
@@ -898,20 +898,31 @@ def context_show(
command_name = "project context show"
success_message = "Context policy loaded"
include_resources_display = (
", ".join(include_resources) if include_resources else "(all)"
)
exclude_paths_display = ", ".join(exclude_paths) if exclude_paths else "(none)"
include_paths_display = ", ".join(include_paths)
exclude_resources_display = ", ".join(exclude_resources)
query_limit_display = str(query_limit) if query_limit is not None else "(no limit)"
summary_tokens_display = (
str(summary_tokens) if summary_tokens is not None else "(auto)"
)
if fmt == OutputFormat.RICH:
policy_lines = [
f"[cyan]Project:[/cyan] {project}",
f"[blue]View:[/blue] {active_view}",
f"[green]Include:[/green] {', '.join(include_resources) if include_resources else '(all)'}",
f"[yellow]Exclude:[/yellow] {', '.join(exclude_paths) if exclude_paths else '(none)'}",
f"[green]Include:[/green] {include_resources_display}",
f"[yellow]Exclude:[/yellow] {exclude_paths_display}",
]
if include_paths:
policy_lines.append(
f"[green]Include paths:[/green] {', '.join(include_paths)}"
f"[green]Include paths:[/green] {include_paths_display}"
)
if exclude_resources:
policy_lines.append(
f"[yellow]Exclude resources:[/yellow] {', '.join(exclude_resources)}"
f"[yellow]Exclude resources:[/yellow] {exclude_resources_display}"
)
limits = structured_data["limits"]
@@ -919,25 +930,80 @@ def context_show(
f"[magenta]Hot Tokens:[/magenta] {limits['hot_max_tokens']:,}",
f"[magenta]Warm Decisions:[/magenta] {limits['warm_max_decisions']:,}",
f"[magenta]Cold Decisions:[/magenta] {limits['cold_max_decisions']:,}",
f"[cyan]Query Limit:[/cyan] {limits['query_limit'] if limits['query_limit'] is not None else '(no limit)'}",
f"[cyan]Query Limit:[/cyan] {query_limit_display}",
f"[cyan]Max File Size:[/cyan] {limits['max_file_size']}",
f"[cyan]Max Total Size:[/cyan] {limits['max_total_size']}",
]
summarization = structured_data["summarization"]
summarization_lines = [
f"[green]Enabled:[/green] {'yes' if summarization['enabled'] else 'no'}",
f"[blue]Max Tokens:[/blue] {summarization['max_tokens'] if summarization['max_tokens'] is not None else '(auto)'}",
"[green]Enabled:[/green] yes"
if summarization["enabled"]
else "[green]Enabled:[/green] no",
f"[blue]Max Tokens:[/blue] {summary_tokens_display}",
]
usage = structured_data["current_usage"]
usage_lines = [
f"[blue]Hot Context:[/blue] {usage['hot_context_tokens']:,} / {usage['hot_context_limit']:,}",
f"[blue]Warm Entries:[/blue] {usage['warm_entries']:,} / {usage['warm_limit']:,}",
f"[blue]Cold Entries:[/blue] {usage['cold_entries']:,} / {usage['cold_limit']:,}",
(
f"[blue]Hot Context:[/blue] "
f"{usage['hot_context_tokens']:,} / {usage['hot_context_limit']:,}"
),
(
f"[blue]Warm Entries:[/blue] "
f"{usage['warm_entries']:,} / {usage['warm_limit']:,}"
),
(
f"[blue]Cold Entries:[/blue] "
f"{usage['cold_entries']:,} / {usage['cold_limit']:,}"
),
f"[green]Indexed Resources:[/green] {usage['indexed_resources']:,}",
]
raw_policy_blob = _load_policy_json(session_factory, project) or {}
execution_environment = raw_policy_blob.get("execution_environment")
env_priority = raw_policy_blob.get("execution_env_priority")
execution_lines: list[str] = []
if execution_environment:
execution_lines.append(f"[cyan]Environment:[/cyan] {execution_environment}")
if env_priority:
execution_lines.append(f"[cyan]Priority:[/cyan] {env_priority}")
temporal_scope = acms.get("temporal_scope", "current")
auto_refresh = "yes" if acms.get("auto_refresh", True) else "no"
strategies = acms.get("strategies") or []
strategies_display = ", ".join(strategies) if strategies else "(default)"
default_breadth = acms.get("default_breadth", _DEFAULT_BREADTH)
default_depth = acms.get("default_depth", _DEFAULT_DEPTH)
depth_gradient = acms.get("depth_gradient") or {}
skeleton_ratio = acms.get("skeleton_ratio", _DEFAULT_SKELETON_RATIO)
def _gradient_key(entry: tuple[Any, Any]) -> int | str:
hop, _ = entry
try:
return int(str(hop))
except (TypeError, ValueError):
return str(hop)
if depth_gradient:
gradient_parts = [
f"{hop}:{value}"
for hop, value in sorted(depth_gradient.items(), key=_gradient_key)
]
gradient_display = ", ".join(gradient_parts)
else:
gradient_display = "(none)"
pipeline_lines = [
f"[cyan]Temporal Scope:[/cyan] {temporal_scope}",
f"[cyan]Auto Refresh:[/cyan] {auto_refresh}",
f"[cyan]Strategies:[/cyan] {strategies_display}",
f"[cyan]Default Breadth:[/cyan] {default_breadth}",
f"[cyan]Default Depth:[/cyan] {default_depth}",
f"[cyan]Depth gradient:[/cyan] {gradient_display}",
f"[cyan]Skeleton Ratio:[/cyan] {skeleton_ratio}",
]
console.print(
Panel("\n".join(policy_lines), title="Context Policy", expand=False)
)
@@ -948,6 +1014,17 @@ def context_show(
console.print(
Panel("\n".join(usage_lines), title="Current Usage", expand=False)
)
if execution_lines:
console.print(
Panel(
"\n".join(execution_lines),
title="Execution Environment",
expand=False,
)
)
console.print(
Panel("\n".join(pipeline_lines), title="ACMS Pipeline", expand=False)
)
console.print("[green]✓ OK[/green] Context policy loaded")
return
+5 -2
View File
@@ -15,10 +15,11 @@ from __future__ import annotations
import json
import time
from collections.abc import Mapping, Sequence
from datetime import datetime
from enum import Enum, StrEnum
from io import StringIO
from typing import Any, Mapping, Sequence
from typing import Any
import yaml
from rich.console import Console
@@ -315,7 +316,9 @@ def format_output(
rendered = _format_plain(safe_data)
message_lines = _format_plain_messages(plain_pairs)
if message_lines:
rendered = (rendered + "\n" if rendered else "") + "\n".join(message_lines)
prefix = f"{rendered}\n" if rendered else ""
message_block = "\n".join(message_lines)
rendered = f"{prefix}{message_block}"
sys.stdout.write(rendered + "\n")
sys.stdout.flush()
return ""