feat(acms): implement builtin/context skill for CRP #873

Closed
opened 2026-03-13 22:58:46 +00:00 by freemo · 1 comment
Owner

Metadata

  • Commit Message: feat(acms): implement builtin/context skill for CRP
  • Branch: feature/m5-crp-context-skill

Background and Context

The specification defines the Context Request Protocol (CRP) as the structured vocabulary through which actors declare needed information. The spec says CRP is accessed "via builtin/context skill" with three tools: request_context, query_history, and get_context_budget.

The CRP domain models (ContextRequest, ContextFragment, AssembledContext, ContextBudget) are fully implemented in domain/models/acms/crp.py and the ACMS pipeline is operational. However, no builtin/context skill exists to expose these capabilities to actors. Actors currently have no way to programmatically request context through the CRP during plan execution.

Expected Behavior

A builtin/context skill registered in the Skill Registry that exposes:

  • request_context: Accepts a ContextRequest and returns AssembledContext via the ACMS pipeline
  • query_history: Returns previously assembled context fragments for the current plan/session
  • get_context_budget: Returns the current ContextBudget showing available tokens and usage

Acceptance Criteria

  • builtin/context skill is auto-registered at startup in the Skill Registry
  • request_context tool accepts CRP parameters and returns assembled context
  • query_history tool returns recent context fragments
  • get_context_budget tool returns current budget state
  • Tools integrate with the existing ACMS pipeline and tier services
  • Actors can invoke these tools during plan execution

Subtasks

  • Create builtin/context skill definition in skills/builtins/
  • Implement request_context tool delegating to ACMSService
  • Implement query_history tool delegating to context tier service
  • Implement get_context_budget tool delegating to budget management
  • Register skill in the DI container and auto-register at startup
  • Tests (Behave): Add scenarios for each tool invocation
  • Verify coverage >= 97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
## Metadata - **Commit Message**: `feat(acms): implement builtin/context skill for CRP` - **Branch**: `feature/m5-crp-context-skill` ## Background and Context The specification defines the Context Request Protocol (CRP) as the structured vocabulary through which actors declare needed information. The spec says CRP is accessed "via builtin/context skill" with three tools: `request_context`, `query_history`, and `get_context_budget`. The CRP domain models (`ContextRequest`, `ContextFragment`, `AssembledContext`, `ContextBudget`) are fully implemented in `domain/models/acms/crp.py` and the ACMS pipeline is operational. However, no `builtin/context` skill exists to expose these capabilities to actors. Actors currently have no way to programmatically request context through the CRP during plan execution. ## Expected Behavior A `builtin/context` skill registered in the Skill Registry that exposes: - `request_context`: Accepts a `ContextRequest` and returns `AssembledContext` via the ACMS pipeline - `query_history`: Returns previously assembled context fragments for the current plan/session - `get_context_budget`: Returns the current `ContextBudget` showing available tokens and usage ## Acceptance Criteria - [x] `builtin/context` skill is auto-registered at startup in the Skill Registry - [x] `request_context` tool accepts CRP parameters and returns assembled context - [x] `query_history` tool returns recent context fragments - [x] `get_context_budget` tool returns current budget state - [x] Tools integrate with the existing ACMS pipeline and tier services - [x] Actors can invoke these tools during plan execution ## Subtasks - [x] Create `builtin/context` skill definition in `skills/builtins/` - [x] Implement `request_context` tool delegating to `ACMSService` - [x] Implement `query_history` tool delegating to context tier service - [x] Implement `get_context_budget` tool delegating to budget management - [x] Register skill in the DI container and auto-register at startup - [x] Tests (Behave): Add scenarios for each tool invocation - [x] Verify coverage >= 97% via `nox -s coverage_report` - [x] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done.
freemo added this to the v3.5.0 milestone 2026-03-13 23:00:08 +00:00
Member

Implementation Notes

Design Decisions

1. Service Access Pattern — Lazy DI Lookup
Handlers (_handle_request_context, _handle_query_history, _handle_get_context_budget) access ACMSPipeline and ContextTierService via lazy get_container() calls at invocation time (not import time). This:

  • Avoids circular imports since context_ops.py is imported during module loading
  • Allows test overrides via container.override_providers()
  • Follows the same pattern used by CLI commands in the codebase

2. Fragment Bridging — TieredFragment → ContextFragment
The ContextTierService stores TieredFragment objects, but ACMSPipeline.assemble() requires ContextFragment (from domain.models.core.context_fragment). A _tiered_to_pipeline_fragment() helper converts between the two, mapping fragment_id, content, token_count, and creating a FragmentProvenance from the tier's resource_id.

