projmux 0.6.3 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/docs/agent-workflow.md +24 -6
- package/docs/architecture.md +24 -0
- package/docs/cli.md +20 -16
- package/docs/configuration.md +162 -53
- package/docs/globalization.md +449 -0
- package/docs/hooks.md +7 -5
- package/docs/install.md +14 -11
- package/docs/keybindings.md +159 -309
- package/docs/native-picker-no-fzf-poc.md +7 -3
- package/docs/native-picker-parity.md +2 -2
- package/docs/notify-queue.md +8 -9
- package/docs/pr-guideline.md +10 -0
- package/docs/session-restore.md +20 -1
- package/docs/settings-ia.md +33 -5
- package/docs/statusbar.md +33 -13
- package/docs/testing.md +3 -2
- package/docs/theme-palette.md +174 -0
- package/docs/tmux-surface-inventory.md +794 -0
- package/docs/usage-tracking.md +4 -4
- package/package.json +5 -5
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
# Globalization Contract
|
|
2
|
+
|
|
3
|
+
This document is the inventory and contract for globalization. Phase 0 defined
|
|
4
|
+
the user-facing text boundary and literal preservation rules. Later phases add
|
|
5
|
+
the message catalog, locale formatters, runtime surface migration, and the
|
|
6
|
+
Phase 5 user locale override surface.
|
|
7
|
+
|
|
8
|
+
## Phase 0 Scope
|
|
9
|
+
|
|
10
|
+
Phase 0 does three things:
|
|
11
|
+
|
|
12
|
+
- Sets the temporary English baseline for remaining hardcoded Korean
|
|
13
|
+
user-facing product text in code and tests.
|
|
14
|
+
- Classifies existing string families as `translate`, `literal`, `data`, or
|
|
15
|
+
`debug-only`.
|
|
16
|
+
- Defines the surface boundaries for later catalog work.
|
|
17
|
+
|
|
18
|
+
Phase 0 explicitly preserves data and literals. It does not mass-translate docs
|
|
19
|
+
or fixtures.
|
|
20
|
+
|
|
21
|
+
## Surface Inventory
|
|
22
|
+
|
|
23
|
+
### AI Notifications
|
|
24
|
+
|
|
25
|
+
Files:
|
|
26
|
+
|
|
27
|
+
- `internal/app/ai_notify_body.go`
|
|
28
|
+
- `internal/app/ai.go`
|
|
29
|
+
- `internal/app/ai_test.go`
|
|
30
|
+
- `internal/app/ai_ingest_test.go`
|
|
31
|
+
- `internal/app/notify_producer_test.go`
|
|
32
|
+
|
|
33
|
+
Classification:
|
|
34
|
+
|
|
35
|
+
| Family | Examples | Class | Phase 0 policy |
|
|
36
|
+
| --- | --- | --- | --- |
|
|
37
|
+
| Agent names | `Codex`, `Claude`, `AI` | `literal` | Preserve exactly. |
|
|
38
|
+
| Category labels | `Response complete`, `Approval required`, `Input required`, `Error`, `Subagent stopped`, `Teammate waiting` | `translate` | English baseline now; catalog keys later. |
|
|
39
|
+
| Review body prefix | `Review pending:` | `translate` | English baseline now; catalog key later. |
|
|
40
|
+
| Tool names | `Bash`, `Read`, `WebFetch`, `Shell` | `literal` | Preserve provider/source spelling. |
|
|
41
|
+
| Tool input summaries | commands, paths, URLs, queries | `data` | Preserve payload content; only truncate for UI width. |
|
|
42
|
+
| Hook event names | `Stop`, `Notification`, `permission_prompt`, `idle_prompt` | `literal` | Preserve source values. |
|
|
43
|
+
| Severity values | `info`, `warn`, `critical` | `literal` | Preserve enum/source values. |
|
|
44
|
+
|
|
45
|
+
### Notify Queue, Sidebar, And Statusbar
|
|
46
|
+
|
|
47
|
+
Files:
|
|
48
|
+
|
|
49
|
+
- `internal/app/notify.go`
|
|
50
|
+
- `internal/app/status.go`
|
|
51
|
+
- `docs/statusbar.md`
|
|
52
|
+
- `docs/cli.md`
|
|
53
|
+
|
|
54
|
+
Classification:
|
|
55
|
+
|
|
56
|
+
| Family | Examples | Class | Phase 0 policy |
|
|
57
|
+
| --- | --- | --- | --- |
|
|
58
|
+
| CLI flag help and usage | `--text`, `--target`, `notify push`, usage errors | `translate` | Inventory only; convert in catalog phases. |
|
|
59
|
+
| Queue row labels and action hints | ack, clear, focus, open, reconcile labels | `translate` | Inventory only; convert in catalog phases. |
|
|
60
|
+
| Statusbar compact text | notify count, age, stale/gone hints | `translate` | Inventory only; needs compact locale formatter later. |
|
|
61
|
+
| Source/severity enum values | `ai`, `k8s`, `git`, `external`, `critical` | `literal` | Preserve exactly. |
|
|
62
|
+
| tmux style fragments | `#[...]`, tmux format strings | `literal` | Preserve syntax and measure display text separately. |
|
|
63
|
+
| Debug/error internals | wrapped Go errors, diagnostics for failed store reads | `debug-only` | Not catalog-blocking unless surfaced as normal UX. |
|
|
64
|
+
|
|
65
|
+
### Settings
|
|
66
|
+
|
|
67
|
+
Files:
|
|
68
|
+
|
|
69
|
+
- `internal/app/settings.go`
|
|
70
|
+
- `internal/app/settings_*.go`
|
|
71
|
+
- `docs/settings-ia.md`
|
|
72
|
+
|
|
73
|
+
Classification:
|
|
74
|
+
|
|
75
|
+
| Family | Examples | Class | Phase 0 policy |
|
|
76
|
+
| --- | --- | --- | --- |
|
|
77
|
+
| Root and section labels | Settings, Project, Notifications, Appearance, About | `translate` | Inventory only; catalog later. |
|
|
78
|
+
| Row labels and previews | enabled/disabled state, current source, saved values | `translate` | Inventory only; catalog later. |
|
|
79
|
+
| Disabled reasons and warnings | missing project, env override, conflict text | `translate` | Inventory only; catalog later. |
|
|
80
|
+
| Config keys and env vars | `PROJMUX_PROJDIR`, `config.toml`, `ui.locale` | `literal` | Preserve exactly. |
|
|
81
|
+
| Commands shown for copying | `projmux ai integrate codex --dry-run` | `literal` | Preserve exactly. |
|
|
82
|
+
| Persisted values | `none`, `notify`, `raise`, `auto` | `literal` | Preserve enum values. |
|
|
83
|
+
|
|
84
|
+
### Native Picker And Render Surfaces
|
|
85
|
+
|
|
86
|
+
Files:
|
|
87
|
+
|
|
88
|
+
- `internal/ui/projmuxpicker/*`
|
|
89
|
+
- `internal/ui/render/*`
|
|
90
|
+
- `docs/native-picker-no-fzf-poc.md`
|
|
91
|
+
|
|
92
|
+
Classification:
|
|
93
|
+
|
|
94
|
+
| Family | Examples | Class | Phase 0 policy |
|
|
95
|
+
| --- | --- | --- | --- |
|
|
96
|
+
| Search prompt and footer labels | Search, open rows, close, back, preview hints | `translate` | Inventory only; catalog later. |
|
|
97
|
+
| Picker titles and empty states | Projects, Settings, no matches | `translate` | Inventory only; catalog later. |
|
|
98
|
+
| Key names | `Enter`, `Esc`, `Alt-1`, `Ctrl-C` | `literal` | Preserve exactly. |
|
|
99
|
+
| Row data | project names, branch names, paths, session/window names | `data` | Preserve source content. |
|
|
100
|
+
| Width fixtures | CJK path/project examples and Unicode socket paths | `data` | Preserve as test fixtures. |
|
|
101
|
+
|
|
102
|
+
### Welcome, Update, About, And Help
|
|
103
|
+
|
|
104
|
+
Files:
|
|
105
|
+
|
|
106
|
+
- `internal/app/welcome*.go`
|
|
107
|
+
- `internal/app/update*.go`
|
|
108
|
+
- `internal/app/settings*.go`
|
|
109
|
+
- `internal/app/*help*`
|
|
110
|
+
- `docs/cli.md`
|
|
111
|
+
- `docs/agent-workflow.md`
|
|
112
|
+
|
|
113
|
+
Classification:
|
|
114
|
+
|
|
115
|
+
| Family | Examples | Class | Phase 0 policy |
|
|
116
|
+
| --- | --- | --- | --- |
|
|
117
|
+
| Welcome guide and shell prompt copy | first-run guidance, skip action text | `translate` | Inventory only; catalog later. |
|
|
118
|
+
| Update messages | update available, installer source, apply status | `translate` | Inventory only; catalog later. |
|
|
119
|
+
| About labels | version, source, welcome, quit action | `translate` | Inventory only; catalog later. |
|
|
120
|
+
| Command syntax | `projmux shell`, `make test`, `gh pr create` | `literal` | Preserve exactly. |
|
|
121
|
+
| Version strings and release tags | `vX.Y.Z`, git SHA, installer source | `data` | Preserve source content. |
|
|
122
|
+
|
|
123
|
+
## Literal Preservation Rules
|
|
124
|
+
|
|
125
|
+
Do not translate these families:
|
|
126
|
+
|
|
127
|
+
- Product and agent names: `Codex`, `Claude`, `projmux`, `tmux`, `psmux`,
|
|
128
|
+
`GitHub`, `npm`.
|
|
129
|
+
- Terminal and app names: `Windows Terminal`, `Ghostty`, `WezTerm`, `Kitty`,
|
|
130
|
+
`iTerm2`, `Alacritty`, `Foot`.
|
|
131
|
+
- Commands, flags, config, env vars, and paths: `projmux shell`, `make test`,
|
|
132
|
+
`~/.config/projmux/config.toml`, `PROJMUX_NOTIFY_HOOK`, `Alt-1`.
|
|
133
|
+
- Protocol, enum, and source values: `reply-ready`, `approval_required`,
|
|
134
|
+
`state.progress`, `ko-KR`, `en-US`, `critical`.
|
|
135
|
+
- Provider payload data: commands, file paths, URLs, query strings, project
|
|
136
|
+
names, branch names, session/window/pane names, and transcript excerpts.
|
|
137
|
+
- ANSI, terminal, and tmux syntax: escape sequences, `#[...]` style fragments,
|
|
138
|
+
tmux format expressions, and key escape fixtures.
|
|
139
|
+
|
|
140
|
+
These values may appear inside translated sentences, but the value itself stays
|
|
141
|
+
unchanged.
|
|
142
|
+
|
|
143
|
+
## Remaining Korean Hit Policy
|
|
144
|
+
|
|
145
|
+
Korean text is allowed when it is not English baseline product copy:
|
|
146
|
+
|
|
147
|
+
- `README-ko.md` and README language badges are localized docs and links.
|
|
148
|
+
- Roadmap title references in docs are source-note references, not product UI.
|
|
149
|
+
- CJK and Unicode path/socket fixtures are data for width, truncation, URI, and
|
|
150
|
+
filesystem behavior tests.
|
|
151
|
+
- Historical or roadmap-note titles in docs may remain when they identify an
|
|
152
|
+
external planning note.
|
|
153
|
+
|
|
154
|
+
New Korean product UI strings should not be added directly to code during Phase
|
|
155
|
+
0. Add English baseline copy now and move it behind message keys in Phase 1+.
|
|
156
|
+
|
|
157
|
+
## Draft Phase 1 Key Prefixes
|
|
158
|
+
|
|
159
|
+
Use stable, surface-oriented prefixes:
|
|
160
|
+
|
|
161
|
+
- `notify.ai.response_complete`
|
|
162
|
+
- `notify.ai.approval_required`
|
|
163
|
+
- `notify.ai.input_required`
|
|
164
|
+
- `notify.ai.error`
|
|
165
|
+
- `notify.ai.subagent_stopped`
|
|
166
|
+
- `notify.ai.teammate_waiting`
|
|
167
|
+
- `notify.ai.review_pending`
|
|
168
|
+
- `notify.queue.row.age_compact`
|
|
169
|
+
- `notify.queue.action.ack`
|
|
170
|
+
- `status.notify.count`
|
|
171
|
+
- `status.notify.age_compact`
|
|
172
|
+
- `settings.root.notifications`
|
|
173
|
+
- `settings.root.project`
|
|
174
|
+
- `settings.root.appearance`
|
|
175
|
+
- `settings.notifications.desktop`
|
|
176
|
+
- `settings.notifications.delivery_sources`
|
|
177
|
+
- `settings.about.welcome`
|
|
178
|
+
- `picker.prompt.search`
|
|
179
|
+
- `picker.footer.open_rows`
|
|
180
|
+
- `picker.footer.back`
|
|
181
|
+
- `picker.footer.close`
|
|
182
|
+
- `picker.empty.no_matches`
|
|
183
|
+
- `welcome.shell.title`
|
|
184
|
+
- `update.status.available`
|
|
185
|
+
- `help.usage.command`
|
|
186
|
+
|
|
187
|
+
Phase 1 should define the catalog API and fallback behavior before converting
|
|
188
|
+
large surfaces. Phase 2 should add locale-aware formatting for relative age,
|
|
189
|
+
duration, counts, list joins, and terminal cell-width-safe rendering. Later
|
|
190
|
+
phases can then move notify, Settings, picker, welcome, update, and help copy
|
|
191
|
+
behind catalog keys without changing source payload values.
|
|
192
|
+
|
|
193
|
+
## Phase 1 Catalog Foundation
|
|
194
|
+
|
|
195
|
+
Package:
|
|
196
|
+
|
|
197
|
+
- `internal/i18n`
|
|
198
|
+
|
|
199
|
+
Catalog policy:
|
|
200
|
+
|
|
201
|
+
- Catalog data is embedded Go data. Do not download catalog content at runtime
|
|
202
|
+
and do not add a translation service dependency.
|
|
203
|
+
- `en-US` is the fallback locale. Every Phase 0 foundation key must have a
|
|
204
|
+
non-empty `en-US` entry.
|
|
205
|
+
- `ko-KR` is intentionally partial in Phase 1 so fallback behavior is covered
|
|
206
|
+
before broad runtime migration.
|
|
207
|
+
- Missing preferred-locale keys fall back to `en-US`.
|
|
208
|
+
- Missing fallback-locale keys are errors and must also be caught by the
|
|
209
|
+
catalog completeness unit test.
|
|
210
|
+
|
|
211
|
+
Locale resolution:
|
|
212
|
+
|
|
213
|
+
- Precedence is explicit override/API, then `PROJMUX_LOCALE`, then global
|
|
214
|
+
`[ui] locale`, then `LC_ALL`, then `LC_MESSAGES`, then `LANG`, then `en-US`.
|
|
215
|
+
- Common POSIX forms normalize into catalog tags: `ko`, `ko_KR.UTF-8`, and
|
|
216
|
+
`ko-KR` become `ko-KR`; `en` and `en_US` become `en-US`.
|
|
217
|
+
- `C` and `POSIX` locales are skipped as non-user-language values.
|
|
218
|
+
- Supported UI locales are currently `en-US` and `ko-KR`. Unsupported locale
|
|
219
|
+
tags fall back to `en-US` and keep their source attached so Settings can show
|
|
220
|
+
a warning.
|
|
221
|
+
- `auto` is a setting value, not a catalog locale. It means "use the
|
|
222
|
+
auto-detected environment rung".
|
|
223
|
+
|
|
224
|
+
API convention:
|
|
225
|
+
|
|
226
|
+
- Use `i18n.ResolveLocale` to pick the preferred locale.
|
|
227
|
+
- Use `i18n.NewLocalizer(locale).Text(key)` for plain user-facing text.
|
|
228
|
+
- Use `i18n.NewLocalizer(locale).Styled(key)` only for messages that contain
|
|
229
|
+
ANSI or tmux style syntax.
|
|
230
|
+
- Do not pass styled terminal fragments through the plain text API. The lookup
|
|
231
|
+
API returns a kind mismatch error when a caller requests the wrong shape.
|
|
232
|
+
- Future formatter phases should keep payload data, command strings, paths,
|
|
233
|
+
key names, enum/source values, and tmux/ANSI syntax outside translated text
|
|
234
|
+
unless they are inserted as preserved literal values.
|
|
235
|
+
|
|
236
|
+
Contribution convention:
|
|
237
|
+
|
|
238
|
+
- Add new translatable user-facing strings as stable `i18n.Key` constants.
|
|
239
|
+
- Add the `en-US` entry in the same change as the key.
|
|
240
|
+
- Add `ko-KR` when the translation is known; otherwise rely on fallback while
|
|
241
|
+
keeping the missing key intentional in review notes.
|
|
242
|
+
- Do not translate product names (`projmux`, `tmux`, `Codex`, `Claude`),
|
|
243
|
+
commands, paths, config keys, environment variables, provider payloads, or
|
|
244
|
+
source enum values.
|
|
245
|
+
- Runtime migrations should be narrow by surface. Move a string family behind
|
|
246
|
+
the catalog only when its tests can show literal preservation and fallback
|
|
247
|
+
behavior for that surface.
|
|
248
|
+
|
|
249
|
+
## Phase 2 Formatter Foundation
|
|
250
|
+
|
|
251
|
+
Package:
|
|
252
|
+
|
|
253
|
+
- `internal/i18n`
|
|
254
|
+
|
|
255
|
+
Formatter policy:
|
|
256
|
+
|
|
257
|
+
- Formatter functions localize grammar, units, and labels. They do not translate
|
|
258
|
+
caller-owned payload values such as product names, commands, paths, provider
|
|
259
|
+
text, tmux targets, or enum/source data inserted as arguments.
|
|
260
|
+
- Formatter functions accept a `FormatVariant`. `i18n.FormatFull` is for
|
|
261
|
+
prose-friendly labels and `i18n.FormatCompact` is for dense terminal surfaces.
|
|
262
|
+
- Unsupported or empty locales fall back to `en-US`. Korean locale forms
|
|
263
|
+
normalized by `ResolveLocale` use the Korean formatter rules.
|
|
264
|
+
- Relative age has a pinned just-now window of less than five seconds:
|
|
265
|
+
`just now` for `en-US`, `방금 전` for `ko-KR`.
|
|
266
|
+
|
|
267
|
+
Formatter API:
|
|
268
|
+
|
|
269
|
+
- `i18n.FormatRelativeAge(age, locale, variant)` renders elapsed age, for
|
|
270
|
+
example `3m ago` in compact `en-US` and `36초 전` in compact `ko-KR`.
|
|
271
|
+
- `i18n.FormatDuration(duration, locale, variant)` renders the largest whole
|
|
272
|
+
unit in seconds, minutes, hours, or days.
|
|
273
|
+
- `i18n.FormatCount(count, subject, locale, variant)` applies locale-specific
|
|
274
|
+
count grammar for owned subjects such as `i18n.CountNotifications` while
|
|
275
|
+
preserving the numeric value.
|
|
276
|
+
- `i18n.FormatList(items, locale, variant)` joins caller-owned item strings
|
|
277
|
+
using locale-specific separators without translating item payloads.
|
|
278
|
+
- `i18n.FormatStatusToken(token, locale, variant)` renders shared terminal
|
|
279
|
+
status labels for known `i18n.StatusToken` values.
|
|
280
|
+
- `i18n.FormatTargetLabel(kind, number, locale, variant)` localizes the target
|
|
281
|
+
label, such as window or pane, while preserving the target number.
|
|
282
|
+
|
|
283
|
+
Width-safe rendering:
|
|
284
|
+
|
|
285
|
+
- Use `i18n.TerminalCellWidth(value)` when terminal layout depends on visible
|
|
286
|
+
width. It measures terminal cells, not bytes or runes.
|
|
287
|
+
- Use `i18n.TruncateTerminalCells(value, maxCells)` before placing
|
|
288
|
+
locale-specific output into fixed-width terminal columns.
|
|
289
|
+
- ANSI escape sequences and tmux style wrappers such as `#[fg=red]` are
|
|
290
|
+
zero-width for measurement and truncation. Truncation preserves those wrappers
|
|
291
|
+
in the returned string while clipping only visible content.
|
|
292
|
+
- Width clipping is a rendering concern. Keep translated format strings and
|
|
293
|
+
caller-owned payload arguments separate until the final render step.
|
|
294
|
+
|
|
295
|
+
## Phase 3 Notify Runtime Migration
|
|
296
|
+
|
|
297
|
+
Runtime surfaces migrated:
|
|
298
|
+
|
|
299
|
+
- AI desktop notification summaries for Codex and Claude hook payloads.
|
|
300
|
+
- In-app notify queue table/sidebar/statusbar display text for AI entries.
|
|
301
|
+
- Notify live explanation text for `projmux notify list --live`.
|
|
302
|
+
- Sidebar/table/statusbar age formatting and sidebar stale/gone/target labels.
|
|
303
|
+
|
|
304
|
+
Storage and dispatch policy:
|
|
305
|
+
|
|
306
|
+
- Queue storage remains schema-compatible. Stored `notify.Notification.Text`,
|
|
307
|
+
metadata keys, severity/source enum values, targets, and timestamps are not
|
|
308
|
+
localized before persistence.
|
|
309
|
+
- OS notification click/focus routing is unchanged. Locale formatting only
|
|
310
|
+
changes the summary/body strings sent to the configured notifier.
|
|
311
|
+
- JSON queue payloads keep raw queue entries. Localized live-row explanation
|
|
312
|
+
and row display text may appear in `notify list --live` row fields because
|
|
313
|
+
those fields are render/report output, not stored queue schema.
|
|
314
|
+
|
|
315
|
+
Literal preservation and parity rules:
|
|
316
|
+
|
|
317
|
+
- Translate only catalog-owned category labels such as `Response complete`,
|
|
318
|
+
`Approval required`, `Input required`, `Error`, `Subagent stopped`, and
|
|
319
|
+
`Teammate waiting`.
|
|
320
|
+
- Preserve provider-owned payloads verbatim: `Codex`, `Claude`, tool names,
|
|
321
|
+
commands, paths, URLs, query strings, transcript excerpts, teammate IDs, and
|
|
322
|
+
subagent IDs.
|
|
323
|
+
- Desktop notification summaries and in-app queue display text must use the
|
|
324
|
+
same rendered category labels for the same locale while preserving the same
|
|
325
|
+
literal payload body.
|
|
326
|
+
- The response-complete fallback body `Ready` is treated as provider state and
|
|
327
|
+
suppressed in display detail; it is not translated or persisted differently.
|
|
328
|
+
|
|
329
|
+
## Phase 4 Settings And Popup Guidance
|
|
330
|
+
|
|
331
|
+
Runtime surfaces migrated:
|
|
332
|
+
|
|
333
|
+
- Settings root title, scope chips, root row labels/descriptions, common row
|
|
334
|
+
labels/previews/disabled reasons, and shared Settings footer guidance.
|
|
335
|
+
- Native picker search label, empty-list row, and line-mode close prompt.
|
|
336
|
+
- Shell welcome/update guide text and Settings > About > Welcome viewer body.
|
|
337
|
+
|
|
338
|
+
Literal preservation:
|
|
339
|
+
|
|
340
|
+
- Key names such as `Enter`, `Esc`, `Ctrl-b d`, and `s` remain literal inside
|
|
341
|
+
localized guide sentences.
|
|
342
|
+
- Commands, env/config names, and paths such as `projmux shell`,
|
|
343
|
+
`tmux -L projmux kill-server`, `PROJMUX_PROJDIR`, and
|
|
344
|
+
`~/.config/projmux/projdir` remain literal payload text.
|
|
345
|
+
- Project names, paths, provider payloads, enum values, and hook/action IDs are
|
|
346
|
+
not translated.
|
|
347
|
+
|
|
348
|
+
Width policy:
|
|
349
|
+
|
|
350
|
+
- Settings row padding now uses terminal cell width instead of byte length so
|
|
351
|
+
Korean labels align with the existing ANSI row chrome.
|
|
352
|
+
- Native picker prompt, empty row, and footer render through existing frame
|
|
353
|
+
truncation/padding helpers; focused tests cover `en-US`/`ko-KR` output and
|
|
354
|
+
long Korean styled guidance.
|
|
355
|
+
|
|
356
|
+
## Phase 5 Locale Settings And Docs
|
|
357
|
+
|
|
358
|
+
User override surface:
|
|
359
|
+
|
|
360
|
+
- Environment override: `PROJMUX_LOCALE=auto|en-US|ko-KR`.
|
|
361
|
+
- Global config override: `~/.config/projmux/config.toml`:
|
|
362
|
+
|
|
363
|
+
```toml
|
|
364
|
+
[ui]
|
|
365
|
+
locale = "auto" # auto | en-US | ko-KR
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
- Settings surface: `Settings > Appearance > Language / Locale`.
|
|
369
|
+
|
|
370
|
+
Resolution policy:
|
|
371
|
+
|
|
372
|
+
1. API/explicit override used by tests and internal callers.
|
|
373
|
+
2. `PROJMUX_LOCALE` when set to a non-empty value other than `auto`.
|
|
374
|
+
3. Global/user `[ui] locale` when set to a non-empty value other than `auto`.
|
|
375
|
+
4. Auto-detected environment, in order: `LC_ALL`, `LC_MESSAGES`, `LANG`.
|
|
376
|
+
5. Built-in fallback `en-US`.
|
|
377
|
+
|
|
378
|
+
`auto` in either `PROJMUX_LOCALE` or `[ui] locale` does not pin the UI to a
|
|
379
|
+
literal `auto` locale. It re-enters the auto-detection path and Settings shows
|
|
380
|
+
the currently detected locale and source, such as `ko-KR from LC_MESSAGES env`.
|
|
381
|
+
|
|
382
|
+
Fallback and warning policy:
|
|
383
|
+
|
|
384
|
+
- `en-US` and `ko-KR` are the only supported UI locales in Phase 5.
|
|
385
|
+
- Unsupported locale tags such as `ja-JP` or `fr-FR` fall back to `en-US`.
|
|
386
|
+
- Settings displays the unsupported tag, its source (`PROJMUX_LOCALE`,
|
|
387
|
+
`~/.config/projmux/config.toml`, `LC_ALL`, `LC_MESSAGES`, or `LANG`), and
|
|
388
|
+
the effective `en-US` fallback.
|
|
389
|
+
- Project-local locale override is intentionally out of scope. Any parser
|
|
390
|
+
support for `[ui] locale` exists only because global and project config share
|
|
391
|
+
the same TOML implementation; runtime locale resolution consumes only the
|
|
392
|
+
global/user config path.
|
|
393
|
+
|
|
394
|
+
Literal preservation remains unchanged:
|
|
395
|
+
|
|
396
|
+
- Config keys and env vars such as `[ui].locale`, `PROJMUX_LOCALE`,
|
|
397
|
+
`LC_MESSAGES`, and `~/.config/projmux/config.toml` remain literal.
|
|
398
|
+
- Locale enum values such as `auto`, `en-US`, and `ko-KR` remain literal.
|
|
399
|
+
- Commands, paths, provider payloads, tmux format strings, and key names remain
|
|
400
|
+
caller-owned payload text and are not translated.
|
|
401
|
+
|
|
402
|
+
## Phase 6 Governance
|
|
403
|
+
|
|
404
|
+
Phase 6 prevents new user-facing strings from bypassing the catalog while
|
|
405
|
+
keeping the existing literal/data/debug boundary explicit.
|
|
406
|
+
|
|
407
|
+
Governance checks:
|
|
408
|
+
|
|
409
|
+
- `internal/i18n` owns the Go string-literal audit helper.
|
|
410
|
+
- `go test ./internal/i18n` includes synthetic audit coverage for Korean
|
|
411
|
+
candidates, English user-facing candidates, and ignored literal/data/debug
|
|
412
|
+
examples.
|
|
413
|
+
- The current repo guard scans runtime Go files for new Korean string literals
|
|
414
|
+
outside the catalog, formatter locale fragments, tests, `testdata`, and
|
|
415
|
+
comments.
|
|
416
|
+
- The catalog completeness tests require `en-US` fallback coverage for every
|
|
417
|
+
embedded default catalog key and required `ko-KR` coverage for migrated
|
|
418
|
+
`notify.ai.`, `notify.live.`, `settings.`, `picker.`, `welcome.`, `update.`,
|
|
419
|
+
and `help.` surfaces.
|
|
420
|
+
|
|
421
|
+
Contributor rule:
|
|
422
|
+
|
|
423
|
+
- New normal UX copy must be added as a stable catalog key with an `en-US`
|
|
424
|
+
fallback entry and focused test coverage.
|
|
425
|
+
- If the string is intentionally not translated, classify it in review notes as
|
|
426
|
+
`literal`, `data`, or `debug-only` and preserve it verbatim.
|
|
427
|
+
- Korean product UI strings must not be hardcoded in runtime Go. Add or extend
|
|
428
|
+
the catalog entry instead.
|
|
429
|
+
- Do not translate provider payloads, commands, config keys, paths, env vars,
|
|
430
|
+
locale enum values, product names, or tmux/ANSI syntax.
|
|
431
|
+
|
|
432
|
+
Debug/log/internal error classification:
|
|
433
|
+
|
|
434
|
+
- Catalog text when it is normal UX, shown in a picker/sidebar/statusbar,
|
|
435
|
+
desktop notification, user-actionable CLI output, or other expected product
|
|
436
|
+
surface.
|
|
437
|
+
- Do not catalog debug logs, trace strings, diagnostics, or wrapped internal Go
|
|
438
|
+
errors unless that exact text is promoted into normal UX.
|
|
439
|
+
- If a diagnostic is surfaced as normal UX, split it: catalog the user-facing
|
|
440
|
+
explanation or action hint, and keep raw error details, paths, commands, and
|
|
441
|
+
provider payload as preserved data.
|
|
442
|
+
|
|
443
|
+
Audit operation:
|
|
444
|
+
|
|
445
|
+
- Run `GOCACHE=/tmp/projmux-go-cache go test ./internal/i18n` after changing
|
|
446
|
+
i18n helpers, catalog data, migrated UI strings, or locale policy.
|
|
447
|
+
- For broader validation, continue to run the standard repo gates in order:
|
|
448
|
+
`make fmt`, `make fix`, `make test`, `make test-integration`, and
|
|
449
|
+
`make test-e2e` where applicable.
|
package/docs/hooks.md
CHANGED
|
@@ -169,9 +169,11 @@ stdin receives one JSON object:
|
|
|
169
169
|
"topic": "worker loop",
|
|
170
170
|
"pane": "%9",
|
|
171
171
|
"session": "main",
|
|
172
|
-
"message": "
|
|
172
|
+
"message": "worker loop",
|
|
173
173
|
"metadata": {
|
|
174
|
-
"agent": "claude"
|
|
174
|
+
"agent": "claude",
|
|
175
|
+
"category": "response_complete",
|
|
176
|
+
"state": "need"
|
|
175
177
|
},
|
|
176
178
|
"created_at": "2026-05-12T02:03:04Z"
|
|
177
179
|
}
|
|
@@ -346,9 +348,9 @@ events, so `Stop` or `PermissionRequest` can be made state-only or quiet
|
|
|
346
348
|
without changing which hook commands are installed. When a known Codex event
|
|
347
349
|
without a specialized handler, such as `PreToolUse` or `PostToolUse`, is set to
|
|
348
350
|
runtime `notify`, projmux pushes a generic in-app notify row such as
|
|
349
|
-
`
|
|
350
|
-
it does not dispatch `[hooks.send-noti]`,
|
|
351
|
-
or Windows toast.
|
|
351
|
+
`PreToolUse · Bash` with agent/category metadata. That generic path is
|
|
352
|
+
queue/sidebar/statusbar only: it does not dispatch `[hooks.send-noti]`,
|
|
353
|
+
`PROJMUX_NOTIFY_HOOK`, `notify-send`, or Windows toast.
|
|
352
354
|
Generic metadata is limited to safe summary fields such as provider, event,
|
|
353
355
|
tool, cwd, thread, session, turn, and model; raw payloads and tool input are
|
|
354
356
|
not stored.
|
package/docs/install.md
CHANGED
|
@@ -27,17 +27,20 @@ Start the tmux app with:
|
|
|
27
27
|
projmux shell
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
Each `projmux shell` launch prints a short welcome with the current version,
|
|
31
|
+
detach/exit keys, core app shortcuts, and cached update status when available.
|
|
32
|
+
Press Enter to continue for this run, or press `s` to skip the welcome for the
|
|
33
|
+
current projmux version. The next projmux version shows the welcome again.
|
|
34
|
+
|
|
35
|
+
If an installer-supported update is available, the same prompt keeps update
|
|
36
|
+
actions separate from welcome skip: press `u` to run `projmux update apply`,
|
|
37
|
+
`n` to print the manual update command, or `d` to skip daily update prompts for
|
|
38
|
+
that release.
|
|
39
|
+
|
|
40
|
+
To revisit the guide later, run `projmux welcome`, or use Settings > About >
|
|
41
|
+
Welcome inside the app to open it in a visible viewer. Set `PROJMUX_WELCOME=off` before
|
|
42
|
+
launching `projmux shell` to suppress legacy automatic attach popups without
|
|
43
|
+
disabling the shell prompt or manual command.
|
|
41
44
|
|
|
42
45
|
## Runtime Tools
|
|
43
46
|
|