projmux 0.15.3 → 0.16.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.
Files changed (38) hide show
  1. package/README-ko.md +3 -4
  2. package/README.md +3 -3
  3. package/docs/agent-message-replies.md +149 -6
  4. package/docs/ai-agent-shortcuts.md +6 -5
  5. package/docs/architecture.md +467 -66
  6. package/docs/claude-coordination-endpoints.md +192 -20
  7. package/docs/cli-guide.md +872 -148
  8. package/docs/cli.md +1459 -485
  9. package/docs/codex-installed-compatibility.md +6 -11
  10. package/docs/codex-native-required-migration.md +1 -59
  11. package/docs/configuration.md +694 -222
  12. package/docs/globalization.md +18 -5
  13. package/docs/hooks.md +529 -62
  14. package/docs/keybindings.md +74 -4
  15. package/docs/legacy-cli-retirement.md +3 -3
  16. package/docs/legacy-diagnostics-inventory.md +4 -4
  17. package/docs/native-picker.md +3 -5
  18. package/docs/notify-queue.md +1 -1
  19. package/docs/npm-distribution.md +4 -0
  20. package/docs/operational-diagnostics.md +319 -34
  21. package/docs/pr-guideline.md +66 -22
  22. package/docs/release.md +101 -0
  23. package/docs/replacement-contract.md +72 -58
  24. package/docs/repo-layout.md +3 -0
  25. package/docs/resource-attribution.md +6 -2
  26. package/docs/session-restore.md +50 -80
  27. package/docs/settings-ia.md +14 -22
  28. package/docs/statusbar.md +38 -37
  29. package/docs/testing.md +83 -18
  30. package/docs/theme-palette.md +6 -6
  31. package/docs/tmux-surface-inventory.md +21 -10
  32. package/docs/troubleshooting.md +2 -4
  33. package/docs/upgrading.md +161 -24
  34. package/docs/usage-tracking.md +40 -49
  35. package/package.json +5 -5
  36. package/docs/agent-workflow.md +0 -2596
  37. package/docs/codex-generation-pool.md +0 -623
  38. package/docs/codex-stored-qualification.md +0 -45
package/README-ko.md CHANGED
@@ -72,8 +72,8 @@ projmux create claude --project mobile-client -- "마이그레이션 계획 초
72
72
 
73
73
  - [Resource Inspector](docs/resource-attribution.md) — 프로젝트·창·pane별 CPU와
74
74
  RSS를 실시간으로 봅니다.
75
- - [Session State](docs/session-restore.md) — 창 배치와 작업 디렉터리를 스냅샷으로
76
- 남깁니다.
75
+ - [Project Startup](docs/session-restore.md) — 닫힌 프로젝트를 Registry에 저장된
76
+ 창 구성으로 이어 열거나 새로 만듭니다.
77
77
  - 검색 루트, 키 설정, 업데이트는 설정에서 바꿉니다.
78
78
 
79
79
  ## 요구 사항
@@ -93,8 +93,7 @@ projmux create claude --project mobile-client -- "마이그레이션 계획 초
93
93
  [상태 표시줄](docs/statusbar.md) ·
94
94
  [훅](docs/hooks.md) ·
95
95
  [사용량 추적](docs/usage-tracking.md) ·
96
- [운영 진단](docs/operational-diagnostics.md) ·
97
- [에이전트 작업 흐름](docs/agent-workflow.md)
96
+ [운영 진단](docs/operational-diagnostics.md)
98
97
 
99
98
  ## 개발
100
99
 
package/README.md CHANGED
@@ -72,7 +72,8 @@ Templates and naming conventions are in
72
72
 
73
73
  - Live per-project, per-window, and per-pane CPU/RSS in the
74
74
  [Resource Inspector](docs/resource-attribution.md).
75
- - Layout and cwd snapshots in [Session State](docs/session-restore.md).
75
+ - Registry-based Continue project and Clear layout and open in
76
+ [Project Startup](docs/session-restore.md).
76
77
  - Search roots, keybindings, and updates in Settings.
77
78
 
78
79
  ## Requirements
@@ -92,8 +93,7 @@ Templates and naming conventions are in
92
93
  [Statusbar](docs/statusbar.md) ·
93
94
  [Hooks](docs/hooks.md) ·
94
95
  [Usage tracking](docs/usage-tracking.md) ·
95
- [Operational Diagnostics](docs/operational-diagnostics.md) ·
96
- [Agent Workflow](docs/agent-workflow.md)
96
+ [Operational Diagnostics](docs/operational-diagnostics.md)
97
97
 
