projmux 0.16.0 → 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.
@@ -17,15 +17,27 @@ Managed Agent/Pane names and Claude session titles are not route authority.
17
17
  Renaming an unchanged UID/activation preserves its registration. Phase 1 does
18
18
  not discover unmanaged provider names or observe live Claude `/rename` events.
19
19
  Competing session/process/helper claims for an exact activation are refused;
20
- the exact child's next SessionStart atomically claims a new registration
21
- generation before launching its helper. Delayed admission and cleanup from an
22
- older generation cannot overwrite or clear that newer registration.
20
+ the helper launched by the exact child's next SessionStart claims a new
21
+ registration generation and records it Ready in one Registry transaction, so
22
+ no claimed-but-not-Ready registration is ever published. The claim is a
23
+ compare-and-set on the registration generation the hook observed, so delayed
24
+ admission and cleanup from an older generation cannot overwrite or clear a
25
+ newer registration.
23
26
 
24
27
  The activation gate records the actual child PID and kernel birth identity
25
28
  before replacing itself with Claude. The separate managed SessionStart hook
26
- uses `exec`, making the registered provider its direct parent. The helper
27
- verifies the complete helper → hook → provider process chain while the hook
28
- waits for a bounded startup acknowledgement. A nested unmanaged Claude cannot
29
+ uses `exec`, making the registered provider its direct parent. The hook never
30
+ takes or waits on the Registry lock: it reads the Registry lock-free, starts
31
+ the helper, and waits only for a bounded startup acknowledgement, all inside
32
+ Claude's hook timeout. The helper verifies the complete helper → hook →
33
+ provider process chain, then claims and records the registration in its own
34
+ lifetime, bounded by the Registry lock acquisition timeout. The hook's wait
35
+ bounds only the hook: when it ends without the acknowledgement, the hook
36
+ releases the helper instead of killing it, and a helper whose acknowledgement
37
+ nobody reads still records and keeps its registration. A released helper that
38
+ cannot record, or whose generation is no longer current, exits without writing
39
+ and removes its lease files by itself.
40
+ A nested unmanaged Claude cannot
29
41
  register its own endpoint through inherited activation environment variables.
30
42
  The creator-selected Registry path travels only in private Claude activation
31
43
  context, independent of a tmux server's older XDG environment.
@@ -272,10 +284,19 @@ other terminal result once the release has run.
272
284
  ### Operator input
273
285
 
274
286
  A durable envelope can also carry operator input: text a person wrote through
275
- the projmux web client, which is not an Agent. It is represented, and every
276
- reader accepts and labels it, but no command or web route creates it yet.
277
-
278
- - **Envelope.** Operator input carries `"origin":{"kind":"operator","client":"web"}`
287
+ an in-process projmux operator client, which is not an Agent. It is
288
+ represented, and every reader accepts and labels it, but no command creates
289
+ it: only an operator client's own in-process sender can, and an audit test pins
290
+ those senders.
291
+
292
+ The client is a name value, never a list projmux keeps: 1-32 bytes of lowercase
293
+ ASCII letters, digits, and `-`, starting with a letter (`internal/core/operatorclient`).
294
+ Operator input is `"kind":"operator"` with a client name under that rule; a
295
+ name outside it is not operator input and is refused as
296
+ `operator-client-invalid` where one is built. Records an earlier build wrote
297
+ with its fixed client name stay operator input under the same rule.
298
+
299
+ - **Envelope.** Operator input carries `"origin":{"kind":"operator","client":"<client>"}`
279
300
  and no `source` key; its authority is
280
301
  `{"kind":"operator","trust":"untrusted","permission":"coordination-only"}`,
281
302
  which grants none of the turn, steer, or config permissions a person at the
@@ -298,16 +319,17 @@ reader accepts and labels it, but no command or web route creates it yet.
298
319
  helper across an install, so this rule keeps a store of Agent messages
299
320
  readable by those helpers, and keeps a rollback to such a build safe until
300
321
  operator input is written.
301
- - **Frame.** The operator frame's `source` is `{"kind":"operator","client":"web"}`
322
+ - **Frame.** The operator frame's `source` is `{"kind":"operator","client":"<client>"}`
302
323
  in place of an Agent route, `sourceNotice` is "Operator input that arrived
303
- through the projmux web client; projmux did not verify the person.", and
324
+ through the projmux <client> client; projmux did not verify the person."
325
+ with the origin's client name, and
304
326
  `replyAction` is empty. The other keys are those of an Agent frame. The
305
327
  helper proves only the target current, since there is no source route.
306
328
  - **Readers.** The web transcript reader shows operator input as a `user`
307
329
  turn with `via` `projmux-web` and no `from`, judged by the `source` fields
308
330
  alone. A frame without an origin keeps its existing reading: one whose
309
331
  source and target are the same Agent is the operator's own `user` turn.
310
- `agent message status` labels operator input `source=operator (web)` in a trailing text column and prints
332
+ `agent message status` labels operator input `source=operator (<client>)` in a trailing text column and prints
311
333
  an `origin` object and no `source` in JSON; an Agent message's output is
312
334
  unchanged. A reclaimed operator record's history line carries `origin` and
313
335
  no `source`.