projmux 0.15.2 → 0.16.0

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.
@@ -2,9 +2,10 @@
2
2
 
3
3
  The machine-readable ledger is retained as historical liveness evidence only.
4
4
  It is **not** capability authority for `durable-zero-turn-resume` or
5
- `remote-new-session`; those predicates require the exact executable tuple and
6
- the Phase-1 conformance record described in
7
- [`codex-native-required-migration.md`](codex-native-required-migration.md).
5
+ `remote-new-session`. The private generation pool that once owned that
6
+ conformance record has been removed; see
7
+ [`codex-native-required-migration.md`](codex-native-required-migration.md) for
8
+ the payload-free create behavior that remains.
8
9
  The legacy [`codex-installed-capabilities.json`](codex-installed-capabilities.json)
9
10
  schema separates method evidence from the semantic result:
10
11
 
@@ -42,8 +43,8 @@ observation. It must not be cited as payload-free support.
42
43
  The observation historically extended the earlier `pre-turn-attach` owner.
43
44
  That hosted evidence remains run `33560743314`,
44
45
  aggregate artifact `9821171919`, where the same tuple's direct pre-turn
45
- qualification was `pass`. Neither pass is an input to the new exact
46
- payload-free capability authority.
46
+ qualification was `pass`. Neither pass is capability authority for the
47
+ payload-free predicates above.
47
48
 
48
49
  Scheduled and manual `Installed Codex Qualification` artifacts use
49
50
  qualification schema v2 and embed this schema-versioned capability ledger.
@@ -59,11 +60,5 @@ records `github-actions:33566050834:1`.
59
60
  - `TestInstalledIsolatedPreTurnBootstrapSmoke` — historical owner for
60
61
  turn-free start/read/loaded observation and live-Pane liveness; not a
61
62
  payload-free support verdict.
62
- - `TestInstalledExactPayloadFreeCapabilityMatrix` — exact private owner for
63
- zero-turn start/read/stored-resume plus content-free remote-new liveness. It
64
- sends no input or turn, so remote-new remains unknown.
65
63
  - `TestInstalledCensusDeletionReceiptHasOneOwnerPerPrimitive` — topology and
66
64
  protocol ownership plus the Phase 2 merge receipt.
67
-
68
- The maintained repository-wide list in `docs/agent-workflow.md` records the
69
- current Phase-1 authority separately.
@@ -21,61 +21,7 @@ provider response is stored to produce that signal.
21
21
  The Phase-7 zero-turn durable-readiness failure is retained only as historical
22
22
  negative safety evidence. A typed Failed Agent with no Pane is not functional
23
23
  create success. Prompted native create, app-server picker resume, existing
24
- Agent resume, and generation-pinned routes keep their native contracts.
25
-
26
- ## Exact payload-free capability authority (Phase 1)
27
-
28
- Payload-free qualification is now owned by
29
- `internal/integrations/agents/codexgeneration`. A record is valid for exactly
30
- one tuple: RoleTUI binary SHA-256 and size, RoleAppServer binary SHA-256 and
31
- size, app-server version, protocol transport/schema, private socket locator and
32
- bound-runtime digests, state-domain identity/path digest, and platform/arch.
33
- Changing any one axis is a cache miss. A missing, corrupt, trailing, future
34
- schema, stopped, or rebound tuple projects `unknown` and the Phase-0
35
- `plain-fallback`; no semver family, changelog, or successful `thread/read` is an
36
- authority substitute.
37
-
38
- The record reduces two independent executable predicates:
39
-
40
- - `durable-zero-turn-resume` requires the same hashed exact thread to pass
41
- zero-turn start, independent read, and stored resume. Read visibility alone
42
- cannot promote it. Exact 0.153.0 private evidence is read-visible but stored
43
- resume is `unsupported/no-rollout-found`.
44
- - `remote-new-session` requires more than a living TUI. The remote-new thread
45
- and the exact first real input's thread must match, the turn identity must be
46
- present, and the content-free turn cardinality must be exactly one. An
47
- unrelated first-turn event or liveness-only observation stays `unknown`.
48
-
49
- Evidence stores timestamps, digests, closed outcomes, cardinality, and boolean
50
- identity facts only. It has no field for prompts, provider output, turns,
51
- transcripts, socket paths, or state paths. Doctor JSON/text and the create
52
- planner consume the same immutable record projection. Phase 1 intentionally
53
- maps every verdict—including a supported private observation—to
54
- `plain-fallback`; the remote-new production launch belongs to Phase 2.
55
-
56
- The private installed matrix is opt-in and starts/stops only exact root-owned
57
- app-server and tmux fixtures:
58
-
59
- ```sh
60
- smoke_root="$(mktemp -d /tmp/projmux-payload-free-XXXXXX)"
61
- env -u TMUX -u TMUX_PANE \
62
- PROJMUX_CODEX_PAYLOAD_FREE_SMOKE_ROOT="$smoke_root" \
63
- PROJMUX_CODEX_PAYLOAD_FREE_SOURCE_HOME=/absolute/private/copied-source-home \
64
- PROJMUX_CODEX_PAYLOAD_FREE_0152_0=/absolute/0.152.0/bin/codex \
65
- PROJMUX_CODEX_PAYLOAD_FREE_0152_1=/absolute/0.152.1/bin/codex \
66
- PROJMUX_CODEX_PAYLOAD_FREE_0153_0=/absolute/0.153.0/bin/codex \
67
- go test ./internal/testutil/codexinstalled \
68
- -run '^TestInstalledExactPayloadFreeCapabilityMatrix$' -count=1 -v
69
- ```
70
-
71
- An unset binary row is logged `unavailable`; the fixture never synthesizes a
72
- tuple. The installed probe sends no input, prompt, or turn. It may record
73
- content-free TUI liveness/loaded state, but remote-new remains `unknown`
74
- without a separately supplied exact first-real-input thread/turn observation.
75
- Use the documented short smoke-root shape: an overlong private tmux socket path
76
- is rejected before any lifecycle operation and cannot masquerade as liveness.
77
- After fixture cleanup the socket has no current route identity, so transient
78
- private evidence cannot be reused by another route.
24
+ Agent resume, and stored-endpoint routes keep their native contracts.
79
25
 
