crewly 1.20.349 → 1.20.351

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 (70) hide show
  1. package/config/skills/agent/core/complete-task/SKILL.md +6 -5
  2. package/config/skills/agent/core/complete-task/execute.sh +13 -4
  3. package/config/skills/agent/core/complete-task/execute.test.sh +7 -0
  4. package/config/skills/agent/core/report-status/SKILL.md +3 -3
  5. package/config/skills/agent/core/report-status/execute.sh +9 -5
  6. package/config/skills/agent/core/trace-read/SKILL.md +14 -0
  7. package/config/skills/agent/core/trace-read/execute.sh +25 -2
  8. package/config/skills/orchestrator/complete-task/SKILL.md +1 -1
  9. package/config/skills/orchestrator/complete-task/execute.sh +3 -2
  10. package/config/skills/orchestrator/render-verdict/SKILL.md +2 -1
  11. package/config/skills/orchestrator/render-verdict/execute.sh +8 -4
  12. package/config/skills/team-leader/verify-output/SKILL.md +8 -3
  13. package/config/skills/team-leader/verify-output/execute.sh +4 -3
  14. package/config/skills/team-leader/verify-output/execute.test.sh +2 -0
  15. package/dist/backend/backend/src/constants.d.ts +30 -5
  16. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  17. package/dist/backend/backend/src/constants.js +32 -5
  18. package/dist/backend/backend/src/constants.js.map +1 -1
  19. package/dist/backend/backend/src/controllers/request/request.controller.d.ts +12 -0
  20. package/dist/backend/backend/src/controllers/request/request.controller.d.ts.map +1 -1
  21. package/dist/backend/backend/src/controllers/request/request.controller.js +48 -0
  22. package/dist/backend/backend/src/controllers/request/request.controller.js.map +1 -1
  23. package/dist/backend/backend/src/controllers/request/request.routes.d.ts +1 -0
  24. package/dist/backend/backend/src/controllers/request/request.routes.d.ts.map +1 -1
  25. package/dist/backend/backend/src/controllers/request/request.routes.js +4 -1
  26. package/dist/backend/backend/src/controllers/request/request.routes.js.map +1 -1
  27. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +8 -5
  28. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
  29. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +91 -16
  30. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
  31. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
  32. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +3 -1
  33. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
  34. package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.d.ts +6 -0
  35. package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.d.ts.map +1 -1
  36. package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.js +9 -0
  37. package/dist/backend/backend/src/services/messaging/agent-ask-ledger.service.js.map +1 -1
  38. package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts +74 -5
  39. package/dist/backend/backend/src/services/task-pool/completion-evidence.service.d.ts.map +1 -1
  40. package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js +187 -21
  41. package/dist/backend/backend/src/services/task-pool/completion-evidence.service.js.map +1 -1
  42. package/dist/backend/backend/src/services/v3/request-whereabouts.service.d.ts +88 -0
  43. package/dist/backend/backend/src/services/v3/request-whereabouts.service.d.ts.map +1 -0
  44. package/dist/backend/backend/src/services/v3/request-whereabouts.service.js +193 -0
  45. package/dist/backend/backend/src/services/v3/request-whereabouts.service.js.map +1 -0
  46. package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts +16 -0
  47. package/dist/backend/backend/src/types/v2/completion-evidence.types.d.ts.map +1 -1
  48. package/dist/backend/backend/src/types/v2/completion-evidence.types.js.map +1 -1
  49. package/dist/backend/backend/src/types/v2/work-item.types.d.ts +6 -0
  50. package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  51. package/dist/backend/backend/src/types/v2/work-item.types.js +6 -0
  52. package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
  53. package/dist/backend/build-info.json +2 -2
  54. package/dist/cli/backend/src/constants.d.ts +30 -5
  55. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  56. package/dist/cli/backend/src/constants.js +32 -5
  57. package/dist/cli/backend/src/constants.js.map +1 -1
  58. package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.d.ts +6 -0
  59. package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.d.ts.map +1 -1
  60. package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.js +9 -0
  61. package/dist/cli/backend/src/services/messaging/agent-ask-ledger.service.js.map +1 -1
  62. package/dist/cli/backend/src/types/v2/work-item.types.d.ts +6 -0
  63. package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  64. package/dist/cli/backend/src/types/v2/work-item.types.js +6 -0
  65. package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
  66. package/frontend/dist/assets/{index-36b1788c.js → index-b1fc60ea.js} +65 -65
  67. package/frontend/dist/index.html +1 -1
  68. package/package.json +1 -1
  69. package/packages/crewly-agent/src/runtime/tool-registry.test.ts +26 -0
  70. package/packages/crewly-agent/src/runtime/tool-registry.ts +31 -4
