---
# === IDENTITY ===
id: consulting/recipes/platform-extraction/2026
canonical_question: "How do you refactor Signal Stack vertical #1 into reusable engine plus config layer?"
aliases:
  - "Signal Stack platform extraction process"
  - "How to separate generic engine from vertical-specific config"
  - "Refactoring signal pipeline into reusable platform"
entity_type: execution_recipe
domain: consulting > recipes > Platform Extraction
region: global
jurisdiction: global
temporal_scope: 2026-2027

# === VERIFICATION ===
last_verified: 2026-03-29
confidence: 0.85
version: 1.0
first_published: 2026-03-29

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: evolving
  last_breaking_change: "Initial release — Signal Stack platform extraction methodology v1.0"
  next_review: 2026-09-25
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "Hard rule: no platform work until 3 paying customers in vertical #1 — premature abstraction is the #1 killer"
  - "Each subsequent vertical must require <50% effort of first — if it does not, the platform abstraction is wrong"
  - "Generic components must be completely decoupled from vertical-specific config — no vertical assumptions in engine code"
  - "Vertical-specific config must be declarative (config files), not procedural (custom code per vertical)"
  - "Backward compatibility: existing vertical #1 clients must continue operating unchanged after extraction"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User has not yet validated vertical #1 with 3 paying customers"
    use_instead: "consulting/recipes/pilot-execution-playbook/2026"
  - condition: "User needs to launch a new vertical on existing platform"
    use_instead: "consulting/recipes/vertical-launch-checklist/2026"
  - condition: "User needs Signal Stack theory, not execution"
    use_instead: "consulting/signal-stack/five-layer-pipeline-architecture/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: paying_customers
    question: "How many paying customers does vertical #1 have?"
    type: choice
    options: ["1-2 (not ready — need 3)", "3 (minimum threshold)", "4-5", "6+"]
  - key: pipeline_architecture
    question: "Is the current pipeline a monolithic script or already partially modular?"
    type: choice
    options: ["single monolithic script", "partially modular (some functions separated)", "already modular (clear layer boundaries)"]
  - key: target_verticals
    question: "How many additional verticals are planned?"
    type: choice
    options: ["1 (test extraction)", "2-3 (near-term roadmap)", "5+ (platform play)"]
  - key: team_size
    question: "How many engineers are available for extraction?"
    type: choice
    options: ["1 (founder/solo)", "2 (engineer + architect)", "3+ (dedicated team)"]

# === EXECUTION METADATA ===
execution:
  required_inputs:
    - name: "Working vertical #1 pipeline"
      source: "Pilot execution output"
      format: "codebase"
    - name: "3+ paying customer contracts"
      source: "Sales"
      format: "signed agreements"
    - name: "Signal taxonomy for vertical #1"
      source: "Taxonomy workshop output"
      format: "document"
    - name: "Planned vertical #2 signal sources"
      source: "Signal audit"
      format: "document"

  outputs:
    - name: "Generic Engine Codebase"
      format: "code repository"
      description: "Reusable 5-layer pipeline: ingestion framework, classification pipeline, enrichment engine, document generator, delivery/tracking"
    - name: "Vertical Configuration Schema"
      format: "JSON/YAML schema + documentation"
      description: "Declarative config format for vertical-specific sources, triggers, targets, templates, conversion definitions"
    - name: "Vertical #1 Config Files"
      format: "JSON/YAML config files"
      description: "Existing vertical #1 re-expressed as config on top of generic engine"
    - name: "Platform Architecture Document"
      format: "document"
      description: "Component boundaries, API contracts, extension points, deployment topology"

  tools_required:
    - name: "Version control (Git)"
      purpose: "Branch management for extraction refactor"
      tier: "free"
      cost: "$0"
      alternatives: []
    - name: "CI/CD pipeline (GitHub Actions)"
      purpose: "Automated testing for regression and config validation"
      tier: "free"
      cost: "$0"
      alternatives: ["GitLab CI", "CircleCI"]
    - name: "Config validation (JSON Schema/Pydantic)"
      purpose: "Validate vertical config files against schema"
      tier: "free"
      cost: "$0"
      alternatives: ["Zod (TypeScript)", "Cerberus (Python)"]

  credentials_needed:
    - service: "Git hosting"
      type: "SSH key or token"
      where_to_get: "https://github.com/settings/keys"
      free_tier_limits: "Unlimited private repos"

  estimated_duration: "3-5 weeks"
  estimated_cost: "$10K-25K (engineering labor)"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/consulting/recipes/platform-extraction/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-03-29)"

