Inner-loop iteration on a deployed stack often needs a one-off sidecar
container against the same docker daemon the stack lives on — typical
cases are rerunning a Playwright project with a patched .env, retrying
an arbitrary CLI image against an app container, or smoke-checking a
release image without going through Ansible. Without a wrapper the
caller has to spell out `docker exec <host-container> docker run --rm
<flags...> <image> <cmd>` by hand, which is verbose enough that agents
tend to fall back to redeploying instead of validating in-place.
Add `make run IMAGE=<ref> [CMD=...] [RUN_FLAGS=...]` plus the underlying
`scripts/tests/deploy/local/exec/run.sh`. The script reuses
`scripts/meta/env/all.sh` to resolve the host container name (same SPOT
as `make exec`), forwards RUN_FLAGS verbatim, and only wraps CMD in
`sh -lc` so default-entrypoint images and shell one-liners both work.
Wire both iteration loops to mention the wrapper next to `make exec`:
the Role Loop's Inspect block gets a bullet pointing at it, and the
Playwright Spec Loop gains a short "Debugging in the nested docker
daemon" section that also reminds the agent to mirror any successful
hand-patch back into the role's playwright.env.j2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three classes of drift cleaned up across 85 .md files:
- Em-dashes: replaced ` — ` with the contextually correct separator
(colon for `term: explanation`, period to split clauses across
sentences/source lines, parentheses for asides, semicolon for
tight-linked continuations). Two intentional exceptions remain
in `docs/contributing/documentation.md` (the rule literal) and
inside a fenced ```sh block in `docs/contributing/actions/debugging/ci.md`.
- SPOT self-labels: rewrote "This is the SPOT for X" to describe
the subject directly ("This directory holds X" / "This file
describes X"). Cross-references to other artefacts' canonical
role remain unchanged.
- Heading-emoji position: moved leading-emoji headings (`# 🧩 Title`)
to trailing position (`# Title 🧩`) per the headline rule that
emojis MUST come after the title text.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hard-coded self-path references rot the moment the file moves: a header
comment ``# utils/foo/bar.py`` at the top of a module, a docstring
mentioning ``utils/foo/bar.py``, or a docs entry linking
``utils/foo/bar.py`` from inside ``utils/foo/bar.py`` itself all silently
desync from reality after the next ``git mv``.
The new lint walks every project file, computes its POSIX-style relative
path from PROJECT_ROOT, and reports any line whose text contains that
path as a substring. Files at the repo root (no ``/`` in their relative
path) and setuptools-generated ``*.egg-info/`` artefacts are exempt.
Per-line opt-out via ``# nocheck: self-path-reference`` on the offending
line, registered in the suppression catalog.
Existing offenders cleaned up:
- 72 redundant ``# <self-path>`` header lines removed across roles,
cli, plugins, scripts, tests, and utils.
- 4 prometheus templates that told consumers to "update
<self-template-path>" rewritten to drop the redundant self-reference.
- 8 docstring/comment self-references in cli, plugins, tests, utils,
and the dashboard oidc.js.j2 header rewritten to describe the layout
without naming the file's own path.
- 17 legitimate usage examples (shell scripts, test data lists, one
template self-include doc-block) marked with ``nocheck:
self-path-reference``.
- ``container.sh`` heredoc usage strings switched to ``${0}`` so the
marker stays out of the user-visible help output.
- ``healthcheck/http.yml.j2`` doc-block rewritten to prose because
``{# ... #}`` Jinja comments cannot host an inner ``{# nocheck #}``
(the inner ``#}`` closes the outer comment).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Follow-up to d002796a5. The formula `infinito_nexus_${INFINITO_DISTRO}` is
now defined in exactly one place — `scripts/meta/env/defaults.sh:18`,
exported outside the load-once guard so it tracks INFINITO_DISTRO across
matrix iterations (caller re-sources defaults.sh after distro changes).
Every other site reads INFINITO_CONTAINER strictly from env; nothing
re-derives the formula, no lazy/colon-dash fallbacks, no per-call defaults.
Production code aligned:
- cli/deploy/development/common.py: add resolve_container() (strict env
reader, raises SystemExit on unset). make_compose() calls it as an
early-fail guard so a missing defaults.sh source surfaces here instead
of as a confusing compose.yml interpolation error later.
- cli/deploy/development/deploy.py: stop re-deriving from compose.distro;
use resolve_container().
- compose.yml: container_name reads ${INFINITO_CONTAINER:?...} strictly,
so callers that bypass defaults.sh fail fast with a clear hint.
- scripts/meta/resolve/image/local.sh: drop ${INFINITO_DISTRO:-debian}
fallback; require INFINITO_DISTRO via :? error.
- scripts/tests/deploy/ci/dedicated.sh: drop local _container fallback.
- scripts/tests/deploy/local/deploy/fresh-kept-app.sh: drop redundant
${INFINITO_DISTRO:-debian} reassignment after sourcing env/all.sh
(defaults.sh already defaults the value).
- scripts/tests/deploy/local/deploy/fresh-purged-app.sh: drop
target_container fallback; INFINITO_CONTAINER is already in env.
- scripts/tests/deploy/local/exec/container.sh: drop the lazy
${INFINITO_CONTAINER:=infinito_nexus_...} default; defaults.sh source
in env/all.sh already guarantees the value.
- scripts/tests/dns.sh: source defaults.sh so callers only need to set
INFINITO_DISTRO (the implicit dependency was previously a footgun).
- scripts/system/tls/trust/{wsl2,linux}.sh: same — source defaults.sh,
drop the ${INFINITO_CONTAINER:-infinito_nexus_debian} fallback in
linux.sh.
- .github/workflows/test-dns.yml: drop redundant
INFINITO_CONTAINER: infinito_nexus_${{ matrix.distro }} from per-step
env blocks (3 sites). The env now flows from INFINITO_DISTRO via the
defaults.sh sourced inside the scripts.
- tests/unit/cli/deploy/development/test_matrix_deploy.py: replace the
module-level os.environ.setdefault('INFINITO_CONTAINER', 'infinito_nexus_arch')
shim — which itself encoded the formula — with a module-level patch of
resolve_container that returns an opaque test-fixture string. Drop the
now-unused distro="arch" field from the _args() Namespace fixture
(deploy.handler stopped consuming it after the --distro arg removal).
Documentation aligned:
- docs/contributing/environment/variables.md: rewrite the INFINITO_CONTAINER
row to spell out the SPOT contract — set automatically by defaults.sh,
never re-derived elsewhere, callers re-source defaults.sh after
changing INFINITO_DISTRO mid-process.
- docs/contributing/artefact/files/compose.yml.md: replace the
INFINITO_DISTRO row (which described the now-removed
`infinito_nexus_${INFINITO_DISTRO:-debian}` interpolation) with an
INFINITO_CONTAINER row noting the strict ${INFINITO_CONTAINER:?...} read.
Verified:
- Formula derivation: 1 production hit (the SPOT in defaults.sh:18).
- INFINITO_CONTAINER fallback patterns (:-/:=): 0.
- --distro CLI arg refs: 0 (one comment explaining the removal).
- make test green: 1553 unit + 168 integration tests, no skipped suites.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move flow/security/ghcr.md to tools/ghcr/authentication.md
- Move flow/security/mirror-cleanup.md to tools/ghcr/cleanup.md
- Move flow/security/branch.md to tools/github/branch.md
- Move flow/security/repository.md to tools/github/repository.md
- Move code/frameworks/ansible.md to tools/ansible.md
- Merge code/frameworks/Makefile.md into tools/make.md and extract file rules to artefact/files/makefile.md
- Rename tools/makefile.md to tools/make.md
- Add .github/workflows/images-mirror-cleanup.yml for manual GHCR cleanup
- Apply documentation.md standards: emojis on headlines, no em dashes, filename link text
- Fix all cross-references broken by directory restructuring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- deploy.py: use find_provider_roles() to map service names (e.g. 'matomo')
to provider app IDs (e.g. 'web-app-matomo') before filtering deploy_ids;
forward SERVICES_DISABLED into the container via extra_env
- container.sh: rename INSPECT_CMD to CMD for consistency; fix indentation
- Makefile: expose CMD variable on exec target for non-interactive use
- environment.sh: source scripts/meta/env/all.sh for INVENTORY_DIR; add
inventory verification after SERVICES_DISABLED deploy using make exec
- variables.md: document CMD variable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>