# Interface Stability Contract - SDK ↔ Adapter Boundary

**Version**: 1.0  
**Date**: February 14, 2026  
**Status**: DRAFT - Needs Review & Approval

---

## Purpose

This document defines the **stable API contract** between:
- **NT8.Core.dll** (SDK - platform-agnostic)
- **NT8.Adapters.dll** (Adapters - platform-specific)

**Goal**: Ensure SDK updates don't break adapters, and vice versa.

---

## Design Principles

### 1. **Stable Interfaces, Evolving Implementations**
- Interfaces are contracts (change rarely)
- Implementations can evolve freely (change often)
- Adapters depend on interfaces, NOT implementations

### 2. **Semantic Versioning**
- **MAJOR**: Breaking changes to interfaces
- **MINOR**: New features (backward compatible)
- **PATCH**: Bug fixes (no API changes)

### 3. **Explicit Deprecation Cycle**
- Deprecated methods stay for 2+ minor versions
- Mark with `[Obsolete]` attribute
- Provide migration path in docs

---

## Current Interface Contract (v1.0)

### Core SDK Interfaces (STABLE)

These interfaces define the boundary. **Changes require MAJOR version bump.**

#### 1. Strategy Interface

```csharp
// src/NT8.Core/Common/Interfaces/IStrategy.cs
// VERSION: 1.0.0
// STABILITY: STABLE

public interface IStrategy
{
    // Properties
    StrategyMetadata Metadata { get; }
    
    // Methods
    void Initialize(StrategyConfig config, IMarketDataProvider dataProvider, ILogger logger);
    StrategyIntent OnBar(BarData bar, StrategyContext context);
    StrategyIntent OnTick(TickData tick, StrategyContext context);
    Dictionary<string, object> GetParameters();
    void SetParameters(Dictionary<string, object> parameters);
}
```

**Stability Guarantee:**
- ✅ Method signatures won't change
- ✅ Method names won't change
- ✅ Return types won't change (may add properties to returned objects)
- ✅ Parameter types won't change (may add optional parameters)

**Allowed Changes:**
- ➕ Add new optional methods with default implementations
- ➕ Add properties to `StrategyMetadata`
- ➕ Add properties to `StrategyConfig`
- ❌ Cannot remove existing methods
- ❌ Cannot change existing method signatures

---

#### 2. Data Models (STABLE)

```csharp
// src/NT8.Core/Common/Models/BarData.cs
// VERSION: 1.0.0
// STABILITY: STABLE

public class BarData
{
    // Core properties (IMMUTABLE)
    public string Symbol { get; set; }
    public DateTime Time { get; set; }
    public double Open { get; set; }
    public double High { get; set; }
    public double Low { get; set; }
    public double Close { get; set; }
    public long Volume { get; set; }
    public TimeSpan BarSize { get; set; }
    
    // Constructor (IMMUTABLE signature)
    public BarData(
        string symbol,
        DateTime time,
        double open,
        double high,
        double low,
        double close,
        long volume,
        TimeSpan barSize)
    { ... }
}
```

**Stability Guarantee:**
- ✅ Existing properties keep same names
- ✅ Existing properties keep same types
- ✅ Constructor signature won't change (may add overloads)
- ✅ Property getters/setters won't change behavior

**Allowed Changes:**
- ➕ Add new properties (with sensible defaults)
- ➕ Add new constructor overloads
- ➕ Add helper methods
- ❌ Cannot rename existing properties
- ❌ Cannot change property types
- ❌ Cannot remove properties

---

#### 3. Strategy Intent (STABLE)

```csharp
// src/NT8.Core/Common/Models/StrategyIntent.cs
// VERSION: 1.0.0
// STABILITY: STABLE

public class StrategyIntent
{
    // Core properties (IMMUTABLE)
    public string IntentId { get; private set; }
    public DateTime Timestamp { get; private set; }
    public string Symbol { get; set; }
    public OrderSide Side { get; set; }
    public OrderType EntryType { get; set; }
    public double? LimitPrice { get; set; }
    public int StopTicks { get; set; }
    public int? TargetTicks { get; set; }
    public double Confidence { get; set; }
    public string Reason { get; set; }
    public Dictionary<string, object> Metadata { get; set; }
    
    // Constructor (IMMUTABLE signature)
    public StrategyIntent(
        string symbol,
        OrderSide side,
        OrderType entryType,
        double? limitPrice,
        int stopTicks,
        int? targetTicks,
        double confidence,
        string reason,
        Dictionary<string, object> metadata)
    { ... }
    
    // Validation (IMMUTABLE signature)
    public bool IsValid() { ... }
}
```

