Commit Graph

4968 Commits

Author SHA1 Message Date
Miorbnli 3a17d5993a fix: prevent $-pattern injection in prompt template and approval substitution (#123015)
* fix: prevent dollar-pattern injection in prompt template and approval substitution

Three call sites used String.replace/replaceAll with a string replacement
fed a runtime variable, causing dollar-amp/dollar-1/dollar-backtick
sequences in user-supplied args or approval ids to corrupt the rendered text.

Switch each to a function replacement so the value is treated literally:

- prompt-template-arguments: dollar-ARGUMENTS and dollar-@ substitution
  corrupted slash-command args containing dollar signs
- get-reply-inline-actions: bundle command template expansion had the
  same issue with normalizedArgs
- approval-reaction-runtime: approval id placeholder rendering mangled
  ids containing dollar signs; the iMessage sibling
  (extensions/imessage/src/approval-text.ts) already escapes this

* fix: rebase, drop unproven approval rewrite, add dollar regression

Address review: the approval placeholder helper has no canonical
/approve <id> producer in the plugin-SDK manual fallback path, so its
rewrite is unproven - revert it. Keep the two reachable prompt-template
fixes and add an owner-boundary regression covering literal dollar
sequences in dollar-ARGUMENTS and dollar-@ substitution (fails on the
old string replacement form, passes with the callback form).

* test(auto-reply): cover literal dollar bundle command arguments

* fix(agent-core): resolve prompt placeholders in a single substitution pass
2026-08-24 13:43:23 -07:00
Peter Steinberger 998128abd8 fix(reply): preserve distinct streamed location replies (#128846) 2026-08-24 13:28:09 -07:00
Ayaan Zaidi 5238648a3b fix(chat): show native commentary progress (#128793)
Preserve native provider commentary as keyed progress items across live delivery and history reloads while keeping cursor pagination reachable.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-24 17:58:26 +00:00
Peter Steinberger 12d0fd2ef8 refactor(anthropic): replace handwritten Claude sessions with Agent SDK (#128131)
* refactor(anthropic): explore official Claude Agent SDK runtime

* refactor(anthropic): replace handwritten Claude sessions with SDK

* refactor(anthropic): collapse SDK live-session ownership

* refactor(anthropic): simplify SDK ownership and preserve live skills

* fix(anthropic): fence cancelled SDK runs before process startup

* fix(anthropic): harden SDK approvals, lifecycle, and packaging

* refactor(anthropic): own SDK process trees and streamline runtime

* fix(anthropic): repair rebased packaging and legacy test fixtures
2026-08-24 01:59:16 -07:00
Peter Steinberger ccc4e69052 fix(subagents): hide private commentary from logs and completion announcements (#128584)
* fix(subagents): hide commentary in logs and completion announcements

* refactor(agents): remove obsolete test-only history sanitizer export
2026-08-24 00:57:53 -07:00
Peter Steinberger 3cb7f6330c fix(reply): preserve streamed audio delivery order (#128558) 2026-08-23 23:38:07 -07:00
samson1357924 3dd3003f49 fix(status): retry status runtime loads and contain render errors (Fixes #94626) (#94806) 2026-08-23 14:37:09 -07:00
Peter Steinberger e4bf242461 refactor(agents): consolidate generation and runtime fixtures (#128339) 2026-08-23 13:43:05 -07:00
Eden b5460ee697 fix(channels): attribute zero-payload turn warnings and stop false silent-drop alarms (#116486)
* fix: attribute zero-count channel turn warnings

* fix(replies): preserve routed delivery across abort

---------

Co-authored-by: Altay <altay@hey.com>
2026-08-23 17:53:55 +03:00
ClawSweeper a77fbdef33 fix(ui): recover queued follow-ups from settled runs (#126180)
* fix(ui): recover queued follow-ups from settled runs

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>

* fix(ui): preserve terminal client run ownership

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>

* fix(sessions): persist recovered terminal client runs

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>

* test(gateway): publish configured reply runtime

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>

* fix(protocol): refresh Swift session row

Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>

---------

Co-authored-by: Ian Moog <ianmoog42@gmail.com>
Co-authored-by: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com>
Co-authored-by: Roboclaw <roboclaw-bot@users.noreply.github.com>
2026-08-23 06:55:21 -07:00
Peter Steinberger 62cc06be84 fix(media): preserve filename-derived attachment classification (#128220) 2026-08-23 06:18:59 -07:00
Peter Steinberger 79e675521f fix(agents): prevent reloads from losing queued replies or restoring stale credentials (#128138)
* fix(agents): fence retired prepared runtime generations

* test(agents): prove queued turns survive credential reload
2026-08-23 01:10:00 -07:00
Josh Avant 40a6b50cc1 feat(audit): explain plugin and remote actions (#126027)
* fix(audit): converge action receipts after U2

* docs(agents): clarify receipt authority fencing
2026-08-22 14:06:54 -07:00
Vyctor H. Brzezowski a9e3b69750 fix(models): reuse prepared metadata during browse (#127847)
Channel `/models` now reuses the Gateway-prepared plugin metadata snapshot and visibility policy across model resolution, keeping browse responses responsive while preserving plugin-owned aliases.

Fixes #127379.
Reviewed-by: @shakkernerd
2026-08-22 21:59:57 +01:00
Vito Cappello 5ddf381eed fix(channels): preserve gateway context for inbound turns (#127962)
* fix(channels): preserve gateway context for inbound turns

* fix(plugin-sdk): type bound channel reply dispatcher

* fix(channels): carry bound reply dispatchers

* fix(channels): keep reply carrier internal

* fix(auto-reply): consolidate dispatcher type imports

* fix(channels): keep reply dispatch typing internal

* fix(channels): derive inbound reply dispatcher types from turn plan

Keep ChannelRuntimeSurface identical to main: adapters read the bound
dispatchReplyFromConfig through the existing PluginRuntime["channel"]
wiring type and derive its type from the public ChannelInboundTurnPlan
contract, so the compatibility surface no longer grows a Gateway-bound
reply member.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(channels): hoist bound channel runtime casts for assertion ratchet

The assertion-safety ratchet collects SAFETY comments with a plain
ts.Scanner pass, which desyncs at the first template literal with a
substitution — comments after that point in a file are invisible, so
deep casts in monitor files cannot be SAFETY-covered. Hoist one shared
cast per call-site scope (absorbing the pre-existing buildContext
casts) and retype Discord's internal channelRuntime chain as
PluginRuntime["channel"] so dispatch reads need no assertion.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(channels): verify gateway dispatcher ownership

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* test(codex): assert sequenced node process notifications

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* docs(changelog): preserve release-owned root changelog

Channel Gateway tools preserve the owning dispatcher for Telegram, Discord, iMessage, Signal, and WhatsApp so terminal tools remain available. Thanks @VACInc.

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* test(codex): avoid shadowing process notification bindings

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-22 13:44:47 -07:00
Vito Cappello 9837825948 fix(agents): preserve admitted runtime generation for channel turns (#127217)
* fix(agents): retain admitted runtime generation

* fix(agents): own admitted runtime generation scope

* style: format prepared runtime generation handoff

* fix(agents): resolve generation scope through a process-global singleton

* test(agents): prove admitted generation survives runtime replacement

* test(qa): prove admitted generation survives gateway replacement on ephemeral gateway

* fix(agents): drain queued follow-ups outside the admitted generation scope

Queued follow-up turns re-admit on the generation current at drain time.
The follow-up drain now leaves any ambient prepared-generation scope so a
parked turn can never inherit the predecessor run's replaced generation
through the embedded runner's ambient fallback.

* test(qa): prove queued follow-up drains on the replacement generation

Run the ephemeral-gateway proof in followup queue mode so the parked turn
becomes its own drained run, wait on the gateway's queued-run state instead
of a fixed delay, poll agent.wait through the queue phase, and always persist
the redacted gateway log.

* refactor(agents): simplify runtime generation regressions

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* docs(changelog): avoid concurrent release-note conflict

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* docs(changelog): leave release notes to maintainer closeout

Channel runtime replacement keeps active turns on their admitted Gateway generation while detached follow-up turns adopt the current generation. Thanks @VACInc.

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-22 13:26:36 -07:00
Jason O'Neal d0700b3bc2 fix(agents): heartbeat runs no longer block visible turns (#126853)
* fix(heartbeat): keep background runs off the main lane

* docs(queue): describe heartbeat background lane

* fix(agents): forward heartbeat lane to embedded fallback

* test(agents): prove heartbeat and visible lane overlap

* test(agents): expose heartbeat lane in embedded harnesses

* refactor(agents): keep heartbeat lane choice at fallback boundary

Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: sallyom <somalley@redhat.com>
2026-08-22 15:15:18 -04:00
Vincent Koc 7d18cc4ccb test(auto-reply): clean reply dispatch lifecycle (#127814) 2026-08-22 11:43:02 -07:00
Ayaan Zaidi 041938bc2f feat(ui): add a Claude CLI 200K/1M context-window switch to the model picker (#127951)
Adds a generic plugin-declared selectable-context-window surface mirroring thinkingLevels: ModelCatalogEntry.contextWindows + contextWindowDefault through catalog normalization and the gateway protocol, session validation on sessions.create/patch, and a 200K/1M switch inside the Control UI model picker for Claude CLI 5-series models. The Anthropic plugin owns the option mapping: explicit 1m → `[1m]` argv suffix, 200k → bare id + CLAUDE_CODE_DISABLE_1M_CONTEXT=1, omitted → bare id (shipped default argv). Run budgets follow the selection on both CLI and native paths, so a 200K session gets a matching auto-compact window instead of a silent 1M budget.

Review fixes landed in this PR: run-owner prepared-fact plumbing so ordinary replies honor the selection; atomic catalog overlay merge and normalization for the options/default tuple; one-owner tuple reads in the picker; sessions.create key-presence patch semantics; native-run budget capping.

Feature direction and in-picker switch shape by @obviyus (maintainer review).
2026-08-22 23:25:23 +05:30
ClawSweeper 8c1ea23826 fix: preserve internal reply images across gateway restart (#127729)
Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-21 21:03:58 -07:00
Peter Steinberger f048a4370d fix: deliver current-source media before acknowledging (#127737) 2026-08-21 18:47:26 -07:00
Josh Avant 67c06ed54f fix(memory): respect provenance in automatic context (#127469)
* fix: enforce memory provenance for automatic context

* fix: preserve memory provenance compatibility

* fix: repair legacy memory provenance before recall

* fix: fail closed for unsupported memory runtimes

* fix: record command memory exclusions

* docs: clarify memory provenance injection

* docs(memory): clarify bootstrap without a runtime
2026-08-21 18:44:40 -07:00
Josh Avant 0b85966072 fix gateway conversation route ownership (#126424) 2026-08-21 12:20:21 -07:00
Marvinthebored 1b998c0d84 fix: /restart restarts the gateway over and over instead of once (#127179)
The /restart command is dispatched from a durable channel ingress row. The
gateway begins its restart drain before that dispatch returns, so the row is
still claimed when root-work admission closes. The drain sees
GatewayDrainingError and releases the row without spending its retry budget
(#125918), which is correct for an ordinary message and wrong for a command
that caused the drain: the successor gateway claims the same row and runs
/restart again, forever. Every boot is clean, so the gateway looks healthy
throughout.

Adopt the ingress claim in the restart command handler before scheduling the
restart. The command is not idempotent, so losing the acknowledgement is better
than an unbounded restart loop. The drain's deferral branch is unchanged.

Co-authored-by: Marvinthebored <262704729+Marvinthebored@users.noreply.github.com>
2026-08-21 12:12:58 -07:00
xingzhou ee79b0a49a fix(channels): retry timed-out ingress messages (#127090)
Co-authored-by: PollyBot13 <pollybot13@gmail.com>
2026-08-21 11:25:27 -07:00
Peter Steinberger e7e1c53250 fix(auto-reply): surface missing final replies after progress updates (#127070)
* fix(auto-reply): distinguish follow-up progress from final delivery

* test(auto-reply): compact follow-up delivery evidence cases
2026-08-21 00:07:45 -07:00
Peter Steinberger 2ebd80cc96 fix: speech-only supplements silently complete agent replies (#126925)
* fix: keep supplemental speech from settling agent replies

* fix: tolerate malformed supplemental reply media
2026-08-20 18:48:44 -07:00
Josh Avant a042125170 fix(memory): preserve provenance across dreaming (#126489)
* fix(memory): preserve provenance across dreaming

* fix(build): preserve bundled hook metadata

* refactor(build): remove obsolete directory helper

* test(memory): align provenance fixtures

* test(memory): type consolidation run options

* test(memory): register write provenance siblings

* fix(memory): preserve legacy provenance registration

* fix(memory): make provenance provider-independent

* fix(memory): canonicalize provenance workspace keys

* fix(memory): keep provenance mutation host-private

* fix(build): track runtime postbuild implementations

* fix(build): verify bundled hook metadata outputs
2026-08-20 17:58:31 -07:00
Vincent Koc c19bdb3a1d fix(agents): preserve explicit harness runtime selection (#126259) 2026-08-21 06:32:23 +08:00
Dallin Romney 28568d0c12 test(acp): close owned state database exactly (#126746) 2026-08-20 10:34:25 -07:00
Peter Steinberger 3c5cecee06 refactor: compact recovery ownership and model metadata (#126751)
* refactor: compact recovery ownership and model metadata

* chore: respect release-owned changelog gate

* test: skip unsupported Windows permission assertions
2026-08-20 10:30:21 -07:00
Vito Cappello 46ed76e5e2 fix: unblock replies after recovery owner release conflict (#126507)
* fix: unblock replies after recovery owner release conflict

* fix(diagnostics): keep an unreclaimed active run as an observed skip

Removing the noop outcome left recoverStuckDiagnosticSession able to fall off
the end of its try block when an active run neither aborted nor released,
returning undefined from a Promise<StuckSessionRecoveryOutcome> (tsgo TS2366).
Report that residual path as skipped/active_embedded_run so the watchdog never
clears diagnostic state for work that still owns its session.

* fix(sessions): compare persisted row bytes in session-entry replacement CAS

The replacement projection snapshotted entries with the status/store readers
(no participant projection) and revalidated inside the transaction with
readExactSessionEntryRow, which merges session_participants into the entry.
Any row with a participant that is not its owner therefore serialized
differently on the two sides, so the compare-and-swap threw "SQLite session
entry changed before replacement" on every attempt with no concurrent write
at all. Startup orphan marking selects by status, so such a session could
never be repaired: it stayed status=running across restarts, its rotated
session id never persisted, and every later turn failed with "changed while
starting work", retried by the ingress spool for 24h.

Compare the persisted entry_json bytes on both sides, the same raw-bytes CAS
the sibling lifecycle and projection paths already use, so separately mutable
decorations (participants today, owner columns next) cannot invalidate a
logical-session write. Renames the raw reader to readExactSessionEntryJson
now that it is the general CAS reader rather than repair-only, and aligns
shouldRemoveSessionEntry with the participants-excluding equality its own
callers already use.

* fix(sessions): fail closed when a selected replacement row has no persisted bytes

The raw-bytes CAS could not distinguish "row unchanged" from "row gone". If a
selected row was deleted between hydrating the snapshot entry and reading its
persisted bytes, both the snapshot and the transaction read undefined, the
compare agreed, the transaction's source map stayed empty, and the stale
replacement was written back into the deleted key.

A selected key must hold bytes, so treat a missing snapshot read as the
conflict it is. Reported by ClawSweeper on the previous head.

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
2026-08-20 08:02:20 -07:00
Peter Steinberger 465043ca85 fix(acp): prevent lost prompts and preserve conversation bindings (#126657)
* fix(acp): enforce prompt and binding ownership

* test(acp): align execution-start boundary

* perf(startup): avoid broad ACP core import

* fix(acp): order prompt replacement admission
2026-08-20 07:03:11 -07:00
Vito Cappello 1b9d3ac57d fix(claude-cli): apply thinking and keep live sessions warm (#125528)
* fix(models): preserve CLI runtime thinking capabilities

* fix(models): preserve configured thinking overrides

* fix: keep Claude live CLI process warm across captured turns

MCP delivery capture no longer kills the warm Claude process after every
turn. Capture-key admission is fenced by grant activate/deactivate so
prompt-cache continuity can survive across messages.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(claude-cli): apply thinking levels

* fix(claude-cli): materialize thinking capabilities

* test(claude-cli): cover warm thinking budget reuse

* test(models): restore prepared catalog contracts

* fix(agents): restore catalog test boundaries

* fix(agents): break prepared catalog import cycle

* refactor(gateway): extract model-choice runtime resolution into public-projection module

Keeps models-list-result.ts under the max-lines cap after the origin/main
merge by moving resolveModelChoiceAgentRuntime next to the projection
helpers it feeds.

Claude-Session: https://claude.ai/code/session_01QXUQuDVataA5o16kxNnmoX

* test(claude-cli): cover thinking cache reuse

* test(claude-cli): cover captured live reuse

* fix(claude-cli): rotate MCP grants across live turns

* fix(anthropic): respect mandatory adaptive thinking

* fix(claude-cli): restore warm MCP bearer

* fix(anthropic): keep Mythos adaptive thinking

* test(claude-cli): prove live MCP cache reuse

* test(claude-cli): align live cache coverage

* fix(claude-cli): reuse live sessions across MCP grant rotation

* test(claude-cli): satisfy cache lane static gates

* fix(claude-cli): preserve runtime thinking policy

* fix(thinking): honor concrete runtime policy

* fix(gateway): honor mandatory thinking in model list

* refactor(auto-reply): extract prepared catalog merge

* docs(cli-backend): document thinking execution input

* refactor(auto-reply): extract catalog lookup helper

* style(auto-reply): format catalog helper import

* fix(claude-cli): stabilize live context budget

* fix(auto-reply): type prepared context metadata

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-20 06:44:49 -07:00
Peter Steinberger 584e750c16 fix(tui): route usage cost correctly (#126668) 2026-08-20 05:55:11 -07:00
Peter Steinberger c55d9b6d20 fix(agents): preserve terminal tool completion (#126603) 2026-08-20 02:01:36 -07:00
Peter Steinberger 980b07f4a2 refactor(agents): replace tool-failure warning heuristics with a two-rule policy (#126542)
* refactor(agents): reduce tool failure warnings to two rules

* test(agents): remove obsolete tool recovery receipt proof

* refactor(agents): drop unused meta param from buildToolMutationState

* test(agents): remove stale tool warning assertions

* test: export runtime source snapshot from closed runtime-snapshot mocks

Heal the main breakage introduced by 9441e3fe6e / #126531, which added a runtime source-snapshot read to provider model route resolution. Closed Vitest factories now return null for that source snapshot, preserving their pre-projection behavior.

* test(gateway): make compaction read-error faults order-immune

Generation-2 CI failure in run 32342180898, job 96343444772 showed that the mock factory initialized while shared gateway-server importers remained bound to the real transcript reader.

The dedicated isolated project fixes normal shards. Complete its ownership by adding it to the root project matrix and excluding the test from the non-isolated OPENCLAW_GATEWAY_PROJECT_SHARDS=0 fallback.
2026-08-20 01:11:05 -07:00
Peter Steinberger 4d6c40ae30 fix(replies): settle pre-aborted delivery immediately (#126582) 2026-08-20 00:44:03 -07:00
Peter Steinberger 966c233dcc refactor(sessions): remove thinking selection provenance (#126561)
* refactor(sessions): remove thinking selection provenance

* test(gateway): fix shared-worker reasoning cleanup

* test(gateway): avoid shared-worker merge overlap
2026-08-20 00:38:45 -07:00
Peter Steinberger efc33f882e fix: preserve GPT-5.6 Max and Ultra through Codex (#126492)
* fix(agents): preserve GPT-5.6 thinking capabilities

Carry harness-owned effort metadata from the prepared catalog to the final executable model without leaking it across model or harness changes. Preserve exact GPT-5.6 registry metadata and persisted Ultra selections across route-scoped projections.

* fix(agents): resolve ambient catalog owner

* test(commands): mock thinking hydration policy

* fix(sessions): validate persisted thinking selections

* fix(commands): persist thinking selection provenance

* fix(agents): scope thinking hydration per fallback

* fix(sessions): hide fallback thinking provenance
2026-08-19 21:48:18 -07:00
Ayaan Zaidi ade0fb2189 fix(auto-reply): restore ambient room event silence (#126527)
Restore intentional silence for undirected room events while retaining visible-answer recovery for mentions, commands, and ordinary requests.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-20 09:26:40 +05:30
Peter Steinberger 53bd316553 fix(telegram): finalize streamed questions in place (#126248)
* fix(telegram): finalize streamed questions in place

* test(telegram): align partial question delivery coverage

* fix(telegram): propagate partial question finalization

* test(telegram): assert typed partial delivery error
2026-08-19 19:15:46 -07:00
Peter Steinberger 19316660e4 fix(agents): consolidate ambient owner resolution (#126504) 2026-08-19 18:54:32 -07:00
Peter Steinberger 2fe6c0206d fix(discord): retain attachment-only reply context (#126204) 2026-08-19 15:55:55 -07:00
Jason (Json) beb466df3c fix(sessions): preserve resolved context in cold projections (#126422)
* fix(sessions): preserve resolved context in cold projections

* fix(sessions): preserve verified context provenance

* test(sessions): complete context metadata fixture

* fix(sessions): version verified context resolution
2026-08-19 16:34:20 -06:00
Peter Steinberger 7e0b599ca4 fix: surface Codex input prompts across runtimes (#126387)
* fix: surface Codex input prompts across runtimes

Codex structured input now reaches bounded Gateway questions in native and ACP runs, with exact turn ownership, explicit unsupported outcomes, and cancellation fencing. Consume the published ACPX elicitation support.

* chore: align elicitation helpers with current guards

Use protocol-specific helper names required by current main and update the reservation regression to the generalized input owner.

* fix: formalize structured input SDK surface

Expose one documented, frozen agent-harness structured-input contract with runtime and subpath coverage, replacing the accidental function-property API.

* fix: satisfy elicitation architecture gates

Register the real-process ACPX fixture as an executable test root and move shared structured-input types into the boundary leaf to keep Knip and Madge clean.

* fix: remove structured input lint suppression

Preserve the rejected control and invisible-character ranges with an explicit code-point check so the production suppression inventory stays closed.
2026-08-19 15:25:33 -07:00
Jason (Json) 45b8750d8b fix(compaction): default maintenance reasoning to low (#126421)
* fix(compaction): default maintenance reasoning to low

* test(compaction): cover explicit inherit fallback

* test(compaction): preserve inherit literal type
2026-08-19 16:18:06 -06:00
Peter Steinberger 61d217fd2a fix: stop routing IDs from masquerading as delivery receipts (#126385)
* fix(channels): separate routing from receipt identity

Routing identifiers no longer fabricate message delivery evidence; provider-canonical thread placement is preserved.

* fix(channels): preserve conflicting receipt threads

Keep aggregate thread placement absent when provider receipt parts disagree, even when a requested route thread is available.
2026-08-19 11:33:16 -07:00
Peter Steinberger 0606e31d0e feat(gateway): broker GitHub publication (#126306)
* feat(gateway): broker GitHub publication

* refactor(gateway): split publication owners

* fix(gateway): enforce publication branch authority

* fix(gateway): bind publication to remote identity

* fix(gateway): bind publication recovery to remote state

* fix(gateway): preserve publication git state

* fix(gateway): retain publication recovery authority

* fix(gateway): commit publication index atomically

* fix(gateway): narrow publication index errors

* refactor(gateway): keep publication CAS errors private

* fix(gateway): recover publication index transactions

* fix(agents): describe GitHub publication tool

* fix(gateway): harden publication base fetch

* fix(gateway): reject publication filter semantics

* fix(gateway): verify publication creation base

* refactor(agents): align publication tool options

* fix(gateway): isolate publication object lineage

* refactor(gateway): use shared table probe

* test(gateway): keep publication helpers in routed suite

* perf(ui): lazy-load GitHub publication request

* fix(gateway): preserve publication support contracts

* fix(gateway): recover publication before authority checks

* fix(gateway): fence local publication snapshots

* fix(android): format generated protocol models

* fix(gateway): harden publication recovery

* fix(gateway): fence publication recovery

* fix(ui): reset completed publication cycles
2026-08-19 11:05:12 -07:00
Peter Steinberger 3e0c980aaf fix(models): honor per-agent model metadata (#126194)
* fix(models): honor per-agent model metadata

Resolve per-agent aliases, bare providers, fallbacks, and catalog tags consistently across runtime, CLI, Gateway, sessions, and the Control UI.

* fix(models): preserve projection ownership

* fix(models): carry agent scope through fallbacks

* test(models): complete compaction fallback mock

* test(models): complete startup fallback mock

* test(agents): isolate recovery id expectations

* refactor(protocol): split public schema barrel

* test(cron): await child readiness events

* fix(models): scope native catalogs to session agent

* perf(ui): tighten agent model option projection

* perf(ui): reduce agent model projection overhead
2026-08-19 06:04:24 -07:00