Swap size was free(/)-25, which took ~99 GB on the 145 GB root fs.
Remaining ~25 GB then ran out mid-deploy during Playwright image
pulls (ENOSPC). Replace with a fixed 16 GB cap and use mountpoint
to detect a real /mnt partition instead of [ -d /mnt ], which
matched the empty placeholder dir on single-partition runners.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Surfaces df, failed units, and hlth-disc-space status/journal from
inside the infinito container so failure-time dumps reflect the same
filesystem view that the disk-space health check evaluates, not just
the host.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extracts disk/memory/docker/swap dump into a reusable helper,
calls it pre/post swap resize, and runs it on deploy failure
across all four deploy workflows. Also adds SKIP_SWAP=1
short-circuit for A/B probing swap-related regressions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Introduce scripts/github/enlarge_swap.sh that consumes all remaining
space on / minus a 25 GB buffer (Docker layers, checkout, runtime
state), falling back to /mnt when / is too small. Replaces the
default ~4 GB runner swap so transient memory spikes (e.g. peertube
plugin install, issue #162) don't trip the host OOM-killer on the
16 GB GitHub-hosted runner.
Wire the script into all four deploy test workflows (local, universal,
server, workstation) and flip free-disk-space to the aggressive config
(tool-cache, large-packages, docker-images, swap-storage all true):
the deploy actually runs inside the infinito container, so host-side
toolchains, language runtimes, and the default Docker layer cache are
dead weight. Update the workflow SPOT doc accordingly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The --exec 'git commit --amend --allow-empty --no-edit -S' pattern
multiplied identical-tree empty commits during a rebase-merges run
(observed: 3 upstream empties became 16 locally). git rebase -S signs
every rewritten commit natively, without the amend loop, while still
preserving merges via --rebase-merges.
The re-sign rebase failed on empty commits pulled in from upstream
because git refused the --amend. Adding --allow-empty keeps those
commits in place while still GPG-signing them.
The old derivation read @playwright/test out of
roles/test-e2e-playwright/files/package.json and assembled the tag
as `v{version}-{distro}`. That package.json no longer exists — the
version+distro tag now lives verbatim in defaults/main.yml under
images.playwright.version, so read it from the single source of
truth instead of rebuilding a broken tag from a missing file. The
TEST_E2E_PLAYWRIGHT_IMAGE_DISTRO fallback is no longer referenced
once the distro suffix is baked into the upstream version string.
Route pushes through scripts/git/sign-push.sh so the operator's GPG key
stays outside the sandbox. Script signs only @{u}..HEAD (or merge-base
with origin/main|master on first push), skips re-signing when all
commits already carry a good signature, and uses --force-with-lease on
rewritten history. settings.json denies git push*, git send-pack*, and
make sign-push* so the agent cannot trigger a push path directly.
CLAUDE.md instructs the agent to hand off to the operator instead.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous symlink approach left .claude/skills as a real empty dir in
some setups, which collides with the agent sandbox (denyWithinAllow on
.claude/skills expects a file path, not a directory) and breaks every
Bash invocation. Copy the installed skills tree into .claude/skills so
both locations are real, independent copies — no symlink involved.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Treat chore/** branches like feature/fix/etc. for CI: trigger the
push pipeline on chore/** pushes and accept chore as a valid PR
branch prefix in full scope. This unblocks the chore/update-* PRs
that update.yml creates automatically, which previously failed
branch-prefix validation and never triggered the push pipeline.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add repository variable CI_RUN_ON_MAIN that gates whether pushes to
main trigger CI. When unset (default), pushes to main skip CI;
set to 'true' to enable. Pushes to other branches are unaffected.
Reorganize GitHub Actions docs into a dedicated tools/github/actions/
directory and consolidate every CI repository variable in a single
SPOT (configuration.md). Move actions.md to actions/workflows.md and
branch/configuration.md to actions/configuration.md, then update
every cross-reference. Trim README files to scope-only per
docs/contributing/artefact/files/docs/readme_md.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move `pacman-key --init` + `--populate` ahead of the first `pacman -Syu`
call in `build_and_install_arch`. The previous guard
`pacman-key --list-sigs` always returned 0 on a fresh Manjaro/Arch image,
so the keyring init never ran and the upgrade of `archlinux-keyring`
failed with `==> ERROR: There is no secret key available to sign with.`,
breaking the manjarolinux/base test-environment matrix entry.
Refs: https://github.com/infinito-nexus/core/issues/167
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds scripts/install/sandbox.sh, a distro-aware installer for the OS-level
dependencies the Claude Code sandbox backend needs (bubblewrap, socat),
and exposes it through a new `make agent-install` target. Documents the
target in docs/contributing/tools/make.md, scripts/install/README.md, and
the Claude sandbox guide so contributors on a fresh host can bring up a
working sandbox without hand-installing distro packages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude Code discovers project skills under .claude/skills/, but
`skills experimental_install` writes to .agents/skills/. Add a
relative symlink so installed skills (caveman, compress, ...) are
picked up without extra copy step.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The rendered .env already contains the deploy-time CA trust values and the
spec uses ignoreHTTPSErrors, so duplicating the Ansible task's -e wiring
never adds anything in the inner-loop case.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds the documented inner-loop workflow for iterating role-local
Playwright specs against a live stack without a full redeploy, plus
the helper script that reuses the existing staging dir, rendered .env,
and container image defaults so no new TEST_E2E_PLAYWRIGHT_* override
mechanism is introduced.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reorders all documented and scripted `make` invocations from the
`VAR=value make target` shell-env prefix form to the make-native
`make target VAR=value` form. GNU Make auto-exports both command-line
and inherited shell-env variables to recipe shells, so the change is
purely about command-line shape: only the make-suffix form starts with
`make` and is therefore matched by the `Bash(make*)` permission entry
in .claude/settings.json, avoiding unnecessary approval prompts for
agent runs.
Adds an explicit CLAUDE.md rule with ✅/❌ examples and the underlying
reason (permission prefix match, not Makefile semantics).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds inventory consistency guard that fails fast when SERVICES_DISABLED
conflicts with an already-deployed inventory, and ensures the env var is
forwarded through the dedicated runner, development exec command, and
local test scripts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The self-exclusion check compared BASH_SOURCE[0] (relative path when
invoked as `bash ./scripts/…/00_orchestrator.sh`) against the glob-built
step paths (always absolute). The mismatch caused the orchestrator to
include itself in the loop, running a full inner pass of steps 01–10
before the outer loop repeated them — doubling the total runtime.
Fix: resolve SELF to an absolute path using SCRIPT_DIR so the comparison
is always path-equivalent regardless of invocation style.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Keep live registry lookups out of the default make test flow.
Add a dedicated external suite, workflow, and docs so the check stays opt-in but still gates code CI when enabled.
Add tests/lint/repository/test_markdown_links.py — a hard-fail lint
test that scans all git-tracked markdown files for broken relative and
repo-root-absolute links. Skips external URLs, anchor-only links, fenced
code blocks, and placeholder targets.
Apply documentation.md rules to all staged files: add emojis after
headlines in docs files, remove emojis from role README headings,
standardize Credits sections to the canonical format, remove empty
sections and orphaned sentences referring to missing documentation files,
fix raw URLs and incorrect link text across role READMEs and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move emojis after headline text (CONTRIBUTING.md, actions/, design/, tools/, tests/)
- Replace em dashes with colons, semicolons, or complete sentences throughout
- Add missing emojis to all headlines in exceptions.md, principles.md, services.md, shell.md, setup.md, pull-request.md, commit.md, act.md, docker.md, pr/README.md
- Update H1 titles to reflect renamed directories (actions/, design/)
- Fix broken relative links in workflow.md after directory moves
- Fix full-path link texts in services.md (style.css.md, javascript.js.md)
- Fix broken principles.md link to lint.md after testing/ → actions/testing/ move
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When --repo is passed to gh, the --head argument must include the owner
in owner:branch format so GitHub can resolve the head SHA correctly.
Without it the GraphQL API returns 'Head sha can't be blank'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
--force-with-lease requires a remote-tracking ref to exist locally. In a
fresh CI checkout the update branch has no tracking ref, so the push is
rejected as stale. The update branch is always owned by automation, so
--force is safe here.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without --repo, gh targets the wrong repository context when GH_TOKEN is
used in a workflow that runs outside the target repo. Infer the repo from
the git remote URL and pass it to gh pr list, gh pr edit, and gh pr create.
Co-Authored-By: Claude Sonnet 4.6 <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>
Replaces GHCR_PAT-based authentication with GITHUB_TOKEN across all
mirror and build workflows. Packages pushed from a public repository
with GITHUB_TOKEN are automatically linked to the repository and
inherit its public visibility — no publish step required.
Removes cli.mirror.publish (used a non-existent GitHub REST API
endpoint for changing package visibility), the associated unit tests,
and the GHCR_PAT debug helper. Cleans up all GHCR_PAT/GHCR_USERNAME
references and rewrites the GHCR authentication documentation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add scripts/install/skills/install.sh to restore skills from
skills-lock.json via npx skills experimental_install
- Add scripts/install/skills/update.sh to update all skills by
re-running skills add for each source in skills-lock.json
- Add make install-skills and make update-skills targets
- Add .github/workflows/update-skills.yml for daily automated updates
matching Dependabot schedule (00:00 UTC), opens PR on lock changes
- Add docs/agents/meta/caveman.md as SPOT for caveman mode, startup
notification, and token-budget tier progression
- Update AGENTS.md with RFC 2119-compliant skills installation check
- Update docs/agents/action/commit.md: replace ALWAYS with MUST
- Update pyproject.toml: respect-gitignore = true, exclude .agents
- Track skills-lock.json and add .agents to .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds scripts/lint/autoformat.sh that checks tool availability before
running ruff, shfmt, and shellcheck autofixes. Updates Makefile with
the new autoformat target, documents it in makefile.md, and adds a
commit.md rule requiring autoformat to be run before every commit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Image names now follow {owner}/{repository}/mirror/{registry}/{name}
instead of {owner}/mirror/{registry}/{name}.
- GHCRProvider: add `repository` param + `add_args()`/`from_args()` classmethods
as SPOT for CLI argument registration and provider construction
- sync, resolver: use GHCRProvider.add_args() / from_args() (no duplication)
- Workflows: resolve repository name via scripts/meta/resolve/repository/name.sh
and pass --ghcr-repository to sync and publish
- mirrors.sh: require and forward GHCR_REPOSITORY env var
- deploy/development/mirrors.py: derive repository from GITHUB_REPOSITORY
- Tests: update expected paths, argv and env fixtures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move iter_role_images + all helpers + ImageRef from cli/mirror/util.py and
cli/mirror/model.py into utils/docker/image_discovery.py; add source_file field
to ImageRef to distinguish config/main.yml vs vars/main.yml entries
- Delete cli/mirror/util.py; update all callers to import from utils.docker.image_discovery
- Move utils into subpackages: utils/docker/ (image_ref, paths_utils, hadolint) and
utils/roles/ (dependency_resolver, resource_validation); update all imports
- Reorganise tests into subpackages: tests/lint/docker/dockerfile/, tests/integration/docker/,
tests/unit/utils/docker/, tests/unit/utils/roles/; fix parents[N] offsets after relocation
- tests/lint/docker/test_image_versions.py now uses iter_role_images (same SPOT as mirror)
- Add vars/main.yml images.<name>.{image,version} support for non-application roles
(test-e2e-playwright, sys-ctl-hlth-csp); eliminate hardcoded duplicates in defaults/tasks
- Add web-app-matrix matrix-chatgpt-bot and web-app-mini-qr mini-qr entries in config/main.yml;
replace hardcoded image strings in vars/templates with lookup('config', ...) references
- Fix sync/__main__.py log line to use correct registry prefix for non-Docker-Hub images
- Update docs/contributing/code/role/dockerfile.md with image declaration rules and SPOT reference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add ensure_git_safe_directory helper to lib.sh that detects dubious
ownership warnings in mounted containers and adds safe.directory to
the global git config. Call it on lib load and before each step in
the orchestrator.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Opts out of the April 2026 default change that skips file coverage
computation on PRs by setting CODEQL_ACTION_FILE_COVERAGE_ON_PRS=true.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>