projmux 0.12.2 → 0.13.1

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.
@@ -56,10 +56,46 @@ The saved workdir file is:
56
56
  It stores one absolute path per line. Lines beginning with `#` are comments.
57
57
  The file is read only when no env root list is set.
58
58
 
59
- ## Project Named Snapshots
59
+ Workdirs are a **scan source and nothing else**. Adding a root, and scanning one,
60
+ never registers a Registry Project: a discovered child is an unregistered
61
+ candidate until `projmux create project --root <path>` or opening it once from the
62
+ Projects sidebar registers that exact path. See
63
+ [upgrading.md](upgrading.md#discovery-no-longer-registers-projects).
60
64
 
61
- Project open exposes reusable restore choices as named snapshots. Older
62
- checkouts may already have named snapshots in the legacy storage directory:
65
+ ## Project pins
66
+
67
+ Pins are presentation preferences, stored typed:
68
+
69
+ ```text
70
+ ~/.config/projmux/pins
71
+ ```
72
+
73
+ ```text
74
+ projmux-pins v2
75
+ project proj-kwo4qozry2sr2ycij2g45zyvam
76
+ candidate /home/dev/src/scratch
77
+ ```
78
+
79
+ A `project` pin references a Registry Project uid, so its displayed root and name
80
+ come from the Registry and the pin survives a rebind, a rename, and a missing
81
+ root. A `candidate` pin references a path no Project claims. Neither kind is a
82
+ discovery source and neither is managed identity.
83
+
84
+ `projmux pin project list [--kind project|candidate]` prints both collections with
85
+ their kind. `pin project add|remove|toggle <dir>` accepts the same directory
86
+ argument it always has and resolves it to a typed pin — exactly one Project with
87
+ that root makes the pin managed, none makes it a candidate, more than one is
88
+ refused — with `uid:<uid>` available to name a Project directly.
89
+
90
+ A pre-v2 file of bare paths is read without being rewritten and migrated only on
91
+ request with `projmux pin project migrate`; see
92
+ [upgrading.md](upgrading.md#pins-are-typed-and-migrate-on-request) for the
93
+ per-line outcomes and the ambiguity refusal.
94
+
95
+ ## Legacy Project Layout Snapshots
96
+
97
+ Older checkouts may already have named layout snapshots in the legacy storage
98
+ directory:
63
99
 
64
100
  ```text
65
101
  <project>/.projmux/layouts/<name>.toml
@@ -68,9 +104,9 @@ checkouts may already have named snapshots in the legacy storage directory:
68
104
  The project context comes from `PROJMUX_CWD` when set, otherwise projmux walks
69
105
  upward from the current directory to the nearest `.projmux` or `.git` marker.
70
106
  Files outside that project tree are not discovered. This storage is treated as
71
- legacy import data for the `Named snapshot` row in Project open. New primary
72
- user-facing surfaces describe the restore unit as a snapshot, not as a separate
73
- layout or preset feature.
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.
74
110
 
75
111
  The legacy schema is intentionally close to the session-state snapshot shape:
76
112
 
@@ -159,9 +195,12 @@ marker-only edit with a digest-named pre-v2 backup. [docs/keybindings.md](keybin
159
195
  table, the upgrade ordering and the downgrade procedure.
160
196
 
161
197
  This marker is a separate version domain from the CLI resource registry's
162
- `apiVersion: projmux.io/v1alpha1` / camelCase `schemaVersion: 1` envelope. The
198
+ `apiVersion: projmux.io/v1alpha1` / camelCase `schemaVersion: 2` envelope. The
163
199
  two have separate markers, separate backups and separate rollbacks; neither one
164
- failing affects the other.
200
+ failing affects the other. A successful Registry v1 → v2 migration keeps its
201
+ private repair/loss evidence at `<exact-versioned-backup>.migration-report.json`,
202
+ including that backup's absolute path and SHA-256; failed or repeated passes
203
+ publish no report.
165
204
 
166
205
  Legacy `prefix = ...` entries still parse during migration so existing files
167
206
  do not break. Settings preserves existing prefix entries when rewriting the
@@ -380,6 +419,104 @@ warning with the unsupported value and source.
380
419
  Project-local locale override is not part of the runtime policy. Locale is a
381
420
  user/global preference in this release.
382
421
 
422
+ ## Codex app-server health
423
+
424
+ Settings > AI includes a read-only `Codex control plane` row. It reports one of
425
+ `App Server`, `Hook fallback`, or `Unavailable`, together with the existing
426
+ effective reason. Endpoint readiness, running executable/version, official
427
+ daemon-manager ownership, and remote-control capability are separate closed
428
+ axes. Separate `probe_reason` and `install_capability` fields preserve the
429
+ app-server root cause and bounded PATH/managed-payload topology. Lifecycle
430
+ outcome/reason and sanitized CLI, managed, and running versions remain
431
+ independent. Read-only surfaces report `not-attempted/read-only`.
432
+ `projmux doctor --section integrations` and explicit support reports expose the
433
+ same bounded fields without executable/socket paths, prompts, tokens, process
434
+ output, or response payloads.
435
+
436
+ There is no app-server source setting or environment override. Authority is a
437
+ capability result, not a preference: Projmux probes the existing local control
438
+ socket through `codex app-server proxy`, reads official manager evidence through
439
+ `codex app-server daemon version`, and reads remote-control state through
440
+ `remoteControl/status/read`, all with short timeouts. An older endpoint that
441
+ does not expose the last method reports `unsupported` on that axis without
442
+ hiding endpoint readiness. Doctor, Settings, and support reports never start or
443
+ otherwise mutate the daemon, configuration, login state, or control socket.
444
+
445
+ An `external-cli-only` install capability acknowledges that the ordinary CLI
446
+ exists while the canonical managed daemon payload was not observed. It does
447
+ not identify a package manager. Install topology is not manager ownership:
448
+ only the official daemon response's backend field proves a managed process.
449
+
450
+ The Codex integration has a lifecycle seam for later native features. Only an
451
+ actual native user action may use it. A ready unmanaged, version-skewed, or
452
+ ownership/version-unknown endpoint is refused without mutation and reports the
453
+ shared-client interruption risk plus bounded operator recovery. Only an exact
454
+ missing or connection-refused default control socket is start-eligible. That path invokes the
455
+ official idempotent `codex app-server daemon start` command at most once per
456
+ in-flight process decision, then retries proxy initialization with a bounded
457
+ backoff. Projmux never automatically stops, kills, restarts, adopts, or enables
458
+ remote control on the shared app server.
459
+
460
+ The default `Codex` row in the provider picker launches immediately through the
461
+ canonical create route. It does not start or probe the app-server, call
462
+ `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.
484
+
485
+ `projmux agent review` starts `review/start` only for a Running Codex Agent whose
486
+ Registry Agent, owned Pane, activation generation, stored thread, and live Pane
487
+ thread all match exactly. Review availability is based on the negotiated
488
+ app-server version for that connection and is confirmed by the method call;
489
+ Codex 0.149 does not advertise a separate review capability bit. Older versions
490
+ or a method-not-found response are reported explicitly as unavailable. The
491
+ initial `review/start` response is projected into Agent interaction lifecycle;
492
+ the lifecycle observer described below owns later app-server terminal events.
493
+
494
+ A natively created or resumed Codex Agent keeps a content-free lifecycle
495
+ observer on its exact Agent UID, Pane UID/runtime handle, activation generation,
496
+ and thread ID. While its initialized proxy connection and snapshot are current,
497
+ the app server is the only attention authority: active, idle, waiting for input,
498
+ and exact unresolved approval requests project the Agent interaction and badge.
499
+ Only an exact successful `turn/completed` projects response-complete and queues a
500
+ completion notification; failed and interrupted turns become idle. Disconnect
501
+ and thread unload first invalidate the epoch and clear stale attention, then
502
+ enable hook fallback. A reconnect starts a new epoch from `thread/read`; events
503
+ from older epochs or other identities are ignored.
504
+
505
+ `describe agent` and the Codex Agent event Settings page report the effective
506
+ lifecycle source, a closed reason, and active/pending/inactive epoch status.
507
+ These diagnostics never retain prompts, reasoning, output, approval reasons, or
508
+ diff content. Settings aggregates multiple live Codex Panes as counts and says
509
+ `mixed` when native and fallback authority coexist.
510
+
511
+ Projmux does not install, bootstrap, restart, stop, or reconfigure the Codex
512
+ daemon, does not stop the shared daemon when Projmux exits, and does not manage
513
+ Codex authentication. There is no custom socket or remote-control setting.
514
+ The semantic approval/completion policy below drives the same badge, queue, and
515
+ desktop intent for both app-server and hook-fallback authority. Existing
516
+ `ai-hook-actions.json` values remain byte-for-byte unchanged and, when an exact
517
+ runtime override exists, take precedence only while hook fallback is current;
518
+ they are never inferred or copied into the semantic policy store.
519
+
383
520
  ## AI Resume Picker
384
521
 
385
522
  The Agent resume picker lists the most recent
@@ -424,6 +561,19 @@ column (`./`, `./web`, `./api`) so child-directory sessions are easy to tell
424
561
  apart. A missing or zero depth is identical to the historical behavior. Settings
425
562
  edits write the global config.
426
563
 
564
+ Codex uses the local app-server conversation catalog as its primary source.
565
+ Each picker invocation follows opaque `thread/list` cursors to completion with
566
+ explicit `cli`, `vscode`, and `appServer` source kinds, non-archived filtering,
567
+ provider recency ordering, and exact-cwd filtering at depth 0. Wider depth is a
568
+ bounded client-side path-tree filter. Native rows use the exact thread id, the
569
+ provider-owned name (or only a short id when unnamed), git branch, and runtime
570
+ status; prompt preview and transcript turns are never read for titles. If the
571
+ native catalog is unavailable, unsupported, malformed, or returns invalid
572
+ pagination, that invocation discards all native rows and performs one rollout
573
+ fallback. The picker annotates Codex rows with source, confidence, runtime
574
+ status, and a closed fallback reason, so native and rollout rows are never
575
+ silently merged.
576
+
427
577
  Antigravity uses the upstream v1.1.12 current-storage boundary before its
428
578
  legacy history fallback. `cache/last_conversations.json` contributes the latest
429
579
  UUID mapped to a matching workspace; `cache/conversation_metadata.json`
@@ -439,6 +589,13 @@ is not a disk-picker candidate. When a disk picker selection creates a pane,
439
589
  its source is persisted so Session State preview and doctor can report medium
440
590
  confidence for DB-validated cache sources or low confidence for legacy history.
441
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.
598
+
442
599
  ## Environment Variables
443
600
 
444
601
  | Variable | Purpose |
@@ -589,6 +746,21 @@ overrides catalog `action` values during ingest, including known Codex and
589
746
  Claude events. It does not change hook installation; `projmux agent integrate`
590
747
  continues to use the embedded/local catalog `install` fields.
591
748
 
749
+ Codex native lifecycle semantics are stored separately at:
750
+
751
+ ```text
752
+ ${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-semantic-policies.json
753
+ ```
754
+
755
+ The two closed events are `approval_required` and `response_complete`. Each can
756
+ be `notify` (badge + queue + desktop), `state` (badge only), or `quiet` (no
757
+ badge, queue, or desktop). Settings labels these choices `Notify`, `State only`,
758
+ and `Quiet`. The selected intent applies to both the app-server epoch and hook
759
+ fallback. An explicit raw `PermissionRequest` or `Stop` runtime override takes
760
+ precedence only during hook fallback; catalog defaults do not override this
761
+ semantic store. Saving this file does not infer from, rewrite, or normalize the
762
+ raw hook override file.
763
+
592
764
  Delivery depends on the event handler. Specialized notify handlers, such as
593
765
  Codex `PermissionRequest` and `Stop`, can write the in-app notify queue and use
594
766
  the configured OS desktop notification path. Known Codex events without a
@@ -699,33 +871,31 @@ override with `inherit`, `on`, and `off`; `inherit` follows the global value,
699
871
  while `on` and `off` take precedence. Auto-save only updates the latest
700
872
  snapshot. Named snapshots are manual and are never updated by auto-save.
701
873
 
702
- Project open from the Alt-1 sidebar defaults to opening a closed project as its
703
- `Project topology`, which materializes every Registry Window and Window-owned
704
- shell Pane of that project before the client moves. The optional `Settings >
705
- Session State > Sidebar startup picker` toggle enables the native sidebar `Start
706
- project` step. Rows appear as `Latest snapshot`, named snapshot rows, `Project
707
- topology`, and `Back`. `Latest snapshot`
708
- is the snapshot auto-save that changes as auto-save runs; named snapshots are
709
- fixed snapshots. Rows include saved-at date/time metadata when projmux can
710
- determine it. `Back` returns to the project list without creating, replaying, or
711
- opening a session. After the startup mode is selected, project automation trust
712
- is evaluated if needed. A named snapshot containing a startup `command` must
713
- authorize the SHA-256 of the exact layout bytes used for parse/restore, even
714
- when project hooks are disabled or `.projmux/config.toml` is absent. Approval
715
- continues the selected path and deny/cancel aborts without session create,
716
- snapshot replay, or startup command. The Alt-1 sidebar opens trust as the shared
717
- client-scoped `Trust project automation` popup
718
- instead of inline sidebar rows. The selected open continuation runs in a
719
- detached tmux job that can close the sidebar before trust without depending on
720
- the self-closing sidebar process to keep running. Deny/cancel refreshes the
721
- original sidebar query/selection context with a visible status message. Existing
722
- sessions switch directly without a startup picker.
874
+ Project open from the Alt-1 sidebar defaults to `Continue project`, which
875
+ materializes the closed Project's current Registry desired state before moving
876
+ the client. The optional `Settings > Session State > Sidebar startup picker`
877
+ toggle enables a native `Start project` step with exactly `Continue project` and
878
+ `Open fresh`. `Open fresh` confirms exact `Window n / Pane n / Agent n` counts
879
+ and conversation-pointer loss, then atomically replaces the old Project graph
880
+ with a new Project UID and a new canonical Window/shell UID pair. Exactly one
881
+ same-root Project claimant remains. Snapshot bytes, the root directory,
882
+ Git/worktree data, and the trust decision remain unchanged. Esc returns to
883
+ Projects with zero writes. After
884
+ the startup mode is selected, project automation trust is evaluated if needed.
885
+ The Alt-1 sidebar opens trust as the shared client-scoped `Trust project
886
+ automation` popup instead of inline sidebar rows. The selected open
887
+ continuation runs in a detached tmux job that can close the sidebar before trust
888
+ without depending on the self-closing sidebar process to keep running.
889
+ Deny/cancel refreshes the original sidebar query/selection context with a
890
+ visible status message. Existing sessions switch directly without a startup
891
+ picker.
723
892
 
724
893
  Default `projmux shell` no longer opens a startup picker or replays session-state
725
894
  snapshots before attach. It still derives the default app session identity and
726
895
  startup directory from the current project context when available; otherwise it
727
- uses the `home` target and home directory. Session-state restore selection is
728
- limited to the Session State sidebar startup picker.
896
+ uses the `home` target and home directory. Snapshot restore is an explicit CLI
897
+ operation that requires both the source session and the exact target Project;
898
+ it is not a Project-startup choice.
729
899
 
730
900
  Settings > Session State is global settings only: global auto-save, auto-save
731
901
  interval, and storage/retention policy. Settings > Project > Session State
@@ -749,7 +919,8 @@ Manual snapshot actions are available from the CLI:
749
919
  projmux get snapshots
750
920
  projmux create snapshot
751
921
  projmux delete snapshot [--session <name>]
752
- projmux restore snapshot --dry-run [--session <name>]
922
+ projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --dry-run
923
+ projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --yes [--client <tmux-client>]
753
924
  ```
754
925
 
755
926
  `status` prints the source label (`autosave`, `layout(<name>)`, or `fresh`), the
@@ -758,8 +929,21 @@ target session. Older snapshots without a source field display as `autosave`.
758
929
  `save` captures the current tmux session immediately and intentionally bypasses
759
930
  the autosave debounce and disabled-autosave gate; it still requires a current
760
931
  tmux session. `delete` removes the target snapshot without an interactive
761
- confirmation. `restore --dry-run` is preview-only in this release and does not
762
- create sessions or send tmux commands.
932
+ confirmation. Restore treats the snapshot as desired-state input for one exact
933
+ closed Project, never as a global Registry replacement or tmux replay.
934
+ `--dry-run` prints scoped projection counts with zero writes. `--yes` commits
935
+ that target subtree atomically, runs the ordinary materializer, and performs an
936
+ explicit client handoff last when `--client` is present. Restore never modifies
937
+ or deletes the source snapshot.
938
+
939
+ Interactive `projmux quit` also offers `Save Project snapshots and quit`. It
940
+ recaptures the latest snapshot for every live Registry-bound Project on the
941
+ exact app server, regardless of the global or Project auto-save toggle, and
942
+ stops the server only after all captures succeed. A partial failure keeps the
943
+ server running and keeps each successful atomic snapshot for inspection or
944
+ retry. Control/Home, ephemeral, unmanaged, conflicted, and sibling-server
945
+ sessions are never promoted into Project snapshots. `Quit without saving`,
946
+ `quit --yes`, and `quit --force` perform no snapshot inventory or store I/O.
763
947
 
764
948
  ## Decoration Mode
765
949
 
@@ -807,7 +991,8 @@ The saved values are `on` or `off` in these files:
807
991
  ~/.config/projmux/statusbar-visibility-agent-usage-window-antigravity-weekly
808
992
  ```
809
993
 
810
- Missing, empty, and invalid values resolve to the compatibility default `on`;
994
+ Missing, empty, and invalid values resolve to `on` except the Codex `5h`
995
+ window, whose ambient HUD default is `off`; an explicit saved `on` restores it.
811
996
  Settings shows whether the effective value came from `saved` or `default` and
812
997
  marks an invalid saved value as ignored. Saving a toggle regenerates the app
813
998
  and standalone tmux output, and Settings source-reloads the generated app config
package/docs/hooks.md CHANGED
@@ -239,6 +239,17 @@ notify, including unmanaged hooks/conflict details and the relevant
239
239
  hooks-engine events. It reads a single JSON payload from stdin. The embedded
240
240
  default install catalog is based on Codex CLI 0.130.0:
241
241
 
242
+ For an exact native app-server Agent, this raw hook path is fallback-only. The
243
+ pane is marked `pending` before its lifecycle observer starts; `pending`,
244
+ `provider-control-plane`, and `invalidating` authority suppress every Codex hook
245
+ event before any badge, queue, desktop, or Registry interaction write. Only
246
+ after the native epoch is invalidated may `provider-hook` become current and the
247
+ table below apply. Existing hook installation and runtime overrides are kept
248
+ byte-for-byte. `PermissionRequest` and `Stop` use the same semantic policy as
249
+ native lifecycle events unless an explicit raw runtime override exists; that
250
+ override regains its existing meaning only in fallback. Catalog defaults are
251
+ not semantic overrides.
252
+
242
253
  | Event | Behavior |
243
254
  | --- | --- |
244
255
  | `PreToolUse` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
@@ -247,7 +258,7 @@ default install catalog is based on Codex CLI 0.130.0:
247
258
  | `PostToolUse` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
248
259
  | `PreCompact` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
249
260
  | `PostCompact` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
250
- | `SessionStart` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
261
+ | `SessionStart` | marks the matched pane hook-active and writes a quiet ingest diagnostic; for an exact managed initial-task binding it records `pending` startup readiness and opens the separately bounded acknowledgement window, but never acknowledges the task; no notify queue entry is pushed |
251
262
  | `Stop` | pushes an info Codex completion row |
252
263
 
253
264
  Codex hook payload parsing accepts the common fields
@@ -366,7 +377,10 @@ runtime file only changes ingest behavior (`notify`, `state`, or `quiet`);
366
377
  `projmux agent integrate codex` still uses the catalog `install` field to decide
367
378
  which hooks to write. Runtime overrides also apply to known specialized
368
379
  events, so `Stop` or `PermissionRequest` can be made state-only or quiet
369
- without changing which hook commands are installed. When a known Codex event
380
+ without changing which hook commands are installed while hook fallback is
381
+ current. Without such an explicit override, app-server and hook-fallback
382
+ approval/completion use the same semantic policy described in
383
+ [Configuration](configuration.md#notifications). When a known Codex event
370
384
  without a specialized handler, such as `PreToolUse` or `PostToolUse`, is set to
371
385
  runtime `notify`, projmux pushes a generic in-app notify row such as
372
386
  `PreToolUse · Bash` with agent/category metadata. That generic path is
@@ -437,7 +451,7 @@ default install catalog is based on Claude Code 2.1.140 and represents the
437
451
  | `Notification` | pushes a Claude notify row for response-ready, approval-required, or input-ready based on `notification_type` |
438
452
  | `UserPromptSubmit` | marks the matched pane hook-active and sets AI state to thinking/busy; no notify queue entry is pushed |
439
453
  | `UserPromptExpansion` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
440
- | `SessionStart` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
454
+ | `SessionStart` | marks the matched pane hook-active and writes a quiet ingest diagnostic; for an exact managed initial-task binding it records `pending` startup readiness and opens the separately bounded acknowledgement window, but never acknowledges the task; no notify queue entry is pushed |
441
455
  | `Stop` | pushes a Claude completion row, using the last assistant transcript text when `transcript_path` is readable |
442
456
  | `StopFailure` | pushes a critical Claude error row with error type/message metadata when present |
443
457
  | `SubagentStart` | marks the matched pane hook-active and writes a quiet ingest diagnostic; no notify queue entry is pushed |
package/docs/install.md CHANGED
@@ -21,6 +21,11 @@ projmux doctor
21
21
  `doctor` performs read-only diagnostics for runtime tools such as `tmux`,
22
22
  `git`, and `stty`.
23
23
 
24
+ If the npm shim reports `unsupported or incomplete npm install`, or a live
25
+ pre-0.13 app server is missing its logical socket marker, use the canonical
26
+ [Troubleshooting](troubleshooting.md) diagnosis and recovery steps. Doctor is
27
+ read-only; its displayed remediation is never executed automatically.
28
+
24
29
  Provider integrations are opt-in and use the canonical installer spelling:
25
30
 
26
31
  ```sh
@@ -100,10 +105,15 @@ cd projmux
100
105
  make install
101
106
  ```
102
107
 
103
- `make install` builds the binary, atomically replaces
104
- `$(go env GOPATH)/bin/projmux`, runs `projmux config apply`, and reconciles the
105
- notify queue through `projmux notification reconcile`. Override the destination
106
- with `INSTALL_DIR=/usr/local/bin`.
108
+ `make install` builds the candidate, uses that candidate to run
109
+ `config apply --bin <install-target>` before publication, atomically replaces
110
+ `$(go env GOPATH)/bin/projmux`, and runs the installed binary's `config apply`
111
+ again as post-publication verification. This ordering migrates a pre-0.13 live
112
+ server's exact logical socket marker before a consumer that requires it becomes
113
+ reachable. A convergence or publication failure is non-zero and prints the
114
+ exact `projmux config apply --socket <name>` recovery. Successful installs then
115
+ reconcile the notify queue through `projmux notification reconcile`. Override
116
+ the destination with `INSTALL_DIR=/usr/local/bin`.
107
117
 
108
118
  Update source checkouts with the repository workflow:
109
119
 
@@ -121,11 +131,14 @@ marked as release-managed:
121
131
  export PROJMUX_INSTALLER=github-release
122
132
  ```
123
133
 
124
- With that set, `projmux update apply` downloads the latest matching release
125
- asset, replaces the current executable, and reapplies the live tmux config.
134
+ With that set, `projmux update apply` downloads and verifies the latest matching
135
+ release asset, converges the exact live route before replacement, atomically
136
+ replaces the current executable, and reapplies the live tmux config as
137
+ post-publication verification.
126
138
  `--no-apply` skips the live reload only — the new binary still migrates the
127
139
  keymap schema and marker-owned provider files, then writes the generated
128
- config. It does not touch a live tmux bell hook. See
140
+ config. It prints the exact explicit apply required before ordinary mutation
141
+ and does not touch a live tmux bell hook. See
129
142
  [Upgrading](upgrading.md#managed-agent-hook-producer-migration).
130
143
 
131
144
  ## npm Packaging Details
@@ -133,3 +146,6 @@ config. It does not touch a live tmux bell hook. See
133
146
  Repository packaging and publish details are maintained in
134
147
  [npm Distribution](npm-distribution.md). That document is for maintainers; end
135
148
  users should not need it for installation.
149
+
150
+ For incomplete optional dependencies, Doctor findings, and live app socket
151
+ marker recovery, see [Troubleshooting](troubleshooting.md).
@@ -239,9 +239,9 @@ by different picker surfaces, while conflicts inside one surface are rejected.
239
239
 
240
240
  | Surface action | Meaning |
241
241
  | --- | --- |
242
- | `Sidebar:KillSession` | Kill the focused existing session |
242
+ | `Sidebar:KillSession` | Stop only the focused Project runtime; preserve its Project UID and desired Window/Pane topology |
243
243
  | `Sidebar:PinProject` | Pin or unpin the focused directory |
244
- | `SessionPopup:KillSession` | Kill the focused session |
244
+ | `SessionPopup:KillSession` | Stop only the focused runtime Session; preserve managed Registry identity and desired topology |
245
245
  | `SessionPopup:CyclePreviewWindowPrev` / `SessionPopup:CyclePreviewWindowNext` | Preview windows |
246
246
  | `SessionPopup:CyclePreviewPanePrev` / `SessionPopup:CyclePreviewPaneNext` | Preview panes |
247
247
  | `NotifySidebar:Ack` / `NotifySidebar:AckGroup` / `NotifySidebar:ClearNonCritical` / `NotifySidebar:ClearAll` | Manage notifications |
@@ -406,7 +406,9 @@ installed yet, and only it knows its own canonical ids.
406
406
 
407
407
  `--no-apply` suppresses the live tmux reload, not the migration. Installer paths
408
408
  still invoke the new binary as `config apply --no-reload` so the schema does not
409
- fall behind the binary that writes it.
409
+ fall behind the binary that writes it. They omit pre-publication live
410
+ convergence entirely and print the exact explicit `config apply --socket`
411
+ still required before ordinary mutation.
410
412
 
411
413
  ### Downgrading or rolling back
412
414
 
@@ -1,16 +1,21 @@
1
1
  # Legacy CLI Retirement Ledger
2
2
 
3
- Phase 2 removed the human-facing compatibility argv below. Those non-AI
4
- tombstones return exit 2, write no stdout, perform no command or pre-dispatch
5
- migration side effect, and print their replacement on stderr. Phase 3 removes
6
- the final hidden `ai` producer dispatcher and catalog node: every `projmux ai
7
- ...` invocation now follows the root unknown-command contract (exit 1, no
8
- stdout or side effect, and root help plus `unknown command: ai` on stderr).
9
- The seven removed old internal top-level aliases use the same root contract.
3
+ Phase 2 removed the human-facing compatibility argv below. The mixed roots
4
+ retain only their canonical children: rejected `attach`, `focus`, `pin`, and
5
+ `prune` compatibility shapes return exit 2 with exact replacement guidance and
6
+ no stdout, handler reach, or pre-dispatch migration. The fully removed roots
7
+ `current`, `kill`, `notify`, `sessions`, `session-state`, `tag`, `upgrade`, and
8
+ `usage` are absent from the catalog and handler map, so every argv under them
9
+ uses the ordinary root unknown-command contract (exit 1, no stdout or side
10
+ effect, and root help plus `unknown command: <root>` on stderr).
11
+
12
+ Phase 3 removed the final hidden `ai` producer dispatcher and catalog node.
13
+ The `ai` root and the seven removed old internal top-level aliases use that same
14
+ unknown-command contract.
10
15
 
11
16
  | Removed argv | Replacement |
12
17
  | --- | --- |
13
- | `ai split`, `ai picker` | `create agent`, `create pane`, or a provider shortcut |
18
+ | `ai split`, `ai picker` | `create agent`, `create pane`, or a provider shortcut. The `split` handler itself is now gone: the hidden `internal agent-pane launch-default|picker` bridge produces canonical create intents, so `--agent`, `--force-agent`, and `--print-pane-id` have no implementation left. Use `-o pane-id` on a canonical create for the pane handle |
14
19
  | `ai settings` | `config edit` |
15
20
  | `ai status`, `ai topic`, `ai integrate` | `agent status`, `agent topic`, `agent integrate` |
16
21
  | `ai notify [notify] [pane]` | `create notification --text ... --target ...`; translate the old pane/payload because the input and semantics changed |
@@ -84,3 +89,27 @@ The old notify action drove an immediate desktop-notification path from pane
84
89
  state; `create notification` creates a queue row and therefore requires an
85
90
  explicit `--text` and `--target`. The old reset action cleared transient
86
91
  desktop dedupe state, which the public queue commands do not reproduce.
92
+
93
+ ## Post-retirement invariants
94
+
95
+ This breaking boundary removes only the compatibility argv listed above. It
96
+ does not narrow the canonical resource model that shipped after the retirement
97
+ work began. In particular:
98
+
99
+ - Resource Project and Window scope keeps the paired `--project` / `-p` and
100
+ `--window` / `-w` options. Plural Window, Pane, and Agent reads keep
101
+ `--all-projects` / `-A`.
102
+ - Registry-first startup and explicit reconciliation keep materializing the
103
+ recorded Project, Window, and Pane topology without adopting a foreign tmux
104
+ identity.
105
+ - An explicitly selected Offline Window remains canonically deletable from the
106
+ Registry, cascading through its descendant Agent and Pane records without
107
+ issuing a tmux `kill-window` for a mirror that does not exist.
108
+ - Root help and `docs/cli.md` remain generated from the current command
109
+ manifest. They advertise the canonical resource routes and their current
110
+ scope options, never the retired roots.
111
+
112
+ These are preservation constraints for the retirement release, not aliases
113
+ for the removed commands. A future change to one of these contracts needs its
114
+ own feature or fix decision and must not be smuggled into compatibility
115
+ cleanup.
@@ -36,6 +36,14 @@ operation instead of recording nested outcomes. Lifecycle ownership replaces
36
36
  the generic top-level `command.outcome`; it never duplicates it. Start/outcome
37
37
  append failures are ignored and do not change the command result.
38
38
 
39
+ Project lifecycle operator diagnostics also keep plans mutually exclusive:
40
+ `stop`, `close-window`, `delete-project`, and `fresh` are distinct operation
41
+ classes. Startup and unregister failures print the closed action, failing
42
+ stage, old Project UID, and new Project UID (or `-` when absent). These opaque
43
+ UIDs and stage labels are bounded control data; root paths, pane content,
44
+ history, prompts, transcripts, and snapshot contents are never identity or
45
+ intent authority.
46
+
39
47
  Session State mutations use one outcome-only `session-state.outcome` record
40
48
  per selected attempt. The closed operations are `session-state.save`,
41
49
  `session-state.autosave`, `session-state.restore`, and `session-state.delete`;
@@ -198,6 +206,53 @@ the source. Windows ACL privacy is reported as unverified because `os.FileMode`
198
206
  cannot prove it; a separate finding preserves the metadata-only writability
199
207
  result, and Doctor does not modify ACLs.
200
208
 
209
+ ### Registry materialization invariant audit
210
+
211
+ `projmux doctor --section registry` reports the admission difference between
212
+ what the Registry writer accepts and what activation can rebuild.
213
+ `Registry.Validate` and the materialization planner now share the final-v2
214
+ Window contract. Validation allows a same-Window managed Agent
215
+ `spec.anchorPaneRef` with an empty optional `spec.defaultShellPaneRef`; the
216
+ materializer classifies that shape as convergent and plans an explicit
217
+ `allocate default shell` stage before Window/Agent activation. A repeated
218
+ successful materialization is write-free. The audit remains useful for damaged
219
+ or stale refs, but an intentional offline Agent-only Window is not a finding.
220
+
221
+ The verdict is the consumer predicate itself, not a maintained list of suspect
222
+ shapes. Every Registry Project is planned through the shipped topology planner
223
+ with no observed sessions, and the refusals that offline plan records *are* the
224
+ difference. Nothing in the audit re-decides which stored topology can be
225
+ materialized, so the section cannot drift away from the route it describes.
226
+
227
+ The section is read-only in the strongest available sense. The Registry read is
228
+ the zero-write snapshot read, so running diagnostics on a machine that never
229
+ created a Project neither creates nor repairs the state directory, and the tmux
230
+ runner handed to the planner refuses every call instead of reaching a server.
231
+ The audit never writes, repairs, or migrates a Registry; repairing a stored
232
+ topology the materializer cannot build is a separate, explicitly requested
233
+ operation.
234
+
235
+ Findings use the shared severity/code/remediation/count shape:
236
+
237
+ | Code | Severity | Meaning |
238
+ | --- | --- | --- |
239
+ | `registry.materialize.audited` | info | `count` is the number of Projects planned. Always emitted. |
240
+ | `registry.materialize.clean` | info | The difference set is empty. Emitted explicitly, and printed without `--verbose`, because a silent clean audit is indistinguishable from a section that never ran. |
241
+ | `registry.materialize.unavailable` | warning | The Registry could not be read; nothing was planned. |
242
+ | `registry.materialize.fatal.<kind>` | error | `count` stored resources of that kind are refused in a way that stops the whole Project from activating. |
243
+ | `registry.materialize.skipped.<kind>` | warning | `count` stored resources of that kind are refused as single items; the Project still opens without them. |
244
+
245
+ `<kind>` is one of `project`, `window`, `pane`, `agent`, or `other`.
246
+ `fatal` and `skipped` are read off the planner's own refusal split rather than
247
+ re-decided here.
248
+
249
+ The refusal reasons are the planner's own wording and are rendered only under
250
+ `--verbose`, following the report's rule that path-bearing detail is opt-in: a
251
+ stale-cwd reason quotes a stored absolute path. Those reasons are never
252
+ serialized in any format. The support report therefore carries the same codes,
253
+ kinds, and counts as the text report and no reason wording at all, rather than
254
+ relying on the redaction allowlist to hash a private path out of an archive.
255
+
201
256
  ## Storage and retention
202
257
 
203
258
  The path is
@@ -227,8 +282,9 @@ arm`, `attention clear`, `attention window`, `internal tmux autosave-session-sta
227
282
  to the journal; an error from any of them still records exactly one safe error
228
283
  outcome. Explicit user mutations such as `attention toggle` retain their
229
284
  state-changing success record. Direct top-level help and explicit preview-only intents (`update
230
- apply --dry-run`, AI integration dry-runs, and the
231
- currently preview-only session restore) are also read-only. Doctor is a stricter
285
+ apply --dry-run`, AI integration dry-runs, and snapshot projection restore with
286
+ `--dry-run`) are also read-only. Approved snapshot projection restore is a
287
+ state-changing operation. Doctor is a stricter
232
288
  boundary: successes and errors never append to this journal, so diagnostics do
233
289
  not make its filesystem contract self-defeating. Support report success and
234
290
  errors likewise never append; its strict reader shares the viewer's tolerant