Skip to content

Shared contracts and value objects for the Conduit tool ecosystem

License

Notifications You must be signed in to change notification settings

conduit-ui/contracts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Conduit UI Contracts

Tests Latest Stable Version Total Downloads License

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:

  1. 100% test coverage maintained
  2. All Pest expectations pass
  3. Code follows Laravel Pint standards
  4. Documentation updated for new contracts

Related Packages

About

Shared contracts and value objects for the Conduit tool ecosystem

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages