crewly 1.20.107 → 1.20.109

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 (111) hide show
  1. package/config/skills/agent/core/ticket-check/SKILL.md +62 -0
  2. package/config/skills/agent/core/ticket-check/execute.sh +71 -0
  3. package/config/skills/agent/core/ticket-check/execute.test.sh +69 -0
  4. package/dist/backend/backend/src/constants.d.ts +32 -2
  5. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  6. package/dist/backend/backend/src/constants.js +32 -2
  7. package/dist/backend/backend/src/constants.js.map +1 -1
  8. package/dist/backend/backend/src/controllers/tickets/tickets.controller.d.ts +42 -0
  9. package/dist/backend/backend/src/controllers/tickets/tickets.controller.d.ts.map +1 -1
  10. package/dist/backend/backend/src/controllers/tickets/tickets.controller.js +185 -0
  11. package/dist/backend/backend/src/controllers/tickets/tickets.controller.js.map +1 -1
  12. package/dist/backend/backend/src/controllers/tickets/tickets.routes.d.ts +7 -0
  13. package/dist/backend/backend/src/controllers/tickets/tickets.routes.d.ts.map +1 -1
  14. package/dist/backend/backend/src/controllers/tickets/tickets.routes.js +16 -1
  15. package/dist/backend/backend/src/controllers/tickets/tickets.routes.js.map +1 -1
  16. package/dist/backend/backend/src/index.d.ts.map +1 -1
  17. package/dist/backend/backend/src/index.js +52 -1
  18. package/dist/backend/backend/src/index.js.map +1 -1
  19. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +1 -1
  20. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
  21. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
  22. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +6 -0
  23. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
  24. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +2 -2
  25. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  26. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +2 -2
  27. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  28. package/dist/backend/backend/src/services/slack/slack.service.d.ts +9 -0
  29. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/slack/slack.service.js +19 -0
  31. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  32. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.d.ts +8 -0
  33. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.d.ts.map +1 -1
  34. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js +40 -0
  35. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js.map +1 -1
  36. package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -1
  37. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +9 -0
  38. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -1
  39. package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
  40. package/dist/backend/backend/src/services/v3/request.service.js +28 -0
  41. package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
  42. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.d.ts +24 -15
  43. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js +70 -38
  45. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js.map +1 -1
  46. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts +70 -1
  47. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
  48. package/dist/backend/backend/src/services/v3/ticket-intake.service.js +67 -1
  49. package/dist/backend/backend/src/services/v3/ticket-intake.service.js.map +1 -1
  50. package/dist/backend/backend/src/services/v3/ticket-review.service.d.ts +242 -0
  51. package/dist/backend/backend/src/services/v3/ticket-review.service.d.ts.map +1 -0
  52. package/dist/backend/backend/src/services/v3/ticket-review.service.js +456 -0
  53. package/dist/backend/backend/src/services/v3/ticket-review.service.js.map +1 -0
  54. package/dist/backend/backend/src/types/v2/index.d.ts +1 -1
  55. package/dist/backend/backend/src/types/v2/index.d.ts.map +1 -1
  56. package/dist/backend/backend/src/types/v2/index.js.map +1 -1
  57. package/dist/backend/backend/src/types/v2/request.types.d.ts +21 -1
  58. package/dist/backend/backend/src/types/v2/request.types.d.ts.map +1 -1
  59. package/dist/backend/backend/src/types/v2/request.types.js +3 -2
  60. package/dist/backend/backend/src/types/v2/request.types.js.map +1 -1
  61. package/dist/backend/backend/src/types/v2/ticket.types.d.ts +73 -1
  62. package/dist/backend/backend/src/types/v2/ticket.types.d.ts.map +1 -1
  63. package/dist/backend/backend/src/types/v2/ticket.types.js +40 -0
  64. package/dist/backend/backend/src/types/v2/ticket.types.js.map +1 -1
  65. package/dist/backend/build-info.json +2 -2
  66. package/dist/cli/backend/src/constants.d.ts +32 -2
  67. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  68. package/dist/cli/backend/src/constants.js +32 -2
  69. package/dist/cli/backend/src/constants.js.map +1 -1
  70. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +2 -2
  71. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  72. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +2 -2
  73. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  74. package/dist/cli/backend/src/services/slack/slack.service.d.ts +9 -0
  75. package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
  76. package/dist/cli/backend/src/services/slack/slack.service.js +19 -0
  77. package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
  78. package/dist/cli/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -1
  79. package/dist/cli/backend/src/services/v3/request-sla.subscriber.js +9 -0
  80. package/dist/cli/backend/src/services/v3/request-sla.subscriber.js.map +1 -1
  81. package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -1
  82. package/dist/cli/backend/src/services/v3/request.service.js +28 -0
  83. package/dist/cli/backend/src/services/v3/request.service.js.map +1 -1
  84. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.d.ts +24 -15
  85. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.d.ts.map +1 -1
  86. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js +70 -38
  87. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js.map +1 -1
  88. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts +70 -1
  89. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
  90. package/dist/cli/backend/src/services/v3/ticket-intake.service.js +67 -1
  91. package/dist/cli/backend/src/services/v3/ticket-intake.service.js.map +1 -1
  92. package/dist/cli/backend/src/services/v3/ticket-review.service.d.ts +242 -0
  93. package/dist/cli/backend/src/services/v3/ticket-review.service.d.ts.map +1 -0
  94. package/dist/cli/backend/src/services/v3/ticket-review.service.js +456 -0
  95. package/dist/cli/backend/src/services/v3/ticket-review.service.js.map +1 -0
  96. package/dist/cli/backend/src/types/v2/index.d.ts +1 -1
  97. package/dist/cli/backend/src/types/v2/index.d.ts.map +1 -1
  98. package/dist/cli/backend/src/types/v2/index.js.map +1 -1
  99. package/dist/cli/backend/src/types/v2/request.types.d.ts +21 -1
  100. package/dist/cli/backend/src/types/v2/request.types.d.ts.map +1 -1
  101. package/dist/cli/backend/src/types/v2/request.types.js +3 -2
  102. package/dist/cli/backend/src/types/v2/request.types.js.map +1 -1
  103. package/dist/cli/backend/src/types/v2/ticket.types.d.ts +73 -1
  104. package/dist/cli/backend/src/types/v2/ticket.types.d.ts.map +1 -1
  105. package/dist/cli/backend/src/types/v2/ticket.types.js +40 -0
  106. package/dist/cli/backend/src/types/v2/ticket.types.js.map +1 -1
  107. package/frontend/dist/assets/{index-f7b99e81.js → index-07e338a9.js} +284 -284
  108. package/frontend/dist/assets/index-8327e63e.css +42 -0
  109. package/frontend/dist/index.html +2 -2
  110. package/package.json +1 -1
  111. package/frontend/dist/assets/index-413c5813.css +0 -42