98
98
  ## Development
99
99
 
@@ -1,10 +1,24 @@
1
1
  # Explicit reply recovery
2
2
 
3
3
  An explicit Claude reply names the original request with `--reply-to`. The
4
- broker preserves that request's `conversationRef`, reverses its exact source
5
- and target routes, and retains peer, untrusted, coordination-only authority.
6
- Both activations and the original deadline must still be current. A reply
7
- cannot extend that deadline. Source metadata remains an unverified routing
4
+ broker preserves that request's `conversationRef`, reverses its source and
5
+ target Agents, and retains peer, untrusted, coordination-only authority. The
6
+ reply goes to each Agent's current activation, and the original deadline must
7
+ still be current. A reply cannot extend that deadline.
8
+
9
+ Correlation follows the Agent and its provider conversation, not one
10
+ activation. Either Agent may have been relaunched into the same conversation
11
+ since the original, for example by `agent relaunch`: it now runs in a new Pane
12
+ under a new activation, and a reply to the earlier message still commits and
13
+ is delivered there. A reply to another Agent or on another provider is still
14
+ refused as `invalid-explicit-reply-correlation`. When one of the original's
15
+ Agents is now in another provider conversation (another Claude session), the
16
+ reply is refused with `explicit-reply-conversation-changed` and stores
17
+ nothing; the original cannot be answered there, so send a new message without
18
+ `--reply-to`. A `--dialogue-reply-only` Agent's reply tool follows the same
19
+ rule for the original's sender: it still permits a reply to a sender
20
+ relaunched into the same conversation, and denies one to a sender now in
21
+ another conversation. Source metadata remains an unverified routing
8
22
  claim; an explicit reply also requires the registered provider's descendant
9
23
  caller and any existing qualification and execution guard.
10
24
 
@@ -33,12 +47,75 @@ execution guard, use the existing bounded command without that flag:
33
47
  projmux agent message send uid:<original-source-agent> --reply-to <original-request-ref> -- '<corrected reply>'
