fix: normalise locale to UTF-8 in applyHostLocale; add UTF-8 rule to AGENTS.md

applyHostLocale() was writing whatever charset was detected on the host
(including ISO8859-2) verbatim into ~/.login_conf, silently breaking
Slovenian character rendering on next login.

- Always strip the charset suffix from the detected locale tag and
  rewrite it as <base>.UTF-8 — sl_SI.ISO8859-2 → sl_SI.UTF-8
- charset field is always written as UTF-8
- Replace both 'tmux kill-server && tmux' suggestions with instruction
  to open a new tmux window or fresh SSH login
- Add UTF-8 compliance section to AGENTS.md documenting the rule,
  normalisation table, and the cap_mkdb requirement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---
Build: pass | Tests: pass — Tests  431 passed (431)
This commit is contained in:
Clawdie AI 2026-03-28 09:34:48 +00:00
parent d2d6aa1320
commit 98c8f82fc6
2 changed files with 47 additions and 4 deletions

View file

@ -435,3 +435,42 @@ mid-refactor). The footer is not a gate — it is a record. Other agents
picking up this repo mid-session can read the git log and immediately
know the state of the codebase at each commit without re-running the
full suite to establish a baseline.
---
## UTF-8 compliance
**Rule: always write UTF-8 to `~/.login_conf`. Never write a legacy charset.**
### `~/.login_conf` format
```
me:\
:charset=UTF-8:\
:lang=sl_SI.UTF-8:
```
The `lang` tag must end in `.UTF-8`. The `charset` field must be `UTF-8`.
Never write `ISO8859-2`, `ISO-8859-2`, `latin2`, or any other non-UTF-8
encoding — doing so silently breaks Slovenian character rendering (č/š/ž
appear as `_`) in every terminal session until manually corrected.
### Normalisation rule for `applyHostLocale()`
Strip any existing charset suffix from the detected locale tag, then
append `.UTF-8`. For example:
| Detected | Written |
|----------|---------|
| `sl_SI` | `sl_SI.UTF-8` |
| `sl_SI.ISO8859-2` | `sl_SI.UTF-8` |
| `sl_SI.UTF-8` | `sl_SI.UTF-8` |
| `en_US.UTF-8` | `en_US.UTF-8` |
### After writing `~/.login_conf`
Always run `cap_mkdb ~/.login_conf` to rebuild the binary database.
The new locale takes effect on the **next login** — a new tmux window,
new SSH session, or `exec $SHELL -l`. **Never suggest `tmux kill-server`**
to activate locale changes; that destroys the user's entire working
environment.

View file

@ -274,9 +274,13 @@ function writeIdentity(envFile: string, agentName: string, assistantName: string
function applyHostLocale(systemLocale: string): boolean {
try {
// Always normalise to UTF-8 — strip any non-UTF-8 charset suffix and
// rewrite the locale tag with .UTF-8 so ~/.login_conf never locks the
// user into a legacy encoding like ISO8859-2.
const dotIdx = systemLocale.indexOf('.');
const charset = dotIdx !== -1 ? systemLocale.slice(dotIdx + 1) : 'UTF-8';
const content = `me:\\\n\t:charset=${charset}:\\\n\t:lang=${systemLocale}:\n`;
const baseLocale = dotIdx !== -1 ? systemLocale.slice(0, dotIdx) : systemLocale;
const normalizedLocale = `${baseLocale}.UTF-8`;
const content = `me:\\\n\t:charset=UTF-8:\\\n\t:lang=${normalizedLocale}:\n`;
const loginConfPath = path.join(os.homedir(), '.login_conf');
fs.writeFileSync(loginConfPath, content, { encoding: 'utf-8' });
execFileSync('cap_mkdb', [loginConfPath], { stdio: 'ignore' });
@ -791,7 +795,7 @@ export async function run(args: string[]): Promise<void> {
runBsddialog([
'--title', 'Host Locale Set',
'--msgbox',
`Locale set to ${systemLocale}.\n\nWritten to ~/.login_conf.\n\nRespawn tmux to activate:\n tmux kill-server && tmux`,
`Locale set to ${systemLocale} (normalised to UTF-8).\n\nWritten to ~/.login_conf.\n\nOpen a new tmux window or fresh SSH login to activate.`,
'0', '0',
]);
}
@ -891,7 +895,7 @@ export async function run(args: string[]): Promise<void> {
const hostLocaleApplied = applyHostLocale(systemLocale);
if (hostLocaleApplied) {
console.log(
`Locale set to ${systemLocale} in ~/.login_conf. Respawn tmux to activate: tmux kill-server && tmux`,
`Locale set to ${systemLocale} (normalised to UTF-8) in ~/.login_conf. Open a new tmux window or fresh SSH login to activate.`,
);
}