@claude-flow/cli 3.56.1 → 3.56.3
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.
- package/.claude/helpers/helpers.manifest.json +2 -2
- package/catalog-manifest.json +2 -2
- package/dist/src/mcp-tools/hooks-tools.js +6 -2
- package/dist/src/mcp-tools/task-tools.d.ts +5 -0
- package/dist/src/mcp-tools/task-tools.js +51 -7
- package/dist/src/memory/memory-bridge.js +10 -1
- package/dist/src/missions/schemas.d.ts +125 -125
- package/dist/src/mods/command-registry/schema.d.ts +199 -199
- package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
- package/package.json +4 -4
- package/plugins/ruflo-metaharness/.claude-plugin/plugin.json +1 -1
- package/plugins/ruflo-metaharness/CHANGELOG.md +3 -0
- package/plugins/ruflo-metaharness/scripts/smoke.sh +4 -4
- package/plugins/ruflo-metaharness/skills/harness-bench/SKILL.md +1 -1
- package/plugins/ruflo-metaharness/skills/harness-evolve/SKILL.md +1 -1
- package/plugins/ruflo-metaharness/skills/harness-genome/SKILL.md +1 -1
- package/plugins/ruflo-metaharness/skills/harness-mcp-scan/SKILL.md +1 -1
- package/plugins/ruflo-metaharness/skills/harness-mint/SKILL.md +1 -1
- package/plugins/ruflo-metaharness/skills/harness-score/SKILL.md +1 -1
- package/plugins/ruflo-metaharness/skills/harness-threat-model/SKILL.md +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": {
|
|
3
|
-
"version": "3.56.
|
|
3
|
+
"version": "3.56.3",
|
|
4
4
|
"files": {
|
|
5
5
|
"auto-memory-hook.mjs": "c8d218526a3c34034c2a69de23f507f0eb0f70d59c16426a8edc849e6ac22529",
|
|
6
6
|
"hook-handler.cjs": "34d2aacfb59a73ff94b1467bb57ab9d9c4af89c0e470aadf3bd0d74a503a658d",
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
"router.cjs": "16648b3c0d73b6681ac2d8d13def6a68286c57f5a11004de5b19a0fa088c833d"
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
|
-
"signature": "
|
|
12
|
+
"signature": "U1PReRNeRDIa3/64YWz99uxvI1OmVc3d53VBaVg9neZlrSC5LNaCGtMcGyIcrB2bA6jl4SHsHlbDvNcVH38UCw==",
|
|
13
13
|
"algorithm": "ed25519"
|
|
14
14
|
}
|
package/catalog-manifest.json
CHANGED
|
@@ -2600,8 +2600,12 @@ export const hooksSessionEnd = {
|
|
|
2600
2600
|
try {
|
|
2601
2601
|
await bridge?.shutdownBridge();
|
|
2602
2602
|
}
|
|
2603
|
-
catch {
|
|
2604
|
-
// Cleanup is best-effort and must not fail session-end
|
|
2603
|
+
catch (err) {
|
|
2604
|
+
// Cleanup is best-effort and must not fail session-end, but a failed
|
|
2605
|
+
// AgentDB persist (lock/concurrent writer) is never silent.
|
|
2606
|
+
if (err?.code === 'AGENTDB_LOCK_UNRECOVERABLE') {
|
|
2607
|
+
process.stderr.write(`[ruflo] warning: ${err.message}\n`);
|
|
2608
|
+
}
|
|
2605
2609
|
}
|
|
2606
2610
|
}
|
|
2607
2611
|
return {
|
|
@@ -4,5 +4,10 @@
|
|
|
4
4
|
* Tool definitions for task management with file persistence.
|
|
5
5
|
*/
|
|
6
6
|
import { type MCPTool } from './types.js';
|
|
7
|
+
export declare const TASK_STATUSES: readonly ["pending", "in_progress", "completed", "failed", "cancelled"];
|
|
8
|
+
type TaskStatus = (typeof TASK_STATUSES)[number];
|
|
9
|
+
/** The canonical status for a written one (trimmed, any case, known aliases), or null when it is none of the five. */
|
|
10
|
+
export declare function statusOf(value: unknown): TaskStatus | null;
|
|
7
11
|
export declare const taskTools: MCPTool[];
|
|
12
|
+
export {};
|
|
8
13
|
//# sourceMappingURL=task-tools.d.ts.map
|
|
@@ -12,6 +12,21 @@ import { validateIdentifier, validateText } from './validate-input.js';
|
|
|
12
12
|
const STORAGE_DIR = '.claude-flow';
|
|
13
13
|
const TASK_DIR = 'tasks';
|
|
14
14
|
const TASK_FILE = 'store.json';
|
|
15
|
+
export const TASK_STATUSES = ['pending', 'in_progress', 'completed', 'failed', 'cancelled'];
|
|
16
|
+
// Spellings agents write for the same five states (seen in the wild: "complete").
|
|
17
|
+
const STATUS_ALIASES = {
|
|
18
|
+
complete: 'completed', done: 'completed', canceled: 'cancelled',
|
|
19
|
+
running: 'in_progress', 'in-progress': 'in_progress', inprogress: 'in_progress',
|
|
20
|
+
};
|
|
21
|
+
/** The canonical status for a written one (trimmed, any case, known aliases), or null when it is none of the five. */
|
|
22
|
+
export function statusOf(value) {
|
|
23
|
+
if (typeof value !== 'string')
|
|
24
|
+
return null;
|
|
25
|
+
const key = value.trim().toLowerCase();
|
|
26
|
+
if (TASK_STATUSES.includes(key))
|
|
27
|
+
return key;
|
|
28
|
+
return Object.hasOwn(STATUS_ALIASES, key) ? STATUS_ALIASES[key] : null;
|
|
29
|
+
}
|
|
15
30
|
function getTaskDir() {
|
|
16
31
|
return join(getProjectCwd(), STORAGE_DIR, TASK_DIR);
|
|
17
32
|
}
|
|
@@ -290,7 +305,9 @@ export const taskTools = [
|
|
|
290
305
|
type: 'object',
|
|
291
306
|
properties: {
|
|
292
307
|
taskId: { type: 'string', description: 'Task ID' },
|
|
293
|
-
|
|
308
|
+
// No schema enum: the HTTP/WebSocket registry validates enums before the handler, which would refuse the aliases there
|
|
309
|
+
// while stdio accepted them. The handler is the one place that normalises and refuses, for every transport.
|
|
310
|
+
status: { type: 'string', description: 'New status: pending, in_progress, completed, failed or cancelled' },
|
|
294
311
|
progress: { type: 'number', description: 'Progress percentage (0-100)' },
|
|
295
312
|
assignTo: { type: 'array', items: { type: 'string' }, description: 'Agent IDs to assign' },
|
|
296
313
|
result: { type: 'object', description: 'Result data (e.g. the failure of a failed task)' },
|
|
@@ -302,26 +319,52 @@ export const taskTools = [
|
|
|
302
319
|
const vId = validateIdentifier(input.taskId, 'taskId');
|
|
303
320
|
if (!vId.valid)
|
|
304
321
|
return { success: false, error: vId.error };
|
|
322
|
+
// A status outside the five is stored as written otherwise, and every reader that buckets
|
|
323
|
+
// by status (task_list filters, the console kanban) then miscounts it: "complete" read as pending.
|
|
324
|
+
const status = input.status === undefined ? undefined : statusOf(input.status);
|
|
325
|
+
if (status === null) {
|
|
326
|
+
return { success: false, error: `status must be one of ${TASK_STATUSES.join(', ')}` };
|
|
327
|
+
}
|
|
305
328
|
const store = loadTaskStore();
|
|
306
329
|
const taskId = input.taskId;
|
|
307
330
|
const task = store.tasks[taskId];
|
|
308
331
|
if (task) {
|
|
309
|
-
|
|
310
|
-
|
|
332
|
+
// Worker effects run AFTER the task store is saved, as task_complete does: a failed save must not leave
|
|
333
|
+
// workers freed and counted against a task that still reads unfinished.
|
|
334
|
+
let afterSave;
|
|
335
|
+
if (status !== undefined) {
|
|
336
|
+
const newStatus = status;
|
|
337
|
+
const wasCompleted = task.status === 'completed';
|
|
311
338
|
task.status = newStatus;
|
|
312
339
|
if (newStatus === 'in_progress' && !task.startedAt) {
|
|
313
340
|
task.startedAt = new Date().toISOString();
|
|
314
341
|
}
|
|
315
|
-
// A
|
|
316
|
-
//
|
|
317
|
-
|
|
342
|
+
// A finished task frees its workers, as task_complete and task_cancel do; otherwise a worker
|
|
343
|
+
// whose task was finished through task_update stays `busy` forever, and a later task_complete
|
|
344
|
+
// returns early because the status already reads completed.
|
|
345
|
+
if (newStatus === 'failed' || newStatus === 'cancelled') {
|
|
346
|
+
task.completedAt = new Date().toISOString();
|
|
347
|
+
afterSave = () => releaseAgents(task.assignedTo, taskId);
|
|
348
|
+
}
|
|
349
|
+
if (newStatus === 'completed' && !wasCompleted) {
|
|
318
350
|
task.completedAt = new Date().toISOString();
|
|
319
|
-
|
|
351
|
+
// Credited only to a worker still holding this task, so complete -> pending -> complete
|
|
352
|
+
// (no reassignment in between) never counts the same work twice.
|
|
353
|
+
afterSave = () => updateAgents(task.assignedTo, (agent) => {
|
|
354
|
+
if (agent.currentTask === taskId) {
|
|
355
|
+
agent.status = 'idle';
|
|
356
|
+
agent.currentTask = null;
|
|
357
|
+
agent.taskCount = (agent.taskCount || 0) + 1;
|
|
358
|
+
}
|
|
359
|
+
});
|
|
320
360
|
}
|
|
321
361
|
}
|
|
322
362
|
if (typeof input.progress === 'number') {
|
|
323
363
|
task.progress = Math.min(100, Math.max(0, input.progress));
|
|
324
364
|
}
|
|
365
|
+
// Completing is 100% whatever progress the same call carried.
|
|
366
|
+
if (task.status === 'completed')
|
|
367
|
+
task.progress = 100;
|
|
325
368
|
if (input.assignTo) {
|
|
326
369
|
task.assignedTo = input.assignTo;
|
|
327
370
|
}
|
|
@@ -329,6 +372,7 @@ export const taskTools = [
|
|
|
329
372
|
task.result = input.result;
|
|
330
373
|
}
|
|
331
374
|
saveTaskStore(store);
|
|
375
|
+
afterSave?.();
|
|
332
376
|
return {
|
|
333
377
|
success: true,
|
|
334
378
|
taskId: task.taskId,
|
|
@@ -2087,16 +2087,25 @@ export function shutdownBridge() {
|
|
|
2087
2087
|
if (activeOperations > 0)
|
|
2088
2088
|
await new Promise(resolve => { drained = resolve; });
|
|
2089
2089
|
await Promise.allSettled([...registryPromises.values()]);
|
|
2090
|
+
// A failed PERSIST (AGENTDB_LOCK_UNRECOVERABLE: live lock or concurrent
|
|
2091
|
+
// writer on a sql.js database) means pending changes were not saved. That
|
|
2092
|
+
// is surfaced after cleanup completes; other close errors stay best-effort.
|
|
2093
|
+
let persistFailure;
|
|
2090
2094
|
for (const registry of new Set(registryInstances.values())) {
|
|
2091
2095
|
try {
|
|
2092
2096
|
await registry.shutdown();
|
|
2093
2097
|
}
|
|
2094
|
-
catch {
|
|
2098
|
+
catch (err) {
|
|
2099
|
+
if (err?.code === 'AGENTDB_LOCK_UNRECOVERABLE')
|
|
2100
|
+
persistFailure ??= err;
|
|
2101
|
+
}
|
|
2095
2102
|
}
|
|
2096
2103
|
registryInstances.clear();
|
|
2097
2104
|
registryPromises.clear();
|
|
2098
2105
|
testRegistryOverride = null;
|
|
2099
2106
|
bridgeFailureReasons.clear();
|
|
2107
|
+
if (persistFailure)
|
|
2108
|
+
throw persistFailure;
|
|
2100
2109
|
})().finally(() => { shutdownPromise = null; });
|
|
2101
2110
|
return shutdownPromise;
|
|
2102
2111
|
}
|