@claude-flow/cli 3.32.30 → 3.32.32
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/autopilot-state.d.ts +10 -0
- package/dist/src/autopilot-state.js +16 -0
- package/dist/src/commands/autopilot.js +10 -4
- package/dist/src/mcp-tools/autopilot-tools.js +18 -3
- package/dist/src/services/harness-flywheel-runtime.d.ts +21 -1
- package/dist/src/services/harness-flywheel-runtime.js +46 -24
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": {
|
|
3
|
-
"version": "3.32.
|
|
3
|
+
"version": "3.32.32",
|
|
4
4
|
"files": {
|
|
5
5
|
"auto-memory-hook.mjs": "68be7e9a9eba7bf9c4e8a230db7bf61a243b965639f8504842799d6c6ca28762",
|
|
6
6
|
"hook-handler.cjs": "50ea92a72651bdc95634f7588d56a5870963168eef5226f66ed14af3b47c8d9a",
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
"statusline.cjs": "d2a0eac56d1267d8dbed2d70b09feb592299469196ec4b215909f2b052144882"
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
|
-
"signature": "
|
|
11
|
+
"signature": "04DvDI9kCGvy1HIskgegJsTnGUTgnDBMGTb/c+ef/hy3XgM4WvpHb6xePaWraB6YQ4F41+4BZRi4ZeBWBrVbBA==",
|
|
12
12
|
"algorithm": "ed25519"
|
|
13
13
|
}
|
package/catalog-manifest.json
CHANGED
|
@@ -61,6 +61,16 @@ export declare function validateNumber(value: unknown, min: number, max: number,
|
|
|
61
61
|
* Returns only valid sources; falls back to defaults if none are valid.
|
|
62
62
|
*/
|
|
63
63
|
export declare function validateTaskSources(sources: unknown): string[];
|
|
64
|
+
export type TaskSourceValidation = {
|
|
65
|
+
valid: true;
|
|
66
|
+
sources: string[];
|
|
67
|
+
} | {
|
|
68
|
+
valid: false;
|
|
69
|
+
invalidSources: string[];
|
|
70
|
+
reason: string;
|
|
71
|
+
};
|
|
72
|
+
/** Strictly validate user-supplied task sources without enabling defaults. */
|
|
73
|
+
export declare function validateConfiguredTaskSources(sources: unknown): TaskSourceValidation;
|
|
64
74
|
export declare function getDefaultState(): AutopilotState;
|
|
65
75
|
export declare function loadState(): AutopilotState;
|
|
66
76
|
export declare function saveState(state: AutopilotState): void;
|
|
@@ -74,6 +74,22 @@ export function validateTaskSources(sources) {
|
|
|
74
74
|
.filter(s => VALID_TASK_SOURCES.has(s));
|
|
75
75
|
return valid.length > 0 ? valid : defaults;
|
|
76
76
|
}
|
|
77
|
+
/** Strictly validate user-supplied task sources without enabling defaults. */
|
|
78
|
+
export function validateConfiguredTaskSources(sources) {
|
|
79
|
+
if (!Array.isArray(sources) || sources.length === 0) {
|
|
80
|
+
return { valid: false, invalidSources: [], reason: 'At least one task source is required' };
|
|
81
|
+
}
|
|
82
|
+
const normalized = sources.map(source => typeof source === 'string' ? source.trim() : String(source));
|
|
83
|
+
const invalidSources = normalized.filter(source => !VALID_TASK_SOURCES.has(source));
|
|
84
|
+
if (invalidSources.length > 0) {
|
|
85
|
+
return {
|
|
86
|
+
valid: false,
|
|
87
|
+
invalidSources,
|
|
88
|
+
reason: `Unsupported task source(s): ${invalidSources.join(', ')}`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return { valid: true, sources: [...new Set(normalized)] };
|
|
92
|
+
}
|
|
77
93
|
// ── State Management ──────────────────────────────────────────
|
|
78
94
|
export function getDefaultState() {
|
|
79
95
|
return {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* ADR-072: Autopilot Integration
|
|
6
6
|
*/
|
|
7
7
|
import { output } from '../output.js';
|
|
8
|
-
import { loadState, saveState, appendLog, loadLog, discoverTasks, getProgress, calculateReward, tryLoadLearning, validateNumber,
|
|
8
|
+
import { loadState, saveState, appendLog, loadLog, discoverTasks, getProgress, calculateReward, tryLoadLearning, validateNumber, validateConfiguredTaskSources, VALID_TASK_SOURCES, LOG_FILE, } from '../autopilot-state.js';
|
|
9
9
|
import { getCheckpointGate, CheckpointGate } from '../services/checkpoint-gate.js';
|
|
10
10
|
/**
|
|
11
11
|
* Opt-in checkpoint/rollback gate for the autopilot tick (agenticow step 3).
|
|
@@ -183,7 +183,7 @@ const configCommand = {
|
|
|
183
183
|
options: [
|
|
184
184
|
{ name: 'max-iterations', type: 'string', description: 'Max re-engagement iterations (1-1000)' },
|
|
185
185
|
{ name: 'timeout', type: 'string', description: 'Timeout in minutes (1-1440)' },
|
|
186
|
-
{ name: 'task-sources', type: 'string', description:
|
|
186
|
+
{ name: 'task-sources', type: 'string', description: `Comma-separated task sources: ${[...VALID_TASK_SOURCES].join(', ')}` },
|
|
187
187
|
],
|
|
188
188
|
action: async (ctx) => {
|
|
189
189
|
const state = loadState();
|
|
@@ -194,8 +194,14 @@ const configCommand = {
|
|
|
194
194
|
state.maxIterations = validateNumber(maxIter, 1, 1000, state.maxIterations);
|
|
195
195
|
if (timeout)
|
|
196
196
|
state.timeoutMinutes = validateNumber(timeout, 1, 1440, state.timeoutMinutes);
|
|
197
|
-
if (sources)
|
|
198
|
-
|
|
197
|
+
if (sources !== undefined) {
|
|
198
|
+
const validation = validateConfiguredTaskSources(sources.split(',').map(s => s.trim()).filter(Boolean));
|
|
199
|
+
if (!validation.valid) {
|
|
200
|
+
output.printError(`${validation.reason}. Valid sources: ${[...VALID_TASK_SOURCES].join(', ')}`);
|
|
201
|
+
return { success: false, exitCode: 1 };
|
|
202
|
+
}
|
|
203
|
+
state.taskSources = validation.sources;
|
|
204
|
+
}
|
|
199
205
|
saveState(state);
|
|
200
206
|
appendLog({ ts: Date.now(), event: 'config-updated', maxIterations: state.maxIterations, timeoutMinutes: state.timeoutMinutes, taskSources: state.taskSources });
|
|
201
207
|
output.writeln(`Config updated: maxIterations=${state.maxIterations}, timeout=${state.timeoutMinutes}min, sources=${state.taskSources.join(',')}`);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @module @claude-flow/cli/mcp-tools/autopilot
|
|
9
9
|
*/
|
|
10
10
|
import { validateText } from './validate-input.js';
|
|
11
|
-
import { loadState, saveState, appendLog, loadLog, discoverTasks, isTerminal, tryLoadLearning, validateNumber,
|
|
11
|
+
import { loadState, saveState, appendLog, loadLog, discoverTasks, isTerminal, tryLoadLearning, validateNumber, validateConfiguredTaskSources, VALID_TASK_SOURCES, } from '../autopilot-state.js';
|
|
12
12
|
function ok(data) {
|
|
13
13
|
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
14
14
|
}
|
|
@@ -71,7 +71,12 @@ const autopilotConfig = {
|
|
|
71
71
|
properties: {
|
|
72
72
|
maxIterations: { type: 'number', description: 'Max re-engagement iterations (1-1000)' },
|
|
73
73
|
timeoutMinutes: { type: 'number', description: 'Timeout in minutes (1-1440)' },
|
|
74
|
-
taskSources: {
|
|
74
|
+
taskSources: {
|
|
75
|
+
type: 'array',
|
|
76
|
+
minItems: 1,
|
|
77
|
+
items: { type: 'string', enum: [...VALID_TASK_SOURCES] },
|
|
78
|
+
description: `Task sources: ${[...VALID_TASK_SOURCES].join(', ')}`,
|
|
79
|
+
},
|
|
75
80
|
},
|
|
76
81
|
},
|
|
77
82
|
handler: async (params) => {
|
|
@@ -83,7 +88,17 @@ const autopilotConfig = {
|
|
|
83
88
|
state.timeoutMinutes = validateNumber(params.timeoutMinutes, 1, 1440, state.timeoutMinutes);
|
|
84
89
|
}
|
|
85
90
|
if (params.taskSources !== undefined) {
|
|
86
|
-
|
|
91
|
+
const validation = validateConfiguredTaskSources(params.taskSources);
|
|
92
|
+
if (!validation.valid) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
95
|
+
error: validation.reason,
|
|
96
|
+
validSources: [...VALID_TASK_SOURCES],
|
|
97
|
+
}) }],
|
|
98
|
+
isError: true,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
state.taskSources = validation.sources;
|
|
87
102
|
}
|
|
88
103
|
saveState(state);
|
|
89
104
|
return ok({ maxIterations: state.maxIterations, timeoutMinutes: state.timeoutMinutes, taskSources: state.taskSources });
|
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
import { type FlywheelResult } from './harness-flywheel.js';
|
|
2
2
|
import { type GenerationResult } from './harness-flywheel-generations.js';
|
|
3
|
-
import { type DarwinInvoker, type ProposerMode } from './flywheel-proposer.js';
|
|
3
|
+
import { type DarwinInvoker, type ProposerMode, type SafetyEnvelope } from './flywheel-proposer.js';
|
|
4
|
+
/**
|
|
5
|
+
* The ADR-322 retrieval safety envelope.
|
|
6
|
+
*
|
|
7
|
+
* It MUST describe the policy surface the proposer actually emits —
|
|
8
|
+
* `RetrievalConfig`. The v1 envelope allowed `topK`/`rerank`, which are
|
|
9
|
+
* `neural_patterns` search-call arguments not representable in
|
|
10
|
+
* `RetrievalConfig`, while omitting the three weight axes that
|
|
11
|
+
* `retrievalPolicyNeighbors` does mutate. Because `validateCandidate` checks
|
|
12
|
+
* EVERY key of a candidate policy (candidates are full snapshots, not deltas),
|
|
13
|
+
* that drift made every locally-proposed candidate inadmissible and the local
|
|
14
|
+
* evaluation path unreachable — no receipt, therefore no promotion, ever.
|
|
15
|
+
*
|
|
16
|
+
* Every axis carries a finite bound: an allowed key WITHOUT bounds is an
|
|
17
|
+
* unbounded key, because `validateCandidate` applies bounds only when present.
|
|
18
|
+
* A Darwin proposer could otherwise submit arbitrary weights on the three axes.
|
|
19
|
+
*
|
|
20
|
+
* Exported so tests can bind the REAL envelope to the REAL proposer; the drift
|
|
21
|
+
* survived review precisely because no test wired those two together.
|
|
22
|
+
*/
|
|
23
|
+
export declare function retrievalSafetyEnvelope(ref?: string): SafetyEnvelope;
|
|
4
24
|
/**
|
|
5
25
|
* Run one live flywheel tick against `projectRoot`. Opt-in + $0 default: with
|
|
6
26
|
* RUFLO_HARNESS_LOOP unset it is a no-op. Best-effort; never throws.
|
|
@@ -24,6 +24,51 @@ const ANCHOR = [
|
|
|
24
24
|
['Q-learning encoder keyword block', ['q-state encoder', 'route q-state', 'keyword block', '#2239', 'q-encoder']],
|
|
25
25
|
['security hardening crypto random IDs', ['cwe-347', 'crypto.randomuuid', 'security fix', 'random id', 'crypto random']],
|
|
26
26
|
].map(([q, labels], i) => ({ id: `q${String(i).padStart(2, '0')}`, input: { id: `q${String(i).padStart(2, '0')}`, q: q }, expected: labels }));
|
|
27
|
+
/**
|
|
28
|
+
* The ADR-322 retrieval safety envelope.
|
|
29
|
+
*
|
|
30
|
+
* It MUST describe the policy surface the proposer actually emits —
|
|
31
|
+
* `RetrievalConfig`. The v1 envelope allowed `topK`/`rerank`, which are
|
|
32
|
+
* `neural_patterns` search-call arguments not representable in
|
|
33
|
+
* `RetrievalConfig`, while omitting the three weight axes that
|
|
34
|
+
* `retrievalPolicyNeighbors` does mutate. Because `validateCandidate` checks
|
|
35
|
+
* EVERY key of a candidate policy (candidates are full snapshots, not deltas),
|
|
36
|
+
* that drift made every locally-proposed candidate inadmissible and the local
|
|
37
|
+
* evaluation path unreachable — no receipt, therefore no promotion, ever.
|
|
38
|
+
*
|
|
39
|
+
* Every axis carries a finite bound: an allowed key WITHOUT bounds is an
|
|
40
|
+
* unbounded key, because `validateCandidate` applies bounds only when present.
|
|
41
|
+
* A Darwin proposer could otherwise submit arbitrary weights on the three axes.
|
|
42
|
+
*
|
|
43
|
+
* Exported so tests can bind the REAL envelope to the REAL proposer; the drift
|
|
44
|
+
* survived review precisely because no test wired those two together.
|
|
45
|
+
*/
|
|
46
|
+
export function retrievalSafetyEnvelope(ref) {
|
|
47
|
+
const allowedPolicyKeys = ['alpha', 'subjectWeight', 'mmrLambda', 'bodyWeight', 'typePenaltyFactor'];
|
|
48
|
+
const numericBounds = {
|
|
49
|
+
alpha: { min: 0.1, max: 0.9 },
|
|
50
|
+
subjectWeight: { min: 0.1, max: 10 },
|
|
51
|
+
mmrLambda: { min: 0.3, max: 0.9 },
|
|
52
|
+
bodyWeight: { min: 0.1, max: 10 },
|
|
53
|
+
typePenaltyFactor: { min: 0.1, max: 10 },
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
ref: ref ?? sha256Ref(JSON.stringify({
|
|
57
|
+
schema: 'ruflo.retrieval-safety-envelope/v2',
|
|
58
|
+
allowedPolicyKeys,
|
|
59
|
+
numericBounds,
|
|
60
|
+
})),
|
|
61
|
+
allowedPolicyKeys,
|
|
62
|
+
numericBounds,
|
|
63
|
+
// Retrieval evaluations are local and report zero provider spend today;
|
|
64
|
+
// finite ceilings make any future resource evidence fail closed.
|
|
65
|
+
maxP95LatencyMicros: 5_000_000,
|
|
66
|
+
maxCostMicrosPerTask: 10_000,
|
|
67
|
+
maxTokensPerTask: 100_000,
|
|
68
|
+
maxFailureRate: 0.01,
|
|
69
|
+
maxEvaluationCostMicros: 1_000_000,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
27
72
|
/**
|
|
28
73
|
* Run one live flywheel tick against `projectRoot`. Opt-in + $0 default: with
|
|
29
74
|
* RUFLO_HARNESS_LOOP unset it is a no-op. Best-effort; never throws.
|
|
@@ -53,30 +98,7 @@ export async function runFlywheelWorker(projectRoot, opts = {}) {
|
|
|
53
98
|
...DEFAULT_CONFIG,
|
|
54
99
|
...(applier.activeChampion(projectRoot)?.params ?? {}),
|
|
55
100
|
};
|
|
56
|
-
const safetyEnvelope =
|
|
57
|
-
ref: opts.safetyEnvelopeRef ?? sha256Ref(JSON.stringify({
|
|
58
|
-
schema: 'ruflo.retrieval-safety-envelope/v1',
|
|
59
|
-
allowedPolicyKeys: ['alpha', 'topK', 'rerank', 'mmrLambda'],
|
|
60
|
-
numericBounds: {
|
|
61
|
-
alpha: { min: 0.1, max: 0.9 },
|
|
62
|
-
topK: { min: 5, max: 20 },
|
|
63
|
-
mmrLambda: { min: 0.3, max: 0.9 },
|
|
64
|
-
},
|
|
65
|
-
})),
|
|
66
|
-
allowedPolicyKeys: ['alpha', 'topK', 'rerank', 'mmrLambda'],
|
|
67
|
-
numericBounds: {
|
|
68
|
-
alpha: { min: 0.1, max: 0.9 },
|
|
69
|
-
topK: { min: 5, max: 20 },
|
|
70
|
-
mmrLambda: { min: 0.3, max: 0.9 },
|
|
71
|
-
},
|
|
72
|
-
// Retrieval evaluations are local and report zero provider spend today;
|
|
73
|
-
// finite ceilings make any future resource evidence fail closed.
|
|
74
|
-
maxP95LatencyMicros: 5_000_000,
|
|
75
|
-
maxCostMicrosPerTask: 10_000,
|
|
76
|
-
maxTokensPerTask: 100_000,
|
|
77
|
-
maxFailureRate: 0.01,
|
|
78
|
-
maxEvaluationCostMicros: 1_000_000,
|
|
79
|
-
};
|
|
101
|
+
const safetyEnvelope = retrievalSafetyEnvelope(opts.safetyEnvelopeRef);
|
|
80
102
|
// CLI flag opts.proposer takes precedence over RUFLO_FLYWHEEL_PROPOSER.
|
|
81
103
|
const proposerMode = opts.proposer
|
|
82
104
|
?? (process.env.RUFLO_FLYWHEEL_PROPOSER ?? 'auto');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.32.
|
|
3
|
+
"version": "3.32.32",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|