Thin wrapper around the SPARTA pipeline project (79K LOC Python). Runs pipeline steps, checks status, runs tests, launches Explorer UX. The real code lives at ~/workspace/experiments/sparta/src/sparta/pipeline/ — this skill is an interface, not a reimplementation.
Scanned 9/11/2026
Install to Claude Code
npx -y skills add grahama1970/agent-skills --skill ingest-sparta --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ingest Sparta?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/grahama1970-ingest-sparta)More formats (shields.io, HTML) on the badges page.
---
name: ingest-sparta
description: >
Thin wrapper around the SPARTA pipeline project (79K LOC Python).
Runs pipeline steps, checks status, runs tests, launches Explorer UX.
The real code lives at ~/workspace/experiments/sparta/src/sparta/pipeline/ —
this skill is an interface, not a reimplementation.
project-path: ${HOME}/workspace/experiments/sparta
triggers:
- ingest sparta
- sparta ingestion
- sparta explorer
- run sparta pipeline
- sparta pipeline step
- sparta status
provides:
- sparta-ingestion
- sparta-pipeline
composes:
- ux-lab
- memory
- task-monitor
- agentic-evals
taxonomy:
- precision
- resilience
- ingestion
- security
disciplines:
- compliance-security
- data-engineering
---
> STOP. READ THIS ENTIRE SKILL.MD BEFORE CALLING ANY ENDPOINT.
# /ingest-sparta
Thin skill wrapper around the real SPARTA pipeline at
`${HOME}/workspace/experiments/sparta/`.
## What This Skill Does
Dispatches commands to the real pipeline. Does NOT contain pipeline logic.
## What the Real Pipeline Does
40 numbered Python steps (00-18) that:
1. Fetch SPARTA-Data.xlsx + ATT&CK + CWE + D3FEND + NIST + ESA sources
2. Extract and normalize 2,147+ controls across 6 frameworks
3. Fetch ~10K URLs referenced by controls
4. Extract clean text from fetched HTML/PDF
5. Generate embeddings and knowledge anchors
6. Build relationship graph (deterministic + LLM-verified edges)
7. Generate QRAs with T0/T1.5/T2 quality cascade
8. Calibrate confidence thresholds via active learning
9. Export tiered graph
Data stored in DuckDB (358MB production DB) + ArangoDB (via SpartaDataBridge).
DuckDB migration to ArangoDB complete for pipeline steps (commit f8c5be4d).
DuckDB remains as read-only data layer via SpartaDataBridge.
## Commands
```bash
# Run a specific pipeline step (from sparta project root)
cd ${HOME}/workspace/experiments/sparta
uv run python -m sparta.pipeline.00_fetch_source
uv run python -m sparta.pipeline.12_qra --run-id myrun --limit 100
uv run python -m sparta.pipeline.08_relationships --run-id myrun
# Run tests
uv run pytest tests/ -v
uv run pytest tests/ -k "test_qra"
# List available steps
ls src/sparta/pipeline/[0-9]*.py
```
**Module path is `sparta.pipeline.NN_name`, NOT `sparta.pipeline.steps.NN_name`.**
The old `steps/` subdirectory generation (56 files, e.g. `01d_map_cwe_nist`,
steps 48-61) lives only on branch `feature/nrs-standardization` at `e1cba40`;
on main its directory held nothing but stale bytecode and was removed
2026-08-11. Any `sparta.pipeline.steps.*` invocation fails with `No module
named`.
## Pipeline Steps (real, in src/sparta/pipeline/)
Verified against the filesystem 2026-08-11 (40 files, 00-18). Earlier revisions
of this file listed steps 01b/01c/01d/01e, 05d, 11b, 12b/12c, 13b, 14-25,
48-55 and 60-61, none of which exist on main.
| Step | Module | What It Does |
|------|--------|-------------|
| 00 | `00_fetch_source` | Download SPARTA xlsx from sparta.aerospace.org |
| 01 | `01_extract_base` | Parse SPARTA spreadsheet into structured data |
| 02a/02b | `02a_sheet_normalize`, `02b_sheet_audit` | Normalize and audit worksheets |
| 03 | `03_sheet_enrich` | Enrich sheet records |
| 04 | `04_context_merge`, `04b_child_bundle` | Merge context, bundle child records |
| 05 | `05_url_inventory` | Build URL manifest from controls |
| 06 | `06_fetch_urls`, `06b_alt_sources`, `06b_category_knowledge`, `06c_alt_sources_review`, `06c_fetch_cwe`, `06d_verify_alt_sources`, `06m_audit` | Fetch URLs, alternate sources, CWE |
| 07 | `07_generate_knowledge_chunks`, `07_generate_pdf_html_chunks`, `07a_cwe_to_chunks`, `07b_generate_llm_knowledge_chunks`, `07c_audit`, `07c_build_knowledge_anchors` | Chunking and knowledge anchors |
| 08 | `08_relationships`, `08c_cwe_summaries`, `08d_cwe_shortlist`, `08e_cwe_adjudicate` | Deterministic edges, CWE adjudication |
| 09 | `09_relationships_llm`, `09a_relationships_llm_audit`, `09a_relationships_tune`, `09b_cc_conceptual`, `09r_reject_sample_audit` | LLM-verified edges |
| 10 | `10_groupings` | Groupings |
| 11 | `11_export_graph`, `11a_qra_inputs_audit` | Graph export, QRA input audit |
| 12 | `12_qra` | QRA generation with quality cascade |
| 13 | `13_persist_arango` | Persist to ArangoDB |
| 14 | `14_embed_chunks` | Generate embeddings |
| 15 | `15_map_cwe_nist` | CWE→NIST via MITRE Heimdall (recovered 2026-08-11; Rev4 caveat below) |
| 16 | `16_qra_audit` | QRA quality audit |
| 17 | `17_crosswalk_edges` | Deterministic crosswalk edges: ATLAS mitigates, CVE→CWE |
| 18 | `18_ingest_security_corpora` | Dispatch to external ingests: atlas, kev, nvd, qa, refresh, epss, owasp_llm |
Step-number prefixes are not unique: `06b`, `06c`, `07`, `07c` and `09a` each
name two different modules. Always invoke the full module name.
## Framework Registry (what is actually in sparta_controls)
Verified live 2026-08-11 after the framework alignment audit (active =
`deprecated != true`). Every active framework except EMB3D participates in
crosswalk edges; 419,326 total relationships (2026-08-12: 419,299 post-audit + 27 OWASP_LLM).
| source_framework | Active controls | Loaded by | Edges |
|------------------|---------------:|-----------|-------|
| `NVD_CVE` | 372,716 | step 18 → `scripts/ingest_nvd_cvelist.py` | 154,604 CVE→CWE (step 17) |
| `NIST` | 1,896 | numbered pipeline | 121,957 →SPARTA |
| `ATT_CK_Enterprise` | 1,644 | numbered pipeline + domain relabel | yes |
| `CISA_KEV` | 1,616 | step 18 → `scripts/backfill_kev_corpus.py` | 597 CVE→CWE (step 17) |
| `SPARTA` | 1,110 | numbered pipeline | yes |
| `CWE` | 944 | numbered pipeline | yes |
| `CAPEC` | 615 | numbered pipeline | yes |
| `D3FEND` | 424 | numbered pipeline | yes |
| `ATT_CK_Mobile` | 316 | numbered pipeline + domain relabel | yes |
| `MITRE_ATLAS` | 205 | step 18 → `scripts/ingest_atlas.py` | 246 mitigates (step 17) |
| `EMB3D` | 170 | outside pipeline | none — mitigations only; threat nodes not yet ingested, so no edges are derivable (legitimate orphan) |
| `ATT_CK_ICS` | 167 | numbered pipeline + domain relabel | yes |
| `ESA` | 137 | numbered pipeline | 652 |
| `ISO` | 23 | outside pipeline | yes |
| `NASA` | 14 | outside pipeline | yes |
| `OWASP_LLM` | 10 | step 18 → `scripts/ingest_owasp_llm.py` | 27 references_weakness_context → ATLAS/CAPEC/CWE |
Retired labels (records survive with `deprecated: true` and provenance, never
deleted): `NVD` (4,830 merged into `NVD_CVE` after identity analysis proved
the same CVE record family), `ESA_Shield` (137 duplicates of ESA with
`duplicate_of_control_id` pointers), `attack` (524 legacy techniques
relabelled to their MITRE domain via STIX bundles; 12 quarantined —
corrupt pipe-delimited ids and retired technique ids — deprecated),
`retired_probe` (500 `nvdtest__` test residue).
Adding a framework means TWO writes, not one: nodes into `sparta_controls` and
edges into `sparta_relationships` (step 17 for deterministic families). Nodes
alone are reachable by semantic and BM25 search but join no crosswalk chain.
`monitor-sparta` check 30 (Framework Label Alignment) catches orphan
frameworks and label drift; check 31 (Framework Label Congruence) catches edge
labels that contradict their own endpoints.
Use the exact label already present. Do not introduce a case or format variant
of an existing framework. Known surfaced findings, deliberately not repaired:
the `F36_SUPPLY_CHAIN` / `F36_THREAT_PROFILE` / `F36_SPARTA_EXPLORER`
edge-only namespaces and the dangling endpoint references (F36/TA ids with no
control documents).
CVE records additionally carry EPSS enrichment FIELDS (`epss_score`,
`epss_percentile`, `epss_model_version`, `epss_date`; 356,485 records =
95.2% of CVEs, refreshed via step 18 `epss`). EPSS rows are attributes of
existing CVEs, never nodes.
## Crosswalk Paths (CWE → SPARTA)
Edge counts verified against the live corpus 2026-08-11:
| Path | Hops | Data Source | Edges (live) |
|------|------|-------------|--------------|
| CWE → SPARTA (direct) | 1 | SPARTA v3.1 `cwe_class_ids` | 2,825 |
| NIST → SPARTA | 1 | numbered pipeline | 121,957 |
| CAPEC → CWE | 1 | MITRE curated fields | 1,212 |
### Direct Path (SPARTA v3.1)
Step 08 extracts `cwe_class_ids` from SPARTA Techniques and creates CWE→SPARTA edges.
```bash
# Run Step 08 to create/update CWE→SPARTA edges
uv run python -m sparta.pipeline.08_relationships --run-id <run-id>
```
### CWE → NIST 2-hop Path (Heimdall): Step 15
The July pipeline rewrite dropped the old `steps/01d_map_cwe_nist` module; it
was recovered onto main 2026-08-11 as `15_map_cwe_nist` (commit `0864539`).
```bash
uv run python -m sparta.pipeline.15_map_cwe_nist --download --dry-run # preview
uv run python -m sparta.pipeline.15_map_cwe_nist # apply
```
Populates `nist_control_ids` + `nist_source` on CWE controls from the MITRE
Heimdall CSV (144 curated mappings; 138 CWEs present in the corpus enriched on
recovery, 2-hop path verified live: `CWE-79 → SI-10 → 17 SV-* controls` via
`tor_threats`). Note this writes a FIELD, not edges — CWE→NIST edge documents
in `sparta_relationships` still need a relationships step to materialize the
path for graph traversal.
Provenance caveat (externally validated 2026-08-11): `mitre/heimdall_tools` is
archived (last push 2022-02-05, superseded by SAF CLI) and the CSV maps to
800-53 **Rev 4** — hence `nist_source = "mitre_heimdall_800-53r4"` on every
enriched doc. Translate through NIST's Rev4→Rev5 change analysis before
materializing production edges; NIST warns those relationships are not
one-to-one.
### Edge Casing in sparta_relationships
Framework labels on edges are case-exact matches of `sparta_controls`
labels since the 2026-08-11 `relationship_framework_label` repair
(243,914 edges relabelled `nist`→`NIST`, `sparta`→`SPARTA`; zero lowercase
labels remain).
| Edge Type | source_framework | target_framework |
|-----------|-----------------|------------------|
| CWE→SPARTA | `"CWE"` | `"SPARTA"` |
| NIST→SPARTA | `"NIST"` | `"SPARTA"` |
| CAPEC→CWE | `"CAPEC"` | `"CWE"` |
Write new edges with the exact `sparta_controls` label. monitor-sparta
check 30 (`framework_label_alignment`) flags any edge whose framework label
matches no control population.
## Explorer UX
8-tab React UI for SPARTA pipeline transparency. Launch via `./run.sh explorer`.
- **Frontend**: Vite on `:3002` — renders `SpartaExplorer` with 8 view components
- **API proxy**: Express on `:3001` — proxies `/api/memory/*` to daemon Unix socket
- **Data**: ArangoDB via memory daemon. Verified 2026-08-11: 382,700 controls,
250,679 QRAs, 263,854 relationships, 6,854 URLs, 6,855 url_content rows
Views: Overview, Sources, Controls, URLs, Knowledge, QRAs, Relationships, Pipeline.
Keyboard: press 1-8 to switch tabs.
Components at `pi-mono/packages/ux-lab/src/components/sparta/explorer/`.
## Related Skills
| Skill | Relationship |
|-------|-------------|
| `/sparta-review` | Brandon persona assessment of QRA quality |
| `/reality-check-sparta` | Adversarial data quality verification |
| `/monitor-sparta` | Continuous T0/T1.5/T2 quality monitoring |
| `/data-audit` | DuckDB coverage report (Control→URL→Knowledge→QRA) |
| `/qra-review` | Human-in-the-loop QRA accept/reject TUI |
| `/sparta-stress-test` | End-to-end query pipeline stress test |
## QRA Schema (CRITICAL)
**Canonical field for control ID: `source_control_id`**
| QRA Type | qra_type | source_control_id Example | Notes |
|----------|----------|---------------------------|-------|
| Native | `native` | `CAPEC-115`, `T1595`, `CWE-79` | Framework definition QRAs |
| Relationship | `sparta_context` | Technique ID from relationship | SPARTA-linked QRAs |
**Legacy field:** `control_id` exists in older QRAs. Code queries BOTH fields:
```python
cid = qra.get("source_control_id") or qra.get("control_id") or ""
```
**When querying by framework:**
```aql
// Native QRAs (from /create-qras skill)
FOR q IN sparta_qra
FILTER STARTS_WITH(q.source_control_id, "CAPEC-")
RETURN q
// BOTH native and legacy
FOR q IN sparta_qra
LET cid = q.source_control_id != null ? q.source_control_id : q.control_id
FILTER STARTS_WITH(cid, "CWE-")
RETURN q
```
## Environment
```bash
SPARTA_ROOT=${HOME}/workspace/experiments/sparta # auto-detected
# DuckDB: data/runs/<run-id>/sparta.duckdb
# ArangoDB: via SpartaDataBridge (graph_memory)
# Embedding: port 8602
```
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!