
## Drilling

### Execution model

`./ops` runs pipelines by dispatching to resolved POSIX sh files in `.opcache`. On invocation:

1. Check `.opcache` for an already-resolved `.op.sh` matching the target group/pipeline.
2. If present and fresh, execute it directly — no compilation or resolution step.
3. If missing or stale, resolve the needed portion of the pipeline (compile → lower → resolve → emit) and write the result to `.opcache`, then execute.

The same emitted `.op.sh` files in `.opcache` are the ones assembled into standalone scripts by `scripts = {}`. Drilling and standalone generation share identical artifacts — you never run different code locally than what gets used in CI/CD.

Drilling consumes the canonical [IR schema](./ir_schema.md), especially [tier-consumers](./ir/tier-consumers.md), [dependency-and-safety](./ir/dependency-and-safety.md), and [posix-emission](./ir/posix-emission.md).

### CLI surface

Every generated `.op.sh` (root and group) gets a CLI flag parser and `--help`.

- **Root**: full env surface flags (`--kebab-case`), `--env KEY=VALUE`, `--skip-env`, `--help`
- **Group**: only env flags the group's ops actually consume (including transitive), `--help`
- **Flag provenance (depth-1)**: `--target <string>  required by: docker.push`. Full cross-pipeline chain tracing deferred post-engine.
- **Doc comments** (`## ... ##`) surface in `--help`: top-level for summaries, inline for scoped annotations
- **Transitive propagation**: walk full dep graph including `use`d pipelines to build help surface

```
Flags:
  --target <string>   required by: docker.push
  --registry <string> required by: docker.push, docker.tag
  --dry-run           default: false
```

**`@VAR` drilling**: `./ops pipeline @VERSION` reads `.exports.json`, dispatches to the producing group (running transitive deps), echoes the value.

**Per-step drill files**: named steps (via `as`) get individual `.op.sh` files running the prefix of steps up to that point. Conditions: ≥2 leaves, not a block group, at least one `as` name.

### Env Flag Disambiguation

When multiple ops declare the same env key:

1. **No conflict**: short flag. `THRESHOLD` → `--threshold`
2. **Conflict**: compile error. The pipeline author must disambiguate in their `env = {}` block. This keeps the CLI surface codified in the pipeline itself — it never shifts silently when ops are added or removed.
3. **Explicit `env = {}`**: always takes precedence. The declaration is the stable public API for the pipeline.

### Skip, Safety & Defer

**Skip (`--skip-env`)**: required env vars without defaults become `__SKIPPED__`. Steps consuming skipped vars are skipped via `__ops_check_skip`. Skipped exports propagate downstream. Pipeline structure remains visible in `--help` and drilling.

**Skip wants (`--skip-wants`)**: omits all `wants` dependencies for faster local iteration. Skipped wants propagate `__SKIPPED__` downstream via the same mechanism as `--skip-env`.

**Safety gates (`--allow-remote`, `--allow-dangerous`)**: blocks marked `remote` or `dangerous` resolve as `__SKIPPED__` unless their opt-in flag is provided. The calling pipeline keeps running — steps that consume skipped outputs are themselves skipped; steps that don't touch them run normally. Same propagation mechanism as `--skip-env`. The resolver walks the dep graph and marks blocks as transitively remote/dangerous. `--help` annotates affected groups:

```
Flags:
  --version <semver>      required by: deploy
  --datacenter <string>   required by: deploy (remote)

Safety:
  --allow-remote          enable remote operations (off by default)
  --allow-dangerous       enable dangerous operations (off by default)
  --skip-wants            skip soft dependencies
```

**Defer (`std.defer`)**: `@defer` pushes cleanup onto a LIFO stack, drained at group completion like Go's `defer`. Currently broken in bash — `__run_deferred` never called. Emitter generates drain calls or `trap ... EXIT`. Deferred failures don't prevent others from running.

### Error output

Compilation errors use `@error` structure with hex codes and source snippets. `--json` mode emits structured diagnostics. See [strategies/error-catalog](./strategies/error-catalog.md) and [strategies/machine-output](./strategies/machine-output.md).
