Earlier draft used a simple normalize-and-fall-through resolver: any
empty/whitespace per-chat_id systemPrompt fell through to the
groups['*'] wildcard. That doesn't match the WhatsApp resolver
(extensions/whatsapp/src/system-prompt.ts), where defining the
systemPrompt key on the specific group (even as '') means 'this group
has no prompt' and suppresses the wildcard.
Make iMessage resolution byte-identical:
- specific != null && specific.systemPrompt != null -> use the trimmed
specific (empty trim -> undefined, wildcard suppressed).
- otherwise -> trimmed wildcard.
Add the resolver as a small exported helper resolveIMessageGroupSystemPrompt
so the unit tests cover it directly. Update the per-group systemPrompt
doc section in docs/channels/imessage.md to copy WhatsApp's resolution
hierarchy language and add an explicit-suppression example.
Refs #78285.
channels.imessage.groups.<chat_id|*>.systemPrompt is now resolved at
inbound time and forwarded as ctxPayload.GroupSystemPrompt for group
messages, matching the established pattern in Discord, Telegram, IRC,
Slack, GoogleChat, and the retired BlueBubbles channel.
- Add 'systemPrompt?: string' to the channels.imessage.groups[*] entry
schema (types.imessage.ts + zod parser).
- Capture groupListPolicy.groupConfig.systemPrompt at decision build
time, falling back to the groups['*'] wildcard when the per-chat_id
entry has no explicit prompt. DM decisions never carry the prompt.
- Wire decision.groupSystemPrompt through to ctxPayload.GroupSystemPrompt
in buildIMessageInboundContext, gated on decision.isGroup.
Closes#78285.
Expose the existing safe-restart skipDeferral escape hatch through gateway RPC and the daemon CLI, document the flag, and add restart/CLI regression coverage.
Also keep CLI failure output off the cold bootstrap graph and align CLI guidance expectations needed by current CI.
Co-authored-by: Solomon Neas <solomonneas@users.noreply.github.com>