crewly 1.20.214 → 1.20.216

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 (183) hide show
  1. package/config/hooks/agent-status/report.sh +45 -6
  2. package/config/roles/team-leader/fragments/role-boundary.md +2 -1
  3. package/config/roles/team-leader/prompt.md +9 -5
  4. package/config/roles/team-leader/role-boundaries.md +3 -2
  5. package/config/roles/team-leader/tl-addon.md +9 -5
  6. package/config/skills/agent/core/ask-owner/SKILL.md +9 -2
  7. package/config/skills/agent/core/ask-owner/execute.sh +1 -1
  8. package/config/skills/agent/core/project-tickets/SKILL.md +44 -12
  9. package/config/skills/agent/core/project-tickets/execute.sh +46 -13
  10. package/config/skills/agent/core/project-tickets/execute.test.sh +19 -0
  11. package/config/skills/team-leader/delegate-task/SKILL.md +40 -0
  12. package/config/skills/team-leader/delegate-task/execute.sh +39 -1
  13. package/dist/backend/backend/src/constants.d.ts +101 -10
  14. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  15. package/dist/backend/backend/src/constants.js +119 -9
  16. package/dist/backend/backend/src/constants.js.map +1 -1
  17. package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts +2 -1
  18. package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.d.ts.map +1 -1
  19. package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js +26 -3
  20. package/dist/backend/backend/src/controllers/agent-hooks/agent-hooks.controller.js.map +1 -1
  21. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts +10 -2
  22. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.d.ts.map +1 -1
  23. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js +17 -2
  24. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.controller.js.map +1 -1
  25. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts +2 -1
  26. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.d.ts.map +1 -1
  27. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js +4 -2
  28. package/dist/backend/backend/src/controllers/project-tickets/project-tickets.routes.js.map +1 -1
  29. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
  30. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +32 -0
  31. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
  32. package/dist/backend/backend/src/controllers/team/team-lead-share.controller.d.ts +27 -0
  33. package/dist/backend/backend/src/controllers/team/team-lead-share.controller.d.ts.map +1 -0
  34. package/dist/backend/backend/src/controllers/team/team-lead-share.controller.js +92 -0
  35. package/dist/backend/backend/src/controllers/team/team-lead-share.controller.js.map +1 -0
  36. package/dist/backend/backend/src/controllers/team/team.routes.d.ts.map +1 -1
  37. package/dist/backend/backend/src/controllers/team/team.routes.js +4 -0
  38. package/dist/backend/backend/src/controllers/team/team.routes.js.map +1 -1
  39. package/dist/backend/backend/src/index.d.ts.map +1 -1
  40. package/dist/backend/backend/src/index.js +16 -0
  41. package/dist/backend/backend/src/index.js.map +1 -1
  42. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  43. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +6 -0
  44. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  45. package/dist/backend/backend/src/services/decisions/decision-contract.d.ts +25 -1
  46. package/dist/backend/backend/src/services/decisions/decision-contract.d.ts.map +1 -1
  47. package/dist/backend/backend/src/services/decisions/decision-contract.js +39 -2
  48. package/dist/backend/backend/src/services/decisions/decision-contract.js.map +1 -1
  49. package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  50. package/dist/backend/backend/src/services/decisions/decision.service.js +17 -1
  51. package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
  52. package/dist/backend/backend/src/services/open-items/open-item-card.d.ts +26 -0
  53. package/dist/backend/backend/src/services/open-items/open-item-card.d.ts.map +1 -1
  54. package/dist/backend/backend/src/services/open-items/open-item-card.js +71 -1
  55. package/dist/backend/backend/src/services/open-items/open-item-card.js.map +1 -1
  56. package/dist/backend/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
  57. package/dist/backend/backend/src/services/open-items/open-items.service.js +6 -3
  58. package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
  59. package/dist/backend/backend/src/services/orc/reply-destination.wiring.d.ts.map +1 -1
  60. package/dist/backend/backend/src/services/orc/reply-destination.wiring.js +46 -1
  61. package/dist/backend/backend/src/services/orc/reply-destination.wiring.js.map +1 -1
  62. package/dist/backend/backend/src/services/orc/work-item-destination.d.ts +35 -0
  63. package/dist/backend/backend/src/services/orc/work-item-destination.d.ts.map +1 -1
  64. package/dist/backend/backend/src/services/orc/work-item-destination.js +75 -2
  65. package/dist/backend/backend/src/services/orc/work-item-destination.js.map +1 -1
  66. package/dist/backend/backend/src/services/project-tickets/autopilot-speed-command.d.ts +108 -0
  67. package/dist/backend/backend/src/services/project-tickets/autopilot-speed-command.d.ts.map +1 -0
  68. package/dist/backend/backend/src/services/project-tickets/autopilot-speed-command.js +223 -0
  69. package/dist/backend/backend/src/services/project-tickets/autopilot-speed-command.js.map +1 -0
  70. package/dist/backend/backend/src/services/project-tickets/autopilot-speed.wiring.d.ts +57 -0
  71. package/dist/backend/backend/src/services/project-tickets/autopilot-speed.wiring.d.ts.map +1 -0
  72. package/dist/backend/backend/src/services/project-tickets/autopilot-speed.wiring.js +90 -0
  73. package/dist/backend/backend/src/services/project-tickets/autopilot-speed.wiring.js.map +1 -0
  74. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts +18 -4
  75. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.d.ts.map +1 -1
  76. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js +18 -4
  77. package/dist/backend/backend/src/services/project-tickets/project-ticket-workflow.service.js.map +1 -1
  78. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts +135 -14
  79. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.d.ts.map +1 -1
  80. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js +111 -18
  81. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-decision.js.map +1 -1
  82. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts +73 -4
  83. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.d.ts.map +1 -1
  84. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js +86 -7
  85. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-messages.js.map +1 -1
  86. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.d.ts +1 -1
  87. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.d.ts.map +1 -1
  88. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.js +7 -0
  89. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot-trace.js.map +1 -1
  90. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts +104 -4
  91. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.d.ts.map +1 -1
  92. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js +424 -12
  93. package/dist/backend/backend/src/services/project-tickets/ticket-autopilot.service.js.map +1 -1
  94. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  95. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +2 -1
  96. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  97. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  98. package/dist/backend/backend/src/services/slack/slack-initializer.js +10 -0
  99. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  100. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +7 -0
  101. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  102. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +25 -2
  103. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  104. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +23 -0
  105. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  106. package/dist/backend/backend/src/services/task-pool/task-pool.service.js +74 -2
  107. package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  108. package/dist/backend/backend/src/services/tl-delegation/lead-share.d.ts +108 -0
  109. package/dist/backend/backend/src/services/tl-delegation/lead-share.d.ts.map +1 -0
  110. package/dist/backend/backend/src/services/tl-delegation/lead-share.js +170 -0
  111. package/dist/backend/backend/src/services/tl-delegation/lead-share.js.map +1 -0
  112. package/dist/backend/backend/src/services/tl-delegation/lead-share.wiring.d.ts +32 -0
  113. package/dist/backend/backend/src/services/tl-delegation/lead-share.wiring.d.ts.map +1 -0
  114. package/dist/backend/backend/src/services/tl-delegation/lead-share.wiring.js +47 -0
  115. package/dist/backend/backend/src/services/tl-delegation/lead-share.wiring.js.map +1 -0
  116. package/dist/backend/backend/src/services/tl-delegation/tl-delegation.service.d.ts +207 -0
  117. package/dist/backend/backend/src/services/tl-delegation/tl-delegation.service.d.ts.map +1 -0
  118. package/dist/backend/backend/src/services/tl-delegation/tl-delegation.service.js +377 -0
  119. package/dist/backend/backend/src/services/tl-delegation/tl-delegation.service.js.map +1 -0
  120. package/dist/backend/backend/src/types/decision.types.d.ts +6 -1
  121. package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
  122. package/dist/backend/backend/src/types/decision.types.js +1 -1
  123. package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts +46 -4
  124. package/dist/backend/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
  125. package/dist/backend/backend/src/types/ticket-autopilot.types.js +43 -2
  126. package/dist/backend/backend/src/types/ticket-autopilot.types.js.map +1 -1
  127. package/dist/backend/backend/src/types/v2/work-item.types.d.ts +1 -1
  128. package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  129. package/dist/backend/backend/src/types/v2/work-item.types.js +1 -0
  130. package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
  131. package/dist/backend/backend/src/utils/defaultPrompts.js +3 -3
  132. package/dist/backend/backend/src/utils/defaultPrompts.js.map +1 -1
  133. package/dist/backend/build-info.json +2 -2
  134. package/dist/cli/backend/src/constants.d.ts +101 -10
  135. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  136. package/dist/cli/backend/src/constants.js +119 -9
  137. package/dist/cli/backend/src/constants.js.map +1 -1
  138. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  139. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +6 -0
  140. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  141. package/dist/cli/backend/src/services/decisions/decision-contract.d.ts +25 -1
  142. package/dist/cli/backend/src/services/decisions/decision-contract.d.ts.map +1 -1
  143. package/dist/cli/backend/src/services/decisions/decision-contract.js +39 -2
  144. package/dist/cli/backend/src/services/decisions/decision-contract.js.map +1 -1
  145. package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  146. package/dist/cli/backend/src/services/decisions/decision.service.js +17 -1
  147. package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
  148. package/dist/cli/backend/src/services/open-items/open-item-card.d.ts +26 -0
  149. package/dist/cli/backend/src/services/open-items/open-item-card.d.ts.map +1 -1
  150. package/dist/cli/backend/src/services/open-items/open-item-card.js +71 -1
  151. package/dist/cli/backend/src/services/open-items/open-item-card.js.map +1 -1
  152. package/dist/cli/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
  153. package/dist/cli/backend/src/services/open-items/open-items.service.js +6 -3
  154. package/dist/cli/backend/src/services/open-items/open-items.service.js.map +1 -1
  155. package/dist/cli/backend/src/services/orc/work-item-destination.d.ts +35 -0
  156. package/dist/cli/backend/src/services/orc/work-item-destination.d.ts.map +1 -1
  157. package/dist/cli/backend/src/services/orc/work-item-destination.js +75 -2
  158. package/dist/cli/backend/src/services/orc/work-item-destination.js.map +1 -1
  159. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  160. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +2 -1
  161. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  162. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +7 -0
  163. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  164. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +25 -2
  165. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  166. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +23 -0
  167. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  168. package/dist/cli/backend/src/services/task-pool/task-pool.service.js +74 -2
  169. package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  170. package/dist/cli/backend/src/types/decision.types.d.ts +6 -1
  171. package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -1
  172. package/dist/cli/backend/src/types/decision.types.js +1 -1
  173. package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts +46 -4
  174. package/dist/cli/backend/src/types/ticket-autopilot.types.d.ts.map +1 -1
  175. package/dist/cli/backend/src/types/ticket-autopilot.types.js +43 -2
  176. package/dist/cli/backend/src/types/ticket-autopilot.types.js.map +1 -1
  177. package/dist/cli/backend/src/types/v2/work-item.types.d.ts +1 -1
  178. package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  179. package/dist/cli/backend/src/types/v2/work-item.types.js +1 -0
  180. package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
  181. package/frontend/dist/assets/{index-917db1b8.js → index-bc4e2a93.js} +274 -274
  182. package/frontend/dist/index.html +1 -1
  183. package/package.json +1 -1
