Compare commits

...

3 Commits

Author SHA1 Message Date
HAL9000 19d683922a fix(cli): fix integration test and add changelog for actor context list regex (#6500)
- Fix Robot Framework integration test Actor Context List Supports Regex Filter
  to use --context-dir with named actor context subdirectories instead of
  project context files, resolving the CI integration_tests failure
- Add CHANGELOG.md entry for the [REGEX] positional argument feature
- Rebase on master to resolve merge conflicts

ISSUES CLOSED: #6500
2026-05-09 02:43:11 +00:00
HAL9000 ce372625dd fix(cli): fix integration test and add changelog for actor context list regex (#6500)
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 54s
CI / benchmark-regression (pull_request) Failing after 1m17s
CI / helm (pull_request) Successful in 1m4s
CI / push-validation (pull_request) Successful in 55s
CI / build (pull_request) Successful in 1m8s
CI / quality (pull_request) Successful in 1m45s
CI / security (pull_request) Successful in 1m50s
CI / typecheck (pull_request) Successful in 2m25s
CI / integration_tests (pull_request) Successful in 3m54s
CI / e2e_tests (pull_request) Successful in 4m37s
CI / unit_tests (pull_request) Failing after 7m41s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 4s
- Fix Robot Framework integration test Actor Context List Supports Regex Filter
  to use --context-dir with named actor context subdirectories instead of
  project context files, resolving the CI integration_tests failure
- Add CHANGELOG.md entry for the [REGEX] positional argument feature
- Rebase on master to resolve merge conflicts
2026-05-05 19:56:00 +00:00
HAL9000 b272abf358 fix(cli): add [REGEX] positional argument to actor context list (#6500)
ISSUES CLOSED: #6500
2026-05-05 19:26:02 +00:00
7 changed files with 174 additions and 7 deletions
+6
View File
@@ -343,6 +343,12 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
had `@tdd_expected_fail` removed and now run as permanent regression guards.
Net result: 629 features active in CI (up from ~545), zero `@skip` tags remain.
- **Actor Context List Regex Filter** (#6500): `agents actor context list` now
accepts an optional `[REGEX]` positional argument to filter listed named
contexts by a regular expression pattern. Invalid patterns are reported with
a clear error message. The deprecated `agents context list` alias receives
the same filtering capability.
- **Git Worktree Sandbox Apply** (#4454): The `plan apply` command now merges
LLM-generated changes via `git merge` from an isolated worktree branch
instead of flat `shutil.copy2`. Displays spec-aligned Apply Summary
+1
View File
@@ -31,3 +31,4 @@ Below are some of the specific details of various contributions.
* HAL 9000 has contributed comprehensive milestone documentation for v3.6.0 (Advanced Concepts & Deferred Features) and v3.7.0 (TUI Implementation) (PR #9903): split into sub-documents covering context strategies, LLM backends, resource types, A2A rename, container tool execution, scope chain resolution, cost/safety budgets, E2E workflow tests, code review examples, plugin architecture, TUI layout, persona system, reference/command input, session management, configuration, and TuiMaterializer integration.
* HAL 9000 has contributed the LLMTraceRepository data-integrity fix (PR #8185 / issue #7505): replaced the unconditional `session.commit()` in `LLMTraceRepository.save()` with a dual-path implementation that respects the UnitOfWork pattern — flushing only when an external session is provided, and flushing + committing + closing when operating standalone. This eliminates premature transaction commits, loss of rollback capability, and a docstring/implementation mismatch.
* HAL 9000 has contributed the ACMS Index Data Model and File Traversal Engine (PR #9664 / issue #9579): foundational data structures for indexed context entries with hot/warm/cold/archive storage tier classification, tag system, and a timeout-safe chunked file traversal engine for large projects with 10,000+ files.
* HAL 9000 has contributed the actor context list regex filter feature (PR #6741 / issue #6500): added an optional `[REGEX]` positional argument to `agents actor context list` command to filter named contexts by a regular expression pattern, including BDD test coverage and Robot Framework integration test with `--context-dir` support for isolation.
+9
View File
@@ -6,6 +6,15 @@ Feature: Actor context clear, remove, export, and import commands
Background:
Given a temporary context directory for actor context tests
@actor_context_list_regex
Scenario: List actor contexts filtered by regex
Given an actor context named "docs" exists
And an actor context named "notes" exists
When I run actor context list "docs"
Then the actor context list command should succeed
And the list output should contain "docs"
And the list output should not contain "notes"
# ── context clear ─────────────────────────────────────────
Scenario: Clear a named actor context
@@ -105,6 +105,36 @@ def step_create_json_file_with_name(context, name):
context.import_file.write_text(json.dumps(data, indent=2), encoding="utf-8")
# ---------------------------------------------------------------------------
# When — list
# ---------------------------------------------------------------------------
@when('I run actor context list "{pattern}"')
def step_list_with_pattern(context, pattern):
context.result = context.runner.invoke(
actor_context_app,
[
"list",
pattern,
"--context-dir",
str(context.context_dir),
],
)
@when("I run actor context list without a pattern")
def step_list_without_pattern(context):
context.result = context.runner.invoke(
actor_context_app,
[
"list",
"--context-dir",
str(context.context_dir),
],
)
# ---------------------------------------------------------------------------
# When — clear
# ---------------------------------------------------------------------------
@@ -383,6 +413,15 @@ def step_roundtrip_import(context, name):
# ---------------------------------------------------------------------------
@then("the actor context list command should succeed")
def step_list_success(context):
assert context.result.exit_code == 0, (
f"Expected exit 0, got {context.result.exit_code}.\n"
f"stdout: {context.result.output}\n"
f"stderr: {getattr(context.result, 'stderr', '')}"
)
@then("the actor context clear command should succeed")
def step_clear_success(context):
assert context.result.exit_code == 0, (
@@ -514,6 +553,18 @@ def step_all_contexts_empty(context):
# ---------------------------------------------------------------------------
@then('the list output should contain "{text}"')
def step_list_output_contains(context, text):
output = context.result.output
assert text in output, f"Expected '{text}' in list output: {output}"
@then('the list output should not contain "{text}"')
def step_list_output_not_contains(context, text):
output = context.result.output
assert text not in output, f"Did not expect '{text}' in list output: {output}"
@then('the output should contain valid JSON with key "{key}"')
def step_output_json_key(context, key):
output = context.result.output
+32
View File
@@ -81,6 +81,38 @@ List Context Files
[Teardown] Cleanup Test Directory
Actor Context List Supports Regex Filter
[Documentation] Verify actor context list supports optional regex filtering
... Uses --context-dir to point at a directory of named actor
... context subdirectories so the test is self-contained and
... does not depend on project-context state.
[Setup] Setup Test Directory
# Create a temporary context directory with two named actor context subdirs
${ctx_dir}= Set Variable ${TEST_DIR}${/}actor_contexts
Create Directory ${ctx_dir}
Create Directory ${ctx_dir}${/}test-context
Create Directory ${ctx_dir}${/}utils-context
# Filter by "test" — should match test-context but not utils-context
${result}= Run Process ${PYTHON} -m cleveragents actor context list test
... --context-dir ${ctx_dir}
... cwd=${TEST_DIR} timeout=120s on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} test-context
Should Not Contain ${result.stdout} utils-context
# Filter by "nomatch" — no contexts match, should print "No contexts found."
${result}= Run Process ${PYTHON} -m cleveragents actor context list nomatch
... --context-dir ${ctx_dir}
... cwd=${TEST_DIR} timeout=120s on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} No contexts found.
[Teardown] Cleanup Test Directory
Show Context Content
[Documentation] Test context show command
[Setup] Initialize Test Project With Context
@@ -12,6 +12,7 @@ from __future__ import annotations
import hashlib
import json
import re
import shutil
from pathlib import Path
from typing import Annotated, Any
@@ -31,6 +32,46 @@ console = Console()
_FORMAT_HELP = "Output format: json, yaml, plain, table, rich, or color (default: rich)"
@app.command("list")
def context_list(
regex: Annotated[
str | None,
typer.Argument(help="Optional regex filter for context names"),
] = None,
context_dir: Annotated[
Path | None,
typer.Option(
"--context-dir",
help="Directory where contexts are stored",
resolve_path=True,
),
] = None,
) -> None:
"""List named actor contexts, optionally filtered by a regular expression."""
pattern: re.Pattern[str] | None = None
if regex is not None:
try:
pattern = re.compile(regex)
except re.error as exc:
console.print(f"[red]Error:[/red] Invalid regex pattern: {exc}")
raise typer.Abort() from exc
base = _default_context_base(context_dir)
context_names = _list_context_names(base)
if pattern is not None:
context_names = [name for name in context_names if pattern.search(name)]
if not context_names:
typer.echo("No contexts found.")
return
for name in context_names:
typer.echo(name)
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
+34 -7
View File
@@ -9,6 +9,7 @@ Deprecated alias: ``agents context <subcommand>`` (emits deprecation warning)
from __future__ import annotations
import re
from pathlib import Path
from typing import TYPE_CHECKING, Annotated, Any
@@ -396,6 +397,10 @@ def context_rm_deprecated(
@app.command("list")
def context_list(
regex: Annotated[
str | None,
typer.Argument(help="Optional regex filter for context names"),
] = None,
context_dir: Annotated[
Path | None,
typer.Option(
@@ -409,6 +414,14 @@ def context_list(
Or list named contexts in a directory.
"""
pattern: re.Pattern[str] | None = None
if regex is not None:
try:
pattern = re.compile(regex)
except re.error as exc:
console.print(f"[red]Error:[/red] Invalid regex pattern: {exc}")
raise typer.Abort() from exc
if context_dir is not None:
# List named contexts in the given directory
ctx_base = context_dir
@@ -417,6 +430,8 @@ def context_list(
return
context_dirs = sorted([d.name for d in ctx_base.iterdir() if d.is_dir()])
if pattern is not None:
context_dirs = [name for name in context_dirs if pattern.search(name)]
if not context_dirs:
typer.echo("No contexts found.")
@@ -451,24 +466,36 @@ def context_list(
console.print("Use 'agents actor context add <path>' to add files.")
return
# Display context files
table = Table(title=f"Context Files ({len(context_files)} total)")
table.add_column("File Path", style="cyan")
table.add_column("Type", style="green")
table.add_column("Size", style="magenta")
table.add_column("Added", style="yellow")
# Filter and normalize entries
filtered_entries: list[tuple[str, str, str, str]] = []
for file_info in context_files:
path_text, type_label, size, added_at, _ = _normalize_context_entry(
file_info
)
display_name = Path(path_text).name if path_text else ""
if pattern is not None and not pattern.search(display_name):
continue
if isinstance(size, str):
size_str = size
else:
size_str = f"{size:,} bytes" if size > 0 else "0 bytes"
filtered_entries.append((display_name, type_label, size_str, added_at))
if not filtered_entries:
console.print("[yellow]No files matched the pattern.[/yellow]")
return
# Display context files
table = Table(title=f"Context Files ({len(filtered_entries)} total)")
table.add_column("File Path", style="cyan")
table.add_column("Type", style="green")
table.add_column("Size", style="magenta")
table.add_column("Added", style="yellow")
for display_name, type_label, size_str, added_at in filtered_entries:
table.add_row(
display_name,
type_label,