80
26
  ## Native-required prompted create (0.14.0)
81
27
 
@@ -254,10 +200,6 @@ go test ./internal/integrations/agents/codexappserver/ -run TestStartDefaultThre
254
200
  | Both `--interactive-only` spellings are equivalent, and non-Codex providers refuse it at zero transactions | `TestInteractiveOnlyIsTheOnlyPlainCodexLaneAndBothSpellingsAreEquivalent` |
255
201
  | Payload cardinality × `--interactive-only` × readiness stays a closed pre-provider decision table | `TestCodexCreatePayloadCardinalityInteractiveOnlyAndReadinessOutcomeTable` |
256
202
  | Canonical and shortcut payload-free create are byte/argv-equivalent to the explicit plain lane and touch no provider route | `TestPayloadFreeCodexCreateUsesSafePlainFallbackAndInteractiveOnlyEquivalentLane` |
257
- | Exact tuple keys, immutable cache fixed points, and one-axis drift/corrupt/future/trailing fail closed | `TestCapabilityCacheInvalidatesEveryExactTupleAxis`, `TestCapabilityCacheCorruptFutureAndTrailingRecordsResolveUnknown` |
258
- | Read visibility and stored resume reduce independently; remote-new requires the exact first real thread/turn | `TestExactPayloadFreeCapabilitySeparatesReadVisibleFromStoredResumable`, `TestRemoteNewCapabilityRequiresExactFirstRealInputThreadAndTurn` |
259
- | Doctor and create plan consume byte-semantic identical capability projections while Phase 1 stays plain | `TestCodexPayloadFreeDoctorAndCreatePlannerShareExactRecordProjection`, `TestCodexPayloadFreeUnknownCapabilityCannotBypassPhaseZeroFallback` |
260
- | Available exact installed binaries are qualified independently in creator-live/closed private rows | `TestInstalledExactPayloadFreeCapabilityMatrix` |
261
203
  | Saved-default, provider-picker, and direct-provider AI intents produce one managed plain lane without native mutation | `TestEmptyPromptCodexSplitProducersKeepOnePlainCLILane` |
262
204
  | A failed plain launch rolls Registry and tmux back and never tries a provider lane | `TestPayloadFreeCodexPlainLaunchFailureRollsBackWithoutProviderMutation` |
263
205
  | The installed outcome requires a Running plain Agent/Pane, no session ref, zero provider-thread delta, diagnostic signals, isolated socket cleanup, and ambient mutation zero | `TestInstalledPayloadFreePlainFallbackOutcomeSmoke` |
@@ -38,13 +38,15 @@ those folders exist:
38
38
 
39
39
  It does not assume a canonical repo root.
40
40
 
41
- Use Settings > Project Picker for the normal interactive flow:
41
+ Use `Settings > Global > Projects` for the normal interactive flow:
42
42
 
43
- - `Project Root` sets, changes, or clears the saved primary root.
44
- - `+ Add Workdir...` appends one directory to the saved workdirs list.
45
- - `Workdirs` reviews and removes saved workdirs.
43
+ - `Primary discovery root` sets, changes, or clears the saved primary root.
44
+ - `Additional discovery roots > Add path` appends one directory to the saved
45
+ workdirs list.
46
+ - `Additional discovery roots` reviews saved workdirs; each root's
47
+ `Remove discovery root` removes it.
46
48
 
47
- `Add Workdir > Type path manually...` skips the filesystem scan and is useful
49
+ `Add path > Type path manually...` skips the filesystem scan and is useful
48
50
  for large mounts, WSL paths, NFS paths, or temporary project roots.
49
51
 
50
52
  The saved workdir file is:
@@ -56,7 +58,7 @@ The saved workdir file is:
56
58
  It stores one absolute path per line. Lines beginning with `#` are comments.
57
59
  The file is read only when no env root list is set.
58
60
 
59
- Workdirs are a **scan source and nothing else**. Adding a root, and scanning one,
61
+ Saved workdirs are a **scan source and nothing else**. Adding a root, and scanning one,
60
62
  never registers a Registry Project: a discovered child is an unregistered
61
63
  candidate until `projmux create project --root <path>` or opening it once from the
62
64
  Projects sidebar registers that exact path. See