# === RELATED UNITS ===
related_kos:
  depends_on:
    - id: "consulting/recipes/pilot-execution-playbook/2026"
      label: "Pilot must pass Phase 1 exit criteria before extraction begins"
    - id: "consulting/signal-stack/five-layer-pipeline-architecture/2026"
      label: "The five-layer signal pipeline — Ingest, Detect, Enrich, Generate, Deliver"
  feeds_into:
    - id: "consulting/recipes/vertical-launch-checklist/2026"
      label: "New vertical launches use the extracted platform"
  related_to: []

# === SOURCES ===
sources:
  - id: src1
    title: "Signal Stack — A Unified Signal-family Platform"
    author: "Internal methodology"
    url: https://knowledgelib.io/consulting/signal-stack/signal-stack-architecture/2026
    type: primary_research
    published: 2026-03-09
    reliability: high
  - id: src2
    title: "Signal Stack Consulting-as-a-Service — Strategic Intelligence Report"
    author: "Internal methodology"
    url: https://knowledgelib.io/consulting/signal-stack/signal-stack-caas/2026
    type: primary_research
    published: 2026-03-29
    reliability: high
  - id: src3
    title: "Designing Data-Intensive Applications"
    author: "Kleppmann, M."
    url: https://dataintensive.net/
    type: academic_paper
    published: 2017-03-01
    reliability: authoritative
  - id: src4
    title: "Building Microservices"
    author: "Newman, S."
    url: https://www.oreilly.com/library/view/building-microservices-2nd/9781492034018/
    type: academic_paper
    published: 2021-08-01
    reliability: high
---

# Platform Extraction

## Purpose

This recipe refactors a working Signal Stack vertical #1 into a reusable generic engine plus a declarative configuration layer. The extraction separates the 5 generic components (ingestion framework, classification pipeline, enrichment engine, document generator, delivery/tracking) from vertical-specific config (sources, triggers, targets, templates, conversion definitions). The target outcome: each subsequent vertical requires less than 50% of the effort of vertical #1. [src1, src2]

## Prerequisites
<!-- Agents: verify ALL prerequisites before executing. Missing prerequisites = failed execution. -->

- [ ] **3 paying customers** in vertical #1 — the hard prerequisite. No extraction without validated revenue.
- [ ] **Working pipeline** — cron jobs, classification, enrichment, dossier generation, and delivery all operational and producing results
- [ ] **Signal taxonomy documented** — trigger events, scoring logic, and false positive rules written down (not just in code)
- [ ] **Vertical #2 identified** — at least one additional vertical selected so extraction is guided by a real second use case
- [ ] **Regression test suite** — at least 20 known-good signal-to-dossier examples that must continue working after extraction

## Constraints
<!-- Hard rules. Agents: enforce throughout execution. Violating these = broken output or legal risk. -->

- No platform work until 3 paying customers in vertical #1. Premature abstraction destroys startups. [src1]
- Each subsequent vertical must require < 50% effort of first. If it does not, the abstraction is wrong — go back and refactor. [src1]
- Generic components must contain zero vertical-specific assumptions. No hard-coded source URLs, no industry-specific classification rules in engine code. [src3]
- Vertical config must be declarative. If adding a vertical requires writing custom code (not config), the abstraction boundary is in the wrong place. [src4]
- Backward compatibility is non-negotiable. Existing vertical #1 clients must see zero disruption during and after extraction. [src2]

