Commit Graph

4783 Commits

Author SHA1 Message Date
SunnyShu 9594fe4623 fix(media): retain readable images from partial batches (#122361)
Keep readable native images when another attachment fails resolution.
Suppress only unresolved media facts across persisted and transient runner paths.

Co-authored-by: SunnyShu0925 <shu.zongyu@xydigit.com>
2026-08-12 21:57:31 +05:30
Peter Steinberger c23d66e3b5 refactor: consolidate coercion ownership (#122692)
* refactor: consolidate coercion ownership

* test: align shard check with weighted planning

* chore: refresh plugin SDK API baseline
2026-08-12 09:25:28 -07:00
Vincent Koc 9b90e104c5 fix(tts): preserve hidden-only tagged fallback text (#122608)
Punchcard-Session: golden-brook-lantern-zw
2026-08-12 21:18:15 +08:00
James Tatum 5235269b3c fix(agents): heartbeats lose all conversation context on claude-cli chat↔heartbeat transitions (#121509)
* fix(agents): resolve session-stable reply mode for direct resolver turns

Heartbeat wakes and other direct getReplyFromConfig callers bypass
dispatch, so no session-stable delivery mode reached their CLI binding
facts and prepare computed no messageToolPolicyHash, while dispatched
chat turns hashed the stable mode. resolveCliSessionReuse treats that
one-sided hash as a policy change, hard-invalidating the binding on
every chat<->heartbeat transition and leaving heartbeats to run in
fresh CLI sessions with no conversation history (historyPrompt=none).

Extract the synthetic-turn stable-mode resolution that
prepareAgentCommandExecution already used into
resolveSessionStableReplyMode, and apply it in prepareReplyRunContext
whenever a synthetic turn arrives without dispatch's injected mode, so
every turn kind on a session derives the same binding facts and hash.

Fixes #121485

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

* fix(agents): derive synthetic binding facts from the dispatch policy owner

Consolidate the synthetic-turn stable-mode resolution onto dispatch's own
policy pieces instead of a simplified parallel resolver:

- resolveVisibleRepliesPolicy is extracted from dispatch prepare-context
  (configured visible-replies guard + harness default chain) and shared, so
  the fallback and dispatch cannot drift on harness defaults, live-vs-entry
  chat facts, or ExplicitDeliverRoute.
- The stable fact now applies dispatch's messageToolAvailable downgrade via
  the canonical tool-policy resolvers: tool-only delivery with a policy-denied
  message tool records automatic, matching dispatch.
- Synthetic turns no longer fall back to their effective turn mode: a
  response-tool heartbeat's message_tool_only is per-turn enforcement, not
  session policy, and previously bypassed the stable fallback entirely.

Regression coverage: response-tool heartbeat facts match dispatched turns,
and a message-tool-denied config downgrades the synthetic stable fact.

Refs #121485

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

* fix(agents): keep the session-stable reply mode sender-independent

Dispatch's stable-mode downgrade used the turn's sender-aware message-tool
availability, so a sender-scoped message denial hashed the stable policy as
automatic on chat turns while sender-less synthetic turns hashed tool-only —
the same binding reset loop on another axis.

resolveStableMessageToolAvailability becomes the one sender-independent
owner: dispatch passes it as sessionStableMessageToolAvailable for the
stable-mode resolution only (effective per-turn enforcement keeps the
sender-aware verdict), and synthetic binding facts already consume it.
Computed only when the visible-replies candidate is message_tool.

Refs #121485

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

* fix(agents): derive stable reply facts from session surfaces, not wake plumbing

Third-pass review fixes on the #121485 consolidation:

- Strip system-event wake providers ("heartbeat", "cron-event") from the
  stable context and resolve origin-less entries as internal, so synthetic
  facts take the same internal-channel branch dispatch's live webchat turns
  do instead of falling through to harness defaults.
- Fall back to persisted session facts (delivery channel/origin, groupId,
  groupChannel/subject, accountId) for the sender-independent availability
  stack, so bare-ctx callers like command prepare resolve the same
  group/account-scoped policies as dispatched turns; dispatch now passes its
  session entry too.
- Collapse the redundant second mode resolution into the availability
  downgrade, surface dispatch's injected stable mode separately from
  resolvePromptSourceReplyMode so the synthetic slot has one owner, and
  reuse resolveTurnModelOverride instead of an inline copy.
- Refresh docs/.generated/plugin-sdk-api-baseline.jsonl: closure hashes only
  (17 exports, zero declaration changes, verified) — plugin-sdk reply/meeting
  entrypoints transitively bundle the reply pipeline this branch refactors.

Regression: origin-less entry heartbeat resolves internal-automatic facts.

Refs #121485

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

* chore: adapt to main module moves and split API baseline

Mechanical rebase refresh onto d3696f8d76: subagent-capabilities moved to
src/agents/subagents/spawn/, and the plugin-sdk API baseline is now
per-entrypoint content hashes (#122082) — regenerated for the reply-pipeline
closure this branch touches.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-12 16:25:38 +05:30
Ayaan Zaidi 1fd7eedb33 fix(media): let sandboxed agents read staged documents (#122490)
Use successful per-attachment staging results in unsupported-document guidance so sandboxed agents receive only workspace-readable paths. Failed or partial staging keeps the existing fallback.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-12 12:22:35 +05:30
Peter Steinberger 59ea107d09 refactor(agents): delete dead model-selection surface and consolidate compaction targets (#122474)
* refactor(agents): delete dead model-selection surface, consolidate compaction target assembly

Removes production surface with zero live callers: buildConfiguredAllowlistKeys
(orphaned since fallback allowlist filtering was split out), the
retryTransientProviderRuntimeMiss resolveModelAsync option (its gateway startup
prewarming caller was replaced by prepared runtime snapshots), the ignored
useAsyncModelResolution plumbing (kept only as a deprecated no-op field on the
plugin-SDK-shipped prepareSimpleCompletionModelForAgent), and dead facade
re-exports (inferUniqueProviderFromCatalog, ThinkLevel, ModelRefStatus).

Consolidates resolveEmbeddedCompactionTarget's five hand-built result sites into
one assembleTarget helper owning the auth-profile-drop-on-provider-change rule;
resolution precedence is unchanged and now pinned by new table-driven cases
(unique-provider inference, ambiguous literal, profile-suffix preservation).

Net -93 production LOC, -106 test LOC.

* chore(sdk): regenerate plugin SDK API baseline after facade export removals
2026-08-11 23:37:15 -07:00
Peter Steinberger 0b4701677b test(core): remove residual duplicate cases (#122487) 2026-08-11 23:34:31 -07:00
Peter Steinberger b080dd1e76 refactor: consolidate coercion contracts (#122458)
* refactor: consolidate coercion contracts

Centralize exact string, record, numeric, date, Boolean, argument, and structured-error coercions while preserving call-site semantics.

Migrate canonical-name collisions and deprecated internal SDK bypasses, deleting 55 net production/tooling lines. Expand declaration ownership enforcement to 101 allowed helpers and add a narrow export-completeness audit.

* fix: preserve standalone script coercions

Keep copied Control UI tooling self-contained and retain the trusted release harness module-relative source seam when the harness runs against an old target cwd.
2026-08-11 23:26:37 -07:00
Ayaan Zaidi dbb9665e7e fix(discord): let active turns receive steering (#122452)
Remove Discord's duplicate whole-turn session serialization so corrections reach shared reply admission and steer the active run. Preserve shared steer, followup, collect, and interrupt behavior.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-12 06:18:55 +00:00
Ayaan Zaidi b8ddddd702 feat(media): let agents inspect unsupported local documents (#122408)
Let eligible embedded host runs inspect root-approved unsupported documents after final sandbox, filesystem, provider, owner, and tool-policy gates. Generic ACP, sandboxed, URL-only, and restricted-tool paths retain the plain marker.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-12 11:42:24 +05:30
Ayaan Zaidi ec4ae78b75 fix(agents): generate session titles with runtime-owned auth (#122163)
Use the selected harness for isolated title generation, including native Codex auth.
Retry failed dashboard titles from the first user message without overriding manual names.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-12 09:42:16 +05:30
joshavant 1079ccf41d fix: preserve custom debounce completion progress 2026-08-11 22:27:11 -05:00
joshavant d4f8553a0c fix: retry debounced ingress failures before adoption 2026-08-11 22:27:11 -05:00
Peter Steinberger 964c8c84c1 refactor: consolidate coercion ownership (#122299)
* refactor: consolidate coercion ownership

Centralize four canonical coercion helpers, migrate exact core and plugin duplicates through narrow Plugin SDK facades, and enforce declaration and plugin-normalization ownership boundaries.

The sweep adds eight focused SDK exports while deleting more production and tooling code than it adds. User-visible behavior is unchanged except for safer equivalent object and UI parsing at existing boundaries.

* fix: guard integer option ownership

Register resolveIntegerOption with the canonical function owner and extend the declaration-guard fixture so future local duplicates fail validation.

* fix: keep integer helpers on numeric facade

Remove the unshipped duplicate string-coerce exports and route every affected plugin consumer through the existing number-runtime contract.

* fix: point numeric coercion to number runtime

Make boundary and declaration diagnostics recommend the canonical numeric facade, with failing-before coverage for both guidance paths.
2026-08-11 17:14:53 -07:00
Vincent Koc f30e67298a fix(agents): preserve reply cleanup when cancellation throws (#122252)
* refactor(agents): canonicalize reply abort cleanup

* refactor(agents): document reply abort cleanup invariant
2026-08-12 07:04:03 +08:00
Peter Steinberger b350f76484 fix(channels): preserve failed agent run reactions (#122009) 2026-08-11 15:26:44 -07:00
Peter Steinberger 87b3c0e5df refactor(agents): split subscribe leaf ownership (#122249)
* refactor(agents): split embedded tool result ownership

* refactor(agents): split embedded message ownership
2026-08-11 15:04:07 -07:00
Mariano edb7a1692e fix(telegram): expose live location updates to hooks (#122185)
* fix(telegram): expose live location updates to hooks

* test(telegram): keep location coverage focused

* fix(telegram): emit stopped live locations

* test(plugin-sdk): refresh location hook contracts

* docs(changelog): note Telegram live location hooks

* fix(telegram): complete live-location observer path

---------

Co-authored-by: mbelinky <mbelinky@users.noreply.github.com>
2026-08-11 23:26:23 +02:00
Ayaan Zaidi 6a4a546593 feat(mcp): per-requester OAuth for MCP servers (#122166)
Per-requester OAuth for HTTP MCP servers: in shared channels each trusted sender connects their own account. New config: mcp.servers.<name>.oauth.identity ("shared" default, byte-identical behavior) and gateway.publicOrigin (HTTPS except loopback) for the new GET /oauth/mcp/callback served on the Gateway HTTP server. Requester tokens are isolated per (channel, account, sender) in mcp_oauth_stores rows (no schema bump); callbacks correlate through a durable state-keyed one-time index with a 10-minute TTL; per-requester servers are fail-closed out of static/scheduled runtimes; unauthenticated senders get a sign-in link with a portable URL button; MCP config mutations clear requester credentials at the canonical owner. mcp status --json keeps the legacy authStatus fields additively. Proven by a two-user self-hosted-Executor E2E through the real gateway callback. Part of #122034.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-11 20:58:51 +00:00
Peter Steinberger e74be5d41d refactor: eliminate final wrapper-shadowing hazards (#122157)
* refactor: disambiguate wrapper-shadowed exports

* test: align renamed session and facade boundaries

* test: cover renamed runtime mock exports

* refactor: align remaining wrapper owner call sites

* test: align overlap-rebased runtime mocks

* refactor: preserve public SDK names after overlap rebase

* chore: regenerate wrapper shadowing baselines

* test: align cron model selection mocks
2026-08-11 13:34:24 -07:00
Alix-007 d76f71cee7 fix(auto-reply): omit heartbeat inbound metadata (#122075)
* fix(auto-reply): omit heartbeat inbound metadata

Prevent synthetic heartbeat routes from appearing as user-role Conversation info while preserving delivery routing. Fixes #97067. Reported by @xxtyyq.

* test(auto-reply): use complete heartbeat model state

* test(qa): prove heartbeat metadata boundary

* test(auto-reply): deduplicate heartbeat metadata coverage

Co-authored-by: Alix-007 <li.long15@xydigit.com>
Punchcard-Session: frost-cedar-harbor-2n

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-08-12 03:02:22 +08:00
Peter Steinberger 3d76246792 refactor: eliminate final export name collisions (#122083)
* refactor: resolve final export name collisions

* refactor: update remaining collision rename consumers

* style: format rebased auth helpers

* test: update remaining session entry mocks

* test: update remaining runtime mock exports

* test: update delivery info path mock

* refactor: reconcile combined collision sweeps

* chore: regenerate collision and sdk baselines
2026-08-11 11:18:24 -07:00
Peter Steinberger ebb2770000 refactor: eliminate export name collisions (#122084)
* refactor: eliminate export name collisions

* chore(scripts): burn resolved collision baselines

* refactor: narrow legacy session load options

* chore: refresh SDK and session debt baselines

* refactor: adopt upstream secrets collision fix

* test(plugin-sdk): mock renamed session store core

* fix(scripts): track renamed session accessor core
2026-08-11 10:41:50 -07:00
Peter Steinberger eef860d972 feat(ui): unify system notices in chat with a minimal line family (#122144)
* feat(ui): unify system notices in chat with a minimal line family

Class A (model-facing system turns: restart recovery, gateway restarted,
generic internal_system fallback) and class B (lifecycle facts: compaction)
now share one hairline+icon+label rendering; known kinds show operator
summaries instead of raw injected prompts. Core producers share one
formatSystemTurnPrompt owner for the [System] prefix; subagent resume copy
unified from "gateway reload" to "gateway restart". No protocol, channel,
or marker changes.

* fix(ui): keep system-turn prompt helper out of the plugin SDK surface

Relocate formatSystemTurnPrompt to src/sessions/system-turn-prompt.ts so the
core-internal [System] convention does not widen the SDK API baseline; drop
the unused prefix/type exports; use var(--cursor-action) per cursor policy.
2026-08-11 10:24:38 -07:00
Peter Steinberger cad77fb39c refactor: consolidate remaining coercion helpers (#122020) 2026-08-11 10:22:01 -07:00
Peter Steinberger 76ab9a751a fix(agents): treat observed CLI activity as replay-unsafe for whole-turn retries (#122153) 2026-08-11 10:13:52 -07:00
Ayaan Zaidi 82ba647673 fix(media): record per-attachment media dispositions and render bounded skip markers (#122098)
Inbound image, audio, and video attachments could vanish with no recorded outcome and no model-visible explanation: attachments dropped by first-only selection, disabled or unconfigured capabilities, stage failures, URL-only images, and ACP-undelivered images all left the model unaware the media existed. Fixes #122044; completes the outcome custody started for documents in #122025.

Media capabilities now record one closed disposition per pre-truncation candidate at the decision site that owns the reason, with a memoized lazy native-vision probe (fires only when a marker could render; failure yields unknown and never alters outcomes; explicit image models never pay a catalog lookup). One late reader renders bounded, actionable markers from recorded facts only: native-vision and ACP-delivered images suppress per verified index, recorded failures always render, and document plus media markers share one five-marker budget with a reason-neutral overflow summary. The shipped SDK decision type stays additive (optional dispositions map).

Proof: 906 + 103 focused tests including nine adversarial-review regressions, ClawSweeper local review clean (round 9, zero findings, security cleared), live Telegram image drive showing ref preservation with no false marker.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-11 16:52:32 +00:00
emma300es b45ddf2754 fix(heartbeat): keep failed work pending after alerts (#118488)
* fix(heartbeat): keep failed work pending after alerts

Treat visible runner-failure notices as failed heartbeat turns, preserving queued cron and exec events plus prior heartbeat dedupe state for a later successful run.

Co-authored-by: Emma <297947720+emma300es@users.noreply.github.com>

* fix(heartbeat): narrow failure reply payload

* fix(heartbeat): preserve failure reply privacy

* fix(heartbeat): isolate suppressed failure payloads

* refactor(heartbeat): keep terminal failure type private

* fix(heartbeat): consume terminal failure type

* refactor(heartbeat): keep terminal status internal

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Emma <297947720+emma300es@users.noreply.github.com>
2026-08-11 09:28:42 -07:00
Peter Steinberger 8f61ec4120 test(agents): add CLI-backend fault-sequence boundary coverage (#122092) 2026-08-11 08:54:08 -07:00
Peter Steinberger db73b59c04 refactor: burn wrapper shadowing baseline entries (#122040)
* refactor: burn wrapper shadowing entries

* chore: refresh wrapper shadowing baselines

* test: update secrets runtime state mocks

* fix(ci): absorb Control UI build identity variance
2026-08-11 08:24:03 -07:00
Peter Steinberger e390781534 refactor: burn cross-directory export name collisions (#121893)
* refactor: name subsystem logger exports

* refactor(test): distinguish exported test doubles

* refactor: consolidate canonical owner helpers

* refactor: give cross-domain helpers distinct names

* chore(lint): ratchet collision debt baselines

* fix(test): complete collision rename consumers

* fix(test): update remaining collision mock consumers

* fix(test): update transcript reader mock export

* refactor: keep embedded logger name at its owner

* fix(test): align embedded logger mock with owner

* refactor: name shared assistant phase extraction

* fix(ui): update assistant phase extractor import

* chore(generated): refresh collision and SDK baselines

* style(test): format merged plugin mocks

* chore(sdk): refresh API content hashes
2026-08-11 06:50:22 -07:00
Peter Steinberger dd55770715 fix(channels): preserve plugin reply suppression across delivery paths (#121159)
* fix(channels): preserve reply transform suppression

* test: split ACP channel transform coverage

* chore: refresh plugin SDK API baseline
2026-08-11 06:28:20 -07:00
Peter Steinberger 02e8470bb8 refactor: burn SDK export collision debt (#121888)
* refactor: burn SDK export collision debt

* chore: regenerate collision debt baselines

* fix: update durable delivery core import

* fix: remove stale channel metadata type import

* fix: preserve config write SDK parameter type

* fix: preserve chat metadata SDK return type

* chore: refresh plugin SDK API baseline

* test: update plugin enable mock import

* fix: remove duplicate status helper re-export

* fix: preserve strict QA runtime availability errors
2026-08-11 05:06:11 -07:00
Peter Steinberger 992126e382 refactor(sessions): drop the Sqlite infix from session-accessor exports (#121536)
* refactor(sessions): drop the Sqlite infix from session-accessor exports

The storage-neutral seam completed its file->SQLite swap on 2026-07-27;
the Sqlite-infixed export names and their X-as-Y rename blocks were the
fossil of that migration, giving every accessor operation two greppable
names. Rename ~148 exports to their canonical names at the definition
sites, delete the message-cut facade (its conflict->failed mask had one
consumer, which already handles conflict), collapse the remaining pure
delegates, and keep honest SQLite-mechanics names (scope resolution,
canonical repair, in-transaction primitives, storage-row types). The main
barrel's exported surface is byte-identical. Net -203 production LOC.
Part 2 of the session-accessor dual-layer collapse (part 1: #121316).

* fix: repair main-breaking lint/type/test failures blocking PR CI

Three breakages landed on main that push CI's changed-scope never runs:
a caught-error cause missing in the release-validation script and two
type errors in the package-acceptance test (direct commit 1f591bba56),
and a memory-host regression where fs-safe 0.5.4 (#121508) started
throwing FsSafeError("not-file") for extra-path reads whose parent chain
hits a regular file, breaking the missing-file empty-text contract that
rejection unchanged.

Item 4 repairs managed-image action E2E narrowing from bad30d5a74 (#77017).
Item 5's chat-message mock repair was superseded upstream by 750d0dcd9e, whose broader fetch typing and explicit download capture preserve the same contract.
Item 6 restores #121258's cursor token contract after #77017 hard-coded pointer.
Item 7's managed-image thumbnail-path repair was superseded upstream by 750d0dcd9e, which preserves the same contract in main's reorganized URL structure.
Item 8 records #121600's explicit command-bearing lifecycle classification.
Item 9's cron assertion repair was superseded upstream by 3cd034f7a8, whose exact diagnostic rewrite includes the same redacted alert contract.
Item 10 forwards fs-safe 0.5.4 bigint lstat options through the snapshot mock.
Item 11 refreshes release-matrix test ownership after 1f591bba56.
Item 12 awaits f3e1efead48's setup-admission settlement in direct session tests.
Item 13's media FileStore-key repair was superseded upstream by cf432ec871, which fixes the same Windows root cause at the owner boundary.
Item 14 regenerates Swift approval reviewer fields added by 9935ca3b30.
2026-08-11 11:13:29 +00:00
Peter Steinberger bcaec0cf14 fix: resume main sessions after gateway restarts (#121969)
* fix(agents): always resume main sessions after restart

* fix(ui): render internal messages as system rows

* docs: update gateway restart recovery semantics

* refactor(sessions): simplify restart hook checkpoints

* refactor(agents): consolidate restart recovery claims

* test(agents): update delivery recovery revision guard

* fix(plugin-sdk): preserve restart hook state contract

* fix(ui): localize system row label

* test(agents): remove obsolete recovery import

* test(agents): align abort-code propagation with always-resume recovery

* fix(ui): share notice-aware turn boundaries

* test(agents): reconcile restart recovery ownership

* fix(ci): reconcile rebased recovery and UI checks
2026-08-11 04:01:34 -07:00
Peter Steinberger bef753b278 refactor(agents): split reply-run registry into concept modules (#121995) 2026-08-11 03:38:54 -07:00
joshavant e5be751e4f fix(auto-reply): align CLI fallback delivery 2026-08-11 05:00:17 -05:00
joshavant 4ad392abe7 refactor(auto-reply): centralize source delivery state 2026-08-11 05:00:17 -05:00
joshavant cde0af4c60 test(auto-reply): isolate prepared harness delivery proof 2026-08-11 05:00:17 -05:00
joshavant 7582e24aba fix(auto-reply): preserve post-compaction prompt context 2026-08-11 05:00:17 -05:00
joshavant ba97cd010a fix(auto-reply): align prepared delivery prompts 2026-08-11 05:00:17 -05:00
joshavant 174800da0e fix(auto-reply): classify implicit delivery defaults 2026-08-11 05:00:17 -05:00
joshavant 3d6debad13 fix(auto-reply): seal prepared delivery ownership 2026-08-11 05:00:17 -05:00
joshavant eacf6774fa test(auto-reply): align prepared harness proof with SQLite sessions 2026-08-11 05:00:17 -05:00
joshavant 3d6028da4c test(auto-reply): prove prepared ownership through queue params 2026-08-11 05:00:17 -05:00
joshavant 375df347c4 fix(auto-reply): apply prepared delivery before streaming 2026-08-11 05:00:17 -05:00
joshavant 1d1a7fa499 fix(auto-reply): keep prepared delivery ownership internal 2026-08-11 05:00:17 -05:00
joshavant d1ea4ac491 test(auto-reply): prove prepared harness delivery owner 2026-08-11 05:00:17 -05:00
joshavant 3cb3f1e426 fix(auto-reply): bind delivery to prepared harness 2026-08-11 05:00:17 -05:00
joshavant 33a2daf2ba fix(auto-reply): preserve fallback harness delivery owner 2026-08-11 05:00:17 -05:00