Replace the worker's generic `"Continue."` default with a dispatch-time
`initialUserTurn` that is resolved per trigger. Message and peer-request
wakes now enumerate the actual unread messages (id, sender, channel,
subject, reply-to) so the agent's first user turn carries the entities
it is expected to act on, instead of idling into a status summary.
Drop the system-prompt `heartbeatFallbackSection`: its "respond with a
brief status summary" line fought the wake-reason block above it and
was the main reason communication wakes degraded into self-narration.
The wake-reason section plus the bound initial user turn now cover
every case that section was carrying.
Prompt builder kept two full translations side by side — system-en.ts +
system-zh.ts, operating-en.ts + operating-zh.ts, and 38 *.zh.md files
across api-docs, sops, ceo-modes, department-guidelines, and
wake-reasons. Any change required hand-syncing across two locales; drift
was guaranteed. The Chinese user wasn't getting Chinese thinking — the
model reads whatever prompt we give it and responds in whatever language
we tell it to.
English is now the single source of truth. At the tail of the assembled
system prompt, when `ctx.locale === "zh"`, append a directive:
Respond to the user in Chinese.
Claude, GPT, and Gemini all comply with the directive reliably. English
users (the default) get no footer.
- Deleted 38 `*.zh.md` files (api-docs 11, sops 15, ceo-modes 5,
department-guidelines 7, wake-reasons 1 via zh.ts).
- Deleted `messages/system-zh.ts`, `messages/operating-zh.ts`,
`messages/locale.ts`.
- Simplified `messages/index.ts` to a direct re-export of the English
bundle; getters no longer take a locale argument.
- Stripped zh imports + locale branching from `api-section.ts`,
`sop-section.ts`, `operating-instructions.ts`,
`operating-instructions-ceo.ts`, `api-endpoints.ts`, `wake-reasons/`.
- `buildSOPSection()`, `getSOP()`, `renderWakeReason()` drop the locale
arg; callers updated.
- Footer injection in `system-prompt.ts` (lines 246-249), placed after
the importantRulesSection so the model reads it last (highest
instruction salience).
`ctx.locale` stays on `PromptContext` — load-bearing for the footer.
Anthropic prompt cache hits improve (one cache key instead of two for
the same agent across locales).
Inter-agent messages previously entered the recipient's context as a
separate prompt block (recentMessages), rebuilt every turn. This double-
charged tokens and kept messages outside pi's native AgentMessage stream.
Now at prepareRun: pull the recipient's unread inbox, project each
AgentMessageRecord into a pi user-role AgentMessage, persist to
SqliteSessionStore, and mark delivered. The recipient reads messages
as natural conversation turns in the transcript.
- db: listAgentInboxUnread + markAgentInboxDelivered (transactional)
- agent-runtime/inbox-projection.ts: AgentMessageRecord -> pi AgentMessage
- runtime-bridge.prepareRun: inject + deliver before loadMessages
- prompt-builder: delete recentMessages context block + buildMessagesSection
- message-normalize: drop unused normalizeMessagesForPrompt
- delete prompt-builder/attachment-resolver.ts (orphan after section removal)
Send path (api-server/routes-messages, ipc, UI) unchanged — inbox table
remains the UI source. Transactional delivery marking prevents duplicate
injection across runs. Failed append -> no mark -> retry on next run.
Split each prompt section into parallel .en.md/.zh.md bundles (sops, api-docs,
ceo-modes, department-guidelines) and mirrored messages/{operating,system}-{en,zh}.ts
modules for the inline identity/culture/rules text that had stayed as hard-coded
English template literals. Every loader now resolves a locale via a single
shared helper so CEO and IC prompts come out fully Chinese when locale=zh and
fully English otherwise, removing the need for the trailing "请记住:全程使用中文"
language reminder.
- New src/main/prompt-builder/wake-reasons/en.ts: WAKE_REASONS record of
{ title, steps(vars) } entries + renderWakeReason() formatter that
numbers the steps and composes the final block
- buildTaskPrompt in prompt-builder/index.ts collapses 100-line inline
reasonMap into a single renderWakeReason call
- index.ts shrinks from 161 to 77 lines; each wake reason's semantic
content (title text + numbered action steps + embedded curl hints)
preserved verbatim