Skip to content

    Release 1.30.0

    News ·

    archied — Messaging Service extraction completed

    Telegram, email and webhook no longer run inside the daemon. They run in archie-messaging and reach the daemon through the Gateway’s ChatContract over gRPC; the daemon builds no channel and no gateway.Router (#899).

    • The operator surface is re-wired in the extracted service: /update (built from its own [chat.telegram] commands), the update-report relay, the show_tool_calls projection, and /restart’s config reload, which re-resolves the token and allowlist from this service’s own file and refuses a reload that resolves to an empty token.
    • /version is sourced from the Gateway through a new ChatSnapshot.Version field. cmd/archie-messaging deliberately takes no version ldflags, so it cannot report a partial upgrade as a matched one.
    • Channel configuration is validated at composition, so a configured-but- invalid front-end fails the service instead of being silently dropped.
    • The inbound rate limiter moves to the Gateway, which now owns the only Router and is therefore the one place a per-sender budget can apply to every channel’s turns.

    RunningVersions and ReleaseAnnouncements are deliberately left unwired: both need a component’s real running version, and the only versions this process can obtain are another binary’s stamps. See docs/architecture/migration-decisions.md.

    archied — Configuration

    • diff_cap_lines = 0 now switches the cap off, as the dashboard and the workflow step have always documented. It was a plain int, so the defaults pass could not tell an absent key from an explicit 0 and rewrote both to 400 – the documented way to disable the cap was unreachable. Behaviour change: a config that set 0 was silently getting 400 and will now get no cap.
    • The same ambiguity was failing open per identity: configForIdentity assigned the identity’s value unconditionally, so an identity that merely omitted diff_cap_lines overwrote the shared cap with the zero value and disabled the safety rail entirely. An identity now overrides only when it sets the key.
    • A diff-cap park no longer tells the operator to “approve manually”. A parked task’s actions are retry, abandon and reject, so there is no approve path out of diff-cap; it now names the two things that work.
    • [health].dependency_timeout makes the daemon’s readiness probe timeout configurable, matching the extracted services.

    archied — Chat rendering

    • /status and /tasks are line-oriented reports but separated lines with a plain newline, which is CommonMark’s soft wrap: the Telegram renderer joined them into one run-on paragraph. The renderer implements CommonMark’s hard line break and the reports use it. Ordinary prose still soft-wraps.
    • A park reason is capped to its first line in the /tasks list. It carries whatever the failing stage reported, which for a lint gate is a whole tool log; unbounded, one parked task pushed every other task out of the reply. The full reason is unchanged on the task, in task_list and on the dashboard.

    archied — Review

    • Review findings are posted as line-anchored PR comments with suggested fixes, and a suggestion must be single-line – GitHub applies a multi-line suggestion only up to its first line, silently corrupting the file (#891).
    • The remediate workflow handles PR review comments and requested changes.

    archied — /status health surface

    /status reports the live broker connection and the last-known outcome of this process’s chat-model calls, alongside the queue depth and runtime block (#892).

    • A provider error is flattened and capped, so a multiline or oversized error cannot break the one-line-per-fact layout.
    • Concurrent model calls no longer reorder: the completion time is taken before the lock, so the newer outcome wins rather than whichever goroutine stored last.
    • Curator model calls are recorded too. They bypass the chat path, so a daemon whose only recent model traffic was curator work reported “no calls attempted yet” while the provider was demonstrably reachable.
    • Title generation does not record health. It runs detached under its own bound and its error is swallowed, so a cosmetic timeout was overwriting the line with “failed”.

    Known limitation: the container, poll and channel sections cannot render. Those facts live in the daemon, but the only Router lives in the Gateway process, which has no container pool and no poll loop. The command description says what actually appears; restoring the rest needs a cross-process health contract.

    archied — Dashboard and containers

    • The served lifecycle vocabulary reaches an already-painted page, the page registry matches the routes, and the build verifies ui/dist is fresh instead of never looking at it (#890, #898).
    • The container reaper no longer deletes teardown bookkeeping early, so a released container is not torn down twice (#893).

    archied — Build

    • task fmt runs golangci-lint fmt – the same engine and configuration the gate checks with. Standalone gofumpt cannot reproduce gci’s import grouping, so formatting and linting could not converge and no command satisfied the gate (#901).
    • goimports is deliberately absent from the formatter set: it re-reads and re-parses the module index once per file, ~135s across this tree.

    archied — Fixed

    • Config.Clone left the new diff-cap pointers aliased, so a clone could write through to the published snapshot (#902).
    • A curator asking for a completion on a daemon with no configured provider panicked the process; it now returns an error.

    archie-agent

    • The sandboxed runtime picks up line-anchored review comments: a finding is posted against the line it is about, with a suggested fix where it has one, and a suggestion is rejected unless it is single-line – GitHub applies a multi-line suggestion only up to its first line, silently corrupting the file (#891).
    • diff_cap_lines is an optional value in the shared config the runtime reconstructs, so an explicit 0 means “no cap” rather than being rewritten to the default. Behaviour change for a repo that set 0 expecting unlimited and was silently getting 400 (#899).
    • A diff-cap park names a remedy that exists: a parked task’s actions are retry, abandon and reject, so the reason no longer says “approve manually”.
    • A released container is not torn down twice – the reaper no longer deletes teardown bookkeeping before Release is finished with it (#893).
    • Build toolchain: gofumpt and golangci-lint are pinned as one matched pair, and task fmt uses the same engine the gate checks with, so the runtime’s own gate is satisfiable (#901).