crewly 1.20.188 → 1.20.190

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 (140) hide show
  1. package/config/skills/agent/core/attach-file/execute.sh +13 -4
  2. package/config/skills/agent/core/complete-task/execute.sh +3 -0
  3. package/config/skills/agent/core/reply/SKILL.md +32 -4
  4. package/config/skills/agent/core/reply/execute.sh +23 -1
  5. package/config/skills/agent/core/reply/execute.test.sh +9 -0
  6. package/config/skills/agent/core/reply-chat/SKILL.md +9 -2
  7. package/config/skills/agent/core/reply-chat/execute.sh +13 -1
  8. package/config/skills/agent/core/report-status/execute.sh +5 -0
  9. package/config/skills/agent/core/send-chat-response/execute.sh +1 -1
  10. package/dist/backend/backend/src/constants.d.ts +23 -0
  11. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  12. package/dist/backend/backend/src/constants.js +27 -1
  13. package/dist/backend/backend/src/constants.js.map +1 -1
  14. package/dist/backend/backend/src/controllers/chat/agent-reply.controller.d.ts +14 -1
  15. package/dist/backend/backend/src/controllers/chat/agent-reply.controller.d.ts.map +1 -1
  16. package/dist/backend/backend/src/controllers/chat/agent-reply.controller.js +66 -78
  17. package/dist/backend/backend/src/controllers/chat/agent-reply.controller.js.map +1 -1
  18. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts +12 -0
  19. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
  20. package/dist/backend/backend/src/controllers/chat/chat.controller.js +148 -24
  21. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
  22. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -1
  23. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +62 -0
  24. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -1
  25. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
  26. package/dist/backend/backend/src/controllers/slack/slack.controller.js +120 -35
  27. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
  28. package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.d.ts +56 -0
  29. package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.d.ts.map +1 -0
  30. package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.js +114 -0
  31. package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.js.map +1 -0
  32. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +7 -0
  33. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  34. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +9 -0
  35. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  36. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +7 -0
  37. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  38. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +19 -0
  39. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  40. package/dist/backend/backend/src/services/decisions/decision.service.d.ts +4 -1
  41. package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  42. package/dist/backend/backend/src/services/decisions/decision.service.js +10 -3
  43. package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
  44. package/dist/backend/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
  45. package/dist/backend/backend/src/services/memory/project-memory.service.js +21 -10
  46. package/dist/backend/backend/src/services/memory/project-memory.service.js.map +1 -1
  47. package/dist/backend/backend/src/services/open-items/open-items.service.d.ts +29 -0
  48. package/dist/backend/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
  49. package/dist/backend/backend/src/services/open-items/open-items.service.js +92 -8
  50. package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
  51. package/dist/backend/backend/src/services/open-items/open-items.wiring.js +2 -2
  52. package/dist/backend/backend/src/services/open-items/open-items.wiring.js.map +1 -1
  53. package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.d.ts +81 -0
  54. package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.d.ts.map +1 -0
  55. package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.js +88 -0
  56. package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.js.map +1 -0
  57. package/dist/backend/backend/src/services/orc/orc-reply-route.service.d.ts +8 -0
  58. package/dist/backend/backend/src/services/orc/orc-reply-route.service.d.ts.map +1 -1
  59. package/dist/backend/backend/src/services/orc/orc-reply-route.service.js +11 -0
  60. package/dist/backend/backend/src/services/orc/orc-reply-route.service.js.map +1 -1
  61. package/dist/backend/backend/src/services/orc/reply-destination-resolver.d.ts +218 -0
  62. package/dist/backend/backend/src/services/orc/reply-destination-resolver.d.ts.map +1 -0
  63. package/dist/backend/backend/src/services/orc/reply-destination-resolver.js +343 -0
  64. package/dist/backend/backend/src/services/orc/reply-destination-resolver.js.map +1 -0
  65. package/dist/backend/backend/src/services/orc/reply-destination.wiring.d.ts +98 -0
  66. package/dist/backend/backend/src/services/orc/reply-destination.wiring.d.ts.map +1 -0
  67. package/dist/backend/backend/src/services/orc/reply-destination.wiring.js +362 -0
  68. package/dist/backend/backend/src/services/orc/reply-destination.wiring.js.map +1 -0
  69. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts +9 -1
  70. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  71. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +32 -7
  72. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  73. package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts +2 -2
  74. package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts.map +1 -1
  75. package/dist/backend/backend/src/services/slack/slack-agent-post.service.js +9 -0
  76. package/dist/backend/backend/src/services/slack/slack-agent-post.service.js.map +1 -1
  77. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  78. package/dist/backend/backend/src/services/slack/slack-initializer.js +4 -1
  79. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  80. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +1 -1
  81. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  82. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +24 -4
  83. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  84. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts +89 -7
  85. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
  86. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js +159 -21
  87. package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
  88. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts +23 -4
  89. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
  90. package/dist/backend/backend/src/services/v3/ticket-intake.service.js +42 -4
  91. package/dist/backend/backend/src/services/v3/ticket-intake.service.js.map +1 -1
  92. package/dist/backend/build-info.json +2 -2
  93. package/dist/cli/backend/src/constants.d.ts +23 -0
  94. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  95. package/dist/cli/backend/src/constants.js +27 -1
  96. package/dist/cli/backend/src/constants.js.map +1 -1
  97. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +7 -0
  98. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  99. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +9 -0
  100. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  101. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +7 -0
  102. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
  103. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +19 -0
  104. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
  105. package/dist/cli/backend/src/services/decisions/decision.service.d.ts +4 -1
  106. package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  107. package/dist/cli/backend/src/services/decisions/decision.service.js +10 -3
  108. package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
  109. package/dist/cli/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
  110. package/dist/cli/backend/src/services/memory/project-memory.service.js +21 -10
  111. package/dist/cli/backend/src/services/memory/project-memory.service.js.map +1 -1
  112. package/dist/cli/backend/src/services/open-items/open-items.service.d.ts +457 -0
  113. package/dist/cli/backend/src/services/open-items/open-items.service.d.ts.map +1 -0
  114. package/dist/cli/backend/src/services/open-items/open-items.service.js +1158 -0
  115. package/dist/cli/backend/src/services/open-items/open-items.service.js.map +1 -0
  116. package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.d.ts +81 -0
  117. package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.d.ts.map +1 -0
  118. package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.js +88 -0
  119. package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.js.map +1 -0
  120. package/dist/cli/backend/src/services/orc/orc-reply-route.service.d.ts +8 -0
  121. package/dist/cli/backend/src/services/orc/orc-reply-route.service.d.ts.map +1 -1
  122. package/dist/cli/backend/src/services/orc/orc-reply-route.service.js +11 -0
  123. package/dist/cli/backend/src/services/orc/orc-reply-route.service.js.map +1 -1
  124. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts +9 -1
  125. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  126. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +32 -7
  127. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  128. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +1 -1
  129. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  130. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +24 -4
  131. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  132. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts +89 -7
  133. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
  134. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js +159 -21
  135. package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
  136. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts +23 -4
  137. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
  138. package/dist/cli/backend/src/services/v3/ticket-intake.service.js +42 -4
  139. package/dist/cli/backend/src/services/v3/ticket-intake.service.js.map +1 -1
  140. package/package.json +1 -1
