Commit Graph

181 Commits

Author SHA1 Message Date
Peter Steinberger
6ef77d7c7e refactor: expire July 24 plugin compat records (#112944) 2026-07-23 03:04:34 -04:00
Peter Steinberger
bac2bbd243 refactor(google-meet): split CLI modules (#112937)
* refactor(google-meet): split CLI modules

* test(google-meet): align CLI split routing

* refactor(google-meet): isolate CLI command contract
2026-07-23 03:00:34 -04:00
Jason (Json)
6504cf85f2 fix(ui): restore project hierarchy and session activity (#112924)
* fix(ui): restore catalog project type hierarchy

* feat(ui): show catalog session activity

* chore(ui): update startup budget baseline

* test(ui): isolate catalog activity coverage
2026-07-22 23:43:46 -06:00
Peter Steinberger
707343b726 fix(ci): rebase Control UI startup budget baseline onto CI-measured bytes
All four QA Smoke profiles fail on main since the #112880 ratchet landed:
startup JS gzip ~323,326-323,342 B vs baseline 322,526 + 512 B tolerance.
The overage comes from UI commits that landed after the baseline was
captured (#112859 #112866 #112853 #111861). Local macOS builds measure
~322,535 B; Linux CI is ~800 B larger, so the baseline must track the CI
measurement (max observed across profiles, run 29980596056).
2026-07-23 01:04:10 -04:00
Peter Steinberger
32014bd84f refactor(google-meet): split plugin entry modules (#112903) 2026-07-23 01:03:51 -04:00
Peter Steinberger
b3e2af7eb2 refactor(scripts): remove orphaned secret provider proof (#112875) 2026-07-23 00:29:44 -04:00
Peter Steinberger
dfc88210be refactor(google-meet): split Meet API client (#112873)
* refactor(google-meet): split Meet API client

* refactor(google-meet): keep internal API types private
2026-07-23 00:29:21 -04:00
Peter Steinberger
c11f175282 feat(ci): ratchet the Control UI startup JS budget against a committed baseline (#112880)
The startup JS gzip gate was a fixed ceiling that main drifted to within
1-3 KiB of, forcing repeated hand-bumps (315->317 KiB) and failing
feature PRs on drift they did not cause (#112649 burned two CI rounds).

check-control-ui-performance.mjs now also enforces a committed baseline
(config/control-ui-startup-budget-baseline.json) with a 512 B tolerance:
regressions beyond baseline+tolerance fail with an actionable message,
intentional increases become a reviewed one-line diff via
--update-baseline --reason, meaningfully lighter builds print a
lower-the-baseline hint, and a malformed/missing baseline fails closed.
The fixed ceiling stays as the cumulative-creep backstop.

Closes #112743.
2026-07-23 00:19:36 -04:00
Peter Steinberger
099d6351b3 refactor(sessions): canonical lineage model — creation provenance, fork ancestry, generation chain, typed row contract (#111861)
* fix(sessions): preserve spawn/fork lineage across implicit daily/idle rollover

* refactor(sessions): canonical creation model with forkSource ancestry and generation chain

* feat(sessions): stamp creation provenance across all creation paths and emit created events

* refactor(gateway): lock lineage patching, split control from navigation, add typed session-row contract

* docs(gateway): document creation provenance stamping and lineage patch tightening

* fix(sessions): keep provenance proof-only on wire fallbacks and strip node-local lineage from cron continuations

* fix(gateway): never journal a created event for session adoption

* fix(gateway): keep post-create work on adoption while gating the created event

* fix(sessions): restore trusted ensure-main provenance and stamp navigation parent at spawn

* fix(sessions): allow parentSessionKey through the direct child spawn patch

* fix(ci): break type cycles, satisfy export scan, regenerate Swift protocol models

* refactor(sessions): replace createdBy with createdActor

* fix(protocol): export session row type

* fix(sessions): preserve proven creation provenance

* fix(sessions): close lineage creation gaps

* test(sessions): align atomic spawn lineage coverage

* test(sessions): widen transcript search reconcile wait

* fix(sessions): stamp reset-created rows

* test(sessions): keep reset provenance coverage focused

* fix(sessions): journal chat-created rows

* test(ci): anchor release skill reads to repo

* test(ci): avoid cached module paths
2026-07-22 22:54:31 -04:00
Peter Steinberger
8ef067a216 refactor(config): move Discord and Teams schemas to plugins (#112812)
* refactor(config): move Discord and Teams schemas to plugins

* refactor(discord): privatize config schema fragments

* style(discord): format private schema fragments
2026-07-22 21:02:12 -04:00
Peter Steinberger
62c148d7d0 refactor(e2e): remove stale proof scripts (#112776) 2026-07-22 15:31:36 -07:00
Peter Steinberger
4501da6123 refactor(speech-core): split TTS runtime (#112768)
* refactor(speech-core): split TTS runtime

* refactor(speech-core): keep helper types private
2026-07-22 14:48:00 -07:00
Peter Steinberger
2b405755b1 fix(plugins): refresh prepared provider metadata (#112699)
* fix(plugins): refresh prepared provider metadata

* test(agents): tolerate minimal metadata snapshots

* test(agents): cover snapshot endpoint precedence
2026-07-22 11:07:35 -07:00
Peter Steinberger
3c4a1ec905 refactor(agents): move CLI backend adapters from config DSL to registerCliBackend plugins (review request) (#112539)
* refactor(agents): move CLI backend adapters into plugins

* test(agents): register CLI backend fixtures through plugins
2026-07-22 00:25:29 -07:00
Peter Steinberger
edecdbd05e refactor(config): config-surface reduction tranche 3 — product consolidations (review request) (#111527)
* refactor(config): consolidate media model lists

* refactor(config): unify memory configuration

* refactor(config): consolidate TTS ownership

* refactor(config): move typing policy to agents

* refactor(config): retire product-level config surfaces

* refactor(config): share scoped tool policy type

* chore(config): refresh generated baselines

* fix(config): honor agent typing overrides

* fix(config): migrate sibling config consumers

* refactor(infra): keep base64url decoder private

* fix(config): strip invalid legacy TTS values

* chore(config): refresh rebased baseline hash

* fix(doctor): route legacy messages.tts.realtime voice to talk during tts move

* refactor(config): polish final layout names

* refactor(config): freeze retired tuning defaults

* feat(config): add fast mode default symmetry

* refactor(config): key agent entries by id

* docs(config): update final layout reference

* test(config): cover final layout migrations

* chore(config): refresh final layout baselines

* fix(config): align final layout runtime readers

* fix(config): align remaining readers

* fix(config): stabilize final layout migrations

* fix(config): finalize config projection proof

* fix(config): address final layout review

* docs(release): preserve historical config names

* fix(config): complete keyed agent migration

* fix(config): close final migration gaps

* fix(config): finish full-branch review

* fix(config): complete runtime secret detection

* fix(config): close final review findings

* fix(config): finish canonical docs and heartbeat migration

* fix(config): integrate latest main after rebase

* refactor(env): isolate test-only controls

* refactor(env): isolate build and development controls

* refactor(env): collapse process identity indirection

* refactor(env): remove duplicate config and temp aliases

* docs(env): define the operator-facing allowlist

* ci(env): ratchet production variable count

* fix(env): remove stale provider helper import

* fix(env): make ratchet sorting explicit

* test(env): keep test seam in dead-code audit

* test(env): cover ratchet growth and boundary; document surface budgets

* docs(config): document tier-eval consolidations

* docs(config): clarify speech preference ownership

* test(memory): align retired tuning fixtures

* refactor(memory): freeze engine heuristics

* refactor(config): apply tier-eval tranche

* refactor(tts): move persona shaping to providers

* refactor(compaction): move prompt policy to providers

* test(config): align hookified prompt fixtures

* chore(deadcode): classify test-only exports

* chore(github): remove unused spawn helper

* chore(deadcode): classify queue diagnostics

* chore(deadcode): remove unused lane snapshot export

* chore(plugin-sdk): ratchet consolidated surface

* fix(config): integrate latest main after rebase
2026-07-21 20:28:43 -07:00
Peter Steinberger
0f066eec81 feat(dashboard): plugin widget kinds — native WorkBoard card and mini-board widgets (#112434)
* feat(board): add plugin widget kinds

* feat(ui): render native Workboard widgets

* fix(dashboard): compose plugin widgets with current main

* chore: internalize widget-kind contribution types

* fix(ui): retry plugin widget renderer loads

* fix(ui): harden Workboard widget refresh lifecycle

* fix(ci): clear plugin widget landing gates

* fix(boards): migrate plugin widget storage

* fix(db): migrate unreleased board widget constraint

* fix(ui): retry failed Workboard widget loads

* fix(ui): keep stale widget refresh cleanup inert

* fix(ci): align plugin widget landing guards
2026-07-21 17:59:20 -07:00
Peter Steinberger
f0c43dcf72 feat(ui): format international phone numbers for display (#112400)
* feat(ui): format phone numbers for display

* ci: track normalization package exports in Knip
2026-07-21 17:10:25 -07:00
Vincent Koc
1d28128c20 chore(ci): audit dependency fingerprint exports (#112190) 2026-07-21 15:18:09 +08:00
Peter Steinberger
b4e27f8b3d refactor: move provider transports into packages/ai behind a typed host port (#111669)
* refactor(ai): invert plugin coupling behind the transport host port

* fix(ai): queue custom transport registrations until the host is configured

* refactor(ai): remove relocated transport sources from src/agents

* fix(ai): source core stream types from canonical packages and fix tarball fixtures

* fix(ai): invert plugin transport host wiring

* fix(ai): harden managed transport projection

* test(ai): register synchronous stream in transport mock

* fix(ai): lazily install transport runtime host

* fix(ai): preserve completion compat detection
2026-07-20 23:26:00 -07:00
Peter Steinberger
5197428add feat(channels): batch 4 Telegram drops media placeholder bodies (#111855)
Final producer batch of the media-placeholder program: Telegram primary
bodies are caption-only with one aligned structured fact per native
media; the message-cache kind-parsing regex is deleted (native kind
stored directly); reply-chain, debounce/forward, group-history, and
ambient transcript lines render structured facts via the shared
formatter (removing the plugin-local duplicate of the caption-less
literal); audio-transcript and sticker-description replacements gate on
structured facts instead of exact placeholder strings. Also restores
unconditional failed-retryable recording when media resolution is
aborted for live updates, so shutdown cannot silently settle an
undispatched update.
2026-07-20 07:31:10 -07:00
Peter Steinberger
629de998f9 feat(system-agent): agentic cached caretaker greeting with quick actions (#111615)
* feat(system-agent): agentic cached caretaker greeting with quick actions

* test(gateway): pin caretaker greeting in session-ownership tests

* fix(system-agent): offer agent handoff chip only when a model is available

* fix(ci): typecheck narrowing, lint, and knip gates for greeting module

* fix(system-agent): reject structured greeting output on every retained line

* test(gateway): split caretaker welcome tests under the max-lines gate
2026-07-20 01:21:09 -07:00
Peter Steinberger
6e19c36d41 feat(channels): batch 2 producers drop media placeholder bodies (#111665)
* feat(channels): batch 2 producers drop media placeholder bodies

Media-placeholder program batch 2: Discord, Feishu, and MSTeams stop
minting <media:kind> placeholder bodies. Primary bodies carry captions
only; native resources produce ordered structured facts with type-only
facts for failures/rejections (batch-1 alignment contract). Discord
stickers travel as native kind "sticker" (not MIME-derivable); text
carriers (forwarded snapshots, room history, thread starters, pending
text) render via formatMediaPlaceholderText. Feishu audio preflight and
MSTeams unavailable selection move from body-string equality to
structured facts; dead placeholder payload builders deleted.

* test(discord): make allowlist policy explicit
2026-07-19 22:48:32 -07:00
Peter Steinberger
06480d767c feat(dashboard): stitch session dashboards end-to-end — live provider, show_widget pin, board commands (#111218)
* feat(dashboard): pin canvas widgets through board domain

* feat(control-ui): wire session dashboards end to end

* fix(control-ui): preserve direct reset confirmation

* fix(control-ui): localize dashboard default tab

* test(dashboard): satisfy changed typecheck gate

* fix(dashboard): satisfy changed lint gate

* fix(dashboard): harden pinned widget lifecycle

* fix(dashboard): use extracted mock normalizer

* test(dashboard): reconcile hardened board admission tests

* fix(dashboard): align grant and canvas protocol requests

* fix(dashboard): preserve refresh and pin invariants

* fix(boards): treat missing board tables as empty on read-only paths

* fix(boards): accept read-only handles in board table probe

* fix(control-ui): preserve virtual board widget types

* fix(dashboard): align view types with protocol

* fix(dashboard): keep resolved board view typed

* chore(canvas): drop test-only html read wrapper

* chore(release): defer dashboard note generation

* fix(protocol): align board widget put params type

* fix(control-ui): preserve queued reset approval

* fix(control-ui): gate dashboard pinning capability

* chore(test): isolate dashboard capability fixture

* fix(control-ui): refresh dashboard pin affordance
2026-07-19 12:36:54 -07:00
Peter Steinberger
c7e7ac2728 refactor: remove expired plugin compatibility surfaces (#111451)
* docs(secrets): remove retired web credential paths

* refactor(web): remove retired provider compatibility paths

* refactor(providers): delete retired compatibility routes

* refactor(secrets): remove retired credential aliases

* refactor(plugin-sdk): delete retired compatibility surfaces

* docs(plugin-sdk): remove retired migration guidance

* chore(plugin-sdk): refresh rebased surface budgets

* chore(plugin-sdk): refresh API removal baseline

* refactor(compat): migrate retired internal callers

* chore(plugin-sdk): refresh current-main baselines

* test(config): migrate plugin-owned secret assertions

* test(gateway): narrow plugin secret refs

* fix(plugin-sdk): preserve private boundary type identity

* chore(compat): remove stale sweep references

* chore(lint): lower max-lines budget

* refactor(secrets): remove unused web helper

* build(plugin-sdk): drop removed compat entries

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): use Linux API baseline hash

* fix(plugin-sdk): preserve private bundled build entries

* fix(plugin-sdk): package private runtime facades

* fix(plugins): preserve external credential contracts
2026-07-19 11:04:48 -07:00
Peter Steinberger
1f507162ee fix(ci): validate sticky importer restores (#111444) 2026-07-19 07:57:46 -07:00
Peter Steinberger
783a5d21cf refactor(config): purge numeric tuning knobs behind built-in defaults (#111382) 2026-07-19 07:35:45 -07:00
Peter Steinberger
06f5f73e47 refactor: own model discovery by runtime lifecycle (#111173)
* refactor(agents): prepare model runtime catalogs

Build lifecycle-owned model and auth snapshots, carry prepared stores into hot agent paths, and serialize config/auth publication.

Credits @zeroaltitude's #90741 investigation and benchmark approach.

* refactor: finish lifecycle-owned model discovery

* fix: align prepared model catalog contracts

* test: align lifecycle catalog mocks

* test: fix prepared catalog type fixtures

* refactor: split prepared model runtime ownership

* fix: import prepared runtime replacement gate type

* test: split media runtime coverage

* test: preserve image auth fixture key types

* test: isolate lifecycle gate fixtures

* chore: keep release changelog owned

* refactor: finish prepared model catalog migration

* test: keep catalog review fixtures scanner-safe

* refactor: preserve lifecycle model runtime ownership

* fix: close prepared runtime lifecycle races

* fix: preserve compaction workspace fallback

* chore: document btw generation rebinding

* fix: preserve prepared generation boundaries

* fix: keep model-list discovery flag explicit

* fix: serialize standalone model runtime activation

* refactor: migrate subagent model catalog lookup

* refactor: clarify doctor catalog lookup seam

* chore: refresh plugin sdk api baseline

* test: migrate swarm catalog dependency

* refactor(telegram): rename runtime catalog seam

* refactor: extract model-aware tool context

* test(models): isolate lifecycle catalog fixtures

* refactor(agents): avoid btw parameter rebinding

* fix(net-policy): align root ipaddr dependency

* fix(build): keep net policy dependency bundled

* fix(deadcode): document net policy compile dependency
2026-07-19 05:30:54 -07:00
Peter Steinberger
3b84a55d99 refactor(protocol): pre-publish cheat-window cleanup and vintage tracking (#111041)
* fix(codex): drain dynamic-tool handlers before side-thread cleanup

* refactor(protocol): rename question ids to questionId and flatten answer maps

* refactor(protocol): slim worker stack and unify session-catalog shapes

* refactor(protocol): delete dead public surface and polish packaging

* feat(protocol): track release-train vintage on gateway methods and schemas

* fix(apps): align question surfaces merged from main with reshaped protocol

* test(health): shape secret fixtures to scanner-safe token names

* test(health): use scanner-safe token fixtures

* fix(apps): align question surfaces merged from main with reshaped protocol

* fix(ci): prove reshaped protocol in shallow checks

* fix(ui): align sidebar question fixtures with protocol

* fix(apps): read flat Swift question answers

* fix(apps): align question surfaces merged from main with reshaped protocol

* fix(apps): refresh native question inventory

* fix(apps): align macOS snapshot fixtures with protocol

* fix(ui): align narration question fixture with protocol
2026-07-19 04:07:15 -07:00
Peter Steinberger
84e54ab264 chore(pr): landing-UX — aggregated validation, lock classes, ci-dispatch, committer guard (#111287)
* chore(pr): landing-UX — aggregate artifact validation, lock classes, ci-dispatch, committer worktree guard

* fix(pr): CI lane cleanup for landing-ux — lint causes, hermetic tests, private helpers

* chore(deadcode): register pr-lib CLI entries in knip config
2026-07-19 02:09:55 -07:00
Peter Steinberger
2f00a417ed feat(gateway): session dashboard domain — board RPCs, ticketed widgets, dashboard tool, per-agent persistence (#110960)
* feat(gateway): add session dashboard domain

* test(gateway): cover board event guards

* fix(gateway): authorize board widgets with view tickets

* feat(boards): persist dashboards in agent databases

* test(boards): use tracked SQLite temp directories

* test(gateway): isolate board deletion lifecycle coverage

* fix(boards): harden widget view ticket bindings

* fix(boards): lazily ensure additive board schema

* fix(gateway): complete dashboard integration metadata

* fix(boards): satisfy generated integration checks

* fix(boards): align persistence with repository guards

* fix(boards): retain notice test reset

* fix(protocol): generate dashboard union models

* fix(boards): harden dashboard persistence and serving

* fix(boards): satisfy dashboard CI guardrails
2026-07-18 20:17:51 -07:00
Peter Steinberger
ced95b3fce refactor(discord): split message process runtime (#111119) 2026-07-18 19:04:30 -07:00
Peter Steinberger
968f9ad0f3 test(codex): split event projector suites (#111097) 2026-07-18 18:17:25 -07:00
Peter Steinberger
47afe8f88f refactor(discord): split message process tests (#111066)
* refactor(discord): split message process tests

* test(discord): register split suite lifecycle

* test(discord): keep process harness internals private
2026-07-18 17:49:19 -07:00
cxbAsDev
8899940d5a fix(cron): support current and session: targets in initial delivery resolution (#99115)
* fix(cron): support current and session: targets in initial delivery resolution

resolveInitialCronDelivery only checked sessionTarget === 'isolated' for
default announce delivery. All other cron paths (delivery-plan.ts:106-114,
normalize.ts:680-684, jobs.ts:288-298) already treat 'isolated', 'current',
and 'session:' as equivalent. This gap meant cron jobs created with
--session-target current or --session-target session:... would not get
default announce delivery at creation time.

Real behavior proof:
  Input:  sessionTarget='current', payload.kind='agentTurn'
  OLD:    undefined  <- missing default announce delivery
  NEW:    {mode:'announce'}  <- consistent with other cron code paths

Co-Authored-By: Claude <noreply@anthropic.com>

* test(cron): add typed initial delivery resolution tests for all session targets

* test(cron): document direct-service delivery contract and cover service callers

* refactor(cron): centralize detached-delivery-target predicate into shared helper

Extract isDetachedDeliveryTarget(sessionTarget, payloadKind) in normalize.ts
and use it from all three callers:

- normalizeCronJobInput (write-time default, normalize.ts)
- resolveCronDeliveryPlan (read-time default, delivery-plan.ts)
- resolveInitialCronDelivery (service-bypass default, initial-delivery.ts)

This removes the third manually synchronized copy that the original PR
added, addressing ClawSweeper P1 finding.

* fix(cron): align initial delivery targets

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* test(cron): consolidate initial delivery coverage

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* test(cron): keep delivery matrix type-safe

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* chore: keep release note in PR metadata

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-19 00:51:05 +01:00
Peter Steinberger
f7024690ac refactor(gateway): split chat handlers by workflow (#111022) 2026-07-19 00:35:42 +01:00
Peter Steinberger
64019bc0c2 refactor(ui): split lobster-pet into look/plans/element modules (#110816)
* refactor(ui): split lobster-pet into look/plans/element modules

Move existing behavior along appearance and seeded visit-planning ownership seams without changing runtime behavior.

Extract only the bounded logo stand-in, WebAudio chirp, and pure render-template helpers while keeping the state machine in the element. Remove the grandfathered max-lines suppression and baseline entry.

* style(ui): format lobster-pet split modules

* fix(ui): keep lobster split internals unexported, refresh i18n raw-copy baseline

knip flags the split's newly exported internals (strangerLookFor,
renderCrabSvg, lobsterPetSpriteStyle, LobsterPasserKind) — they have no
external consumers; the html-text raw-copy baseline is file-keyed, so the
sprite z/Z markup moving into lobster-pet-look.ts needs a regen.

* fix(ui): satisfy lint for the lobster-pet split (param reassign, max-lines)

* fix(ui): keep moved act-profile internals unexported
2026-07-18 20:02:24 +01:00
Josh Lehman
453444636c feat: bound transcript reads across replacements (#110374) 2026-07-18 11:41:39 -07:00
Peter Steinberger
e8566596e0 refactor(state): split openclaw-agent-db into focused modules under the line limit (#110707) 2026-07-18 15:04:57 +01:00
Peter Steinberger
e01a880084 refactor(state): split openclaw-state-db into focused modules under the line limit (#110666) 2026-07-18 13:47:57 +01:00
Peter Steinberger
f6de912efe refactor(update): split update-runner into focused modules under the line limit (#110664) 2026-07-18 12:52:54 +01:00
Peter Steinberger
0bbb862c55 fix(gateway): keep setup.detect off the event loop so health stays live (#110625) 2026-07-18 12:19:59 +01:00
Peter Steinberger
a068d38b66 refactor(plugins)!: remove experimental workspaces plugin (#110416)
* refactor(plugins)!: remove experimental workspaces plugin

* fix(doctor): remove retired workspaces plugin state

* refactor(doctor): settle retired-workspaces cleanup before legacy-state detect

* chore(i18n): leave workflow-owned locale artifacts to the locale refresh

* ci: retrigger after GitHub scheduling outage
2026-07-18 10:56:37 +01:00
Peter Steinberger
0d91b07f5b refactor(update): split update-command into focused modules under the line limit (#110550) 2026-07-18 09:51:00 +01:00
Peter Steinberger
bba71531a9 test(ui): split app sidebar suite (#110549) 2026-07-18 09:22:48 +01:00
Josh Avant
6def1a9c04 fix: prevent repeated tool-call IDs from poisoning sessions (#110518)
* fix(agents): pair repeated tool calls by occurrence

* docs: regenerate docs map
2026-07-18 00:49:40 -07:00
Peter Steinberger
a4ed1eb083 fix: show cloud-worker progress in sessions tail (#110460)
* fix: persist cloud-worker session trajectories

* chore: remove release-owned changelog edit
2026-07-18 07:19:08 +01:00
Peter Steinberger
723f5ba4fc improve(ui): restructure Settings around user-facing pages with full agent parity (#110445)
* refactor(ui): restructure Settings IA around user-facing pages

Settings sidebar shrinks to settings-only destinations grouped by attention:
General/Appearance/Notifications up top, Connections, Agents & Tools,
Privacy & Security, System. Sessions, Worktrees, Activity, and Memory
Import leave the takeover: Sessions/Activity return to the workspace
sidebar, Worktrees becomes a Sessions hub tab, Memory Import is reached
from the Agents memory panel. Model Setup becomes a Models subpage.

New config pages: Notifications (web push), Privacy & Security (curated
policy rows + security/approvals schema sections), Advanced (uncurated
schema sections + raw editor, replacing the General quick/advanced
toggle). General slims to model defaults, language, and gateway host;
identity moves to Profile, lobster appearance rows to Appearance.

* feat(agents): widen system-agent config writes to operator parity

Every config surface the Control UI can edit is now agent-writable behind
the exact-operation human approval gate, except a small documented
denylist ($include, auth, env, models, secrets). tools.* and
plugins.entries.* writes are allowed; plugin_uninstall works for plugins
that provably do not back the active default inference route (fail closed
otherwise); set_default_model takes an optional agentId and live-tests a
per-agent model with the same rigor as the default route. Per-agent
routing fields on non-default agents are direct-writable; the default
agent's route keeps the verified set_default_model/onboard paths. A new
config-write-parity contract test forces explicit classification of every
top-level config key.

* feat(ui): sync operator display prefs through config ui.prefs

Theme, theme mode, text scale, locale, and chat display prefs get a
canonical server-side home in config ui.prefs. The Control UI mirrors
them into localStorage for instant boot, writes local changes through to
the gateway (best-effort; viewer-scope or offline clients stay
device-local), and applies server-side deltas on connect and on every
config snapshot reload — so an agent changing the theme through the
approval gate takes effect in the UI, and prefs follow the operator
across devices.

* chore: prune quick.ts from max-lines baseline after slim-down

* style: oxfmt changed files

* chore: regenerate plugin-sdk api baseline for ui.prefs config surface

* fix: dedupe runPluginUninstall dep type and narrow locale extraction

* docs: update Control UI settings structure and ui.prefs sync

* fix: address autoreview findings on parity guards and prefs sync

- plugins.entries.* config writes get the same active-route ownership
  check as plugin_uninstall (fail closed when unprovable)
- system-agent prompt now describes the guarded write policy instead of
  the old blanket refusals
- per-agent set_default_model logs the agent-scoped label
- legacy /config?section=... deep links redirect to the Advanced page
- prefs sync: pushes coalesce and drain serially (no CAS races dropping
  updates), replaced config hashes mark pre-patch snapshots as stale, and
  the last-seen server value persists per gateway scope so reloads cannot
  revert unpushable viewer-scope edits
- lint: theme membership checks use Sets

* fix: harden uninstall route guard and scope prefs queue per gateway

- plugin uninstall ownership now covers execution owners (runtime policy,
  embedded harness override) in addition to the provider, and re-verifies
  inside the commit boundary so a concurrent route switch cannot slip a
  destructive uninstall past the pre-approval check
- prefs push queue binds to one gateway client; switching gateways drops
  the old queue (device-local fallback) instead of cross-writing prefs

* style: top-level type import in config-page test

* fix: close review races in config-write guards and prefs reconciliation

- config_set/config_set_ref re-verify the inference-route guard inside
  the commit boundary so conditional verdicts (per-agent routing, plugin
  entries) cannot be flipped by a concurrent edit after approval
- server prefs apply per changed field, so a server change to one pref
  no longer reverts unpushable local edits of the others
- replaced-hash staleness retires once post-patch state is observed, so
  a genuine restore of the pre-patch config becomes authoritative again
- moved-section deep links (communications notifications, automation
  approvals) redirect to their new pages

* style: satisfy no-useless-assignment and loop-condition lints in prefs sync

* fix(ci): resolve unhandled profile-test rejections and knip unused exports

The profile page's new identity section reads context.config; the test
context mock now provides it, eliminating the unhandled rejections that
failed checks-ui and the compact-large shard. Exports flagged by the
dependency gate (extract/patch helpers, section-key and prop types) go
module-private; extraction coverage moves behind applyServerUiPrefs.

* refactor(agents): move config-write policy to its own module

The static path classifier and documented denylist move to
config-write-policy.ts, shared by the execution guard and the parity
contract test — no test-only exports left for the dependency gate to
flag. Blocked-root refusals now cite the denylist's documented
escalation for that root.
2026-07-18 07:03:31 +01:00
Peter Lee
d1163dac16 fix(acp): persist spawn label to target session store instead of requester store (#106241)
* fix(acp): persist spawn label to target session store instead of requester store

When /acp spawn --label <name> creates a cross-agent ACP session (e.g.
from main into cursor or codex), the label was written to the requester's
store partition rather than the spawned session's store.  The write was a
silent no-op because the session key (agent:cursor:acp:<uuid>) did not
exist in the requester's store.  Follow-up commands like /focus <label>
and /acp status <label> then failed with "No session found with label".

persistSpawnedSessionLabel now resolves the canonical store path from the
spawned session key via resolveSessionStorePathForAcp before writing, and
only mutates the in-memory requester session store when both stores are
actually the same.

Fixes #106136.

* fix(acp): export resolveSessionStorePathForAcp for cross-store label persistence

* refactor(acp): extract spawn binding helpers to bindings.ts

* fix(acp): remove unused oxlint-disable after extracting spawn bindings

* chore(acp): prune stale max-lines baseline entry for lifecycle.ts

* test(acp): tighten cross-store spawn label coverage

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 06:55:44 +01:00
Peter Steinberger
a89f01abf4 perf(sqlite): fast schema gates, background integrity verification, and downgrade protection (#110271)
* perf(sqlite): gate schema version before integrity scans and quarantine terminal open failures

* feat(gateway): refuse incompatible database schemas at boot and verify integrity in the background

* feat(update): refuse installing builds that cannot open the current databases

* docs: add database schema reference with version history and downgrade guidance

* test(update): tolerate optional runner options in git-mutation mocks

* refactor(update): split npm package-target metadata out of update-check

* chore: model verifier internals for knip and regenerate docs map

* chore(i18n): resync stale iOS localization catalog

* chore: allowlist read-only preflight and verifier raw SQLite access
2026-07-18 05:49:39 +01:00
Peter Steinberger
b6bac30e33 refactor(agent-core): delete the unused session harness layer (#110287) 2026-07-18 02:27:48 +01:00