projmux 0.11.0 → 0.12.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.
@@ -54,6 +54,7 @@
54
54
  - `make test`: CLI information architecture v2 Phase 7 Agent create composition: `create agent` and the `codex`/`claude`/`antigravity` shortcuts gain a resource-backed detached route behind the same `--project` dispatch discriminator `create pane` uses, so the `--project`-less invocation stays the byte-identical `ai split` bridge while the canonical route allocates a Window-owned Agent plus its Agent-owned `<agent-name>-pane` managed Pane, reuses the Phase 6 anchor resolution, `--create-window` ensure, operation ledger and rollback, and enforces a new `{create, Agent} = 1..N` fan-out cell that four tests falsify when it is weakened; a matrix covers provider-required refusals on every canonical spelling, shortcut-to-canonical registry-snapshot equivalence, non-reuse against a Window that already owns a running Agent of the same provider (`codex` → `codex-1` → `codex-2`, first Agent's `status.paneRef` untouched), Window-scoped explicit `--name` (legal across two Windows, exit 2 with zero mutations inside one), payload-after-`--` reaching the provider launch but never the Agent or Pane name, all seven shared `-o` modes end to end with `AgentList`/`AgentMetadataList` envelopes for a single result and `-o pane-id` resolving to the managed Pane rather than the anchor, multi-window fan-out hitting each Window's own anchor exactly once, four failure stages each leaving the registry byte-identical with no `Failed` Agent behind, six racers converging on one ensured Window uid under the real on-disk lock with `-race -count=10`, the Settings enabled-agents gate applying to the canonical route as a plain error without promoting `--force-agent`, and a help-honesty audit that runs every advertised `-o` token and every advertised `--flag` of the Agent node and all three shortcuts; the identity projections of the compatibility bridge become exit 2 naming `--project` as the fix instead of exit 1 claiming the composition is unwired.
55
55
  - `make test-e2e`: CLI information architecture v2 Phase 7 Agent create against a real tmux server on the same dedicated exact socket under the smoke root, with inherited `TMUX`/`TMUX_PANE` stripped from every call and only the verified `#{socket_path}` killed: a stub provider binary proves the launch actually ran in the created pane with the project root as its cwd, the managed pane carries both the Projmux Pane uid mirror and the `@projmux_ai_managed`/`@projmux_ai_agent` options, the active window and pane are unchanged and the new pane is not active, the `codex` shortcut allocates `codex-1` instead of reusing the first Agent, a `--` payload reaches the provider argv while the name stays `codex-2`, a missing `--provider` and an explicit name collision are each exit 2 with zero stdout and an unchanged registry md5, and the `--project`-less bridge still refuses its identity projections with a message naming `--project`.
56
56
  - `make test` / `make test-e2e`: canonical create even-axis parity shares the legacy AI split geometry parser, row/column peer selector, and deterministic remainder distributor across `create pane`, `create agent`, and every provider shortcut; route tests pin split → Window-local geometry read → axis-only resize ordering for explicit/default anchors, right/down placement, fan-out, ensured Windows, one-pane no-op, malformed/unreadable topology, unrelated rows/columns, and silent post-split observation/resize failures with zero false rollback. The shared geometry format carries the materializer's escaped `\037` row separator rather than a raw tab, and a dedicated test pins both that the format holds no raw tab and that a `_`-sanitized row parses as no geometry: tmux 3.5a rewrites a raw tab in list output to `_` while 3.6 emits it verbatim, so the tab spelling parsed every row as a single field and made equalization a silent no-op on 3.5a — the version the e2e image runs. The isolated real-tmux create smoke repeats horizontal and vertical canonical creates to four panes, measures a maximum one-cell size difference, preserves raw pane IDs, Registry mirrors, focus, and an unrelated Window's exact geometry, and retains exact socket-contained cleanup.
57
+ - `make test` / `make test-e2e`: Registry–tmux Phase 6 Agent interaction and launch-readiness coverage pins exact active/explicit Agent topic and semantic-status resolution, Registry-first commit plus exact live projection and public reconcile retry, Offline topic resume mirroring, lifecycle-separated closed interaction kinds with restart/stale/Offline current-`unknown` invalidation, and Agent-owned Pane plus shell-manual-attention Window badge priority without durable glyph/color/aggregate state. Provider hooks coalesce session-ref and semantic observations into one Registry transaction when both occur and never synthesize an Agent for a shell Pane. Initial-prompt create distinguishes `Running` resource creation from bounded provider activation, returns an exact Agent/Pane retry-and-cleanup diagnostic when unconfirmed, and proves prompt non-persistence plus zero pane capture. Provider-neutral `--cwd`/repeatable `--add-dir` validation rejects nonexistent, traversal/symlink escape, unauthorized sibling, duplicate, and provider-unsupported paths before runtime mutation; preserves the Window's Project owner; stores effective Agent/Pane workspace; and forwards only caller-explicit additional roots through Codex/Claude argv. The isolated real-tmux slice uses exact primary/foreign sockets to cover immediate topic/status projection, Offline topic-to-resume mirroring, committed projection failure plus public reconcile retry/no-op, raw title/topic non-identity, foreign-socket containment, and explicit cross-Project workspace with unchanged owner Project. Compatibility `ai topic|status` keeps its stdout/stderr/exit surface while forwarding managed Pane changes through Agent authority, and notify queue acknowledgement/TTL/severity plus shell manual attention remain unchanged.
57
58
  - `make docs`: regenerates `docs/cli.md` from the `internal/cli` command manifest through `go run ./internal/tools/gendocs`. The render goes to stdout and is captured through a temp file, so a failed generator cannot truncate the checked-in page. Run it whenever a route, summary, usage synopsis, output mode, or field projection changes; `make test` fails until the checked-in page matches.
58
59
  - `make test`: CLI information architecture v2 Phase 8 generated CLI reference: `docs/cli.md` is rendered from the command tree in `internal/cli/catalog.go` -- the same manifest the binary renders `projmux help` from -- and the hand-maintained prose it used to hold moved to `docs/cli-guide.md`, which the generated page, `README.md`, and `README-ko.md` all link. The drift gate compares the checked-in page byte for byte against a fresh render and names `make docs` in its failure, so the CI `Unit Tests` job catches a stale page; a determinism test renders twice and rejects an embedded repository or temp path, which is what makes regeneration on an unchanged tree a guaranteed no-op. Coverage is a two-way diff rather than a count: every public route and sub-route in the tree has a section and every section in the document is a real node, with a non-vacuity guard that both a canonical and a shortcut route exist to cover. The internal boundary is held on the published page as well as in the primary listing -- no hidden route gets a section, and no `Canonical spelling:` line may point at an executable path absent from the manifest. The generator reads the command tree and never `canonical.go`; canonical-only summaries are therefore checked as an explicit divergent set rather than leaking into command help. Advertisement-honesty checks keep registry reads aligned with the outputs their handlers implement and keep restore limited to its shipped dry-run preview contract.
59
60
  - `make test`: Agent provider session binding Phase 0 persists a validated provider-discriminated `sessionRef` for Claude, Codex, and Antigravity without coupling lifecycle phase or Pane ownership to conversation identity. Metadata/store tests cover structural refusal, deep clones, pre-field byte-compatible reads, exact provider folding, and durable observation timestamps. `internal/app` drives canonical `internal agent-hook ingest` payloads for all providers against an in-memory Registry and proves correct provider-member population, option preservation, zero-write negative cases, conversation retention after Pane release, and stable `describe agent`, `get agents`, and `agent resume` behavior.
@@ -137,7 +138,7 @@
137
138
  - `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.
138
139
  - `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.
139
140
  - `make test` also covers `projmux agent integrate tmux-bell` dry-run/install/remove tmux command planning, managed `alert-bell` hook append/idempotence/removal, preservation of unmanaged bell hooks, and canonical `projmux internal agent-hook ingest bell --pane` queue push/metadata/dedupe behavior for non-AI-managed panes.
140
- - `make test` also covers upgrade-safe managed ingest producer convergence: fresh Codex/Claude/Antigravity hooks, Antigravity Statusline, and tmux bell writers use `projmux internal agent-hook ingest`; marker-owned 0.10.1 fixtures migrate transactionally while missing and unmanaged providers remain untouched; dry-runs show every target and old→canonical command; repeats perform zero file/tmux mutations; later-provider conflicts preflight before any write; injected Antigravity second-file and tmux Nth-command failures restore original bytes, options, and unrelated hooks; `config apply --no-reload` migrates files without live calls; and normal apply targets the requested exact `-L` socket.
141
+ - `make test` also covers upgrade-safe managed ingest producer convergence: fresh Codex/Claude/Antigravity hooks, Antigravity Statusline, and tmux bell writers use `projmux internal agent-hook ingest`; marker-owned 0.10.1 fixtures migrate transactionally while missing and unmanaged providers remain untouched; dry-runs show every target and old→canonical command; repeats perform zero file/tmux mutations; later-provider conflicts preflight before any write; injected Antigravity second-file and tmux Nth-command failures restore original bytes, options, and unrelated hooks; `config apply --no-reload` migrates files without live calls; and normal apply targets the requested exact `-L` socket. The pinned v0.10.1 GitHub Release post-replace fixture additionally proves that normal update executes exact `tmux apply` against the candidate and converges all four managed files plus the exact bell hook through the hidden current-apply handoff, while old `--no-apply` executes the candidate zero times and requires the documented explicit candidate `config apply --no-reload` split stage; current updater `--no-apply` continues to invoke the new binary automatically.
141
142
  - `make test` also covers `projmux diagnostics agent-hook` tail/path rendering and bounded JSONL log trimming for ingest diagnostics.
142
143
  - `make test` also covers the Phase 0 operational diagnostics foundation: closed safe-event schema, control/length/home sanitization, lossy stable top-level error messages with dynamic pane/title/body/transcript/config-value exclusion, exhaustive allowlisted top-level/multi-mode command classification including direct-help and explicit dry-run success exclusion with boolean `=false` safeguards, exactly-once state-changing/error outcomes with explicit zero-success/error-one coverage for the six automatic `internal agent-hook ingest`, attention arm/clear/window, session-state autosave, and recent-window record paths plus an explicit-mutation success regression, private permission repair, platform replace-existing bounded complete-record retention, corrupt-tail recovery, OS-owned inter-process lock identity/crash recovery and explicit 200 ms budget, concurrent short-process rotation, common text/JSON/tail/filter reader fixtures, and unchanged top-level runtime/usage/exitCoder output and exit semantics.
143
144
  - `make test` also covers Operational diagnostics Phase 2 lifecycle adoption: the maintained explicit-mutation inventory (attach/current/kill/sessions/switch plus session-popup open, window recent, runtime prune, focus session switching, shell open-app, snapshot replay creation, popup-toggle cancel restore, and config apply); session create/attach/switch/kill and `config apply` start/outcome success/error tables; composite create-then-attach and prune-kill-then-attach failure-stage attribution while preserving one outer pair; shared run IDs and no duplicate top-level outcome; best-effort store/write failure injection; closed operation/code pairing; apply typed no-server versus generic runner failure classification; focus success sealing at the actual switch-client boundary; unchanged read-only/hot-path zero-success recording; typed no-write runtime health projection with latest-state and bounded failure-code semantics; Doctor runtime/log typed consumer reuse; and support-report raw socket/path/session/window/pane/name negative fixtures. `make test-integration` additionally runs real create/attach/switch/kill success/failure routing against a run-unique `-L` socket, validates exact lifecycle pairs and apply classifications without raw routing, and guards cleanup with the queried actual socket path beneath the run-unique smoke root.
@@ -179,7 +180,7 @@
179
180
  - Shell focused unit coverage includes `projmux shell` routing to `tmux -L projmux -f <generated config> new-session -A -s <session> [-c <cwd>]`, generated tmux config callbacks, native key-broker platform policy, runtime overrides, and nested-socket guards.
180
181
  - `make test` also covers npm retire/staging path canonicalization for the resolved projmux executable so generated tmux config and hooks never embed a `node_modules/.projmux-<hash>` directory, plus error-suppressed attention and rebalance-panes hooks.
181
182
  - `make test` also covers the public config spelling: `projmux config edit [--get|--set <mode>]`, `config render standalone|app`, and `config apply` forward raw argv to their manual leaf handlers; flags, unknown tokens, streams, handler errors, and side effects stay on those handlers. `make install` and every update path emit `projmux config apply`, while generated plumbing uses only the hidden `internal` namespace.
182
- - `make test` also covers Legacy CLI retirement Phase 2: the exact removed-public argv matrix returns action-aware replacement guidance with stdout/handler/pre-dispatch mutation zero; `attach project`, `focus project|window|pane`, `pin project`, and `prune project|snapshot` remain exact raw-argv forwards; removed pre-namespace internal tokens have no catalog or top-level handler and use root unknown-command exit 1. The hidden producer compatibility gate admits only the exact byte allowlist recorded in the retirement ledger; missing/future/custom events, different flag order, extras, the removed detailed-log route, and every other legacy AI argv are denied before handler reach, stdout, or migration. The maintained-doc scan rejects executable recommendations for every retired route outside explicit retirement/upgrading/historical records. Catalog/canonical/handler two-way audits, root/command-tree/reference goldens, the exact retired route set, preserved Shortcut/kind aliases, and generated producer scans close the topology and drift contracts.
183
+ - `make test` also covers Legacy CLI retirement Phase 2/3: the remaining removed-public argv matrix returns exact replacement guidance with stdout/handler/pre-dispatch mutation zero; `attach project`, `focus project|window|pane`, `pin project`, and `prune project|snapshot` remain exact raw-argv forwards; removed pre-namespace internal tokens and the final `ai` root have no catalog or top-level handler and use root unknown-command exit 1 for every argv. Canonical `internal agent-hook ingest` forwards all provider event shapes to the unchanged handler, while stale unmanaged legacy-hook fixtures remain byte-preserved and require the documented manual canonical-prefix remediation. The repository literal audit permits the retired producer spelling only in test fixtures and explicit retirement/upgrade history. Maintained-doc scans, catalog/canonical/handler two-way audits, root/command-tree/reference goldens, the exact retired route set, preserved Shortcut/kind aliases, and generated producer scans close the topology and drift contracts.
183
184
  - `make test` also covers the canonical manifest honesty audit: every canonical spelling resolves to a full executable path in the command tree, no canonical summary carries forward-looking vocabulary or any adjudicated-and-retired string, the two remaining target-state summaries (`delete pane`, `restore snapshot`) are pinned verbatim with a named owning track and must stay absent from every command-tree node, and the separate shortcut gaps are enumerated as a two-way diff so a future change cannot drop a mapping unadjudicated; config and workflow routes are also asserted to have no cardinality-matrix row because they resolve no resource set.
184
185
  - `make test` also covers singular and plural kind spellings on the four resource verbs: `Route.Aliases` in `internal/cli/catalog.go` is the single declaration, `cli.CanonicalChildToken` normalizes an alias to its canonical token before `get`/`describe`/`delete`/`rename` dispatch, and the unknown-kind refusals are rendered from `cli.ChildSpellings` so an accepted spelling can never be missing from the list they print. `TestKindSpellingAliasesAreByteIdenticalToTheCanonicalSpelling` runs all 17 canonical/alias pairs -- including the two forwarded parity kinds per verb, whose forwarded argv is compared as well -- and requires identical stdout, identical stderr, and an identical error, with the canonical run required to succeed so an all-failing pair cannot satisfy byte-equality vacuously; `TestEveryManifestKindHasAParityCase` derives the matrix from the manifest so a kind added later cannot escape coverage, and `TestKindSpellingAliasesNeverReachAnotherRoute` proves each singular `get` alias answers its own inventory and is distinguishable from every sibling kind. On the manifest side `TestCanonicalKindSpellingsSurviveTheAliasContract` pins the canonical kind token of every resource-verb child so an alias can never replace a shipped spelling, `TestNoChildAliasShadowsACanonicalSpelling` walks the whole tree for alias/name collisions and duplicate aliases, and `TestResourceVerbsAcceptBothFormsOfEveryKind` asserts zero missing singular/plural combinations with `get pane`/`get panes` as the one enumerated divergent pair. That exception is the product decision the track recorded and is held by `TestGetPaneKeepsItsOwnRouteUnderBothSpellings` and `TestGetPaneSpellingIsUnchanged`: `get pane` stays the exact-one Pane read that owns `--current -o cwd`, `get panes` stays the 0..N inventory, and neither aliases onto the other. `rename` no longer special-cases the `agent` token by hand -- the manifest has no Agent child, so `agent` and `agents` both reach the ordinary refusal.
185
186
  - `make test-integration` / `make test-e2e` / `make test-install-smoke`: suite containers still run with `--network none`, so `scripts/test-docker-run.sh` prefetches the checked-in module graph once per `go.sum` into a host-side Go module cache outside the repository and mounts it into the isolated run; `test/lib/smoke.sh` honors that inherited `GOMODCACHE` instead of forcing an empty run-local one.
package/docs/cli-guide.md CHANGED
@@ -153,6 +153,66 @@ already committed, and names the same public reconcile route as the retry. A
153
153
  valid unique Project UID wins over the old path after rebind; unknown and
154
154
  duplicate UID claims remain fail-closed.
155
155
 
156
+ ### Agent topic, interaction, activation, and workspace
157
+
158
+ `agent topic get|set|clear` and `agent status get|set` resolve exactly one
159
+ Agent, either from an explicit Agent reference or from the Agent-owned active
160
+ managed Pane. Topic is a non-identifying Registry annotation. Interaction is a
161
+ separate semantic field with the closed values `unknown`, `idle`,
162
+ `in_progress`, `approval_required`, `input_required`, and
163
+ `response_complete`; it never changes the Agent lifecycle
164
+ `Pending`/`Running`/`Offline`/`Failed`. Offline, Failed, unbound, and stale
165
+ observations read as current `unknown`, so a completed badge cannot survive as
166
+ current state after its Pane is gone.
167
+
168
+ `agent status set` always records the closed `manual` source; there is no public
169
+ free-form source flag. Compatibility `ai status` and provider hooks forward to
170
+ the same Agent authority with the closed `compatibility-ai` and `provider-hook`
171
+ sources. Registries written before this field existed may still be read with an
172
+ empty source, but new mutations cannot persist arbitrary prompt, credential, or
173
+ operator text as provenance.
174
+
175
+ For a Running Agent, the exact pane's topic and
176
+ `@projmux_ai_state`/`@projmux_ai_badge_kind`/`@projmux_attention_state` are live
177
+ projections of Registry authority. A failed exact write exits nonzero after the
178
+ Registry commit and names `projmux reconcile resources` as the retry. An
179
+ Offline topic stays stored and is projected when `agent resume` creates the new
180
+ managed Pane. Window badges remain derived presentation: Agent semantic badges
181
+ and shell Pane manual attention share the existing priority reducer, while
182
+ `dot`/`emoji`/`off`, glyphs, colors, and the Window aggregate are never stored
183
+ in resource metadata.
184
+
185
+ Resource-backed Agent create accepts provider-neutral `--cwd <absolute>` and
186
+ repeatable `--add-dir <absolute>`. Explicit paths must exist, resolve without a
187
+ symlink escape, and remain inside a registered Project tree; only Codex and
188
+ Claude accept additional writable roots. These flags change the Agent's
189
+ effective launch workspace, not the Window's owning Project. The Agent stores
190
+ the effective cwd and exact caller-provided additional roots, while its managed
191
+ Pane stores the effective cwd. Provider argv translation (`-C`/`--add-dir`) is
192
+ an implementation detail rather than roadmap prompt knowledge.
193
+
194
+ The default owner Project root is subject to the same existing-directory and
195
+ canonical-path validation before create performs any Registry or tmux mutation.
196
+ Resume revalidates the persisted workspace against the current registered-root
197
+ and provider rules before creating a Pane. A pre-workspace Agent projects its
198
+ owner Project root from `get`/`describe`, and a successful resume persists that
199
+ normalized effective workspace without changing Window Project ownership.
200
+
201
+ When `create agent -- <initial-prompt>` is used, normal resource creation and
202
+ provider activation are distinct. Projmux waits for bounded hook/lifecycle
203
+ metadata only; it never captures pane content or stores the prompt. If
204
+ activation cannot be confirmed, the command exits nonzero while naming the
205
+ exact Agent UID and Pane plus safe provider retry and `delete agent ... --yes`
206
+ cleanup options. The live resources remain explicit and retryable rather than
207
+ being reported as an ordinary success.
208
+
209
+ Activation metadata is bounded to provider-hook provenance and fixed
210
+ acknowledged/timed-out/failed diagnostics. Provider error strings and initial
211
+ prompt text are never stored. Resource-backed Agent create and resume do not
212
+ start the legacy title/content watcher; that watcher remains only for legacy
213
+ non-resource panes and exits before reading title or capture content if resource
214
+ identity appears.
215
+
156
216
  ### When the active target is not a Projmux resource
157
217
 
158
218
  A pane created outside the registry-backed routes carries no
@@ -244,7 +304,7 @@ hook payload, or a `make install` log.
244
304
  | `internal statusbar` | Status bar click and shortcut dispatch (`click`, `usage-refresh`). |
245
305
  | `internal preview` | Persisted preview cursor (`cycle-pane`, `cycle-window`, `select`). |
246
306
  | `internal session-popup` | Session popup preview/open and popup cursor movement. |
247
- | `internal agent-hook` | Provider hook ingest (`ingest`) and the Agent pane title watcher (`watch-title`). |
307
+ | `internal agent-hook` | Provider hook ingest (`ingest`) and the legacy non-resource pane title watcher (`watch-title`). |
248
308
  | `internal focus` | Machine focus ingress used by statusbar and notification-sidebar actions. |
249
309
  | `internal key-broker` | Darwin physical key transport. |
250
310
  | `internal popup-wait-key` | Single-key reader that closes a display-only popup. |
package/docs/cli.md CHANGED
@@ -61,8 +61,9 @@ projmux <command> [args...]
61
61
  Manage Agent state, topic, integrations, and account usage
62
62
 
63
63
  ```
64
- projmux agent status [set <state> [pane]]
65
- projmux agent topic [set|clear] ...
64
+ projmux agent status [get [<agent-ref>] | set <unknown|idle|in_progress|approval_required|input_required|response_complete> [<agent-ref>]] [--agent <ref>]
65
+ projmux agent topic get|clear [<agent-ref>] [--agent <ref>]
66
+ projmux agent topic set <text> [<agent-ref>] [--agent <ref>]
66
67
  projmux agent resume <ref> [--project <ref>] [--window <ref>]...
67
68
  projmux agent integrate <provider> [--dry-run]
68
69
  projmux agent usage [--model <name>] [--window <name>] [--json] [--force]
@@ -72,8 +73,8 @@ Subcommands:
72
73
 
73
74
  | Route | Summary |
74
75
  | --- | --- |
75
- | [`projmux agent status`](#projmux-agent-status) | Read or set the Agent status state |
76
- | [`projmux agent topic`](#projmux-agent-topic) | Read, set, or clear the Agent topic annotation |
76
+ | [`projmux agent status`](#projmux-agent-status) | Read or set semantic Agent interaction independently of lifecycle |
77
+ | [`projmux agent topic`](#projmux-agent-topic) | Read, set, or clear one exact Agent topic annotation |
77
78
  | [`projmux agent resume`](#projmux-agent-resume) | Rebind an Offline or Failed Agent to a new managed Pane |
78
79
  | [`projmux agent integrate`](#projmux-agent-integrate) | Install or remove provider hook integrations |
79
80
  | [`projmux agent usage`](#projmux-agent-usage) | Read provider account usage quota snapshots |
@@ -82,18 +83,19 @@ Canonical spelling: `projmux agent status`, `projmux agent topic`, `projmux agen
82
83
 
83
84
  ### `projmux agent status`
84
85
 
85
- Read or set the Agent status state
86
+ Read or set semantic Agent interaction independently of lifecycle
86
87
 
87
88
  ```
88
- projmux agent status [set <state> [pane]]
89
+ projmux agent status [get [<agent-ref>] | set <unknown|idle|in_progress|approval_required|input_required|response_complete> [<agent-ref>]] [--agent <ref>]
89
90
  ```
90
91
 
91
92
  ### `projmux agent topic`
92
93
 
93
- Read, set, or clear the Agent topic annotation
94
+ Read, set, or clear one exact Agent topic annotation
94
95
 
95
96
  ```
96
- projmux agent topic [set|clear] ...
97
+ projmux agent topic get|clear [<agent-ref>] [--agent <ref>]
98
+ projmux agent topic set <text> [<agent-ref>] [--agent <ref>]
97
99
  ```
98
100
 
99
101
  ### `projmux agent resume`
@@ -283,8 +285,8 @@ Create Projmux resources
283
285
  ```
284
286
  projmux create window --project <ref> [--name <name>] [--label key=value]... [-o <mode>] [-- <payload>]
285
287
  projmux create pane --project <ref> [--window <ref>]... [--pane <ref>]... [--create-window] [--placement right|down] [-o <mode>] [-- <payload>]
286
- projmux create agent --provider <provider> --project <ref> [--window <ref>]... [--pane <ref>]... [--create-window] [--placement right|down] [-o <mode>] [-- <payload>]
287
- projmux create codex|claude|antigravity --project <ref> [--window <ref>]... [--create-window] [--placement right|down] [-o <mode>] [-- <payload>]
288
+ projmux create agent --provider <provider> --project <ref> [--cwd <path>] [--add-dir <path>]... [--window <ref>]... [--pane <ref>]... [--create-window] [--placement right|down] [-o <mode>] [-- <payload>]
289
+ projmux create codex|claude|antigravity --project <ref> [--cwd <path>] [--add-dir <path>]... [--window <ref>]... [--create-window] [--placement right|down] [-o <mode>] [-- <payload>]
288
290
  projmux create notification --text <s> --target <SESSION[:WINDOW[.PANE]]> [--socket <s>]
289
291
  projmux create snapshot
290
292
  ```
@@ -335,7 +337,7 @@ Output modes (`-o`): `uid`, `name`, `ref`, `metadata`, `json`, `pane-id`, `none`
335
337
  Create an Agent and its managed Pane; --provider is required, and --project splits the resolved Windows detached
336
338
 
337
339
  ```
338
- projmux create agent --provider <provider> --project <ref> [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
340
+ projmux create agent --provider <provider> --project <ref> [--cwd <path>] [--add-dir <path>]... [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
339
341
  projmux create agent --provider <provider> [--placement right|down] [-o pane-id|none] [-- <payload>]
340
342
  ```
341
343
 
@@ -362,7 +364,7 @@ projmux create snapshot
362
364
  Provider shortcut for create agent --provider codex
363
365
 
364
366
  ```
365
- projmux create codex --project <ref> [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
367
+ projmux create codex --project <ref> [--cwd <path>] [--add-dir <path>]... [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
366
368
  projmux create codex [--placement right|down] [-o pane-id|none] [-- <payload>]
367
369
  ```
368
370
 
@@ -373,7 +375,7 @@ Output modes (`-o`): `uid`, `name`, `ref`, `metadata`, `json`, `pane-id`, `none`
373
375
  Provider shortcut for create agent --provider claude
374
376
 
375
377
  ```
376
- projmux create claude --project <ref> [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
378
+ projmux create claude --project <ref> [--cwd <path>] [--add-dir <path>]... [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
377
379
  projmux create claude [--placement right|down] [-o pane-id|none] [-- <payload>]
378
380
  ```
379
381
 
@@ -384,7 +386,7 @@ Output modes (`-o`): `uid`, `name`, `ref`, `metadata`, `json`, `pane-id`, `none`
384
386
  Provider shortcut for create agent --provider antigravity
385
387
 
386
388
  ```
387
- projmux create antigravity --project <ref> [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
389
+ projmux create antigravity --project <ref> [--cwd <path>] [--add-dir <path>]... [--window <ref>]... [--pane <ref>]... [--selector key=value]... [--create-window] [--name <name>] [--label key=value]... [--placement right|down] [-o <mode>] [-- <payload>]
388
390
  projmux create antigravity [--placement right|down] [-o pane-id|none] [-- <payload>]
389
391
  ```
390
392
 
@@ -1,11 +1,12 @@
1
1
  # Legacy CLI Retirement Ledger
2
2
 
3
- Phase 2 is a breaking CLI release. Removed human-facing compatibility argv
4
- returns exit 2, writes no stdout, performs no command or pre-dispatch migration
5
- side effect, and prints the replacement below on stderr. The seven removed old
6
- internal top-level aliases instead follow the root unknown-command contract:
7
- exit 1, no stdout or side effect, and root help plus `unknown command: <token>`
8
- on stderr.
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.
9
10
 
10
11
  | Removed argv | Replacement |
11
12
  | --- | --- |
@@ -37,25 +38,46 @@ routes `doctor`, `quit`, `resources`, `settings`, `shell`, `switch`, and
37
38
 
38
39
  The removed pre-namespace internal aliases are `key-broker`, `popup-wait-key`,
39
40
  `preview`, `session-popup`, `status`, `statusbar`, and `tmux`. Their only
40
- remaining entrypoints are the corresponding `internal ...` routes. Public
41
- configuration work uses `config render` and `config apply`.
41
+ remaining entrypoints are the corresponding `internal ...` routes, subject to
42
+ the exact updater handoff exception below. Public configuration work uses
43
+ `config render` and `config apply`.
42
44
 
43
- ## Internal migration exception
45
+ ## Updater handoff exception
44
46
 
45
- Phase 2 intentionally retains one hidden compatibility dispatcher until the
46
- next release gate: exact old managed-producer argv only. The accepted bytes are
47
+ The immutable v0.10.1 GitHub Release updater replaces its own executable and
48
+ then invokes the replacement with exact argv `tmux apply`. The replacement
49
+ accepts only those two tokens as a hidden handoff and routes them through the
50
+ current `config apply` convergence path. Exit status, stdout, stderr, managed
51
+ producer migration, generated-config writes, rollback, and live tmux mutation
52
+ are therefore the current apply contract rather than a second implementation.
53
+
54
+ This exception does not restore a `tmux` catalog node or top-level handler and
55
+ is absent from root help and generated CLI documentation. Bare `tmux`, every
56
+ other old tmux subcommand, and `tmux apply` with any extra argv still use the
57
+ removed-root contract: exit 1, no stdout or side effect, and root help plus
58
+ `unknown command: tmux` on stderr.
59
+
60
+ ## Final ingest compatibility removal
61
+
62
+ Phase 2 temporarily retained one hidden compatibility dispatcher for exact old
63
+ managed-producer argv. The accepted historical bytes were
47
64
  `ai ingest codex-hook`, `ai ingest claude-hook`, `ai ingest antigravity-hook
48
65
  --event <event>` where `<event>` is exactly `PreInvocation`, `PostInvocation`,
49
66
  `PostToolUse`, `Stop`, or `Statusline`, and `ai ingest bell --pane <pane-id>`.
50
- The flag order is fixed and no extra argv is accepted. Human and machine callers
51
- with identical argv cannot be distinguished.
67
+ The v0.11.1 `R_migrate` release migrated marker-owned Codex, Claude,
68
+ Antigravity/Statusline, and tmux-bell producers to `internal agent-hook ingest`
69
+ before this dispatcher was removed. The old bytes are now history, not an
70
+ executable alias; every `ai` argv is rejected at the root before stdin, tmux,
71
+ diagnostics, or automatic migration is touched.
52
72
 
53
- Every other `ai` argv, including `ai ingest log`, a missing/future/custom
54
- Antigravity event, reordered flags, or extra argv, returns the public retirement
55
- usage error before stdin, tmux, diagnostics, or stdout is touched. Managed
56
- producers already emit `internal agent-hook ingest`; this exception exists only
57
- for the binary-replacement-before-migration window. Do not remove it until the
58
- post-release `R_migrate` evidence gate is closed.
73
+ A markerless or otherwise unmanaged hook is intentionally never rewritten.
74
+ If one still invokes the old spelling, decide that the hook is yours, preserve
75
+ its provider arguments, redirection, and fallback, and manually replace only
76
+ the command prefix with `projmux internal agent-hook ingest`. For example, the
77
+ historical `projmux ai ingest claude-hook` prefix becomes `projmux internal
78
+ agent-hook ingest claude-hook`. Run `projmux agent integrate <provider>
79
+ --dry-run` afterward; a remaining conflict must be resolved by the owner, not
80
+ by projmux taking ownership of the entry.
59
81
 
60
82
  The `ai notify` split is intentional parity guidance, not an alias mapping.
61
83
  The old notify action drove an immediate desktop-notification path from pane
package/docs/upgrading.md CHANGED
@@ -73,12 +73,14 @@ Statusline, and the tmux bell fallback with the canonical
73
73
  `projmux internal agent-hook ingest ...` entrypoint. Copyable integration
74
74
  commands use `projmux agent integrate <provider>`.
75
75
 
76
- Update ordering is hook-first and lossless: the new binary is atomically
77
- installed while the exact old managed-producer argv described in the ledger's
78
- internal migration note still dispatches to the same handler; the new binary then migrates every
79
- marker-owned producer; only after that does it generate and apply tmux config.
80
- An old managed hook that fires between binary replacement and migration is
81
- therefore handled before its command is rewritten.
76
+ The v0.11.1 migration release used hook-first ordering: the new binary was
77
+ atomically installed while the exact old managed-producer argv described in the
78
+ ledger still dispatched to the same handler; it then migrated every
79
+ marker-owned producer before generating and applying tmux config. Phase 3's
80
+ next breaking release removes that temporary dispatcher after the public
81
+ fresh/upgrade/`--no-apply` migration evidence gate. Upgrade an old installation
82
+ through v0.11.1 before the next release when you need the migration-window
83
+ event guarantee.
82
84
 
83
85
  Migration is ownership- and transaction-aware. Codex managed blocks and the
84
86
  Claude, Antigravity, Statusline, and tmux-bell markers are the only ownership
@@ -104,11 +106,44 @@ files, but they neither inspect nor modify a live tmux server. A later normal
104
106
  `projmux config apply --socket <name>` converges a marker-owned bell hook only on
105
107
  that exact `-L <name>` socket.
106
108
 
109
+ **Upgrading directly from v0.10.1:** its GitHub Release updater predates the
110
+ current post-update argv. A normal
111
+ `PROJMUX_INSTALLER=github-release projmux update apply` replaces the executable
112
+ and then calls exact legacy `tmux apply`; the replacement accepts that hidden
113
+ handoff and performs the same managed-producer migration, generated-config
114
+ write, and live reload as current `config apply`. The old route is not restored
115
+ in help or the command catalog, and no other `tmux` argv is accepted.
116
+
117
+ The v0.10.1 updater's own `--no-apply` behavior is historically different: it
118
+ returns immediately after binary replacement and never executes the new
119
+ binary. Treat that invocation as replace-only, verify that the executable is
120
+ the intended new version, and then run the replacement explicitly:
121
+
122
+ ```sh
123
+ PROJMUX_INSTALLER=github-release projmux update apply --no-apply
124
+ projmux version
125
+ projmux config apply --no-reload
126
+ ```
127
+
128
+ The explicit last step migrates marker-owned provider files and writes the
129
+ generated config without inspecting or mutating live tmux. This split-stage
130
+ recovery applies only when the command that started the update was v0.10.1;
131
+ current `update apply --no-apply` already executes the new binary's
132
+ `config apply --no-reload` automatically.
133
+
107
134
  If a conflict is reported, keep the unmanaged entry unchanged while deciding
108
135
  which tool owns it; remove or rewrite it manually only after that decision,
109
136
  then rerun the dry-run and installer. A failed transaction is safe to retry
110
137
  because it restores its starting state.
111
138
 
139
+ **Stale unmanaged legacy hooks after the final removal:** projmux does not take
140
+ ownership of markerless hooks and does not rewrite them automatically. Such a
141
+ hook now fails with `unknown command: ai`. After confirming that you own the
142
+ entry, preserve its provider/event arguments, redirection, and fallback and
143
+ manually replace the old `projmux ai ingest` prefix with `projmux internal
144
+ agent-hook ingest`. Then run `projmux agent integrate <provider> --dry-run` and
145
+ resolve any reported ownership conflict before installing a managed entry.
146
+
112
147
  **Downgrading to 0.10.1 or older:** those binaries do not expose the canonical
113
148
  internal ingress. Before replacing the current binary, remove each managed
114
149
  integration with `projmux agent integrate <provider> --remove`. After the old
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "projmux",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "tmux project session manager",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/crevissepartners/projmux#readme",
@@ -28,9 +28,9 @@
28
28
  "package:npm:pack": "scripts/package-npm.sh --pack"
29
29
  },
30
30
  "optionalDependencies": {
31
- "@projmux/linux-x64": "0.11.0",
32
- "@projmux/linux-arm64": "0.11.0",
33
- "@projmux/darwin-x64": "0.11.0",
34
- "@projmux/darwin-arm64": "0.11.0"
31
+ "@projmux/linux-x64": "0.12.0",
32
+ "@projmux/linux-arm64": "0.12.0",
33
+ "@projmux/darwin-x64": "0.12.0",
34
+ "@projmux/darwin-arm64": "0.12.0"
35
35
  }
36
36
  }