refactor(prompt): collapse en/zh mirror to English + runtime locale directive

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).
This commit is contained in:
ZacharyZhang-NY committed 2026-04-17 15:41:51 -04:00
1 parent 40040b3dd2
commit 5a3647e98e
53 files changed
+58 -1681

No files matched your search

@@ -1,7 +1,6 @@
import type { AppLocale } from "@shared/locale";
import type { PromptContext } from "./index";
import { buildCEOInstructions } from "./operating-instructions-ceo";
import { getOperatingMessages, resolveLocale } from "./messages";
import { getOperatingMessages } from "./messages";
import engineeringEn from "./department-guidelines/engineering.en.md?raw";
import financeEn from "./department-guidelines/finance.en.md?raw";
@@ -11,16 +10,8 @@ import salesEn from "./department-guidelines/sales.en.md?raw";
import customerSupportEn from "./department-guidelines/customer_support.en.md?raw";
import operationsEn from "./department-guidelines/operations.en.md?raw";
import engineeringZh from "./department-guidelines/engineering.zh.md?raw";
import financeZh from "./department-guidelines/finance.zh.md?raw";
import hrZh from "./department-guidelines/hr.zh.md?raw";
import marketingZh from "./department-guidelines/marketing.zh.md?raw";
import salesZh from "./department-guidelines/sales.zh.md?raw";
import customerSupportZh from "./department-guidelines/customer_support.zh.md?raw";
import operationsZh from "./department-guidelines/operations.zh.md?raw";
export function buildOperatingInstructions(ctx: PromptContext, isCEO: boolean, isManager: boolean): string {
const m = getOperatingMessages(ctx.locale);
const m = getOperatingMessages();
const parts: string[] = [];
if (isCEO && ctx.allAgents.length > 1) {
@@ -48,7 +39,7 @@ export function buildOperatingInstructions(ctx: PromptContext, isCEO: boolean, i
}
export function buildDecisionAuthoritySection(ctx: PromptContext, isCEO: boolean, isManager: boolean): string {
const m = getOperatingMessages(ctx.locale);
const m = getOperatingMessages();
const level = isCEO ? "executive" : isManager ? "manager" : "individual_contributor";
const budgetDisplay = ctx.agent.budgetMonthlyUsd > 0
? m.budgetMonthly(ctx.agent.budgetMonthlyUsd, ctx.agent.spentMonthlyUsd)
@@ -56,31 +47,20 @@ export function buildDecisionAuthoritySection(ctx: PromptContext, isCEO: boolean
return m.decisionAuthoritySection(level, budgetDisplay);
}
const DEPARTMENT_GUIDELINES: Record<AppLocale, Record<string, string>> = {
en: {
engineering: engineeringEn,
finance: financeEn,
hr: hrEn,
marketing: marketingEn,
sales: salesEn,
customer_support: customerSupportEn,
operations: operationsEn,
},
zh: {
engineering: engineeringZh,
finance: financeZh,
hr: hrZh,
marketing: marketingZh,
sales: salesZh,
customer_support: customerSupportZh,
operations: operationsZh,
},
const DEPARTMENT_GUIDELINES: Record<string, string> = {
engineering: engineeringEn,
finance: financeEn,
hr: hrEn,
marketing: marketingEn,
sales: salesEn,
customer_support: customerSupportEn,
operations: operationsEn,
};
export function buildDepartmentSection(ctx: PromptContext): string {
const dept = ctx.agent.department;
if (!dept) return "";
const template = DEPARTMENT_GUIDELINES[resolveLocale(ctx.locale)][dept];
const template = DEPARTMENT_GUIDELINES[dept];
if (!template) return "";
return template.replace(/\{\{companyId\}\}/g, ctx.agent.companyId);
}