## Tool Selection Decision

```
Which path?
├── Pipeline is a monolithic Python script
│   └── PATH A: Strangler Fig — wrap existing code, extract interfaces incrementally
├── Pipeline is partially modular (some functions separated)
│   └── PATH B: Interface Extraction — define contracts between layers, refactor in place
├── Pipeline is already modular but tightly coupled
│   └── PATH C: Config Extraction — extract hard-coded values into config files
└── Starting fresh (rare — only if current code is unmaintainable)
    └── PATH D: Rewrite with config-first architecture (high risk, avoid if possible)
```

| Path | Approach | Duration | Risk | Best For |
|------|----------|----------|------|----------|
| A: Strangler Fig | Incremental wrapping | 4-5 weeks | Low — existing code keeps running | Monolithic pipelines |
| B: Interface Extraction | Define contracts, refactor | 3-4 weeks | Medium — requires clear layer boundaries | Partially modular code |
| C: Config Extraction | Pull values into config | 2-3 weeks | Low — minimal code changes | Already modular code |
| D: Rewrite | Build new, migrate | 5-8 weeks | High — may break things | Unmaintainable code only |

## Execution Flow

### Step 1: Architecture Audit

**Duration**: 2-3 days
**Tool**: Code review + architecture diagramming

Map the current pipeline code to the 5-layer architecture: (1) ingestion, (2) signal detection/classification, (3) enrichment, (4) asset generation, (5) delivery + feedback. For each layer, identify what is generic (reusable across any vertical) vs. what is vertical-specific (sources, rules, templates, targets). [src1]

Produce an architecture diagram showing current component boundaries, data flows between layers, and hard-coded vertical assumptions in each layer.

**Verify**: Architecture diagram reviewed and validated. Every hard-coded vertical assumption annotated.
**If failed**: If boundaries are unclear, pair with the engineer who built the pipeline to trace data flow end-to-end.

### Step 2: Define Configuration Schema

**Duration**: 3-5 days
**Tool**: JSON Schema or Pydantic model definition

Design the declarative configuration schema that captures everything vertical-specific. The schema must cover:
- **Sources config**: data source URLs, API credentials, scraping rules, refresh schedules, rate limits
- **Trigger config**: what signal patterns count as trigger events, strength scoring weights, compound signal logic, false positive exclusion rules
- **Target config**: decision-maker roles, firmographic filters, enrichment API selection
- **Template config**: dossier structure, section templates, proof pack format, brand voice parameters
- **Delivery config**: channel selection (email, CRM, Slack), tracking parameters, compliance jurisdiction
- **Conversion config**: what counts as conversion at each funnel stage, feedback loop definitions

Validate the schema by expressing vertical #1 entirely as a config file. If any vertical #1 behavior cannot be expressed in config, the schema is incomplete. [src3, src4]

**Verify**: Vertical #1 fully expressible as config + generic engine. No vertical-specific code remains outside config.
**If failed**: Identify the behavior that cannot be captured in config. Either extend the schema or accept it as a generic engine feature (not vertical-specific).

### Step 3: Extract Generic Engine

**Duration**: 5-8 days
**Tool**: Git branching + incremental refactoring

Extract the generic engine from vertical #1 code. Work layer by layer:

1. **Ingestion framework**: Generic connector interface (HTTP scraper, API poller, RSS reader, file watcher). Source-specific details (URLs, parsing rules, authentication) move to config.
2. **Classification pipeline**: Generic LLM prompt template with variable slots. Signal-specific trigger definitions, scoring weights, and exclusion rules move to config.
3. **Enrichment engine**: Generic enrichment orchestrator that calls APIs based on config. Which APIs to call and which fields to extract move to config.
4. **Document generator**: Generic template engine (Jinja2 or similar). Dossier structure, section content, and formatting move to config templates.
5. **Delivery + tracking**: Generic delivery dispatcher. Channel selection, tracking events, and compliance rules move to config. [src1]

