projmux 0.6.4 → 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/docs/agent-workflow.md +6 -1
- package/docs/configuration.md +91 -0
- package/docs/globalization.md +212 -7
- package/docs/pr-guideline.md +10 -0
- package/docs/settings-ia.md +11 -0
- package/docs/statusbar.md +8 -0
- package/docs/theme-palette.md +80 -11
- package/package.json +5 -5
package/docs/agent-workflow.md
CHANGED
|
@@ -48,11 +48,16 @@
|
|
|
48
48
|
- `make test` also covers `projmux ai ingest claude-hook` core and extra Claude Code hook ingest for event parsing, transcript fallback, cataloged hook notification body formatting, permission summary formatting, UserPromptSubmit busy/no-queue behavior, Notification severity/text mapping, StopFailure/TeammateIdle text/severity/metadata mapping, SubagentStop quiet/no-notify diagnostics, unknown future-event quiet fallback, hook-active pane marking, topic preservation without hook candidate writes, mutable resume metadata writes for `@projmux_ai_resume_id`, source, and updated-at, and Claude transcript path preservation.
|
|
49
49
|
- `make test` also covers the Globalization Phase 0 English baseline for AI desktop notification summaries/bodies and hook-ingest queue text while preserving agent names, tool names, commands, paths, and provider payload values as literals/data.
|
|
50
50
|
- `make test` also covers the Globalization Phase 1 message catalog foundation: locale resolver priority and normalization, `ko-KR` to `en-US` fallback, missing fallback-key errors, `en-US` completeness for foundation keys, and plain-text versus ANSI/tmux-styled fragment API separation.
|
|
51
|
+
- `make test` also covers the Globalization Phase 2 formatter foundation: compact/full relative age and duration formatting, locale-specific just-now text, notification count plural/count preservation, list joins that preserve payload items, status token and target label localization, terminal cell-width measurement/truncation, and ANSI/tmux style wrappers treated as zero-width.
|
|
52
|
+
- `make test` also covers the Globalization Phase 3 notify runtime migration: AI notify category rendering for `en-US`/`ko-KR`, Codex/Claude hook literal preservation for agent names, tool names, commands, paths, URLs, provider messages, subagent and teammate payloads, desktop notification and in-app queue display parity, notify sidebar/statusbar locale formatter output, and raw queue storage schema preservation.
|
|
53
|
+
- `make test` also covers the Globalization Phase 4 Settings and popup guidance migration: `en-US`/`ko-KR` Settings root title/chips/rows/footer rendering, native picker search/empty/footer rendering without overflow, Settings row padding by terminal cell width, shell welcome guide catalog rendering, and long Korean ANSI/tmux-styled guide truncation safety while preserving key/command/path literals.
|
|
54
|
+
- `make test` also covers the Globalization Phase 5 locale settings surface: `PROJMUX_LOCALE` > global `[ui].locale` > `LC_ALL` > `LC_MESSAGES` > `LANG` > `en-US` priority, Settings > Appearance > Language / Locale row/detail visibility, `auto` current-locale/source display, unsupported locale fallback warnings, global config writes, and preserved command/config/env/path literals.
|
|
55
|
+
- `make test` also covers the Globalization Phase 6 governance guard: Go string-literal audit classification for hardcoded Korean candidates, English user-facing candidates, and ignored literal/data/debug examples; no unapproved runtime Korean literals outside catalog/formatter/test fixtures; `en-US` coverage for every embedded default catalog key; and required `ko-KR` coverage for migrated notify, Settings, picker, welcome, update, and help surfaces.
|
|
51
56
|
- `make test` also covers `projmux ai integrate tmux-bell` dry-run/install/remove tmux command planning, managed `alert-bell` hook append/idempotence/removal, preservation of unmanaged bell hooks, and `projmux ai ingest bell --pane` queue push/metadata/dedupe behavior for non-AI-managed panes.
|
|
52
57
|
- `make test` also covers `projmux ai ingest log` tail/path rendering and bounded JSONL log trimming for ingest diagnostics.
|
|
53
58
|
- `make test` also covers welcome revisit policy: shell `skip_version` gating, `s` skip vs Enter one-run continue, Settings > About > Welcome native viewer, and attach-popup no-duplicate/no-op behavior.
|
|
54
59
|
- `make test` also covers `projmux quit` action-picker rows, cancel/close no-op behavior, explicit quit of only app-owned mux runtimes marked by `@projmux_app=1` on the selected `tmux`/`psmux -L projmux` backend, missing/default runtime no-ops, dispatcher wiring, and `Settings > About > Quit projmux` routing through the same picker before any shutdown side effect.
|
|
55
|
-
- `make test` also covers the built-in semantic palette foundation: non-empty fallback truecolor/tmux tokens, distinct action/attention/AI/progress/danger roles, native picker chip/current/titlebar render strings, statusbar git/notify/usage/settings palette regressions, attention/pane-border/popup/switch progress color guards, renderer-only lead-mode topic prefix styling,
|
|
60
|
+
- `make test` also covers the built-in semantic palette foundation: non-empty fallback truecolor/tmux tokens, distinct action/attention/AI/progress/danger roles, native picker chip/current/titlebar render strings, statusbar git/notify/usage/settings palette regressions, attention/pane-border/popup/switch progress color guards, renderer-only lead-mode topic prefix styling, settings/trust/destructive row color guards, Theme settings Phase 0/1 resolver behavior for project/global/fallback source labels, preset fill, explicit token override, invalid-layer warnings, and truecolor-to-tmux mapping, Phase 2 fallback render parity and project/global color isolation for native picker and tmux status/window background adapters, Phase 3 desired font config save/resolve plus unsupported `not applied` status without breaking no-adapter fallback rendering, and Phase 4 Settings theme editing boundaries for project/global resets, project inherit-vs-override labels, effective source labels, and project config theme values feeding the native project popup render path.
|
|
56
61
|
- Current focused unit coverage also includes strict notify SOT behavior
|
|
57
62
|
(TTL does not remove rows, focus success and target-gone clicks ack,
|
|
58
63
|
reconcile reports stale rows), `notify list --live` queue/live explanations, notify sidebar
|
package/docs/configuration.md
CHANGED
|
@@ -158,6 +158,96 @@ chord and the replacement before binding the merged action. Popup and floating
|
|
|
158
158
|
UI actions still route through `tmux popup-toggle`, so pressing the same
|
|
159
159
|
configured key opens and closes the popup.
|
|
160
160
|
|
|
161
|
+
## Theme Resolver Foundation
|
|
162
|
+
|
|
163
|
+
Theme settings are resolved against the same project/global axes as
|
|
164
|
+
declarative hooks and project recipe fields:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
<project>/.projmux/config.toml
|
|
168
|
+
~/.config/projmux/config.toml
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Settings can edit the global `[theme]` in `~/.config/projmux/config.toml` and
|
|
172
|
+
the current project override in `<project>/.projmux/config.toml`. The Effective
|
|
173
|
+
theme view shows the final project > global > built-in fallback value for each
|
|
174
|
+
field with source labels: `project`, `global`, or `fallback`.
|
|
175
|
+
|
|
176
|
+
Renderer adapters can apply an already resolved `EffectiveTheme` to native
|
|
177
|
+
picker frame background/foreground SGR and tmux status/window `colourN`
|
|
178
|
+
background tokens. Settings and native project picker surfaces load global and
|
|
179
|
+
project `[theme]` values through the shared effective-theme source. Fallback
|
|
180
|
+
renderer output intentionally keeps the existing palette constants byte for
|
|
181
|
+
byte.
|
|
182
|
+
|
|
183
|
+
Resolver schema shape:
|
|
184
|
+
|
|
185
|
+
```toml
|
|
186
|
+
[theme]
|
|
187
|
+
preset = "projmux-dark"
|
|
188
|
+
background = "#182226"
|
|
189
|
+
surface = "#182226"
|
|
190
|
+
surface_active = "#2c383d"
|
|
191
|
+
foreground = "#d8e0e4"
|
|
192
|
+
muted = "#75848c"
|
|
193
|
+
accent = "#7ac7ad"
|
|
194
|
+
critical = "#ff6b6b"
|
|
195
|
+
warning = "#ffcc66"
|
|
196
|
+
font_family = "Cascadia Mono"
|
|
197
|
+
font_size = 12
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Supported presets are `projmux-dark`, `midnight`, `forest`, `rose`, and
|
|
201
|
+
`high-contrast`. A preset fills missing color tokens in its own layer, and
|
|
202
|
+
explicit color tokens override preset values. Missing or `inherit` values fall
|
|
203
|
+
through to the next layer.
|
|
204
|
+
|
|
205
|
+
Unknown presets and invalid color/font values invalidate only their own theme
|
|
206
|
+
layer and produce resolver warnings; the next source still resolves normally.
|
|
207
|
+
Colors are `#RRGGBB`. Settings edits colors through a preset selector, swatch
|
|
208
|
+
rows, and a hex input page. Truecolor renderers use exact RGB SGR tokens, and
|
|
209
|
+
tmux surfaces use the stored or nearest xterm 256-color `colourN` mapping. Font
|
|
210
|
+
values are desired terminal profile hints, not universal tmux or ANSI renderer
|
|
211
|
+
tokens. Without a supported terminal font adapter, Settings reports the
|
|
212
|
+
effective desired font as `not applied`; projmux does not create or modify
|
|
213
|
+
terminal profiles in this phase.
|
|
214
|
+
|
|
215
|
+
## UI Locale
|
|
216
|
+
|
|
217
|
+
The UI locale can be pinned globally or left on automatic detection.
|
|
218
|
+
|
|
219
|
+
Preferred interactive path:
|
|
220
|
+
|
|
221
|
+
- `Settings > Appearance > Language / Locale`
|
|
222
|
+
|
|
223
|
+
Global config path:
|
|
224
|
+
|
|
225
|
+
```text
|
|
226
|
+
~/.config/projmux/config.toml
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Schema:
|
|
230
|
+
|
|
231
|
+
```toml
|
|
232
|
+
[ui]
|
|
233
|
+
locale = "auto" # auto | en-US | ko-KR
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Resolution priority is:
|
|
237
|
+
|
|
238
|
+
1. `PROJMUX_LOCALE`
|
|
239
|
+
2. global/user `[ui] locale`
|
|
240
|
+
3. auto-detected environment: `LC_ALL`, then `LC_MESSAGES`, then `LANG`
|
|
241
|
+
4. built-in fallback `en-US`
|
|
242
|
+
|
|
243
|
+
`auto` means detect from the environment. In Settings, the `auto` detail shows
|
|
244
|
+
the currently detected locale and source. Supported UI locales are `en-US` and
|
|
245
|
+
`ko-KR`; unsupported tags fall back to `en-US` and the Settings detail shows a
|
|
246
|
+
warning with the unsupported value and source.
|
|
247
|
+
|
|
248
|
+
Project-local locale override is not part of the runtime policy. Locale is a
|
|
249
|
+
user/global preference in this release.
|
|
250
|
+
|
|
161
251
|
## Environment Variables
|
|
162
252
|
|
|
163
253
|
| Variable | Purpose |
|
|
@@ -165,6 +255,7 @@ configured key opens and closes the popup.
|
|
|
165
255
|
| `PROJMUX_PROJDIR` | Explicit primary project root. Accepts an OS-native PATH-style multi-value: the first non-empty entry is the primary root and later entries are prepended to managed-root discovery. The primary value is memoized to `~/.config/projmux/projdir`. |
|
|
166
256
|
| `PROJMUX_MANAGED_ROOTS` | Search-root override. Uses the OS-native path-list separator and takes priority over the saved workdirs file and default weak probes. |
|
|
167
257
|
| `TMUX_SESSIONIZER_ROOTS` | Legacy alias still honored at runtime for managed roots. |
|
|
258
|
+
| `PROJMUX_LOCALE` | UI locale override. `auto` resumes detection; `en-US` and `ko-KR` pin supported locales. Unsupported tags fall back to `en-US` and surface a Settings warning. |
|
|
168
259
|
| `PROJMUX_NOTIFY_HOOK` | External executable that receives AI desktop notifications instead of the built-in Linux/WSL sender. Separate from declarative `[hooks.send-noti]`. |
|
|
169
260
|
| `PROJMUX_NOTIFY_HOOK_DEPTH` | Internal recursion guard for `send-noti` hooks. Depth `>= 1` suppresses nested hook dispatch while still allowing the queue write itself. |
|
|
170
261
|
| `PROJMUX_NOTIFY_EXPIRE_MS` | AI desktop notification expiration in milliseconds. Defaults to `5000`; unset, zero, negative, and non-numeric values fall back to the default. |
|
package/docs/globalization.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Globalization Contract
|
|
2
2
|
|
|
3
3
|
This document is the inventory and contract for globalization. Phase 0 defined
|
|
4
|
-
the user-facing text boundary and literal preservation rules.
|
|
5
|
-
message catalog
|
|
6
|
-
|
|
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
7
|
|
|
8
8
|
## Phase 0 Scope
|
|
9
9
|
|
|
@@ -210,13 +210,16 @@ Catalog policy:
|
|
|
210
210
|
|
|
211
211
|
Locale resolution:
|
|
212
212
|
|
|
213
|
-
- Precedence is explicit override/API, then `
|
|
214
|
-
`LANG`, then `en-US`.
|
|
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
215
|
- Common POSIX forms normalize into catalog tags: `ko`, `ko_KR.UTF-8`, and
|
|
216
216
|
`ko-KR` become `ko-KR`; `en` and `en_US` become `en-US`.
|
|
217
217
|
- `C` and `POSIX` locales are skipped as non-user-language values.
|
|
218
|
-
-
|
|
219
|
-
|
|
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".
|
|
220
223
|
|
|
221
224
|
API convention:
|
|
222
225
|
|
|
@@ -242,3 +245,205 @@ Contribution convention:
|
|
|
242
245
|
- Runtime migrations should be narrow by surface. Move a string family behind
|
|
243
246
|
the catalog only when its tests can show literal preservation and fallback
|
|
244
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/pr-guideline.md
CHANGED
|
@@ -69,6 +69,11 @@ Use this template:
|
|
|
69
69
|
- [ ] make fmt-check
|
|
70
70
|
- [ ] make test
|
|
71
71
|
- [ ] manual verification step (if relevant)
|
|
72
|
+
|
|
73
|
+
## Globalization
|
|
74
|
+
- [ ] No user-facing string changes.
|
|
75
|
+
- [ ] User-facing strings are behind `internal/i18n` catalog keys with tests.
|
|
76
|
+
- [ ] Non-translated strings are classified as literal/data/debug-only.
|
|
72
77
|
```
|
|
73
78
|
|
|
74
79
|
Notes:
|
|
@@ -76,6 +81,11 @@ Notes:
|
|
|
76
81
|
- **Why** matters more than **what**. Diff already shows the what.
|
|
77
82
|
- Reference issues with `Closes #<n>` so they auto-close on merge.
|
|
78
83
|
- Mention follow-ups explicitly when scope was deliberately deferred.
|
|
84
|
+
- For any new or changed user-facing text, check exactly one Globalization
|
|
85
|
+
item. Normal UX copy needs a catalog key and test coverage. Commands, paths,
|
|
86
|
+
config keys, env vars, provider payloads, locale enum values, product names,
|
|
87
|
+
debug logs, and internal diagnostics may stay out of the catalog only when
|
|
88
|
+
explicitly classified in the PR body.
|
|
79
89
|
|
|
80
90
|
## Branch protection in effect
|
|
81
91
|
|
package/docs/settings-ia.md
CHANGED
|
@@ -71,6 +71,17 @@ view-first layout:
|
|
|
71
71
|
and `Notify icon` details. Each detail shows the current mode plus
|
|
72
72
|
immediately selectable off/symbol/emoji preview rows. There is no separate
|
|
73
73
|
`Change` page for icon decoration.
|
|
74
|
+
- `Settings > Appearance` also shows a read-only `Theme font` status row.
|
|
75
|
+
`font_family` and `font_size` are desired values from the effective
|
|
76
|
+
project/global theme, and unsupported terminal paths must say `not applied`
|
|
77
|
+
instead of implying tmux changed the font.
|
|
78
|
+
- `Settings > Appearance > Language / Locale` is the global/user language
|
|
79
|
+
detail. The root row shows the saved `[ui].locale` value and the currently
|
|
80
|
+
effective locale. The detail shows `Current`, `[ui].locale`, optional
|
|
81
|
+
`PROJMUX_LOCALE` env override, and direct choices for `auto`, `en-US`, and
|
|
82
|
+
`ko-KR`. When `auto` is active it must show the detected source (`LC_ALL`,
|
|
83
|
+
`LC_MESSAGES`, `LANG`, or fallback). Unsupported locale tags must remain
|
|
84
|
+
visible as warnings and fall back to `en-US`.
|
|
74
85
|
|
|
75
86
|
Hooks remain the reference pattern for this IA:
|
|
76
87
|
|
package/docs/statusbar.md
CHANGED
|
@@ -86,6 +86,11 @@ The notify segment renders the newest queued item as a single notification
|
|
|
86
86
|
block: project, state (`NEED`/`INFO`/`WARN`/`CRIT`), optional agent, text,
|
|
87
87
|
age, and `+N` for older pending entries. Window/pane ids are not shown in the
|
|
88
88
|
compact status segment.
|
|
89
|
+
The compact age text is locale-formatted through `internal/i18n` (`2m ago` in
|
|
90
|
+
`en-US`, `36초 전` in `ko-KR`). AI notify body text uses catalog-owned category
|
|
91
|
+
labels while preserving agent names, commands, paths, URLs, and provider
|
|
92
|
+
payload excerpts. The `+N` older-entry count remains a numeric compact badge so
|
|
93
|
+
it does not expand the status segment.
|
|
89
94
|
When the notify block is wider than its cell budget, clipping shrinks the body
|
|
90
95
|
text first and appends an ellipsis while preserving project, state, agent, age,
|
|
91
96
|
and count metadata. If the segment is still too wide, the age is dropped next
|
|
@@ -186,6 +191,9 @@ updates the matching live tmux option
|
|
|
186
191
|
(`@projmux_statusbar_decoration_cwd`, `_git`, or `_notify`) when run inside
|
|
187
192
|
tmux. The legacy `~/.config/projmux/statusbar-decoration` and
|
|
188
193
|
`@projmux_statusbar_decoration` remain fallback defaults for older configs.
|
|
194
|
+
Appearance also shows the effective desired theme font. This is a status row,
|
|
195
|
+
not a font editor: tmux status strings and ANSI output cannot force terminal
|
|
196
|
+
font family or size, so unsupported environments report `not applied`.
|
|
189
197
|
|
|
190
198
|
To add a new clickable segment:
|
|
191
199
|
|
package/docs/theme-palette.md
CHANGED
|
@@ -6,31 +6,70 @@ truth in code is `internal/theme/palette.go`.
|
|
|
6
6
|
|
|
7
7
|
## Scope
|
|
8
8
|
|
|
9
|
-
The fallback palette is a semantic token layer
|
|
10
|
-
|
|
11
|
-
the
|
|
9
|
+
The fallback palette is a semantic token layer. Theme settings resolve project
|
|
10
|
+
and global config into the resolver-facing token inventory below, then fall
|
|
11
|
+
back to the built-in values from `internal/theme/palette.go`.
|
|
12
12
|
|
|
13
13
|
- Native picker truecolor SGR tokens.
|
|
14
14
|
- Native sidebar and chip-strip 256-color SGR tokens.
|
|
15
15
|
- Tmux statusbar and generated-config color tokens.
|
|
16
16
|
- Settings/action/state/trust/attention helper tokens.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
Renderer adapters apply resolver-backed background/foreground colors to native
|
|
19
|
+
picker frame chrome and to tmux status/window background tokens when an
|
|
20
|
+
`EffectiveTheme` is supplied by the caller. Fallback-sourced fields still
|
|
21
|
+
render through the historical constants so built-in default output remains
|
|
22
|
+
byte-identical. Settings and native project picker surfaces load `[theme]`
|
|
23
|
+
values from global and project config through the shared effective-theme source.
|
|
24
|
+
Theme marketplace/import/export and Visual palette reselection remain out of
|
|
25
|
+
scope.
|
|
26
|
+
|
|
27
|
+
## Resolver Token Inventory
|
|
28
|
+
|
|
29
|
+
The public resolver inventory is intentionally smaller than the current
|
|
30
|
+
renderer literal inventory. Surface-specific renderers map their detailed roles
|
|
31
|
+
onto these stable names:
|
|
32
|
+
|
|
33
|
+
| Token | Meaning | Shared surfaces |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `background` | base popup/sidebar/status surface background | native picker, frame titlebar, notify sidebar, settings popup, statusbar |
|
|
36
|
+
| `surface` | raised or inactive chrome surface | frame titlebar, chips, switch cards, settings popup |
|
|
37
|
+
| `surface_active` | selected/current row or active chip surface | native picker current row, frame chips, statusbar active window |
|
|
38
|
+
| `foreground` | primary readable text | native picker, titlebar, statusbar, notify sidebar, settings popup |
|
|
39
|
+
| `muted` | secondary text, divider, disabled or stale details | picker metadata, titlebar rule, notify age/stale, settings descriptions |
|
|
40
|
+
| `accent` | pointer, primary action, highlight, active affordance | native picker pointer/highlight, settings actions, chips |
|
|
41
|
+
| `critical` | destructive/error/critical state | settings remove/quit, notify critical badge, statusbar critical usage |
|
|
42
|
+
| `warning` | progress, pending, warning, busy state | AI busy/thinking indicators, notify pending title, usage warning |
|
|
43
|
+
|
|
44
|
+
Renderer-only role names such as `accent.ai`, `state.progress`, `git.branch`,
|
|
45
|
+
and trust colors remain in `internal/theme/palette.go` until Phase 2+ maps each
|
|
46
|
+
surface to the resolver tokens. The key product contract for this phase is that
|
|
47
|
+
native picker, frame titlebar, chips, statusbar, notify sidebar, and settings
|
|
48
|
+
popup all consume a shared effective token set instead of independently
|
|
49
|
+
choosing colors.
|
|
50
|
+
|
|
51
|
+
Font is not part of this universal token inventory. `font_family` and
|
|
52
|
+
`font_size` are resolved as terminal capability/profile hints: projmux can
|
|
53
|
+
store and display the desired value, but tmux/ANSI rendering cannot force a
|
|
54
|
+
font family or size across terminal emulators. In environments without a
|
|
55
|
+
supported terminal font adapter, projmux reports the desired font as
|
|
56
|
+
`not applied` instead of treating storage as a successful font change.
|
|
22
57
|
|
|
23
58
|
## Mapping Policy
|
|
24
59
|
|
|
25
60
|
Native picker rows can emit truecolor SGR, while tmux statusbar/config strings
|
|
26
|
-
must use tmux color specs. The
|
|
27
|
-
|
|
61
|
+
must use tmux color specs. The resolver therefore carries both forms for each
|
|
62
|
+
color token.
|
|
28
63
|
|
|
29
64
|
Rules:
|
|
30
65
|
|
|
31
|
-
- Truecolor tokens keep exact
|
|
32
|
-
|
|
66
|
+
- Truecolor tokens keep exact `#RRGGBB` values and can be converted to
|
|
67
|
+
foreground/background SGR fragments such as `38;2;R;G;B` or `48;2;R;G;B`.
|
|
33
68
|
- Tmux tokens keep `colourN` strings where tmux owns rendering.
|
|
69
|
+
- The built-in `projmux-dark` fallback uses the established ANSI and tmux
|
|
70
|
+
tokens from `internal/theme/palette.go` to preserve current output.
|
|
71
|
+
- Explicit `#RRGGBB` overrides keep exact truecolor and derive the closest
|
|
72
|
+
xterm 256-color `colourN` token for tmux surfaces.
|
|
34
73
|
- Native chip/sidebar badge tokens use 256-color SGR when they intentionally
|
|
35
74
|
mirror tmux colors.
|
|
36
75
|
- Output compatibility wins inside this baseline. For example, the kube
|
|
@@ -39,6 +78,35 @@ Rules:
|
|
|
39
78
|
- Renderers should reference semantic names instead of spelling color literals
|
|
40
79
|
directly. Test fixtures may still pin rendered escape strings.
|
|
41
80
|
|
|
81
|
+
## Resolver Contract
|
|
82
|
+
|
|
83
|
+
Theme resolution is field-by-field after validating each layer:
|
|
84
|
+
|
|
85
|
+
1. Project `.projmux/config.toml`
|
|
86
|
+
2. Global `~/.config/projmux/config.toml`
|
|
87
|
+
3. Built-in fallback preset `projmux-dark`
|
|
88
|
+
|
|
89
|
+
Rules:
|
|
90
|
+
|
|
91
|
+
- Project values override global values for the same field.
|
|
92
|
+
- Missing or `inherit` project values fall back to global values.
|
|
93
|
+
- Missing global values fall back to built-in values.
|
|
94
|
+
- A preset fills missing color tokens in its own layer.
|
|
95
|
+
- Explicit color tokens in the same layer override preset colors.
|
|
96
|
+
- An unknown preset invalidates only that layer and emits a warning.
|
|
97
|
+
- An invalid color, `font_family`, or `font_size` invalidates only that layer
|
|
98
|
+
and emits a warning.
|
|
99
|
+
- Every effective field reports `project`, `global`, or `fallback` as its
|
|
100
|
+
source label.
|
|
101
|
+
|
|
102
|
+
Built-in preset config values are:
|
|
103
|
+
|
|
104
|
+
- `projmux-dark`
|
|
105
|
+
- `midnight`
|
|
106
|
+
- `forest`
|
|
107
|
+
- `rose`
|
|
108
|
+
- `high-contrast`
|
|
109
|
+
|
|
42
110
|
## Fallback Inventory
|
|
43
111
|
|
|
44
112
|
Chrome and text:
|
|
@@ -90,6 +158,7 @@ After the Phase 3 token pass, raw color values intentionally remain in:
|
|
|
90
158
|
The converted implementation paths include:
|
|
91
159
|
|
|
92
160
|
- `internal/ui/projmuxpicker/ansi.go`
|
|
161
|
+
- `internal/ui/projmuxpicker/frame.go`
|
|
93
162
|
- `internal/app/tmux.go`
|
|
94
163
|
- `internal/app/status.go`
|
|
95
164
|
- `internal/app/statusbar.go`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projmux",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "tmux project session manager",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/crevissepartners/projmux#readme",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"LICENSE"
|
|
25
25
|
],
|
|
26
26
|
"optionalDependencies": {
|
|
27
|
-
"@projmux/darwin-arm64": "0.6.
|
|
28
|
-
"@projmux/darwin-x64": "0.6.
|
|
29
|
-
"@projmux/linux-arm64": "0.6.
|
|
30
|
-
"@projmux/linux-x64": "0.6.
|
|
27
|
+
"@projmux/darwin-arm64": "0.6.5",
|
|
28
|
+
"@projmux/darwin-x64": "0.6.5",
|
|
29
|
+
"@projmux/linux-arm64": "0.6.5",
|
|
30
|
+
"@projmux/linux-x64": "0.6.5"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"package:npm": "scripts/package-npm.sh",
|