@@ -5,12 +5,18 @@
5
5
  * - GET /api/tickets?column=&q=&kind=&includeLegacy= — board-shaped list
6
6
  * - GET /api/tickets/:tkt — one ticket by `TKT-123`, `123` or id
7
7
  * - POST /api/tickets/:id/dismiss — the "不用记" action
8
+ * - POST /api/tickets/:id/verify — 验过了 (Phase 2)
9
+ * - POST /api/tickets/:id/reject { reason } — 打回 (Phase 2)
10
+ * - PUT /api/tickets/:id/acceptance { items } — replace acceptance list (Phase 2)
11
+ * - POST /api/tickets/:id/self-check { index, result, evidence } — agent self-check (Phase 2)
12
+ * - PATCH /api/tickets/:id { title, priority, kind, assignee } — board edits (Phase 2)
8
13
  *
9
14
  * @module controllers/tickets/tickets.controller
10
15
  */
11
16
  import { getTicketIntakeService, } from '../../services/v3/ticket-intake.service.js';
12
17
  import { isTicketBoardColumn, isTicketKind } from '../../types/v2/ticket.types.js';
13
18
  import { readAgentSessionHeader } from '../../utils/agent-caller.utils.js';
19
+ import { getTicketReviewService, } from '../../services/v3/ticket-review.service.js';
14
20
  /**
15
21
  * The wired intake service, or a 503 when boot has not wired it.
16
22
  *
@@ -132,4 +138,183 @@ export async function dismissTicket(req, res) {
132
138
  res.status(500).json({ success: false, error: error.message });
133
139
  }
134
140
  }
141
+ // ---------------------------------------------------------------------------
142
+ // Phase 2 — review
143
+ // ---------------------------------------------------------------------------
144
+ /** HTTP status for each refusal. */
145
+ const REVIEW_REFUSAL_STATUS = {
146
+ not_found: 404,
147
+ invalid: 400,
148
+ not_in_review: 409,
149
+ already_done: 409,
150
+ cancelled: 409,
151
+ open_work: 409,
152
+ };
153
+ /** Human text for each refusal. */
154
+ const REVIEW_REFUSAL_TEXT = {
155
+ not_found: 'Ticket not found',
156
+ invalid: 'Invalid input',
157
+ not_in_review: 'Ticket is not waiting for review',
158
+ already_done: 'Ticket is already done',
159
+ cancelled: 'Ticket was cancelled',
160
+ open_work: 'Ticket still has open work items',
161
+ };
162
+ /**
163
+ * The wired review service, or a 503.
164
+ *
165
+ * @param res - Response to write the 503 to
166
+ * @returns The service, or null after responding
167
+ */
168
+ function reviewOr503(res) {
169
+ const svc = getTicketReviewService();
170
+ if (!svc) {
171
+ res.status(503).json({ success: false, error: 'Ticket review is not ready' });
172
+ return null;
173
+ }
174
+ return svc;
175
+ }
176
+ /**
177
+ * Refuse a call made by an agent (owner-only actions).
178
+ *
179
+ * @param req - Express request
180
+ * @param res - Response
181
+ * @param what - What is owner-only (for the message)
182
+ * @returns True when refused
183
+ */
184
+ function refuseAgent(req, res, what) {
185
+ if (!readAgentSessionHeader(req))
186
+ return false;
187
+ res.status(403).json({ success: false, error: `Only the owner can ${what}` });
188
+ return true;
189
+ }
190
+ /**
191
+ * Write a review action's result.
192
+ *
193
+ * @param res - Response
194
+ * @param result - The result
195
+ */
196
+ function sendReviewResult(res, result) {
197
+ if (result.ok) {
198
+ res.json({ success: true, data: result.ticket });
199
+ return;
200
+ }
201
+ res.status(REVIEW_REFUSAL_STATUS[result.reason]).json({
202
+ success: false,
203
+ error: REVIEW_REFUSAL_TEXT[result.reason],
204
+ code: result.reason,
205
+ });
206
+ }
207
+ /**
208
+ * Run a review handler with the shared 503 / 500 handling.
209
+ *
210
+ * @param res - Response
211
+ * @param fn - The action
212
+ */
213
+ async function runReview(res, fn) {
214
+ const svc = reviewOr503(res);
215
+ if (!svc)
216
+ return;
217
+ try {
218
+ sendReviewResult(res, await fn(svc));
219
+ }
220
+ catch (error) {
221
+ res.status(500).json({ success: false, error: error.message });
222
+ }
223
+ }
224
+ /**
225
+ * POST /api/tickets/:id/verify — 验过了. Owner only.
226
+ *
227
+ * @param req - Express request with `id` param
228
+ * @param res - `{ success, data: ticket }`, 403, 404 or 409
229
+ */
230
+ export async function verifyTicket(req, res) {
231
+ if (refuseAgent(req, res, 'accept a ticket'))
232
+ return;
233
+ await runReview(res, (svc) => svc.verify(req.params.id ?? ''));
234
+ }
235
+ /**
236
+ * POST /api/tickets/:id/reject — 打回 with a required reason. Owner only.
237
+ * The reason becomes an acceptance criterion and a rework WorkItem is queued.
238
+ *
239
+ * @param req - Express request with `id` param and body `{ reason }`
240
+ * @param res - `{ success, data: ticket }`, 400, 403, 404 or 409
241
+ */
242
+ export async function rejectTicket(req, res) {
243
+ if (refuseAgent(req, res, 'send a ticket back'))
244
+ return;
245
+ const reason = typeof req.body?.reason === 'string' ? req.body.reason.trim() : '';
246
+ if (!reason) {
247
+ res.status(400).json({ success: false, error: 'A reason is required', code: 'invalid' });
248
+ return;
249
+ }
250
+ await runReview(res, (svc) => svc.reject(req.params.id ?? '', reason, 'board'));
251
+ }
252
+ /**
253
+ * PUT /api/tickets/:id/acceptance — replace the live acceptance list. Owner only.
254
+ *
255
+ * @param req - Express request with body `{ items: [{ text, check? }] }`
256
+ * @param res - `{ success, data: ticket }`, 400, 403 or 404
257
+ */
258
+ export async function setTicketAcceptance(req, res) {
259
+ if (refuseAgent(req, res, 'edit acceptance criteria'))
260
+ return;
261
+ const raw = req.body?.items;
262
+ if (!Array.isArray(raw)) {
263
+ res.status(400).json({ success: false, error: '`items` must be an array', code: 'invalid' });
264
+ return;
265
+ }
266
+ const items = [];
267
+ for (const entry of raw) {
268
+ const text = typeof entry === 'string' ? entry : entry?.text;
269
+ const check = typeof entry === 'object' && entry ? entry.check : undefined;
270
+ if (typeof text !== 'string') {
271
+ res.status(400).json({ success: false, error: 'Each item needs a `text`', code: 'invalid' });
272
+ return;
273
+ }
274
+ items.push({ text, ...(check === 'auto' || check === 'judgment' ? { check } : {}) });
275
+ }
276
+ await runReview(res, (svc) => svc.setAcceptance(req.params.id ?? '', items));
277
+ }
278
+ /**
279
+ * POST /api/tickets/:id/self-check — an agent records its check of one
280
+ * criterion. Agents may call this.
281
+ *
282
+ * @param req - Express request with body `{ index, result: 'pass'|'fail', evidence? }`
283
+ * @param res - `{ success, data: ticket }`, 400 or 404
284
+ */
285
+ export async function selfCheckTicket(req, res) {
286
+ const index = Number(req.body?.index);
287
+ const result = req.body?.result;
288
+ const evidence = typeof req.body?.evidence === 'string' ? req.body.evidence : undefined;
289
+ if (!Number.isInteger(index) || index < 0 || (result !== 'pass' && result !== 'fail')) {
290
+ res.status(400).json({ success: false, error: '`index` (>= 0) and `result` (pass|fail) are required', code: 'invalid' });
291
+ return;
292
+ }
293
+ await runReview(res, (svc) => svc.selfCheck(req.params.id ?? '', index, result, evidence));
294
+ }
295
+ /**
296
+ * PATCH /api/tickets/:id — board edits (title, priority, kind, assignee). Owner only.
297
+ *
298
+ * @param req - Express request with a partial body
299
+ * @param res - `{ success, data: ticket }`, 400, 403 or 404
300
+ */
301
+ export async function patchTicket(req, res) {
302
+ if (refuseAgent(req, res, 'edit a ticket'))
303
+ return;
304
+ const body = (req.body ?? {});
305
+ const patch = {};
306
+ if (typeof body.title === 'string')
307
+ patch.title = body.title;
308
+ if (typeof body.priority === 'string')
309
+ patch.priority = body.priority;
310
+ if (typeof body.kind === 'string')
311
+ patch.kind = body.kind;
312
+ if (typeof body.assignee === 'string' || body.assignee === null)
313
+ patch.assignee = body.assignee;
314
+ if (Object.keys(patch).length === 0) {
315
+ res.status(400).json({ success: false, error: 'Nothing to change', code: 'invalid' });
316
+ return;
317
+ }
318
+ await runReview(res, (svc) => svc.patch(req.params.id ?? '', patch));
319
+ }
135
320
  //# sourceMappingURL=tickets.controller.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tickets.controller.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/tickets/tickets.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACL,sBAAsB,GAEvB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAE3E;;;;;GAKG;AACH,SAAS,YAAY,CAAC,GAAa;IACjC,MAAM,GAAG,GAAG,sBAAsB,EAAE,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAmB,EAAE,GAAa;IAClE,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,MAAM,EAAE,EAAE,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC,CAAC;YACzE,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC;YAC1B,GAAG,CAAC,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,aAAa,EAAE,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,MAAM;SAC/D,CAAC,CAAC;QACH,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAmB,EAAE,GAAa;IAChE,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACvF,OAAO;QACT,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAmB,EAAE,GAAa;IACpE,IAAI,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAC,CAAC;QACvF,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;YAC5F,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACtF,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,oDAAoD;YACzH,IAAI,EAAE,MAAM,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"tickets.controller.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/tickets/tickets.controller.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,13 @@ import { Router } from 'express';
