Compare commits
1 Commits
pr-practice
...
pr-5968
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dafe25343 |
@@ -107,6 +107,13 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`plan use` UNIQUE constraint violation** (`ActionRepository.update`): Replaced the
|
||||
`.clear()` + `.append()` SQLAlchemy pattern with explicit `sa_delete()` + `session.flush()`
|
||||
before re-inserting `action_arguments` and `action_invariants` child rows. Added
|
||||
`session.expire()` to force collection reload, preventing stale identity-map references
|
||||
that caused `sqlite3.IntegrityError: UNIQUE constraint failed` when re-using an action
|
||||
that already had arguments registered. (#4174, #4197)
|
||||
|
||||
- **Robot Framework TDD Listener Guards** (#5436): Added three guard conditions to the
|
||||
`tdd_expected_fail_listener` `end_test()` function to prevent blindly inverting ALL test
|
||||
failures to passes, which was masking infrastructure errors and causing flaky CI behavior.
|
||||
|
||||
@@ -40,11 +40,11 @@ class FacadeDispatchSuite:
|
||||
|
||||
def setup(self) -> None:
|
||||
self.facade = A2aLocalFacade()
|
||||
self.session_req = A2aRequest(operation="session.create")
|
||||
self.session_req = A2aRequest(method="session.create", params={})
|
||||
self.plan_req = A2aRequest(
|
||||
operation="plan.execute", params={"plan_id": "BENCH001"}
|
||||
method="plan.execute", params={"plan_id": "BENCH001"}
|
||||
)
|
||||
self.context_req = A2aRequest(operation="context.get")
|
||||
self.context_req = A2aRequest(method="context.get", params={})
|
||||
|
||||
def time_dispatch_session_create(self) -> None:
|
||||
self.facade.dispatch(self.session_req)
|
||||
@@ -57,7 +57,7 @@ class FacadeDispatchSuite:
|
||||
|
||||
def time_dispatch_all_operations(self) -> None:
|
||||
for op in self.facade.list_operations():
|
||||
req = A2aRequest(operation=op)
|
||||
req = A2aRequest(method=op, params={})
|
||||
self.facade.dispatch(req)
|
||||
|
||||
def time_list_operations(self) -> None:
|
||||
|
||||
@@ -50,17 +50,17 @@ class M6FacadeDispatchSuite:
|
||||
|
||||
def time_session_create(self) -> None:
|
||||
"""Benchmark session.create dispatch."""
|
||||
self._facade.dispatch(A2aRequest(operation="session.create", params={}))
|
||||
self._facade.dispatch(A2aRequest(method="session.create", params={}))
|
||||
|
||||
def time_plan_create(self) -> None:
|
||||
"""Benchmark plan.create dispatch."""
|
||||
self._facade.dispatch(A2aRequest(operation="plan.create", params={}))
|
||||
self._facade.dispatch(A2aRequest(method="plan.create", params={}))
|
||||
|
||||
def time_plan_execute(self) -> None:
|
||||
"""Benchmark plan.execute dispatch."""
|
||||
self._facade.dispatch(
|
||||
A2aRequest(
|
||||
operation="plan.execute",
|
||||
method="plan.execute",
|
||||
params={"plan_id": "01M6SM0KE00000000000000001"},
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
# `cleveragents.action` — Action Configuration Schema
|
||||
|
||||
The `action` package provides the YAML configuration schema, validation, and
|
||||
loading utilities for CleverAgents action definitions.
|
||||
|
||||
Actions are the top-level automation units in CleverAgents: each action binds
|
||||
lifecycle actors, typed arguments, invariants, and completion criteria into a
|
||||
named, reusable workflow template.
|
||||
|
||||
See the [Action Configuration Files](../schema/action.schema.yaml) schema and
|
||||
`examples/actions/` for reference examples.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from cleveragents.action.schema import ActionConfigSchema
|
||||
|
||||
# Parse from a YAML string
|
||||
config = ActionConfigSchema.from_yaml("""
|
||||
name: local/my-action
|
||||
description: "Refactor a Python module"
|
||||
strategy_actor: openai/gpt-4o
|
||||
execution_actor: openai/gpt-4o-mini
|
||||
definition_of_done: "All tests pass and coverage >= 90%"
|
||||
arguments:
|
||||
- name: target_module
|
||||
type: string
|
||||
required: true
|
||||
description: "Module path to refactor"
|
||||
invariants:
|
||||
- "Do not modify public API signatures"
|
||||
""")
|
||||
|
||||
print(config.name) # "local/my-action"
|
||||
print(config.arguments[0]) # ActionArgumentSchema(name='target_module', ...)
|
||||
|
||||
# Load from a file
|
||||
config = ActionConfigSchema.from_yaml_file("examples/actions/refactor.yaml")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `ActionConfigSchema`
|
||||
|
||||
```python
|
||||
from cleveragents.action.schema import ActionConfigSchema
|
||||
```
|
||||
|
||||
Pydantic model that validates a complete action YAML configuration.
|
||||
|
||||
### Factory Methods
|
||||
|
||||
#### `ActionConfigSchema.from_yaml(yaml_string: str) → ActionConfigSchema`
|
||||
|
||||
Parse and validate an action YAML string.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `yaml_string` | `str` | Raw YAML content |
|
||||
|
||||
**Returns:** Validated `ActionConfigSchema` instance.
|
||||
|
||||
**Raises:**
|
||||
- `ValueError` — if the YAML is empty, `None`, or not a mapping
|
||||
- `pydantic.ValidationError` — if schema validation fails
|
||||
|
||||
**Processing pipeline:**
|
||||
1. Parse YAML with `yaml.safe_load`
|
||||
2. Normalize camelCase keys → snake_case (with deprecation warnings)
|
||||
3. Interpolate `${ENV_VAR}` placeholders from environment variables
|
||||
4. Validate with Pydantic
|
||||
|
||||
---
|
||||
|
||||
#### `ActionConfigSchema.from_yaml_file(path: str | Path) → ActionConfigSchema`
|
||||
|
||||
Load and validate an action YAML file from disk.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `path` | `str \| Path` | Path to the YAML file |
|
||||
|
||||
**Returns:** Validated `ActionConfigSchema` instance.
|
||||
|
||||
**Raises:**
|
||||
- `FileNotFoundError` — if the file does not exist
|
||||
- `ValueError` — if the path is `None` or does not point to a regular file
|
||||
- `pydantic.ValidationError` — if schema validation fails
|
||||
|
||||
---
|
||||
|
||||
### Fields
|
||||
|
||||
#### Identity
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `schema_version` | `str` | No (default: `"1"`) | Schema version for forward compatibility |
|
||||
| `name` | `str` | **Yes** | Namespaced action name — `namespace/name` format |
|
||||
| `description` | `str` | **Yes** | Short description of the action |
|
||||
| `long_description` | `str \| None` | No | Detailed multi-line description |
|
||||
|
||||
The `name` field must match `^[a-z0-9][a-z0-9_-]*/[a-z0-9][a-z0-9_-]*$`.
|
||||
Examples: `local/my-action`, `builtin/refactor`.
|
||||
|
||||
#### Lifecycle Actors
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `strategy_actor` | `str` | **Yes** | Actor for the Strategize phase |
|
||||
| `execution_actor` | `str` | **Yes** | Actor for the Execute phase |
|
||||
| `estimation_actor` | `str \| None` | No | Optional actor for cost/risk estimation |
|
||||
| `review_actor` | `str \| None` | No | Optional actor for code review / QA |
|
||||
| `apply_actor` | `str \| None` | No | Optional actor for the Apply phase |
|
||||
| `invariant_actor` | `str \| None` | No | Optional actor for invariant reconciliation |
|
||||
|
||||
All actor names must follow the `namespace/name` format.
|
||||
|
||||
#### Completion Criteria
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `definition_of_done` | `str` | **Yes** | Testable criteria defining task completion |
|
||||
|
||||
#### Behaviour
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `reusable` | `bool` | `True` | Whether the action persists after use |
|
||||
| `read_only` | `bool` | `False` | Restrict the action to read-only operations |
|
||||
| `state` | `str` | `"available"` | Action state: `available` or `archived` |
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `arguments` | `list[ActionArgumentSchema]` | `[]` | Typed arguments accepted by the action |
|
||||
|
||||
#### Automation & Invariants
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `automation_profile` | `str \| None` | `None` | Default automation profile for derived plans |
|
||||
| `invariants` | `list[str]` | `[]` | Constraints carried as plan-level invariants |
|
||||
| `inputs_schema` | `dict[str, Any] \| None` | `None` | Optional JSON Schema for advanced input validation |
|
||||
|
||||
Invariants are automatically trimmed, de-duplicated, and blank entries are
|
||||
dropped during validation.
|
||||
|
||||
---
|
||||
|
||||
## `ActionArgumentSchema`
|
||||
|
||||
```python
|
||||
from cleveragents.action.schema import ActionArgumentSchema
|
||||
```
|
||||
|
||||
Pydantic model for a single typed action argument. Arguments are values
|
||||
supplied by the user at plan-use time (`agents plan use --arg name=value`).
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `name` | `str` | **Required** | Argument name (1–64 chars, valid identifier) |
|
||||
| `type` | `str` | `"string"` | Data type: `string`, `integer`, `float`, `boolean`, `list` |
|
||||
| `required` | `bool` | `False` | Whether the argument must be provided |
|
||||
| `description` | `str` | `""` | Human-readable description (max 500 chars) |
|
||||
| `default` | `str \| int \| float \| bool \| list[str] \| None` | `None` | Default value when argument is not provided |
|
||||
| `validation_pattern` | `str \| None` | `None` | Regex pattern for string argument validation |
|
||||
| `min_value` | `float \| None` | `None` | Minimum value for numeric arguments |
|
||||
| `max_value` | `float \| None` | `None` | Maximum value for numeric arguments |
|
||||
|
||||
The `name` field must be a valid Python identifier (alphanumeric, underscores,
|
||||
or hyphens).
|
||||
|
||||
---
|
||||
|
||||
## camelCase Compatibility
|
||||
|
||||
The schema accepts both `snake_case` and `camelCase` keys for backward
|
||||
compatibility. camelCase keys are automatically normalized with a deprecation
|
||||
warning:
|
||||
|
||||
| camelCase | snake_case |
|
||||
|-----------|------------|
|
||||
| `strategyActor` | `strategy_actor` |
|
||||
| `executionActor` | `execution_actor` |
|
||||
| `definitionOfDone` | `definition_of_done` |
|
||||
| `longDescription` | `long_description` |
|
||||
| `estimationActor` | `estimation_actor` |
|
||||
| `reviewActor` | `review_actor` |
|
||||
| `applyActor` | `apply_actor` |
|
||||
| `invariantActor` | `invariant_actor` |
|
||||
| `readOnly` | `read_only` |
|
||||
| `automationProfile` | `automation_profile` |
|
||||
| `inputsSchema` | `inputs_schema` |
|
||||
| `validationPattern` | `validation_pattern` |
|
||||
| `minValue` | `min_value` |
|
||||
| `maxValue` | `max_value` |
|
||||
| `schemaVersion` | `schema_version` |
|
||||
|
||||
---
|
||||
|
||||
## Environment Variable Interpolation
|
||||
|
||||
String values in the YAML may reference environment variables using
|
||||
`${VAR_NAME}` syntax. Missing variables are left as-is (no error):
|
||||
|
||||
```yaml
|
||||
name: local/deploy
|
||||
description: "Deploy to ${TARGET_ENV}"
|
||||
strategy_actor: openai/gpt-4o
|
||||
execution_actor: openai/gpt-4o-mini
|
||||
definition_of_done: "Deployment to ${TARGET_ENV} verified"
|
||||
```
|
||||
|
||||
```python
|
||||
import os
|
||||
os.environ["TARGET_ENV"] = "staging"
|
||||
config = ActionConfigSchema.from_yaml(yaml_string)
|
||||
# config.description == "Deploy to staging"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Integrity Note
|
||||
|
||||
When updating an action that already has arguments or invariants registered,
|
||||
`ActionRepository.update()` uses explicit `sa_delete()` + `session.flush()`
|
||||
before re-inserting child rows. This avoids the SQLAlchemy `.clear()` +
|
||||
`.append()` pattern that could trigger a `UNIQUE constraint failed` error
|
||||
on `(action_name, name)` pairs. See [#4197](https://git.cleverthis.com/cleveragents/cleveragents-core/pulls/4197).
|
||||
|
||||
---
|
||||
|
||||
## Complete Example
|
||||
|
||||
```yaml
|
||||
# examples/actions/refactor.yaml
|
||||
schema_version: "1"
|
||||
name: local/refactor
|
||||
description: "Refactor a Python module to improve code quality"
|
||||
long_description: |
|
||||
Analyses the target module for code smells, applies refactoring
|
||||
patterns, and ensures all tests continue to pass.
|
||||
|
||||
strategy_actor: openai/gpt-4o
|
||||
execution_actor: openai/gpt-4o-mini
|
||||
review_actor: anthropic/claude-4-sonnet
|
||||
estimation_actor: local/estimator
|
||||
|
||||
definition_of_done: |
|
||||
- All existing tests pass
|
||||
- Coverage >= 90%
|
||||
- No new linting errors
|
||||
- Public API unchanged
|
||||
|
||||
reusable: true
|
||||
read_only: false
|
||||
state: available
|
||||
|
||||
arguments:
|
||||
- name: target_module
|
||||
type: string
|
||||
required: true
|
||||
description: "Python module path to refactor (e.g. src/myapp/utils.py)"
|
||||
- name: max_complexity
|
||||
type: integer
|
||||
required: false
|
||||
default: 10
|
||||
description: "Maximum cyclomatic complexity threshold"
|
||||
min_value: 1
|
||||
max_value: 50
|
||||
|
||||
invariants:
|
||||
- "Do not modify public API signatures"
|
||||
- "Preserve all existing test assertions"
|
||||
|
||||
automation_profile: standard
|
||||
```
|
||||
@@ -10,6 +10,7 @@ classes, functions, and exceptions with signatures and usage examples.
|
||||
|--------|-------------|
|
||||
| [`cleveragents.core`](core.md) | Exception hierarchy, error handling, retry patterns, async cleanup |
|
||||
| [`cleveragents.a2a`](a2a.md) | Agent-to-Agent (A2A) protocol facade, transport, models, and events |
|
||||
| [`cleveragents.action`](action.md) | Action YAML configuration schema, validation, argument types, and env-var interpolation |
|
||||
| [`cleveragents.actor`](actor.md) | Actor registry, configuration, loader, and compiler |
|
||||
| [`cleveragents.skills`](skills.md) | Skill framework — schema, protocol, registry, discovery, and inline executor |
|
||||
| [`cleveragents.tool`](tool.md) | Tool runtime, lifecycle, registry, router, and container executor |
|
||||
|
||||
@@ -23,10 +23,13 @@ nav:
|
||||
- Configuration: api/config.md
|
||||
- AI Providers: api/providers.md
|
||||
- TUI: api/tui.md
|
||||
- ACMS / UKO: api/acms.md
|
||||
- Modules:
|
||||
- Shell Safety: modules/shell-safety.md
|
||||
- UKO Provenance Tracking: modules/uko-provenance.md
|
||||
- Invariant Reconciliation: modules/invariant-reconciliation.md
|
||||
- ACMS Context Hydration: modules/context-hydration.md
|
||||
- Git Worktree Sandbox: modules/git-worktree-sandbox.md
|
||||
- Development:
|
||||
- Agent System Specification: development/agent-system-specification.md
|
||||
- CI/CD Pipeline: development/ci-cd.md
|
||||
@@ -38,6 +41,7 @@ nav:
|
||||
- System Watchdog: development/system-watchdog.md
|
||||
- Automation Tracking: development/automation-tracking.md
|
||||
- Custom Sandbox Strategy: development/custom_sandbox_strategy.md
|
||||
- Documentation Writer: development/docs-writer.md
|
||||
- Implementation Timeline: timeline.md
|
||||
- FAQ: faq.md
|
||||
- Reference: reference/
|
||||
|
||||
Reference in New Issue
Block a user