Compare commits

...

1 Commits

Author SHA1 Message Date
HAL9000 1b718e32e6 docs: architecture corrections — invariant precedence, TUI shell safety, sandbox protocol, validation args, ACMS strategy interface
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Failing after 46s
CI / build (pull_request) Successful in 3m17s
CI / helm (pull_request) Successful in 24s
CI / security (pull_request) Successful in 4m8s
CI / quality (pull_request) Successful in 4m12s
CI / push-validation (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 4m19s
CI / coverage (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
CI / integration_tests (pull_request) Failing after 6m36s
CI / e2e_tests (pull_request) Successful in 8m9s
CI / unit_tests (pull_request) Successful in 10m53s
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 1s
Closes #4600 — TUI shell safety: add CRITICAL danger level, update pattern table
Closes #4523 — SandboxStrategyProtocol name, write() return type DiffEntry, registration config keys
Closes #4382 — validation attach --key value format, SemanticEmbeddingStrategy v1 note, SpecStrategyAdapter doc
Closes #4554 — skill YAML: remove skill: wrapper, fix agent_skills_dirs -> agent_skill_folders
Closes #3675 — ACMS reference doc: remove resolved v1 limitations, update strategy interface examples
Fixes invariant precedence pseudocode: plan > action > project > global (was missing action tier)
2026-04-09 00:49:08 +00:00
2 changed files with 69 additions and 54 deletions
+23 -30
View File
@@ -98,16 +98,18 @@ Properties:
## Context Strategies
Strategies implement the `ContextStrategy` protocol:
Strategies implement the `ContextStrategy` protocol (defined in `cleveragents.domain.models.acms.strategy`):
| Method | Description |
|--------|-------------|
| `name` (property) | Strategy identifier |
| `capabilities` (property) | `StrategyCapabilities` dataclass |
| `can_handle(request)` | Confidence (0.0-1.0) for handling a request |
| `assemble(fragments, budget)` | Rank/filter fragments to fit budget |
| `can_handle(request: ContextRequest, backends: BackendSet)` | Confidence (0.0-1.0) for handling a request |
| `assemble(request: ContextRequest, backends: BackendSet, budget: int, plan_context: PlanContext)` | Execute the strategy; must respect the budget |
| `explain()` | Human-readable explanation |
`StrategyCapabilities` fields: `uses_text`, `uses_vector`, `uses_graph`, `uses_temporal`, `uko_levels`, `resource_types`, `quality_score`.
### Relevance (default)
Sorts fragments by `relevance_score` descending. Highest-relevance
@@ -150,9 +152,6 @@ milestones:
| Area | v1 Behaviour | Spec Target | Planned |
|------|-------------|-------------|---------|
| `ContextStrategy.can_handle` signature | `(request: dict[str, Any]) -> float` | `(request: ContextRequest, backends: BackendSet) -> float` | M6 strategy registry aligns signatures |
| `ContextStrategy.assemble` signature | `(fragments, budget)` — receives pre-fetched fragments | `(request, backends, budget, plan_context)` — queries backends directly | M6 strategy registry aligns signatures |
| `StrategyCapabilities` fields | `supports_semantic_search`, `supports_graph_navigation`, `supports_temporal_archaeology`, `max_fragments` | `uses_text`, `uses_vector`, `uses_graph`, `uses_temporal`, `uko_levels`, `resource_types`, `quality_score` | M6 strategy registry uses spec field names |
| Pipeline components | All 10 Protocol + Default classes defined; defaults are pass-through stubs | Production implementations (parallel execution, dedup, scoring, compression) | Future milestone |
| Tiers | Sort-priority labels for ranking (`hot > warm > cold`) | Storage tiers with retention policies, promotion/demotion | `ContextTierService` in future milestone |
| `StrategySelector.select()` | `(strategies, request: dict)` | `(strategies, request: ContextRequest, backends: BackendSet)` — spec §42666 | M6 strategy registry aligns signatures |
@@ -168,21 +167,18 @@ milestones:
## Extension Points
Register custom context strategies at runtime:
Register custom context strategies at runtime using the spec-aligned `ContextStrategy` protocol from `cleveragents.domain.models.acms.strategy`. Custom strategies are registered via `SpecStrategyAdapter`:
```python
from cleveragents.application.services.acms_service import (
ACMSPipeline,
from cleveragents.domain.models.acms.strategy import (
ContextStrategy,
StrategyCapabilities,
ContextRequest,
BackendSet,
PlanContext,
)
from cleveragents.domain.models.core.context_fragment import (
ContextBudget,
ContextFragment,
FragmentProvenance,
)
from collections.abc import Sequence
from typing import Any
from cleveragents.domain.models.core.context_fragment import ContextFragment
from cleveragents.application.services.acms_service import ACMSPipeline, SpecStrategyAdapter
class MyCustomStrategy:
@@ -192,31 +188,28 @@ class MyCustomStrategy:
@property
def capabilities(self) -> StrategyCapabilities:
return StrategyCapabilities()
return StrategyCapabilities(uses_text=True, quality_score=0.5)
def can_handle(self, request: dict[str, Any]) -> float:
def can_handle(self, request: ContextRequest, backends: BackendSet) -> float:
return 0.5
def assemble(
self,
fragments: Sequence[ContextFragment],
budget: ContextBudget,
) -> Sequence[ContextFragment]:
# Custom ranking logic
return list(fragments)
request: ContextRequest,
backends: BackendSet,
budget: int,
plan_context: PlanContext,
) -> list[ContextFragment]:
# Custom retrieval logic using backends
return []
def explain(self) -> str:
return "Custom strategy description."
pipeline = ACMSPipeline()
pipeline.register_strategy("custom", MyCustomStrategy())
payload = pipeline.assemble(
plan_id="plan-1",
fragments=fragments,
budget=budget,
strategy="custom",
)
adapter = SpecStrategyAdapter(MyCustomStrategy())
pipeline.register_strategy("custom", adapter)
```
## Example Usage
+46 -24
View File
@@ -9537,7 +9537,7 @@ Register a new validation. The validation is fully defined by the YAML configura
##### agents validation attach
<div class="highlight"><pre><code><span style="color: cyan; font-weight: 600;">agents</span> validation attach [<span style="color: cyan;">--project</span> <span style="color: #66cc66;">&lt;PROJECT&gt;</span>|<span style="color: cyan;">--plan</span> <span style="color: #66cc66;">&lt;PLAN_ID&gt;</span>]
<span style="color: #66cc66;">&lt;RESOURCE&gt;</span> <span style="color: #66cc66;">&lt;VALIDATION&gt;</span> [<span style="color: #66cc66;">&lt;ARGS&gt;</span>...]</code></pre></div>
<span style="color: #66cc66;">&lt;RESOURCE&gt;</span> <span style="color: #66cc66;">&lt;VALIDATION&gt;</span> [<span style="color: cyan;">--&lt;KEY&gt;</span> <span style="color: #66cc66;">&lt;VALUE&gt;</span>...]</code></pre></div>
**Purpose**
Attach a registered validation to a resource, with an optional project or plan scope. A resource is always required — validations are fundamentally resource-centric. The optional `--project` or `--plan` flag narrows when the validation is active: without either flag, the validation runs whenever any plan or project accesses the resource; with `--project`, it only runs when the resource is accessed through that project; with `--plan`, it only runs when the resource is accessed through that plan. At most one scope flag may be provided per invocation.
@@ -9550,7 +9550,7 @@ The command returns a system-assigned **attachment ULID** that uniquely identifi
- `<VALIDATION>`: Validation name (positional argument, required).
- `--project PROJECT`: Scope the attachment to a specific project. The validation only runs for this resource when it is accessed through the specified project.
- `--plan PLAN_ID`: Scope the attachment to a specific plan. The validation only runs for this resource when it is accessed through the specified plan.
- `<ARGS>...`: Optional validation-specific arguments (passed through to the validation tool's `input_schema` at execution time).
- `--<KEY> <VALUE> ...`: Optional validation-specific named options passed through to the validation tool's `input_schema` at execution time. Each argument must be provided as a named option in `--key value` format (e.g., `--coverage-threshold 90`). Hyphens in option names are normalised to underscores before passing to the validation schema (e.g., `--coverage-threshold``coverage_threshold`). Positional `key=value` format is not accepted and will produce an error.
**Examples**
@@ -19798,8 +19798,8 @@ The system collects, reconciles, and checks invariants:
<span style="color: magenta; font-weight: 600;">or</span> self.get_global_invariant_actor()
)
<span style="opacity: 0.7;"># 3. Reconcile: apply precedence (plan &gt; project &gt; global), resolve conflicts</span>
effective = reconciler.reconcile(raw, precedence=[<span style="color: #66cc66;">&#x27;plan&#x27;</span>, <span style="color: #66cc66;">&#x27;project&#x27;</span>, <span style="color: #66cc66;">&#x27;global&#x27;</span>])
<span style="opacity: 0.7;"># 3. Reconcile: apply precedence (plan &gt; action &gt; project &gt; global), resolve conflicts</span>
effective = reconciler.reconcile(raw, precedence=[<span style="color: #66cc66;">&#x27;plan&#x27;</span>, <span style="color: #66cc66;">&#x27;action&#x27;</span>, <span style="color: #66cc66;">&#x27;project&#x27;</span>, <span style="color: #66cc66;">&#x27;global&#x27;</span>])
<span style="color: magenta; font-weight: 600;">return</span> effective
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">collect_all_invariants</span>(self, plan):
@@ -30051,16 +30051,21 @@ When shell mode is active (`!`/`$` prefix), the prompt performs heuristic analys
| Pattern | Risk Level | Example |
|---------|-----------|---------|
| `rm -rf` / `rm -r` | High | `rm -rf /` |
| `rm -rf /` / `rm -rf /*` (root/wildcard) | Critical | `rm -rf /` |
| `:(){ :\|:& };:` (fork bomb) | Critical | Fork bomb patterns |
| `dd if=` | High | `dd if=/dev/zero of=/dev/sda` |
| `mkfs` | High | `mkfs.ext4 /dev/sda1` |
| `shred` on device or with `--remove` | High | `shred /dev/sda` |
| `chmod 777` | Medium | `chmod 777 /var/www` |
| `> /dev/sda` / `dd if=` | High | `dd if=/dev/zero of=/dev/sda` |
| `:(){ :\|:& };:` (fork bomb) | High | Fork bomb patterns |
| `mkfs` / `fdisk` / `parted` | High | Disk formatting tools |
| `kill -9` / `killall` | Medium | Process termination |
| `sudo` / `su` | Low | Privilege escalation (warning only) |
| `sudo rm` | Medium | `sudo rm -rf /tmp/data` |
| `wget \| sh` / `curl \| sh` | Medium | `curl https://example.com/install.sh \| sh` |
| `git push --force` | Low | `git push --force origin main` |
| `chmod -R` with permissive modes | Low | `chmod -R 644 /var/www` |
Danger detection is controlled by the `shell.warn_dangerous` setting (default: `true`). The detection is advisory only — it never prevents command execution. The warning text reads: `⚠ Potentially destructive command detected`.
Four danger levels are defined, from least to most severe: **Low** (minor risk, generally recoverable), **Medium** (moderate risk, can cause data loss or security exposure), **High** (significant, hard-to-reverse damage), and **Critical** (can destroy the entire system or create a fork bomb). All levels trigger the same advisory warning — the level is used for styling and future escalation logic.
### Notification System
@@ -45482,6 +45487,8 @@ Basic keyword/regex text search. Works with any backend, any resource type. No g
Vector similarity search. Finds semantically related content even without exact keyword matches. Requires a vector backend. Quality score: 0.6.
> **v1 Implementation Note:** The current implementation uses a character-frequency embedding as a v1 approximation of semantic similarity. This approximation is passed to `VectorBackend.similarity_search()` and is intended for replacement with a real embedding model in a future release.
##### Strategy: `breadth-depth-navigator`
The graph-aware strategy that uses the depth/breadth projection system. Works with the UKO graph to provide structurally-aware context at any detail depth. Supports focus items, hop traversal, and detail depth gradients. This is the primary strategy for code-aware context. Quality score: 0.85.
@@ -45508,6 +45515,8 @@ Retrieves context from parent and ancestor plan decisions. This is how child pla
The ACMS-specific extension points (analyzers, backends, UKO vocabularies, strategies, and pipeline components) are documented in the **Extensibility** section below. See **Extensibility > ACMS Extensions** for the full details.
**`SpecStrategyAdapter`**: The built-in strategies are registered with `ACMSPipeline` at construction time via `SpecStrategyAdapter`, a bridge class that adapts the domain-model `ContextStrategy` protocol to the pipeline's internal protocol without modifying either interface. Custom strategies that implement `ContextStrategy` directly can also be registered via `SpecStrategyAdapter`. Note: the long-term goal is to consolidate the two protocols so that `SpecStrategyAdapter` is no longer needed — see issue #4560.
#### UKO Runtime Services
The UKO runtime is operationalized through three service classes:
@@ -46388,21 +46397,20 @@ Tools are the atomic unit of execution and the primary extension point. There ar
2. **MCP server tools**: Any MCP-compliant server can expose tools to CleverAgents. Skills reference MCP servers by their transport configuration:
<div class="highlight"><pre><code><span style="color: #888;"># File: skills/kubernetes-ops.yaml</span>
<span style="color: cyan; font-weight: 600;">skill</span>:
<span style="color: cyan; font-weight: 600;">name</span>: <span style="color: #66cc66;">local/kubernetes-ops</span>
<span style="color: cyan; font-weight: 600;">description</span>: <span style="color: #66cc66;">"Kubernetes cluster management tools"</span>
<span style="color: cyan; font-weight: 600;">mcp_servers</span>:
- <span style="color: cyan; font-weight: 600;">transport</span>: <span style="color: #66cc66;">stdio</span>
<span style="color: cyan; font-weight: 600;">command</span>: <span style="color: #66cc66;">npx</span>
<span style="color: cyan; font-weight: 600;">args</span>: [<span style="color: #66cc66;">"-y"</span>, <span style="color: #66cc66;">"@anthropic/mcp-kubernetes"</span>]
<span style="color: cyan; font-weight: 600;">name</span>: <span style="color: #66cc66;">local/kubernetes-ops</span>
<span style="color: cyan; font-weight: 600;">description</span>: <span style="color: #66cc66;">"Kubernetes cluster management tools"</span>
<span style="color: cyan; font-weight: 600;">mcp_servers</span>:
- <span style="color: cyan; font-weight: 600;">name</span>: <span style="color: #66cc66;">kubernetes</span>
<span style="color: cyan; font-weight: 600;">transport</span>: <span style="color: #66cc66;">stdio</span>
<span style="color: cyan; font-weight: 600;">command</span>: <span style="color: #66cc66;">npx</span>
<span style="color: cyan; font-weight: 600;">args</span>: [<span style="color: #66cc66;">"-y"</span>, <span style="color: #66cc66;">"@anthropic/mcp-kubernetes"</span>]
</code></pre></div>
3. **Agent Skills Standard tools**: Tools organized in standard folder structures are auto-discovered and registered:
<div class="highlight"><pre><code><span style="color: cyan; font-weight: 600;">skill</span>:
<span style="color: cyan; font-weight: 600;">name</span>: <span style="color: #66cc66;">local/project-tools</span>
<span style="color: cyan; font-weight: 600;">agent_skills_dirs</span>:
- <span style="color: #66cc66;">./agent-skills/</span>
<div class="highlight"><pre><code><span style="color: cyan; font-weight: 600;">name</span>: <span style="color: #66cc66;">local/project-tools</span>
<span style="color: cyan; font-weight: 600;">agent_skill_folders</span>:
- <span style="color: #66cc66;">./agent-skills/</span>
</code></pre></div>
4. **Built-in tools**: Core file operations (`read_file`, `write_file`, `edit_file`, `delete_file`, `move_file`, `list_files`, `search_files`), plan operations (`create-subplan`), and system operations are provided as built-in tools grouped into built-in skills.
@@ -46530,11 +46538,11 @@ New backends are registered via configuration:
The sandbox layer supports custom isolation strategies for specialized resource types:
<div class="highlight"><pre><code><span style="color: magenta; font-weight: 600;">class</span> <span style="color: cyan; font-weight: 600;">SandboxStrategy</span>(<span style="color: cyan;">Protocol</span>):
<div class="highlight"><pre><code><span style="color: magenta; font-weight: 600;">class</span> <span style="color: cyan; font-weight: 600;">SandboxStrategyProtocol</span>(<span style="color: cyan;">Protocol</span>):
<span style="color: #888;">"""Interface for sandbox isolation strategies."""</span>
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">create</span>(<span style="color: cyan;">self</span>, plan_id: <span style="color: cyan;">str</span>, resource: Resource) -> SandboxRef: ...
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">read</span>(<span style="color: cyan;">self</span>, ref: SandboxRef, path: <span style="color: cyan;">str</span>) -> <span style="color: cyan;">bytes</span>: ...
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">write</span>(<span style="color: cyan;">self</span>, ref: SandboxRef, path: <span style="color: cyan;">str</span>, content: <span style="color: cyan;">bytes</span>) -> Change: ...
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">write</span>(<span style="color: cyan;">self</span>, ref: SandboxRef, path: <span style="color: cyan;">str</span>, content: <span style="color: cyan;">bytes</span>) -> DiffEntry: ...
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">diff</span>(<span style="color: cyan;">self</span>, ref: SandboxRef) -> DiffView: ...
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">commit</span>(<span style="color: cyan;">self</span>, ref: SandboxRef) -> <span style="color: cyan;">None</span>: ...
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">rollback</span>(<span style="color: cyan;">self</span>, ref: SandboxRef) -> <span style="color: cyan;">None</span>: ...
@@ -46543,7 +46551,21 @@ The sandbox layer supports custom isolation strategies for specialized resource
<span style="color: magenta; font-weight: 600;">def</span> <span style="color: cyan; font-weight: 600;">cleanup</span>(<span style="color: cyan;">self</span>, ref: SandboxRef) -> <span style="color: cyan;">None</span>: ...
</code></pre></div>
Custom strategies are mapped to resource types via the resource type configuration's `sandbox_strategy` field, or globally via `sandbox.strategy` config.
Custom strategies are registered via configuration and then referenced by name in the resource type's `sandbox_strategy` field:
```toml
# config.toml — register the custom strategy
[sandbox.custom_strategies.my-strategy]
module = "my_package.my_module"
class = "MySandboxClass"
```
```yaml
# resource-types/my-resource.yaml — reference the strategy by name
resource_type:
name: local/my-resource
sandbox_strategy: my-strategy
```
#### ACMS Extensions