11
11
  * - GET / — board-shaped list
12
12
  * - GET /:tkt — one ticket
13
13
  * - POST /:id/dismiss — "不用记"
14
+ * - POST /:id/verify — 验过了
15
+ * - POST /:id/reject — 打回 { reason }
16
+ * - PUT /:id/acceptance — replace acceptance list
17
+ * - POST /:id/self-check — agent self-check of one criterion
18
+ * - PATCH /:id — title / priority / kind / assignee
19
+ * - POST /:id/acceptance, POST /:id/update — the same two, for the relay
20
+ * (portal / phone), which only carries GET and POST
14
21
  *
15
22
  * @returns Express router for /api/tickets
16
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"tickets.routes.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/tickets/tickets.routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C"}
1
+ {"version":3,"file":"tickets.routes.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/tickets/tickets.routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAYjC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAc5C"}
@@ -4,7 +4,7 @@
4
4
  * @module controllers/tickets/tickets.routes
5
5
  */
6
6
  import { Router } from 'express';
7
- import { listTickets, getTicket, dismissTicket } from './tickets.controller.js';
7
+ import { listTickets, getTicket, dismissTicket, verifyTicket, rejectTicket, setTicketAcceptance, selfCheckTicket, patchTicket, } from './tickets.controller.js';
8
8
  /**
9
9
  * Create the tickets router.
10
10
  *
@@ -12,6 +12,13 @@ import { listTickets, getTicket, dismissTicket } from './tickets.controller.js';
12
12
  * - GET / — board-shaped list
13
13
  * - GET /:tkt — one ticket
14
14
  * - POST /:id/dismiss — "不用记"
15
+ * - POST /:id/verify — 验过了
16
+ * - POST /:id/reject — 打回 { reason }
17
+ * - PUT /:id/acceptance — replace acceptance list
18
+ * - POST /:id/self-check — agent self-check of one criterion
19
+ * - PATCH /:id — title / priority / kind / assignee
20
+ * - POST /:id/acceptance, POST /:id/update — the same two, for the relay
21
+ * (portal / phone), which only carries GET and POST
15
22
  *
16
23
  * @returns Express router for /api/tickets
17
24
  */