@@ -232,6 +232,14 @@ export declare class OrcReplyRouteService {
232
232
  * @param sessionName - Agent session
233
233
  * @returns Its state, created on first use
234
234
  */
235
+ /**
236
+ * The head of the last message delivered to a session (owner, system or
237
+ * harness prompt) — specs/2026-10-02-harness-owned-routing.md §1 step 5.
238
+ *
239
+ * @param sessionName - Agent session
240
+ * @returns Its first characters, or undefined when nothing was delivered
241
+ */
242
+ getLastDelivered(sessionName: string): string | undefined;
235
243
  private stateFor;
236
244
  }
237
245
  //# sourceMappingURL=orc-reply-route.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orc-reply-route.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orc-reply-route.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"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"}
@@ -114,6 +114,7 @@ export class OrcReplyRouteService {
114
114
  * @returns The new origin, or null when the message was system-originated
115
115
  */
116
116
  noteDelivery(sessionName, message, now = Date.now()) {
117
+ this.stateFor(sessionName).lastDelivered = String(message ?? '').slice(0, ORC_REPLY_ROUTE_CONSTANTS.LAST_DELIVERED_HEAD_CHARS);
117
118
  const parsed = parseInboundOrigin(message);
118
119
  if (!parsed)
119
120
  return null;
@@ -303,6 +304,16 @@ export class OrcReplyRouteService {
303
304
  * @param sessionName - Agent session
304
305
  * @returns Its state, created on first use
305
306
  */
307
+ /**
308
+ * The head of the last message delivered to a session (owner, system or
309
+ * harness prompt) — specs/2026-10-02-harness-owned-routing.md §1 step 5.
310
+ *
311
+ * @param sessionName - Agent session
312
+ * @returns Its first characters, or undefined when nothing was delivered
313
+ */
314
+ getLastDelivered(sessionName) {
315
+ return this.sessions.get(sessionName)?.lastDelivered;
316
+ }
306
317
  stateFor(sessionName) {
307
318
  let state = this.sessions.get(sessionName);
308
319
  if (!state) {
@@ -1 +1 @@
1
- {"version":3,"file":"orc-reply-route.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orc-reply-route.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Where an agent's message to the owner goes — decided by the harness from
3
+ * references, never from places the agent guessed
4
+ * (specs/2026-10-02-harness-owned-routing.md §1).
5
+ *
6
+ * Incident (TKT-187, 2026-10-02): Owen ran `reply-chat --thread <#pro-ce key>`
7
+ * with no conversation; the endpoint stored it against the globally newest
8
+ * conversation (an unrelated huddle), filed it as status for the
9
+ * orchestrator and answered `success: true`. The follow-up work item knew the
10
+ * right thread the whole time.
11
+ *
12
+ * Order:
13
+ * 1. the referenced message's conversation / thread;
14
+ * 2. the referenced ticket's thread (request ticket chat thread, project
15
+ * ticket thread binding) or decision card's thread;
16
+ * 3. the referenced work item's origin / destination;
17
+ * 4. validated hints (agent-supplied conversation / thread ids);
18
+ * 5. the reference the harness last prompted the agent about, when newer
19
+ * than its last owner turn;
20
+ * 6. the agent's turn origin / current work;
21
+ * 7. the agent's owner DM.
22
+ *
23
+ * Pure decision logic; collaborators are injected
24
+ * (`reply-destination.wiring.ts` wires the real ones).
25
+ *
26
+ * @module services/orc/reply-destination-resolver
27
+ */
28
+ import type { WorkItem } from '../../types/v2/work-item.types.js';
29
+ import type { TurnOrigin } from './orc-reply-route.service.js';
30
+ import { type PromptReference, type ReplyReference } from './agent-prompt-reference.service.js';
31
+ import { type WorkDestination } from './work-item-destination.js';
32
+ export type { ReplyReference } from './agent-prompt-reference.service.js';
33
+ /** Agent-supplied ids: hints only. */
34
+ export interface ReplyHints {
35
+ /** `--conversation` / `--channel` (chat-v2 id) */
36
+ conversationId?: string;
37
+ /** `--thread`: a Slack thread key `C…:ts` or a chat-v2 message id */
38
+ thread?: string;
39
+ /** `slack-post --target` / upload channel (a Slack channel id), when one was named */
40
+ slackChannelId?: string;
41
+ }
42
+ /** Which step decided. */
43
+ export type ReplyDestinationSource = 'message' | 'ticket' | 'decision' | 'work-item' | 'hint' | 'prompt' | 'turn-origin' | 'current-work' | 'owner-dm';
44
+ /** Where the message goes. */
45
+ export type ReplyDestination =
46
+ /** A chat-v2 conversation the agent belongs to (DM / room / huddle), in `thread` (Slack key or chat-v2 root id) */
47
+ {
48
+ kind: 'conversation';
49
+ conversationId: string;
50
+ thread?: string;
51
+ source: ReplyDestinationSource;
52
+ reason: string;
53
+ }
54
+ /** A Slack place outside any chat conversation (ticket thread, trigger destination, team channel top level) */
55
+ | {
56
+ kind: 'work';
57
+ destination: Exclude<WorkDestination, {
58
+ kind: 'owner-origin';
59
+ }>;
60
+ source: ReplyDestinationSource;
61
+ reason: string;
62
+ }
63
+ /** Nothing the harness can stand behind; `fix` is the command to tell the agent */
64
+ | {
65
+ kind: 'unresolved';
66
+ reason: string;
67
+ fix: string;
68
+ };
69
+ /** A hint that was not used, and why (logged by the caller). */
70
+ export interface IgnoredHint {
71
+ hint: string;
72
+ why: string;
73
+ }
74
+ /** Result of {@link resolveReplyDestination}. */
75
+ export interface ReplyResolution {
76
+ destination: ReplyDestination;
77
+ ignoredHints: IgnoredHint[];
78
+ }
79
+ /** The chat-v2 message fields the resolver reads. */
80
+ export interface ResolverChatMessage {
81
+ id: string;
82
+ channelId: string;
83
+ threadId?: string;
84
+ metadata?: Record<string, unknown>;
85
+ }
86
+ /** A request ticket's conversation. */
87
+ export interface ResolverRequestTicket {
88
+ id: string;
89
+ label: string;
90
+ conversationId?: string;
91
+ threadRootId?: string;
92
+ slackChannelId?: string;
93
+ threadTs?: string;
94
+ }
95
+ /** A decision's card place. */
96
+ export interface ResolverDecision {
97
+ id: string;
98
+ asker: string;
99
+ requestedBy?: string;
100
+ slackChannelId?: string;
101
+ threadTs?: string;
102
+ ticket?: {
103
+ projectPath: string;
104
+ id: string;
105
+ title?: string;
106
+ };
107
+ teamId?: string;
108
+ }
109
+ /** Collaborators. */
110
+ export interface ReplyResolverDeps {
111
+ /** A chat-v2 message by id */
112
+ getMessage(id: string): ResolverChatMessage | null;
113
+ /** Whether the agent may post in a chat-v2 conversation (its DM, a room it is in) */
114
+ ownsConversation(session: string, conversationId: string): Promise<boolean>;
115
+ /** The Slack channel a chat-v2 conversation is mirrored to (team channel / DM link), or null */
116
+ slackChannelOfConversation(conversationId: string): string | null;
117
+ /** The chat-v2 conversation (and thread root) a Slack thread lives in, or null */
118
+ conversationOfSlackThread(slackChannelId: string, threadTs: string): {
119
+ conversationId: string;
120
+ threadRootId?: string;
121
+ } | null;
122
+ /** A request ticket by number */
123
+ requestTicket(ticketNumber: number): Promise<ResolverRequestTicket | null>;
124
+ /** A project ticket the agent can be talking about */
125
+ projectTicket(session: string, ticketId: string): Promise<{
126
+ projectPath: string;
127
+ ticketId: string;
128
+ title?: string;
129
+ teamId?: string;
130
+ } | null>;
131
+ /** A decision by id */
132
+ decision(id: string): Promise<ResolverDecision | null>;
133
+ /** A work item by id */
134
+ workItem(id: string): Promise<WorkItem | null>;
135
+ /** Every pool item (for the agent's current work) */
136
+ poolItems(): Promise<WorkItem[]>;
137
+ /** The agent's last owner turn origin */
138
+ turnOrigin(session: string): TurnOrigin | undefined;
139
+ /** What the harness last prompted the agent about */
140
+ promptReference(session: string): PromptReference | undefined;
141
+ /** Whether the agent owes the owner an answer (owner-message watchdog) */
142
+ owesOwner(session: string): boolean;
143
+ /** Head of the last message delivered to the agent */
144
+ lastDelivered(session: string): string | undefined;
145
+ /** The agent's owner DM conversation (chat-v2), or null */
146
+ ownerDm(session: string): Promise<string | null>;
147
+ /** Clock (epoch ms) */
148
+ now(): number;
149
+ }
150
+ /** Input of {@link resolveReplyDestination}. */
151
+ export interface ReplyResolveInput {
152
+ session: string;
153
+ reference?: ReplyReference;
154
+ hints?: ReplyHints;
155
+ /**
156
+ * Skip the owner-DM fallback (step 7) — for posts that must not land in
157
+ * the DM, e.g. the `[DONE]` notice.
158
+ */
159
+ noOwnerDm?: boolean;
160
+ }
161
+ /**
162
+ * The thread an answer to `msg` belongs in: its Slack thread key when the
163
+ * conversation is mirrored to Slack and the message knows its Slack thread,
164
+ * else its chat-v2 thread root.
165
+ *
166
+ * @param msg - chat-v2 message
167
+ * @param slackChannelId - The conversation's Slack channel, if any
168
+ * @returns Thread reference
169
+ */
170
+ export declare function threadOfMessage(msg: ResolverChatMessage, slackChannelId: string | null): string;
171
+ /**
172
+ * The command the agent should run when its message could not be placed.
173
+ *
174
+ * @param prompt - The agent's last prompt reference, if any
175
+ * @returns An English instruction
176
+ */
177
+ export declare function fixCommand(prompt?: ReplyReference): string;
178
+ /**
179
+ * Resolve one reference (steps 1–3).
180
+ *
181
+ * @param session - Agent
182
+ * @param ref - Reference
183
+ * @param deps - Collaborators
184
+ * @returns A destination; `unresolved` when the reference is wrong; null when it names nothing usable (continue)
185
+ */
186
+ export declare function resolveReference(session: string, ref: ReplyReference, deps: ReplyResolverDeps): Promise<ReplyDestination | null>;
187
+ /**
188
+ * Validate agent-supplied ids (step 4).
189
+ *
190
+ * @param session - Agent
191
+ * @param hints - Its ids
192
+ * @param origin - Its turn origin (an origin in the same conversation supplies the thread)
193
+ * @param deps - Collaborators
194
+ * @returns The conversation they validly name (or null) and every hint ignored
195
+ */
196
+ export declare function validateHints(session: string, hints: ReplyHints, origin: TurnOrigin | undefined, deps: ReplyResolverDeps): Promise<{
197
+ destination: ReplyDestination | null;
198
+ ignored: IgnoredHint[];
199
+ }>;
200
+ /**
201
+ * Whether a prompt reference may steer a bare reply: the agent owes the
202
+ * owner nothing, and the last message delivered to it is that prompt.
203
+ *
204
+ * @param session - Agent
205
+ * @param prompt - Its prompt reference
206
+ * @param deps - Collaborators
207
+ * @returns True to use it
208
+ */
209
+ export declare function promptIsCurrent(session: string, prompt: PromptReference, deps: Pick<ReplyResolverDeps, 'owesOwner' | 'lastDelivered'>): boolean;
210
+ /**
211
+ * Decide where an agent's message goes. See module docs for the order.
212
+ *
213
+ * @param input - Agent, references, hints
214
+ * @param deps - Collaborators
215
+ * @returns The destination and the hints that were ignored
216
+ */
217
+ export declare function resolveReplyDestination(input: ReplyResolveInput, deps: ReplyResolverDeps): Promise<ReplyResolution>;
218
+ //# sourceMappingURL=reply-destination-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply-destination-resolver.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/reply-destination-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,343 @@
1
+ /**
2
+ * Where an agent's message to the owner goes — decided by the harness from
3
+ * references, never from places the agent guessed
4
+ * (specs/2026-10-02-harness-owned-routing.md §1).
5
+ *
6
+ * Incident (TKT-187, 2026-10-02): Owen ran `reply-chat --thread <#pro-ce key>`
7
+ * with no conversation; the endpoint stored it against the globally newest
8
+ * conversation (an unrelated huddle), filed it as status for the
9
+ * orchestrator and answered `success: true`. The follow-up work item knew the
10
+ * right thread the whole time.
11
+ *
12
+ * Order:
13
+ * 1. the referenced message's conversation / thread;
14
+ * 2. the referenced ticket's thread (request ticket chat thread, project
15
+ * ticket thread binding) or decision card's thread;
16
+ * 3. the referenced work item's origin / destination;
17
+ * 4. validated hints (agent-supplied conversation / thread ids);
18
+ * 5. the reference the harness last prompted the agent about, when newer
19
+ * than its last owner turn;
20
+ * 6. the agent's turn origin / current work;
21
+ * 7. the agent's owner DM.
22
+ *
23
+ * Pure decision logic; collaborators are injected
24
+ * (`reply-destination.wiring.ts` wires the real ones).
25
+ *
26
+ * @module services/orc/reply-destination-resolver
27
+ */
28
+ import { REPLY_ROUTING_CONSTANTS, SLACK_THREAD_KEY_CONSTANTS } from '../../constants.js';
29
+ import { parseTicketNumber } from '../../types/v2/ticket.types.js';
30
+ import { formatSlackThreadKey, parseSlackThreadKey } from '../slack/slack-thread-key.js';
31
+ import { hasReference } from './agent-prompt-reference.service.js';
32
+ import { currentWorkItemOf, originOfWorkItem, planWorkDestination } from './work-item-destination.js';
33
+ /**
34
+ * The thread an answer to `msg` belongs in: its Slack thread key when the
35
+ * conversation is mirrored to Slack and the message knows its Slack thread,
36
+ * else its chat-v2 thread root.
37
+ *
38
+ * @param msg - chat-v2 message
39
+ * @param slackChannelId - The conversation's Slack channel, if any
40
+ * @returns Thread reference
41
+ */
42
+ export function threadOfMessage(msg, slackChannelId) {
43
+ const meta = msg.metadata ?? {};
44
+ const named = parseSlackThreadKey(meta[SLACK_THREAD_KEY_CONSTANTS.METADATA_KEY]);
45
+ if (named)
46
+ return formatSlackThreadKey(named.slackChannelId, named.threadTs);
47
+ const ts = typeof meta.slackThreadTs === 'string' && meta.slackThreadTs ? meta.slackThreadTs : undefined;
48
+ if (ts && slackChannelId)
49
+ return formatSlackThreadKey(slackChannelId, ts);
50
+ return msg.threadId ?? msg.id;
51
+ }
52
+ /**
53
+ * The command the agent should run when its message could not be placed.
54
+ *
55
+ * @param prompt - The agent's last prompt reference, if any
56
+ * @returns An English instruction
57
+ */
58
+ export function fixCommand(prompt) {
59
+ if (prompt?.ticket)
60
+ return `reply --ticket ${prompt.ticket} "<your message>"`;
61
+ if (prompt?.decisionId)
62
+ return `reply --decision ${prompt.decisionId} "<your message>"`;
63
+ if (prompt?.workItemId)
64
+ return `reply --work-item ${prompt.workItemId} "<your message>"`;
65
+ if (prompt?.messageId)
66
+ return `reply --to ${prompt.messageId} "<your message>"`;
67
+ return 'reply "<your message>"';
68
+ }
69
+ /**
70
+ * Resolve one reference (steps 1–3).
71
+ *
72
+ * @param session - Agent
73
+ * @param ref - Reference
74
+ * @param deps - Collaborators
75
+ * @returns A destination; `unresolved` when the reference is wrong; null when it names nothing usable (continue)
76
+ */
77
+ export async function resolveReference(session, ref, deps) {
78
+ if (ref.messageId) {
79
+ const msg = deps.getMessage(ref.messageId);
80
+ if (!msg)
81
+ return { kind: 'unresolved', reason: `there is no message ${ref.messageId}`, fix: fixCommand() };
82
+ if (!(await deps.ownsConversation(session, msg.channelId))) {
83
+ return { kind: 'unresolved', reason: `you are not in the conversation of message ${ref.messageId}`, fix: fixCommand() };
84
+ }
85
+ return {
86
+ kind: 'conversation',
87
+ conversationId: msg.channelId,
88
+ thread: threadOfMessage(msg, deps.slackChannelOfConversation(msg.channelId)),
89
+ source: 'message',
90
+ reason: `answering message ${ref.messageId}`,
91
+ };
92
+ }
93
+ if (ref.ticket) {
94
+ const label = ref.ticket.trim();
95
+ const n = REPLY_ROUTING_CONSTANTS.REQUEST_TICKET_PATTERN.test(label) ? parseTicketNumber(label) : null;
96
+ if (n !== null) {
97
+ const t = await deps.requestTicket(n);
98
+ if (!t)
99
+ return { kind: 'unresolved', reason: `there is no ticket ${label}`, fix: fixCommand() };
100
+ const key = t.slackChannelId && t.threadTs ? formatSlackThreadKey(t.slackChannelId, t.threadTs) : undefined;
101
+ if (t.conversationId) {
102
+ return {
103
+ kind: 'conversation',
104
+ conversationId: t.conversationId,
105
+ ...(key || t.threadRootId ? { thread: key ?? t.threadRootId } : {}),
106
+ source: 'ticket',
107
+ reason: `ticket ${t.label}'s thread`,
108
+ };
109
+ }
110
+ if (t.slackChannelId && t.threadTs) {
111
+ const mapped = deps.conversationOfSlackThread(t.slackChannelId, t.threadTs);
112
+ if (mapped)
113
+ return { kind: 'conversation', conversationId: mapped.conversationId, thread: key, source: 'ticket', reason: `ticket ${t.label}'s thread` };
114
+ return {
115
+ kind: 'work',
116
+ destination: { kind: 'slack', target: t.slackChannelId, threadTs: t.threadTs, reason: `ticket ${t.label}'s Slack thread` },
117
+ source: 'ticket',
118
+ reason: `ticket ${t.label}'s Slack thread`,
119
+ };
120
+ }
121
+ return { kind: 'unresolved', reason: `ticket ${t.label} has no conversation to answer in`, fix: 'reply --to <message id from your prompt> "<your message>"' };
122
+ }
123
+ if (REPLY_ROUTING_CONSTANTS.PROJECT_TICKET_PATTERN.test(label)) {
124
+ const pt = await deps.projectTicket(session, label);
125
+ if (!pt)
126
+ return { kind: 'unresolved', reason: `there is no project ticket ${label} you are working on`, fix: fixCommand() };
127
+ return {
128
+ kind: 'work',
129
+ destination: {
130
+ kind: 'ticket-thread',
131
+ projectPath: pt.projectPath,
132
+ ticketId: pt.ticketId,
133
+ ...(pt.title ? { title: pt.title } : {}),
134
+ ...(pt.teamId ? { teamId: pt.teamId } : {}),
135
+ reason: `ticket ${pt.ticketId}'s thread`,
136
+ },
137
+ source: 'ticket',
138
+ reason: `ticket ${pt.ticketId}'s thread`,
139
+ };
140
+ }
141
+ return { kind: 'unresolved', reason: `"${label}" is not a ticket id (TKT-187 or CE-7)`, fix: fixCommand() };
142
+ }
143
+ if (ref.decisionId) {
144
+ const d = await deps.decision(ref.decisionId.trim().toUpperCase());
145
+ if (!d)
146
+ return { kind: 'unresolved', reason: `there is no decision ${ref.decisionId}`, fix: fixCommand() };
147
+ if (d.asker !== session && d.requestedBy !== session) {
148
+ return { kind: 'unresolved', reason: `decision ${d.id} was not asked by you`, fix: fixCommand() };
149
+ }
150
+ if (d.slackChannelId && d.threadTs) {
151
+ const mapped = deps.conversationOfSlackThread(d.slackChannelId, d.threadTs);
152
+ if (mapped && (await deps.ownsConversation(session, mapped.conversationId))) {
153
+ return { kind: 'conversation', conversationId: mapped.conversationId, thread: formatSlackThreadKey(d.slackChannelId, d.threadTs), source: 'decision', reason: `decision ${d.id}'s thread` };
154
+ }
155
+ return {
156
+ kind: 'work',
157
+ destination: { kind: 'slack', target: d.slackChannelId, threadTs: d.threadTs, reason: `decision ${d.id}'s card thread` },
158
+ source: 'decision',
159
+ reason: `decision ${d.id}'s card thread`,
160
+ };
161
+ }
162
+ if (d.ticket) {
163
+ return {
164
+ kind: 'work',
165
+ destination: { kind: 'ticket-thread', projectPath: d.ticket.projectPath, ticketId: d.ticket.id, ...(d.ticket.title ? { title: d.ticket.title } : {}), ...(d.teamId ? { teamId: d.teamId } : {}), reason: `decision ${d.id}'s ticket thread` },
166
+ source: 'decision',
167
+ reason: `decision ${d.id}'s ticket thread`,
168
+ };
169
+ }
170
+ return null;
171
+ }
172
+ if (ref.workItemId) {
173
+ const wi = await deps.workItem(ref.workItemId);
174
+ if (!wi)
175
+ return { kind: 'unresolved', reason: `there is no work item ${ref.workItemId}`, fix: fixCommand() };
176
+ return fromWorkItem(wi, 'work-item', deps);
177
+ }
178
+ return null;
179
+ }
180
+ /**
181
+ * Where a work item's answer goes (its origin / destination). A work item
182
+ * with no recorded origin gives null (continue with the next step).
183
+ *
184
+ * @param wi - Work item
185
+ * @param source - Step label
186
+ * @param deps - Collaborators (clock)
187
+ * @returns Destination or null
188
+ */
189
+ function fromWorkItem(wi, source, deps) {
190
+ if (!originOfWorkItem(wi))
191
+ return null;
192
+ const planned = planWorkDestination({ workItem: wi, now: deps.now() });
193
+ if (planned.kind === 'owner-origin') {
194
+ const o = planned.origin;
195
+ const thread = o.slackThreadKey ?? o.chatThreadId;
196
+ return { kind: 'conversation', conversationId: o.conversationId, ...(thread ? { thread } : {}), source, reason: planned.reason };
197
+ }
198
+ return { kind: 'work', destination: planned, source, reason: planned.reason };
199
+ }
200
+ /**
201
+ * Validate agent-supplied ids (step 4).
202
+ *
203
+ * @param session - Agent
204
+ * @param hints - Its ids
205
+ * @param origin - Its turn origin (an origin in the same conversation supplies the thread)
206
+ * @param deps - Collaborators
207
+ * @returns The conversation they validly name (or null) and every hint ignored
208
+ */
209
+ export async function validateHints(session, hints, origin, deps) {
210
+ const ignored = [];
211
+ const conv = hints.conversationId?.trim() || undefined;
212
+ const rawThread = hints.thread?.trim() || undefined;
213
+ const key = parseSlackThreadKey(rawThread);
214
+ const target = hints.slackChannelId?.trim() || undefined;
215
+ if (key) {
216
+ const keyText = formatSlackThreadKey(key.slackChannelId, key.threadTs);
217
+ if (target && target !== key.slackChannelId) {
218
+ ignored.push({ hint: `target ${target}`, why: `thread ${keyText} is in channel ${key.slackChannelId}, not ${target}` });
219
+ }
220
+ if (conv) {
221
+ const convSlack = deps.slackChannelOfConversation(conv);
222
+ if (convSlack === key.slackChannelId && (await deps.ownsConversation(session, conv))) {
223
+ return { destination: { kind: 'conversation', conversationId: conv, thread: keyText, source: 'hint', reason: 'named its conversation and thread' }, ignored };
224
+ }
225
+ ignored.push({
226
+ hint: `conversation ${conv}`,
227
+ why: convSlack === key.slackChannelId ? 'you are not in that conversation' : `thread ${keyText} is not in that conversation (its Slack channel is ${convSlack ?? 'none'})`,
228
+ });
229
+ }
230
+ const mapped = deps.conversationOfSlackThread(key.slackChannelId, key.threadTs);
231
+ if (mapped && (await deps.ownsConversation(session, mapped.conversationId))) {
232
+ return { destination: { kind: 'conversation', conversationId: mapped.conversationId, thread: keyText, source: 'hint', reason: `Slack thread ${keyText} mapped to its conversation` }, ignored };
233
+ }
234
+ ignored.push({ hint: `thread ${keyText}`, why: mapped ? 'you are not in the conversation of that thread' : 'no known conversation has that Slack thread' });
235
+ return { destination: null, ignored };
236
+ }
237
+ if (rawThread) {
238
+ const msg = deps.getMessage(rawThread);
239
+ if (msg && (!conv || msg.channelId === conv) && (await deps.ownsConversation(session, msg.channelId))) {
240
+ return {
241
+ destination: { kind: 'conversation', conversationId: msg.channelId, thread: threadOfMessage(msg, deps.slackChannelOfConversation(msg.channelId)), source: 'hint', reason: 'named a thread in its conversation' },
242
+ ignored,
243
+ };
244
+ }
245
+ ignored.push({ hint: `thread ${rawThread}`, why: !msg ? 'no such message' : msg.channelId !== conv && conv ? `that message is not in conversation ${conv}` : 'you are not in its conversation' });
246
+ // A thread that is ANOTHER conversation's message contradicts the
247
+ // conversation: neither is used. An unknown id only loses the thread.
248
+ if (conv && msg) {
249
+ ignored.push({ hint: `conversation ${conv}`, why: 'its thread is in another conversation' });
250
+ return { destination: null, ignored };
251
+ }
252
+ if (!conv)
253
+ return { destination: null, ignored };
254
+ }
255
+ if (conv) {
256
+ if (await deps.ownsConversation(session, conv)) {
257
+ const thread = origin?.conversationId === conv ? origin.slackThreadKey ?? origin.chatThreadId : undefined;
258
+ return { destination: { kind: 'conversation', conversationId: conv, ...(thread ? { thread } : {}), source: 'hint', reason: 'named its own conversation' }, ignored };
259
+ }
260
+ ignored.push({ hint: `conversation ${conv}`, why: 'not a conversation you are in' });
261
+ }
262
+ return { destination: null, ignored };
263
+ }
264
+ /**
265
+ * Whether a prompt reference may steer a bare reply: the agent owes the
266
+ * owner nothing, and the last message delivered to it is that prompt.
267
+ *
268
+ * @param session - Agent
269
+ * @param prompt - Its prompt reference
270
+ * @param deps - Collaborators
271
+ * @returns True to use it
272
+ */
273
+ export function promptIsCurrent(session, prompt, deps) {
274
+ if (!prompt.marker)
275
+ return false;
276
+ if (deps.owesOwner(session))
277
+ return false;
278
+ return (deps.lastDelivered(session) ?? '').includes(prompt.marker);
279
+ }
280
+ /**
281
+ * Decide where an agent's message goes. See module docs for the order.
282
+ *
283
+ * @param input - Agent, references, hints
284
+ * @param deps - Collaborators
285
+ * @returns The destination and the hints that were ignored
286
+ */
287
+ export async function resolveReplyDestination(input, deps) {
288
+ const { session } = input;
289
+ const ignoredHints = [];
290
+ const prompt = deps.promptReference(session);
291
+ // 1–3. Explicit references are authoritative: a wrong one is an error.
292
+ if (hasReference(input.reference)) {
293
+ const d = await resolveReference(session, input.reference, deps);
294
+ if (d)
295
+ return { destination: d, ignoredHints };
296
+ }
297
+ const origin = deps.turnOrigin(session);
298
+ // 4. Hints the harness can stand behind.
299
+ if (input.hints && (input.hints.conversationId || input.hints.thread)) {
300
+ const v = await validateHints(session, input.hints, origin, deps);
301
+ ignoredHints.push(...v.ignored);
302
+ if (v.destination)
303
+ return { destination: v.destination, ignoredHints };
304
+ }
305
+ // 5. What the harness last prompted the agent about — only when the agent
306
+ // owes the owner nothing and that prompt is the last thing it was given:
307
+ // a bare answer to a 10:00 owner question must not land in the thread of
308
+ // a 10:02 TKT-150 nudge (and close its promise).
309
+ if (prompt && promptIsCurrent(session, prompt, deps)) {
310
+ const d = await resolveReference(session, prompt.reference, deps);
311
+ if (d && d.kind !== 'unresolved')
312
+ return { destination: { ...d, source: 'prompt', reason: `the harness prompted you about it (${d.reason})` }, ignoredHints };
313
+ }
314
+ // 6. Turn origin / current work.
315
+ const items = await deps.poolItems().catch(() => []);
316
+ const workItem = currentWorkItemOf(items, session);
317
+ const planned = planWorkDestination({ workItem, ownerOrigin: origin, now: deps.now() });
318
+ if (planned.kind === 'owner-origin') {
319
+ const o = planned.origin;
320
+ const thread = o.slackThreadKey ?? o.chatThreadId;
321
+ const fromOwner = o === origin;
322
+ return {
323
+ destination: { kind: 'conversation', conversationId: o.conversationId, ...(thread ? { thread } : {}), source: fromOwner ? 'turn-origin' : 'current-work', reason: planned.reason },
324
+ ignoredHints,
325
+ };
326
+ }
327
+ const isScheduled = !!workItem && originOfWorkItem(workItem)?.kind === 'trigger';
328
+ if (planned.kind !== 'new-top-level' || isScheduled) {
329
+ return { destination: { kind: 'work', destination: planned, source: 'current-work', reason: planned.reason }, ignoredHints };
330
+ }
331
+ // 7. The owner DM; a team-channel top-level post only when there is none.
332
+ if (!input.noOwnerDm) {
333
+ const dm = await deps.ownerDm(session).catch(() => null);
334
+ if (dm)
335
+ return { destination: { kind: 'conversation', conversationId: dm, source: 'owner-dm', reason: `${planned.reason} — your DM with the owner` }, ignoredHints };
336
+ return { destination: { kind: 'work', destination: planned, source: 'current-work', reason: `${planned.reason} (no owner DM)` }, ignoredHints };
337
+ }
338
+ return {
339
+ destination: { kind: 'unresolved', reason: planned.reason, fix: fixCommand(prompt?.reference) },
340
+ ignoredHints,
341
+ };
342
+ }
343
+ //# sourceMappingURL=reply-destination-resolver.js.map