@@ -10,7 +10,7 @@
10
10
  <script>(function(){try{var m=null;try{m=window.localStorage.getItem('crewly-theme')}catch(e){}var d=false;try{d=!!(window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches)}catch(e){}var t=(m==='light'||m==='dark')?m:(d?'dark':'light');document.documentElement.setAttribute('data-theme',t)}catch(e){}})();</script>
11
11
  <!-- Nunito font is self-hosted via @fontsource/nunito (imported in main.tsx) -->
12
12
  <title>Crewly AI Studio</title>
13
- <script type="module" crossorigin src="/assets/index-36b1788c.js"></script>
13
+ <script type="module" crossorigin src="/assets/index-b1fc60ea.js"></script>
14
14
  <link rel="stylesheet" href="/assets/index-b62e5501.css">
15
15
  </head>
16
16
  <body class="bg-background-dark font-display text-text-primary-dark">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crewly",
3
- "version": "1.20.349",
3
+ "version": "1.20.351",
4
4
  "type": "module",
5
5
  "description": "Multi-agent orchestration platform for AI coding teams — coordinates Claude Code, Gemini CLI, and Codex agents with a real-time web dashboard",
6
6
  "workspaces": [
@@ -1309,6 +1309,19 @@ describe('Tool Registry', () => {
1309
1309
  });
1310
1310
  });
1311
1311
 