@@ -20,6 +27,14 @@ export function createTicketsRouter() {
20
27
  router.get('/', listTickets);
21
28
  router.get('/:tkt', getTicket);
22
29
  router.post('/:id/dismiss', dismissTicket);
30
+ router.post('/:id/verify', verifyTicket);
31
+ router.post('/:id/reject', rejectTicket);
32
+ router.put('/:id/acceptance', setTicketAcceptance);
33
+ router.post('/:id/self-check', selfCheckTicket);
34
+ router.patch('/:id', patchTicket);
35
+ // POST twins: the relay (portal / phone) only carries GET and POST.
36
+ router.post('/:id/acceptance', setTicketAcceptance);
37
+ router.post('/:id/update', patchTicket);
23
38
  return router;
24
39
  }
25
40
  //# sourceMappingURL=tickets.routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tickets.routes.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/tickets/tickets.routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAEhF;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC7B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC/B,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IAC3C,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"tickets.routes.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/tickets/tickets.routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EACL,WAAW,EACX,SAAS,EACT,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,WAAW,GACZ,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC7B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC/B,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IAC3C,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACzC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;IACnD,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,oEAAoE;IACpE,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;IACpD,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../backend/src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../backend/src/index.ts"],"names":[],"mappings":"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"}
@@ -58,11 +58,14 @@ import { setRequestServiceEventBus, RequestService } from './services/v3/request
58
58
  import { getSlackService } from './services/slack/slack.service.js';