**Stability Guarantee:**
- ✅ All property names fixed
- ✅ All property types fixed
- ✅ `IsValid()` signature fixed
- ✅ Enums can add new values (but not remove)

**Allowed Changes:**
- ➕ Add new optional properties
- ➕ Add new validation methods
- ➕ Add enum values to `OrderSide`, `OrderType`
- ❌ Cannot remove properties
- ❌ Cannot change property types
- ❌ Cannot remove enum values

---

#### 4. Strategy Context (STABLE)

```csharp
// src/NT8.Core/Common/Models/StrategyContext.cs
// VERSION: 1.0.0
// STABILITY: STABLE

public class StrategyContext
{
    // Core properties (IMMUTABLE)
    public string Symbol { get; set; }
    public DateTime CurrentTime { get; set; }
    public Position CurrentPosition { get; set; }
    public AccountInfo Account { get; set; }
    public MarketSession Session { get; set; }
    public Dictionary<string, object> CustomData { get; set; }
    
    // Constructor (IMMUTABLE signature)
    public StrategyContext(
        string symbol,
        DateTime currentTime,
        Position currentPosition,
        AccountInfo account,
        MarketSession session,
        Dictionary<string, object> customData)
    { ... }
}
```

**Stability Guarantee:**
- ✅ Context structure is stable
- ✅ Nested objects (`Position`, `AccountInfo`, `MarketSession`) can add properties
- ✅ `CustomData` dictionary for extensibility

**Allowed Changes:**
- ➕ Add properties to `Position`, `AccountInfo`, `MarketSession`
- ➕ Add new top-level properties to `StrategyContext`
- ❌ Cannot remove existing properties
- ❌ Cannot change property types

---

### Adapter Interface (SEMI-STABLE)

This is platform-specific. Can evolve more freely.

```csharp
// src/NT8.Adapters/NinjaTrader/INT8Adapter.cs
// VERSION: 1.0.0
// STABILITY: SEMI-STABLE (can evolve between minor versions)

public interface INT8Adapter
{
    // Initialization
    void Initialize(IRiskManager riskManager, IPositionSizer positionSizer);
    
    // Data conversion (SDK models as return types = STABLE)
    BarData ConvertToSdkBar(string symbol, DateTime time, double open, double high, double low, double close, long volume, int barSize);
    AccountInfo ConvertToSdkAccount(double equity, double buyingPower, double dailyPnL, double maxDrawdown, DateTime lastUpdate);
    Position ConvertToSdkPosition(string symbol, int quantity, double averagePrice, double unrealizedPnL, double realizedPnL, DateTime lastUpdate);
    
    // Intent execution (SDK models as parameters = STABLE)
    void ExecuteIntent(StrategyIntent intent, SizingResult sizing);
    
    // NT8 callbacks (NT8-specific parameters = CAN CHANGE)
    void OnOrderUpdate(string orderId, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, string orderState, DateTime time, string errorCode, string nativeError);
    void OnExecutionUpdate(string executionId, string orderId, double price, int quantity, string marketPosition, DateTime time);
}
```

**Stability Guarantee:**
- ✅ Methods that return SDK models are stable
- ✅ Methods that accept SDK models are stable
- 🟡 NT8-specific signatures can evolve (minor versions)

**Allowed Changes:**
- ➕ Add new conversion methods
- ➕ Add optional parameters to NT8-specific methods
- ➕ Add new callback methods
- ❌ Cannot change SDK model signatures
- 🟡 Can change NT8-specific signatures (with deprecation)

---

## Versioning Strategy

### SDK Core (NT8.Core.dll)

```
Version Format: MAJOR.MINOR.PATCH

1.0.0 → Initial release (Phase 1)
1.1.0 → Add new optional features (Phase 2)
1.2.0 → More new features (Phase 3)
2.0.0 → Breaking interface changes (major refactor)
```

