News
1.32.1
archied — Host packaging: archie-messaging now ships and updates
cmd/archie-messagingis included in the distribution zip, andscripts/archie-update-installinstalls and restarts it.- Why this mattered. v1.30.0 moved Telegram, email and webhook out of
archiedand intoarchie-messaging, but nothing packaged the new binary. A host install that upgraded across v1.30.0 therefore ran on with no messaging process at all:archiedlogged that it stopped serving the telegram gateway, nothing replaced it, and Telegram stayed dead — with no error logged anywhere, because nothing was failing. The process simply did not exist. - The host component set was enumerated in four places — the zip’s build loop, the zip’s copy list,
the installer’s service list, and the installer’s binary list — and
archie-messagingwas missing from all four. The duplication was the defect: a single test now derives the host-run commands fromcmd/and asserts that all four lists agree with it, so adding or extracting a process fails until it is packaged. deployments/systemd-user-service.mdgains the messaging unit. That is load-bearing rather than cosmetic: the updater refuses an update when a service unit is missing and tells the operator to create one from that document, which previously had nothing to offer.
Upgrade note: a host that reached v1.30.0 without a messaging unit has been running with no
Telegram, email or webhook. Updating to this release installs and starts archie-messaging.
1.32.0
archied — EDA: playbook action ids, and a dispatch idempotency ledger
- Action ids (J1). Every action a later action references must now carry an
id. Ids are validated at load – unique and stable-identifier-shaped – and awhen/argsexpression naming an unknownactions.<id>is a load failure, not a runtime miss, the same reject-at-load rule already applied to a binding collision. - Reference classification is strict at load. A map-index reference (
actions[expr]), a non-literal index, and a reference to an unknown prior id are all rejected when the playbook loads; references are classified by identifier versus static access, and the when-compilation helper is shared between the load-time and runtime paths. - Dispatch idempotency ledger. A
playbook_dispatchesrow records a dispatch against(playbook_id, playbook_version, event_id, action_id), written withINSERT OR IGNOREand surfaced through the sharedstore.ErrAlreadyDispatchedsentinel. Module, channel and forge action positions are therefore at-most-once, which is what unblocks the side-effecting positions that were previously rejected at load. - The ledger is wired into production.
stateStoreDepsconstructsDeps.PlaybookDispatcher, so the ledger RPCs no longer answerUnavailablein a running daemon. This defect was found by the pre-release review of this change rather than by its tests.
Behaviour change: a playbook whose actions reference actions.<id> without declaring that
id, declare a duplicate id, or index actions with a non-literal value now fails to load
instead of failing at dispatch time.
archie-agent
The sandboxed runtime links storecontract and staterpc, so it carries the dispatch-ledger
contract alongside archied:
- The shared
store.ErrAlreadyDispatchedsentinel now describes both dedup ledgers –binding_dispatchesper(binding_id, capture_id), andplaybook_dispatchesper(playbook_id, playbook_version, event_id, action_id). Each is an at-most-once guarantee. RecordPlaybookDispatchis part of the store contract the runtime builds against.
archied and archie-agent move together in this release.
1.31.0
archied — Dashboard replaced: Preact -> Vue 3 + shadcn-vue
The dashboard is now a Vue 3 application built on shadcn-vue. This is the large piece of this release; it touches every page.
- History routing, a grouped topbar built from components, the violet palette with self-hosted Geist, and a command palette with live tasks.
- Chat is a FAB-opened panel that behaves like a chat window and scrolls its
transcript with
MessageScroller. - Task actions and dangerous approvals are deliberate; the task detail page is a single head strip with honest states; the run page settles its head around an attempts pager, which is hidden for zero or one attempt.
- Appearance and System navigation were refined, with a four-column appearance grid on wide screens.
- A copy pass removed redundant tails and restating descriptions, empty states derive their own titles, and a stuck log read surfaces as an error rather than eternal loading.
- The capture pane is bound to the list it sits beside and reads beside it, not over it.
archied — Events is one page with three tabs
- Inspector, Bindings and Mappings are now tabs of a single Events page.
- The nav entry is always live, the tabs prune by capability, and the three old paths survive as bookmarks that redirect to their tab.
- Tab selection lives in one module (
ui/src/events/tab-selection.ts) that the page uses, rather than a copy of it. feat(tools): a capture-intake sender exists for exercising the Events surfaces.
archied — The channel travels with the message
SessionSource.Platform – the first component of the session natural key, and
the column GetByChannel filters on – was a constant "web", because one
Router serves every channel and named itself after its own. Two things followed:
the per-user identity policy was real code that no production call site reached
with a real channel name, and a curator pass’s write to agent-user memory could
not be read back by the turn that wrote it, because that turn resolved no
UserID.
- The frontends now name the channel they carry (
telegram,email,webhook,web), the channel rides the message, and the Gateway stamps the session from it – falling back to its own name when a sender names none, which is what every existing row holds. - Identity resolution reads the platform off the inbound, so
carriesPersonIdentitydecides something in production: telegram and email resolve a person, the dashboard and a webhook resolve nothing, and an unknown platform fails closed. - Behaviour change: a chat whose active session came from
/newor/branchre-resolves once, because session lookup now filters on the channel’s real name. A chat without/newre-resolves onto the same deterministic id and heals silently. - Deliberately unchanged:
TurnRunnerConfig.Channelstill keys tool availability, so no channel gains or loses a tool in this release.
archied — Control plane: runtime administration, history, and derived schemas
- The State Store’s gRPC server now carries runtime administration, and each process reports which settings version it is running; the dashboard shows it.
- Resource history is exposed so edits can be reviewed and rolled back, and
resource schemas are derived from the documents they describe – the document
editor reads the derived schema (labels from
title,format: duration->1m0s, hints fromdoc), and the abandoned schema-driven card is deleted. - A live settings replacement is checked before it is switched to, the daemon’s state surfaces are folded into one boot step, and a SIGHUP reload re-applies database-owned settings.
- Forge intake settings that nothing reads are now rejected at load.
archied — Configuration: judged where it is owned
- The runtime config overlay is deleted; database-owned settings are judged at the layer that owns them rather than on the file load path.
- A file overlay no longer drops the fields it omits inside a map entry, and a kind with no stored value leaves the file’s value in force.
- The default config path is resolved in one place, and the channel document has its own shape.
archied — State Store: offline backup, restore, validate and rollback
- New offline backup / restore / validate / rollback path.
validateruns boot’s own gate; it no longer replaces the database, reads a kind the store does not hold as its seed, or touches the daemon’s log.- The recovery control-plane server is built on the shared step vocabulary.
archied — Workflow: one step vocabulary and a gate.diff-rules replacement
- The step vocabulary is owned by a family manager registered at each
composition root, replacing
.archie/gate.gowithgate.diff-rules, which fails closed on a change it never read. - Workflow roots are pinned and the dead vocabulary is removed; the workflow pin crosses the wire.
- The schedules resource skips the legacy cron jobs it cannot hold, and the scheduling policy carries the label its trigger pairs with.
archied — EDA: the playbook coordinator reaches production selection
- The playbook coordinator is wired into production workflow selection, so a
matching playbook decides a real task’s workflow at the daemon’s definition
pin, inheriting idempotency from
TaskEnvelope.
archied — Reliability and operations
cronstorewrites a schedule interval as a duration, not nanoseconds – a persisted1mno longer round-trips as60000000000.- Worktrees are cut from the mapped base branch, and the Gateway’s worktree
manager is built so it serves
review_pr. - A late max-uptime callback no longer resurrects teardown state.
- The state store dial installs client keepalive, and its server policy accepts the dialer’s pings; control-plane watch streams re-establish themselves after they end.
/statusserves only the health facts a reply can carry; the daemon reports systemd readiness and loop-driven watchdog heartbeats.- A webhook route path no longer becomes a sender identity.
- A chat session compresses when a turn crosses its context budget.
- The MCP client supports per-server
parallel_tool_calls, carried through the tool-settings projection. - Resource request-ID idempotency keys are scoped to their kind.
- The session curator addresses memory by the deployment’s bot user.
archie-agent
The sandboxed runtime links the same shared packages as archied, so this release carries the control-plane and workflow changes alongside it:
- Runtime administration over the State Store’s gRPC server, resource history, and control-plane apply status on the store contract.
- The shared step vocabulary, owned by a family manager registered at each
composition root, and
gate.diff-rulesin place of.archie/gate.go(fails closed on a change it never read). - The workflow pin crosses the wire.
Runtime-specific changes:
refactor(plugin): the unusedRegistrytype is deleted.yaegiutilrefuses incomplete Yaegi interface wrappers at load rather than running them.- The runtime config overlay is deleted.
- The state store dial installs client keepalive, and the server policy accepts the dialer’s pings.
- The MCP client supports per-server
parallel_tool_calls. - A late max-uptime callback no longer resurrects teardown state.
- A webhook route path no longer becomes a sender identity.
Note: the archie-agent image is rebuilt by this tag through CI
(.github/workflows/deploy.yml); a gateway-only release would not have rebuilt
it. docker compose pull agent is required to pick it up.
1.30.0
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, theshow_tool_callsprojection, 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. /versionis sourced from the Gateway through a newChatSnapshot.Versionfield.cmd/archie-messagingdeliberately 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 = 0now switches the cap off, as the dashboard and the workflow step have always documented. It was a plainint, so the defaults pass could not tell an absent key from an explicit0and rewrote both to 400 – the documented way to disable the cap was unreachable. Behaviour change: a config that set0was silently getting 400 and will now get no cap.- The same ambiguity was failing open per identity:
configForIdentityassigned the identity’s value unconditionally, so an identity that merely omitteddiff_cap_linesoverwrote 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_timeoutmakes the daemon’s readiness probe timeout configurable, matching the extracted services.
archied — Chat rendering
/statusand/tasksare 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
/taskslist. 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, intask_listand 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/distis 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 fmtrunsgolangci-lint fmt– the same engine and configuration the gate checks with. Standalonegofumptcannot reproduce gci’s import grouping, so formatting and linting could not converge and no command satisfied the gate (#901).goimportsis 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.Cloneleft 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_linesis an optional value in the shared config the runtime reconstructs, so an explicit0means “no cap” rather than being rewritten to the default. Behaviour change for a repo that set0expecting 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
Releaseis finished with it (#893). - Build toolchain:
gofumptandgolangci-lintare pinned as one matched pair, andtask fmtuses the same engine the gate checks with, so the runtime’s own gate is satisfiable (#901).
1.29.0
archied — Security
google.golang.org/grpcbumped pastv1.84.0to patch GO-2026-6443, a server panic via a missing:authority/Hostheader reachable througharchied’s gRPC gateway server. No stable release carries the fix yet, so this pins the pre-release commit that does (v1.85.0-dev.0.20260825072537-93e31b48545e) untilgrpc-gocutsv1.85.0.
archied — Memory engine unification
One memory engine, addressed by four typed scopes (global, agent, user, agent-user), replaces the two disconnected stores that previously existed: a chat-tool-written store nothing ever read back, and a curator-written store with no scope model.
internal/domain/memoryis a CRUD contract (Create/Get/Query/List/Update/Forget/Revisions) with retained revisions; updates supersede rather than overwrite, so a crash mid-write leaves a recoverable extra history entry, never a lost prior state (#886).- The chat turn reads its subject’s scopes synchronously before the prompt is
built, rendering recalled records into a
<memory>block; a failing or panicking engine degrades to no memory block rather than failing the turn (#887). - The model writes memory through four id-addressed tools
(
memory_create/update/delete/list), scoped to the turn’s own resolved identity – the model chooses the scope kind, never the ids, so it has no path to write into another user’s memory (#888). - The session curator now derives the agent-user scope from the session’s own user-role messages, instead of keying facts by a session id that stops meaning anything once the session ends.
- A channel with no resolvable user (dashboard, webhook) reads and writes only global and agent scope; a webhook’s route path is never treated as a user identity.
- Fixed a review finding on the read path: the per-scope record limit was being applied as one shared total across all scopes rather than per scope, and the rendered block’s byte cap was checked before template escaping rather than after, letting the escaped block exceed it.
archied — Work intake
- feat(workintake): define review reaction envelope
- feat(workintake): authorize review reactions by owned PR
archied — Cleanup
- Deleted the unwired plugin capability-host health surface
(
Host.Health/Host.Manifests/ModuleStatus) and theModule.Healthchain it fed – including themcp/builtintool-provider health implementations and their aggregation intools/provider.Registry– none of which had ever had a production caller (#882).
archie-agent
- The sandboxed runtime picks up the review-reaction envelope and its owned-PR authorization, so an agent can only react to reviews on pull requests it opened itself.
google.golang.org/grpcbumped pastv1.84.0to patch GO-2026-6443 (shared dependency witharchied; the pre-release commit is pinned pending a stablev1.85.0).
1.28.0
archied — Task detail and attempt attribution
- New per-run task detail page, showing each attempt’s own events, changes and configuration rather than a single merged view.
- Events, changes and config are attributed to the attempt that produced them;
EventcarriesattemptandReadTaskLogRequestcarriesstage. - The task detail page remounts when the task id changes, so switching tasks does not leave the previous one’s data on screen.
archied — Configuration
- Services are keyed by name through a registry, so the State Store and Gateway listen addresses are configurable rather than fixed.
- A partial overlay no longer clears the fields it omits — an overlay that set one key was wiping the rest.
- The Services map is cloned on publish, so an overlay can no longer mutate the snapshot other readers are holding.
- The service context is enforced at registration.
archied — Logging and park reasons
- A parked run’s reason is recorded in its own attempt log, in both the daemon and the workflow, so “why did this park?” is answerable from the task itself.
TaskRegistry.Writetakes the caller’s context.
archied — Worktrees and containers
- Retries recover from path-type conflicts instead of failing opaquely, and the underlying cause is no longer masked.
- The worktree is handed back on every sandbox exit.
- A container’s max-uptime reaper is cancelled on release, the cap stays active through the grace period, and teardown is claimed once rather than by cancelling a timer.
archied — Daemon and startup
- Every identity’s forge and repos are swept at startup, including the root forge.
- A cancelled startup is no longer reported as an exhausted sweep budget; an exhausted budget names itself as the cause.
archied — Other
grepcan use the workspace codesearch index.- Forge labels are matched when namespaced, so label-driven routing works for namespaced labels.
- Triage is given criteria for choosing between workflows, and a workflow is required when a code change is needed.
- The Telegram adapter restart callback is wired into the chat router.
- The
ARCHIE_REACTIONSfan-out stream is provisioned and bounded by age. archie-uiexits cleanly when graceful shutdown overruns its deadline.- The dashboard’s event pump retries priming until the State Store answers.
- The update writer emits the agent version sidecar with a real newline.
- The UI finishes its Preact port; the imperative DOM layer is deleted.
- Collection fields decoded over the State Store gRPC contract are never nil
slices, so an empty collection marshals as
[]rather thannull.
archie-agent
- The sandboxed runtime picks up the attempt-attribution contract, so the events and changes an agent produces are recorded against the attempt that produced them.
grepcan use the workspace codesearch index.- A worktree is handed back on every sandbox exit, and container teardown is claimed once — a released container’s reaper is cancelled rather than re-firing during the grace period.
- Retries recover from worktree path-type conflicts instead of failing opaquely.
- A parked workflow run records its park reason in its own log.
- Triage criteria distinguish the workflows, and a workflow is required when a code change is needed.
- Namespaced forge labels match when routing by kind.
- The
ARCHIE_REACTIONSfan-out stream is provisioned. - Collection fields decoded over the State Store gRPC contract are never nil
slices, so an empty collection marshals as
[]rather thannull.
1.27.0
archied — Dashboard task logs
- Task logs are readable from the dashboard again, through a new State Store
read contract (
ReadTaskLog,StreamTaskLogContent) rather than the UI process reaching into the daemon’s log files. Wired server-side by the standalone state-store process. - Added
GET /api/tasks/{id}/logs/download, serving an attempt’s raw log as atask-<id>-attempt-<n>.logattachment. - A process that cannot read logs and an attempt that recorded no log are now distinguishable (“cannot read” answers 503, “no log” answers 404) instead of both rendering as a claim about a configuration setting.
archied — Telegram output
- Tool results are summarised rather than quoted: a search reports how many matches came back, a truncated result reports the tool’s own total. The renderer no longer states a count it computed from its own truncated sample.
- Repeated successful tool calls collapse into one counted entry.
- The tool-activity block is capped to a third of the live frame, keeps the
newest lines, and marks what it dropped with a
+N earlierindicator. Every line that fits is kept. - Every clamped answer marks its cut with an ellipsis, including the opening frame, which previously appeared to begin mid-sentence.
- An error response from the log download no longer ships as a
.logfile.
archied — Readiness and shutdown
- The disk probe reports per-filesystem results and checks the root filesystem as well as the work directory, so a full root is no longer invisible.
- A path shared by several disk targets keeps the strictest requirement any target places on it, so an optional target can no longer mask a required one.
- The shutdown-watchdog test no longer races the Go scheduler, which was intermittently failing the quality gate and parking work unrelated to it.
archied — Other
- Messages persist the channel-native sender id.
- go-telegram/bot bumped to v1.27.0, fixing a streaming bug where the multipart
body could not be replayed and
sendMessage/editMessageTextfailed until the connection dropped.
archie-agent
- The per-task runtime picks up the new State Store task-log read contract, so the sandboxed agents share one log-reading path with the daemon and the dashboard.
1.26.0
archied
- fix(webui): publish per-identity forges so multi-identity task rows keep their links
- feat(config): add [scheduling] config block
- feat(configuration): translate [scheduling] into scheduling.EngineConfig
- feat(cronevents): adapt the events bus to scheduling.Sink
- fix(webui): count every chat front-end in the published projection
- fix(scheduling): respect configuration ownership
- feat(ratelimit): wire per-identity inbound rate limiting into the gateway
- fix(tools): judge the rm guard by base name so absolute paths cannot bypass it
- fix(store): keep an empty binding secret empty so a partial edit cannot erase it
- fix(archied): stop advertising review_pr when no reviewer can run
- fix(daemon): carry kind/label routing bindings to the process that routes
- feat(configuration): add archied setup, the caller the first-run flow was built for
- fix(configuration): stop letting a secret value be set from the command line
- feat(configuration): let setup reference a secret without carrying its value
- fix(archied): disable a provider whose credential is missing instead of refusing to boot
- refactor(install): install.sh delegates config generation, and tests stop reading hand-written configs
- fix(daemon): guard binding dispatch loop against nil dispatcher/creator
- fix(webui): enforce CSRF/origin gate on binding and mapping mutations
- fix(secret): recover a panicking secret engine instead of crashing
- fix(config): deep-copy Image.Hosted/Image.Local in Config.Clone
- fix(email): stop dropping the first paragraph of plain-text bodies
- fix(logging): keep the live descriptor open across a failed rotation
- feat(configuration): report config keys no decode target consumed
- feat(archied): warn at boot when the config file has unrecognised keys
- feat(archied): wire the scheduling ticker engine at boot
- fix(agentworker): wire configured tool-result policy into worker’s LoopRunner
- refactor(staterpc): delete the superseded single-token auth interceptor
- refactor(memory): delete the unreachable
fence scrubber - fix(channels): delete unreachable Telegram webhook delivery mode
- fix(gateway): delete unwired Router.Dangerous approval path
- refactor(gateway): delete orphaned SessionState goal/steer/queue machinery
- refactor(archied): delete the daemon’s unused webui.Server and UI adapters
- refactor(tools): delete unreachable dispatch/gating engine
- feat(channels): wire chat.webhook route config through to the gateway
- refactor(tools): delete unreachable AST-based tool discovery
- refactor(tools): delete unused plugin-tool registration API from builtin.Registry
- feat(channels): wire ConfigSchema/ValidateConfig into a startup validation loop
- refactor(state): delete the dead IncrementRetryCount RPC (breaking change, accepted)
- fix(curator): populate PassInput.Since with the prior pass time
- fix(memory): install the threat scanner the composition root never wired
- fix(staterpc): preserve marshal_error marker in eventDataJSON
- fix(gate): validate finding level and share the blocking threshold
- fix(scheduling): record a completed run so a recurring job stops re-firing every tick
- fix(releaseupdate): don’t treat empty available as deferred
- fix(tools/provider/mcp): preserve MCP binary tool results for delivery
- refactor(gateway): share sensitive-key markers with webhookguard
- refactor(daemon): remove unreachable SQLite poll/drain path
- refactor(tools/mcp): delete unreachable MCP adaptation path
- fix(taskactions): resolve max_retries from the task’s owning identity
- fix(daemon): forward configured MCP servers to task agents
- refactor(skill): delete dead Discover/DiscoverPlugins/Skill path
- refactor(skillbuild): delete dead AugmentRegistry path
- fix(builtin): bound read/edit filesystem work by DefaultToolTimeout
- refactor(binding): delete dead Matcher.Overlaps method
- refactor(forge): delete dead CreateIssue surface
- fix(mcp): cancel in-flight SSE reconnect on Stop
- fix(container): enforce MaxUptime lifetime cap with a timer
- refactor(store): use taskstate status constants in SQL
- fix(ui): unbreak binding approve and the two deletes, and centralise the client
- fix(tools): stop testing on the text of other files, and ungate contractaudit
- refactor(forge): delete the unwired RepliesAfter surface
- refactor(config): delete the two decoded-but-unread policy fields
This release is dominated by dead-code removal and the completion of the
scheduling capability. Roughly half the commits delete surfaces that no longer
had a caller: the unreachable SQLite poll/drain path, the unwired MCP
adaptation path, the AST-based tool discovery, the superseded single-token auth
interceptor, and several dead forge and binding methods. The
IncrementRetryCount State Store RPC is gone with them – a breaking change to
the wire contract, accepted because nothing called it.
The cron/scheduling epic lands its remaining slices: the [scheduling] config
block, its translation into the engine’s own settings, the events-bus sink
adapter, and the boot wiring that starts the ticker. A recurring job now records
a completed run, so it stops re-firing on every tick.
Operator-facing work: archied setup gives the first-run flow the caller it was
built for, configuration no longer accepts a secret value from the command line,
and a provider whose credential is missing is disabled rather than refusing to
boot. A secret engine that panics is now recovered instead of crashing the
daemon.
archie-agent
- feat(config): add [scheduling] config block
- fix(webui): count every chat front-end in the published projection
- fix(scheduling): respect configuration ownership
- feat(ratelimit): wire per-identity inbound rate limiting into the gateway
- fix(tools): judge the rm guard by base name so absolute paths cannot bypass it
- fix(daemon): carry kind/label routing bindings to the process that routes
- fix(config): deep-copy Image.Hosted/Image.Local in Config.Clone
- fix(logging): keep the live descriptor open across a failed rotation
- fix(agentworker): wire configured tool-result policy into worker’s LoopRunner
- refactor(staterpc): delete the superseded single-token auth interceptor
- refactor(tools): delete unreachable dispatch/gating engine
- feat(channels): wire chat.webhook route config through to the gateway
- refactor(tools): delete unreachable AST-based tool discovery
- refactor(tools): delete unused plugin-tool registration API from builtin.Registry
- refactor(state): delete the dead IncrementRetryCount RPC (breaking change, accepted)
- fix(staterpc): preserve marshal_error marker in eventDataJSON
- fix(gate): validate finding level and share the blocking threshold
- fix(tools/provider/mcp): preserve MCP binary tool results for delivery
- refactor(tools/mcp): delete unreachable MCP adaptation path
- refactor(skill): delete dead Discover/DiscoverPlugins/Skill path
- refactor(skillbuild): delete dead AugmentRegistry path
- fix(builtin): bound read/edit filesystem work by DefaultToolTimeout
- refactor(binding): delete dead Matcher.Overlaps method
- refactor(forge): delete dead CreateIssue surface
- fix(mcp): cancel in-flight SSE reconnect on Stop
- fix(container): enforce MaxUptime lifetime cap with a timer
- refactor(forge): delete the unwired RepliesAfter surface
- refactor(config): delete the two decoded-but-unread policy fields
The runtime carries a smaller, more focused set of changes than the same
version’s archied entry: agent-side tool-result policy is now wired into the
worker’s loop, MCP binary tool results survive to delivery, the container
MaxUptime lifetime cap is enforced with a timer, and a scheduled run records
completion so it does not re-fire each tick.
Note that several bullets above name config, webui and ratelimit packages. Those
are attributed here by the release tool’s package-closure rule (go list -deps
over the agent binary), not because the agent owns them; the substantive
runtime changes are the worker, MCP, container and scheduling fixes.
This entry also confirms the removal of the dead IncrementRetryCount State
Store RPC, which the agent reaches through staterpc rather than by calling it
directly.
1.25.0
archied
- fix(update): resolve releases without a checkout, and fail loudly when it cannot
- fix(update): back up the task store the daemon actually uses, or refuse
- fix(update): build each component from its own approved release tag
Components are independently versioned, so the newest archied/v* and
archie/v* tags usually sit on different commits. The installer required both
tags to resolve to one commit whenever both components changed, which refused
every update once the two newest releases diverged – a deployment stuck on
1.22.0 could not take any update. Each component now builds from its own
approved tag.
archie-agent
- chore: no user-facing changes; versioned so the 1.25.0 release tags both components at the same commit
1.24.0
archied
Makes 1.23.0 deployable. That release split archied into separate processes,
but the self-updater still installed only the archied binary and restarted
only archied.service, so updating to it left the State Store, Gateway and UI
on the previous release. archied cannot boot without a reachable State Store,
so the update failed its health check and rolled back. Update to this release
rather than to 1.23.0.
If your host does not yet run the four units in
deployments/systemd-user-service.md, create them first: the updater now
refuses, naming what is missing, instead of installing binaries onto a host it
would leave broken.
- fix(update): install and cycle every process in the release
- fix(telegram): stop the relay corrupting identifiers and code
Also in this release, though outside the version-stamped package closure:
- ci(deploy): produce a complete distribution zip on every release. No zip was
built for v1.23.0 at all, and the zip omitted
archie-ui.
Page 5 of 10