Changelog

All notable changes to Soleur.

v3.248.7 — 2026-08-11

Infra test harness

  • run-registered-suites.sh captures per-suite output and prints a bounded, marker-anchored excerpt on RED with rc, elapsed and start offset.
  • Closes a false green: PASS + RED must equal the derived suite count; vanished suites are named UNACCOUNTED and their output dumped.
  • Log dirs are reaped from the EXIT trap plus an age-reap of older siblings (ADR-133's reaper scopes to /tmp; this runner uses /var/tmp).
  • New SOLEUR_INFRA_DIR / INFRA_ORPHAN_LIST test seams so fixtures never touch the live tree.
  • credential-persist-home-guard.test.sh diffs against a frozen snapshot instead of the live source.

CI

  • main-health-monitor.yml filters the diagnostic sentinel out of the public issue body, widens its anchor to name vanished suites, points the operator at the run log, and widens the redaction set.
  • deploy-script-tests timeout re-derived 12 → 14 min (suite 3s → 67s).

Docs

  • ADR-133 records two departures: this instrument is not observe-only (186 files/run), making it a confound for the very capacity hypothesis it measures; and the ships-ahead ordering was departed from while honouring the property that rule protects.

v3.248.6 — 2026-08-10

Plugin

  • plan: new Phase 0.7 writes a skeleton plan file before the Phase 1 research fan-out; Phase 1.7 persists ## Research Insights in a single Edit; an interrupted run is continued in place rather than duplicated or overwritten.
  • plan: filename derivation moves out of Step 2 into Phase 0.7 (one derivation site, before research). Save Tasks now stages the exact plan path with a :? guard instead of the plans/ directory.
  • one-shot: plan-artifact recovery selects by frontmatter branch: (bounded, non-recursive, plans/archive/ excluded by construction) and branches on a single content predicate. Recovery runs at most once, then files an action-required issue.
  • plan-issue-templates.md: documents the two-stage frontmatter lifecycle and drops the lane: pre-seeding that contradicted plan's own rule.
  • Corrects a stale skill-description budget across brainstorm, plan, review, skill-creator, AGENTS.rules.md (injected into every session) and plugins/soleur/AGENTS.md: all asserted 1800 against a real cap of 2400. Each now names SKILL_DESCRIPTION_WORD_BUDGET rather than a literal. Also restores the correct ~2,500 agent-description figure that the first pass wrongly deleted.
  • ADR-175 records the decision, including why the cursor was rejected.

v3.248.5 — 2026-08-10

Plugin

  • preflight Check 10 now executes probes inside a bubblewrap sandbox with the repository read-only and no credential stores bound; it fails closed to SKIP-NOSANDBOX rather than ever running a probe unsandboxed.
  • The credentialed-CLI denylist is replaced by a 10-verb deny-by-default allowlist, extracted to plugins/soleur/skills/preflight/scripts/probe-verb-gate.sh so a parity harness can execute the runtime of record instead of scraping prose.
  • New credentials_required plan field grants a declared-credentialed probe a SKIP-DECLARED terminal with an inverted advisory, instead of a misleading FAIL.
  • env -i is now documented and pinned as load-bearing. bwrap does not scrub the environment, and DOPPLER_TOKEN / GH_TOKEN / ANTHROPIC_API_KEY live there only, with no on-disk store to unmount — so the sandbox's file-removal reasoning never reached them.
  • Anti-vacuity gate for the Check 10 suites (preflight-check10-suite-integrity.test.sh): named-test manifest, runtime skip/todo/fail measurement, a test/it/describe rebinding guard, and absolute floors including one on the gate's own dispatch.
  • ADR-173 records the decision; its evaluation order and Layer 1 scope are reconciled with the CTO ruling that removed the arg and path rules.

v3.248.4 — 2026-08-10

  • fix(registry): sign the bootstrap image so D10 A2 can pass, and stop promising a reviewer gate that does not exist

v3.248.3 — 2026-08-10

Plugin

  • worktree-manager.sh: added _safe_worktree_name (shared branch→directory derivation) and _sanitize_marker_field (extracted from the failure summary that already carried the rule); routed create_worktree, create_for_feature, switch_worktree, copy_env_to_worktree and cleanup_merged_worktrees through them.
  • Orphan reaper: descendant guard + filesystem backstop + fail-closed on an empty registry parse.
  • New SOLEUR_WORKTREE_SLUG_COLLISION marker; SOLEUR_WORKTREE_LEASE_ACQUIRE_FAILED now splits reason=name-not-keyable from rc-nonzero and reports key= rather than branch= (every caller passes the slug, so the old field named a ref that does not exist).
  • git-worktree/SKILL.md: Sharp Edges entry + a migration runbook for already-nested worktrees.
  • test-helpers.sh: print_results takes an optional anti-vacuity floor. Neutering assert_eq previously printed Passed: 0 / ALL TESTS PASSED and exited 0.
  • review/SKILL.md: one Sharp Edges entry on verification scoping.
  • ADR-099: one idiom bullet — a refname is not a path component, and the lease key is the resolved directory basename.

Web platform

  • git-lock-marker-telemetry.ts: registered both new markers in MARKER_RE, mirrored-not-paged (the skip and the refusal are the safe outcomes).

v3.248.2 — 2026-08-10

  • fix(kb): index only spec.md and tasks.md inside a spec directory

v3.248.1 — 2026-08-10

  • Fixed: a bare repo stored in a .git subdirectory had ensure_bare_config skip itself entirely, so extensions.worktreeConfig was never removed and every linked worktree reported as bare — breaking draft-pr and every other working-tree subcommand.
  • Fixed: atomic_git_config now treats --unset-all idempotently; without it the new call would have failed worktree creation on every already-healthy repo.
  • Added: create-time core.bare = false seed per worktree, plus a detection-time self-heal with a one-worktree blast radius.
  • Added: SOLEUR_GIT_BARE_POISON / SOLEUR_GIT_BARE_SELFHEAL telemetry, paging only on an unrecoverable heal.
  • Docs: ADR-173 records the polarity and its git-version scope; ADR-099 row 3 now names the root's .git directory and states that [[ -d <root>/.git ]] cannot discriminate it from a normal clone.

v3.248.0 — 2026-08-10

Tooling

  • Add two write-time CI gates over docs/legal/** and its Eleventy mirror: scope-block referent agreement, and a canonical↔mirror drift ratchet.
  • Extract the legal-corpus normaliser into scripts/lib/legal-normalise.sh (one definition site, two consumers) and the base resolver into scripts/lib/legal-base-ref.sh.
  • Register all four suites in scripts/test-all.sh; extend lint-orphan-test-suites.sh REQUIRED_RUNNERS so the live gate lines cannot be silently dropped.
  • Document the gates in legal-generate, legal-audit and the clo agent — the surfaces an editor of that corpus actually opens.

v3.247.6 — 2026-08-10

Restore engine (scripts/registry-restore-from-ghcr.sh)

  • Verification 2 verifies per child, not per whole-ref. Platform children keep crane validate --remote; attestation children route to a new verify_blobs_of() that fetches the config blob and every layer blob to /dev/null.
  • The sink index is read by digest, not by tag. crane manifest <tag> does not verify returned bytes (go-containerregistry: "Do nothing for tags; I give up"), so reading by tag dropped the index's only byte-integrity check and re-resolved the tag, leaving the verified children possibly not the ones verification 1 proved parity for.
  • Four-way manifest classification (index / manifest / malformed / unparseable). A .manifests field present but not an array is neither; the old two-way test folded it into the plain-manifest branch and handed a malformed index straight back to the whole-ref validate this change exists to stop calling.
  • A nested-index child fails closed rather than recursing into crane validate — that is #7378 one level down.
  • Child-count equality (n_children == n_declared), not > 0. The old guard passed when one child of five was verified.
  • A platform-child floor: an index whose only child is an attestation has no image any host could pull and must not read as "restored".
  • jq errors are no longer swallowed by || true. .manifests[] streams, so a shape fault at element k emits 1..k-1 then exits 5, and the truncated list passed every downstream guard.
  • The cosign signature payload is now blob-verified too. Verification 3 proved the signature manifest resolves via crane digest — a HEAD. zot gc+dedupe can evict the payload blob while the manifest survives, and that blob is exactly what ci-deploy.sh fetches to run cosign verify, so A2 could go green over a signature no host could verify.
  • Named classify() cases for gzip: invalid header (LAYERFORMAT) and error verifying sha256 checksum (CONTENTMISMATCH), both mapped to the runbook's exit-4 row rather than the unclassified exit 6.
  • crane_capture pins </dev/null so a future crane that reads stdin cannot hang the gate.

Tests

  • tests/scripts/test-registry-restore-from-ghcr.sh: 43 → 71 assertions, with a MIN_ASSERTIONS=71 floor so deleting a block is loud. New fixture helpers cover single manifests, OCI indexes (with a selectable attestation signal — annotation only, architecture only, or both), attestation children, cosign signatures and raw malformed shapes. Added a proof that the positive control's fixture removal actually lands, after an earlier version of that control passed against the pre-fix engine.
  • tests/scripts/test-registry-gate-mutation-battery.sh: floor 45 → 53. Eight rows (E24–E31) cover both attestation-detection disjuncts separately, the child-count equality, the platform floor, the nested-index guard, the digest sentinel, blob presence, and the signature blob verification. E22 promoted from expect_survive to mutate.

Docs

  • registry-luks-recut-6929.md: records the first live execution of the throwaway-zot rehearsal — one of four surfaces ADR-169 flagged as never-executed — corrects the cold/warm inventory table (5 of 6 were warm, not cold), and extends the exit-4 row. Also corrects "never touches" to "never writes to": the engine reads GHCR on every entry.
  • ADR-169: amendment recording that A2's blob-completeness obligation is per child, the rejected alternative (uniform blob-presence for every child, which would drop tar-structure walking, diffID/rootfs consistency and manifest/config self-consistency on the children hosts actually pull), and two narrowings that were implicit — the architecture: unknown signal is an assumption rather than a measured invariant, and the platform floor asserts existence, not completeness.
  • A learning file, and one bounded bullet routed into work/SKILL.md's RED-verification gate: a disjunction needs one fixture per disjunct alone, and when the operands come from @tsv, check the parse before the logic.

v3.247.5 — 2026-08-10

  • Fixed: main-health-monitor now reports a failing main at all — a timeout (cancelled) is treated as a failure, and the suite's real exit code is no longer discarded by | tee, which had let a red suite report success and auto-close human-filed trackers.
  • Fixed: the monitor now covers the apps/web-platform/infra/ suites, which its diff-based gate had excluded permanently on a clean main checkout, and runs them sequentially to avoid a known parallel-runner flake.
  • Fixed: the monitor's runner now installs the toolchain its own suites require (gitleaks, likec4, terraform, cloud-init, node 22) with an assertion step — previously four suites aborted or silently self-skipped as PASS.
  • Fixed: a filed issue now names the failing suite, excerpts only the step that failed, redacts secrets before publication, and its title and body name only a cause the job actually measured.
  • Fixed: the monitor only auto-closes trackers it filed itself, so it can no longer close a human-filed issue about a failure class it never ran.
  • Added: a Sentry cron monitor for the executor, so a dropped dispatch, disabled workflow, or unavailable runner pages on a missed check-in instead of producing no run and no signal.
  • Added: a committed guard suite pinning the workflow's conditions, ceilings and markers, mutation-proven.

v3.247.4 — 2026-08-10

Plugin

  • Corrected three sites claiming cleanup-merged archives spec directories (merge-pr/SKILL.md, worktree-manager.sh --help, and compound's consolidation note)
  • compound now names archive-kb.sh's slug-glob and feat--prefix discovery gaps

v3.247.3 — 2026-08-10

  • feat(registry): a read-only zot disk-inventory lever — measure what is actually consuming the 59 GB

v3.247.2 — 2026-08-10

Legal corpus

  • Adds §2.1c to the Data Protection Disclosure defining operator-assisted processing and Jikigai-purpose access, with a four-row role table and an explicit note that the configurations are not mutually exclusive
  • Adds §3.14 to the GDPR Policy: the Article 6(1)(f) basis with its balancing summary, the recorded safeguards including the negative one (local clones sit on a workstation that is not full-disk encrypted), the Article 14(5)(b) posture with its weakest point named, and an explicit Article 21(1) right to object
  • Adds a Privacy Policy §8.1 carve-out for third parties who never gave Jikigai anything — people named in a repository, and commit authors — with the erasure limitation stated per limb
  • Binds the existing sub-processor denial to plugin-local scope and discloses the AI provider as Jikigai's sub-processor for operator-assisted sessions
  • Sweeps retention in the Privacy Policy and GDPR Policy: content sent under Jikigai credentials is held for a period the user does not set and Jikigai cannot shorten
  • Opens closed enumerations that a third relationship type made stale
  • Instrument commitments are stated in the forward tense at all four sites — one such session has occurred and it ran without an instrument, so a present-tense claim of standing practice would be false as to every instance
  • Qualifies the annex's transfer-mechanism clause with the open account-tier condition

Tooling

  • Routes legal-posture decisions to the CLO agent rather than the operator, as a sibling of the existing architectural-fork rule
  • Requires positive verification that binding items landed — a prohibition sweep is structurally incapable of detecting an omission
  • Adds a fourth disposition to review triage: route to the domain agent for a binding ruling

v3.247.1 — 2026-08-10

Plugin

  • create, create re-entry, feature re-entry, and switch now acquire a session lease; acquisition moved ahead of git worktree add so the worktree is never unleased
  • Lease acquisition extracted to _acquire_worktree_lease, with trap-gating, artifact verification, and a telemetry marker
  • New SOLEUR_WORKTREE_LEASE_ACQUIRE_FAILED sentinel, mirrored and paged
  • acquire_lease no longer reports success on a failed write

web-v0.249.6 — 2026-08-10

Plugin

  • plan: new Phase 0.7 writes a skeleton plan file before the Phase 1 research fan-out; Phase 1.7 persists ## Research Insights in a single Edit; an interrupted run is continued in place rather than duplicated or overwritten.
  • plan: filename derivation moves out of Step 2 into Phase 0.7 (one derivation site, before research). Save Tasks now stages the exact plan path with a :? guard instead of the plans/ directory.
  • one-shot: plan-artifact recovery selects by frontmatter branch: (bounded, non-recursive, plans/archive/ excluded by construction) and branches on a single content predicate. Recovery runs at most once, then files an action-required issue.
  • plan-issue-templates.md: documents the two-stage frontmatter lifecycle and drops the lane: pre-seeding that contradicted plan's own rule.
  • Corrects a stale skill-description budget across brainstorm, plan, review, skill-creator, AGENTS.rules.md (injected into every session) and plugins/soleur/AGENTS.md: all asserted 1800 against a real cap of 2400. Each now names SKILL_DESCRIPTION_WORD_BUDGET rather than a literal. Also restores the correct ~2,500 agent-description figure that the first pass wrongly deleted.
  • ADR-175 records the decision, including why the cursor was rejected.

web-v0.249.5 — 2026-08-10

CI / release pipeline

  • zot-mirror failure messages now branch on a measured token verdict instead of naming an unmeasured cause; the failing job reads and prints the registry host's restart series
  • the zot restart-loop alarm can now file its issue on FIRE, and its Sentry check-in requires a verdict rather than an exit code alone
  • the private-NIC advisory dates its reboot claim instead of re-emitting an old convergence as news
  • new lint-diagnosis-claims gate blocks operator-facing CI messages that name an unmeasured cause
  • new alarm-issue-filing-guard gate blocks issue-filing steps that cannot report the verdict they exist for
  • the ship Incident-PIR gate now recognises a delivery outage (releases blocked, production pinned versions behind) as an incident, not just a user-facing one

Docs

  • post-incident report for the blockage (2026-08-03-zot-mirror-blocked-releases-…-postmortem.md), status unresolved but ended — the mirror recovered unattributed and #7247 is still open
  • ADR-166 + principles-register AP-021 (diagnostic honesty)
  • zot-registry-revert.md runbook: verdict-first triage, corrected token remedy, three-cause bad-handshake framing

v3.247.0 — 2026-08-09

  • /soleur:sync c4 — new area generating a LikeC4 model from component docs, with the full artifact set the viewer needs (generated-components.c4, model.likec4.json, c4-model.md). Non-destructive: distinct composing file, GENERATED header, refuses to overwrite anything it did not write.
  • Component dependency contractdependencies: frontmatter added to the component template and to sync's Project Analysis, with markdown-link fallback for docs written before it.
  • domain-model-drift.sh init — bootstraps an absent register so the area works on a fresh repo.
  • domain-model in all dispatch — new non-interactive path (init → drift → append) for headless runs; the standalone invocation stays terminal.
  • /soleur:sync coverage summary — deterministic kb-coverage.md plus a SOLEUR_KB_SYNC_PRODUCERS marker on stdout and in the artifact.
  • Observability layer 7 (cli-stdout-artifact) — added to observability-coverage-reviewer, for code running on a customer's self-hosted CLI where no Soleur-side sink exists or should.
  • ADR-171 — KB composition manifest + the observability boundary, with claim 3a reconciling its consent argument against the #7342 controller/processor determination (see below).
  • scripts/lint-shell-capture-exit.py — new repo-level gate for the shell-capture-exit class (x=$(grep …) aborting under set -e; grep -c printing 0 and exiting 1 so || echo 0 yields "0\n0"). Sibling to lint-workflow-errexit-capture.py, not a widening of it. Registered in scripts/test-all.sh as scripts/lint-shell-capture-exit (unit, 25 assertions) and scripts/lint-shell-capture-exit-live (gate). Ships with a 216-entry baseline so it blocks NEW occurrences only.

v3.246.6 — 2026-08-09

Infrastructure

  • The registry-luks-recut D10 gate now derives the app domain from committed Terraform instead of a Doppler secret that does not exist, making the dispatch fireable.
  • D10 PREPARE is credential-free (DOPPLER_TOKEN_PRD removed).
  • The recut's restore leg derives its push host from the same source, ending a split-brain where gate and write-side resolved the base differently.

Tests

  • New derivation unit suite (34 rows) and a static workflow-wiring gate (22 rows), both registered in test-all.sh.

v3.246.5 — 2026-08-07

  • Fixed: worktree leases acquired through the documented CLI entry points were never honoured — acquire_lease records the PID of a process that exits immediately, so is_lease_active reported inactive and sweep_orphan_leases deleted the lease file. cleanup-merged consequently reaped live worktrees, deleting the local and remote branch and closing the PR. The lease window is now the authority; PID-liveness is advisory.
  • Fixed: worktree-manager.sh now fails closed when session-state.sh cannot be sourced (previously it reported every worktree as unleased, permitting reaps at the moment it could not measure whether one was in use), and restores sweep_orphan_leases to the stub set.
  • Tests: added a dead-acquirer scenario to lease-protects-active.test.sh (the existing fixture only ever exercised a live PID, a shape production never has), plus T9/T10/T11 in session-state.test.sh. T4's assertion is inverted in place with rationale.

v3.246.4 — 2026-08-07

Legal / compliance

  • Controller/processor determination for operator-assisted alpha-tester runs (dual finding: processor + controller).
  • New Art. 30(2) processor register; PA-34 and PA-35 added to the Art. 30(1) register.
  • Art. 30 §0 membership predicate re-keyed from a host-based surface list to purpose / credential / infrastructure.
  • Legitimate Interest Assessment for repository observation, including its own recommendation against the configuration chosen.
  • Art. 28(3) processing annex drafted (unexecuted, counsel review pending).
  • Fifth DSAR requester class added to the statutory response catalog.
  • Anthropic fired re-evaluation trigger actioned; 30-day retention consequence recorded.

Plugin

  • Terms and Conditions, Privacy Policy, AUP and Data Protection Disclosure surfaced in the plugin README (previously only the BSL licence, while the T&Cs bind on installation).
  • review/SKILL.md: convergent defect-class entry for compliance-artifact claim verification.
  • AGENTS.rules.md: new hard rule hr-third-party-content-grep-on-undertaking.

v3.246.3 — 2026-08-06

  • fix(pipeline): three measured fixes for the habits that made #7325 expensive

v3.246.2 — 2026-08-06

  • chore(infra): repin the registry host to cpx22 — for stock volatility, not unorderability

v3.246.1 — 2026-08-06

CI lint (ADR-166)

  • apps/web-platform/infra/ is now scanned for unmeasured causal claims (+71 walked files, 0 new hits).
  • CLAIM gains a closed adjective enumeration for the "X is the fix" shape. One intervening word previously defeated it, so the hedged is the likely cause was caught while the confident is the root cause was not. The open slot (?:[a-z]+ )? was measured at +2 hits and rejected; the closed form costs +0.
  • A missing DIRS entry is now a hard error rather than a quietly smaller walk.
  • /test/ matched nothing (the tree uses tests/, test-fixtures/, fixtures/) and is now /tests?/, with a fixture making it load-bearing. .bench.sh excluded; .terraform/ pruned from the walk.
  • The ratchet windows now restore the committed baseline on interrupt.

Documentation

  • ADR-166 and the 2026-08-03 zot-mirror post-mortem both enumerated the old three-directory scope and were left false by the widening. Corrected — the sweep's unit is the claim, not the file.
  • Two route-to-definition bullets: inherited framing (compound) and cardinality-vs-identity assertions (review).

v3.246.0 — 2026-08-06

  • fix(inngest): inngest-redis crash-loops on a stale credential path, and its stderr reached no telemetry

v3.245.5 — 2026-08-06

Plugin

  • one-shot: Step 0a.5 now re-probes the plan's frontmatter target after the planning phase returns, so a work target discovered during planning is collision-checked before /work begins.

Knowledge base

  • Recut runbook: the user_data precondition now quotes a command and a verdict shape instead of a byte count, fixes a ≥ 0> 0 boundary, documents the SKIP-exits-0 trap, and points an over-cap verdict at the gate's own CAUSE: line.
  • New learning: The collision gate cleared the issues I passed it, not the one I worked on.

v3.245.4 — 2026-08-06

  • fix(ci): the prod version-drift alerter went dark on exactly the two verdicts it exists to raise

v3.245.3 — 2026-08-06

Infrastructure

  • registry-userdata-budget.sh now extracts registry_rationale_strip from zot-registry.tf (never restating it) and applies it before base64gzip, and asserts the strip is applied at user_data — not merely declared. Unwiring the replace( wrapper previously left the gate reporting 9,408 B and exit 0 on a tree storing 36,404 B; ADR-152 had already recorded that exact fail-open with the rule "Assert on the RENDER EXPRESSION, not on a string in a file."
  • Adds a plausibility floor (4,000 B) and a #cloud-config-survives assertion. Every numeric arm was previously a ceiling, so an over-broad strip reported maximum headroom for an empty payload that boots a dark host.
  • Measures bytes, not graphemes. length() counts grapheme clusters and the cap is a byte cap; the template carries 152 non-ASCII characters, 23 surviving the strip.
  • Fails closed in CI when terraform is absent — the last remaining measure-nothing-report-green path.
  • The over-cap message now discriminates a broken regex from real payload growth.
  • New registry-userdata-budget.test.sh: 16 checks, mutation-proven against a green control.

CI

  • continue-on-error: true removed from the registry-userdata-budget job — the check now fails the run for real.
  • Infra Validation also runs on pushes to main for the infra content globs, with detect-changes diffing github.event.before (not HEAD^1, which examines only the tip commit and made a multi-commit or admin push report a green run that validated nothing).
  • New notify-main-failure job — the push-on-main trigger otherwise had no consumer, reproducing this PR's own defect one layer up.
  • deploy-script-tests timeout 8 → 12 min, re-derived as its comment mandates: measured 384–501 s against a 480 s ceiling, i.e. already cancelling 14% of runs.

Records corrected

  • ADR-096 — the byte cap is retracted as a live apply blocker and as constraint 2 of the rollback procedure, which is read mid-incident.
  • ADR-152 — the byte-exact-measurement gap it declared open is now closed.
  • Corrected #7302 (promotion is a cost/benefit call, not blocked on #6480) and commented on #7287, whose checklist carried the same phantom blocker.

v3.245.2 — 2026-08-05

Registry recut authorization

  • D10 gate rewritten around a rehearsed restore as the pass condition (A0–A4; there is deliberately no A5).
  • New scripts/registry-restore-from-ghcr.sh restore engine with intrinsic blob-completeness verification and a fully enumerated exit-code contract.
  • The rehearsal moved into a needs:-preceding registry_pull_path_gate job so a timeout there destroys nothing; the recut's derived 30-minute mutex budget again starts at the apply.
  • A chained registry_store_restore job re-materialises the pinned set post-destroy.
  • ADR-169 added; ADR-096 amended in place (clause (g) stays open).

Testing

  • New committed mutation battery (45 dispatched) registered in the full-suite runner.
  • Gate suite 46 → 60 rows, engine suite 34 → 43.
  • terraform-target-parity's step-order safety property fixed (it had been 2/103 RED for the life of the branch, unnoticed because the previous exit-gate run was void) and strengthened to span both jobs.

v3.245.1 — 2026-08-05

  • fix(infra): grant the config handler's daemon-reload so delivery actually activates (#7220)

v3.245.0 — 2026-08-05

Infrastructure

  • zot registry image pinned to v2.1.20 per arch, with an explicit version tag
  • new zot-image-staleness.test.sh — 15 offline assertions, exit 0/10/2, anti-vacuity floor + positive control
  • new zot-image-staleness-mutation.test.sh — 18 mutations, expected-rc + marker asserted, registered in CI
  • new registry-userdata-budget.sh — offline templatefile()/base64gzip() byte measurement, no credentials
  • new zot-image.provenance.md — config-compat analysis, non-adoption decisions, previous-known-good pin, bump procedure
  • zot_image_digest added to the SOLEUR_ZOT_DISK heartbeat via the existing docker inspect

CI

  • rule-audit.yml: upstream release poll + digest↔repository probe, one idempotent action-required issue
  • infra-validation.yml: staleness gate, mutation battery, and a warn-only byte-budget job
  • renovate.json5 removed

Docs

  • ADR-096 "Pin freshness" amendment; projectZot added to the C4 model with its trust boundary
  • zotRegistry corrected from cx33/7168m to cx23/derived 3072m

View all releases on GitHub →

Frequently Asked Questions

How often is Soleur updated?

Soleur ships continuously — updates are released when ready and tagged with semantic versioning. There is no fixed release schedule. Changes range from new agents and skills to bug fixes and documentation improvements.

How do I upgrade Soleur?

Run claude plugin install soleur to get the latest version. The plugin manager handles the update automatically. Check the changelog or GitHub releases page for details on what changed.

Does Soleur use semantic versioning?

Yes. Soleur follows semantic versioning — major versions for breaking changes, minor versions for new agents or skills, and patch versions for bug fixes and documentation updates. Version labels are set during PR review and applied automatically at merge.

Stay in the loop

Monthly updates about Soleur — new agents, skills, and what we're building next.