@kangentic/protocol 0.20.0 → 0.22.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.
@@ -13,8 +13,8 @@
13
13
  * this protocol surface honest: a tool renamed or removed desktop-side
14
14
  * fails that test instead of silently breaking phones.
15
15
  */
16
- export declare const BOARD_TOOL_READ_NAMES: readonly ["search_tasks", "find_task", "get_current_task", "get_task_stats", "get_usage_stats", "board_summary", "list_sessions", "get_session_history", "get_column_detail", "list_board_profiles", "get_handoff_context", "get_transcript", "get_session_files", "get_session_events", "get_activity_intervals"];
17
- export declare const BOARD_TOOL_WRITE_NAMES: readonly ["create_task", "update_task", "delete_task", "link_pr", "remove_attachment", "update_column", "create_board_profile", "update_board_profile", "delete_board_profile", "create_backlog_task", "promote_backlog", "update_backlog_item", "delete_backlog_item"];
16
+ export declare const BOARD_TOOL_READ_NAMES: readonly ["search_tasks", "find_task", "get_current_task", "get_task_stats", "get_usage_stats", "board_summary", "list_sessions", "get_session_history", "get_column_detail", "list_board_profiles", "get_handoff_context", "get_transcript", "get_session_files", "get_session_events", "get_activity_intervals", "list_workflows", "get_workflow"];
17
+ export declare const BOARD_TOOL_WRITE_NAMES: readonly ["create_task", "update_task", "delete_task", "link_pr", "remove_attachment", "update_column", "create_board_profile", "update_board_profile", "delete_board_profile", "create_backlog_task", "promote_backlog", "update_backlog_item", "delete_backlog_item", "pause_workflow", "resume_workflow"];
18
18
  export type BoardToolReadName = (typeof BOARD_TOOL_READ_NAMES)[number];
19
19
  export type BoardToolWriteName = (typeof BOARD_TOOL_WRITE_NAMES)[number];
20
20
  export type BoardToolName = BoardToolReadName | BoardToolWriteName;
@@ -1,4 +1,9 @@
1
- export declare const PUSH_CATEGORIES: readonly ["input-required", "turn-complete", "session-failed", "plan-complete", "spawn-stalled"];
1
+ /**
2
+ * Append only. `workflow-complete` (every task of a workflow reached Done) is
3
+ * the newest; a phone that predates it reads the envelope as an unknown
4
+ * category and shows the generic placeholder.
5
+ */
6
+ export declare const PUSH_CATEGORIES: readonly ["input-required", "turn-complete", "session-failed", "plan-complete", "spawn-stalled", "workflow-complete"];
2
7
  export type PushCategory = (typeof PUSH_CATEGORIES)[number];
3
8
  export declare function isPushCategory(value: unknown): value is PushCategory;
4
9
  /** Reject an opened envelope whose sentAt is older than this (stale replay). */
