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
PipelineStateand transition classes underorchestrator/, 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 |