@@ -0,0 +1,377 @@
1
+ /**
2
+ * Team-lead delegation: the execution nudge, its counts, and "no member
3
+ * fits" records (crewly#1083, specs/2026-10-04-tl-delegation.md §2, §4).
4
+ *
5
+ * The nudge rides on the Claude Code agent-status hook: each `PostToolUse`
6
+ * reports the tool name, and a lead that edited files
7
+ * {@link TL_DELEGATION_CONSTANTS.EDIT_THRESHOLD} times within
8
+ * {@link TL_DELEGATION_CONSTANTS.WINDOW_MS} gets one note back as hook
9
+ * `additionalContext` — at most once per
10
+ * {@link TL_DELEGATION_CONSTANTS.NUDGE_COOLDOWN_MS}. It never blocks: the
11
+ * tool already ran, and any failure means no note.
12
+ *
13
+ * @module services/tl-delegation/tl-delegation.service
14
+ */
15
+ import * as fs from 'fs';
16
+ import * as path from 'path';
17
+ import { TL_DELEGATION_CONSTANTS } from '../../constants.js';
18
+ import { getTeamLeads } from '../../utils/team.utils.js';
19
+ import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
20
+ import { LoggerService } from '../core/logger.service.js';
21
+ import { memberLedgerKeys } from './lead-share.js';
22
+ const AVAILABILITY_ORDER = { idle: 0, stopped: 1, working: 2 };
23
+ const AVAILABILITY_WORDS = {
24
+ idle: 'idle',
25
+ stopped: 'stopped — starts when assigned',
26
+ working: 'working',
27
+ };
28
+ /**
29
+ * Members best placed to take hands-on work: idle first, then stopped, then
30
+ * working; at most {@link TL_DELEGATION_CONSTANTS.NUDGE_MAX_MEMBERS}.
31
+ *
32
+ * @param members - The lead's members
33
+ * @returns Ranked, capped list
34
+ */
35
+ export function rankMembersForNudge(members) {
36
+ return [...members]
37
+ .sort((a, b) => AVAILABILITY_ORDER[a.availability] - AVAILABILITY_ORDER[b.availability])
38
+ .slice(0, TL_DELEGATION_CONSTANTS.NUDGE_MAX_MEMBERS);
39
+ }
40
+ /**
41
+ * The nudge text (English harness text).
42
+ *
43
+ * @param edits - Edits counted in the window
44
+ * @param members - The lead's members
45
+ * @returns Note
46
+ */
47
+ export function buildNudgeText(edits, members) {
48
+ const minutes = Math.round(TL_DELEGATION_CONSTANTS.WINDOW_MS / 60000);
49
+ const named = rankMembersForNudge(members)
50
+ .map((m) => `${m.name} (${m.role}, ${AVAILABILITY_WORDS[m.availability]})`)
51
+ .join(', ');
52
+ return (`${TL_DELEGATION_CONSTANTS.NUDGE_TAG} You have edited files ${edits} times in the last ${minutes} minutes. ` +
53
+ `As team lead, hand hands-on work to a member: ${named}. ` +
54
+ 'Any member can do any work that needs no special account, tool or permission — role is a preference, not a limit. ' +
55
+ 'Delegate with delegate-task (pass --thread <key> for an owner request, so the member answers the owner in that thread). ' +
56
+ 'Keep it only if the change is tiny, every member is busy, or it needs your own judgment — then record why: ' +
57
+ 'delegate-task --no-member-fits "<what is missing>" --task "<the work>".');
58
+ }
59
+ /**
60
+ * Local date key (YYYY-MM-DD).
61
+ *
62
+ * @param ms - Epoch ms
63
+ * @returns Day key
64
+ */
65
+ export function localDayKey(ms) {
66
+ const d = new Date(ms);
67
+ const pad = (n) => String(n).padStart(2, '0');
68
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
69
+ }
70
+ /**
71
+ * Trim a free-text field to one line within the cap.
72
+ *
73
+ * @param text - Any text
74
+ * @returns One line, capped
75
+ */
76
+ function oneLine(text) {
77
+ const flat = text.replace(/\s+/g, ' ').trim();
78
+ const max = TL_DELEGATION_CONSTANTS.MAX_TEXT_CHARS;
79
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
80
+ }
81
+ /**
82
+ * Nudge bookkeeping and kept-work records.
83
+ */
84
+ export class TlDelegationService {
85
+ static instance = null;
86
+ deps;
87
+ statePath;
88
+ now;
89
+ logger;
90
+ /** session → recent edit times (epoch ms), in-memory only */
91
+ edits = new Map();
92
+ state = null;
93
+ writing = Promise.resolve();
94
+ /**
95
+ * @param deps - Collaborators
96
+ */
97
+ constructor(deps) {
98
+ this.deps = deps;
99
+ this.statePath = deps.statePath ?? path.join(getCrewlyHomePath(), TL_DELEGATION_CONSTANTS.STATE_FILENAME);
100
+ this.now = deps.now ?? (() => Date.now());
101
+ this.logger = deps.logger ?? LoggerService.getInstance().createComponentLogger('TlDelegation');
102
+ }
103
+ /**
104
+ * The process instance (built from the team store on first use).
105
+ *
106
+ * @returns Service
107
+ */
108
+ static getInstance() {
109
+ if (!TlDelegationService.instance) {
110
+ TlDelegationService.instance = new TlDelegationService({ leadContext: cachedLeadContext() });
111
+ }
112
+ return TlDelegationService.instance;
113
+ }
114
+ /**
115
+ * Replace (tests) or clear the process instance.
116
+ *
117
+ * @param service - New instance, or null
118
+ */
119
+ static setInstance(service) {
120
+ TlDelegationService.instance = service;
121
+ }
122
+ /**
123
+ * A tool call finished in `session`. Returns the nudge to show the agent,
124
+ * or null. Never throws.
125
+ *
126
+ * @param session - Agent session
127
+ * @param toolName - Claude Code tool name
128
+ * @returns Nudge text, or null
129
+ */
130
+ async observeToolUse(session, toolName) {
131
+ try {
132
+ if (!TL_DELEGATION_CONSTANTS.EDIT_TOOLS.includes(toolName))
133
+ return null;
134
+ const now = this.now();
135
+ const recent = (this.edits.get(session) ?? []).filter((t) => now - t < TL_DELEGATION_CONSTANTS.WINDOW_MS);
136
+ recent.push(now);
137
+ this.edits.set(session, recent);
138
+ if (recent.length < TL_DELEGATION_CONSTANTS.EDIT_THRESHOLD)
139
+ return null;
140
+ const state = this.load();
141
+ const counts = state.nudges[session];
142
+ if (counts?.lastAt !== undefined && now - counts.lastAt < TL_DELEGATION_CONSTANTS.NUDGE_COOLDOWN_MS)
143
+ return null;
144
+ const lead = await this.deps.leadContext(session);
145
+ if (!lead || lead.members.length === 0) {
146
+ // Not a lead: stop counting for it until the window passes.
147
+ this.edits.set(session, []);
148
+ return null;
149
+ }
150
+ const text = buildNudgeText(recent.length, lead.members);
151
+ this.edits.set(session, []);
152
+ const next = { ...(counts ?? { count: 0, followed: 0 }) };
153
+ next.count += 1;
154
+ next.lastAt = now;
155
+ next.pendingSince = now;
156
+ const day = localDayKey(now);
157
+ const days = { ...(next.days ?? {}) };
158
+ days[day] = { count: (days[day]?.count ?? 0) + 1, followed: days[day]?.followed ?? 0 };
159
+ next.days = pruneDays(days, now);
160
+ state.nudges[session] = next;
161
+ this.save();
162
+ this.logger.info('Team lead nudged to delegate', { session, teamId: lead.teamId, edits: recent.length });
163
+ return text;
164
+ }
165
+ catch (err) {
166
+ this.logger.debug('Nudge check failed — no nudge', { session, error: err instanceof Error ? err.message : String(err) });
167
+ return null;
168
+ }
169
+ }
170
+ /**
171
+ * A work item was delegated. Counts as following a nudge when the
172
+ * delegator was nudged within {@link TL_DELEGATION_CONSTANTS.FOLLOW_WINDOW_MS}.
173
+ *
174
+ * @param delegator - Delegating session
175
+ * @param target - Target session
176
+ * @returns True when it followed a nudge
177
+ */
178
+ recordDelegation(delegator, target) {
179
+ try {
180
+ if (!delegator || !target || delegator === target)
181
+ return false;
182
+ const state = this.load();
183
+ const counts = state.nudges[delegator];
184
+ if (!counts?.pendingSince)
185
+ return false;
186
+ const now = this.now();
187
+ if (now - counts.pendingSince > TL_DELEGATION_CONSTANTS.FOLLOW_WINDOW_MS) {
188
+ delete counts.pendingSince;
189
+ this.save();
190
+ return false;
191
+ }
192
+ counts.followed += 1;
193
+ const day = localDayKey(counts.pendingSince);
194
+ if (counts.days?.[day])
195
+ counts.days[day].followed += 1;
196
+ delete counts.pendingSince;
197
+ this.save();
198
+ this.logger.info('Team lead delegated after a nudge', { delegator, target });
199
+ return true;
200
+ }
201
+ catch {
202
+ return false;
203
+ }
204
+ }
205
+ /**
206
+ * Record work a lead keeps because no member fits.
207
+ *
208
+ * @param input - Lead session, team, reason, work, optional work item / ticket
209
+ * @returns The stored record
210
+ */
211
+ recordKeptWork(input) {
212
+ const record = {
213
+ at: new Date(this.now()).toISOString(),
214
+ session: input.session,
215
+ ...(input.teamId ? { teamId: input.teamId } : {}),
216
+ reason: oneLine(input.reason),
217
+ work: oneLine(input.work),
218
+ ...(input.workItemId ? { workItemId: input.workItemId } : {}),
219
+ ...(input.ticket ? { ticket: input.ticket } : {}),
220
+ };
221
+ const state = this.load();
222
+ state.records.push(record);
223
+ if (state.records.length > TL_DELEGATION_CONSTANTS.MAX_RECORDS) {
224
+ state.records.splice(0, state.records.length - TL_DELEGATION_CONSTANTS.MAX_RECORDS);
225
+ }
226
+ this.save();
227
+ this.logger.info('Team lead kept work: no member fits', { session: input.session, teamId: input.teamId });
228
+ return record;
229
+ }
230
+ /**
231
+ * Kept-work records since a time, optionally for one team or set of sessions.
232
+ *
233
+ * @param sinceMs - Lower bound (epoch ms)
234
+ * @param filter - Team id and/or lead sessions (either matches)
235
+ * @returns Records, oldest first
236
+ */
237
+ keptWorkSince(sinceMs, filter) {
238
+ const sessions = new Set(filter?.sessions ?? []);
239
+ return this.load().records.filter((r) => {
240
+ if ((Date.parse(r.at) || 0) < sinceMs)
241
+ return false;
242
+ if (!filter)
243
+ return true;
244
+ return (filter.teamId !== undefined && r.teamId === filter.teamId) || sessions.has(r.session);
245
+ });
246
+ }
247
+ /**
248
+ * Nudge counts of some sessions: all-time, and for one local day.
249
+ *
250
+ * @param sessions - Lead sessions
251
+ * @param dayMs - A time on the day to report (default: now)
252
+ * @returns Totals and that day's numbers
253
+ */
254
+ nudgeCounts(sessions, dayMs) {
255
+ const state = this.load();
256
+ const day = localDayKey(dayMs ?? this.now());
257
+ const out = { total: { count: 0, followed: 0 }, day: { count: 0, followed: 0 } };
258
+ for (const s of new Set(sessions)) {
259
+ const c = state.nudges[s];
260
+ if (!c)
261
+ continue;
262
+ out.total.count += c.count;
263
+ out.total.followed += c.followed;
264
+ out.day.count += c.days?.[day]?.count ?? 0;
265
+ out.day.followed += c.days?.[day]?.followed ?? 0;
266
+ }
267
+ return out;
268
+ }
269
+ /** Wait for pending writes (tests, shutdown). */
270
+ async flush() {
271
+ await this.writing;
272
+ }
273
+ /**
274
+ * Load the state once (a missing or broken file starts empty).
275
+ *
276
+ * @returns State
277
+ */
278
+ load() {
279
+ if (this.state)
280
+ return this.state;
281
+ let parsed = null;
282
+ try {
283
+ parsed = JSON.parse(fs.readFileSync(this.statePath, 'utf8'));
284
+ }
285
+ catch {
286
+ parsed = null;
287
+ }
288
+ this.state = {
289
+ version: 1,
290
+ nudges: parsed && typeof parsed.nudges === 'object' && parsed.nudges ? parsed.nudges : {},
291
+ records: Array.isArray(parsed?.records) ? parsed.records : [],
292
+ };
293
+ return this.state;
294
+ }
295
+ /** Write the state (serialized, best-effort). */
296
+ save() {
297
+ const snapshot = JSON.stringify(this.state, null, 2);
298
+ this.writing = this.writing
299
+ .then(async () => {
300
+ await fs.promises.mkdir(path.dirname(this.statePath), { recursive: true });
301
+ const tmp = `${this.statePath}.tmp`;
302
+ await fs.promises.writeFile(tmp, snapshot, 'utf8');
303
+ await fs.promises.rename(tmp, this.statePath);
304
+ })
305
+ .catch((err) => {
306
+ this.logger.warn('Could not save team-lead delegation state', { error: err instanceof Error ? err.message : String(err) });
307
+ });
308
+ }
309
+ }
310
+ /**
311
+ * Keep only the last 14 days of per-day counts.
312
+ *
313
+ * @param days - Day key → counts
314
+ * @param now - Clock
315
+ * @returns Pruned map
316
+ */
317
+ function pruneDays(days, now) {
318
+ const oldest = localDayKey(now - 14 * 24 * 60 * 60 * 1000);
319
+ return Object.fromEntries(Object.entries(days).filter(([k]) => k >= oldest));
320
+ }
321
+ /**
322
+ * The availability of a member, as the nudge words it.
323
+ *
324
+ * @param m - Member
325
+ * @returns Availability
326
+ */
327
+ export function memberAvailability(m) {
328
+ if (m.agentStatus === 'inactive' || m.agentStatus === 'suspended')
329
+ return 'stopped';
330
+ return m.workingStatus === 'in_progress' ? 'working' : 'idle';
331
+ }
332
+ /**
333
+ * The lead context of a session among teams: the team it leads, with its
334
+ * other members. Null when it leads no team with other members.
335
+ *
336
+ * @param teams - Teams
337
+ * @param session - Agent session
338
+ * @returns Context, or null
339
+ */
340
+ export function leadContextFromTeams(teams, session) {
341
+ for (const team of teams) {
342
+ if (team.archived)
343
+ continue;
344
+ const leads = getTeamLeads(team);
345
+ if (!leads.some((l) => memberLedgerKeys(l).includes(session)))
346
+ continue;
347
+ const leadIds = new Set(leads.map((l) => l.id));
348
+ const members = (team.members ?? [])
349
+ .filter((m) => !leadIds.has(m.id) && m.role !== 'orchestrator')
350
+ .map((m) => ({ name: m.name, role: String(m.role), availability: memberAvailability(m) }));
351
+ if (members.length === 0)
352
+ continue;
353
+ return { teamId: team.id, teamName: team.name, members };
354
+ }
355
+ return null;
356
+ }
357
+ /**
358
+ * Lead context from the team store, cached per session for a minute (the
359
+ * hook calls this on every file edit).
360
+ *
361
+ * @returns Lookup
362
+ */
363
+ function cachedLeadContext() {
364
+ const cache = new Map();
365
+ const TTL = 60 * 1000;
366
+ return async (session) => {
367
+ const hit = cache.get(session);
368
+ if (hit && Date.now() - hit.at < TTL)
369
+ return hit.value;
370
+ const { StorageService } = await import('../core/storage.service.js');
371
+ const teams = await StorageService.getInstance().getTeams().catch(() => []);
372
+ const value = leadContextFromTeams(teams, session);
373
+ cache.set(session, { at: Date.now(), value });
374
+ return value;
375
+ };
376
+ }
377
+ //# sourceMappingURL=tl-delegation.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tl-delegation.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/tl-delegation/tl-delegation.service.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Decision cards — structured owner questions (specs/2026-10-01-decision-cards.md).
3
3
  *
