# Diagnostics: recursive container rescue snapshot `container.py` is the single failure-diagnostics entry point. The CI workflows (compose + swarm) call it once on the runner when a job fails; it captures the current level and then recurses itself through every Docker-in-Docker boundary, so one call collects evidence from the outermost runner down to the innermost application container. It always exits 1. ```mermaid flowchart TB subgraph entry["🩺 One workflow call on failure()"] wf["⚙️ CI step (compose + swarm identical)
INFINITO_RESCUE_DIAGNOSTICS_DIR=/tmp/rescue-diagnostics/<app>
python3 utils/diagnostics/container.py <app> <context>"]:::infra end subgraph level["📸 Per-level capture (repeated on every depth)"] direction TB host["🖥️ Host facts
meta, uname, df/free/uptime,
journal, dmesg OOM evidence"]:::store dumps["📂 local-dumps/
in-play role evidence from
DIR_RESCUE_DIAGNOSTICS (pg_hba, xwiki)"]:::store rtc["🐳 Runtime state
info, stats, ps -a,
per-container logs + inspect"]:::store svc["🐝 Swarm services
ls, per-service ps + logs"]:::store end subgraph recursion["🔁 Recursion (RESCUE_MAX_DEPTH, default 3)"] direction TB probe["🔍 For every RUNNING container:
has python3 + docker/container runtime?"]:::step copy["📤 Copy itself in
(stdin → /tmp/rescue-self.py)"]:::step nested["🩺 Run nested capture
RESCUE_DEPTH+1, own staging dir"]:::step pull["📥 tar the nested snapshot back to
containers/<name>/nested/ + clean up"]:::step probe -->|yes| copy --> nested --> pull probe -.->|no: plain app container,
logs already captured| skipped["⏭️ skip"]:::skip end wf --> level --> recursion nested -.->|same program,
one level deeper| level result["🗂️ Artifact tree (uploaded by CI)
<app>-<stamp>-<pid>/
├── meta/system/journal/…
├── local-dumps/…
├── containers/<name>.log + .inspect.json
├── containers/<did-node>/nested/<app>-…/ (recursion)
└── services/<svc>.log + .ps.txt"]:::store recursion --> result classDef infra fill:#f3f7fb,stroke:#d6e2ee,color:#455a64; classDef store fill:#f1f8f6,stroke:#d5e7e2,color:#455a64; classDef step fill:#fbf6f0,stroke:#eee1cf,color:#455a64; classDef skip fill:#f7f8f9,stroke:#e3e6e9,color:#455a64; style entry fill:#ffffff,stroke:#e6e6e6; style level fill:#ffffff,stroke:#e6e6e6; style recursion fill:#ffffff,stroke:#e6e6e6; ``` Ansible `rescue:` blocks are forbidden (`tests/lint/ansible/structure/test_no_rescue_blocks.py`); the rare justified block (`# nocheck: rescue-`) leaves its role-specific evidence in `DIR_RESCUE_DIAGNOSTICS`, which every capture level ships as `local-dumps/`.