Added skeleton_fragments: tuple[ContextFragment, ...] field to ContextPayload in context_fragment.py
- Enables carrying compressed skeleton fragments along with normal context.
Extended ACMSPipeline.assemble() in acms_service.py
- Introduced skeleton_ratio: float = 0.15 (default matching spec) and parent_fragments: tuple[ContextFragment, ...] | None = None parameters.
- These same parameters are also added to ContextAssemblyPipeline.assemble() in acms_pipeline.py for consistency.
Skeleton compression integration
- In Phase 3 of both assemble() methods, computed skeleton_budget = int(budget.available_tokens * skeleton_ratio) and invoked self._skeleton_compressor.compress(parent_fragments, skeleton_budget).
- Compressed skeleton fragments are included in the returned ContextPayload.skeleton_fragments, enabling propagation of skeleton context to child plans.
Tests and behavior coverage
- Added a TDD issue-capture Behave scenario (@tdd_issue @tdd_issue_3563) to demonstrate the fix.
- Added four Behave unit test scenarios asserting: compressor invocation, correct arguments, skeleton presence in output, and skeleton_ratio budget enforcement.
- Added a Robot Framework integration test: parent plan accumulates context → child plan spawned → child plan context contains non-empty skeleton.
- Added skeleton-context-inheritance command to helper_acms_pipeline.py to support testing and manual verification.
Key design decisions
- skeleton_ratio defaults to 0.15 to align with the spec's --skeleton-ratio default.
- parent_fragments is None by default to maintain backward compatibility (no skeleton compression when no parent context).
- skeleton_budget is computed as skeleton_budget = int(budget.available_tokens * skeleton_ratio), deriving the skeleton budget from the total token budget.
- Both ACMSPipeline and ContextAssemblyPipeline are fixed to maintain consistency across the codepath.
ISSUES CLOSED: #3563
Route the 'agents actor add' CLI command through ActorRegistry.add() instead
of the legacy registry.upsert_actor() path. This ensures the original YAML
text, schema_version, and compiled_metadata are preserved in the database.
Changes:
- src/cleveragents/cli/commands/actor.py: Add _load_config_text() helper that
returns both raw text and parsed dict. Refactor add() to call registry.add()
with the raw yaml_text and update=update_existing flag when a registry is
available. The service fallback path (no registry) is unchanged.
- features/steps/actor_cli_steps.py: Update add command step definitions to
mock registry.add() instead of registry.upsert_actor(). Update 'the actor
add should pass the loaded config' assertion to verify registry.add() is
called with a non-empty yaml_text string.
- features/steps/actor_cli_yaml_steps.py: Update add command steps to mock
registry.add() instead of registry.upsert_actor().
- features/steps/actor_add_rich_output_steps.py: Update add command steps to
mock registry.add() instead of registry.upsert_actor().
- robot/helper_actor_add_rich_output.py: Update helper to mock registry.add()
instead of registry.upsert_actor().
- features/actor_add_yaml_first_path.feature: New Behave feature verifying
the YAML-first persistence path is used by actor add.
- features/steps/actor_add_yaml_first_path_steps.py: Step definitions for
the new YAML-first path feature.
- robot/actor_add_yaml_first_path.robot: New Robot integration tests verifying
yaml_text is preserved and upsert_actor is not called.
- robot/helper_actor_add_yaml_first_path.py: Helper script for Robot tests.
Fixes#3426
ISSUES CLOSED: #3426
Implements all four automatic checkpoint triggers defined in the specification
for the Execute phase of the plan lifecycle:
- before_tool_execute: Checkpoint created before any tool with writes=True runs
- after_tool_execute: Checkpoint created after a write tool completes successfully
- on_subplan_spawn: Checkpoint created immediately after a child plan is spawned
- on_error: Checkpoint created after any unrecoverable error in the Execute phase
Changes:
- tool/runner.py: Added optional CheckpointService and auto_checkpoint_triggers
parameters to ToolRunner. Checkpoint hooks fire around write-tool execution
when a CheckpointService is wired. Exported DEFAULT_AUTO_TRIGGERS as a public
constant (single source of truth). Made is_trigger_active() public so callers
can query the active trigger set without accessing private attributes.
- application/services/subplan_execution_service.py: Added optional
CheckpointService, auto_checkpoint_triggers, and parent_plan_id parameters.
on_subplan_spawn checkpoint fires in _execute_one_with_retry before the
first execution attempt. Now imports DEFAULT_AUTO_TRIGGERS from runner.py
(DRY fix).
- application/services/plan_executor.py: Added _is_auto_trigger_active() helper
and on_error checkpoint hooks in both _run_execute_with_stub() and
_run_execute_with_runtime() error paths. Delegates to
ToolRunner.is_trigger_active() instead of accessing private attributes
(module boundary fix).
- application/services/config_service.py: Registered new config key
core.checkpoints.auto_create_on (default: all four triggers enabled) with
env var CLEVERAGENTS_CHECKPOINT_AUTO_CREATE_ON.
- application/services/llm_actors.py: Replaced Any type for lifecycle_service
with PlanLifecycleProtocol (typed Protocol) and tool_runner with ToolRunner
type annotation. Eliminates Any usage for injected dependencies.
Tests:
- features/checkpoint_auto_triggers.feature: 15 Behave scenarios covering all
four triggers, disable-trigger behavior, no-checkpoint-service fallback, and
config key registration.
- features/steps/checkpoint_auto_triggers_tool_steps.py: Step definitions for
ToolRunner and config service scenarios (split from original 519-line file).
- features/steps/checkpoint_auto_triggers_executor_steps.py: Step definitions
for SubplanExecutionService and PlanExecutor scenarios (split from original).
Closes#3439
ISSUES CLOSED: #3439