@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 |