# CLAUDE.md -- Omega Cloud jumphost session contract

This working directory is the LIVE operations clone on the jumphost
(vcloud). Commands here reach the real cloud: the juju controller,
MAAS, and the OpenStack APIs. This file is always in context; the full
operating skill loads on demand from `.claude/skills/openstack-cloud-ops/`
(read its SKILL.md before any nontrivial task -- it carries the routing table,
the standard loops, and the script-authoring/troubleshooting discipline).

## Hard rules (non-negotiable; a live shell relaxes transport, never discipline)

1. Execute only the current runbook step, exactly as written. No added scope,
   no adjacent improvements mid-step. Findings are LOGGED (changelog / D-NNN
   proposal), never executed live mid-step.
2. Never use an inferred value. No IP, ID, name, or scope enters a command
   unless measured this session or carried from confirmed as-built. Would-be
   inferences STOP and get measured.
3. Verify before mutate. Read-only audit first; every mutation is presented,
   justified as the minimal correct action, and individually human-approved
   (the permission `ask` rules enforce this -- do not work around them).
   Destructive steps are never batched.
4. **USE THE TESTED ARTIFACT. Look it up BEFORE you type a command.** This repo
   exists to make deployment and troubleshooting error-free WITHOUT a build:
   93 scripts, 28 runbooks, 98 harnesses, each written because an incident
   proved it was needed. **`docs/tool-index.md` maps the job to the artifact --
   read it first.** Typing a raw `juju` / `maas` / `tofu` / `virsh` command for
   an operation is the ERROR SIGNAL, not the starting point: it means the lookup
   was skipped. Deriving an invocation from `--help` or from a prior session's
   transcript when a tested script is on disk is the same error. If no artifact
   exists, SAY SO and propose building one -- a gap is a finding, never a licence
   to improvise. (Added 2026-08-03 after an ad-hoc `juju destroy-model` was run
   instead of the D-061 teardown scripts and took the dc0 controller down.)

## Session bootstrap (run at the start of every session)

    git pull
    bash scripts/repo-lint.sh          # expected result: see docs/CURRENT-STATE.md (GA-R1)
    bash scripts/run-tests-all.sh      # after any tooling change; ALL GREEN expected

For any session that will mutate the cloud, the operator starts logging first:
`bash scripts/run-logged.sh <label>` (see docs/as-executed-log-convention.md).

## Secrets (enforced by permission rules + the PreToolUse guard; also a norm)

Never read key or credential material into context: `~/vault-init/`,
`~/as-executed/`, `~/tenant-*/`, any `*-cred.txt` / `*appcred*` file. Verify
secrets by length/format from a script, never by printing. One-shot vault
operations (init/rekey/generate-root) are operator-only, verbatim from the
runbook -- the guard hook hard-blocks them.

## Tooling guardrails (enforced by permission rules + repo-lint; also a norm)

Never run `/caveman-compress` -- or its underlying `python3 -m scripts <file>`
compressor -- against ANY repo-tracked file. It overwrites the target IN PLACE
with a lossy caveman-speak rewrite and drops a `<name>.original.md` backup, which
is incompatible with this repo's verbatim-record discipline (GA-R1 exact
captures, GA-R5 quoted operator utterances, the append-only D-NNN log). The
prose-record corpus is the whole hazard surface, not a short list: CLAUDE.md,
`docs/CURRENT-STATE.md`, `docs/design-decisions.md`, `docs/security-ledger.md`,
`docs/audit/*`, the runbooks, the skill, and every changelog. Layered
enforcement: the caveman plugin is DISABLED (SEC-017); a permission `deny` blocks
the compressor's invocation; repo-lint L11 FAILS on any `*.original.md` residue.

## Where things are

- Deploy gate: `bash scripts/preflight.sh` (the ONLY pre-deploy entry).
- Cloud health: `bash scripts/cloud-assert.sh` (behavioral; `--capture` = BOM).
- Incidents: `runbooks/appendix-A-troubleshooting.md` by verbatim symptom.
- Restart: `runbooks/ops-restart-procedure.md`.
- Decisions: `docs/design-decisions.md` -- grep for the governing D-NNN before
  ANY change to a built surface; PROPOSED means present options, never pick.
- Numbering: grep for next-free before assigning any D-/DOCFIX-/BUNDLEFIX-NNN.
- Delivery: every script change ships with its `tests/<name>/run-tests.sh`
  harness green, `repo-lint` clean, and a changelog entry with a revert.

Repo content is authoritative over anything remembered from prior sessions;
when they diverge, the repo wins and the divergence gets flagged.
