Skip to content

Dry-Run Feature Modularity Audit & Expansion Plan

Executive Summary

This document provides a comprehensive audit of the existing dry-run feature's modularity and outlines a strategic plan for expanding it across other capabilities, particularly co-sell relationships and partner management workflows.


Part 1: Current Implementation Audit

1.1 Architecture Overview

The dry-run feature currently consists of four main components:

Component Location Responsibility
DryRunService app/Extensions/AiPresentation/System/Services/DryRunService.php AI-powered question generation, persona management, prompt building
AiPresentation Model app/Extensions/AiPresentation/System/Models/AiPresentation.php History storage, session management
Controller Endpoints app/Extensions/AiPresentation/System/Http/Controllers/AiPresentationController.php API routes for config, generation, history, deletion
View Component app/Extensions/AiPresentation/resources/views/home/dry-run-modal.blade.php Alpine.js-based UI with tabs for config/results/history

1.2 Modularity Strengths

  1. Separation of Concerns: Service layer properly isolated from controller logic
  2. Configuration Management: Static methods (getPersonas(), getIndustries(), etc.) centralize config data
  3. Quality Tiers: Configurable AI model selection based on quality level (quick/standard/deep)
  4. Clean API Design: RESTful endpoints follow Laravel conventions
  5. Frontend Encapsulation: Alpine.js component manages all state independently

1.3 Modularity Weaknesses (Tight Coupling)

Issue Impact Severity
History storage hardcoded to AiPresentation model Cannot reuse for other entities High
No shared interfaces or traits Cannot compose with other features High
Personas/industries hardcoded in PHP arrays Cannot customize per organization Medium
Max 10 sessions hardcoded (line 107) No configurability Low
Prompt building presentation-specific Cannot reuse for proposals/co-sell High
No analytics or persistence beyond JSON Cannot analyze patterns Medium

1.4 Current Data Flow

┌─────────────────────────────────────────────────────────────────┐
│                        Current Flow                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  User Config (persona, industry, quality)                        │
│       ↓                                                          │
│  Controller validates → DryRunService.generateQuestions()        │
│       ↓                                                          │
│  buildPrompt() → BedrockRuntimeService.invokeModel()             │
│       ↓                                                          │
│  parseResponse() → AiPresentation.addDryRunToHistory()           │
│       ↓                                                          │
│  JSON stored in dry_run_history column                           │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Part 2: Expansion Opportunities

2.1 Co-Sell Relationship Dry-Run Use Cases

The most valuable expansion is into co-sell workflows. Here's a detailed breakdown:

A. Pre-Partnership Assessment

Scenario: Before formalizing a co-sell relationship with a partner

Persona Questions to Simulate
Alliance Manager "What's your AWS certification status?" "How does your solution complement ours?"
Partner Development "What's your customer overlap?" "What's your co-sell track record?"
Technical Reviewer "Is your solution AWS-native?" "What integration points exist?"

Value: Identify partnership risks before committing resources

B. Brand Voice Merger Simulation

Scenario: Testing if two brands work together before content creation

Simulation Type Output
Brand Alignment Score 0-100 compatibility rating
Messaging Preview Sample merged messaging
Conflict Detection Areas where brands clash

Value: Avoid content rework and brand conflicts

C. Approval Workflow Testing

Scenario: Predicting approval bottlenecks before campaign launch

Simulation Type Output
Timeline Forecast Days to publish estimate
Bottleneck Identification Which partner/stage delays
Rejection Prediction Likelihood of rework cycles

Value: Set realistic expectations and resource allocation

D. Publishing Coordination Dry-Run

Scenario: Testing multi-channel publishing before going live

Simulation Type Output
Channel Mix Optimization Best platform combination
Schedule Validation Timing and offset verification
Failure Scenario Testing Retry logic validation

Value: Ensure coordinated execution without real-world failures

E. Proposal Approval Simulation

Scenario: Testing CPPO proposal viability before submission

Simulation Type Output
Approval Probability Likelihood score with reasoning
Margin Analysis Impact on portfolio profitability
Risk Identification Deal-specific risk factors
Stakeholder Path Required approvals and decision makers

Value: Don't waste effort on proposals unlikely to approve

2.2 Additional Capability Opportunities

