docs: document v3.8.1 changes — skeleton context inheritance, actor YAML-first path, checkpoint triggers #3696

Closed
freemo wants to merge 1 commits from docs/ca-docs-writer-v3.8.1-2026-04-05 into master
4 changed files with 267 additions and 0 deletions
+57
View File
@@ -7,6 +7,63 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
---
## [3.8.1] — 2026-04-05
### Added
- **ACMS — Skeleton context inheritance for child plans**: `ACMSPipeline.assemble()`
and `ContextAssemblyPipeline.assemble()` now accept `skeleton_ratio: float = 0.15`
and `parent_fragments: tuple[ContextFragment, ...] | None = None` parameters.
When `parent_fragments` is provided, the `SkeletonCompressor` is invoked in
Phase 3 to compress parent context to the skeleton budget
(`int(budget.available_tokens * skeleton_ratio)`). Compressed skeleton fragments
are returned in the new `ContextPayload.skeleton_fragments` field, enabling child
plans to inherit a compressed representation of the parent plan's accumulated
context. Includes 4 Behave unit test scenarios and 1 Robot Framework integration
test. (#3563)
### Fixed
- **CLI — `agents actor add` YAML-first persistence path**: The `actor add` command
now routes through `ActorRegistry.add()` instead of the legacy
`registry.upsert_actor()` path, ensuring the original YAML text,
`schema_version`, and `compiled_metadata` are preserved in the database.
A `_load_config_text()` helper returns both raw text and parsed dict; the
service fallback path (no registry) is unchanged. (#3426)
- **CLI — `agents diagnostics` extended to all 9 providers**: The diagnostics
command now checks all nine supported providers (OpenAI, Anthropic, Google,
Azure OpenAI, OpenRouter, Gemini, Cohere, Groq, Together) for credential
presence and reports which are configured. (#3422)
- **Executor — Automatic per-tool-write and event-based checkpoint triggers**:
The execution engine now creates checkpoints automatically at four trigger
points: `on_tool_write` (before each write-tool call), `on_tool_write_complete`
(after each write-tool call), `on_subplan_spawn` (before first subplan attempt),
and `on_error` (when Execute phase fails). Triggers are configurable via
`core.checkpoints.auto_create_on`. `CheckpointService` is injected as an
optional parameter into `ToolRunner`, `SubplanExecutionService`, and
`PlanExecutor`. (#3439)
- **CLI — `--container-id` flag on `agents resource add container-instance`**:
The `resource add` command for container-instance resources now accepts a
`--container-id` flag to specify the Docker/Podman container ID explicitly,
rather than requiring auto-discovery. (#2598)
- **Domain — `ToolLifecycle` execute hook**: The `ToolLifecycle` model now
includes the `execute` hook to satisfy the spec's four-stage lifecycle
(`activate → validate → execute → deactivate`). (#2820)
- **MCP — `MCPToolResult.data` type annotation**: The `data` field type
annotation on `MCPToolResult` has been corrected to match the MCP 1.4.0
content list format. (#2743)
- **CLI — `automation-profile list` output structure**: The `automation-profile
list` command now renders the correct Rich table structure and output format
matching the specification. (#2064)
---
## [3.8.0] — 2026-04-05
### Added
+19
View File
@@ -68,6 +68,25 @@ actor = registry.get("openai/gpt-4o")
In-memory registry for actor configurations. Thread-safe.
### `ActorRegistry.add()` — YAML-first persistence path
The `agents actor add` CLI command routes through `ActorRegistry.add()` to
ensure the original YAML text, `schema_version`, and `compiled_metadata` are
preserved in the database.
```python
registry.add(yaml_text="name: openai/gpt-4o\n...", update=False)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `yaml_text` | `str` | Raw YAML text of the actor configuration |
| `update` | `bool` | When `True`, overwrite an existing actor with the same name |
> **Note:** The legacy `registry.upsert_actor()` path is still available for
> programmatic use but is no longer called by the CLI. Use `registry.add()`
> for all new code that needs to persist actor configurations.
---
## `compile_actor` / `CompiledActor`
+28
View File
@@ -217,6 +217,34 @@ Key UKO capabilities:
- **Graph persistence**`UKOGraphPersistence` serialises/restores state via
JSON-file or in-memory backends across application restarts
### Skeleton Context Inheritance
When a parent plan spawns a child plan, the ACMS pipeline compresses the
parent's accumulated context fragments into a **skeleton** for propagation.
This prevents child plans from starting with an empty context while keeping
the inherited payload within budget.
```
Parent Plan Context
▼ SkeletonCompressor (skeleton_ratio=0.15)
▼ skeleton_fragments (top-relevance, budget-bounded)
▼ Child Plan ContextPayload.skeleton_fragments
```
Key parameters:
| Parameter | Default | Description |
|-----------|---------|-------------|
| `skeleton_ratio` | `0.15` | Fraction of the child's token budget allocated to inherited skeleton context |
| `parent_fragments` | `None` | Parent plan's accumulated `ContextFragment` tuple; `None` disables skeleton compression |
The `ContextPayload.skeleton_fragments` field carries the compressed result.
See [`docs/reference/skeleton_compressor.md`](reference/skeleton_compressor.md)
for the full compression algorithm and configuration reference.
---
## Invariant Reconciliation
+163
View File
@@ -0,0 +1,163 @@
# ACMS Skeleton Context Inheritance
## Overview
When a parent plan spawns a child plan, the child plan starts with no
accumulated context. Without inherited context, the child's actor must
re-discover information the parent already gathered, wasting tokens and
execution time.
**Skeleton context inheritance** solves this by compressing the parent
plan's accumulated context fragments into a budget-bounded **skeleton**
that is passed to the child plan's context assembly pipeline.
This feature was introduced in v3.8.1 (issue #3563).
---
## How It Works
```
Parent Plan
├── ContextFragment (relevance=0.9, tokens=800)
├── ContextFragment (relevance=0.7, tokens=600)
└── ContextFragment (relevance=0.3, tokens=400)
▼ SkeletonCompressor
│ skeleton_ratio=0.15
│ skeleton_budget = available_tokens * 0.15
▼ Compressed skeleton (top-relevance, budget-bounded)
Child Plan ContextPayload
├── fragments — child's own assembled context
└── skeleton_fragments — inherited from parent (compressed)
```
The `SkeletonCompressor` sorts parent fragments by relevance descending
and greedily packs them into the skeleton budget. The compressed result
is returned in `ContextPayload.skeleton_fragments`.
---
## API
### `ACMSPipeline.assemble()`
```python
from cleveragents.application.services.acms_service import ACMSPipeline
from cleveragents.domain.models.core.context_fragment import ContextFragment
pipeline = ACMSPipeline()
payload = pipeline.assemble(
plan_id="child-plan-id",
fragments=child_fragments,
budget=budget,
strategy="relevance",
# Skeleton inheritance parameters:
skeleton_ratio=0.15, # fraction of budget for skeleton
parent_fragments=parent_frags, # parent's accumulated fragments
)
# Access inherited skeleton
for frag in payload.skeleton_fragments:
print(frag.uko_node, frag.token_count)
```
**New parameters (v3.8.1+):**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `skeleton_ratio` | `float` | `0.15` | Fraction of `budget.available_tokens` allocated to the skeleton |
| `parent_fragments` | `tuple[ContextFragment, ...] \| None` | `None` | Parent plan's accumulated fragments; `None` disables skeleton compression |
When `parent_fragments` is `None`, `ContextPayload.skeleton_fragments` is
an empty tuple and no compression is performed.
### `ContextAssemblyPipeline.assemble()`
The same `skeleton_ratio` and `parent_fragments` parameters are available
on `ContextAssemblyPipeline.assemble()` for consistency across the two
pipeline entry points.
### `ContextPayload.skeleton_fragments`
```python
@dataclass(frozen=True)
class ContextPayload:
...
skeleton_fragments: tuple[ContextFragment, ...] = ()
```
Immutable tuple of compressed parent context fragments. Empty when no
parent context was provided.
---
## Configuration
### Default skeleton ratio
The default `skeleton_ratio` of `0.15` means the skeleton budget is 15%
of the child plan's available token budget. For a 4096-token budget with
512 reserved tokens, the skeleton budget is:
```
skeleton_budget = (4096 - 512) * 0.15 = 537 tokens
```
### Per-project override
Set a custom skeleton ratio for a project's context policy:
```bash
agents project context set --skeleton-ratio 0.20
```
This overrides the default for all child plans spawned within that project.
---
## Relationship to `SkeletonCompressorService`
The `SkeletonCompressorService` (registered in the DI container as
`skeleton_compressor_service`) is the underlying service that performs
the compression. The ACMS pipeline calls it internally during Phase 3
(Context Finalization).
For direct use of the compressor outside the pipeline, see
[`docs/reference/skeleton_compressor.md`](../reference/skeleton_compressor.md).
---
## Subplan Spawning Integration
The `SubplanService.spawn()` method passes the parent plan's accumulated
context as `parent_fragments` when assembling the child plan's initial
context. This is the primary production path for skeleton inheritance.
```python
# Conceptual — internal to SubplanService
child_payload = pipeline.assemble(
plan_id=child_plan_id,
fragments=child_fragments,
budget=child_budget,
parent_fragments=parent_plan.accumulated_fragments,
skeleton_ratio=project_context_policy.skeleton_ratio,
)
```
---
## Gotchas
- **`skeleton_ratio=0.0`** disables compression entirely — all parent
fragments pass through unchanged. Use this only when you want the full
parent context in the child (rare; usually exceeds budget).
- **`skeleton_ratio=1.0`** keeps only the single highest-relevance fragment.
Useful for very tight token budgets.
- The skeleton budget is computed from `budget.available_tokens`, not
`budget.max_tokens`. Reserved tokens are already excluded.
- Skeleton fragments are **not** deduplicated against the child's own
assembled fragments. If the same resource appears in both, it will be
present twice. A deduplication pass is planned for a future milestone.