34
48
  ```
35
49
 
50
+ Operator input from an operator client has no Agent route to reverse, so a reply
51
+ to it is refused with `explicit-reply-operator-origin` and stores nothing.
52
+
53
+ Within the same provider session, a reply also commits after the Claude lease
54
+ helper was replaced, for example by compact. The new helper did not push the
55
+ original, so it reads the original from the durable store and judges it by the
56
+ same checks. It reads the store only while its own route is the Registry's
57
+ current authority for the Agent; a replaced or unregistered helper reads and
58
+ writes nothing, and is refused with `broker-reply-helper-not-current`.
59
+ `broker-reply-original-not-found` means the original is in neither the helper
60
+ nor the store.
61
+
62
+ ## Reply refusal tokens
63
+
64
+ Each refusal names its cause with one token. The CLI prints it after
65
+ `replyTo=<ref>:`, the Claude helper returns it as the `reply-refused` reason,
66
+ and the store returns it as the reply conflict reason. A token asks for one
67
+ action, so two causes that need different actions never share one.
68
+ `invalid-explicit-reply-correlation` is kept for a reply that does not match
69
+ its original. Every refusal here except `broker-reply-outcome-unknown` comes
70
+ before the reply is written anywhere: no provider saw it, so following the
71
+ action cannot duplicate it. The retry rules below govern an attempt that was
72
+ stored.
73
+
74
+ | Token | Cause | Action |
75
+ | --- | --- | --- |
76
+ | `invalid-explicit-reply-correlation` | The reply's Agents, providers, or `conversationRef` do not match the original. | Check that `--reply-to` names a message you received and that the positional Agent is its sender. |
77
+ | `explicit-reply-conversation-changed` | One of the original's Agents is now in another provider conversation. | Send a new message without `--reply-to`. |
78
+ | `invalid-explicit-reply-envelope` | The reply itself is not a valid envelope, for example a payload over the limit. | Correct the reply, for example shorten it, and send it with a fresh ref. |
79
+ | `explicit-reply-operator-origin` | The original is operator input from an operator client. | There is no Agent to answer; do not reply to it. |
80
+ | `explicit-reply-deadline-expired` | The original's deadline has passed. | Send a new message without `--reply-to`. |
81
+ | `explicit-reply-deadline-extended` | The reply's deadline is later than the original's. | Send the reply without a longer `--ttl`. |
82
+ | `explicit-reply-source-route-stale`, `explicit-reply-target-route-stale` | The replying or the answered Agent's route is not its current one, for example during a relaunch, or the helper serving the reply is not the replying Agent's. | Wait until the Agent is registered again, then send the reply. |
83
+ | `explicit-reply-route-stale` | The helper found a route no longer current at the moment it committed. | As above. |
84
+ | `broker-reply-original-not-found` | The original is in neither the helper nor the store, for example because it was reclaimed. | Send a new message without `--reply-to`. |
85
+ | `broker-reply-original-not-delivered` | The original never reached its target, so there is nothing to answer. | Inspect the original with `agent message status`; do not reply to it. |
86
+ | `broker-reply-original-without-envelope` | The helper holds the ref, but not as an Agent message it can answer. | Send a new message without `--reply-to`. |
87
+ | `broker-reply-helper-closed` | The replying Agent's Claude helper is shutting down, for example for a restart. | Wait for the new helper to register, then send the reply. |
88
+ | `broker-reply-helper-not-current` | The Registry no longer names this helper as the Agent's current one; it was replaced. | Wait for the current helper to register, then send the reply. |
89
+ | `broker-reply-unavailable` | The helper runs without a message broker and can commit no reply. | Relaunch the Agent so it starts a helper with one. |
90
+ | `broker-reply-store-unavailable` | The helper could not use the durable message store. | Check the state directory, then send the reply. |
91
+ | `broker-reply-store-busy` | Another writer held the message store. | Send the reply again. |
92
+ | `broker-reply-store-malformed` | The message store file could not be read as a store. | Inspect the store; do not resend until it reads. |
93
+ | `broker-reply-store-capacity` | The store is full and nothing can be reclaimed; see below. | Wait for records to be reclaimed. |
94
+ | `reply-already-committed` | Another reply to the original was already committed. | Inspect it with `previousRef`; do not resend. |
95
+ | `reply-ref-envelope-mismatch` | The same reply ref was used before with different content. | Use a fresh ref. |
96
+ | `broker-reply-outcome-unknown` | A commit was attempted and its result is not known. | Inspect the reply status; do not resend. |
97
+
98
+ A Claude helper that started before a build keeps that build's tokens until it
99
+ is replaced. An older helper therefore still reports most of these causes as
100
+ `invalid-explicit-reply-correlation`, and the CLI prints whichever token the
101
+ helper sent.
102
+
103
+ ## Retries
104
+
36
105
  A same-ref call returns the original immutable receipt and never pushes again.
37
106
  Changing its payload is refused with the earlier ref and cause. A fresh ref
38
107
  allows one new attempt only when every previous attempt is known-zero. Failed
39
108
  records and the original request remain available; recovery never deletes or
40
- resets them. Store capacity can refuse a new attempt rather than discard its
41
- history.
109
+ resets them.
110
+
111
+ Store capacity treats the two kinds of attempt differently. A first attempt,
112
+ one whose original has no stored attempt yet, is a new acceptance rather than a
113
+ recovery, so a full store reclaims room for it under the same rule a new
114
+ message uses, while pinning the original and every attempt already stored
115
+ against it. A recovery attempt, which follows an earlier known-zero attempt, is
116
+ still refused with a capacity error rather than discarding the history it is
117
+ recovering from. Either way a reclaimed record moves to the history log below
118
+ instead of being deleted, and a store with nothing reclaimable refuses both.
42
119
 
43
120
  Delivered replies, partial writes, unknown outcomes, pending attempts, expired
44
121
  deadlines, and stale routes must not be resent. Inspect their status and the
@@ -47,3 +124,69 @@ the stored state and specific zero-write reason must agree. These rules also
47
124
  apply after store reload and to concurrent callers. Automatic resend is
48
125
  disabled, and replies whose delivery target is Codex do not gain a new retry
49
126
  policy here.
127
+
128
+ ## Reclaimed records move to a history log
129
+
130
+ The store is a bounded hot inbox. When it accepts a new message, or a first
131
+ explicit reply attempt, it first reclaims records that went terminal more than
132
+ 24 hours ago, and then, if it is still at its record limit, the oldest
133
+ unprotected terminal record. Before either step it expires any accepted or
134
+ held record whose deadline has passed, exactly as a status read would, so such
135
+ a record becomes terminal at that moment and follows the same reclaim rules;
136
+ its 24 hours count from that expiry, not from its deadline. Reclaiming is not
137
+ deleting: every reclaimed record is appended to
138
+ `<state>/agent-messages/history.jsonl`, one JSON object per line, under the same
139
+ file lock and with the same private directory and file permissions as the store.
140
+
141
+ The append is fsynced before the store renames its own new file into place, so a
142
+ crash in that window can leave a record in both the store and the log, but never
143
+ in neither.
144
+
145
+ Each line carries the envelope's own key names:
146
+
147
+ ```json
148
+ {"schemaVersion":1,"evictedAt":"…","reason":"retention","adapter":"claude-coordination",
149
+ "messageRef":"…","conversationRef":"…","replyTo":"…",
150
+ "state":"delivered","deliveryReason":"unspecified","handoffObserved":false,
151
+ "acceptedAt":"…","terminalAt":"…","payloadBytes":466,"payloadSHA256":"…",
152
+ "source":{"agentUID":"…","provider":"…"},
153
+ "target":{"agentUID":"…","provider":"…"}}
154
+ ```
155
+
156
+ `reason` is `retention` for the 24-hour rule and `capacity` for the record
157
+ limit. `replyTo` is omitted when the record is not a reply. `outcomeUnknown`
158
+ appears, as `true`, only on a failed record whose outcome is unknown; it is
159
+ absent otherwise. `source` and `target` carry only `agentUID` and `provider`:
160
+ the Pane and activation generation fence a live delivery, and the incarnation
161
+ follows the provider conversation; all three mean nothing once the record has
162
+ left the store. The envelope's `deadline` is not written. A line for operator
163
+ input (see [Operator input](claude-coordination-endpoints.md#operator-input)) carries
164
+ `"origin":{"kind":"operator","client":"<client>"}` in place of `source`; an Agent
165
+ message's line has no `origin`. Every other key is always present.
166
+
167
+ Lines written by earlier builds may still be in the same file. They carry full
168
+ routes (`paneUID`, `activationGeneration`, `incarnation`), a `deadline`, and
169
+ `outcomeUnknown` even when it is `false`, and they read the same way: a reader
170
+ ignores keys it does not expect and reads an absent key as its zero value, so
171
+ both shapes give the same edges, states and times. Lines written before the
172
+ payload digest existed have no `payloadSHA256` key and read with an empty
173
+ digest, which means "not recorded", not a mismatch; earlier lines are not
174
+ backfilled. All of these are `schemaVersion` 1: every added key is additive.
175
+
176
+ `schemaVersion` starts at 1 and follows the same rule as the
177
+ coordination frame's field of that name: an absent or zero value reads as 1, and
178
+ a reader that meets a higher version reads the fields it knows rather than
179
+ discarding the line or failing. It is independent of the durable envelope
180
+ version and of the store file version.
181
+
182
+ The log does not keep the message body. It records `payloadBytes`, the original
183
+ payload length, and `payloadSHA256`, the SHA-256 of the payload's exact bytes
184
+ as 64 lowercase hex characters, and has no `payload` key at all: the log is
185
+ unbounded in time, and its intended consumers need the message graph, not its
186
+ text. The digest lets a consumer that holds the text elsewhere, such as a
187
+ transcript, prove it is the same message; the reader and its consumers compute
188
+ it with the same function (`PayloadSHA256` in `internal/core/agentmessage`).
189
+
190
+ The active log rotates to `history.jsonl.1` once it would pass 8 MiB, replacing
191
+ any earlier `history.jsonl.1`. At most two generations exist, so the log's disk
192
+ use is bounded even though its history is not complete.
@@ -53,11 +53,12 @@ Everything after `--` reaches the configured provider executable. Placeholder
53
53
  model, permission, and agent flags are private customization examples, not
54
54
  project defaults. Omit the separator when there is no payload.
55
55
 
56
- Settings > AI Settings > Enabled providers controls whether Claude, Codex, and
57
- Antigravity may launch. Canonical create routes respect that setting. There is
58
- no shared command-line override for a disabled provider; change Settings when
59
- the provider should become available. For a plain shell split use `projmux
60
- create pane`, not an Agent provider.
56
+ `Settings > Global > AI > Enabled providers` controls whether Claude, Codex,
57
+ and Antigravity may launch. Canonical create routes respect that setting.
58
+ There is no per-launch override for a disabled provider; enable it in Settings
59
+ or with `projmux config providers --enable <id>` (`--disable <id>` turns one
60
+ off), which goes through the same writer. For a plain shell split use
61
+ `projmux create pane`, not an Agent provider.
61
62
 
62
63
  Interactive provider and resume selection belong to the app's picker surfaces.
63
64
  CLI automation should choose an explicit provider or use `projmux agent resume