Capability Dry-Run Benefit
Competitive Battlecards Simulate competitor objections before sales calls
Analyst Briefing Prep Practice analyst questions before briefings
Partner Pitch Decks Rehearse partner manager questions
Email Sequences Forecast engagement without damaging reputation
Event Follow-Up Practice follow-up conversation scenarios

Part 3: Modular Architecture Design

3.1 Proposed Interface Contracts

<?php

namespace App\Contracts\DryRun;

/**
 * Contract for entities that support dry-run simulation
 */
interface SimulatableInterface
{
    /**
     * Get the content/context for simulation
     */
    public function getSimulationContext(): array;

    /**
     * Add a simulation session to history
     */
    public function addSimulationToHistory(SimulationResult $result): void;

    /**
     * Get simulation history
     */
    public function getSimulationHistory(): array;

    /**
     * Get available personas for this entity type
     */
    public static function getAvailablePersonas(): array;

    /**
     * Get maximum history sessions to retain
     */
    public function getMaxHistorySessions(): int;
}

/**
 * Contract for simulation services
 */
interface SimulationServiceInterface
{
    /**
     * Run a simulation
     */
    public function simulate(
        SimulatableInterface $entity,
        SimulationConfig $config
    ): SimulationResult;

    /**
     * Get available configuration options
     */
    public function getConfigurationOptions(): array;

    /**
     * Validate configuration before simulation
     */
    public function validateConfig(array $config): bool;
}

3.2 Proposed Trait for History Management

<?php

namespace App\Traits;

use App\Contracts\DryRun\SimulationResult;

trait HasSimulationHistory
{
    /**
     * Add simulation to history
     */
    public function addSimulationToHistory(SimulationResult $result): void
    {
        $history = $this->simulation_history ?? [];

        $history[] = [
            'id' => uniqid('sim_'),
            'created_at' => now()->toIso8601String(),
            'type' => $result->getType(),
            'config' => $result->getConfig(),
            'result' => $result->getData(),
        ];

        // Keep only last N sessions
        $maxSessions = $this->getMaxHistorySessions();
        if (count($history) > $maxSessions) {
            $history = array_slice($history, -$maxSessions);
        }

        $this->simulation_history = $history;
        $this->save();
    }

    /**
     * Get simulation history
     */
    public function getSimulationHistory(): array
    {
        return $this->simulation_history ?? [];
    }

    /**
     * Get count of simulation sessions
     */
    public function getSimulationCountAttribute(): int
    {
        return count($this->simulation_history ?? []);
    }

    /**
     * Delete a specific simulation session
     */
    public function deleteSimulation(string $simulationId): bool
    {
        $history = $this->simulation_history ?? [];
        $newHistory = array_filter($history, fn($s) => $s['id'] !== $simulationId);

        if (count($newHistory) === count($history)) {
            return false; // Not found
        }

        $this->simulation_history = array_values($newHistory);
        $this->save();
        return true;
    }

    /**
     * Default max sessions - can be overridden
     */
    public function getMaxHistorySessions(): int
    {
        return 10;
    }
}

3.3 Proposed Base Simulation Service

<?php

namespace App\Services\DryRun;

use App\Contracts\DryRun\SimulatableInterface;
use App\Contracts\DryRun\SimulationServiceInterface;
use App\Services\Bedrock\BedrockRuntimeService;

abstract class BaseSimulationService implements SimulationServiceInterface
{
    protected BedrockRuntimeService $bedrockService;

    protected const QUALITY_MODELS = [
        'quick' => 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
        'standard' => 'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
        'deep' => 'us.anthropic.claude-3-opus-20240229-v1:0',
    ];

    protected const QUALITY_CONFIG = [
        'quick' => ['max_tokens' => 2000, 'temperature' => 0.7],
        'standard' => ['max_tokens' => 3000, 'temperature' => 0.8],
        'deep' => ['max_tokens' => 4000, 'temperature' => 0.85],
    ];

    public function __construct(BedrockRuntimeService $bedrockService)
    {
        $this->bedrockService = $bedrockService;
    }

    /**
     * Template method for simulation
     */
    public function simulate(
        SimulatableInterface $entity,
        SimulationConfig $config
    ): SimulationResult {
        $this->validateConfig($config->toArray());

        $prompt = $this->buildPrompt($entity, $config);
        $response = $this->invokeAI($prompt, $config->quality);
        $parsed = $this->parseResponse($response);

        return new SimulationResult(
            type: $this->getSimulationType(),
            config: $config->toArray(),
            data: $parsed
        );
    }

