Savvi Studio

Gap 2: Declarative Tool Contracts - Implementation Summary

Implementation completed: Thursday 4/4/2026 (as per WEEKLY_ACTION_ITEMS_20260401.md)


✅ Deliverables Completed

1. Package Structure Created

  • Path: /Volumes/Workspace/savvi-studio-full/packages/tool-contracts
  • Files:
    • package.json — Workspace member with zod dependency
    • tsconfig.json — TypeScript configuration extending base
    • vitest.config.ts — Test runner configuration
    • src/contracts.ts — Core contract system
    • src/index.ts — Public exports
    • src/contracts.test.ts — Comprehensive test suite

2. Core Interfaces Implemented

SemanticType Registry

type SemanticType = 'ltree-path' | 'resource-id' | 'module-ref' | 'uuid' | 'semver' | 'file-path' | 'json-object' | 'unknown'

Predicate Types

interface PreconditionPredicate {
    description: string;
    errorCode: string;
    evaluate: (context: Record<string, unknown>) => boolean;
}

interface PostconditionPredicate {
    description: string;
    errorCode: string;
    evaluate: (context: Record<string, unknown>) => boolean;
}

DeclaredToolContract Interface

interface DeclaredToolContract {
    toolName: string;
    description: string;
    inputSchema: z.ZodSchema;
    outputSchema: z.ZodSchema;
    inputSemanticTypes?: Record<string, SemanticType>;
    outputSemanticTypes?: Record<string, SemanticType>;
    preconditions?: PreconditionPredicate[];
    postconditions?: PostconditionPredicate[];
    dependencies?: string[];
    capabilities: CapabilityTag[];
    resourceLimits?: ResourceLimits;
}

Tool Dependency Graph

interface ToolDependencyGraph {
    tools: Map<string, DeclaredToolContract>;
    dependencies: Map<string, Set<string>>;
    validate(): string[]; // Returns circular/unregistered dependency errors
}

3. Utility Functions

  • createToolDependencyGraph() — Initialize new dependency graph
  • registerToolContract() — Register tool with dependency tracking
  • createPrecondition() — Factory for precondition predicates
  • createPostcondition() — Factory for postcondition predicates
  • evaluatePreconditions() — Evaluate all preconditions, return errors
  • evaluatePostconditions() — Evaluate all postconditions, return errors

4. Test Coverage: 14 Tests (100% Passing)

✓ should create a tool dependency graph
✓ should register tool contracts
✓ should track dependencies between tools
✓ should detect circular dependencies
✓ should detect unregistered dependencies
✓ should evaluate preconditions
✓ should handle missing preconditions
✓ should evaluate postconditions
✓ should handle missing postconditions
✓ should catch precondition evaluation errors
✓ should catch postcondition evaluation errors
✓ should evaluate multiple conditions
✓ should validate semantic types
✓ should construct complex preconditions for real scenarios

✅ Integration Status

Registry: pnpm-workspace.yaml

  • Added packages/tool-contracts to workspace packages list (alphabetically ordered)

Dependencies

  • zod@^3.22.4 — Schema validation
  • Dev deps: @types/node, typescript, vitest

TypeScript Compilation

✅ tool-contracts: 0 errors
✅ studio-mcp: 0 errors

Regression Testing

  • studio-mcp unit tests: 8 tests passed ✅
  • studio-mcp integration tests: 23 tests passed ✅
  • Gap 1 execution-steps tests: 4 tests passed ✅

📋 What's Next (Friday 4/5)

Integration Phase (Optional Acceleration)

If proceeding today instead of Friday:

  1. Add @savvi-studio/tool-contracts to studio-mcp dependencies
  2. Wire DeclaredToolContract into modules.compile handler
  3. Add contract validation to compile bootstrap
  4. Extend tool registration to include preconditions/postconditions

Standard Friday Workflow

  • Run all existing tests (✅ verified no regressions)
  • Plan Phase 2B (Observability) scope
  • Update SESSION_SYNTHESIS_20260401.md with decision log

📊 Architecture Notes

Design Decisions

  1. Separation of Concerns: Tool contracts live independently from studio-mcp

    • Allows reuse in other frameworks
    • Single responsibility principle
    • Future: could be npm publishable
  2. Predicate Pattern: Function-based evaluation vs declarative strings

    • Enables arbitrary runtime logic
    • Error handling at source
    • Testable without MCP runtime
  3. Semantic Types: Registry vs inheritance

    • Type-safe but extensible
    • Allows validation without full runtime
    • Compatible with codegen tools
  4. Dependency Graph: Explicit cycle detection

    • Fast O(n) circular dependency check
    • Clear error messages
    • Early validation before deployment

Evolution Path

Phase 2A (Current):
  Tool Contracts Framework ✅
  + Execution Steps ✅
  
Phase 2B (Next):
  Integrate tool contracts into modules.compile
  Add precondition/postcondition validation
  Extend query_state to include contract metadata
  
Phase 3:
  Schema-driven tool registry
  Async model patterns
  Tool versioning system

🔍 File Locations

  • Framework: /packages/tool-contracts/src/contracts.ts (180 lines)
  • Tests: /packages/tool-contracts/src/contracts.test.ts (238 lines)
  • Public API: /packages/tool-contracts/src/index.ts (22 lines)
  • Config: /packages/tool-contracts/package.json, tsconfig.json, vitest.config.ts

✨ Success Criteria Met

Goal: Add preconditions/postconditions metadata to tools ✅ Package skeleton created and configured ✅ All interfaces defined and exported ✅ Test suite comprehensive (14 tests, 100% passing) ✅ No regressions in studio-mcp or execution steps ✅ TypeScript compiles with zero errors ✅ Ready for integration into studio-mcp on Friday 4/5


Status: COMPLETE Time: Thursday 4/4/2026 Elapsed: ~45 minutes (package setup, interface design, comprehensive test suite)