---
name: ssp-compile
description: Compile flat SSP CSV manifests + companion narratives into a halo-action-pipeline actions.jsonl, or project any action file back to a review CSV
---

# SSP Compile

Compile the four flat SSP structure manifests (`components.csv`, `cap-component-rel6.csv`, `odp-parameters.csv`, `is-manifest.csv`) plus AFUUID-keyed companion narrative markdown into a `[[halo-action-pipeline]]` `actions.jsonl`, then hand off to `/grcitsm-analyst:halo-apply`. The manifests are the human review projection; the JSONL is the executable source of truth. The compiler is deterministic and offline — it never calls MCP; every tenant-derived input arrives as a file.

The reverse projection (any action file → a flat review CSV) is independently useful and needs no compile run.

## Usage

```
/grcitsm-analyst:ssp-compile <manifest-dir>
/grcitsm-analyst:ssp-compile --plan-review-only <action-file>
```

- `<manifest-dir>` — directory holding the four CSV manifests (default forward-compile flow). Companion markdown, snapshot, and library CSVs are resolved alongside it or produced in step 2.
- `--plan-review-only <action-file>` — skip compile entirely; project an existing `actions.jsonl` to a flat `plan-review.csv` (one row per action) and present it. Reverse projection only, no tenant reads.

## Agents

| Agent | Purpose | When Invoked |
|-------|---------|--------------|
| `ssp-reviewer` | Runs the mandatory SSP Review Chain (CHANGE-PLAN review loop) over narrative changes | Narrative-touching runs only — when the compiler's review gate reports a `narrative_sha` mismatch on a non-library row. Pure-structure and all-library batches skip it |

Pure-structure compiles need no agent: the command runs `ssp_compile.py` directly and presents the output. Only narrative mutations route through `ssp-reviewer`.

## Process

Load the **`ssp-csv-compile` skill** and follow it; the column contract is in `[[ssp-manifest-schemas]]`. The scripts live in the skill's `scripts/` dir. In brief:

**`--plan-review-only` path:** run `make_plan_review.py <action-file> -o <plan-review.csv>`, present the CSV, and stop. No compile, no tenant reads.

**Forward compile path:**

1. **Validate manifests (fail loud).** Run
   `ssp_compile.py check --manifests <dir> [--companions <dir>] [--snapshot F] [--library F] --client-id <client> --site-id <site>`.
   The tenant-scope flags are required whenever the compile emits creates — `check` also validates the emitted actions (REQUIRED_ARGS gate), so an under-specified create fails here, never in front of an executor.
   Surface the row-level errors verbatim (unknown column, bad enum, missing required field, unknown AFUUID, dangling FK, `library_flag=library` with no library-lookup match). Stop on non-zero exit — these are contract breaks, no partial output, no improvisation.

2. **Produce the tenant snapshot, library-lookup, and field-map CSVs.** The compiler is pure and never calls MCP. For **small targeted scopes**, this agent step runs read-only MCP lookups — existing SSP assets by AFUUID into the **snapshot CSV**, library rows (`lookup_implementation_statement_definition` / component library) into the **library CSV**, and `asset_type_fields` per spine type into the **field-map CSV** (`assettype_id,field_name,field_id` — numeric Asset Field ids are tenant-specific and must arrive per-tenant at run time, never hardcoded). For **BULK scopes**, accept a USER-EXPORTED CSV (e.g. a Halo report export) instead of a read fleet. The files are what the script consumes via `--snapshot` / `--library` / `--field-map`.

3. **Check the review gate.** The compiler compares each non-library row's live companion-file hash against its stamped `narrative_sha`. Any mismatch means the narrative changed since last review → route that batch through the `ssp-reviewer` CHANGE-PLAN chain (the SSP Review Chain is mandatory for content mutations). A pure-structure or all-library batch (every stamp matching) skips to step 4.

4. **Compile.** Run
   `ssp_compile.py compile --manifests <dir> --companions <dir> --snapshot F --library F --field-map F --out actions.jsonl --plan-review plan-review.csv --report report.json [--system-name NAME] --client-id <client> --site-id <site>`.
   Present the compiled plan, `plan-review.csv`, and the `report.json` decision items:
   - **Drift** (a snapshot field differs from a manifest-owned row) → `report.json` lists the field + tenant value. Default is **overwrite** (manifest wins); to hold a row out of this run, pass `--exclude-file <afuuids.txt>` (one AFUUID per line) and re-run. Silent overwrite never happens — adopt-into-manifest (fold-back) is deferred, so "adopt" is a manual manifest edit for now.
   - **No-op** (existing row matches the tenant on every written field) → its UPDATE is skipped automatically (changed-only emit; requires a wide snapshot).
   - **Orphans** (a manifest-owned asset in the snapshot with no manifest row) → REPORT rows only, never a delete/retire action.
   The action file is **not finalized** until every drift item is decided and the user gives explicit approval.

5. **Hand off to apply.** On approval, invoke `/grcitsm-analyst:halo-apply` (unchanged) with the compiled `actions.jsonl`.

## Guardrails

- **The compiler never writes to Halo and never calls MCP** — it emits an action file; `/grcitsm-analyst:halo-apply` is the only executor.
- **Never bypass the review gate.** A `narrative_sha` mismatch means the content changed since last review — it must go through `ssp-reviewer`, not straight to apply.
- **No deletes.** Orphans are reported, never retired or deleted by this pipeline; retirement is a deliberate manual/ops action.
- **Fail loud on contract breaks.** Schema violations, unknown AFUUIDs, and dangling FKs stop the run with no partial `actions.jsonl` — fix the manifest or the upstream reads and re-run `check`.

## Error Handling

- No Halo MCP connection (needed for step 2 small-scope reads) → stop and point at `/grcitsm-analyst:setup`, or accept a user-exported snapshot/library CSV instead.
- `check` reports row-level errors → do not compile; return the errors for the user to fix in the manifests.
- Optional hand-review workbook: `make_review_xlsx.py <manifest-dir> <review.xlsx> --plan-review plan-review.csv` (openpyxl-gated). The CSVs remain the round-trip source of truth; the workbook is a read view only.

## Related Commands

- `/grcitsm-analyst:halo-apply` — applies the compiled `actions.jsonl` to the tenant (the executor this command hands off to).
- `/grcitsm-analyst:ssp-ingest` — the documentation-driven CHANGE-PLAN path into the same SSP spine (prose inputs rather than authored manifests).
- `/grcitsm-analyst:ssp-generate` — generate SSP deliverables from the populated spine.