    /**
     * Invoke AI model with quality-specific settings
     */
    protected function invokeAI(string $prompt, string $quality): string
    {
        $modelId = self::QUALITY_MODELS[$quality] ?? self::QUALITY_MODELS['standard'];
        $config = self::QUALITY_CONFIG[$quality] ?? self::QUALITY_CONFIG['standard'];

        return $this->bedrockService->invokeModel($modelId, $prompt, $config);
    }

    /**
     * Parse JSON response from AI
     */
    protected function parseResponse(string $response): array
    {
        $response = preg_replace('/^```json\s*/m', '', $response);
        $response = preg_replace('/\s*```$/m', '', $response);

        $parsed = json_decode(trim($response), true);

        return json_last_error() === JSON_ERROR_NONE ? $parsed : [];
    }

    /**
     * Must be implemented by concrete services
     */
    abstract protected function buildPrompt(
        SimulatableInterface $entity,
        SimulationConfig $config
    ): string;

    abstract protected function getSimulationType(): string;
}

3.4 Proposed Directory Structure

app/
├── Contracts/
│   └── DryRun/
│       ├── SimulatableInterface.php
│       ├── SimulationServiceInterface.php
│       ├── SimulationConfig.php
│       └── SimulationResult.php
├── Traits/
│   └── HasSimulationHistory.php
├── Services/
│   └── DryRun/
│       ├── BaseSimulationService.php
│       ├── Config/
│       │   ├── PersonaRegistry.php        # Centralized persona management
│       │   ├── IndustryRegistry.php       # Centralized industry data
│       │   └── QualityConfig.php          # Quality level configuration
│       ├── Simulators/
│       │   ├── PresentationSimulator.php  # Migrated from DryRunService
│       │   ├── CoSellSimulator.php        # New
│       │   ├── ProposalSimulator.php      # New
│       │   ├── ApprovalWorkflowSimulator.php  # New
│       │   └── PartnershipSimulator.php   # New
│       └── Prompts/
│           ├── PresentationPromptBuilder.php
│           ├── CoSellPromptBuilder.php
│           └── ProposalPromptBuilder.php
└── Extensions/
    ├── AiPresentation/
    │   └── System/
    │       └── Models/
    │           └── AiPresentation.php     # Uses HasSimulationHistory trait
    └── ContentManager/
        └── System/
            └── Models/
                ├── CoSellPlan.php         # Add HasSimulationHistory trait
                └── CoSellRelationship.php # Add HasSimulationHistory trait

Part 4: Co-Sell Dry-Run Implementation Details

4.1 CoSellSimulator Service

<?php

namespace App\Services\DryRun\Simulators;

use App\Contracts\DryRun\SimulatableInterface;
use App\Services\DryRun\BaseSimulationService;

class CoSellSimulator extends BaseSimulationService
{
    protected function getSimulationType(): string
    {
        return 'co_sell_preparation';
    }

    public static function getAvailablePersonas(): array
    {
        return [
            'alliance_manager' => [
                'name' => 'AWS Alliance Manager',
                'icon' => 'handshake',
                'focus' => ['partnership value', 'AWS alignment', 'co-sell potential', 'deal support'],
                'description' => 'Evaluates partnership strength and AWS marketplace alignment',
            ],
            'partner_development' => [
                'name' => 'Partner Development Manager',
                'icon' => 'users',
                'focus' => ['partner enablement', 'training needs', 'certification', 'go-to-market'],
                'description' => 'Assesses partner readiness and enablement requirements',
            ],
            'deal_desk' => [
                'name' => 'Deal Desk / Pricing',
                'icon' => 'calculator',
                'focus' => ['margin requirements', 'pricing approval', 'deal structure', 'compliance'],
                'description' => 'Reviews deal economics and pricing compliance',
            ],
            'legal_compliance' => [
                'name' => 'Legal & Compliance',
                'icon' => 'shield-check',
                'focus' => ['contract terms', 'liability', 'IP protection', 'regulatory compliance'],
                'description' => 'Evaluates legal and compliance requirements',
            ],
            'technical_reviewer' => [
                'name' => 'Technical Solution Reviewer',
                'icon' => 'code',
                'focus' => ['integration quality', 'AWS best practices', 'security posture', 'scalability'],
                'description' => 'Validates technical implementation and architecture',
            ],
        ];
    }

