Skip to content

Package Architecture

vega-core uses src/ as the package root (set via pyproject.toml package-dir = {"" = "src"}). All framework boundaries are visible in that directory layout: common stage machinery lives outside concrete stage implementations, each stage owns its local files, and plugins are a first-class framework layer.

Directory layout

vega-core/
  pyproject.toml           # build config; package-data for prompts/schemas

  src/
    api/                   # public entrypoints and request/result types
      entrypoints.py       # plan_repo, run_scan, verify_and_patch, configure_*
      requests.py          # PlanRequest, ScanRequest, ScanIntent, ScanExecution,
                           #   VerificationRequest
      results.py           # CoreResult

    framework/             # reusable stage machinery
      base_stage.py        # BaseStage[InputT, OutputT] — lifecycle, hooks, helpers
      context.py           # RunContext — shared dependency object for every stage
      state.py             # PipelineState — immutable shared state across a sequence
      transitions.py       # SequenceTransition protocol
      policy.py            # RunPolicy — run-time configuration consumed by stages
      errors.py            # StageError
      types.py             # StageStatus, StageName, StageInput, StageOutput, Progress
      lifecycle.py         # lifecycle stub

    services/              # framework service protocols used by RunContext
      events.py            # EventSink protocol
      artifacts.py         # ArtifactStore protocol
      cancellation.py      # CancellationToken protocol, CancellationManager,
                           #   StageCancelled
      agents.py            # AgentRunner re-export
      triage.py            # SharedTriageService re-export

    orchestrator/          # workflow assembly
      stage_orchestrator.py  # StageOrchestrator — public workflow methods
      plan_workflow.py       # PlanTransition
      scan_workflow.py       # ScanTransition
      verify_patch_workflow.py  # VerifyPatchTransition

    stages/                # concrete stage implementations
      schema_overrides.py  # apply_schema_enum_overrides, SchemaEnumExtensionPoint

      plan/
        stage.py           # PlanStage
        models.py          # PlanComponent, PlanModule
        prompts/default.txt

      threat_model/
        stage.py           # BaseThreatModelStage
        codex_direct_threat_model_stage.py   # CodexDirectThreatModelStage
        bug_class_threat_model_stage.py      # BugClassThreatModelStage
        default_threat_model_stage.py        # DefaultThreatModelStage
        cache.py           # threat model cache fingerprint validation
        models.py
        prompts/           # codex_direct.txt, bug_class_selection.txt, default.txt
        schemas/           # bug_class_selection.json
        bug_classes/       # research_concepts.json (CWE taxonomy)

      audit/
        stage.py           # BaseAuditStage
        default_audit_stage.py        # DefaultAuditStage
        variant_analysis_audit_stage.py  # VariantAnalysisAuditStage
        models.py
        prompts/           # default.txt, variant_analysis.txt
        schemas/findings.json

      verify/
        stage.py           # VerifyStage
        models.py
        prompts/           # default.txt, threat_model_simplify.txt
        schemas/           # results.json, threat_model_summary.json

      patch/
        stage.py           # PatchStage
        models.py
        prompts/           # generate.txt, minimality_review.txt,
                           #   vulnerability_recheck.txt, default.txt
        schemas/           # generate_results.json, results.json

    plugins/               # plugin capability matching and customization layer
      base.py              # StagePlugin protocol
      capabilities.py      # PluginCapability, PromptSection
      context.py           # PluginContext, PluginSelectionInput, StagePluginRef
      registry.py          # PluginRegistry
      resolver.py          # PluginResolver (deterministic first-match)
      schema.py            # SchemaEnumOverride, SchemaOverrideMode
      selection.py         # PluginSelectionService (3-tier: explicit → match → LLM)

      builtin/
        default/plugin.py            # DefaultPlugin
        linux/plugin.py              # LinuxPlugin
        web_application/plugin.py    # WebApplicationPlugin

    agents/                # agent runner and adapter layer
      runner.py            # AgentRunner, AgentAdapter protocol,
                           #   AgentRunnerError, AgentSelectionError,
                           #   AgentAdapterExecutionError, AgentCancelled,
                           #   AgentTimedOut
      models.py            # AgentTask, AgentResult

      adapters/
        codex.py           # CodexAdapter — Codex CLI subprocess adapter
        fake.py            # FakeAgentAdapter — for tests

    artifacts/             # artifact store implementations
      refs.py              # ArtifactRef, S3ArtifactLocation, URI helpers
      local_store.py       # LocalArtifactStore
      s3_store.py          # S3ArtifactStore

    events/                # event system
      bus.py               # EventBus
      types.py             # CoreEvent

    triage/                # shared bug triage
      shared_service.py    # SharedTriageService
      models.py            # RawFindingBatch, DeduplicatedBugBatch

    runtime/
      config.py            # RuntimeConfig, ArtifactStoreConfig, CodexRuntimeConfig,
                           #   RuntimeServices, build_runtime_services(),
                           #   build_stage_orchestrator()

    source/
      scope.py             # SourceView, normalize_include_paths, path helpers

    contracts/             # backend-facing schema placeholders (JSON)
    testing/               # FakeAgentAdapter, test fixtures

  tests/
    unit/                  # fast unit tests per module
    integration/           # integration tests (plan_repo, run_scan, verify_patch)
    manual/e2e_scan_debug.py  # local CLI debug runner

