crewly 1.20.108 → 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 (103) 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 +30 -0
  5. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  6. package/dist/backend/backend/src/constants.js +30 -0
  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/v3/request-decompose.subscriber.d.ts +8 -0
  29. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js +40 -0
  31. package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js.map +1 -1
  32. package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -1
  33. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +9 -0
  34. package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -1
  35. package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
  36. package/dist/backend/backend/src/services/v3/request.service.js +28 -0
  37. package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
  38. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.d.ts +17 -0
  39. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.d.ts.map +1 -1
  40. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js +52 -5
  41. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js.map +1 -1
  42. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts +63 -1
  43. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/v3/ticket-intake.service.js +67 -1
  45. package/dist/backend/backend/src/services/v3/ticket-intake.service.js.map +1 -1
  46. package/dist/backend/backend/src/services/v3/ticket-review.service.d.ts +242 -0
  47. package/dist/backend/backend/src/services/v3/ticket-review.service.d.ts.map +1 -0
  48. package/dist/backend/backend/src/services/v3/ticket-review.service.js +456 -0
  49. package/dist/backend/backend/src/services/v3/ticket-review.service.js.map +1 -0
  50. package/dist/backend/backend/src/types/v2/index.d.ts +1 -1
  51. package/dist/backend/backend/src/types/v2/index.d.ts.map +1 -1
  52. package/dist/backend/backend/src/types/v2/index.js.map +1 -1
  53. package/dist/backend/backend/src/types/v2/request.types.d.ts +21 -1
  54. package/dist/backend/backend/src/types/v2/request.types.d.ts.map +1 -1
  55. package/dist/backend/backend/src/types/v2/request.types.js +3 -2
  56. package/dist/backend/backend/src/types/v2/request.types.js.map +1 -1
  57. package/dist/backend/backend/src/types/v2/ticket.types.d.ts +71 -1
  58. package/dist/backend/backend/src/types/v2/ticket.types.d.ts.map +1 -1
  59. package/dist/backend/backend/src/types/v2/ticket.types.js +40 -0
  60. package/dist/backend/backend/src/types/v2/ticket.types.js.map +1 -1
  61. package/dist/backend/build-info.json +2 -2
  62. package/dist/cli/backend/src/constants.d.ts +30 -0
  63. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  64. package/dist/cli/backend/src/constants.js +30 -0
  65. package/dist/cli/backend/src/constants.js.map +1 -1
  66. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +2 -2
  67. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  68. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +2 -2
  69. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  70. package/dist/cli/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -1
  71. package/dist/cli/backend/src/services/v3/request-sla.subscriber.js +9 -0
  72. package/dist/cli/backend/src/services/v3/request-sla.subscriber.js.map +1 -1
  73. package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -1
  74. package/dist/cli/backend/src/services/v3/request.service.js +28 -0
  75. package/dist/cli/backend/src/services/v3/request.service.js.map +1 -1
  76. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.d.ts +17 -0
  77. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.d.ts.map +1 -1
  78. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js +52 -5
  79. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js.map +1 -1
  80. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts +63 -1
  81. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
  82. package/dist/cli/backend/src/services/v3/ticket-intake.service.js +67 -1
  83. package/dist/cli/backend/src/services/v3/ticket-intake.service.js.map +1 -1
  84. package/dist/cli/backend/src/services/v3/ticket-review.service.d.ts +242 -0
  85. package/dist/cli/backend/src/services/v3/ticket-review.service.d.ts.map +1 -0
  86. package/dist/cli/backend/src/services/v3/ticket-review.service.js +456 -0
  87. package/dist/cli/backend/src/services/v3/ticket-review.service.js.map +1 -0
  88. package/dist/cli/backend/src/types/v2/index.d.ts +1 -1
  89. package/dist/cli/backend/src/types/v2/index.d.ts.map +1 -1
  90. package/dist/cli/backend/src/types/v2/index.js.map +1 -1
  91. package/dist/cli/backend/src/types/v2/request.types.d.ts +21 -1
  92. package/dist/cli/backend/src/types/v2/request.types.d.ts.map +1 -1
  93. package/dist/cli/backend/src/types/v2/request.types.js +3 -2
  94. package/dist/cli/backend/src/types/v2/request.types.js.map +1 -1
  95. package/dist/cli/backend/src/types/v2/ticket.types.d.ts +71 -1
  96. package/dist/cli/backend/src/types/v2/ticket.types.d.ts.map +1 -1
  97. package/dist/cli/backend/src/types/v2/ticket.types.js +40 -0
  98. package/dist/cli/backend/src/types/v2/ticket.types.js.map +1 -1
  99. package/frontend/dist/assets/{index-f7b99e81.js → index-07e338a9.js} +284 -284
  100. package/frontend/dist/assets/index-8327e63e.css +42 -0
  101. package/frontend/dist/index.html +2 -2
  102. package/package.json +1 -1
  103. 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":"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"}
