The header and the rule lists narrated the config instead of being an
exception, a parameter doc or a nocheck directive, and one of them was
wrong: it listed MD040 as kept on while the config disables it. No key
or value changes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The 16.0.0 entry pkgmgr wrote on top of CHANGELOG.md uses "-" bullets
while every older entry uses "*". MD004's default "consistent" style takes
the marker of the first list in a file, so lint-markdown reported 400
MD004 findings in CHANGELOG.md and the pre-push gate refused the release
push.
MD004 is now pinned to "dash", the marker pkgmgr and the changelog skill
write, and make autoformat (markdownlint-cli2 --fix) converted the lists
of the 72 files that still used "*". Only list markers changed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Two bots bumped the one baudolo version independently. The pip pin
updater rewrites the literal package_name pin in
roles/svc-bkp-volume-2-local/tasks/01_install.yml and opens a PR scoped
to roles/<entry>/, and dependabot bumps the same package in
pyproject.toml. Each PR alone splits the pins that
tests/lint/repository/dependencies/test_baudolo_pin.py holds equal; #995
merged such a split and turned main's test-lint red until #996, and the
next upstream release (7.1.2 is tagged) would repeat it.
The version lookup now takes an optional distribution name and returns
its exact == pin from [project.dependencies]. The install task asks it
for backup-docker-to-local, so pyproject.toml is the only place the
version lives, dependabot is the only bot that moves it, and the pip
updater no longer finds a literal to bump. The lint now forbids a
literal pin in the task and requires the lookup.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
compose/cache.shared.override.yml attaches every worktree stack's
infinito service to the primary's network (infinito-nexus-core_default,
172.30.0.0/24) without an ipv4_address. The default network declared
no ip_range, so Docker IPAM handed out the lowest free address and the
worktree stacks took 172.30.0.2, .3, .8, .9 and, whenever the primary
container was down, .10, the primary's INFINITO_IP4. The primary's
`make compose-up` then failed with "Address already in use", and with
it `make quality-high` on main.
The default network now declares ip_range: ${INFINITO_IP_RANGE}, the
upper half of INFINITO_SUBNET. Every static address of the stack (.1,
.4 to .6, .10, .53) sits in the lower half, so a container without a
static address can no longer take one.
INFINITO_IP_RANGE is derived from the final INFINITO_SUBNET after
custom.env is applied, because a worktree pins its subnet there and
`make dotenv-force` regenerates without it in the environment. Existing
worktrees therefore get their own slot's range without a new pin.
A lint checks that every static IP in default.env and every
172.30.${slot}.N pin in scripts/system/worktree/up.sh lies below the
pool.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The README merged with #323 lists svc-swarm-node as a 1:1 dependent, but
no role on main references svc-net-wireguard. make docs regenerates the
Cosmos block from the actual dependency graph and drops the edge.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A freshly built dev container installs ansible-lint unpinned (26.10.1,
yamllint 1.38.0), and its --fix pass in make autoformat now drops the
trailing blank line of meta/packages.yml and
roles/sys-svc-container/meta/packages.yml and adds the missing document
start to roles/svc-net-wireguard/files/test/compose.yml (from #323).
Parsed YAML is unchanged.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The pip pin updater moved roles/svc-bkp-volume-2-local/tasks/01_install.yml
to backup-docker-to-local==7.1.1 in #995 (ab76a5fd82) and left
pyproject.toml on 7.0.2. tests/lint/repository/dependencies/
test_baudolo_pin.py holds both pins equal, because utils/recovery/layout.py
spells baudolo's generation layout out as literals, so main fails
test-lint since that merge: "Lists differ: ['7.1.1'] != ['7.0.2']".
pyproject.toml follows the role to 7.1.1, which PyPI serves. Between
v7.0.2 and v7.1.1 upstream changes the rsync flags of backup and restore
to -aHAX and nothing in baudolo/generation.py or baudolo/restore/paths.py,
so the layout literals stay valid.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The swarm wait added for the search precheck reads the newest task of
the init service through job_state.sh, which takes the first line of
`container service ps`. That holds for a one-shot job with one task,
the contract the akaunting setup and keycloak import jobs meet by
creating their job with `container service create`.
Zammad's init is a stack service, so it took the topology default of
compose_replicas: one task per host in the web-app-zammad group. Only
the primary placement keeps the CI swarm at one host; an inventory
that puts several hosts into the group would start one zammad-init per
host, each migrating the same database, and the wait would pass on the
first task to complete. init now pins replicas: 1, like the scheduler.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
scripts/meta/resolve/diff/affected_roles.sh emits __ALL__ as soon as
one changed path outside roles/<role>/ is not a .md or .rst file. A
role fix that also adds its unit test under tests/unit/python/roles/
therefore deployed the whole matrix: PR #982 changed
roles/web-app-zammad/ plus
tests/unit/python/roles/web-app-zammad/files/test_search_allocation_precheck.py,
and its "Detect affected roles" job logged "Resolver output: __ALL__".
Paths under tests/ now join the .md/.rst skip-list. No role deploy
reads the top-level tests/ tree, and those suites run in their own
jobs whatever the whitelist says. A diff of only skipped paths keeps
falling back to __ALL__, as before. The same resolver feeds
effective_whitelist.sh, so the narrowing applies to every diff-driven
run.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
In swarm the role gated init only through "wait for Zammad init (seeds
+ pk-sequence reset)", which checks database state. On an existing
installation that state is already there, so a swarm deploy that
restarts init while Elasticsearch refuses shards passed: the init task
kept failing on the allocation precheck and nothing reported it.
A swarm-only task now runs sys-svc-compose's job_state.sh against the
init service after the seeds wait. It passes once the newest init task
is Complete. If the newest task stays Failed, it fails the deploy
after 60 retries 5 s apart. An init the stack deploy did not restart
is already Complete and passes at once. Compose needs no extra wait,
because railsserver depends on init with
service_completed_successfully.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
In swarm, docker stack deploy ignores depends_on, so the precheck
service and every init replica ran search_allocation_precheck.sh at the
same time. They shared one probe index: one invocation's PUT could fail
the shards_acknowledged check because another had created the index
first, and either one's cleanup could delete the other's probe. The
init service carries no replica override, so compose_replicas gives it
one task per host in the application group and the collision also
happens between init replicas.
A failing precheck task also never reached has_fatal_task in
stack_ready.sh: with restart_policy none it records a single error,
while has_fatal_task needs three. stack_ready.sh then kept answering
"not converged" until the handler ran out of retries. And a Running
init task counts as converged through running_current_spec, so the
swarm deploy never depended on init failing; the role's "wait for
Zammad init" task is what stops it.
The probe index now carries the container's hostname, which docker
sets to the container id, so concurrent invocations no longer share an
index. compose.yml.j2 renders the precheck service, and init's
service_completed_successfully dependency on it, only outside swarm.
Compose keeps its fast stop on a refusal; in swarm, init runs the same
check in front of zammad-init, a refusal leaves Zammad unseeded, the
wait for Zammad init fails the deploy, and the init service logs carry
the allocation explanation.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>