@@ -92,51 +94,11 @@ request with `projmux pin project migrate`; see
92
94
  [upgrading.md](upgrading.md#pins-are-typed-and-migrate-on-request) for the
93
95
  per-line outcomes and the ambiguity refusal.
94
96
 
95
- ## Legacy Project Layout Snapshots
97
+ ## Legacy Project Layout Files
96
98
 
97
- Older checkouts may already have named layout snapshots in the legacy storage
98
- directory:
99
-
100
- ```text
101
- <project>/.projmux/layouts/<name>.toml
102
- ```
103
-
104
- The project context comes from `PROJMUX_CWD` when set, otherwise projmux walks
105
- upward from the current directory to the nearest `.projmux` or `.git` marker.
106
- Files outside that project tree are not discovered. This storage is treated as
107
- legacy import data for explicit conversion and preview. Closed-Project startup
108
- does not expose legacy snapshot choices; current user-facing surfaces describe
109
- the restore unit as a snapshot, not as a separate layout or preset feature.
110
-
111
- The legacy schema is intentionally close to the session-state snapshot shape:
112
-
113
- ```toml
114
- schema_version = 1
115
- description = "Daily dev"
116
- mode = "inherit-autosave" # default; or "fresh-each-time"
117
- default_cwd = "${PROJMUX_CWD}"
118
-
119
- [[windows]]
120
- index = 0
121
- name = "main"
122
- layout = "..."
123
- active_pane_index = 0
124
-
125
- [[windows.panes]]
126
- index = 0
127
- cwd = "${PROJMUX_CWD}"
128
- command = "make watch"
129
- ```
130
-
131
- `command` records a startup recipe, matching the supported session-state replay
132
- recipe. Panes without `command` may use `recipe = "shell"`. Supported
133
- interpolation placeholders are limited to `${PROJMUX_CWD}` and
134
- `${PROJMUX_SESSION}`; other `${...}` values are rejected during load.
135
-
136
- Unknown fields and unknown sections are ignored so future schema additions do
137
- not break older files. The built-in parser only accepts quoted strings and
138
- integer values for the known fields above; it does not implement the full TOML
139
- language.
99
+ Older checkouts may still have named layout files under
100
+ `<project>/.projmux/layouts/*.toml`. projmux no longer reads, writes, trusts,
101
+ or deletes them; they have no effect and can be removed by hand.
140
102
 
141
103
  ## Keymap File
142
104
 
@@ -234,7 +196,7 @@ popup action with no built-in shortcut. Every configured alias renders the
234
196
  canonical client-scoped body
235
197
  `projmux internal tmux popup-toggle --client #{client_tty} resource-inspector`; pressing
236
198
  the same alias again closes only that client's popup. It remains available on
237
- Linux/tmux even when the Labs live-resource status segment is off.
199
+ Linux/tmux even when the `Status Bar > Resources` live-resource segment is off.
238
200
 
239
201
  The Settings writer is deterministic and rewrites the supported saved subset
240
202
  only. If the existing file has parse errors or unknown action IDs, Settings
@@ -342,6 +304,7 @@ success = "#5faf87"
342
304
  action_required = "#ffaf00"
343
305
  pane_active_bg = "default"
344
306
  focus = "#00ffff"
307
+ provenance = "#ff8700"
345
308
  ```
346
309
 
347
310
  `text_primary` controls primary content text in native terminal-rendered UI.
@@ -360,6 +323,13 @@ active-pane background tint, and `focus` is the active-pane border color. Each
360
323
  of these is a public token: leave it unset to keep the historical built-in
361
324
  color, or set it to repaint the matching chrome.
362
325
 
326
+ `provenance` is the compact usage label color for a provider row whose numbers
327
+ came from a fallback data source rather than its authoritative one (today: a
328
+ Codex row outside a healthy app-server). It is independent of `warning` and
329
+ `critical`, which stay reserved for usage thresholds, and of the ordinary AI
330
+ label color; the fallback value is orange. See `docs/usage-tracking.md` for what
331
+ the label looks like and `docs/theme-palette.md` for the preset contract.
332
+
363
333
  Supported presets are `projmux`, `high-contrast`, `blue-hour`, `carbon-violet`,
364
334
  `daylight`, `ember`, `forest`, and `rose`. `daylight` is the fully-light
365
335
  preset; the others are dark. Preset colors paint projmux chrome only (status
@@ -457,30 +427,11 @@ in-flight process decision, then retries proxy initialization with a bounded
457
427
  backoff. Projmux never automatically stops, kills, restarts, adopts, or enables
458
428
  remote control on the shared app server.
459
429
 
460
- The default `Codex` row in the provider picker launches immediately through the
430
+ The `Codex` row in the provider picker launches immediately through the
461
431
  canonical create route. It does not start or probe the app-server, call
462
432
  `model/list`, or add `--model` or `model_reasoning_effort`; the Codex process
463
- therefore keeps its own configured defaults.
464
-
465
- The separate `Codex advanced launch` action uses the readiness path to read
466
- every page of the current app-server `model/list`. Its second picker shows only
467
- visible models and their advertised reasoning efforts. The display also carries
468
- the advertised default, supported input modalities, and whether personality is
469
- supported; the boolean personality capability is not expanded into invented
470
- personality choices. The selected model and effort are launch-only CLI
471
- overrides (`--model` and `--config model_reasoning_effort=...`); Projmux never
472
- writes a Codex configuration file. Each normalized catalog is tied to its live
473
- connection and negotiated-version epoch. Projmux retains that connection from
474
- picker render through pre-create validation and refreshes `model/list` before
475
- building argv, so a disconnect or removed option invalidates the selection. If
476
- advanced discovery fails, is empty, or comes from an older Codex, that action
477
- reports the exact unavailable reason and creates nothing; the separate default
478
- `Codex` row remains available.
479
-
480
- Picker chrome and semantic annotations such as default, unspecified modality,
481
- and personality support use the Projmux message catalog. Model display names,
482
- effort identifiers, and advertised modality tags remain exact provider data and
483
- are not translated.
433
+ therefore keeps its own configured defaults. The picker has no per-launch model
434
+ or effort row.
484
435
 
485
436
  `projmux agent review` starts `review/start` only for a Running Codex Agent whose
486
437
  Registry Agent, owned Pane, activation generation, stored thread, and live Pane
@@ -517,6 +468,76 @@ desktop intent for both app-server and hook-fallback authority. Existing
517
468
  runtime override exists, take precedence only while hook fallback is current;
518
469
  they are never inferred or copied into the semantic policy store.
519
470
 
471
+ ## Split Start Directory
472
+
473
+ New splits start in the owner Project root. `[ai] split_cwd_from = "pane"`
474
+ starts UI splits in the active Pane's live directory instead, while that
475
+ directory is inside the owner Project root. Settings exposes the same value as
476
+ `AI > New splits start in` (`Project root` / `Current Pane directory`); choosing
477
+ one writes only the global `[ai] split_cwd_from`.
478
+
479
+ Config paths (global and project both honored):
480
+
481
+ ```text
482
+ ~/.config/projmux/config.toml # global
483
+ <project>/.projmux/config.toml # project
484
+ ```
485
+
486
+ Schema:
487
+
488
+ ```toml
489
+ [ai]
490
+ split_cwd_from = "project" # project|pane; where a new shell or Agent split starts
491
+ ```
492
+
493
+ Resolution depends on who starts the split.
494
+
495
+ **CLI** (`create pane`, `create agent`, and the provider shortcuts) — the flag
496
+ only:
497
+
498
+ 1. `--cwd-from project|pane`
499
+ 2. otherwise `project`
500
+
501
+ The CLI opens no config file for this decision. A CLI result is determined by
502
+ its arguments, so scripts and automation keep starting in the Project root when
503
+ someone changes this setting.
504
+
505
+ **UI** (keybinding splits, the launcher, the resume picker's new row, and the
506
+ Pane menu) — the config tiers:
507
+
508
+ 1. an explicit per-call value (flag)
509
+ 2. project `[ai] split_cwd_from`, read from the owner Project root
510
+ 3. global/user `[ai] split_cwd_from`
511
+ 4. built-in default (`project`)
512
+
513
+ There is no environment override, and an unknown value skips its own tier. The
514
+ project tier is always read from the owner Project root, so where a Pane sits
515
+ never changes which config decides. The Settings row shows the UI result and the
516
+ tier that decided it (`project`, `global`, or `default`).
517
+
518
+ With `pane` selected, the active Pane is the origin of the split: the Pane a
519
+ keybinding ran in, the Pane a right-click menu was opened on, or the anchor Pane
520
+ a CLI create resolved. Its live directory is used only when it is inside the
521
+ owner Project root. `$HOME`, another registered Project tree, a directory that no
522
+ longer exists, and an unreadable directory all start in the Project root and
523
+ report one line naming the reason and that root — on stderr for a CLI create
524
+ with `--cwd-from pane`, and as one client message for a split started from the
525
+ UI. A split is never refused for this reason. `--cwd` on `create agent` still
526
+ names the Agent working directory outright and ignores this setting.
527
+
528
+ ## Enabled AI Providers
529
+
530
+ Disabled providers are a central policy, stored in
531
+ `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-enabled-agents`, that the CLI
532
+ honors as well as the UI: `create agent`, `create window --provider`, and
533
+ `agent resume` refuse a disabled provider, and the refusal names the command
534
+ that re-enables it.
535
+ `projmux config providers` lists every provider as `<id> enabled` or
536
+ `<id> disabled`; `projmux config providers --enable <id>` and
537
+ `--disable <id>` change one through the same writer as
538
+ `Settings > Global > AI > Enabled providers`. A missing file means every
539
+ provider is enabled; disabling every provider persists as none enabled.
540
+
520
541
  ## AI Resume Picker
521
542
 
522
543
  The Agent resume picker lists the most recent
@@ -526,7 +547,7 @@ the defaults are 30 rows and depth 0 (the current directory only).
526
547
 
527
548
  Preferred interactive path:
528
549
 
529
- - `Settings > AI Settings > Resume picker`
550
+ - `Settings > Global > AI > Agent Resume Picker` (`Picker limit`, `Scan depth`)
530
551
 
531
552
  Config paths (global and project both honored):
532
553
 
@@ -584,17 +605,8 @@ existence/mtime. They do not open SQLite content and do not treat `.db-wal`,
584
605
  latest-session floor rather than complete history. Missing/malformed cache,
585
606
  workspace-less metadata, and stale mappings degrade to legacy `history.jsonl`
586
607
  without changing the shared exact/depth/sort/cap behavior.
587
- Live hook/session-state resume metadata is a separate high-confidence lane and
588
- is not a disk-picker candidate. When a disk picker selection creates a pane,
589
- its source is persisted so Session State preview and doctor can report medium
590
- confidence for DB-validated cache sources or low confidence for legacy history.
591
-
592
- Session State saves the exact bound Codex session/thread id before considering
593
- discovery. An existing bound session id or persisted resume id is replayed
594
- without an app-server read. Only a thread-only candidate is validated with
595
- `thread/read` and `includeTurns=false`; this validation is probe-only and never
596
- starts the shared daemon. Failure retains the persisted id or uses the current
597
- rollout fallback, and a read response can never substitute a different id.
608
+ Live hook resume metadata is a separate high-confidence lane and is not a
609
+ disk-picker candidate.
598
610
 
599
611
  ## Release channel
600
612
 
@@ -638,7 +650,7 @@ installed; that install stays put until its stable line ships.
638
650
 
639
651
  | Variable | Purpose |
640
652
  | --- | --- |
641
- | `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`. |
653
+ | `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`. The legacy `PROJDIR` and `RP` env vars are no longer honored. |
642
654
  | `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. |
643
655
  | `TMUX_SESSIONIZER_ROOTS` | Legacy alias still honored at runtime for managed roots. |
644
656
  | `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. |
@@ -650,12 +662,12 @@ installed; that install stays put until its stable line ships.
650
662
  | `PROJMUX_DESKTOP_NOTIFY_MODE` | OS desktop notification mode override. `off` / `none` / `notify` (case insensitive). When set, this takes priority over every other resolution rung. The in-app notify queue is not affected. The retired `raise` / `auto-raise` / `autoraise` literals are still accepted and read as `notify`. |
651
663
  | `PROJMUX_DESKTOP_NOTIFY` | Legacy on/off override kept for backward compatibility. `on` maps to `notify`, `off` maps to `none`. Honored only when `PROJMUX_DESKTOP_NOTIFY_MODE` is unset. |
652
664
  | `PROJMUX_WSL_TOAST_ICON_DIR` | Directory used when copying the WSL toast icon into a Windows-readable path. |
653
- | `PROJMUX_USAGE_STATE_DIR` | Override directory for AI usage snapshots. Defaults to `<state>/projmux/usage`. Point this at a synced directory to share authoritative usage across machines. |
665
+ | `PROJMUX_USAGE_STATE_DIR` | Override directory for AI usage snapshots. Defaults to `<state>/projmux/usage`. Point this at a synced directory to share authoritative usage across machines. The value is used as given, with no `~` expansion. |
654
666
  | `PROJMUX_USAGE_DEBUG` | When non-empty, prints adapter errors from the `projmux internal status usage` renderer to stderr. |
655
667
  | `PROJMUX_USAGE_LIMITS_PATH` | Deprecated. Read but ignored; limits now come from upstream APIs and local Codex rollout state. |
656
- | `PROJMUX_SESSIONSTATE_AUTOSAVE` | Session snapshot autosave override for the global fallback. Values such as `off`, `false`, or `0` disable autosave for projects that inherit the global setting; explicit project auto-save `on`/`off` still takes precedence. |
657
- | `PROJMUX_SESSIONSTATE_DEBUG` | When non-empty, quiet autosave surfaces suppressed session-state errors to stderr. |
658
- | `PROJMUX_FOCUS_DEBUG` | When non-empty, `projmux focus` prints one telemetry line to stderr. |
668
+ | `PROJMUX_SESSIONSTATE_AUTOSAVE` | Ignored. Project snapshots and their auto-save were removed. |
669
+ | `PROJMUX_SESSIONSTATE_DEBUG` | Ignored. It only gated stderr for the removed quiet autosave. |
670
+ | `PROJMUX_FOCUS_DEBUG` | When non-empty, `projmux focus` prints one telemetry line to stderr with the target, session, window, pane, socket, client, source, and kind. |
659
671
  | `PROJMUX_INSTALLER` | Installer source hint used by update flows. npm installs set this automatically; advanced release installs can set `github-release`. |
660
672
  | `PROJMUX_RELEASE_CHANNEL` | Release channel the update judgment is made against, orthogonal to `PROJMUX_INSTALLER`. Only an exact `rc` opts in; unset, empty, and unrecognised values all mean the default `stable` channel, which never sees a prerelease. An rc install is answered with whichever of the stable and rc lines is newer, so it returns to stable as soon as that line ships. Read only until `[update] release_channel` exists; see [Release channel](#release-channel). |
661
673
  | `PROJMUX_SHELL_UPDATE_CHECK_TIMEOUT_MS` | Timeout in milliseconds for the best-effort release check attempted by `projmux shell` when the update cache is missing or stale. Invalid, zero, or negative values use the default. |
@@ -706,7 +718,7 @@ export PROJMUX_PROJDIR="/main/repos:/srv/work/repos"
706
718
  On Linux and macOS the separator is `:`. On Windows-style paths the separator
707
719
  is `;`.
708
720
 
709
- ## tmux Project Root Option
721
+ ## tmux Primary Discovery Root Option
710
722
 
711
723
  The switch command also reads this tmux option:
712
724
 
@@ -768,7 +780,8 @@ seconds window. Resolution priority is:
768
780
  `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-notify-dedupe-seconds`
769
781
  3. default `120`
770
782
 
771
- Settings exposes this at `Settings > Notifications > AI notification dedupe`.
783
+ Settings exposes this at
784
+ `Settings > Global > Notifications > Desktop delivery > Dedupe window`.
772
785
  The value is stored as integer seconds and applies only to AI desktop
773
786
  notification dispatch. The tmux bell fallback keeps its fixed 5 second
774
787
  dedupe window.
@@ -853,7 +866,7 @@ Settings press through the new row writes `desktop-notify-mode`, mirrors the
853
866
  new value into `@projmux_desktop_notify_mode` when tmux is live, and leaves the
854
867
  legacy key unused. No eager rewrite of tmux state.
855
868
 
856
- Toggle from Settings > Notifications > `Desktop notifications`. The
869
+ Choose it from `Settings > Global > Notifications > Desktop delivery > Delivery mode`. The
857
870
  Settings info row labels the effective source as `env`, `env (legacy)`,
858
871
  `setting`, `setting (legacy)`, or `default` so users see which rung of
859
872
  the cascade pinned the value. `projmux config apply` regenerates the live tmux
@@ -899,28 +912,35 @@ ${PROJMUX_USAGE_STATE_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/projmux/usage}/
899
912
  See [Usage tracking](usage-tracking.md) for adapter behavior, throttling, and
900
913
  failure handling.
901
914
 
902
- ## Session State
903
-
904
- `projmux shell` autosaves session snapshots from the app tmux status tick. The
905
- autosave command is quiet and debounced per session, and stores snapshots under
906
- `${XDG_STATE_HOME:-$HOME/.local/state}/projmux/sessions`.
907
-
908
- Global auto-save defaults to `off` on a fresh install. Project auto-save is an
909
- override with `inherit`, `on`, and `off`; `inherit` follows the global value,
910
- while `on` and `off` take precedence. Auto-save only updates the latest
911
- snapshot. Named snapshots are manual and are never updated by auto-save.
912
-
913
- With no saved preference, Project open from the Alt-1 sidebar shows a native
914
- `Start project` step with exactly `Continue project` and `Recreate Project`.
915
- Settings > Projects > Project Sidebar > Closed Project startup reports this as
916
- `Continue project / Recreate Project - default`. A saved `on` keeps the same explicit
917
- choice and reports `Continue project / Recreate Project - on - saved`. A saved `off`
918
- reports `Continue project - off - saved` and skips the picker: a registered root
919
- continues, while an unregistered root follows the existing Fresh adjudication.
920
- Resolving or cancelling the missing-file default never creates the preference
921
- file or changes saved bytes or mtime. `Recreate Project` confirms first, then atomically replaces the old Project graph
915
+ ## Project Startup
916
+
917
+ The Registry (`registry.json`) is the only saved Project state; see
918
+ [session-restore.md](session-restore.md). projmux keeps no separate Project
919
+ snapshot store. Nothing reads the former
920
+ `${XDG_STATE_HOME:-$HOME/.local/state}/projmux/sessions/*.json` snapshot
921
+ files; they are removed by `config apply`. The app tmux status tick saves
922
+ nothing: generated status lines carry no auto-save job, and the hidden
923
+ `internal tmux autosave-session-state` route that older generated configs
924
+ still call is a silent no-op that writes nothing and records no diagnostics.
925
+ The `sessionstate-autosave` and `sessionstate-autosave-interval` files and the
926
+ per-Project `sessionstate-projects/<session>/autosave` files are removed by
927
+ `config apply`, together with the `sessions/` and `sessionstate-projects/`
928
+ directories once they are empty. Any other entry there is kept, and listed
929
+ by the apply that removes the files.
930
+ `PROJMUX_SESSIONSTATE_AUTOSAVE` is still ignored without a warning.
931
+
932
+ Opening a registered closed Project from the Alt-1 sidebar shows a native
933
+ `Start project` step with exactly `Continue project` and
934
+ `Clear layout and open`. A root that is not a registered Project skips that
935
+ step and opens fresh, which registers it. There is no setting that skips the
936
+ step for a registered Project.
937
+ An explicit `Continue project` on a root that is not a registered Project
938
+ refuses with zero writes and points to `Clear layout and open`.
939
+ `Clear layout and open` clears only the saved Window and Agent layout: the
940
+ folder, its files, `.projmux/config.toml`, and trust stay. It confirms first,
941
+ then atomically replaces the old Project graph
922
942
  with a new Project UID and a new canonical Window/shell UID pair. Exactly one
923
- same-root Project claimant remains. Snapshot bytes, the root directory,
943
+ same-root Project claimant remains. The root directory,
924
944
  Git/worktree data, and the trust decision remain unchanged. Esc returns to
925
945
  Projects with zero writes. After
926
946
  the startup mode is selected, project automation trust is evaluated if needed.
@@ -932,62 +952,17 @@ Deny/cancel refreshes the original sidebar query/selection context with a
932
952
  visible status message. Existing sessions switch directly without a startup
933
953
  picker.
934
954
 
935
- Default `projmux shell` no longer opens a startup picker or replays session-state
936
- snapshots before attach. It still derives the default app session identity and
937
- startup directory from the current project context when available; otherwise it
938
- uses the `home` target and home directory. Snapshot restore is an explicit CLI
939
- operation that requires both the source session and the exact target Project;
940
- it is not a Project-startup choice.
941
-
942
- Settings > Session State is global settings only: global auto-save, auto-save
943
- interval, and storage/retention policy. Settings > Project > Session State
944
- is override/effective-focused: project identity, project auto-save
945
- `inherit`/`on`/`off`, effective auto-save value/source, and snapshot save
946
- actions. Snapshot inspection lives under `Projects > Sessions > State`, whose
947
- overview shows latest/named snapshot status and the window -> pane read model
948
- without immediate mutation.
949
-
950
- The saved global toggles live under
951
- `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-autosave`,
952
- `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-autosave-interval`, and
953
- `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sidebar-startup-picker`. Project
954
- auto-save overrides live under
955
- `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-projects/<session>/autosave`.
956
- The environment variables above override the global files.
957
- `sidebar-startup-picker` accepts the existing `on` and `off` bytes; absence is a
958
- read-only effective `on - default`, not a migration or an implicit write.
959
-
960
- Manual snapshot actions are available from the CLI:
955
+ Default `projmux shell` does not open a startup picker before attach. It
956
+ derives the default app session identity and startup directory from the
957
+ current project context when available; otherwise it uses the `home` target
958
+ and home directory.
961
959
 
962
- ```sh
963
- projmux get snapshots
964
- projmux create snapshot
965
- projmux delete snapshot [--session <name>]
966
- projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --dry-run
967
- projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --yes [--client <tmux-client>]
968
- ```
960
+ The retired closed-Project startup setting's file under
961
+ `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/` is not read, and `config apply`
962
+ removes it; see [Upgrading](upgrading.md#closed-project-startup-setting-removed).
969
963
 
970
- `status` prints the source label (`autosave`, `layout(<name>)`, or `fresh`), the
971
- effective auto-save state, and a compact snapshot preview for the
972
- target session. Older snapshots without a source field display as `autosave`.
973
- `save` captures the current tmux session immediately and intentionally bypasses
974
- the autosave debounce and disabled-autosave gate; it still requires a current
975
- tmux session. `delete` removes the target snapshot without an interactive
976
- confirmation. Restore treats the snapshot as desired-state input for one exact
977
- closed Project, never as a global Registry replacement or tmux replay.
978
- `--dry-run` prints scoped projection counts with zero writes. `--yes` commits
979
- that target subtree atomically, runs the ordinary materializer, and performs an
980
- explicit client handoff last when `--client` is present. Restore never modifies
981
- or deletes the source snapshot.
982
-
983
- Interactive `projmux quit` also offers `Save Project snapshots and quit`. It
984
- recaptures the latest snapshot for every live Registry-bound Project on the
985
- exact app server, regardless of the global or Project auto-save toggle, and
986
- stops the server only after all captures succeed. A partial failure keeps the
987
- server running and keeps each successful atomic snapshot for inspection or
988
- retry. Control/Home, ephemeral, unmanaged, conflicted, and sibling-server
989
- sessions are never promoted into Project snapshots. `Quit without saving`,
990
- `quit --yes`, and `quit --force` perform no snapshot inventory or store I/O.
964
+ Interactive `projmux quit` offers only the quit row and `Cancel`. Neither it
965
+ nor `quit --yes` / `quit --force` saves Project state.
991
966
 
992
967
  ## Decoration Mode
993
968
 
@@ -1016,9 +991,8 @@ independent global presentation preferences:
1016
991
 
1017
992
  - `Notifications HUD > Visible`
1018
993
  - `Agent Usage HUD > Visible`
1019
- - `Agent Usage HUD > Claude|Codex|Antigravity > Visible`
1020
- - each provider's supported HUD windows (`Claude`/`Codex`: `5h`, `Weekly`;
1021
- `Antigravity`: `Weekly`)
994
+ - `Agent Usage HUD > Claude|Codex > Visible`
995
+ - each provider's supported HUD windows (`5h`, `Weekly`)
1022
996
 
1023
997
  The saved values are `on` or `off` in these files:
1024
998
 
@@ -1027,12 +1001,10 @@ The saved values are `on` or `off` in these files:
1027
1001
  ~/.config/projmux/statusbar-visibility-agent-usage-hud
1028
1002
  ~/.config/projmux/statusbar-visibility-agent-usage-provider-claude
1029
1003
  ~/.config/projmux/statusbar-visibility-agent-usage-provider-codex
1030
- ~/.config/projmux/statusbar-visibility-agent-usage-provider-antigravity
1031
1004
  ~/.config/projmux/statusbar-visibility-agent-usage-window-claude-5h
1032
1005
  ~/.config/projmux/statusbar-visibility-agent-usage-window-claude-weekly
1033
1006
  ~/.config/projmux/statusbar-visibility-agent-usage-window-codex-5h
1034
1007
  ~/.config/projmux/statusbar-visibility-agent-usage-window-codex-weekly
1035
- ~/.config/projmux/statusbar-visibility-agent-usage-window-antigravity-weekly
1036
1008
  ```
1037
1009
 
1038
1010
  Missing, empty, and invalid values resolve to `on` except the Codex `5h`
@@ -1046,8 +1018,9 @@ Parent visibility gates only the effective projection. Turning the overall HUD
1046
1018
  or a provider off does not rewrite its provider/window leaf files; turning the
1047
1019
  parent back on restores the saved child selection. Provider rows follow the
1048
1020
  usage-supported provider catalog. Window rows come only from the explicit HUD
1049
- capability map, so opaque quota buckets never create settings and Antigravity
1050
- never gains a fabricated `5h` row.
1021
+ capability map, so opaque quota buckets never create settings. Antigravity has
1022
+ no usage source; `statusbar-visibility-agent-usage-*-antigravity*` files left by
1023
+ older releases are ignored and never deleted.
1051
1024
 
1052
1025
  Visibility does not enable or disable either producer. Hiding Notifications HUD
1053
1026
  does not change the persistent queue, desktop delivery, or Notification
@@ -1131,12 +1104,27 @@ The CPU delta cache is internal state at
1131
1104
  CPU reference samples older than 30 seconds are ignored and replaced on the
1132
1105
  next refresh.
1133
1106
 
1107
+ ## Setting Layers
1108
+
1109
+ Settings live in two layers:
1110
+
1111
+ | Layer | Where | What |
1112
+ | --- | --- | --- |
1113
+ | central | `config.toml` central keys (`[ui] locale`, `[update]`, `[startup]`, `[hooks.*]`, `[env]`, `[ai] split_cwd_from`), `ai-enabled-agents`, `live-resources`, `projdir`, `workdirs`, `pins`, `tags`, `project-hooks`, `desktop-notify-mode`, `ai-notify-dedupe-seconds`, `ai-hook-actions.json`, `ai-semantic-policies.json`, `ai-hooks.d/`, `hooks/`, `personas/` | product behavior every surface shares |
1114
+ | TUI | `statusbar-visibility-*`, `statusbar-decoration*`, `ai-badge-style`, `runtime-diagnostics-visibility`, `keymap.toml`, `tmux-ai-split-mode`, `config.toml` `[theme]`, `[ui] native_keys`, `[ai] resume_*` | how the terminal looks and launches |
1115
+
1116
+ TUI is the front layer: only the front entry points (`settings`, `shell`,
1117
+ `switch`, `config render|apply|edit` and the internal namespace) read it. Every
1118
+ other public route reads the central layer alone, except that a route opening a
1119
+ picker may read that picker's theme and keys to paint it.
1120
+
1121
+
1134
1122
  ## Rare Tunables
1135
1123
 
1136
1124
  These are intended for debugging or local policy, not routine setup:
1137
1125
 
1138
1126
  | Variable | Purpose |
1139
1127
  | --- | --- |
1140
- | `PROJMUX_TMUX_NOTIFY_DEDUPE_SECONDS` | Override the Settings/default collapse window for duplicate AI desktop notifications keyed on the pane-local AI notification key. |
1128
+ | `PROJMUX_TMUX_NOTIFY_DEDUPE_SECONDS` | Override the Settings/default collapse window for duplicate AI desktop notifications keyed on the pane-local AI notification key. The Settings value and default apply only when this env is unset or not a positive integer. |
1141
1129
  | `PROJMUX_CODEX_TITLE_WATCH_INTERVAL` | Title-watch loop pacing for Codex panes. |
1142
1130
  | `PROJMUX_CODEX_REPLY_SETTLE_LOOPS` | Reply-detection settle-loop pacing for Codex panes. |
@@ -110,7 +110,6 @@ Files:
110
110
  - `internal/app/*help*`
111
111
  - `docs/cli.md`
112
112
  - `docs/cli-guide.md`
113
- - `docs/agent-workflow.md`
114
113
 
115
114
  Classification:
116
115
 
@@ -122,6 +121,17 @@ Classification:
122
121
  | Command syntax | `projmux shell`, `make test`, `gh pr create` | `literal` | Preserve exactly. |
123
122
  | Version strings and release tags | `vX.Y.Z`, git SHA, installer source | `data` | Preserve source content. |
124
123
 
124
+ ### Install replacement failures
125
+
126
+ `internal/app/install_replacement*.go` adds the failure explanation, remaining
127
+ target heading, impact, and recovery under `install.replacement.*` catalog keys
128
+ with `en-US` and `ko-KR` entries (`translate`). The pre-existing summary and
129
+ successful/pending install output remain unchanged. Role/refusal tokens,
130
+ `pid`, `revision`, and `unknown` are `literal`; observed pids and revisions are
131
+ `data`, preserved only in the terminal diagnostic. `Codex` and `make install`
132
+ remain literal inside the translated guidance. No process identity is added to
133
+ the persisted outcome or residue ledger.
134
+
125
135
  ## Literal Preservation Rules
126
136
 
127
137
  Do not translate these families: