@kangentic/protocol 0.13.1 → 0.15.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.
@@ -8,8 +8,17 @@
8
8
  * the desktop's capability router (Phase 2) still has to implement and
9
9
  * wire a handler, and a device's roster entry still has to include it in
10
10
  * its CapabilitySet.
11
+ *
12
+ * Append only. The desktop mirrors this tuple by hand in its import-free
13
+ * types module and pins the two equal INDEX for index, so a verb inserted
14
+ * mid-list fails that parity test even when both lists hold the same names.
15
+ *
16
+ * `start-session` is the second lifecycle verb beside `move-task`: it spawns
17
+ * or resumes a task's session in the column the task is already in, so a
18
+ * phone's "Session ended" state can bring the agent back without moving the
19
+ * task. A live session is an idempotent no-op; nothing is ever stopped.
11
20
  */
12
- export declare const CAPABILITY_VERBS: readonly ["read-stream", "read-board", "read-diff", "send-user-message", "move-task", "answer-permission-prompt", "interactive-terminal", "board-tool-read", "board-tool-write", "register-push"];
21
+ export declare const CAPABILITY_VERBS: readonly ["read-stream", "read-board", "read-diff", "send-user-message", "move-task", "answer-permission-prompt", "interactive-terminal", "board-tool-read", "board-tool-write", "register-push", "start-session"];
13
22
  export type CapabilityVerb = (typeof CAPABILITY_VERBS)[number];
14
23
  export declare function isCapabilityVerb(value: string): value is CapabilityVerb;
15
24
  /** Deny-by-default: a verb absent from the set is not authorized. */
@@ -65,10 +65,48 @@ export type ActivityEventPayload = {
65
65
  * phone learns "this session is over" from the feed itself instead of
66
66
  * inferring it from silence. `intentional` distinguishes a deliberate
67
67
  * stop (desktop Stop button, suspend, shutdown) from a crash.
68
+ *
69
+ * `spawnProgressLabel`, when present, means the desktop had a respawn in
70
+ * flight for this task when the session ended - a same-column respawn
71
+ * (model switch, agent switch, effort change, isolated-session-track
72
+ * switch) or an in-place restart (a model or effort pick on the running
73
+ * task, a board-profile change, or the auto_command escalation that
74
+ * re-sends a command as the resume prompt, "Re-sending command...") rather
75
+ * than a genuine park. Read it as what the desktop
76
+ * believed, not as a fact about what happens next; the caveats below
77
+ * bound it. `intentional` cannot carry this distinction on its own:
78
+ * the desktop's SessionManager.suspend() sets `status = 'suspended'`
79
+ * before the force-kill for every caller, a respawn and a real park
80
+ * alike, so both reach the phone as `intentional: true`. The string is
81
+ * the desktop's own display text for what it is doing ("Switching
82
+ * model...", "Starting agent...", a live git-queue wait count) - treat it
83
+ * as untrusted display text, not a key to switch on, cap its length, and
84
+ * fall back to generic copy rather than parsing it.
85
+ *
86
+ * INTENT, not a guarantee, on the same terms `BoardColumnWire.spawns_session`
87
+ * documents: the desktop can suspend without a successor ever landing (a
88
+ * board profile change, a failed worktree checkout, a shutdown, a racing
89
+ * move), so a client MUST keep whatever timeout already bounds its
90
+ * session-swap wait and use the label only to skip a redundant one.
91
+ *
92
+ * Absent from pre-0.14.0 desktops, and never sent as `null`. A park that
93
+ * goes through `task-move.ts` (move to To Do, to Done, or into an
94
+ * `auto_spawn=false` column) clears the label first, so it carries none.
95
+ * Five other genuine parks do not clear it - a manual pause, the
96
+ * idle-timeout suspend, the `kill_session` action, project-relocate, and
97
+ * auto-spawn-reconcile - so one of those firing while a label is still in
98
+ * flight sends the label on a real park. The label then survives at most
99
+ * the desktop's 120s spawn-progress TTL. That gap is why the timeout above
100
+ * is mandatory, not advisory.
101
+ *
102
+ * A label can also ride an `intentional: false` exit, since a respawn whose
103
+ * spawn fails still has its label in flight when the PTY dies. The two
104
+ * fields are independent; do not read them as mutually exclusive.
68
105
  */
69
106
  | {
70
107
  type: 'session-ended';
71
108
  intentional: boolean;
109
+ spawnProgressLabel?: string;
72
110
  }
73
111
  /**
74
112
  * The agent's most recent assistant message, already collapsed to a short