**Breaking Changes (MAJOR bump):**
- Remove methods from `IStrategy`
- Change method signatures in core interfaces
- Remove properties from data models
- Change property types in data models

**Compatible Changes (MINOR bump):**
- Add new optional interface methods (with defaults)
- Add new properties to data models
- Add new data models
- Add new interfaces

**Bug Fixes (PATCH bump):**
- Fix bugs in implementations
- Performance improvements
- Internal refactoring
- Documentation updates

---

### Adapters (NT8.Adapters.dll)

```
Version Format: Matches SDK version for compatibility

NT8.Core 1.0.0 → NT8.Adapters 1.0.x (compatible)
NT8.Core 1.1.0 → NT8.Adapters 1.1.x (compatible)
NT8.Core 2.0.0 → NT8.Adapters 2.0.x (requires rewrite)
```

**Adapter versions MUST match SDK MAJOR.MINOR**

---

## Interface Evolution Examples

### Example 1: Adding Optional Feature (MINOR version)

**Scenario**: Add support for multiple targets

```csharp
// v1.0.0 - Original
public class StrategyIntent
{
    public int? TargetTicks { get; set; }
    // ...
}

// v1.1.0 - Enhanced (BACKWARD COMPATIBLE)
public class StrategyIntent
{
    public int? TargetTicks { get; set; }      // Keep for compatibility
    
    // NEW: Optional multiple targets
    public List<int> TargetTicksList { get; set; }  // Defaults to null
    
    // Helper to maintain compatibility
    public int? GetPrimaryTarget()
    {
        if (TargetTicksList != null && TargetTicksList.Count > 0)
            return TargetTicksList[0];
        return TargetTicks;
    }
}
```

**Adapter Impact**: ✅ None - old code still works  
**Strategy Impact**: ✅ None - can optionally use new feature

---

### Example 2: Deprecating Old Method (MINOR version with warning)

**Scenario**: Rename method for clarity

```csharp
// v1.0.0 - Original
public interface IStrategy
{
    StrategyIntent OnBar(BarData bar, StrategyContext context);
}

// v1.1.0 - Add new, deprecate old
public interface IStrategy
{
    [Obsolete("Use OnBarClose instead. Will be removed in v2.0.0")]
    StrategyIntent OnBar(BarData bar, StrategyContext context);
    
    // NEW preferred method
    StrategyIntent OnBarClose(BarData bar, StrategyContext context);
}

// v1.2.0 - Still support both
// ... same as v1.1.0 ...

// v2.0.0 - Remove old (BREAKING CHANGE)
public interface IStrategy
{
    StrategyIntent OnBarClose(BarData bar, StrategyContext context);
}
```

**Migration Timeline**:
- v1.1.0: Add new method, deprecate old (warning)
- v1.2.0: Keep both (warning)
- v2.0.0: Remove old (breaking change, requires adapter update)

---

### Example 3: Breaking Change (MAJOR version)

**Scenario**: Change position model to support multi-symbol

```csharp
// v1.x.x - Original
public class StrategyContext
{
    public Position CurrentPosition { get; set; }  // Single position
}

// v2.0.0 - Breaking change
public class StrategyContext
{
    public Dictionary<string, Position> Positions { get; set; }  // Multi-symbol
    
    // Helper for single-symbol strategies
    public Position GetPosition(string symbol) 
    {
        return Positions.ContainsKey(symbol) ? Positions[symbol] : null;
    }
}
```

**Adapter Impact**: ❌ Must update - breaking change  
**Migration Required**: Yes, all adapters need rewrite  
**Version Bump**: 1.x.x → 2.0.0

---

## Compatibility Matrix

### SDK ↔ Adapter Compatibility

| SDK Version | Adapter Version | Compatible? | Notes |
|-------------|-----------------|-------------|-------|
| 1.0.0 | 1.0.x | ✅ Yes | Perfect match |
| 1.1.0 | 1.0.x | ✅ Yes | Forward compatible |
| 1.1.0 | 1.1.x | ✅ Yes | Perfect match |
| 1.2.0 | 1.1.x | ✅ Yes | Forward compatible |
| 2.0.0 | 1.x.x | ❌ No | Breaking change |
| 2.0.0 | 2.0.x | ✅ Yes | Perfect match |

