Add PermissionQuestionWidget API documentation to docs/api/tui.md including
method table, key bindings, PermissionDecisionEvent dataclass, and
render_permission_question() helper reference. Add corresponding CHANGELOG
entry under [Unreleased] Added section.
Refs: #997
Implement inline permission question widget for quick allow/reject
decisions within the conversation stream with file diff context.
ISSUES CLOSED: #997
Align Unicode box-drawing blocks and related tables in specification.md,
ADR-044/045/046, and reference pages for consistent MkDocs rendering.
ISSUES CLOSED: #1171
Consolidate duplicate Added/Fixed headings in [Unreleased] section into single canonical sections per Keep a Changelog format. Add new entries for DomainBaseModel (#1941) and TDD bug-capture test (#1094).
Co-authored-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Co-committed-by: Jeffrey Phillips Freeman <the@jeffreyfreeman.me>
Add a new Behave TDD regression scenario that persists corrupt automation-profile JSON and verifies repository reads do not leak raw JSONDecodeError. The scenario is tagged with @tdd_bug, @tdd_bug_989, and @tdd_expected_fail so it currently inverts the intentional assertion failure and will require tag removal when bug #989 is fixed.\n\nAlso stabilize an unrelated integration fixture in robot/resource_dag.robot by sharing a single SQLAlchemy session in inline scripts; this removes nondeterministic visibility of flushed resource-type rows and keeps required nox integration quality gates deterministic for this branch.\n\nISSUES CLOSED: #1094
Agent evolver identified a systematic pattern:
- Pattern: PR stale/conflict cascade
- Evidence: 11+ PRs were approved but closed without merge due to
conflicts. PRs #1248, #1247, #1237, #1236, #1220, #1219, #1238,
#1246, #1269 were all bulk-closed as stale. Reviewer notes on
#1248, #1220, #1219, #1252 explicitly mention 'merge blocked by
conflicts'. With 16 parallel workers, master moves fast and branches
created minutes earlier are already behind by the time PRs are created.
- Fix: Add a rebase-onto-latest-master step (Phase 3, Step 3.0) in
ca-issue-worker before committing and creating the PR. This ensures
the branch is current when the PR is opened, dramatically reducing
the chance of merge conflicts when the reviewer processes it.
This change requires human approval before taking effect.
Agent evolver identified a systematic pattern:
- Pattern: UAT tester filing bugs for features already being implemented
- Evidence: 25+ UAT bugs filed for TUI MainScreen features (#1329-#1355)
that already had open implementation PRs (#1219, #1236, #1237, #1238,
#1246, #1247, #1248, etc.). The tester reported 'missing sidebar',
'missing tab bar', 'missing escape navigation' etc. while PRs
implementing these exact features were open and under review.
- Fix: Add step 4 to duplicate avoidance requiring the tester to check
for open PRs before filing 'missing feature' bugs.
This change requires human approval before taking effect.
- Add missing 'nox -s format -- --check' step (parity with ci.yml)
- Add NOX_DEFAULT_VENV_BACKEND: uv to global env and each nox step
- Fix quality gates script invocation (was using invalid nox session '3.13')
- Fix report artifact paths to match actual nox session output locations
(build/coverage.json and build/bandit-report.json instead of build/reports/)
- Add mkdir for build/reports before writing quality-trend.json
ISSUES CLOSED: #1537
BREAKING CHANGE: Supervisors can no longer use Task tool to launch workers
Major refactor of the permission model for product-builder and all 15
continuous supervisors to enforce strict separation: supervisors MUST use
curl/prompt_async via bash to launch workers, and CANNOT use the Task tool.
Key Changes:
1. Product-Builder Permissions (product-builder.md):
- Removed ALL Task permissions for supervisors (previously had 17)
- Kept Task permissions ONLY for 7 one-shot agents:
ca-project-bootstrapper, ca-ref-reader, ca-issue-finder,
ca-session-persister, ca-product-verifier, ca-milestone-reviewer,
ca-final-reporter
- Restricted bash to: echo, curl, sleep, jq only
- Removed Phase B (Architecture) and Phase C.1 (Planning)
- Updated to launch 15 supervisors (up from 13)
2. New Continuous Supervisors:
- ca-architect: Converted from one-shot to continuous supervisor
Monitors for spec needs, new milestones, ambiguities
- ca-epic-planner: Converted from one-shot to continuous supervisor
Monitors for milestones without issues, incomplete epics
3. All 15 Supervisors - Standardized Permissions:
- Removed ALL Task permissions for launching workers
- Workers MUST be launched via curl to OpenCode Server prompt_async API
- Added 'jq *' for JSON parsing (replacing python3)
- Restricted bash to specific commands only (deny all, allow specific)
- Git commands restricted to specific operations (clone*, fetch*, etc.)
- Directory operations (cd, mkdir, rm -rf) only where needed
4. Supervisor-Specific Updates:
- issue-implementor: Removed ca-issue-worker task permission
- ca-continuous-pr-reviewer: Added git + directory ops, removed worker tasks
- ca-uat-tester: Added read-only file/git commands, removed self-dispatch
- ca-bug-hunter: Restricted git to read-only, removed self-dispatch
- ca-test-infra-improver: Added read-only commands, removed self-dispatch
- ca-human-liaison: Removed ca-epic-planner/ca-architect task permissions
- ca-agent-evolver: Added git + directory operations
- ca-architecture-guard: Added read-only + git clone operations
- ca-spec-updater: Added git + directory operations
- ca-backlog-groomer: Removed ca-epic-planner task permission
- ca-docs-writer: Added git + directory operations
- ca-timeline-updater: Added git + directory operations
- ca-project-owner: Minimal permissions (curl, jq, sleep only)
Impact:
- Proper separation of concerns: supervisors orchestrate, workers execute
- No possibility of supervisors blocking on Task tool calls
- True fire-and-forget worker launching via prompt_async
- Consistent permission model across all 15 supervisors
- Maximum parallelism with proper isolation
Architecture now enforces: Product-builder → 15 supervisors → N workers
All launched via curl/prompt_async, NO Task tool for supervisors.
Introduce DomainBaseModel in src/cleveragents/domain/models/base.py that
defines the single shared model_config (str_strip_whitespace, validate_assignment,
arbitrary_types_allowed=False, populate_by_name, use_enum_values) previously
duplicated verbatim across five domain model files.
Update 14 classes across five files to inherit from DomainBaseModel instead
of pydantic.BaseModel directly, removing all inline model_config duplication:
- aimodelscredentials/ai_models_credentials.py (ModelProviderOption)
- aimodelserrors/ai_models_errors.py (ModelError, FallbackResult)
- aimodelsproviders/ai_models_providers.py (ModelProviderExtraAuthVars,
ModelProviderConfigSchema)
- auth/auth.py (AuthHeader, TrialPlansExceededError, TrialMessagesExceededError,
BillingError, ApiError, ClientAccount, ClientAuth)
- planconfig/plan_config.py (PlanConfig, ConfigSetting)
Pure structural refactor — no behavioral changes. Models with different
configurations (acms, aimodels_custom, etc.) are left untouched.
Add BDD feature (22 scenarios) and Robot integration tests (8 test cases)
verifying inheritance, config correctness, and no-duplication invariants.
ISSUES CLOSED: #1941
Centralize E2E initialization in common suite setup so DB-dependent CLI commands no longer rely on per-suite or per-test init workarounds. This also sanitizes suite-home names to prevent invalid path-derived initialization failures in isolated Robot runs.
ISSUES CLOSED: #1023
Add explicit aiohttp>=3.13.4 dependency constraint to pyproject.toml to remediate CVE-2026-34515, a high-severity open redirect vulnerability. The lockfile already resolves aiohttp to 3.13.5 which satisfies the constraint.
Closes#1544
Consolidates all per-job uv cache key prefixes across CI workflow files into a single shared key, eliminating redundant package downloads. Also adds missing uv cache steps to the build job and nightly-quality.yml.
Closes#1535
Restores the working OpenCode server mode + curl-based async supervisor
launch functionality from commit 9bbec0e6 (2026-04-02) and updates it for
the current 13-supervisor architecture.
Changes applied to 7 agent files (938 insertions, 221 deletions):
1. product-builder.md: Restored from 9bbec0e6 and updated for 13 supervisors
- Full bash permissions for curl/sleep
- Server URL: http://localhost:4096
- Launch via POST /session + POST /session/:id/prompt_async
- Session resume (adopts existing [CA-AUTO] sessions)
- Added ca-test-infra-improver and ca-project-owner to launch sequence
- Updated concurrent worker calculations (~5N + ~8 singletons)
2. issue-implementor.md: Restored curl-based worker dispatch
- 10-second polling loop with bash sleep
- Worker sessions via prompt_async
- Session resume for existing workers
3. ca-continuous-pr-reviewer.md: Restored curl dispatch pattern
4. ca-uat-tester.md: Restored curl pool mode
5. ca-bug-hunter.md: Restored curl pool mode
6. ca-test-infra-improver.md: Added self-dispatch permission
7. ca-session-cleanup.md: Restored utility agent
Architecture: 5 pool supervisors (N workers each) + 8 singleton supervisors
= 13 total supervisors running async via prompt_async.
Replaces the broken prompt_async implementation from commit 074c472e that
removed supervisors from task permissions without working server launch.
To use: Start OpenCode with --port 4096, then launch product-builder.
Refs: commit 9bbec0e6 (working version), commit 074c472e (broken version)
Add explicit aiohttp>=3.13.4 dependency constraint to pyproject.toml to
remediate CVE-2026-34515, a high-severity open redirect vulnerability in
aiohttp that affects the A2A server HTTP transport, MCP tool source
fetching, and agent communication layers.
The uv.lock already resolves aiohttp to 3.13.5 which satisfies the
>=3.13.4 constraint. Adding the explicit constraint ensures vulnerable
versions (<3.13.4) cannot be installed even if upstream transitive
dependency constraints are loosened.
ISSUES CLOSED: #1544
Rewrites the A2aRequest and A2aResponse Pydantic models to use the field
names mandated by the JSON-RPC 2.0 specification, fixing a fundamental
protocol compliance issue that prevented external A2A-compliant clients
from communicating with the server.
Changes:
- A2aRequest: a2a_version→jsonrpc (fixed '2.0'), request_id→id,
operation→method; auth field removed (not in JSON-RPC 2.0)
- A2aResponse: a2a_version→jsonrpc, request_id→id, status+data→result
(success path), timing_ms removed; added _result_xor_error validator
enforcing mutual exclusion of result and error fields
- A2aLocalFacade.dispatch(): updated to use request.method, request.id,
result=data, error=A2aErrorDetail(...)
- A2aHttpTransport.send(): updated to use request.method
- CLI call sites (session.py, plan.py): updated A2aRequest(method=...)
and response.result / response.error field access
- All existing A2A Behave step files updated to new field names
- New 35-scenario Behave feature (a2a_jsonrpc_wire_format.feature)
covering serialisation, deserialisation, validation, and facade dispatch
- New 7-test Robot Framework suite (a2a_jsonrpc_wire_format.robot)
for end-to-end wire format verification
ISSUES CLOSED: #1501
Extended `_print_actor()` to render the full spec-required output for
`agents actor add`: the Actor Added panel now includes a Type field, and
three additional panels (Config, Capabilities, Tools) plus a success
status line are rendered when `show_add_panels=True`.
- Add `Type:` field to the Actor Added panel (from `config_blob["type"]`)
- Implement Config panel: Path, Hash, Options count, Nodes count, Edges count
- Implement Capabilities panel: bulleted list (rendered only when non-empty)
- Implement Tools panel: Rich table with Tool, Read-Only, Safe columns
(rendered only when non-empty; string tool entries default to yes/yes)
- Add `✓ OK Actor added` success status line after all panels
- Pass `config_path` and `show_add_panels=True` from `add()` command
- Add Behave BDD scenarios covering each new panel and the success line
- Add Robot Framework integration test verifying the full rich output
ISSUES CLOSED: #1499
Add ULID format validation to all v3 plan commands to prevent users from
accidentally mixing legacy ('agents tell') and v3 ('agents plan use')
workflows. The two systems use separate storage backends and cannot be
mixed; this change detects the mismatch early and provides actionable
error messages.
Changes:
- Add _validate_plan_ulid() with proper Crockford Base32 regex
(^[0-9A-HJKMNP-TV-Z]{26}$, re.IGNORECASE) that correctly rejects
invalid characters (I, L, O, U), hyphens, and wrong-length strings
- Add _PLAN_ULID_RE compiled regex and _ULID_VALIDATION_ERROR_MSG constant
with actionable guidance explaining the legacy/v3 incompatibility
- Apply ULID validation to all v3 commands: execute_plan,
_lifecycle_apply_with_id, lifecycle_apply_plan, plan_status,
plan_errors, cancel_plan (only on user-provided IDs, not auto-discovered)
- Update _LEGACY_DEPRECATION_MSG and tell/build command warnings to
explicitly state that the two workflows are INCOMPATIBLE and cannot be mixed
- Add comprehensive BDD tests in features/plan_ulid_validation.feature
with step definitions using Typer CLI runner (not subprocess)
- Update CONTRIBUTING.md with 'Workflow Choice: Legacy vs. v3 Plan
Lifecycle' section documenting the incompatibility and migration path
ISSUES CLOSED: #1560
The TLS handshake failure on git.dev.cleveragents.com was caused by the
hostname being absent from the certificate's Subject Alternative Names
(SANs), or by SNI virtual-host misconfiguration on the server side.
This commit delivers the repository-side remediation:
- scripts/check-tls-cert.py: New TLS certificate health-check script.
Connects to a hostname, verifies the certificate's SANs include the
target hostname, checks expiry, and reports errors/warnings. Accepts
an injectable SSLContext for unit testing without real network access.
Supports wildcard SAN matching and configurable expiry warning threshold.
- docs/development/ops-runbook.md: New ops runbook documenting the full
certificate renewal procedure (Let's Encrypt/certbot and manual CA),
SNI misconfiguration diagnosis steps, expiry monitoring with cron, and
recommended alert thresholds (30/14/7/0 days).
- features/tls_certificate_check.feature: 14 Behave scenarios tagged
@tdd_issue @tdd_issue_1543 covering: missing SAN detection, valid SAN
acceptance, expired certificate detection, expiry warning threshold,
TLS handshake errors, connection timeouts, connection refused, wildcard
SAN matching, and _hostname_matches_san unit tests.
- features/steps/tls_certificate_check_steps.py: Step definitions for
the above feature, using unittest.mock to inject SSL contexts and
socket connections so no real network calls are made.
- mkdocs.yml: Added Ops Runbook to the Development section navigation.
The actual server-side certificate renewal (adding git.dev.cleveragents.com
as a SAN and reloading the web server) must be performed by the server
administrator following the procedure in docs/development/ops-runbook.md.
Closes#1543
ISSUES CLOSED: #1543
Add deterministic BDD feature and step definitions to resolve the
flaky-test detection alert for test_example_flaky_test (issue #1542).
Root cause: the async-job heartbeat step previously relied on a fixed
time.sleep(0.01) that was insufficient on fast CI runners. When two
consecutive datetime.now(UTC) calls returned the same microsecond value
the 'heartbeat updated' assertion failed intermittently.
The busy-wait guard (already present in async_execution_steps.py) is
the correct fix. This commit adds a dedicated feature that:
- Validates the heartbeat timestamp strictly advances after the
busy-wait (the primary test_example_flaky_test scenario)
- Covers rejection of heartbeat recording for queued and completed jobs
- Adds a bounded heartbeat step that asserts the busy-wait terminates
within a wall-clock budget, preventing infinite hangs on broken clocks
ISSUES CLOSED: #1542
- Add _EVENT_TYPE_TO_METHOD class-level mapping (ClassVar[dict[str, str]]) to
convert A2A event types to JSON-RPC 2.0 method names:
TaskStatusUpdateEvent → task/statusUpdate
TaskArtifactUpdateEvent → task/artifactUpdate
- Refactor SseEventFormatter.format() to produce JSON-RPC 2.0 notification
envelope: {"jsonrpc": "2.0", "method": "...", "params": {...}}
- Move event data fields into params object; include taskId (from plan_id)
in params when plan_id is present, per spec §Streaming Architecture
- Remove non-spec fields (event_id, event_type, timestamp, plan_id) from
the data payload; these remain in SSE envelope headers (event: and id:)
- Update BDD feature to verify JSON-RPC 2.0 structure for both event types,
events with/without plan_id, custom data in params, and exclusion of
non-spec fields
- Fix pre-existing type errors in step definitions: replace try/except
ImportError pattern with direct imports and use behave.runner.Context
for proper static typing (0 pyright errors)
ISSUES CLOSED: #1502
Move the large embedded `_BEHAVE_PARALLEL_CLI_SOURCE` string constant out of
noxfile.py and into a standalone `scripts/run_behave_parallel.py` module.
The `_install_behave_parallel()` helper now reads the script from disk via
`Path(__file__).parent / 'scripts' / 'run_behave_parallel.py'` instead of
embedding the source as a raw string literal. This allows ruff to lint and
type-check the runner independently, and makes noxfile.py significantly
shorter and easier to read.
No functional changes: the installed `behave-parallel` entry point is
identical to the previous embedded version. Parallel and sequential modes,
coverage integration, and the multiprocessing fork model are all preserved.
Fixed two SIM105 lint violations in the extracted script (replaced
try/except/pass with contextlib.suppress).
ISSUES CLOSED: #1538
Add missing provider: field to all actor examples in examples/actors/.
Fix llm_with_tools.yaml actor name from assistants/file_analyzer to
local/assistants-file_analyzer (custom actors must use local/ namespace
and cannot contain two slashes).
Add validate-all command to helper_actor_examples.py that uses ActorLoader
to validate all examples via business logic checks. Add integration test
Validate All Actor Examples Import Without Errors to actor_examples.robot
that confirms every example in examples/actors/ can be imported without
errors.
ISSUES CLOSED: #1504
Replace per-job cache key prefixes (uv-lint-, uv-typecheck-, uv-security-,
uv-quality-, uv-tests-, uv-coverage-) with a single shared key
uv-${{ hashFiles('pyproject.toml') }} across all jobs in ci.yml.
Also add a missing uv cache step to the build job and add uv caching
to nightly-quality.yml, which previously had no cache at all.
All jobs now share the same cache entry when pyproject.toml is unchanged,
eliminating redundant package downloads and reducing CI wall-clock time.
ISSUES CLOSED: #1535
The lint, typecheck, security, and quality static analysis jobs already
run in parallel (no needs dependencies between them). However, downstream
jobs only gated on a subset of these jobs, allowing the pipeline to
proceed even when some static analysis checks failed.
Updated needs dependencies for downstream jobs:
- coverage: [lint, typecheck] → [lint, typecheck, security, quality]
- benchmark-regression: [lint, typecheck] → [lint, typecheck, security, quality]
- docker: [lint, typecheck, unit_tests, security] → [lint, typecheck, security, quality, unit_tests]
All four static analysis jobs (lint, typecheck, security, quality) now
run in parallel and all downstream jobs correctly gate on the full set,
ensuring no job proceeds unless all static analysis checks pass.
ISSUES CLOSED: #1536
- CHANGELOG: add Fixed entries for PRs #1574, #1570, #1569, #1547, #1548,
#1522, #1524, #1525, #1520, #1553 covering rich output panels for session,
actor, and plan commands, plus version commit SHA and provider fix
- docs/reference/session_cli.md: document new rich output panels for
session create (Settings, Actor Details), session list (Name column,
Summary panel), session show (Automation field), session delete
(Deletion Summary, Cleanup panels); update export to document --format md
- docs/reference/actor_cli.md: document new rich output panels for
actor remove (Actor Removed, Impact, Cleanup) and actor list (Summary panel)
- docs/reference/plan_cli.md: document new rich output for plan list
(Elapsed column, Filters panel, Summary panel)
- docs/reference/cli_system_commands.md: document commit SHA resolution
order (CLEVERAGENTS_COMMIT env var → git rev-parse → 'unknown')
ISSUES CLOSED: #1574#1570#1569#1547#1548#1522#1524#1525#1520#1553
The product-builder was ignoring prompt_async instructions and implementing
tickets directly because its identity was "autonomous product builder that
handles everything." The LLM absorbed this framing and defaulted to doing
the work itself rather than launching supervisors.
Root cause fix — two structural changes applied to product-builder AND all
5 pool supervisors:
1. IDENTITY REFRAME: The product-builder is now explicitly a "Supervisor
Launcher and Monitor" — not a "product builder." The opening section
states: "YOUR ONLY JOB: Launch 13 supervisor sessions via bash curl
and keep them alive." A prominent DO NOT list prohibits implementing
issues, creating PRs, writing code, or doing any work a supervisor
handles. The file was compressed from 975 to 312 lines — prerequisites
are brief, the supervisor launch is the first major section, and the
monitoring loop is the primary content.
2. WORKER AGENTS REMOVED FROM TASK PERMISSIONS: Every pool supervisor had
its worker agent in the task permissions, giving the LLM the choice to
use the Task tool instead of prompt_async. Now removed:
- issue-implementor: removed ca-issue-worker
- ca-continuous-pr-reviewer: removed ca-pr-self-reviewer, ca-pr-checker
- ca-uat-tester: removed ca-uat-tester (self-dispatch)
- ca-bug-hunter: removed ca-bug-hunter (self-dispatch)
- ca-test-infra-improver: removed ca-test-infra-improver (self-dispatch)
Each supervisor now has a prominent framing block at the top: "YOU ARE A
POOL SUPERVISOR. You dispatch workers via bash curl prompt_async. Worker
agents have been REMOVED from your task permissions."
Non-worker task permissions preserved (ca-ref-reader, ca-spec-reader,
ca-new-issue-creator, etc.) for legitimate one-shot subagent calls.