Skip to content

005 — Repository Language ​

Everything committed to this repository is in English. The only exception is a tenant's own configuration, which is gitignored and never committed.

This is not a translation task ​

The Spanish currently in src/ is a symptom, not the problem. Customer-facing copy is hardcoded in source:

ts
// src/routes/turn.ts
const ACK_MESSAGE = 'Dame un segundo que lo chequeo 👍';

// src/agent/guardrails.ts
const ESCALATION_TEXT = 'Dejame que te pase con alguien del equipo...';

Translating those to English produces the same bug in a different language: a codebase that can serve exactly one linguistic market, now English instead of Spanish. A tenant in São Paulo would be equally stuck.

So the rule is stronger than "write English". It is:

No customer-facing natural language lives in source at all. Copy belongs to the tenant, in configuration. Source contains English identifiers, comments, and documentation — and no sentences a contact could ever read.

That makes the repository publishable in English and makes the product multi-tenant in a way it currently is not.

The four categories ​

CategoryRule
Code, comments, identifiers, docs, specs, ADRs, commit and PR textEnglish, always
Customer-facing copy (acknowledgement, escalation message)Not in source — tenant config
Prompt scaffolding the framework owns (operating rules, catalogue labels)English; never reaches a contact verbatim
A tenant's persona, catalogue, and reply languageTenant config, any language, gitignored

Reply language is configuration, not a property of the code ​

The framework's prompt scaffolding is English. The tenant's persona file states the language and register to answer in. Models follow a persona instruction to reply in another language reliably, so English scaffolding does not force English replies — it only stops the framework from assuming a language it has no business assuming.

This is already how config/prompt.md works. The change is that the rest of the prompt stops being Spanish too.

What changes ​

1. Copy moves to rules.json ​

ESCALATION_TEXT and ACK_MESSAGE become tenant-configured, with the schema requiring them. No default is shipped in source: a missing value must fail at boot rather than silently emitting English at a Spanish-speaking contact.

jsonc
{
  "messages": {
    "acknowledgement": "Give me one second while I check.",
    "escalation": "Let me put you through to someone on the team.",
  },
}

2. prompt.ts scaffolding becomes English ​

Operating rules, the security preamble, the format instructions, and the catalogue labels (descripcion: → description:, cursada: → schedule:). These are internal structure; a contact never sees them.

Escalation reason identifiers (price_negotiation, complaint) are already English and stay exactly as they are — they are enum values, not prose.

3. The committed demo tenant becomes English ​

config/*.example and test/fixtures/config/* describe a fictional English-speaking academy. These are the first thing a stranger reads, and a Spanish demo in an English repository reads as an oversight.

4. Tests and evals become English ​

Test names, assertions, and fixture strings. evals/golden/cases.jsonl becomes English cases against the English demo catalogue.

Tests contain no non-English prose either, including fixtures and test data.

That still leaves the guarantee testable. What must be proven is that copy comes from configuration, not that any particular language works — so the suite runs the same code paths for two tenants whose copy differs, both in English. If a string were baked back into source, both tenants would receive it and the assertions fail. Two English tenants prove that exactly as strongly as an English and a non-English pair, without putting prose into the repository that C9 forbids.

The alternate tenant's persona asks for replies in another language — written in English, as an instruction — which is where a real tenant expresses that, and it is carried through verbatim without the framework interpreting it.

The exception, scoped precisely ​

A deploying tenant's real config/prompt.md, config/catalog.json, config/rules.json and .env stay in whatever language that tenant sells in. They are gitignored (Constitution C1) and verified unstageable. The exception needs no discipline to hold — git enforces it.

Order of work ​

  1. Copy out of source (guardrails.ts, turn.ts, schema, config examples). This is the behavioural change and the only one that can break a running bot, so it lands first and alone.
  2. Prompt scaffolding (prompt.ts) — re-run the eval suite after, since prompt wording changes model behaviour and that is what the evals exist for.
  3. Demo tenant and fixtures.
  4. Tests and evals, including the non-English section.
  5. mock-provider.ts replies, last — it is test infrastructure and changing it early would obscure whether step 2 altered real behaviour.

Verification ​

  • pnpm eval passes against the English demo tenant, and the non-English section passes against its fixture. Step 2 is the risk: if English scaffolding degrades escalation accuracy, the evals are what will show it.

  • A test asserts that no file under src/ contains non-ASCII Latin letters (\u00C0-\u024F). Accented characters are the cheap signal that prose in another language has been pasted back in.

    This is a heuristic, not language detection: it catches accented prose and misses unaccented prose. It exists to catch the obvious regression, not to be authoritative. Review is the real enforcement.

  • No file under config/ other than *.example and README.md is tracked.