    public static function getPartnershipStages(): array
    {
        return [
            'prospecting' => [
                'name' => 'Prospecting / Initial Outreach',
                'concerns' => ['fit assessment', 'initial value prop', 'partnership criteria'],
            ],
            'evaluation' => [
                'name' => 'Evaluation / Due Diligence',
                'concerns' => ['technical validation', 'business model alignment', 'reference checks'],
            ],
            'negotiation' => [
                'name' => 'Negotiation / Contracting',
                'concerns' => ['terms alignment', 'pricing structure', 'SLA requirements'],
            ],
            'onboarding' => [
                'name' => 'Onboarding / Enablement',
                'concerns' => ['training completion', 'certification', 'go-to-market readiness'],
            ],
            'active' => [
                'name' => 'Active Partnership',
                'concerns' => ['deal flow', 'relationship health', 'growth opportunities'],
            ],
        ];
    }

    protected function buildPrompt(
        SimulatableInterface $entity,
        SimulationConfig $config
    ): string
    {
        $context = $entity->getSimulationContext();
        $persona = self::getAvailablePersonas()[$config->persona];
        $stage = self::getPartnershipStages()[$config->stage ?? 'evaluation'];

        return <<<PROMPT
You are simulating a {$persona['name']} evaluating a co-sell partnership opportunity.

## YOUR PERSONA
**Role:** {$persona['name']}
**Focus Areas:** {$this->formatArray($persona['focus'])}
**Description:** {$persona['description']}

## PARTNERSHIP STAGE
**Stage:** {$stage['name']}
**Key Concerns:** {$this->formatArray($stage['concerns'])}

## PARTNERSHIP CONTEXT
**Partner A:** {$context['partner_a']['name']}
**Partner B:** {$context['partner_b']['name']}
**Proposed Value:** {$context['value_proposition']}

## YOUR TASK
Generate challenging questions this persona would ask to validate this co-sell partnership.

Return JSON:
{
  "questions": [
    {
      "question": "...",
      "category": "business_fit|technical|legal|financial|operational",
      "difficulty": "easy|medium|hard",
      "intent": "What you're really evaluating",
      "red_flags": "What would concern you in the answer"
    }
  ],
  "partnership_risks": [
    {
      "risk": "Specific risk this persona would identify",
      "mitigation": "How to address this risk",
      "severity": "low|medium|high"
    }
  ],
  "success_criteria": [
    "What would make this partnership succeed from your perspective"
  ],
  "recommended_next_steps": [
    "Actions to take before proceeding"
  ]
}
PROMPT;
    }
}

4.2 Co-Sell Specific Personas

Persona Focus Areas Key Questions
AWS Alliance Manager Co-sell potential, AWS alignment "What's your AWS certification level?" "How does this accelerate marketplace revenue?"
Partner Development Manager Enablement, training "What training do your sellers need?" "How quickly can you be deal-ready?"
Deal Desk Pricing, margins "What's the margin split?" "Does this meet approval thresholds?"
Legal/Compliance Contracts, liability "Who owns the customer relationship?" "What's the IP arrangement?"
Technical Reviewer Architecture, integration "Is this Well-Architected compliant?" "What's the integration complexity?"

4.3 Database Migration

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        // Add simulation_history to co_sell_plans
        Schema::table('co_sell_plans', function (Blueprint $table) {
            $table->json('simulation_history')->nullable()->after('status');
        });

        // Add simulation_history to co_sell_relationships
        Schema::table('co_sell_relationships', function (Blueprint $table) {
            $table->json('simulation_history')->nullable()->after('health_score');
        });
    }

    public function down(): void
    {
        Schema::table('co_sell_plans', function (Blueprint $table) {
            $table->dropColumn('simulation_history');
        });

        Schema::table('co_sell_relationships', function (Blueprint $table) {
            $table->dropColumn('simulation_history');
        });
    }
};

Part 5: Implementation Roadmap

Phase 1: Foundation (Week 1-2)

  • Create SimulatableInterface and SimulationResult contracts
  • Create HasSimulationHistory trait
  • Create BaseSimulationService abstract class
  • Create PersonaRegistry and IndustryRegistry config classes
  • Migrate DryRunService to use new architecture (backwards compatible)