Package responsibility map

Package Owns
api/ Stable product-facing entrypoints; request and result types called by vega-backend
framework/ BaseStage, RunContext, PipelineState, SequenceTransition, RunPolicy, StageError, StageStatus, StageName
services/ Service protocol definitions and re-exports used by RunContext
orchestrator/ StageOrchestrator public workflow methods; PlanTransition, ScanTransition, VerifyPatchTransition
stages/ Concrete stage logic, stage-specific models, prompts, schemas, and parsing
plugins/ Plugin registration, capability matching, PluginSelectionService, PluginContext, built-in plugins
agents/ AgentRunner contract, adapter selection, timeout/cancellation wiring, CodexAdapter, FakeAgentAdapter
artifacts/ ArtifactRef, LocalArtifactStore, S3ArtifactStore, URI helpers
events/ CoreEvent, EventBus, EventSink
triage/ SharedTriageService, RawFindingBatch, DeduplicatedBugBatch
runtime/ Environment-backed construction of all services and the default StageOrchestrator
source/ Source-root and include-path normalization used by planning, cache fingerprints, and component selection
testing/ FakeAgentAdapter and shared test fixtures

Import rules

These rules keep the architecture layered:

  • Concrete stages may import from framework/, services/, and their own stage package only.
  • Concrete stages must not import sibling stages, specific plugin implementations, or backend modules.
  • Plugins customize stages through framework hooks and PluginContext, not by replacing concrete stage classes.
  • Stage-to-stage handoff belongs in PipelineState and transition classes under orchestrator/, not in stage imports.
  • Backend-owned persistence, queues, and product state remain outside this package.

Key framework types

StageName enum

class StageName(str, Enum):
    PLUGIN_SELECTION = "plugin_selection"
    PLAN             = "plan"
    THREAT_MODEL     = "threat_model"
    AUDIT            = "audit"
    TRIAGE           = "triage"
    VERIFY           = "verify"
    PATCH            = "patch"

StageInput / StageOutput

Every stage receives a StageInput (or subclass) and returns a StageOutput (or subclass). These are frozen dataclasses — stages do not invent their own result envelopes.

@dataclass(frozen=True)
class StageInput:
    repo_id: str
    run_id: str
    source_snapshot: ArtifactRef | None = None
    plan_artifact: ArtifactRef | None = None
    artifacts: Mapping[str, ArtifactRef] = field(default_factory=dict)
    data: Mapping[str, Any] = field(default_factory=dict)

@dataclass(frozen=True)
class StageOutput:
    status: StageStatus
    artifacts: Mapping[str, ArtifactRef] = field(default_factory=dict)
    data: Mapping[str, Any] = field(default_factory=dict)
    progress: Progress | None = None
    error: StageError | None = None

BaseStage

class BaseStage(Generic[InputT, OutputT]):
    name: ClassVar[StageName]
    required_artifacts: tuple[str, ...] = ()
    produced_artifacts: tuple[str, ...] = ()

    def run(self, context: RunContext, input: InputT) -> OutputT: ...  # final
    def execute(self, context: RunContext, input: InputT) -> OutputT: ...  # override this

run(...) is the framework entry point. It handles input validation, artifact checks, plugin hooks, lifecycle events, cancellation checkpoints, error mapping, and timing. Concrete stages override only execute(...).

Artifact kinds

Key artifact_kind string
plan vega.plan
threat_model vega.threat_model
raw_findings vega.raw_findings
audit_component_state vega.audit_component_state
deduplicated_bugs vega.deduplicated_bugs
verification_evidence vega.verification_results
patch vega.remediation_results
codex_run_log vega.codex_run_log