Use the Strangler Fig pattern: wrap existing code behind new interfaces, then gradually replace internals. Never break the running pipeline. [src4]

**Verify**: Generic engine runs vertical #1 using only the config file from Step 2. Output matches pre-extraction output exactly.
**If failed**: Diff pre- and post-extraction outputs. Fix discrepancies before proceeding. Common cause: edge cases in classification logic that were implicit in code but not captured in config.

### Step 4: Regression Testing

**Duration**: 2-3 days
**Tool**: Automated test suite

Run the regression test suite (20+ known-good examples) through the extracted engine + vertical #1 config. Compare output dossiers field by field against pre-extraction baselines.

Test categories:
- **Signal classification**: same inputs produce same trigger/no-trigger decisions
- **Enrichment**: same companies produce same firmographic data
- **Dossier generation**: same signals produce same dossier content (allowing for LLM variation — test structure, not exact wording)
- **Delivery**: same routing and tracking behavior
- **End-to-end**: full pipeline from raw signal to delivered dossier

**Verify**: 100% regression pass rate on classification and enrichment. > 95% structural match on dossier generation.
**If failed**: Identify failing cases. Most common cause: config schema does not capture a classification edge case. Add the missing config parameter and re-test.

### Step 5: Vertical #2 Dry Run

**Duration**: 3-5 days
**Tool**: New config file + limited test data

Create a config file for vertical #2 using the schema from Step 2. Run the generic engine with vertical #2 config against 20-50 test signals from the new vertical.

Measure extraction success:
- How long did it take to create the vertical #2 config? (Target: < 3 days)
- Did the generic engine require any code changes? (Target: zero)
- What percentage of vertical #2 behavior is captured in config? (Target: > 90%)
- What is the dossier quality on vertical #2 test data? (Target: comparable to early vertical #1 quality)

This is the extraction validation gate. If vertical #2 requires > 50% of vertical #1 effort, the abstraction is wrong. [src1, src2]

**Verify**: Vertical #2 config created in < 3 days, zero engine code changes, > 90% behavior in config.
**If failed**: Identify what required custom code. Refactor that component into the generic engine with a new config parameter. Re-run dry run.

### Step 6: Documentation and Handoff

**Duration**: 2-3 days
**Tool**: Documentation + walkthrough

Produce the platform architecture document:
- Component diagram with clear engine/config boundary
- Config schema reference with examples for each field
- Step-by-step guide for creating a new vertical config
- Deployment topology (how engine + config are deployed per client)
- Extension points (where custom code is acceptable vs. where config must be used)

Conduct walkthrough with the team to ensure anyone can create a new vertical config without the original architect. [src3]

**Verify**: A team member who did not build the platform can create a basic vertical config from the documentation alone.
**If failed**: The documentation has gaps. Have the team member annotate where they got stuck and fill those gaps.

## Output Schema

```json
{
  "output_type": "platform_extraction_package",
  "format": "code repository + documentation",
  "sections": [
    {"name": "generic_engine", "type": "object", "description": "5-layer reusable pipeline codebase", "required": true},
    {"name": "config_schema", "type": "object", "description": "JSON/YAML schema for vertical configuration", "required": true},
    {"name": "vertical_1_config", "type": "object", "description": "Existing vertical expressed as config", "required": true},
    {"name": "vertical_2_config", "type": "object", "description": "New vertical dry-run config", "required": true},
    {"name": "regression_results", "type": "object", "description": "Test suite pass/fail report", "required": true},
    {"name": "architecture_doc", "type": "object", "description": "Platform architecture and config guide", "required": true}
  ],
  "expected_sections": "6",
  "sort_order": "layer order (ingestion → classification → enrichment → generation → delivery)"
}
```

## Quality Benchmarks