1312
+ describe('complete_task review fields (#1314)', () => {
1313
+ it('sends verdict, feedback and checks inside result', async () => {
1314
+ mockClient.post.mockResolvedValue({ success: true, data: {}, status: 200 });
1315
+ mockClient.get.mockResolvedValue({ success: true, data: [], status: 200 });
1316
+ const checks = [{ entry: 0, did: 'opened it', outcome: 'pass' }];
1317
+ await (tools.complete_task as any).execute({ workItemId: 'wi-v', sessionName: 'tl', summary: 'ok', verdict: 'verified', checks });
1318
+ expect(mockClient.post).toHaveBeenCalledWith('/task-pool/complete/wi-v', {
1319
+ agentId: 'tl',
1320
+ result: { summary: 'ok', verdict: 'verified', checks },
1321
+ });
1322
+ });
1323
+ });
1324
+
1312
1325
  describe('report_status', () => {
1313
1326
  it('should send status via chat API with formatted message', async () => {
1314
1327
  mockClient.post.mockResolvedValue({
@@ -1376,6 +1389,19 @@ describe('Tool Registry', () => {
1376
1389
  );
1377
1390
  });
1378
1391
 
1392
+ it('returns a refused completion instead of swallowing it (#1312)', async () => {
1393
+ mockClient.post.mockImplementation(async (endpoint: string) => endpoint.startsWith('/task-pool/complete/')
1394
+ ? { success: false, error: 'complete requires evidence', status: 400 }
1395
+ : { success: true, data: { acknowledged: true }, status: 200 });
1396
+ mockClient.get.mockResolvedValueOnce({ success: true, data: { workItems: [{ id: 'wi-running-3' }] }, status: 200 });
1397
+
1398
+ const result = await (tools.report_status as any).execute({ status: 'done', summary: 'Done' });
1399
+
1400
+ expect(result.acknowledged).toBe(true);
1401
+ expect(result.completionError).toContain('wi-running-3 is still OPEN');
1402
+ expect(result.completionError).toContain('complete requires evidence');
1403
+ });
1404
+
1379
1405
  it('should not auto-complete tasks when status is in_progress', async () => {
1380
1406
  mockClient.post.mockResolvedValue({ success: true, data: { acknowledged: true }, status: 200 });
1381
1407
 
@@ -38,6 +38,15 @@ const completionEvidenceSchema = z.array(z.discriminatedUnion('type', [
38
38
  'if you could not finish (the WorkItem is then recorded as blocked, not done).',
39
39
  );
40
40
 
41
+ /** What a reviewer checked when accepting a `Verify: …` item (#1314). */
42
+ const reviewChecksSchema = z.array(z.object({
43
+ entry: z.number().int().nullable().describe("Index in the worker's output.evidence, or null for a direct look at the work"),
44
+ did: z.string().min(1).describe('What you did and saw: opened it, re-ran it (exit code), looked at the page'),
45
+ outcome: z.enum(['pass', 'fail']),
46
+ })).describe(
47
+ 'Required to accept a review: one entry per worker evidence entry you checked; at least one must name an entry when there is any.',
48
+ );
49
+
41
50
  /** One completion evidence entry, as accepted by {@link completionEvidenceSchema}. */
42
51
  type CompletionEvidenceInput = z.infer<typeof completionEvidenceSchema>;
43
52
 
@@ -1286,8 +1295,11 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
1286
1295
  sessionName: z.string().describe('Agent session that completed it'),
1287
1296
  summary: z.string().describe('Completion summary'),
1288
1297
  evidence: completionEvidenceSchema.optional(),
1298
+ verdict: z.enum(['verified', 'rejected']).optional().describe('Reviewing a Verify item: verified accepts (needs checks), rejected sends it back (needs feedback)'),
1299
+ feedback: z.string().optional().describe('With verdict rejected: what is wrong'),
1300
+ checks: reviewChecksSchema.optional(),
1289
1301
  }),
1290
- execute: async ({ workItemId, sessionName: agent, summary, evidence }) => {
1302
+ execute: async ({ workItemId, sessionName: agent, summary, evidence, verdict, feedback, checks }) => {
1291
1303
  // V3-only as of spec 2026-05-06-task-management-v1-deprecation.md.
1292
1304
  // Replaces v1 `/task-management/complete`. Note: the legacy
1293
1305
  // `absoluteTaskPath` parameter is removed; callers must now pass
@@ -1303,7 +1315,12 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
1303
1315
  // - tool-registry.ts §report_status auto-complete path (below)
1304
1316
  const result = await client.post(`/task-pool/complete/${workItemId}`, {
1305
1317
  agentId: agent,
1306
- result: completionResult(summary as string, evidence as CompletionEvidenceInput | undefined),
1318
+ result: {
1319
+ ...completionResult(summary as string, evidence as CompletionEvidenceInput | undefined),
1320
+ ...(verdict ? { verdict } : {}),
1321
+ ...(typeof feedback === 'string' && feedback.trim() ? { feedback } : {}),
1322
+ ...(Array.isArray(checks) && checks.length > 0 ? { checks } : {}),
1323
+ },
1307
1324
  });
1308
1325
 
1309
1326
  // Auto-cancel scheduled checks targeting the completing agent
@@ -1737,6 +1754,7 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
1737
1754
  // V3-only as of spec 2026-05-06-task-management-v1-deprecation.md:
1738
1755
  // resolve the running claim from the pool, then call
1739
1756
  // `/task-pool/complete/:id`. Replaces v1 `/task-management/complete-by-session`.
1757
+ let completionError: string | undefined;
1740
1758
  if (status === 'done') {
1741
1759
  try {
1742
1760
  const poolResp = await client.get(
@@ -1754,12 +1772,18 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
1754
1772
  // `agentId` here is `sessionName` because that's the runtime
1755
1773
  // identity of the completing agent (the session whose
1756
1774
  // status=done message triggered this auto-complete path).
1757
- await client
1775
+ // A refused completion (e.g. 400 evidence_required, #1312) is
1776
+ // returned to the agent: swallowing it left the WorkItem open
1777
+ // while the agent believed it was done.
1778
+ const completion = await client
1758
1779
  .post(`/task-pool/complete/${wiId}`, {
1759
1780
  agentId: sessionName,
1760
1781
  result: completionResult(summary as string, evidence as CompletionEvidenceInput | undefined),
1761
1782
  })
1762
- .catch(() => {});
1783
+ .catch((err: unknown) => ({ success: false, error: String(err) }));
1784
+ if (!completion.success) {
1785
+ completionError = `Status was sent, but WorkItem ${wiId} is still OPEN: ${completion.error ?? 'completion failed'}`;
1786
+ }
1763
1787
  }
1764
1788
  } catch {
1765
1789
  // Non-fatal: status report still succeeded.
@@ -1777,6 +1801,9 @@ export function createTools(client: CrewlyApiClient, sessionName: string, projec
1777
1801
  }).catch(() => {});
1778
1802
  }
1779
1803
 
1804
+ if (completionError) {
1805
+ return { ...(result.success ? (result.data as Record<string, unknown>) : { error: result.error }), completionError };
1806
+ }
1780
1807
  return result.success ? result.data : { error: result.error };
1781
1808
  },
1782
1809
  },