4
- * An agent that needs the owner asks ONE question with 2–3 options, a default
4
+ * An agent that needs the owner asks ONE question with 2–5 options, a default
5
5
  * and a deadline. The responsible agent's own Slack bot posts it as a card in
6
6
  * the team channel (ticket thread, or a new thread), and the owner answers
7
7
  * with a button, a reaction or a thread reply. The decision is stored here
@@ -71,6 +71,11 @@ export interface DecisionOption {
71
71
  label: string;
72
72
  /** Optional one-line detail shown under the question */
73
73
  detail?: string;
74
+ /**
75
+ * The agent's full question this option stands for (either/or cards derived
76
+ * from consecutive reply questions): quoted back to the agent when chosen.
77
+ */
78
+ question?: string;
74
79
  }
75
80
  /** Lifecycle of a decision. */
76
81
  export type DecisionStatus =
@@ -1 +1 @@
1
- {"version":3,"file":"decision.types.d.ts","sourceRoot":"","sources":["../../../../../backend/src/types/decision.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decision.types.d.ts","sourceRoot":"","sources":["../../../../../backend/src/types/decision.types.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Decision cards — structured owner questions (specs/2026-10-01-decision-cards.md).
3
3
  *
4
- * An agent that needs the owner asks ONE question with 2–3 options, a default
4
+ * An agent that needs the owner asks ONE question with 2–5 options, a default
5
5
  * and a deadline. The responsible agent's own Slack bot posts it as a card in
6
6
  * the team channel (ticket thread, or a new thread), and the owner answers
7
7
  * with a button, a reaction or a thread reply. The decision is stored here
@@ -6,6 +6,25 @@
6
6
  *
7
7
  * @module types/ticket-autopilot.types
8
8
  */
9
+ import { TICKET_AUTOPILOT_CONSTANTS } from '../constants.js';
10
+ /** Autopilot speed (specs/2026-10-04-autopilot-speed-modes.md). */
11
+ export type AutopilotSpeedMode = 'rush' | 'normal' | 'chill';
12
+ /** What a speed mode supplies (see TICKET_AUTOPILOT_CONSTANTS.SPEED_MODES). */
13
+ export type AutopilotSpeedProfile = (typeof TICKET_AUTOPILOT_CONSTANTS.SPEED_MODES)[AutopilotSpeedMode];
14
+ /**
15
+ * Whether a value is a speed mode name.
16
+ *
17
+ * @param value - Anything
18
+ * @returns True for rush / normal / chill
19
+ */
20
+ export declare function isAutopilotSpeedMode(value: unknown): value is AutopilotSpeedMode;
21
+ /**
22
+ * The profile of a speed mode.
23
+ *
24
+ * @param mode - Mode
25
+ * @returns Its replan gap / cap, self-review cadence, empty-replan retry and default budget
26
+ */
27
+ export declare function speedProfile(mode: AutopilotSpeedMode): AutopilotSpeedProfile;
9
28
  /** The per-project switch as stored. Every field but `enabled` is optional. */
10
29
  export interface TicketAutopilotSettings {
11
30
  /** Master switch (default off) */
@@ -35,11 +54,17 @@ export interface TicketAutopilotSettings {
35
54
  retro?: boolean;
36
55
  /**
37
56
  * Goal replans per local day (specs/2026-10-04-autopilot-goal-replan.md):
38
- * how often the driver may be woken to plan the next tickets toward the
39
- * project's goal when nothing is left to triage. 0 = off. Absent = the
40
- * default ({@link TICKET_AUTOPILOT_CONSTANTS.DEFAULT_REPLANS_PER_DAY}).
57
+ * a hard cap on how often the driver may be woken to plan the next tickets
58
+ * toward the project's goal when nothing is left to triage. 0 = off.
59
+ * Absent = the speed mode's daily cap.
41
60
  */
42
61
  replansPerDay?: number;
62
+ /**
63
+ * Speed mode (specs/2026-10-04-autopilot-speed-modes.md): replan gap and
64
+ * daily cap, self-review cadence, retry after an empty replan, and the
65
+ * budget when none is set. Absent = normal.
66
+ */
67
+ speedMode?: AutopilotSpeedMode;
43
68
  /**
44
69
  * Hours a goal replan may stay live before it is expired (cancelled where
45
70
  * possible, never counted as live again). Absent = the default
@@ -56,10 +81,25 @@ export interface ResolvedTicketAutopilotSettings {
56
81
  maxInFlightPerMember: number;
57
82
  /** The retro switch as set (null = the default: on while an autopilot experiment runs) */
58
83
  retro: boolean | null;
59
- /** Goal replans allowed per local day (0 = off) */
84
+ /** Goal replans allowed per local day (0 = off): the explicit setting, else the mode's cap */
60
85
  replansPerDay: number;
61
86
  /** Hours a goal replan may stay live */
62
87
  replanTtlHours: number;
88
+ /** Speed mode (normal when never set) */
89
+ speedMode: AutopilotSpeedMode;
90
+ /** Where the budget comes from: the project's own setting, or the mode's default */
91
+ budgetSource: 'explicit' | 'mode';
92
+ /** Where the daily replan cap comes from: the project's own setting, or the mode */
93
+ replansPerDaySource: 'explicit' | 'mode';
94
+ /** A replan never starts sooner than this after the last one (ms) */
95
+ replanMinGapMs: number;
96
+ /** Cadence of the driver's self-review (ms) */
97
+ selfReviewEveryMs: number;
98
+ /** After a replan that opened no tickets: retry after this many hours, or this many days later */
99
+ emptyReplanRetry: {
100
+ unit: 'hours' | 'days';
101
+ amount: number;
102
+ };
63
103
  }
64
104
  /** A change request for the settings (API / skill body). */
65
105
  export interface TicketAutopilotSettingsInput {
@@ -78,6 +118,8 @@ export interface TicketAutopilotSettingsInput {
78
118
  replansPerDay?: unknown;
79
119
  /** An integer 1..limit (hours); `null` resets to the default */
80
120
  replanTtlHours?: unknown;
121
+ /** rush / normal / chill; `null` or "default" resets to normal */
122
+ speedMode?: unknown;
81
123
  }
82
124
  /** Outcome of {@link applyTicketAutopilotInput}. */
83
125
  export type TicketAutopilotInputResult = {
@@ -1 +1 @@
1
- {"version":3,"file":"ticket-autopilot.types.d.ts","sourceRoot":"","sources":["../../../../../backend/src/types/ticket-autopilot.types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,+EAA+E;AAC/E,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,6CAA6C;AAC7C,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,0FAA0F;IAC1F,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,4DAA4D;AAC5D,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0CAA0C;IAC1C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,sFAAsF;IACtF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,oDAAoD;AACpD,MAAM,MAAM,0BAA0B,GAClC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,uBAAuB,CAAA;CAAE,GAC/C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;GAKG;AACH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG7G;AAsBD,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,+BAA+B,CAe3I;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS,GAAG,IAAI,EAC5D,KAAK,EAAE,4BAA4B,GAClC,0BAA0B,CAuE5B"}
1
+ {"version":3,"file":"ticket-autopilot.types.d.ts","sourceRoot":"","sources":["../../../../../backend/src/types/ticket-autopilot.types.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,24 @@
8
8
  */
9
9
  import { TICKET_AUTOPILOT_CONSTANTS, USAGE_CONSTANTS } from '../constants.js';
10
10
  import { parseTokenAmount } from '../services/usage/token-format.js';
11
+ /**
12
+ * Whether a value is a speed mode name.
13
+ *
14
+ * @param value - Anything
15
+ * @returns True for rush / normal / chill
16
+ */
17
+ export function isAutopilotSpeedMode(value) {
18
+ return typeof value === 'string' && TICKET_AUTOPILOT_CONSTANTS.SPEED_MODE_NAMES.includes(value);
19
+ }
20
+ /**
21
+ * The profile of a speed mode.
22
+ *
23
+ * @param mode - Mode
24
+ * @returns Its replan gap / cap, self-review cadence, empty-replan retry and default budget
25
+ */
26
+ export function speedProfile(mode) {
27
+ return TICKET_AUTOPILOT_CONSTANTS.SPEED_MODES[mode];
28
+ }
11
29
  /**
12
30
  * Fill in the defaults of stored (possibly absent) settings.
13
31
  *
@@ -45,16 +63,28 @@ function isReplanTtlHours(n) {
45
63
  export function resolveTicketAutopilotSettings(stored) {
46
64
  const budget = stored?.dailyBudgetTokens ?? legacyBudgetTokens(stored) ?? undefined;
47
65
  const cap = stored?.maxInFlightPerMember;
66
+ const speedMode = isAutopilotSpeedMode(stored?.speedMode)
67
+ ? stored.speedMode
68
+ : TICKET_AUTOPILOT_CONSTANTS.DEFAULT_SPEED_MODE;
69
+ const profile = speedProfile(speedMode);
70
+ const explicitBudget = typeof budget === 'number' && Number.isFinite(budget) && budget > 0;
71
+ const explicitReplans = isReplansPerDay(stored?.replansPerDay);
48
72
  return {
49
73
  enabled: stored?.enabled === true,
50
74
  driver: typeof stored?.driver === 'string' && stored.driver.trim() ? stored.driver.trim() : null,
51
- dailyBudgetTokens: typeof budget === 'number' && Number.isFinite(budget) && budget > 0 ? budget : TICKET_AUTOPILOT_CONSTANTS.DEFAULT_DAILY_BUDGET_TOKENS,
75
+ dailyBudgetTokens: explicitBudget ? budget : profile.dailyBudgetTokens,
52
76
  maxInFlightPerMember: typeof cap === 'number' && Number.isInteger(cap) && cap >= 1 && cap <= TICKET_AUTOPILOT_CONSTANTS.MAX_IN_FLIGHT_PER_MEMBER_LIMIT
53
77
  ? cap
54
78
  : TICKET_AUTOPILOT_CONSTANTS.DEFAULT_MAX_IN_FLIGHT_PER_MEMBER,
55
79
  retro: typeof stored?.retro === 'boolean' ? stored.retro : null,
56
- replansPerDay: isReplansPerDay(stored?.replansPerDay) ? stored.replansPerDay : TICKET_AUTOPILOT_CONSTANTS.DEFAULT_REPLANS_PER_DAY,
80
+ replansPerDay: explicitReplans ? stored?.replansPerDay : profile.replansPerDayCap,
57
81
  replanTtlHours: isReplanTtlHours(stored?.replanTtlHours) ? stored.replanTtlHours : TICKET_AUTOPILOT_CONSTANTS.DEFAULT_REPLAN_TTL_HOURS,
82
+ speedMode,
83
+ budgetSource: explicitBudget ? 'explicit' : 'mode',
84
+ replansPerDaySource: explicitReplans ? 'explicit' : 'mode',
85
+ replanMinGapMs: profile.replanMinGapMs,
86
+ selfReviewEveryMs: profile.selfReviewEveryMs,
87
+ emptyReplanRetry: { ...profile.emptyReplanRetry },
58
88
  };
59
89
  }
60
90
  /**
@@ -88,6 +118,8 @@ export function applyTicketAutopilotInput(current, input) {
88
118
  next.replansPerDay = current.replansPerDay;
89
119
  if (isReplanTtlHours(current?.replanTtlHours))
90
120
  next.replanTtlHours = current.replanTtlHours;
121
+ if (isAutopilotSpeedMode(current?.speedMode))
122
+ next.speedMode = current.speedMode;
91
123
  if (input.enabled !== undefined) {
92
124
  if (typeof input.enabled !== 'boolean')
93
125
  return { ok: false, error: 'enabled must be true or false' };
@@ -161,6 +193,15 @@ export function applyTicketAutopilotInput(current, input) {
161
193
  next.replanTtlHours = n;
162
194
  }
163
195
  }
196
+ if (input.speedMode !== undefined) {
197
+ const raw = typeof input.speedMode === 'string' ? input.speedMode.trim().toLowerCase() : input.speedMode;
198
+ if (raw === null || raw === 'default' || raw === '')
199
+ delete next.speedMode;
200
+ else if (isAutopilotSpeedMode(raw))
201
+ next.speedMode = raw;
202
+ else
203
+ return { ok: false, error: 'speedMode must be rush, normal or chill' };
204
+ }
164
205
  return { ok: true, settings: next };
165
206
  }
166
207
  //# sourceMappingURL=ticket-autopilot.types.js.map