@@ -182,9 +182,10 @@ export interface SessionUsageWire {
182
182
  * task, which is what makes it meaningful for a completed one: a task worked
183
183
  * across five `--resume` legs has five session rows, and reporting only the
184
184
  * final leg would under-report everything. The desktop's getSummaryForTask
185
- * owns those aggregation rules (SUM cost/duration/tool calls/lines, MAX files
186
- * changed, and tokens taken as the latest row per session lineage so a
187
- * resumed session is not double-counted) - they are not re-derived here.
185
+ * owns those aggregation rules - they are not re-derived here. Cost, duration
186
+ * and tokens are each conversation's cumulative reading, so they count once per
187
+ * session lineage and add across lineages; tool calls and lines SUM; files
188
+ * changed takes the MAX.
188
189
  *
189
190
  * `sessionId` is the transcript ANCHOR, not a live session: it resolves
190
191
  * through the desktop's session records, which outlive the agent, so it reads
@@ -465,6 +466,74 @@ export interface BoardTaskWire {
465
466
  * key from every real wire response.
466
467
  */
467
468
  pausable?: boolean | null;
469
+ /**
470
+ * True when column automations are off for this task: no On task enter, On
471
+ * agent turn end or On task exit row runs for it in any column, and a move
472
+ * types no column message. Column settings, a hand's moves and the task's own
473
+ * first command are untouched. It is the fact the desktop card's "Automations
474
+ * disabled" strip reads, and the desktop menu's Enable or Disable automations
475
+ * row flips it.
476
+ *
477
+ * There is no verb for it. A phone flips it with the `board-tool-write`
478
+ * `update_task` call, whose param is camelCase: `automationsDisabled: true`
479
+ * or `false`, never `automations_disabled`. A workflow task always reads
480
+ * false, because its workflow's Pause holds it, and `update_task` refuses
481
+ * `true` for one. Hide the control while `workflow` is non-null, as the
482
+ * desktop menu does.
483
+ *
484
+ * The desktop also clears it by itself: when the task leaves Done (a rollback
485
+ * of a failed move excepted), when it is restored from the archive, and when
486
+ * it joins a workflow. Every change, by any hand, reaches the phone as a
487
+ * `task-updated` board event, after which the next snapshot carries the new
488
+ * value.
489
+ *
490
+ * Null or absent means a desktop that predates the field (pre-0.22.0). A
491
+ * client offers no control then, since it cannot read the switch's state.
492
+ *
493
+ * Declared OPTIONAL (`?`) like `pausable`; `parseBoardTaskWire` populates the
494
+ * key from every real wire response.
495
+ */
496
+ automations_disabled?: boolean | null;
497
+ /**
498
+ * The workflow the task belongs to (a set of linked tasks that runs through
499
+ * its boards by itself), or null for an ordinary task. Absent from desktops
500
+ * that predate workflows, which the parser reads as null, as it does a value
501
+ * it cannot read. Declared OPTIONAL for the reason `pr_merge_readiness` is.
502
+ */
503
+ workflow?: BoardTaskWorkflowWire | null;
504
+ }
505
+ /**
506
+ * A board task's workflow, as its card draws it: the strip (name, color), what
507
+ * the task waits for, and whether a hand may move it. `lock_reason` is the
508
+ * desktop's own sentence, so a phone that refuses a move says what the desktop
509
+ * would; the desktop refuses a locked move on its own anyway.
510
+ */
511
+ export interface BoardTaskWorkflowWire {
512
+ id: string;
513
+ title: string;
514
+ /** The workflow's home project, which may not be the board's. */
515
+ project_id: string;
516
+ /** `running`, `paused`, `draft` or `done`; a value a client does not know reads as running. */
517
+ state: string;
518
+ /** Which of six categorical colors (1 to 6) the desktop paints its icon in. */
519
+ color_slot: number;
520
+ /** The columns the task visits, by id, in board order. */
521
+ route: string[];
522
+ /** The tasks it waits for that are not done, named as the card's footer names them ("#413"). */
523
+ waiting_for: string[];
524
+ /**
525
+ * While the card is locked (its workflow runs and it is not waiting in a
526
+ * human gate), the desktop's sentence for a refused move; null otherwise,
527
+ * which is when the desktop draws no lock. An unlocked card still never
528
+ * moves into To Do, and while `gate_target_id` is set it moves only there.
529
+ */
530
+ lock_reason: string | null;
531
+ /**
532
+ * While the workflow runs and the card waits in a column no agent judges
533
+ * (a human gate): the one column a hand may move it to, the next on its
534
+ * route. Moving it there is how the person reports the step done. Null otherwise.
535
+ */
536
+ gate_target_id: string | null;
468
537
  }
469
538
  /**
470
539
  * One live Command Terminal of a project (protocol 0.20.0): an agent the
@@ -564,6 +633,11 @@ export declare function parseSessionEventWire(payload: JsonValue): SessionEventW
564
633
  export declare function parseBoardColumnWire(value: JsonValue): BoardColumnWire;
565
634
  /** Narrows one board-task row. Throws on a malformed required field. */
566
635
  export declare function parseBoardTaskWire(value: JsonValue): BoardTaskWire;
636
+ /**
637
+ * A board task's workflow, or null when absent or unreadable. Lenient on
638
+ * purpose: a malformed workflow costs the card its strip, never the board.
639
+ */
640
+ export declare function parseBoardTaskWorkflowWire(value: JsonValue | undefined): BoardTaskWorkflowWire | null;
567
641
  /**
568
642
  * Narrows one Command Terminal row. Throws on a malformed required field. An
569
643
  * unrecognized activity state or reason reads as null rather than throwing, so
package/dist/index.cjs CHANGED
@@ -97,6 +97,7 @@ __export(index_exports, {
97
97
  parseBacklogItemWire: () => parseBacklogItemWire,
98
98
  parseBoardColumnWire: () => parseBoardColumnWire,
99
99
  parseBoardTaskWire: () => parseBoardTaskWire,
100
+ parseBoardTaskWorkflowWire: () => parseBoardTaskWorkflowWire,
100
101
  parseCapabilityRequestPayload: () => parseCapabilityRequestPayload,
101
102
  parseCommandTerminalStartResponsePayload: () => parseCommandTerminalStartResponsePayload,
102
103
  parseCommandTerminalWire: () => parseCommandTerminalWire,
@@ -5228,7 +5229,7 @@ function base64UrlDecode(encoded) {
5228
5229
  }
5229
5230
 
5230
5231
  // src/crypto/push-envelope.ts
5231
- var PUSH_CATEGORIES = ["input-required", "turn-complete", "session-failed", "plan-complete", "spawn-stalled"];
5232
+ var PUSH_CATEGORIES = ["input-required", "turn-complete", "session-failed", "plan-complete", "spawn-stalled", "workflow-complete"];
5232
5233
  function isPushCategory(value) {
5233
5234
  return typeof value === "string" && PUSH_CATEGORIES.includes(value);
5234
5235
  }
@@ -5509,7 +5510,25 @@ function parseBoardTaskWire(value) {
5509
5510
  spawn_progress: nullableString(value, "spawn_progress"),
5510
5511
  resumable: nullableBoolean(value, "resumable"),
5511
5512
  paused: nullableBoolean(value, "paused"),
5512
- pausable: nullableBoolean(value, "pausable")
5513
+ pausable: nullableBoolean(value, "pausable"),
5514
+ automations_disabled: nullableBoolean(value, "automations_disabled"),
5515
+ workflow: parseBoardTaskWorkflowWire(value.workflow)
5516
+ };
5517
+ }
5518
+ function parseBoardTaskWorkflowWire(value) {
5519
+ if (value === void 0 || !isRecord(value)) return null;
5520
+ const strings = (field) => Array.isArray(field) ? field.filter((entry) => typeof entry === "string") : [];
5521
+ if (typeof value.id !== "string" || typeof value.title !== "string" || typeof value.project_id !== "string") return null;
5522
+ return {
5523
+ id: value.id,
5524
+ title: value.title,
5525
+ project_id: value.project_id,
5526
+ state: typeof value.state === "string" ? value.state : "running",
5527
+ color_slot: typeof value.color_slot === "number" ? value.color_slot : 1,
5528
+ route: strings(value.route),
5529
+ waiting_for: strings(value.waiting_for),
5530
+ lock_reason: typeof value.lock_reason === "string" ? value.lock_reason : null,
5531
+ gate_target_id: typeof value.gate_target_id === "string" ? value.gate_target_id : null
5513
5532
  };
5514
5533
  }
5515
5534
  function parseCommandTerminalWire(value) {
@@ -6186,7 +6205,10 @@ var BOARD_TOOL_READ_NAMES = [
6186
6205
  "get_transcript",
6187
6206
  "get_session_files",
6188
6207
  "get_session_events",
6189
- "get_activity_intervals"
6208
+ "get_activity_intervals",
6209
+ // Workflows: the project's workflows and one workflow's tasks, routes and links.
6210
+ "list_workflows",
6211
+ "get_workflow"
6190
6212
  ];
6191
6213
  var BOARD_TOOL_WRITE_NAMES = [
6192
6214
  "create_task",
@@ -6201,7 +6223,10 @@ var BOARD_TOOL_WRITE_NAMES = [
6201
6223
  "create_backlog_task",
6202
6224
  "promote_backlog",
6203
6225
  "update_backlog_item",
6204
- "delete_backlog_item"
6226
+ "delete_backlog_item",
6227
+ // Workflows: stop every task of a running workflow at once, and start them again.
6228
+ "pause_workflow",
6229
+ "resume_workflow"
6205
6230
  ];
6206
6231
  function isBoardToolReadName(value) {
6207
6232
  return BOARD_TOOL_READ_NAMES.includes(value);
@@ -6404,6 +6429,7 @@ function isBridgeEvent(value) {
6404
6429
  parseBacklogItemWire,
6405
6430
  parseBoardColumnWire,
6406
6431
  parseBoardTaskWire,
6432
+ parseBoardTaskWorkflowWire,
6407
6433
  parseCapabilityRequestPayload,
6408
6434
  parseCommandTerminalStartResponsePayload,
6409
6435
  parseCommandTerminalWire,
package/dist/index.d.ts CHANGED
@@ -22,5 +22,5 @@ export { formatKeyFingerprint } from './roster/fingerprint';
22
22
  export { CAPABILITY_VERBS, isCapabilityVerb, capabilitySetFromArray, capabilitySetToArray, type CapabilityVerb, type CapabilitySet, } from './capabilities/verbs';
23
23
  export { BOARD_TOOL_READ_NAMES, BOARD_TOOL_WRITE_NAMES, isBoardToolReadName, isBoardToolWriteName, type BoardToolReadName, type BoardToolWriteName, type BoardToolName, } from './capabilities/board-tools';
24
24
  export { isBridgeEvent, parseActivityEventPayload, type BridgeEvent, type TranscriptEvent, type ActivityEvent, type ActivityEventPayload, type TerminalEvent, type TerminalResizeEvent, type BoardEvent, type BoardEventPayload, type DiffEvent, } from './events/event';
25
- export { parseTranscriptEntriesWire, parseTranscriptEventPayload, type TranscriptEventPayload, type TranscriptUpsertWire, isActivityStateWire, isActivityReasonWire, parseSessionUsageWire, parseSessionSummaryWire, parseSessionEventWire, parseTerminalDimensionsWire, parseBoardColumnWire, parseBoardTaskWire, parseCommandTerminalWire, parseBacklogItemWire, parseDiffFileListWire, parseDiffFileContentWire, isTodoRole, isDoneRole, BOARD_COLUMN_ROLES, type TranscriptBlockWire, type TranscriptEntryWire, type TranscriptTurnUsageWire, type TranscriptSystemSubtypeWire, type ActivityStateWire, type ActivityReasonWire, type SessionUsageWire, type SessionSummaryWire, type SessionEventWire, type TerminalDimensionsWire, type BoardColumnWire, type BoardColumnRoleWire, type BoardTaskWire, type CommandTerminalWire, type BacklogItemWire, type DiffFileStatusWire, type DiffFileWire, type DiffFileListWire, type DiffFileContentWire, } from './events/payloads';
25
+ export { parseTranscriptEntriesWire, parseTranscriptEventPayload, type TranscriptEventPayload, type TranscriptUpsertWire, isActivityStateWire, isActivityReasonWire, parseSessionUsageWire, parseSessionSummaryWire, parseSessionEventWire, parseTerminalDimensionsWire, parseBoardColumnWire, parseBoardTaskWire, parseCommandTerminalWire, parseBoardTaskWorkflowWire, parseBacklogItemWire, parseDiffFileListWire, parseDiffFileContentWire, isTodoRole, isDoneRole, BOARD_COLUMN_ROLES, type TranscriptBlockWire, type TranscriptEntryWire, type TranscriptTurnUsageWire, type TranscriptSystemSubtypeWire, type ActivityStateWire, type ActivityReasonWire, type SessionUsageWire, type SessionSummaryWire, type SessionEventWire, type TerminalDimensionsWire, type BoardColumnWire, type BoardColumnRoleWire, type BoardTaskWire, type CommandTerminalWire, type BoardTaskWorkflowWire, type BacklogItemWire, type DiffFileStatusWire, type DiffFileWire, type DiffFileListWire, type DiffFileContentWire, } from './events/payloads';
26
26
  export type { Transport, TransportState, Unsubscribe } from './transport/transport';
package/dist/index.mjs CHANGED
@@ -5089,7 +5089,7 @@ function base64UrlDecode(encoded) {
5089
5089
  }
5090
5090
 
5091
5091
  // src/crypto/push-envelope.ts
5092
- var PUSH_CATEGORIES = ["input-required", "turn-complete", "session-failed", "plan-complete", "spawn-stalled"];
5092
+ var PUSH_CATEGORIES = ["input-required", "turn-complete", "session-failed", "plan-complete", "spawn-stalled", "workflow-complete"];
5093
5093
  function isPushCategory(value) {
5094
5094
  return typeof value === "string" && PUSH_CATEGORIES.includes(value);
5095
5095
  }
@@ -5370,7 +5370,25 @@ function parseBoardTaskWire(value) {
5370
5370
  spawn_progress: nullableString(value, "spawn_progress"),
5371
5371
  resumable: nullableBoolean(value, "resumable"),
5372
5372
  paused: nullableBoolean(value, "paused"),
5373
- pausable: nullableBoolean(value, "pausable")
5373
+ pausable: nullableBoolean(value, "pausable"),
5374
+ automations_disabled: nullableBoolean(value, "automations_disabled"),
5375
+ workflow: parseBoardTaskWorkflowWire(value.workflow)
5376
+ };
5377
+ }
5378
+ function parseBoardTaskWorkflowWire(value) {
5379
+ if (value === void 0 || !isRecord(value)) return null;
5380
+ const strings = (field) => Array.isArray(field) ? field.filter((entry) => typeof entry === "string") : [];
5381
+ if (typeof value.id !== "string" || typeof value.title !== "string" || typeof value.project_id !== "string") return null;
5382
+ return {
5383
+ id: value.id,
5384
+ title: value.title,
5385
+ project_id: value.project_id,
5386
+ state: typeof value.state === "string" ? value.state : "running",
5387
+ color_slot: typeof value.color_slot === "number" ? value.color_slot : 1,
5388
+ route: strings(value.route),
5389
+ waiting_for: strings(value.waiting_for),
5390
+ lock_reason: typeof value.lock_reason === "string" ? value.lock_reason : null,
5391
+ gate_target_id: typeof value.gate_target_id === "string" ? value.gate_target_id : null
5374
5392
  };
5375
5393
  }
5376
5394
  function parseCommandTerminalWire(value) {
@@ -6047,7 +6065,10 @@ var BOARD_TOOL_READ_NAMES = [
6047
6065
  "get_transcript",
6048
6066
  "get_session_files",
6049
6067
  "get_session_events",
6050
- "get_activity_intervals"
6068
+ "get_activity_intervals",
6069
+ // Workflows: the project's workflows and one workflow's tasks, routes and links.
6070
+ "list_workflows",
6071
+ "get_workflow"
6051
6072
  ];
6052
6073
  var BOARD_TOOL_WRITE_NAMES = [
6053
6074
  "create_task",
@@ -6062,7 +6083,10 @@ var BOARD_TOOL_WRITE_NAMES = [
6062
6083
  "create_backlog_task",
6063
6084
  "promote_backlog",
6064
6085
  "update_backlog_item",
6065
- "delete_backlog_item"
6086
+ "delete_backlog_item",
6087
+ // Workflows: stop every task of a running workflow at once, and start them again.
6088
+ "pause_workflow",
6089
+ "resume_workflow"
6066
6090
  ];
6067
6091
  function isBoardToolReadName(value) {
6068
6092
  return BOARD_TOOL_READ_NAMES.includes(value);
@@ -6264,6 +6288,7 @@ export {
6264
6288
  parseBacklogItemWire,
6265
6289
  parseBoardColumnWire,
6266
6290
  parseBoardTaskWire,
6291
+ parseBoardTaskWorkflowWire,
6267
6292
  parseCapabilityRequestPayload,
6268
6293
  parseCommandTerminalStartResponsePayload,
6269
6294
  parseCommandTerminalWire,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kangentic/protocol",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Kangentic mobile bridge wire protocol: framing, Noise-based pairing and session handshakes, signed device roster, and capability verbs shared between desktop and mobile.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",