diff --git a/docs/reference/acms.md b/docs/reference/acms.md index bb8abead1..aefc27130 100644 --- a/docs/reference/acms.md +++ b/docs/reference/acms.md @@ -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 diff --git a/docs/specification.md b/docs/specification.md index 4accaad8b..ee078196a 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -9537,7 +9537,7 @@ Register a new validation. The validation is fully defined by the YAML configura ##### agents validation attach
agents validation attach [--project <PROJECT>|--plan <PLAN_ID>]
- <RESOURCE> <VALIDATION> [<ARGS>...]# File: skills/kubernetes-ops.yaml
- skill:
- name: local/kubernetes-ops
- description: "Kubernetes cluster management tools"
- mcp_servers:
- - transport: stdio
- command: npx
- args: ["-y", "@anthropic/mcp-kubernetes"]
+ name: local/kubernetes-ops
+ description: "Kubernetes cluster management tools"
+ mcp_servers:
+ - name: kubernetes
+ transport: stdio
+ command: npx
+ args: ["-y", "@anthropic/mcp-kubernetes"]
skill:
- name: local/project-tools
- agent_skills_dirs:
- - ./agent-skills/
+ name: local/project-tools
+ agent_skill_folders:
+ - ./agent-skills/
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:
-class SandboxStrategy(Protocol):
+class SandboxStrategyProtocol(Protocol):
"""Interface for sandbox isolation strategies."""
def create(self, plan_id: str, resource: Resource) -> SandboxRef: ...
def read(self, ref: SandboxRef, path: str) -> bytes: ...
- def write(self, ref: SandboxRef, path: str, content: bytes) -> Change: ...
+ def write(self, ref: SandboxRef, path: str, content: bytes) -> DiffEntry: ...
def diff(self, ref: SandboxRef) -> DiffView: ...
def commit(self, ref: SandboxRef) -> None: ...
def rollback(self, ref: SandboxRef) -> None: ...
@@ -46543,7 +46551,21 @@ The sandbox layer supports custom isolation strategies for specialized resource
def cleanup(self, ref: SandboxRef) -> None: ...
-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