Phase 2: Co-Sell Integration (Week 3-4)

  • Add simulation_history migration for co_sell_plans and co_sell_relationships
  • Implement CoSellSimulator service
  • Add HasSimulationHistory trait to CoSellPlan and CoSellRelationship models
  • Create API endpoints for co-sell simulation
  • Build co-sell dry-run UI component

Phase 3: Proposal Simulation (Week 5)

  • Implement ProposalSimulator for CPPO proposals
  • Add approval prediction logic
  • Integrate with existing proposal workflow

Phase 4: Analytics & Optimization (Week 6)

  • Add simulation analytics tracking
  • Build simulation history dashboard
  • Implement pattern detection across simulations

Part 6: Value Assessment Matrix

6.1 Priority Ranking

Capability Business Value Implementation Effort Priority
Co-Sell Partnership Prep High - Risk mitigation Medium P1
CPPO Proposal Approval High - Deal velocity Medium P1
Brand Voice Validation Medium - Content quality Low P2
Approval Workflow Testing Medium - Process efficiency Medium P2
Publishing Dry-Run Low - Already simulated Low P3
Email Sequence Testing Medium - Reputation protection Medium P3

6.2 ROI Estimates

Use Case Without Dry-Run With Dry-Run Savings
Failed partnership (discovered late) $50K+ in wasted effort Early identification ~$40K/partnership
Proposal rejection (discovered at submission) 2-3 week delay Preemptive fixes 2+ weeks/deal
Brand conflict (discovered in campaign) Campaign restart Upfront validation ~$10K/campaign
Approval bottleneck Unpredictable timelines Forecasted delays Resource optimization

Part 7: Technical Considerations

7.1 Performance

  • Simulation calls use Bedrock AI - ~5-30 seconds depending on quality level
  • History stored as JSON - efficient for small datasets, consider separate table at scale
  • Frontend uses Alpine.js - minimal bundle impact

7.2 Security

  • All simulations authenticated via middleware
  • No PII in simulation prompts (use entity references, not raw data)
  • History deletion available for data hygiene

7.3 Scalability

  • JSON column limits: ~1GB per row (PostgreSQL), ~4GB (MySQL)
  • 10 sessions × ~50KB average = ~500KB per entity - well within limits
  • Consider archival to S3 for historical analysis at scale

Part 8: Success Metrics

8.1 Adoption Metrics

  • Simulations per entity type per month
  • Unique users running simulations
  • Simulation-to-action conversion rate

8.2 Quality Metrics

  • Simulation accuracy (predicted vs actual outcomes)
  • User satisfaction scores
  • Time saved per workflow

8.3 Business Impact

  • Partnership success rate improvement
  • Proposal approval rate improvement
  • Time-to-market reduction for co-sell campaigns

Appendix A: Current File References

File Path Key Lines
DryRunService app/Extensions/AiPresentation/System/Services/DryRunService.php 78-299 (configs), 304-374 (generate), 379-481 (prompt)
AiPresentation Model app/Extensions/AiPresentation/System/Models/AiPresentation.php 80-113 (history methods)
Controller app/Extensions/AiPresentation/System/Http/Controllers/AiPresentationController.php 398-522 (endpoints)
Routes app/Extensions/AiPresentation/System/AiPresentationServiceProvider.php 126-130 (route definitions)
View app/Extensions/AiPresentation/resources/views/home/dry-run-modal.blade.php Full file (811 lines)

Appendix B: Co-Sell Services Reference

Service Path Dry-Run Opportunity
ApprovalWorkflowService app/Extensions/ContentManager/System/Services/CoSell/ApprovalWorkflowService.php Approval timeline simulation
BrandVoiceMerger app/Extensions/ContentManager/System/Services/CoSell/BrandVoiceMerger.php Brand compatibility testing
CoSellAnalyticsService app/Extensions/ContentManager/System/Services/CoSell/CoSellAnalyticsService.php Performance forecasting
CrossPartnerPublishingService app/Extensions/ContentManager/System/Services/CoSell/CrossPartnerPublishingService.php Publishing coordination testing
EmailFunnelService app/Extensions/ContentManager/System/Services/CoSell/EmailFunnelService.php Engagement forecasting
CppoProposalGeneratorCapability app/Extensions/ContentManager/System/Services/Capabilities/CppoProposalGeneratorCapability.php Proposal approval prediction

Document generated: 2025-12-31 Author: Claude Code Audit