@claude-flow/cli 3.56.10 → 3.57.1
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-version +1 -1
- package/.claude/helpers/helpers.manifest.json +2 -2
- package/README.md +12 -3
- package/catalog-manifest.json +2 -2
- package/dist/src/commands/daemon.js +8 -2
- package/dist/src/commands/doctor.js +95 -18
- package/dist/src/commands/policy.js +6 -1
- package/dist/src/index.js +5 -5
- package/dist/src/init/settings-generator.js +4 -58
- package/dist/src/mcp-tools/memory-tools.d.ts +1 -1
- package/dist/src/mcp-tools/memory-tools.js +30 -5
- package/dist/src/mcp-tools/metaharness-tools.js +1 -1
- package/dist/src/mcp-tools/neural-tools.js +20 -50
- package/dist/src/mcp-tools/policy-tools.js +5 -3
- package/dist/src/memory/intelligence.js +80 -33
- package/dist/src/memory/stats-file-lock.d.ts +7 -0
- package/dist/src/memory/stats-file-lock.js +53 -0
- package/dist/src/missions/schemas.d.ts +113 -113
- package/dist/src/mods/command-registry/schema.d.ts +193 -193
- package/dist/src/services/distill-oracle.d.ts +1 -1
- package/dist/src/services/distill-oracle.js +2 -2
- package/dist/src/services/policy-anchor-log.d.ts +13 -0
- package/dist/src/services/policy-anchor-log.js +242 -0
- package/dist/src/services/policy-archive-scan.d.ts +7 -0
- package/dist/src/services/policy-archive-scan.js +50 -0
- package/dist/src/services/policy-ledger-anchor.d.ts +14 -8
- package/dist/src/services/policy-ledger-anchor.js +356 -40
- package/dist/src/services/policy-ledger-audit.d.ts +22 -0
- package/dist/src/services/policy-ledger-audit.js +260 -0
- package/dist/src/services/policy-ledger-record.d.ts +3 -0
- package/dist/src/services/policy-ledger-record.js +22 -0
- package/dist/src/services/policy-runtime.d.ts +1 -0
- package/dist/src/services/policy-runtime.js +261 -40
- 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/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
- package/node_modules/@claude-flow/security/dist/policy/engine.d.ts +17 -1
- package/node_modules/@claude-flow/security/dist/policy/engine.d.ts.map +1 -1
- package/node_modules/@claude-flow/security/dist/policy/engine.js +99 -24
- package/node_modules/@claude-flow/security/dist/policy/engine.js.map +1 -1
- package/node_modules/@claude-flow/security/dist/policy/types.d.ts +14 -1
- package/node_modules/@claude-flow/security/dist/policy/types.d.ts.map +1 -1
- package/node_modules/@claude-flow/security/dist/policy/types.js +3 -1
- package/node_modules/@claude-flow/security/dist/policy/types.js.map +1 -1
- package/package.json +3 -3
- package/plugins/ruflo-console/dist/tui.mjs +153 -153
- package/plugins/ruflo-metaharness/hooks/screen.ts +7 -1
- package/plugins/ruflo-metaharness/scripts/_darwin.mjs +4 -4
- package/plugins/ruflo-metaharness/.claude-flow/daemon-state.json +0 -179
- package/plugins/ruflo-metaharness/.claude-flow/daemon.pid +0 -1
- package/plugins/ruflo-metaharness/.claude-flow/logs/daemon.log +0 -32
- package/plugins/ruflo-metaharness/.claude-flow/metrics/backup.json +0 -23
- package/plugins/ruflo-metaharness/.claude-flow/metrics/codebase-map.json +0 -11
- package/plugins/ruflo-metaharness/.claude-flow/metrics/consolidation.json +0 -16
- package/plugins/ruflo-metaharness/.claude-flow/metrics/harness-loop.json +0 -91
- package/plugins/ruflo-metaharness/.claude-flow/metrics/performance.json +0 -17
- package/plugins/ruflo-metaharness/.claude-flow/metrics/security-audit.json +0 -12
- package/plugins/ruflo-metaharness/.claude-flow/metrics/test-gaps.json +0 -8
- package/plugins/ruflo-metaharness/.claude-flow/neural/patterns.json +0 -2809
- package/plugins/ruflo-metaharness/.claude-flow/neural/stats.json +0 -6
- package/plugins/ruflo-metaharness/.claude-flow/policy/state.json +0 -11
- package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db +0 -0
- package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db-shm +0 -0
- package/plugins/ruflo-metaharness/.swarm/agentdb-memory.db-wal +0 -0
- package/plugins/ruflo-metaharness/.swarm/backups/memory-2026-10-14T16-09-38-164Z.db +0 -0
- package/plugins/ruflo-metaharness/.swarm/backups/store-agentdb-memory.db-2026-10-14T16-09-38-166Z.db +0 -0
- package/plugins/ruflo-metaharness/.swarm/ewc-fisher.json +0 -397
- package/plugins/ruflo-metaharness/.swarm/memory.db +0 -0
- package/plugins/ruflo-metaharness/.swarm/memory.db-shm +0 -0
- package/plugins/ruflo-metaharness/.swarm/memory.db-wal +0 -0
- package/plugins/ruflo-metaharness/agentdb.rvf +0 -0
- package/plugins/ruflo-metaharness/agentdb.rvf.lock +0 -0
- package/plugins/ruflo-metaharness/ruvector.db +0 -0
|
@@ -908,9 +908,6 @@ export const neuralTools = [
|
|
|
908
908
|
if (!v.valid)
|
|
909
909
|
return { success: false, error: v.error };
|
|
910
910
|
}
|
|
911
|
-
// Resolve provider so embeddingProvider in the result matches the old
|
|
912
|
-
// eager-init reporting.
|
|
913
|
-
await ensureEmbeddings();
|
|
914
911
|
const store = loadNeuralStore();
|
|
915
912
|
const method = input.method || 'quantize';
|
|
916
913
|
const targetReduction = input.targetSize || 0.5;
|
|
@@ -919,38 +916,25 @@ export const neuralTools = [
|
|
|
919
916
|
return { success: false, error: 'No patterns to compress. Train patterns first with neural_train.' };
|
|
920
917
|
}
|
|
921
918
|
const beforeCount = patterns.length;
|
|
922
|
-
const beforeSize = patterns.reduce((s, p) => s + (p.embedding?.length || 0) * 4, 0); // Float32 = 4 bytes
|
|
923
919
|
if (method === 'quantize') {
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
940
|
-
saveNeuralStore(store);
|
|
941
|
-
return {
|
|
942
|
-
success: true, _real: true, method,
|
|
943
|
-
embeddingProvider: embeddingServiceName,
|
|
944
|
-
patternsCompressed: totalCompressed,
|
|
945
|
-
compressionRatio: '3.92x (Int8)',
|
|
946
|
-
beforeBytes: beforeSize,
|
|
947
|
-
afterBytes: Math.round(beforeSize / 3.92),
|
|
948
|
-
};
|
|
949
|
-
}
|
|
950
|
-
catch {
|
|
951
|
-
return { success: false, error: 'Quantization requires memory-initializer. Run `memory init` first.' };
|
|
952
|
-
}
|
|
920
|
+
// Neural-store readers consume `embedding` as a full-precision number[]
|
|
921
|
+
// (search, prediction, deduplication, and optimization). The former
|
|
922
|
+
// implementation discarded the Int8 vector, persisted only metadata,
|
|
923
|
+
// and reported a calculated 3.92x reduction. Refuse until the store has
|
|
924
|
+
// a persisted representation with a reader-side decode contract.
|
|
925
|
+
const storedBytes = readFileSync(getNeuralPath()).byteLength;
|
|
926
|
+
return {
|
|
927
|
+
success: false,
|
|
928
|
+
error: 'Quantized embeddings are not persisted: neural-store readers require full-precision embedding arrays.',
|
|
929
|
+
method,
|
|
930
|
+
patternsCompressed: 0,
|
|
931
|
+
beforeBytes: storedBytes,
|
|
932
|
+
afterBytes: storedBytes,
|
|
933
|
+
compressionRatio: '1.00x (unchanged JSON storage)',
|
|
934
|
+
};
|
|
953
935
|
}
|
|
936
|
+
// Resolve provider only for operations that actually use embeddings.
|
|
937
|
+
await ensureEmbeddings();
|
|
954
938
|
if (method === 'prune') {
|
|
955
939
|
// Prune patterns with low usage count below threshold (targetReduction as min usage)
|
|
956
940
|
const threshold = targetReduction;
|
|
@@ -1136,24 +1120,10 @@ export const neuralTools = [
|
|
|
1136
1120
|
if (duplicatesRemoved > 0)
|
|
1137
1121
|
actions.push(`Removed ${duplicatesRemoved} near-duplicate patterns`);
|
|
1138
1122
|
}
|
|
1139
|
-
// memory / balanced:
|
|
1123
|
+
// memory / balanced: report the unsupported persisted representation
|
|
1124
|
+
// instead of attaching metadata for a discarded Int8 vector.
|
|
1140
1125
|
if (target === 'memory' || target === 'balanced') {
|
|
1141
|
-
|
|
1142
|
-
const { quantizeInt8, getQuantizationStats } = await import('../memory/memory-initializer.js');
|
|
1143
|
-
for (const p of Object.values(store.patterns)) {
|
|
1144
|
-
if (p.embedding && p.embedding.length > 0 && !p._quantized) {
|
|
1145
|
-
const stats = getQuantizationStats(p.embedding);
|
|
1146
|
-
const q = quantizeInt8(p.embedding);
|
|
1147
|
-
p._quantized = { scale: q.scale, zeroPoint: q.zeroPoint, compressionRatio: stats.compressionRatio };
|
|
1148
|
-
patternsQuantized++;
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
if (patternsQuantized > 0)
|
|
1152
|
-
actions.push(`Quantized ${patternsQuantized} pattern embeddings (Int8, ~3.92x)`);
|
|
1153
|
-
}
|
|
1154
|
-
catch {
|
|
1155
|
-
actions.push('Quantization skipped (memory-initializer not available)');
|
|
1156
|
-
}
|
|
1126
|
+
actions.push('Quantization skipped: neural-store readers require persisted full-precision embedding arrays.');
|
|
1157
1127
|
}
|
|
1158
1128
|
// accuracy / balanced: prune low-usage, zero-embedding patterns
|
|
1159
1129
|
if (target === 'accuracy' || target === 'balanced') {
|
|
@@ -24,9 +24,11 @@ export const policyTools = [
|
|
|
24
24
|
category: 'security',
|
|
25
25
|
inputSchema: {
|
|
26
26
|
type: 'object',
|
|
27
|
-
properties: {
|
|
27
|
+
properties: {
|
|
28
|
+
full: { type: 'boolean', description: 'Also replay the archived receipts to verify the complete historical ledger, not just the retained hot tail (#3164)' },
|
|
29
|
+
},
|
|
28
30
|
},
|
|
29
|
-
handler: async (
|
|
31
|
+
handler: async (input, context) => {
|
|
30
32
|
const root = typeof context?.projectRoot === 'string' ? context.projectRoot : process.cwd();
|
|
31
33
|
const state = loadPolicyState(root);
|
|
32
34
|
return {
|
|
@@ -39,7 +41,7 @@ export const policyTools = [
|
|
|
39
41
|
approvals: state.approvals.length,
|
|
40
42
|
receipts: state.receipts.length,
|
|
41
43
|
},
|
|
42
|
-
ledger: await verifyPolicyLedger(root),
|
|
44
|
+
ledger: await verifyPolicyLedger(root, { full: input.full === true }),
|
|
43
45
|
};
|
|
44
46
|
},
|
|
45
47
|
},
|
|
@@ -16,6 +16,7 @@ import { createRequire } from 'node:module';
|
|
|
16
16
|
import { join } from 'node:path';
|
|
17
17
|
import { resolveTrainingBackend } from '../ruvector/lora-adapter.js';
|
|
18
18
|
import { getProjectCwd } from '../mcp-tools/types.js';
|
|
19
|
+
import { withStatsFileLock } from './stats-file-lock.js';
|
|
19
20
|
// ============================================================================
|
|
20
21
|
// Persistence Configuration
|
|
21
22
|
// ============================================================================
|
|
@@ -664,11 +665,9 @@ function bumpStat(key, n = 1) {
|
|
|
664
665
|
}
|
|
665
666
|
function readStatsFile() {
|
|
666
667
|
try {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
const data = JSON.parse(readFileSync(path, 'utf-8'));
|
|
671
|
-
return data && typeof data === 'object' ? data : null;
|
|
668
|
+
// Read-only callers keep their unavailable-on-error contract, while invalid
|
|
669
|
+
// disk values cannot poison local state and a later repaired-file flush.
|
|
670
|
+
return readStatsForWrite(getStatsPath());
|
|
672
671
|
}
|
|
673
672
|
catch {
|
|
674
673
|
return null;
|
|
@@ -701,33 +700,79 @@ function maxTimestamp(a, b) {
|
|
|
701
700
|
return a;
|
|
702
701
|
return Math.max(a, b);
|
|
703
702
|
}
|
|
704
|
-
/**
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
703
|
+
/** Missing files are first use; unreadable or invalid files must not be replaced. */
|
|
704
|
+
function readStatsForWrite(path) {
|
|
705
|
+
let text;
|
|
706
|
+
try {
|
|
707
|
+
text = readFileSync(path, 'utf-8');
|
|
708
|
+
}
|
|
709
|
+
catch (error) {
|
|
710
|
+
if (error.code === 'ENOENT')
|
|
711
|
+
return null;
|
|
712
|
+
throw error;
|
|
713
|
+
}
|
|
714
|
+
let data;
|
|
715
|
+
try {
|
|
716
|
+
data = JSON.parse(text);
|
|
717
|
+
}
|
|
718
|
+
catch {
|
|
719
|
+
throw Object.assign(new Error('Invalid learning stats JSON'), { code: 'EINVALIDSTATS' });
|
|
720
|
+
}
|
|
721
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
722
|
+
throw Object.assign(new Error('Invalid learning stats object'), { code: 'EINVALIDSTATS' });
|
|
723
|
+
}
|
|
724
|
+
for (const key of ['trajectoriesRecorded', 'patternsLearned', 'signalsProcessed']) {
|
|
725
|
+
const value = data[key];
|
|
726
|
+
// Older files may omit a counter, but present counters must be exact counts.
|
|
727
|
+
if (value === undefined)
|
|
728
|
+
continue;
|
|
729
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {
|
|
730
|
+
throw Object.assign(new Error(`Invalid learning stats field: ${key}`), { code: 'EINVALIDSTATS' });
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
const timestamp = data.lastAdaptation;
|
|
734
|
+
if (timestamp != null && (typeof timestamp !== 'number' || !Number.isFinite(timestamp) || timestamp < 0)) {
|
|
735
|
+
throw Object.assign(new Error('Invalid learning stats timestamp'), { code: 'EINVALIDSTATS' });
|
|
736
|
+
}
|
|
737
|
+
return data;
|
|
738
|
+
}
|
|
739
|
+
/** Merge pending deltas under the cooperating-writer lock, then adopt committed totals. */
|
|
709
740
|
function savePersistedStats() {
|
|
741
|
+
let statsPath;
|
|
710
742
|
try {
|
|
711
|
-
ensureDataDir();
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
743
|
+
statsPath = join(ensureDataDir(), 'stats.json');
|
|
744
|
+
withStatsFileLock(statsPath, (path) => {
|
|
745
|
+
const disk = readStatsForWrite(path);
|
|
746
|
+
const merged = disk
|
|
747
|
+
? {
|
|
748
|
+
trajectoriesRecorded: (disk.trajectoriesRecorded ?? 0) + pendingDelta.trajectoriesRecorded,
|
|
749
|
+
patternsLearned: (disk.patternsLearned ?? 0) + pendingDelta.patternsLearned,
|
|
750
|
+
signalsProcessed: (disk.signalsProcessed ?? 0) + pendingDelta.signalsProcessed,
|
|
751
|
+
lastAdaptation: maxTimestamp(disk.lastAdaptation ?? null, globalStats.lastAdaptation),
|
|
752
|
+
}
|
|
753
|
+
: { ...globalStats };
|
|
754
|
+
for (const key of ['trajectoriesRecorded', 'patternsLearned', 'signalsProcessed']) {
|
|
755
|
+
if (!Number.isSafeInteger(merged[key]) || merged[key] < 0) {
|
|
756
|
+
throw Object.assign(new Error('Learning stats counter overflow'), { code: 'EINVALIDSTATS' });
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (merged.lastAdaptation != null &&
|
|
760
|
+
(!Number.isFinite(merged.lastAdaptation) || merged.lastAdaptation < 0)) {
|
|
761
|
+
throw Object.assign(new Error('Invalid merged learning stats timestamp'), { code: 'EINVALIDSTATS' });
|
|
720
762
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
763
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
764
|
+
writeFileSync(tmp, JSON.stringify(merged, null, 2), 'utf-8');
|
|
765
|
+
renameSync(tmp, path);
|
|
766
|
+
// Commit local state before release: a failed release must not replay it.
|
|
767
|
+
globalStats = merged;
|
|
768
|
+
pendingDelta = { trajectoriesRecorded: 0, patternsLearned: 0, signalsProcessed: 0 };
|
|
769
|
+
persistedStatsLoaded = true;
|
|
770
|
+
});
|
|
728
771
|
}
|
|
729
|
-
catch {
|
|
730
|
-
|
|
772
|
+
catch (error) {
|
|
773
|
+
const { code = 'UNKNOWN', path = statsPath || 'neural stats directory' } = error;
|
|
774
|
+
// Do not print file contents, which may be malformed or user-controlled.
|
|
775
|
+
console.warn(`[intelligence] Could not persist learning stats at ${path} (${code}); pending increments retained`);
|
|
731
776
|
}
|
|
732
777
|
}
|
|
733
778
|
/**
|
|
@@ -1015,13 +1060,15 @@ export async function recordTrajectory(steps, verdict) {
|
|
|
1015
1060
|
const avgQuality = verdict === 'success' ? 1.0 : verdict === 'partial' ? 0.5 : 0.0;
|
|
1016
1061
|
ruvllmCoord.recordTrajectory({
|
|
1017
1062
|
steps: enrichedSteps.map(s => ({
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1063
|
+
type: ['query', 'route', 'generate', 'memory', 'feedback'].includes(s.type)
|
|
1064
|
+
? s.type : 'generate',
|
|
1065
|
+
input: s.content,
|
|
1066
|
+
output: '',
|
|
1067
|
+
durationMs: 0,
|
|
1068
|
+
confidence: avgQuality
|
|
1022
1069
|
})),
|
|
1023
1070
|
totalReward: avgQuality,
|
|
1024
|
-
|
|
1071
|
+
outcome: verdict
|
|
1025
1072
|
});
|
|
1026
1073
|
}
|
|
1027
1074
|
catch {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize cooperating local writers without stealing a paused writer's lock.
|
|
3
|
+
* Abnormal termination can leave an orphan: recovery requires confirming that
|
|
4
|
+
* no writer still owns the directory before removing it. Never age-reap it.
|
|
5
|
+
*/
|
|
6
|
+
export declare function withStatsFileLock<T>(file: string, write: (canonicalFile: string) => T): T;
|
|
7
|
+
//# sourceMappingURL=stats-file-lock.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { mkdirSync, realpathSync, rmdirSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Serialize cooperating local writers without stealing a paused writer's lock.
|
|
5
|
+
* Abnormal termination can leave an orphan: recovery requires confirming that
|
|
6
|
+
* no writer still owns the directory before removing it. Never age-reap it.
|
|
7
|
+
*/
|
|
8
|
+
export function withStatsFileLock(file, write) {
|
|
9
|
+
const canonicalFile = join(realpathSync(dirname(file)), basename(file));
|
|
10
|
+
const lock = `${canonicalFile}.lock`;
|
|
11
|
+
const deadline = performance.now() + 1000;
|
|
12
|
+
const sleeper = new Int32Array(new SharedArrayBuffer(4));
|
|
13
|
+
for (;;) {
|
|
14
|
+
try {
|
|
15
|
+
mkdirSync(lock, { mode: 0o700 });
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (error.code !== 'EEXIST')
|
|
20
|
+
throw error;
|
|
21
|
+
const remaining = deadline - performance.now();
|
|
22
|
+
if (remaining <= 0) {
|
|
23
|
+
throw Object.assign(new Error('Learning stats lock is busy'), { code: 'ELOCKED', path: lock });
|
|
24
|
+
}
|
|
25
|
+
Atomics.wait(sleeper, 0, 0, Math.min(10, remaining));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const cleanup = () => {
|
|
29
|
+
// Only remove our empty directory. Never recursively remove foreign data.
|
|
30
|
+
rmdirSync(lock);
|
|
31
|
+
};
|
|
32
|
+
const onExit = () => {
|
|
33
|
+
try {
|
|
34
|
+
cleanup();
|
|
35
|
+
}
|
|
36
|
+
catch { /* abnormal exits may require deliberate recovery */ }
|
|
37
|
+
};
|
|
38
|
+
process.once('exit', onExit);
|
|
39
|
+
try {
|
|
40
|
+
return write(canonicalFile);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
process.removeListener('exit', onExit);
|
|
44
|
+
try {
|
|
45
|
+
cleanup();
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const code = error.code || 'UNKNOWN';
|
|
49
|
+
console.warn(`[intelligence] Could not release learning stats lock at ${lock} (${code}); verify ownership before recovery`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=stats-file-lock.js.map
|