conduit-ui / contracts
Shared contracts and value objects for the Conduit tool ecosystem
v0.2.0
2026-08-22 17:41 UTC
Requires
- php: ^8.3
Requires (Dev)
- laravel/framework: ^12.0|^13.0
- pestphp/pest: ^3.0
README
Shared contracts and value objects for the Conduit tool ecosystem.
Overview
Conduit Contracts provides a foundation for building composable, role-based tools with guaranteed quality through shipped tests and custom Pest expectations.
The Composability Guarantee
Every tool in the Conduit ecosystem ships with 100% test coverage. When you compose tools together, you only need to test your composition logic - the tools themselves are pre-validated.
Example leverage:
- 10 tools × 19 tests each = 190 tests normally required
- With Conduit: Only 20 tests needed (89% reduction)
- 8.5x testing leverage
Installation
composer require conduit-ui/contracts
Core Concepts
Tool Roles
Every tool performs exactly ONE role:
use ConduitUI\ValueObjects\ToolRole; ToolRole::MUSIC; // Spotify, Apple Music ToolRole::INTAKE; // GitHub Issues, Linear ToolRole::ATTEMPT; // Git commits, code fixes ToolRole::SUBMISSION; // Pull requests ToolRole::VALIDATION; // Tests, linters ToolRole::DELIVERY; // CI/CD, deployment ToolRole::MEMORY; // Vector databases ToolRole::ANALYSIS; // LLMs, AI services
Contracts
All tools implement these interfaces:
Tool- Base contract (execute, isAvailable, role, getProviderName)Observable- Event emission (emitStarted, emitCompleted, emitFailed)KnowledgeAware- Knowledge integration (recordToKnowledge, loadContext, queryKnowledge)
Role-specific contracts extend the base:
MusicProvider- suggestPlaylist(), playSong(), detectEmotionalState()IntakeManager- receiveWorkRequest(), classifyRequest(), routeToAgent()AttemptExecutor- attemptSolution(), validateAttempt(), retryOnFailure()SubmissionHandler- proposeSolution(), requestReview(), handleFeedback()ValidationRunner- runValidation(), getViolations()DeliveryHandler- deploy(), rollback(), healthCheck()MemoryProvider- store(), retrieve(), embed(), search()AnalysisProvider- analyze(), reason(), compare()
Building a Tool
1. Implement the Contract
use ConduitUI\Contracts\Tool; use ConduitUI\Contracts\Roles\MusicProvider; use ConduitUI\ValueObjects\{ToolRole, Context, Result, EmotionalState}; class SpotifyTool implements Tool, MusicProvider { public function role(): ToolRole { return ToolRole::MUSIC; } public function getProviderName(): string { return 'Spotify'; } public function isAvailable(): bool { return ! empty(config('services.spotify.token')); } public function execute(Context $context): Result { $this->emitStarted($context); try { // Implementation $result = Result::success('Playlist started'); $this->emitCompleted($result); return $result; } catch (\Throwable $e) { $this->emitFailed($e); return Result::failure('Failed to start playlist', $e); } } // MusicProvider methods public function suggestPlaylist(EmotionalState $state): string { /* ... */ } public function playSong(string $songId): Result { /* ... */ } public function detectEmotionalState(): EmotionalState { /* ... */ } // Observable methods public function emitStarted(Context $context): void { /* ... */ } public function emitCompleted(Result $result): void { /* ... */ } public function emitFailed(\Throwable $exception): void { /* ... */ } // KnowledgeAware methods public function recordToKnowledge(Result $result): void { /* ... */ } public function loadContext(string $collection): Context { /* ... */ } public function queryKnowledge(array $criteria): array { /* ... */ } }
2. Extend the Abstract Test
use ConduitUI\Tests\Contracts\Roles\MusicProviderContractTest; use ConduitUI\ValueObjects\{ToolRole, Context}; class SpotifyToolTest extends MusicProviderContractTest { protected function createTool(): Tool { return new SpotifyTool(); } protected function createValidContext(): Context { return new MusicContext( mood: 'focused', energy: 0.8 ); } protected function expectedRole(): ToolRole { return ToolRole::MUSIC; } protected function getValidPlaylistId(): string { return 'test-playlist-id'; } protected function getValidSongId(): string { return 'test-song-id'; } }
3. Run the Shipped Tests
The abstract test automatically validates:
- ✅ Implements all required interfaces
- ✅ Returns correct role
- ✅ Executes and returns Result
- ✅ Emits events properly
- ✅ Records to knowledge
- ✅ All role-specific methods work
Custom Pest Expectations
use function ConduitUI\Tests\Pest\Expectations\expect; // Tool validation expect($tool)->toBeAValidConduitTool(); expect($tool)->toHaveRole(ToolRole::MUSIC); expect($tool)->toBeAvailable(); // Execution expect($tool)->toExecuteSuccessfully($context); expect($tool)->toFailExecution($invalidContext); // Events expect($tool)->toEmitStartedEvent($context); expect($tool)->toEmitCompletedEvent($result); // Results expect($result)->toBeASuccessfulResult(); expect($result)->toBeAFailedResult(); expect($result)->toHaveResultMessage('Operation completed'); // Knowledge expect($tool)->toRecordToKnowledge($result); expect($tool)->toLoadContextFromKnowledge('collection');
Value Objects
Result
use ConduitUI\ValueObjects\Result; // Success $result = Result::success( message: 'Deployment completed', data: ['deployment_id' => 123], metadata: ['duration' => 45.2] ); // Failure $result = Result::failure( message: 'Database connection failed', error: $exception, metadata: ['retry_count' => 3] ); // Check outcome if ($result->isSuccess()) { // Handle success }
Context
use ConduitUI\ValueObjects\Context; use ConduitUI\ValueObjects\ToolRole; class MusicContext extends Context { public function __construct( public string $mood, public float $energy, public array $preferences = [] ) {} public function role(): ToolRole { return ToolRole::MUSIC; } public function toArray(): array { return [ 'mood' => $this->mood, 'energy' => $this->energy, 'preferences' => $this->preferences, ]; } }
Testing
composer test
composer test-coverage
License
MIT License. See LICENSE for details.
Contributing
Contributions welcome! Please ensure:
- 100% test coverage maintained
- All Pest expectations pass
- Code follows Laravel Pint standards
- Documentation updated for new contracts
Related Packages
- conduit-ui/issue - GitHub issue management
- conduit-ui/pr - Pull request operations
- conduit-ui/commit - Git commit operations
- conduit-ui/spotify - Spotify integration