3. Optional plan_id Input
request_context now accepts an optional plan_id (ULID string) in its input schema. If omitted, a fresh ULID is generated. This supports both:

  • Actor invocation during plan execution (plan_id provided by runtime)
  • Standalone/testing invocation (auto-generated)

4. Query Matching — Simple Keyword Matching
query_history and request_context (when filtering) use case-insensitive substring matching on fragment content and identifiers. This is appropriate for the v1 implementation. Semantic/vector search would require wiring the vector backends, which is a separate concern.

5. Budget Defaults
get_context_budget and request_context use ContextBudget(max_tokens=4096, reserved_tokens=512) as defaults. These match the ContextBudget model defaults in domain.models.core.context_fragment. "Used tokens" is computed from the hot tier's fragment token counts.

Key Code Locations

  • Handlers: cleveragents.skills.builtins.context_ops_handle_request_context, _handle_query_history, _handle_get_context_budget
  • ACMSPipeline DI registration: cleveragents.application.container.Container.acms_pipeline (new Singleton provider)
  • SkillDefinition factory: cleveragents.skills.builtins.context_ops.build_context_skill_definition()
  • BDD tests: features/crp_models.feature — 8 new scenarios replacing 3 obsolete NotImplementedError stubs

Test Results

  • Lint: All checks passed
  • Typecheck: 0 errors
  • Unit tests: 48/48 CRP scenarios passed, 140/140 steps passed
  • Coverage: 98% overall, 98% for context_ops.py specifically
  • Pre-existing failures: 40 errored scenarios in unrelated features (SQLite contention in parallel workers); 17 failed integration tests in checkpoint/rollback/E2E (unrelated)
## Implementation Notes ### Design Decisions **1. Service Access Pattern — Lazy DI Lookup** Handlers (`_handle_request_context`, `_handle_query_history`, `_handle_get_context_budget`) access `ACMSPipeline` and `ContextTierService` via lazy `get_container()` calls at invocation time (not import time). This: - Avoids circular imports since `context_ops.py` is imported during module loading - Allows test overrides via `container.override_providers()` - Follows the same pattern used by CLI commands in the codebase **2. Fragment Bridging — TieredFragment → ContextFragment** The `ContextTierService` stores `TieredFragment` objects, but `ACMSPipeline.assemble()` requires `ContextFragment` (from `domain.models.core.context_fragment`). A `_tiered_to_pipeline_fragment()` helper converts between the two, mapping `fragment_id`, `content`, `token_count`, and creating a `FragmentProvenance` from the tier's `resource_id`. **3. Optional `plan_id` Input** `request_context` now accepts an optional `plan_id` (ULID string) in its input schema. If omitted, a fresh ULID is generated. This supports both: - Actor invocation during plan execution (plan_id provided by runtime) - Standalone/testing invocation (auto-generated) **4. Query Matching — Simple Keyword Matching** `query_history` and `request_context` (when filtering) use case-insensitive substring matching on fragment content and identifiers. This is appropriate for the v1 implementation. Semantic/vector search would require wiring the vector backends, which is a separate concern. **5. Budget Defaults** `get_context_budget` and `request_context` use `ContextBudget(max_tokens=4096, reserved_tokens=512)` as defaults. These match the `ContextBudget` model defaults in `domain.models.core.context_fragment`. "Used tokens" is computed from the hot tier's fragment token counts. ### Key Code Locations - **Handlers**: `cleveragents.skills.builtins.context_ops` — `_handle_request_context`, `_handle_query_history`, `_handle_get_context_budget` - **ACMSPipeline DI registration**: `cleveragents.application.container.Container.acms_pipeline` (new Singleton provider) - **SkillDefinition factory**: `cleveragents.skills.builtins.context_ops.build_context_skill_definition()` - **BDD tests**: `features/crp_models.feature` — 8 new scenarios replacing 3 obsolete NotImplementedError stubs ### Test Results - **Lint**: ✅ All checks passed - **Typecheck**: ✅ 0 errors - **Unit tests**: 48/48 CRP scenarios passed, 140/140 steps passed - **Coverage**: 98% overall, 98% for `context_ops.py` specifically - **Pre-existing failures**: 40 errored scenarios in unrelated features (SQLite contention in parallel workers); 17 failed integration tests in checkpoint/rollback/E2E (unrelated)
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#396 Epic: ACMS Context Pipeline
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#873
No description provided.