**Rule**: Adapter MINOR can be less than SDK MINOR (forward compatible)  
**Rule**: Adapter MAJOR must equal SDK MAJOR

---

## Contract Testing

### Automated Contract Tests

Create tests that verify interface stability:

```csharp
// tests/NT8.Core.Tests/Contracts/InterfaceStabilityTests.cs

[Fact]
public void IStrategy_Interface_Should_Be_Stable()
{
    var type = typeof(IStrategy);
    
    // Verify method count hasn't decreased
    var methods = type.GetMethods();
    Assert.True(methods.Length >= 5, "IStrategy methods removed!");
    
    // Verify specific methods exist
    Assert.NotNull(type.GetMethod("OnBar"));
    Assert.NotNull(type.GetMethod("OnTick"));
    Assert.NotNull(type.GetMethod("Initialize"));
    
    // Verify method signatures
    var onBarMethod = type.GetMethod("OnBar");
    Assert.Equal(typeof(StrategyIntent), onBarMethod.ReturnType);
    
    var parameters = onBarMethod.GetParameters();
    Assert.Equal(2, parameters.Length);
    Assert.Equal(typeof(BarData), parameters[0].ParameterType);
    Assert.Equal(typeof(StrategyContext), parameters[1].ParameterType);
}

[Fact]
public void BarData_Properties_Should_Be_Stable()
{
    var type = typeof(BarData);
    
    // Verify required properties exist
    Assert.NotNull(type.GetProperty("Symbol"));
    Assert.NotNull(type.GetProperty("Time"));
    Assert.NotNull(type.GetProperty("Open"));
    Assert.NotNull(type.GetProperty("High"));
    Assert.NotNull(type.GetProperty("Low"));
    Assert.NotNull(type.GetProperty("Close"));
    Assert.NotNull(type.GetProperty("Volume"));
    
    // Verify property types haven't changed
    Assert.Equal(typeof(string), type.GetProperty("Symbol").PropertyType);
    Assert.Equal(typeof(DateTime), type.GetProperty("Time").PropertyType);
    Assert.Equal(typeof(double), type.GetProperty("Open").PropertyType);
}

[Fact]
public void StrategyIntent_Constructor_Should_Be_Stable()
{
    var type = typeof(StrategyIntent);
    
    // Verify constructor exists with expected parameters
    var constructor = type.GetConstructor(new[]
    {
        typeof(string),              // symbol
        typeof(OrderSide),           // side
        typeof(OrderType),           // entryType
        typeof(double?),             // limitPrice
        typeof(int),                 // stopTicks
        typeof(int?),                // targetTicks
        typeof(double),              // confidence
        typeof(string),              // reason
        typeof(Dictionary<string, object>)  // metadata
    });
    
    Assert.NotNull(constructor);
}
```

**Run these tests** in CI/CD to catch accidental breaking changes!

---

## Adapter-Safe Practices

### For SDK Developers

**DO:**
- ✅ Add optional parameters with defaults
- ✅ Add new properties with sensible defaults
- ✅ Add new interfaces for new features
- ✅ Add helper methods to existing classes
- ✅ Mark deprecated methods with `[Obsolete]`
- ✅ Run contract tests before release

**DON'T:**
- ❌ Remove existing methods
- ❌ Change method signatures
- ❌ Rename properties
- ❌ Change property types
- ❌ Remove enum values
- ❌ Break existing constructors

### For Adapter Developers

**DO:**
- ✅ Depend only on interfaces, not implementations
- ✅ Use factory patterns for object creation
- ✅ Handle new optional properties gracefully
- ✅ Catch and log unknown enum values
- ✅ Version-check SDK at runtime if needed

**DON'T:**
- ❌ Depend on internal implementation details
- ❌ Assume fixed property counts
- ❌ Hard-code enum values
- ❌ Access private members via reflection

---

## Naming Conventions (IMMUTABLE)

These naming patterns are **contracts** and won't change:

### Interface Names
```
Pattern: I{Concept}
Examples: IStrategy, IRiskManager, IPositionSizer, ILogger
```

