open-design/apps/daemon/tests/prompts/discovery-localization-drift.test.ts
Matt Van Horn 715ed04f5d
fix(prompt): instruct discovery form to follow user's chat language (#2534)
* fix(prompt): instruct discovery form to follow user's chat language

The discovery form was reaching users in English even when their UI
language was Chinese (#1416). The form is generated by the LLM under
guidance from packages/contracts/src/prompts/discovery.ts, but the
prompt only mentioned that option labels MAY follow the user's
language. The example form embedded English text for title,
description, per-question labels, and placeholders, and the LLM
copied that text verbatim instead of localizing.

Two minimal changes to the prompt:

1. Add a sentence under RULE 1 making the language-match expectation
   explicit before the example forms.
2. Expand the Form authoring rules bullet so it covers every
   user-facing string (title, description, label, placeholder, option
   label) and pins the unlocalized identifiers (id, type, option
   value, branch values) for the runtime branch logic.

Fixes #1416

* fix(prompts): mirror discovery localization rule to daemon prompt copy

Apply the same 'Match the user's chat language' paragraph and the
expanded 'Localize every user-facing string' bullet to
apps/daemon/src/prompts/discovery.ts, which the daemon-backed chat
path uses (it imports ./discovery.js, not the contracts copy).

Also add apps/daemon/tests/prompts/discovery-localization-drift.test.ts,
which reads both prompt copies and asserts each one contains both rules,
so the contracts and daemon files cannot silently drift on this behavior.

Apply-anyway reason: pnpm install / pnpm vitest could not run locally
(registry DNS blocked in sandbox + node v26 vs required v24). Direct
Node content assertion over both files passes. CI will run vitest.

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
2026-05-23 11:48:17 +08:00

28 lines
1.4 KiB
TypeScript

import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';
import { describe, expect, it } from 'vitest';
const testDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(testDir, '../../../..');
const promptPaths = [
'packages/contracts/src/prompts/discovery.ts',
'apps/daemon/src/prompts/discovery.ts',
] as const;
const languageMatchRule =
"Match the user's chat language. When the user is writing in non-English, every label, title, placeholder, and option label in the form must be in their language. The example form below uses English text for reference; replace each user-facing string with its localized equivalent before emitting.";
const localizationBullet =
"- Localize every user-facing string in the form (\\`title\\`, \\`description\\`, the per-question \\`label\\`, \\`placeholder\\`, and option \\`label\\`s) to the user's chat language. \\`id\\`, \\`type\\`, option \\`value\\`, and the stable branch values (\\`pick_direction\\`, \\`brand_spec\\`, \\`reference_match\\`) MUST stay in English because later branch rules match against them.";
describe('discovery prompt localization rules', () => {
it.each(promptPaths)('%s includes the localized form wording', (promptPath) => {
const source = readFileSync(resolve(repoRoot, promptPath), 'utf8');
expect(source).toContain(languageMatchRule);
expect(source).toContain(localizationBullet);
});
});