1
+ {"version":3,"file":"tickets.controller.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/tickets/tickets.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;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;AAC3E,OAAO,EACL,sBAAsB,GAIvB,MAAM,4CAA4C,CAAC;AAGpD;;;;;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;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,oCAAoC;AACpC,MAAM,qBAAqB,GAAwE;IACjG,SAAS,EAAE,GAAG;IACd,OAAO,EAAE,GAAG;IACZ,aAAa,EAAE,GAAG;IAClB,YAAY,EAAE,GAAG;IACjB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;CACf,CAAC;AAEF,mCAAmC;AACnC,MAAM,mBAAmB,GAAwE;IAC/F,SAAS,EAAE,kBAAkB;IAC7B,OAAO,EAAE,eAAe;IACxB,aAAa,EAAE,kCAAkC;IACjD,YAAY,EAAE,wBAAwB;IACtC,SAAS,EAAE,sBAAsB;IACjC,SAAS,EAAE,kCAAkC;CAC9C,CAAC;AAEF;;;;;GAKG;AACH,SAAS,WAAW,CAAC,GAAa;IAChC,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,4BAA4B,EAAE,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,GAAmB,EAAE,GAAa,EAAE,IAAY;IACnE,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sBAAsB,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,GAAa,EAAE,MAA0B;IACjE,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IACD,GAAG,CAAC,MAAM,CAAC,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACpD,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;QACzC,IAAI,EAAE,MAAM,CAAC,MAAM;KACpB,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,SAAS,CAAC,GAAa,EAAE,EAA6D;IACnG,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,IAAI,CAAC;QACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,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,YAAY,CAAC,GAAmB,EAAE,GAAa;IACnE,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,iBAAiB,CAAC;QAAE,OAAO;IACrD,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAmB,EAAE,GAAa;IACnE,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,oBAAoB,CAAC;QAAE,OAAO;IACxD,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sBAAsB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACzF,OAAO;IACT,CAAC;IACD,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAClF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAmB,EAAE,GAAa;IAC1E,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,0BAA0B,CAAC;QAAE,OAAO;IAC9D,MAAM,GAAG,GAAY,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAC7F,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAA2D,EAAE,CAAC;IACzE,KAAK,MAAM,KAAK,IAAI,GAAgB,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,KAA4B,EAAE,IAAI,CAAC;QACrF,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAE,KAA6B,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QACpG,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;YAC7F,OAAO;QACT,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAmB,EAAE,GAAa;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;IAChC,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,CAAC,EAAE,CAAC;QACtF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sDAAsD,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACzH,OAAO;IACT,CAAC;IACD,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAmB,EAAE,GAAa;IAClE,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC;QAAE,OAAO;IACnD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;IACzD,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;QAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC7D,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ;QAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAmC,CAAC;IACjG,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,IAA2B,CAAC;IACjF,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;QAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAyB,CAAC;IACjH,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACtF,OAAO;IACT,CAAC;IACD,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;AACvE,CAAC"}
@@ -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