59
59
  import { sendBootAnnouncement, isFirstBoot, markBooted } from './services/boot/boot-announce.service.js';
60
60
  import { SubAgentMessageQueue } from './services/messaging/sub-agent-message-queue.service.js';
61
- import { SUB_AGENT_QUEUE_CONSTANTS, CHAT_CONTEXT_CONSTANTS, SAFE_RESTART, PROCESS_EXIT_CODES, CLAUDE_STARTUP_CONSTANTS, WEB_CONSTANTS } from './constants.js';
61
+ import { SUB_AGENT_QUEUE_CONSTANTS, CHAT_CONTEXT_CONSTANTS, SAFE_RESTART, PROCESS_EXIT_CODES, CLAUDE_STARTUP_CONSTANTS, WEB_CONSTANTS, TICKET_CONSTANTS } from './constants.js';
62
62
  import { PtyActivityTrackerService } from './services/agent/pty-activity-tracker.service.js';
63
63
  import { InFlightTurnTracker } from './services/restart/in-flight-turn-tracker.service.js';
64
64
  import { TicketIntakeService, setTicketIntakeService, resolveTicketIdForSession, } from './services/v3/ticket-intake.service.js';
65
65
  import { createChatV2ReceiptSink } from './services/v3/ticket-channel-hooks.js';
