A local containment profile uses plugins.enabled=false to stop plugin and channel runtime churn. The previous startup path still built plugin lookup tables and doctor stale scans despite the global disable, which made the switch noisy and slow.
Constraint: plugins.enabled=false must leave channel blocker warnings intact while treating stale plugin config as inert.
Rejected: Clear user plugin config automatically | would mutate a reversible containment setting.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce plugin registry discovery before checking plugins.enabled.
Tested: pnpm test src/gateway/server-startup-plugins.test.ts src/config/plugin-auto-enable.core.test.ts src/commands/doctor/shared/stale-plugin-config.test.ts src/commands/doctor/shared/preview-warnings.test.ts
Tested: pnpm check:changed
Tested: pnpm build
* fix(agents): resolve model aliases in sessions_spawn
normalizeModelSelection() only trims the input — it never resolves
aliases through the model alias index. When a user passes an alias
like 'opus' to sessions_spawn, the child session gets patched with
the raw string, which the gateway cannot match to any provider.
Add resolveModelThroughAliases() to check bare strings against the
configured alias map before returning from
resolveSubagentSpawnModelSelection().
Fixes#57532
Refs #50736
* refactor: address review feedback on alias resolution
- Accept pre-built ModelAliasIndex instead of rebuilding per call
- Narrow helper signature to (string, ModelAliasIndex) → string
- Remove unreachable ?? raw fallback
Co-Authored-By: greptile-apps[bot]
* fix(agents): resolve sessions_spawn model aliases
---------
Co-authored-by: HowdyDooToYou <HowdyDooToYou@users.noreply.github.com>
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
End-to-end testing on macOS + BlueBubbles + ElevenLabs walked through three CAF flavors before landing on the format Apple's Messages.app actually emits when a user records a native iMessage voice memo:
- PCM int16 @ 44.1 kHz CAF: BlueBubbles' internal `afconvert -f m4af -d aac` conversion fails; the original CAF reaches iMessage but renders with 0 s duration.
- AAC @ 22.05 kHz mono CAF: BlueBubbles' conversion succeeds and the server silently downgrades the delivery, sending the converted MP3 as a generic audio attachment.
- **Opus @ 24 kHz mono CAF**: byte-identical to the descriptor block Apple's Messages.app produces; BlueBubbles passes it through unchanged and iMessage renders a native voice-memo bubble with proper duration and waveform UI.
Adds an opt-in `tts.voice.preferAudioFileFormat` channel capability and a macOS `afconvert`-backed pre-transcode in the speech-core pipeline. BlueBubbles declares `preferAudioFileFormat: "caf"`. Other channels are unaffected. Falls back to the original buffer when the host platform, the source/target pair, or the transcoder process can't produce the preferred container — so non-Darwin hosts and unsupported provider combinations are unchanged.
Also adds a `caff` magic-byte sniff in `src/media/mime.ts` so the auto-reply host-local-media validator (which uses `file-type` and didn't recognize CAF natively) accepts the buffer instead of dropping it as "⚠️ Media failed."
Fixes#72506.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>