### Model Classes
```
Pattern: {Concept}{Type}
Examples: BarData, TickData, StrategyIntent, StrategyContext
```

### Enums
```
Pattern: {Concept}{Optional Suffix}
Examples: OrderSide, OrderType, TickType, RiskLevel
```

### Methods
```
Pattern: {Verb}{Noun}
Examples: OnBar, OnTick, Initialize, ValidateOrder, CalculateSize
```

### Properties
```
Pattern: {Noun} or {Adjective}{Noun}
Examples: Symbol, Timestamp, CurrentPosition, DailyPnL
```

**These patterns are STABLE and won't change.**

---

## Extension Points (For Future Growth)

### 1. Metadata Dictionaries
```csharp
public Dictionary<string, object> Metadata { get; set; }
```
**Use for**: Adding data without breaking compatibility

### 2. Optional Parameters
```csharp
public void Initialize(
    StrategyConfig config, 
    IMarketDataProvider dataProvider, 
    ILogger logger,
    Dictionary<string, object> options = null)  // Extension point
```

### 3. Interface Composition
```csharp
// Instead of changing IStrategy, create new interface
public interface IAdvancedStrategy : IStrategy
{
    void OnMarketDepth(MarketDepthData depth);
}
```

### 4. Feature Flags
```csharp
public class StrategyMetadata
{
    public Dictionary<string, bool> SupportedFeatures { get; set; }
}
```

**Adapters can check**: `if (metadata.SupportedFeatures["MultiTarget"]) { ... }`

---

## Documentation Requirements

### For Every Interface Change

**Must Document:**
1. **What changed** (method/property added/removed/changed)
2. **Why it changed** (business reason)
3. **Version** it changed in
4. **Migration path** for adapters
5. **Deprecation timeline** (if applicable)

**Example**:
```markdown
## v1.1.0 - January 2026

### Added
- `StrategyIntent.TargetTicksList` - Support for multiple profit targets
  - **Migration**: Not required. Old code using `TargetTicks` still works.
  - **New feature**: Strategies can now specify multiple targets.
  
### Deprecated
- `IStrategy.OnBar()` - Deprecated in favor of `OnBarClose()`
  - **Reason**: Clearer naming for bar-close strategies
  - **Timeline**: Will be removed in v2.0.0 (12+ months)
  - **Migration**: Replace `OnBar` with `OnBarClose` (same signature)
```

---

## Approval Process

### Before Releasing Interface Changes

**Required Reviews:**
1. ✅ Technical review (breaking vs. non-breaking)
2. ✅ Contract tests pass
3. ✅ Documentation updated
4. ✅ Migration guide written (if needed)
5. ✅ Version number updated correctly

**For Breaking Changes:**
1. ✅ All of the above, plus:
2. ✅ Deprecation period completed (2+ minor versions)
3. ✅ Adapter developers notified 30+ days in advance
4. ✅ Migration tooling provided (if possible)

---

## Summary

### The Contract

**SDK Core provides:**
- Stable interfaces (`IStrategy`, `IRiskManager`, `IPositionSizer`)
- Stable data models (`BarData`, `StrategyIntent`, `StrategyContext`)
- Versioned API (semantic versioning)
- Backward compatibility within MAJOR versions

**Adapters rely on:**
- Interface contracts (not implementations)
- Data model structures
- Method signatures
- Enum values

**The promise:**
- SDK can evolve WITHOUT breaking adapters (within MAJOR version)
- Adapters can evolve WITHOUT rewriting SDK
- Clear versioning communicates compatibility
- Deprecation gives time to migrate

---

## Action Items

### Immediate (Before Phase 1 Release)

- [ ] Review all public interfaces for stability
- [ ] Add contract tests to CI/CD
- [ ] Document current interface versions
- [ ] Establish version numbering (start at 1.0.0)
- [ ] Get team approval on this contract

### Ongoing

- [ ] Run contract tests on every build
- [ ] Review all PR's for interface stability
- [ ] Document changes in CHANGELOG.md
- [ ] Notify adapter developers of deprecations
- [ ] Maintain compatibility matrix

---

**Version History:**
- v1.0 (2026-02-14): Initial draft
- [Future versions will be listed here]