66
+ import { TicketReviewService, setTicketReviewService, getTicketReviewService } from './services/v3/ticket-review.service.js';
67
+ import { activeAcceptance, formatTicketMarker, formatTicketNumber } from './types/v2/ticket.types.js';
68
+ import { createWorkItem, TERMINAL_WORK_ITEM_STATUSES } from './types/v2/work-item.types.js';
66
69
  import { runPoolArchiveMigration } from './services/task-pool/pool-archive-migration.js';
67
70
  import { createPtyTurnProbe } from './services/restart/turn-probe.js';
68
71
  import { RestartDrainService, resolveRestartDrainMs } from './services/restart/restart-drain.service.js';
@@ -415,6 +418,45 @@ export class CrewlyServer {
415
418
  }));
416
419
  setTicketIntakeService(ticketIntake);
417
420
  TaskPoolService.getInstance().setTicketResolver((sessionName) => resolveTicketIdForSession(InFlightTurnTracker.getInstance(), sessionName));
421
+ // Phase 2: answered → 待验收 → 验过了 / 打回 / silence accepts.
422
+ const ticketReview = new TicketReviewService({
423
+ requests: RequestService.getInstance(),
424
+ fallbackAgent: ORCHESTRATOR_SESSION_NAME,
425
+ openWorkItemCount: async (requestId) => (await TaskPoolService.getInstance().getAllItems()).filter((wi) => wi.requestId === requestId && !TERMINAL_WORK_ITEM_STATUSES.has(wi.status)).length,
426
+ createRework: async ({ ticket, reason, target }) => {
427
+ const tkt = formatTicketNumber(ticket.ticketNumber ?? 0);
428
+ const criteria = activeAcceptance(ticket.acceptance).map((a) => `- ${a.text}`).join('\n');
429
+ const wi = createWorkItem({
430
+ type: 'delegate',
431
+ owner: 'system',
432
+ target,
433
+ requestId: ticket.id,
434
+ title: TICKET_CONSTANTS.REVIEW.REWORK_TITLE(tkt),
435
+ description: `${formatTicketMarker(ticket)} The owner sent ${tkt} back: ${reason}\n\n` +
436
+ `Original ask: ${ticket.description}\n` +
437
+ (ticket.reply ? `Your last answer: ${ticket.reply.excerpt}\n` : '') +
438
+ (criteria ? `\nAcceptance criteria:\n${criteria}\n` : '') +
439
+ `\nFix it and answer in the ticket's conversation.`,
440
+ metadata: { ticketRework: true },
441
+ });
442
+ await TaskPoolService.getInstance().addToPool(wi);
443
+ return wi.id;
444
+ },
445
+ markReceiptDone: (ticket) => ticketIntake.markReceiptDone(ticket),
446
+ });
447
+ setTicketReviewService(ticketReview);
448
+ ticketIntake.setReviewHandler(ticketReview);
449
+ getChatV2Service().on('chat_message', (dto) => {
450
+ void ticketReview.onChatMessage(dto).catch(() => undefined);
451
+ });
452
+ const reviewSweep = setInterval(() => {
453
+ void ticketReview.sweep().catch((sweepErr) => {
454
+ this.logger.warn('Ticket review sweep failed', {
455
+ error: sweepErr instanceof Error ? sweepErr.message : String(sweepErr),
456
+ });
457
+ });
458
+ }, TICKET_CONSTANTS.REVIEW.SWEEP_INTERVAL_MS);
459
+ reviewSweep.unref?.();
418
460
  }
