# Phase C: Deployment Automation & Integration Testing - Detailed Specification **For:** Kilocode AI Agent (Autonomous Implementation) **Phase:** Phase C - Deployment & Testing **Components:** Deployment Script + Integration Tests **Estimated Time:** 3-4 hours **Mode:** Code Mode **Dependencies:** Phases A & B must be complete --- ## 🎯 Objective Create automated deployment tooling and comprehensive integration tests to validate the complete NT8 SDK integration. This phase ensures our SDK can be reliably deployed to NinjaTrader 8 and runs correctly end-to-end. --- ## 📋 Component 1: Deployment Automation Script ### Overview PowerShell script that automates the complete deployment process from SDK build to NT8 strategy compilation. ### Location **Create:** `deployment/Deploy-To-NT8.ps1` ### Full Implementation ```powershell <# .SYNOPSIS Automates deployment of NT8 SDK to NinjaTrader 8. .DESCRIPTION This script: 1. Builds SDK in Release mode 2. Runs all unit tests 3. Copies DLLs to NT8 Custom directory 4. Copies strategy files to NT8 Strategies directory 5. Verifies deployment .PARAMETER BuildFirst Build SDK before deploying (default: true) .PARAMETER RunTests Run tests before deploying (default: true) .PARAMETER CopyStrategies Copy strategy .cs files (default: true) .PARAMETER SkipVerification Skip deployment verification (default: false) .EXAMPLE .\Deploy-To-NT8.ps1 Full deployment with build, tests, and verification .EXAMPLE .\Deploy-To-NT8.ps1 -BuildFirst:$false -RunTests:$false Deploy without building or testing (fast deployment) .NOTES Requires: - .NET Framework 4.8 SDK - NinjaTrader 8 installed - PowerShell 5.1 or higher #> param( [switch]$BuildFirst = $true, [switch]$RunTests = $true, [switch]$CopyStrategies = $true, [switch]$SkipVerification = $false, [string]$Configuration = "Release" ) $ErrorActionPreference = "Stop" #region Configuration $sdkRoot = "C:\dev\nt8-sdk" $nt8Custom = "$env:USERPROFILE\Documents\NinjaTrader 8\bin\Custom" $nt8Strategies = "$nt8Custom\Strategies" # Source paths $coreDllPath = "$sdkRoot\src\NT8.Core\bin\$Configuration\net48" $adaptersDllPath = "$sdkRoot\src\NT8.Adapters\bin\$Configuration\net48" $strategiesPath = "$sdkRoot\src\NT8.Adapters\Strategies" # Verify paths exist if (-not (Test-Path $sdkRoot)) { Write-Error "SDK root not found: $sdkRoot" exit 1 } if (-not (Test-Path $nt8Custom)) { Write-Error "NinjaTrader 8 Custom directory not found: $nt8Custom" Write-Host "Please verify NinjaTrader 8 is installed" -ForegroundColor Red exit 1 } #endregion #region Helper Functions function Write-Header { param([string]$Message) Write-Host "" Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host $Message -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan } function Write-Step { param( [string]$Step, [string]$Message ) Write-Host "`n[$Step] $Message" -ForegroundColor Yellow } function Write-Success { param([string]$Message) Write-Host " ✓ $Message" -ForegroundColor Green } function Write-Warning { param([string]$Message) Write-Host " ⚠ $Message" -ForegroundColor Yellow } function Write-Failure { param([string]$Message) Write-Host " ✗ $Message" -ForegroundColor Red } #endregion #region Main Deployment Write-Header "NT8 SDK Deployment Script" Write-Host "Configuration: $Configuration" -ForegroundColor White Write-Host "SDK Root: $sdkRoot" -ForegroundColor White Write-Host "NT8 Custom: $nt8Custom" -ForegroundColor White Write-Host "" $startTime = Get-Date #region Step 1: Build SDK if ($BuildFirst) { Write-Step "1/6" "Building SDK..." Push-Location $sdkRoot try { # Clean previous builds Write-Host " Cleaning previous builds..." & dotnet clean --configuration $Configuration --verbosity quiet if ($LASTEXITCODE -ne 0) { Write-Failure "Clean failed" Pop-Location exit 1 } # Build Write-Host " Building SDK..." & dotnet build --configuration $Configuration --verbosity quiet if ($LASTEXITCODE -ne 0) { Write-Failure "Build failed" Pop-Location exit 1 } Write-Success "Build succeeded" } finally { Pop-Location } } else { Write-Step "1/6" "Skipping build (BuildFirst = false)" } #endregion #region Step 2: Run Tests if ($RunTests) { Write-Step "2/6" "Running tests..." Push-Location $sdkRoot try { Write-Host " Executing test suite..." $testOutput = & dotnet test --configuration $Configuration --no-build --verbosity quiet if ($LASTEXITCODE -ne 0) { Write-Failure "Tests failed" Write-Host $testOutput Pop-Location exit 1 } # Parse test results $passedMatch = $testOutput | Select-String "Passed!\s+-\s+Failed:\s+(\d+),\s+Passed:\s+(\d+)" if ($passedMatch) { $failed = $passedMatch.Matches[0].Groups[1].Value $passed = $passedMatch.Matches[0].Groups[2].Value if ($failed -eq "0") { Write-Success "All tests passed ($passed tests)" } else { Write-Failure "$failed tests failed, $passed passed" Pop-Location exit 1 } } else { Write-Success "Tests completed" } } finally { Pop-Location } } else { Write-Step "2/6" "Skipping tests (RunTests = false)" } #endregion #region Step 3: Copy SDK DLLs Write-Step "3/6" "Copying SDK DLLs..." # Core DLL if (Test-Path "$coreDllPath\NT8.Core.dll") { Copy-Item "$coreDllPath\NT8.Core.dll" $nt8Custom -Force Write-Success "Copied NT8.Core.dll" } else { Write-Failure "NT8.Core.dll not found" exit 1 } # Core PDB (for debugging) if (Test-Path "$coreDllPath\NT8.Core.pdb") { Copy-Item "$coreDllPath\NT8.Core.pdb" $nt8Custom -Force Write-Success "Copied NT8.Core.pdb" } # Adapters DLL (if it exists - Phase A/B might not build it) if (Test-Path "$adaptersDllPath\NT8.Adapters.dll") { Copy-Item "$adaptersDllPath\NT8.Adapters.dll" $nt8Custom -Force Write-Success "Copied NT8.Adapters.dll" if (Test-Path "$adaptersDllPath\NT8.Adapters.pdb") { Copy-Item "$adaptersDllPath\NT8.Adapters.pdb" $nt8Custom -Force Write-Success "Copied NT8.Adapters.pdb" } } else { Write-Warning "NT8.Adapters.dll not found (expected if not built as DLL)" } #endregion #region Step 4: Copy Dependencies Write-Step "4/6" "Copying dependencies..." $dependencies = @( "Microsoft.Extensions.*.dll", "System.Memory.dll", "System.Buffers.dll", "System.Runtime.CompilerServices.Unsafe.dll" ) $copiedCount = 0 foreach ($pattern in $dependencies) { $files = Get-ChildItem "$coreDllPath\$pattern" -ErrorAction SilentlyContinue foreach ($file in $files) { Copy-Item $file.FullName $nt8Custom -Force Write-Success "Copied $($file.Name)" $copiedCount++ } } if ($copiedCount -eq 0) { Write-Warning "No dependencies found (this may be normal)" } else { Write-Success "Copied $copiedCount dependency files" } #endregion #region Step 5: Copy Strategy Files if ($CopyStrategies) { Write-Step "5/6" "Copying strategy files..." # Ensure strategies directory exists if (-not (Test-Path $nt8Strategies)) { New-Item -ItemType Directory -Path $nt8Strategies -Force | Out-Null Write-Success "Created Strategies directory" } $strategyFiles = @( "NT8StrategyBase.cs", "SimpleORBNT8.cs", "MinimalTestStrategy.cs" ) $copiedStrategies = 0 foreach ($file in $strategyFiles) { $sourcePath = Join-Path $strategiesPath $file if (Test-Path $sourcePath) { Copy-Item $sourcePath $nt8Strategies -Force Write-Success "Copied $file" $copiedStrategies++ } else { Write-Warning "$file not found (skipping)" } } if ($copiedStrategies -eq 0) { Write-Failure "No strategy files copied" exit 1 } } else { Write-Step "5/6" "Skipping strategy files (CopyStrategies = false)" } #endregion #region Step 6: Verify Deployment if (-not $SkipVerification) { Write-Step "6/6" "Verifying deployment..." $verificationPassed = $true # Check Core DLL if (Test-Path "$nt8Custom\NT8.Core.dll") { $coreInfo = Get-Item "$nt8Custom\NT8.Core.dll" $coreVersion = $coreInfo.VersionInfo.FileVersion Write-Success "NT8.Core.dll present (v$coreVersion)" } else { Write-Failure "NT8.Core.dll missing" $verificationPassed = $false } # Check strategy files foreach ($file in $strategyFiles) { $targetPath = Join-Path $nt8Strategies $file if (Test-Path $targetPath) { $fileInfo = Get-Item $targetPath $fileSizeKB = [math]::Round($fileInfo.Length / 1KB, 2) Write-Success "$file present ($fileSizeKB KB)" } else { Write-Failure "$file missing" $verificationPassed = $false } } if (-not $verificationPassed) { Write-Host "" Write-Failure "Deployment verification failed" exit 1 } } else { Write-Step "6/6" "Skipping verification (SkipVerification = true)" } #endregion #region Completion $endTime = Get-Date $duration = $endTime - $startTime Write-Header "Deployment Complete!" Write-Host "" Write-Host "Summary:" -ForegroundColor Cyan Write-Host " Duration: $($duration.TotalSeconds.ToString('F1')) seconds" Write-Host " SDK DLLs: Copied to $nt8Custom" Write-Host " Strategies: Copied to $nt8Strategies" Write-Host "" Write-Host "Next Steps:" -ForegroundColor Yellow Write-Host " 1. Open NinjaTrader 8" Write-Host " 2. Tools → NinjaScript Editor (F5)" Write-Host " 3. Compile → Compile All (F5)" Write-Host " 4. Verify compilation succeeds" Write-Host " 5. Create strategy instance on chart" Write-Host " 6. Test in simulation before live trading" Write-Host "" Write-Host "Strategy Files Deployed:" -ForegroundColor Cyan foreach ($file in $strategyFiles) { $targetPath = Join-Path $nt8Strategies $file if (Test-Path $targetPath) { Write-Host " ✓ $file" } } Write-Host "" Write-Success "Deployment succeeded!" #endregion exit 0 ``` --- ## 📋 Component 2: Integration Test Suite ### Overview Comprehensive integration tests that validate end-to-end functionality. ### Location **Create:** `tests/NT8.Integration.Tests/NT8IntegrationTests.cs` ### Full Implementation ```csharp using System; using System.Collections.Generic; using System.Threading; using Xunit; using FluentAssertions; using NT8.Core.Common.Interfaces; using NT8.Core.Common.Models; using NT8.Core.Risk; using NT8.Core.Sizing; using NT8.Core.Logging; using NT8.Adapters.NinjaTrader; using NT8.Strategies.Examples; namespace NT8.Integration.Tests { /// /// Integration tests for NT8 SDK end-to-end workflows. /// Tests complete flow: Strategy → Risk → Sizing → OMS → Adapter /// public class NT8IntegrationTests { #region Helper Methods private StrategyContext CreateTestContext( string symbol = "ES", int positionQuantity = 0, double equity = 100000.0, double dailyPnL = 0.0) { var currentTime = new DateTime(2026, 2, 17, 10, 30, 0); var position = new Position( symbol, positionQuantity, 0, 0, dailyPnL, currentTime); var account = new AccountInfo( equity, equity * 2.5, dailyPnL, 0, currentTime); var session = new MarketSession( currentTime.Date.AddHours(9).AddMinutes(30), currentTime.Date.AddHours(16), true, "RTH"); var customData = new Dictionary(); return new StrategyContext( symbol, currentTime, position, account, session, customData); } private BarData CreateTestBar( string symbol = "ES", double open = 4200.0, double high = 4210.0, double low = 4195.0, double close = 4208.0) { return new BarData( symbol, new DateTime(2026, 2, 17, 10, 30, 0), open, high, low, close, 10000, TimeSpan.FromMinutes(5)); } #endregion #region End-to-End Workflow Tests [Fact] public void CompleteWorkflow_StrategyToExecution_ShouldProcessIntent() { // Arrange var logger = new BasicLogger("IntegrationTest"); var riskManager = new BasicRiskManager(logger); var positionSizer = new BasicPositionSizer(logger); var executionAdapter = new NT8ExecutionAdapter(); var strategy = new SimpleORBStrategy(30, 1.0); var config = new StrategyConfig( "TestStrategy", "ES", new Dictionary(), new RiskConfig(1000.0, 200.0, 3, true), new SizingConfig(SizingMethod.FixedDollarRisk, 1, 10, 100.0, new Dictionary()) ); strategy.Initialize(config, null, logger); var context = CreateTestContext(); var bar = CreateTestBar(); // Act - Generate intent var intent = strategy.OnBar(bar, context); // If intent generated, process through risk/sizing if (intent != null) { // Risk validation var riskDecision = riskManager.ValidateOrder( intent, context, config.RiskSettings); riskDecision.Should().NotBeNull(); if (riskDecision.Approved) { // Position sizing var sizingResult = positionSizer.CalculateSize( intent, context, config.SizingSettings); sizingResult.Should().NotBeNull(); sizingResult.Contracts.Should().BeGreaterOrEqualTo(1); sizingResult.Contracts.Should().BeLessOrEqualTo(10); // Order submission (tracked, not executed) var orderRequest = new OrderRequest( intent.Symbol, intent.Side, sizingResult.Contracts, intent.EntryType, intent.LimitPrice, intent.StopPrice ); var orderName = string.Format("TEST_{0}", Guid.NewGuid().ToString("N")); var trackingInfo = executionAdapter.SubmitOrder(orderRequest, orderName); trackingInfo.Should().NotBeNull(); trackingInfo.SdkOrderId.Should().Be(orderName); trackingInfo.CurrentState.Should().Be(OrderState.Pending); } } // Assert - No exceptions thrown // Complete workflow executed successfully } [Fact] public void DataConversion_NT8ToSDK_ShouldPreserveData() { // Arrange var symbol = "ES"; var time = new DateTime(2026, 2, 17, 10, 0, 0); var open = 4200.0; var high = 4215.0; var low = 4192.0; var close = 4210.0; var volume = 15000L; var barSizeMinutes = 5; // Act var barData = NT8DataConverter.ConvertBar( symbol, time, open, high, low, close, volume, barSizeMinutes); // Assert barData.Symbol.Should().Be(symbol); barData.Time.Should().Be(time); barData.Open.Should().Be(open); barData.High.Should().Be(high); barData.Low.Should().Be(low); barData.Close.Should().Be(close); barData.Volume.Should().Be(volume); barData.BarSize.Should().Be(TimeSpan.FromMinutes(barSizeMinutes)); } [Fact] public void ExecutionAdapter_OrderLifecycle_ShouldTrackCorrectly() { // Arrange var adapter = new NT8ExecutionAdapter(); var orderRequest = new OrderRequest( "ES", OrderSide.Buy, 2, OrderType.Market, null, null); var orderName = "TEST_001"; // Act & Assert - Submit var trackingInfo = adapter.SubmitOrder(orderRequest, orderName); trackingInfo.CurrentState.Should().Be(OrderState.Pending); // Act & Assert - Working adapter.ProcessOrderUpdate( "NT8_123", orderName, "WORKING", 0, 0, 0, null); var status = adapter.GetOrderStatus(orderName); status.State.Should().Be(OrderState.Working); // Act & Assert - Partial Fill adapter.ProcessOrderUpdate( "NT8_123", orderName, "PARTFILLED", 1, 4200.50, 0, null); adapter.ProcessExecution( "NT8_123", "EXEC_001", 4200.50, 1, DateTime.UtcNow); status = adapter.GetOrderStatus(orderName); status.State.Should().Be(OrderState.PartiallyFilled); status.Filled.Should().Be(1); // Act & Assert - Filled adapter.ProcessOrderUpdate( "NT8_123", orderName, "FILLED", 2, 4200.75, 0, null); adapter.ProcessExecution( "NT8_123", "EXEC_002", 4201.0, 1, DateTime.UtcNow); status = adapter.GetOrderStatus(orderName); status.State.Should().Be(OrderState.Filled); status.Filled.Should().Be(2); } [Fact] public void RiskManager_DailyLossLimit_ShouldRejectOverRisk() { // Arrange var logger = new BasicLogger("RiskTest"); var riskManager = new BasicRiskManager(logger); var intent = new StrategyIntent( "ES", OrderSide.Buy, OrderType.Market, null, null, 10, 20, ConfidenceLevel.High, "Test"); // Context with daily loss near limit var context = CreateTestContext( dailyPnL: -950.0); // Close to $1000 limit var riskConfig = new RiskConfig( dailyLossLimit: 1000.0, maxTradeRisk: 200.0, maxOpenPositions: 3, emergencyFlattenEnabled: true); // Act var decision = riskManager.ValidateOrder(intent, context, riskConfig); // Assert decision.Should().NotBeNull(); decision.Approved.Should().BeFalse(); decision.Reason.Should().Contain("daily loss"); } [Fact] public void PositionSizer_FixedDollarRisk_ShouldCalculateCorrectly() { // Arrange var logger = new BasicLogger("SizingTest"); var sizer = new BasicPositionSizer(logger); var intent = new StrategyIntent( "ES", OrderSide.Buy, OrderType.Market, null, null, 8, 16, ConfidenceLevel.High, "Test"); var context = CreateTestContext(equity: 100000.0); var sizingConfig = new SizingConfig( SizingMethod.FixedDollarRisk, minContracts: 1, maxContracts: 10, riskPerTrade: 100.0, methodParameters: new Dictionary() ); // Act var result = sizer.CalculateSize(intent, context, sizingConfig); // Assert result.Should().NotBeNull(); result.Contracts.Should().BeGreaterOrEqualTo(1); result.Contracts.Should().BeLessOrEqualTo(10); result.Method.Should().Be(SizingMethod.FixedDollarRisk); } #endregion #region Thread Safety Tests [Fact] public void ExecutionAdapter_ConcurrentAccess_ShouldBeThreadSafe() { // Arrange var adapter = new NT8ExecutionAdapter(); var threads = 10; var ordersPerThread = 10; var exceptions = new List(); var successCount = 0; var lockObj = new object(); // Act var threadList = new List(); for (int t = 0; t < threads; t++) { var threadNum = t; var thread = new Thread(() => { try { for (int i = 0; i < ordersPerThread; i++) { var orderRequest = new OrderRequest( "ES", OrderSide.Buy, 1, OrderType.Market, null, null); var orderName = string.Format("THREAD_{0}_ORDER_{1}", threadNum, i); var tracking = adapter.SubmitOrder(orderRequest, orderName); // Simulate order update adapter.ProcessOrderUpdate( orderName + "_NT8", orderName, "WORKING", 0, 0, 0, null); lock (lockObj) { successCount++; } } } catch (Exception ex) { lock (lockObj) { exceptions.Add(ex); } } }); threadList.Add(thread); thread.Start(); } // Wait for all threads foreach (var thread in threadList) { thread.Join(); } // Assert exceptions.Should().BeEmpty("No exceptions should occur in thread-safe code"); successCount.Should().Be(threads * ordersPerThread, "All orders should be processed successfully"); } #endregion #region Performance Tests [Fact] public void PerformanceTest_OnBarUpdate_ShouldComplete200ms() { // Arrange var logger = new BasicLogger("PerfTest"); var strategy = new SimpleORBStrategy(30, 1.0); var config = new StrategyConfig( "PerfTest", "ES", new Dictionary(), new RiskConfig(1000.0, 200.0, 3, true), new SizingConfig(SizingMethod.FixedDollarRisk, 1, 10, 100.0, new Dictionary()) ); strategy.Initialize(config, null, logger); var context = CreateTestContext(); var bar = CreateTestBar(); // Warmup for (int i = 0; i < 10; i++) { strategy.OnBar(bar, context); } // Act - Measure 100 iterations var iterations = 100; var startTime = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { strategy.OnBar(bar, context); } var endTime = DateTime.UtcNow; var totalMs = (endTime - startTime).TotalMilliseconds; var avgMs = totalMs / iterations; // Assert avgMs.Should().BeLessThan(200.0, "OnBar should complete in <200ms on average"); logger.LogInformation("Performance: {0:F2}ms avg over {1} iterations", avgMs, iterations); } #endregion } } ``` --- ## 📋 Component 3: Deployment Verification Script ### Overview Lightweight verification script to check deployment status. ### Location **Create:** `deployment/Verify-Deployment.ps1` ### Implementation ```powershell <# .SYNOPSIS Verifies NT8 SDK deployment without rebuilding. .DESCRIPTION Checks that all required files are in place for NT8 SDK. #> param( [switch]$Detailed ) $nt8Custom = "$env:USERPROFILE\Documents\NinjaTrader 8\bin\Custom" $nt8Strategies = "$nt8Custom\Strategies" Write-Host "NT8 SDK Deployment Verification" -ForegroundColor Cyan Write-Host ("=" * 50) Write-Host "" $allGood = $true # Check Custom directory Write-Host "Checking Custom directory..." -ForegroundColor Yellow $requiredDlls = @("NT8.Core.dll") $optionalDlls = @("NT8.Adapters.dll") foreach ($dll in $requiredDlls) { $path = Join-Path $nt8Custom $dll if (Test-Path $path) { $info = Get-Item $path Write-Host " ✓ $dll" -ForegroundColor Green if ($Detailed) { Write-Host " Size: $([math]::Round($info.Length/1KB, 2)) KB" -ForegroundColor Gray Write-Host " Modified: $($info.LastWriteTime)" -ForegroundColor Gray } } else { Write-Host " ✗ $dll (MISSING)" -ForegroundColor Red $allGood = $false } } foreach ($dll in $optionalDlls) { $path = Join-Path $nt8Custom $dll if (Test-Path $path) { Write-Host " ✓ $dll (optional)" -ForegroundColor Green } else { Write-Host " - $dll (optional, not present)" -ForegroundColor Gray } } # Check Strategies directory Write-Host "`nChecking Strategies directory..." -ForegroundColor Yellow $strategyFiles = @( "NT8StrategyBase.cs", "SimpleORBNT8.cs", "MinimalTestStrategy.cs" ) foreach ($file in $strategyFiles) { $path = Join-Path $nt8Strategies $file if (Test-Path $path) { $info = Get-Item $path Write-Host " ✓ $file" -ForegroundColor Green if ($Detailed) { Write-Host " Size: $([math]::Round($info.Length/1KB, 2)) KB" -ForegroundColor Gray Write-Host " Modified: $($info.LastWriteTime)" -ForegroundColor Gray } } else { Write-Host " ✗ $file (MISSING)" -ForegroundColor Red $allGood = $false } } # Final status Write-Host "" if ($allGood) { Write-Host "✓ Deployment verified - All required files present" -ForegroundColor Green exit 0 } else { Write-Host "✗ Deployment incomplete - Missing required files" -ForegroundColor Red Write-Host "" Write-Host "Run: .\Deploy-To-NT8.ps1" -ForegroundColor Yellow exit 1 } ``` --- ## ✅ Verification & Testing ### Deployment Test Plan **Test 1: Fresh Deployment** ```powershell # Clean NT8 directories Remove-Item "$env:USERPROFILE\Documents\NinjaTrader 8\bin\Custom\NT8.*.dll" Remove-Item "$env:USERPROFILE\Documents\NinjaTrader 8\bin\Custom\Strategies\*NT8*.cs" # Deploy .\deployment\Deploy-To-NT8.ps1 # Verify .\deployment\Verify-Deployment.ps1 -Detailed ``` **Test 2: Incremental Deployment** ```powershell # Make changes to strategy # Deploy without building .\deployment\Deploy-To-NT8.ps1 -BuildFirst:$false -RunTests:$false # Verify .\deployment\Verify-Deployment.ps1 ``` **Test 3: Build Verification** ```powershell # Full deployment with verification .\deployment\Deploy-To-NT8.ps1 # Should complete without errors # Should show all tests passing # Should verify all files copied ``` ### Integration Test Execution ```bash # Run integration tests dotnet test tests/NT8.Integration.Tests --configuration Release # Expected results: # - All tests pass # - No warnings # - Performance tests meet targets # - Thread safety validated ``` --- ## 📊 Success Criteria ### Must Have (Release Blockers) - [ ] Deploy-To-NT8.ps1 completes without errors - [ ] All SDK DLLs copy correctly - [ ] All strategy files copy correctly - [ ] Verify-Deployment.ps1 reports all files present - [ ] Integration tests all pass (15+ tests) - [ ] Performance test meets <200ms target - [ ] Thread safety test passes - [ ] Complete workflow test passes - [ ] Can deploy from clean state - [ ] Can deploy incrementally ### Should Have (Quality Targets) - [ ] Deployment completes in <30 seconds - [ ] Clear progress indicators - [ ] Helpful error messages - [ ] Verification detailed output - [ ] Integration test coverage >80% --- ## 🚨 Critical Constraints ### PowerShell Requirements - PowerShell 5.1+ (built into Windows 10+) - Execution policy allows scripts - If script blocked: `Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned` ### Path Requirements - SDK must be at `C:\dev\nt8-sdk` - NT8 must be installed (default location) - User has write access to Documents folder ### Build Requirements - .NET Framework 4.8 SDK installed - All Phase A & B code complete - All tests passing --- ## 🔄 Implementation Workflow ### Step 1: Create Deployment Script (2 hours) 1. Create `deployment/Deploy-To-NT8.ps1` 2. Implement all deployment steps 3. Add comprehensive error handling 4. Test on clean system 5. Test incremental deployment ### Step 2: Create Verification Script (30 min) 1. Create `deployment/Verify-Deployment.ps1` 2. Implement file checks 3. Add detailed output option 4. Test verification ### Step 3: Create Integration Tests (1.5 hours) 1. Create `tests/NT8.Integration.Tests/NT8IntegrationTests.cs` 2. Implement all 15+ tests 3. Run and verify all pass 4. Check performance targets met ### Step 4: Documentation (30 min) 1. Update README with deployment instructions 2. Create deployment troubleshooting guide 3. Document test execution ### Step 5: Git Commit ```bash git add deployment/ git add tests/NT8.Integration.Tests/NT8IntegrationTests.cs git commit -m "feat: Add deployment automation and integration tests Deployment: - Deploy-To-NT8.ps1: Full automated deployment - Verify-Deployment.ps1: Deployment verification - Handles build, test, copy, verify - Clear progress and error reporting Integration Tests: - 15+ end-to-end workflow tests - Performance validation (<200ms) - Thread safety validation - Complete SDK workflow coverage Tested: - Fresh deployment successful - Incremental deployment successful - All integration tests passing - Performance targets met Phase C complete: Deployment automation ready" ``` --- ## 📚 Deliverables Checklist - [ ] `deployment/Deploy-To-NT8.ps1` (~300 lines) - [ ] `deployment/Verify-Deployment.ps1` (~100 lines) - [ ] `tests/NT8.Integration.Tests/NT8IntegrationTests.cs` (~500 lines) - [ ] All deployment tests pass - [ ] All integration tests pass (15+) - [ ] Performance tests meet targets - [ ] Documentation updated - [ ] Git committed --- ## 🎯 Success Definition **Phase C is complete when:** 1. ✅ Deploy-To-NT8.ps1 works from clean state 2. ✅ Deploy-To-NT8.ps1 works incrementally 3. ✅ Verify-Deployment.ps1 validates correctly 4. ✅ All 15+ integration tests passing 5. ✅ Performance test <200ms average 6. ✅ Thread safety test passes with 100 concurrent orders 7. ✅ Complete workflow test validates all layers 8. ✅ Documentation complete 9. ✅ Code committed to Git **Time Target:** 3-4 hours total --- **READY FOR KILOCODE EXECUTION IN CODE MODE** ✅ **Dependencies:** Phases A & B must be complete before starting Phase C