| Quality Metric | Minimum Acceptable | Good | Excellent |
|---------------|-------------------|------|-----------|
| Regression pass rate | > 95% | > 98% | 100% |
| Vertical #2 config time | < 5 days | < 3 days | < 2 days |
| Engine code changes for V2 | < 5 changes | 1-2 changes | Zero changes |
| Config coverage (% of behavior in config) | > 85% | > 90% | > 95% |
| Backward compatibility (V1 client disruption) | < 1 hour downtime | Zero downtime | Zero disruption |
| Documentation completeness (team can create config) | With help | Independently with questions | Independently, no questions |

**If below minimum**: The abstraction boundary is wrong. Pause vertical #2 launch, refactor the engine, and re-test.

## Error Handling

| Error | Likely Cause | Recovery Action |
|-------|-------------|----------------|
| Regression failures after extraction | Config schema missing edge cases from original code | Diff outputs, add missing config parameters, re-test |
| Vertical #2 requires engine code changes | Abstraction boundary too narrow | Generalize the affected component, add to config schema |
| Config schema too complex (> 200 fields) | Over-engineering — trying to configure everything | Simplify: identify the 20% of config that covers 80% of vertical variation |
| Existing clients report issues post-extraction | Backward compatibility regression | Immediate rollback to pre-extraction code, fix, re-deploy |
| Team cannot create config from docs | Documentation gaps or config schema too complex | Pair-program a vertical config, document every stumbling point |

## Cost Breakdown

| Component | Solo Founder ($10K) | Small Team ($15K) | Dedicated Team ($25K) |
|-----------|--------------------|--------------------|----------------------|
| Architecture audit | $1K | $2K | $3K |
| Config schema design | $2K | $3K | $4K |
| Engine extraction | $4K | $5K | $8K |
| Regression testing | $1K | $2K | $3K |
| Vertical #2 dry run | $1K | $2K | $4K |
| Documentation | $1K | $1K | $3K |
| **Total** | **$10K** | **$15K** | **$25K** |

## Anti-Patterns

### Wrong: Extracting the platform before 3 paying customers
Building generic infrastructure before proving the vertical works commercially. Result: you optimize for flexibility nobody needs while the core product stagnates. The #1 startup killer in signal-based businesses. [src1]

### Correct: Prove revenue first, extract second
The hard rule exists because premature abstraction is seductive — it feels like progress. Wait for 3 paying customers. Their usage patterns reveal what actually needs to be generic vs. what is one-off.

### Wrong: Making everything configurable
Creating a config schema with 200+ fields that covers every conceivable variation. Result: config files become as complex as code, nobody can create a new vertical without the architect, and the "platform" is just a different form of custom engineering. [src3]

### Correct: Configure the 80%, code the 20%
Identify the 20% of vertical variation that covers 80% of use cases. Make that configurable. Accept that rare edge cases may require small code additions — that is cheaper than infinite config complexity.

### Wrong: Big-bang rewrite instead of incremental extraction
Rewriting the entire pipeline from scratch to be "properly architected." Result: 2-3 months of no new features, existing clients on legacy code diverging from new platform, and inevitable scope creep. [src4]

### Correct: Strangler Fig pattern
Wrap existing code behind new interfaces. Extract one layer at a time. The old pipeline keeps running until the new engine proves equivalent. Zero downtime, zero risk.

## When This Matters

Use when an agent needs to plan or execute the transition from a working single-vertical Signal Stack pipeline to a reusable platform. This is the critical inflection point: done right, it enables rapid vertical expansion at marginal cost. Done wrong (too early or too abstractly), it kills momentum and wastes months of engineering time.

## Related Units

- [Pilot Execution Playbook](/consulting/recipes/pilot-execution-playbook/2026)
- [Signal Stack Architecture](/consulting/signal-stack/signal-stack-architecture/2026)
- [Vertical Launch Checklist](/consulting/recipes/vertical-launch-checklist/2026)