419
461
  catch (ticketBootErr) {
420
462
  this.logger.error('Ticket intake boot failed — messages are still delivered, no tickets filed', {
@@ -913,6 +955,11 @@ export class CrewlyServer {
913
955
  // was mid-answer and never got a reply; the message was still
914
956
  // in the queue an hour later (2026-09-21, Ella).
915
957
  setImmediate(() => void this.flushQueuedAgentMessages(event.sessionName));
958
+ // Ticket loop Phase 2: an agent that finished its turn has answered
959
+ // the tickets it replied in — submit them (待验收 or done).
960
+ void getTicketReviewService()
961
+ ?.onAgentIdle(event.sessionName)
962
+ .catch(() => undefined);
916
963
  // V3: Auto-close open Requests when the orchestrator goes idle
917
964
  // Handles direct responses (no WorkItem delegation)
918
965
  if (event.sessionName === ORCHESTRATOR_SESSION_NAME) {
@@ -3589,6 +3636,10 @@ export class CrewlyServer {
3589
3636
  for (const req of all) {
3590
3637
  if (req.status !== 'open')
3591
3638
  continue;
3639
+ // Tickets matched to their chat turn close when their answer
3640
+ // settles (TicketReviewService), not on a timer.
3641
+ if (req.chatRef)
3642
+ continue;
3592
3643
  const reqAge = Date.now() - new Date(req.createdAt).getTime();
3593
3644
  if (reqAge > 10 * 60 * 1000)
3594
3645
  continue; // older than 10 min — skip