# `abap-enclave` — ABAP Enclave CLI

The pip-installable foundation + capability CLI for [ABAP Enclave](../README.md).
Air-gapped by design: the ADT client talks only to your on-prem SAP system and
the Ollama client talks to a local endpoint — **no ABAP source leaves the
network**.

```sh
pip install -e .            # or: pipx install .   (from this folder)
abap-enclave --version
abap-enclave --help
cp abap-enclave.toml.example abap-enclave.toml   # edit; NO secrets in it
abap-enclave doctor        # resolved (redacted) config + local Ollama check
```

## Layout

- `abap_enclave_core/` — shared foundation the capability modules reuse:
  - `adt.py` — ADT REST client (basic auth + optional `sap-client`, CSRF/cookie
    handling). **Read methods** (`get_object_source`, `run_atc`/`fetch_atc_results`,
    `run_aunit`/`fetch_coverage`, `where_used`, `crawl_package`) plus **opt-in
    write methods** (`lock`/`write_source`/`activate`) the foundation never calls.
    Endpoints are centralized in `endpoints.py` — confirm them against your
    system's `GET /sap/bc/adt/discovery` per release.
  - `ollama.py` — local Ollama client (streaming off, retries, no telemetry).
  - `config.py` — TOML (`abap-enclave.toml`) + env (`ABAP_ENCLAVE_*`). The SAP
    password is read **only** from `$ABAP_ENCLAVE_ADT_PASSWORD` or a prompt.
  - `output.py` — Markdown report builder + optional `.xlsx` (openpyxl). For
    in-system Excel, you can also generate `.xlsx` in SAP with abap2xlsx.
- `abap_enclave/` — the `abap-enclave` typer CLI; capability modules register
  subcommands on the shared app.

## Capabilities

| Command | Default | What it does |
|---------|---------|--------------|
| `atc-triage` | read-only | Explain ATC findings + suggest fixes (advisory). |
| `gen-tests` | dry-run | Draft ABAP Unit tests; write-back is double-gated. |
| `gen-docs` | read-only | Document/explain legacy code; ABAP Doc write is opt-in. |

### `atc-triage` — ATC finding triage (READ-ONLY)

Pull ATC findings (an existing worklist, or a fresh run), ground each in its
source span, ask the local model for an explanation + advisory fix, and write a
report grouped by remediation pattern and ranked by severity + frequency.

```sh
# Triage an existing worklist into a Markdown report:
abap-enclave atc-triage --worklist-id 0123ABC --output md --output-path triage.md

# Run ATC for a package with a specific variant, add caller context, write xlsx:
abap-enclave atc-triage --package ZMY_PKG --check-variant ABAP_CLOUD_DEVELOPMENT_DEFAULT \
    --include-where-used --output xlsx --output-path triage.xlsx
```

| Flag | Default | Meaning |
|------|---------|---------|
| `--worklist-id` | — | Use an existing ATC worklist (no run triggered). |
| `--package` / `--transport` / `--objects` | — | Object set for a fresh run. |
| `--check-variant` | `ABAP_CLOUD_DEVELOPMENT_DEFAULT` | ATC variant for a fresh run. |
| `--model` | config | Local model override. |
| `--output` / `--output-path` | `md` | `md` or `xlsx`, and the file path. |
| `--include-where-used` | off | Add caller context to each prompt (slower). |
| `--batch-size` | `20` | Findings per progress batch. |

**Read-only guarantee:** this command only reads — it never calls
`lock`/`write_source`/`activate`. ADT's own quick fixes cover only a portion of
the typical S/4HANA simplification cases, so the model's suggestions are
**advisory**: a developer reviews and applies the actual fix.

Sample (redacted) report:

```md
# ATC triage report

_3 finding(s). Suggestions are advisory — a developer reviews and applies each fix._

## SAP-table write (1)
**`CLAS/OC ZCL_…`** — Error
*Direct write to an SAP standard table* (`…#88`)
1) Root cause … 2) Clean Core context … 3) Suggested fix … 4) Risk (advisory).
```

### `gen-tests` — ABAP Unit test generation (DRY-RUN by default)

Fetch a class's source, prompt the local model for an AAA test class (test
doubles via `CL_ABAP_TESTDOUBLE`), and **write it to a local file** for review.

```sh
# Dry-run (default): generate local files only — NO system writes:
abap-enclave gen-tests --classes ZCL_A,ZCL_B --out-dir ./generated-tests --coverage-target 80

# Write back into the system (double-gated — both flags required), then activate:
abap-enclave gen-tests --classes ZCL_A --write-back --yes --activate
```

| Flag | Default | Meaning |
|------|---------|---------|
| `--classes` / `--package` | — | Classes to generate tests for. |
| `--out-dir` | `abap-enclave-tests` | Local output dir (dry-run). |
| `--coverage-target` | `80` | Target statement coverage % (guides the prompt). |
| `--write-back` | **off** | Create the test include in the system — **MUTATES**. |
| `--yes` | **off** | Required to confirm any mutation. |
| `--activate` | off | Activate after write-back (needs `--write-back`). |
| `--force` | off | Overwrite an existing test include. |

**Safety design:** writing back is **double-gated** — it happens only with
`--write-back` **and** `--yes`, prints a warning naming the target object, and
never overwrites an existing test include without `--force`. By default nothing
in the system changes. **Human-in-the-loop:** local-model output can be wrong —
generated tests are a starting point a developer reviews and runs; the command
never auto-iterates mutations. With `--write-back`, coverage can be measured
afterward via the core's AUnit + coverage calls.

### `gen-docs` — documentation & legacy-code explainer (READ-ONLY by default)

Crawl a package (or take `--objects`), pull each object's source + where-used,
summarize with the local model, and emit a Markdown docs set (index + per-object
pages). The lowest-accuracy-risk capability.

```sh
# Read-only: write a Markdown docs set for a package (NO system writes):
abap-enclave gen-docs --package ZMY_PKG --out-dir ./abap-docs

# Opt-in: also push ABAP Doc comments back into source (gated), then activate:
abap-enclave gen-docs --objects ZCL_A --abap-doc --yes
```

| Flag | Default | Meaning |
|------|---------|---------|
| `--package` / `--objects` | — | Crawl a package, or an explicit object list. |
| `--out-dir` | `abap-enclave-docs` | Markdown output dir. |
| `--format` | `md` | Output format. |
| `--abap-doc` | **off** | Insert ABAP Doc comments into source — **MUTATES**. |
| `--yes` | **off** | Required to confirm any ABAP-Doc write. |
| `--force` | off | Overwrite existing ABAP Doc comments. |

**Read-only default + gated write:** by default this only emits files. Pushing
ABAP Doc comments back is double-gated (`--abap-doc` **and** `--yes`), warns per
object, and never overwrites existing comments without `--force`. Summaries are
**model-generated and should be spot-checked**.

## Tests

```sh
pip install -e ".[dev]"
python -m pytest          # mocked HTTP (responses) + fixtures; offline
```

Live SAP/Ollama behavior is **not** exercised by the tests — only mocks and
committed fixtures. Confirm ADT endpoints/payloads against your target release.

> A starting point the **ABAP Enclave service** tailors to your landscape:
> https://lumivara.ca/services/abap-enclave
