Files
cleveragents-core/features/tdd_spec_clarifications.feature
T
HAL9000 2fc2f9f444 [AUTO-ARCH-1] Spec clarifications: layer boundary DI exception, ULID scope, TUI/ACMS gap-fill
Add BDD test coverage for spec clarifications regarding:
- Application layer DI exception (container.py)
- ULID identifier scope (domain vs internal IDs)
- ACMS pipeline protocol contracts
- TUI component public interfaces

ISSUES CLOSED: #10451
2026-06-10 20:39:28 -04:00

205 lines
12 KiB
Gherkin

@spec @clarification @layer_boundary @di_exception @ulid_scope @acms_pipeline @tui_components
Feature: Spec clarifications — layer boundary DI exception, ULID scope, TUI/ACMS gap-fill
As a CleverAgents developer
I want BDD coverage for the AUTO-ARCH-1 spec clarifications introduced in PR #10451
So that the following architectural rules can be tested programmatically:
- Application layer container.py is the sole permitted location for application-to-infrastructure concrete type references
- Domain entity IDs must be ULIDs; ephemeral internal IDs need not be
- ACMS pipeline per-stage protocol contracts include storage tier definitions and budget enforcement
- TUI has 8+ component public interfaces with verifiable checks
# ---------------------------------------------------------------------------
# Layer boundary DI exception container.py as sole permitted location
# ---------------------------------------------------------------------------
@di_exception @layer_boundary
Scenario: Import analysis confirms container.py references infrastructure types
Given the source directory is at "src/cleveragents"
And I examine file "application/container.py"
Then container.py should import from cleveragents.infrastructure (application-to-infrastructure concrete type references)
@di_exception @layer_boundary
Scenario: Non-container application files must not import infrastructure types directly
Given the source directory is at "src/cleveragents"
And I examine all files in "application/services/" for imports
Then no file outside container.py should import from cleveragents.infrastructure with a concrete class
And application modules may only depend on domain model interfaces
@di_exception @layer_boundary
Scenario: container.py is the designated DI exception per spec clarification
Given the source directory is at "src/cleveragents"
When I check that cleveragents/application/container.py imports infrastructure types
Then "container.py" should be listed as the sole permitted location for application-to-infrastructure concrete references
And ADR-003 (Dependency Injection Framework) section on layer boundaries should cite this exception
@di_exception @layer_boundary
Scenario: container.py imports from domain models and infrastructure simultaneously
Given the file "src/cleveragents/application/container.py" is readable
Then container.py should import domain types such as AIProviderInterface, AnalyzerRegistry, InMemoryGraphBackend, InMemoryTextBackend
And container.py should import infrastructure types such as UnitOfWork, CheckpointRepository, SessionRepository, LLMTraceRepository
# ---------------------------------------------------------------------------
# ULID scope — domain entity IDs must be ULIDs; ephemeral internal IDs don't have to be
# ---------------------------------------------------------------------------
@ulid_scope @spec_clarification_10451
Scenario: Domain entity Plan uses ULID for plan_id field
When I verify the domain model for "Plan" at cleveragents.domain.models.core.plan
Then the plan model should have a plan_id field typed as a ULID string (26 chars, Crockford alphabet)
@ulid_scope @spec_clarification_10451
Scenario: Decision entity uses ULID for decision_id
When I verify the domain model for "Decision" at cleveragents.domain.models.core.decision
Then the decision model should have a parent_plan_id field typed as a nullable ULID
And the decision model should have a plan_id field typed as a ULID string
@ulid_scope @spec_clarification_10451
Scenario: Actor entity uses a namespaced identifier (not raw ULID)
When I verify the domain model for "Actor" at cleveragents.domain.models.core.actor
Then the actor model should use an actor_id field as its persistent identity format
@ulid_scope @spec_clarification_10451
Scenario: Child plans identified solely by ULID (no namespaced name) — spec clarification
When I verify subplan identity rules in the specification
Then child plans should use ULID identifiers only, not namespaced names
And all operations on child plans reference them by plan ID (ULID)
@ulid_scope @spec_clarification_10451
Scenario: Ephemeral internal IDs are exempt from ULID requirement
When I verify the ephemeral context fragment model
Then ContextFragment should have a fragment_id field typed as any str (not mandated to be ULID)
And the specification should clarify that domain entity identifiers must be ULIDs
And ephemeral internal identifiers need not conform to ULID format
@ulid_scope @spec_clarification_10451
Scenario: Resource identifier uses ULID consistently
When I verify the domain model for "Resource" at cleveragents.domain.models.core
Then all resource identifiers should be ULIDs (resource_ulid field)
# ---------------------------------------------------------------------------
# ACMS pipeline per-stage protocol contracts with storage tier and budget enforcement
# ---------------------------------------------------------------------------
@acms_protocol @per_stage_contract
Scenario: Phase 1 components define Pipeline Protocol interfaces
Given the ACMS pipeline specification at docs/specification.md section "Context Assembly Pipeline"
And I identify the Phase 1 Strategy Orchestration components
Then Phase 1 should have exactly three components: StrategySelector, BudgetAllocator, StrategyExecutor
And each component must be defined as a @runtime_checkable Protocol
@acms_protocol @per_stage_contract
Scenario: Phase 2 (Fragment Fusion) protocol interfaces are specified
Given the ACMS pipeline specification at docs/specification.md section "Context Assembly Pipeline"
And I identify the Phase 2 Fragment Fusion components
Then Phase 2 should have exactly four components:
| Component | Protocol |
| FragmentDeduplicator | FragmentDeduplicatorProtocol |
| DetailDepthResolver | DetailDepthResolverProtocol |
| FragmentScorer | FragmentScorerProtocol |
| BudgetPacker | BudgetPackerProtocol |
@acms_protocol @per_stage_contract
Scenario: Phase 3 (Context Finalization) protocol interfaces are specified
Given the ACMS pipeline specification at docs/specification.md section "Context Assembly Pipeline"
And I identify the Phase 3 Context Finalization components
Then Phase 3 should have exactly two components: PreambleGenerator and SkeletonCompressor
And each must be defined as a @runtime_checkable Protocol
@acms_protocol @per_stage_contract
Scenario: BudgetPacker enforces token budget limit (storage tier definition)
Given the ACMS pipeline modules are available
When I assemble with strategy "tiered" and budget 200 tokens from hot + warm tier fragments
Then the payload total tokens should not exceed the specified budget of 200
And BudgetPackerProtocol should guarantee total_tokens <= budget.max_tokens
@acms_protocol @per_stage_contract
Scenario: StrategyExecutor handles strategy failures gracefully with circuit breaking
Given a pipeline with a custom coordinator that has a per-strategy cost cap
When I coordinate with a budget of 100 tokens using the capped coordinator
Then the coordination result should list strategies used without raising unhandled exceptions
@acms_protocol @per_stage_contract
Scenario: Fragment deduplication retains highest relevance score for duplicates
Given fusion fragments with duplicates by URI and content
When I fuse with a budget of 500 tokens
Then the coordination fragment count should be less than or equal to total distinct resources
And each unique resource_uri should appear at most once in the output
@acms_protocol @per_stage_contract
Scenario: SkeletonCompressor integrates with parent plan context hierarchy
Given the ACMS pipeline specification describes skeleton compression for child plans
When a child plan's ContextRequest is assembled via ACMSPipeline
Then the payload should include skeleton_fragments derived from parent context
# ---------------------------------------------------------------------------
# TUI component public interfaces — 8+ components with verifiable checks
# ---------------------------------------------------------------------------
@tui_component @public_interface
Scenario: TUI widgets module exports exactly the documented component classes
Given the source directory is at "src/cleveragents"
When I enumerate widgets exported from "tui/widgets/__init__.py"
Then the following widget public interfaces should be present:
| Component |
| ActorSelectionOverlay |
| HelpPanelOverlay |
| PermissionQuestionWidget |
| PersonaBar |
| PromptInput |
| ReferencePickerOverlay |
| SlashCommandOverlay |
| ThoughtBlockWidget |
@tui_component @public_interface
Scenario: All TUI widget classes are Textual-compatible with _StaticBase base
Given the source directory is at "src/cleveragents"
When I check each TUI widget file for its base class
Then every widget in tui/widgets/ should derive from a Static base (Textual or Fallback)
And this provides graceful degradation when Textual is not installed
@tui_component @public_interface
Scenario: PromptInput exposes mode-aware behavior (normal, command, shell, multi-line)
When I verify the PromptInput class interface at cleveragents.tui.widgets.prompt
Then PromptInput should support InputMode enum values for mode-dependent symbol rendering
And PromptInput should emit a PromptSubmitted event on submission
@tui_component @public_interface
Scenario: PersonaBar provides content update API
Given the TUI persona bar module is importable
When I check PersonaBar's public methods
Then PersonaBar should have a set_content method for updating display text
@tui_component @public_interface
Scenario: ReferencePickerOverlay exposes suggestion population API
Given the TUI reference picker module is importable
When I check ReferencePickerOverlay's public methods
Then ReferencePickerOverlay should have a set_suggestions method accepting query and suggestion list
@tui_component @public_interface
Scenario: HelpPanelOverlay provides context-sensitive help rendering
Given the source directory is at "src/cleveragents"
Then HelpPanelOverlay should derive from a base Static widget class with _load_static_base
@tui_component @public_interface
Scenario: Throbber widget defined and documented in specification (8th+ component beyond widgets/)
Given the TUI app module imports widgets
When I verify throbber.py exists in tui/widgets/
Then ThrobberWidget should be a valid widget class with update visibility and animation methods
@tui_component @public_interface
Scenario: TUI total public interface component count meets 8+ requirement
When I count all classes exported from cleveragents.tui.widgets
Then the total component count should be at least 8
And the following minimum set must all be present:
| Component |
| ActorSelectionOverlay |
| HelpPanelOverlay |
| PermissionQuestionWidget |
| PersonaBar |
| PromptInput |
| ReferencePickerOverlay |
| SlashCommandOverlay |
| ThoughtBlockWidget |
| ThrobberWidget |