moflo 4.5.0 → 4.6.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/package.json +1 -1
- package/src/@claude-flow/cli/dist/src/commands/appliance.js +12 -12
- package/src/@claude-flow/cli/dist/src/commands/benchmark.js +2 -2
- package/src/@claude-flow/cli/dist/src/commands/claims.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/config.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/daemon.js +25 -3
- package/src/@claude-flow/cli/dist/src/commands/deployment.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/doctor.js +23 -6
- package/src/@claude-flow/cli/dist/src/commands/embeddings.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/hooks.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/init.js +14 -12
- package/src/@claude-flow/cli/dist/src/commands/neural.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/orc.d.ts +2 -2
- package/src/@claude-flow/cli/dist/src/commands/orc.js +12 -12
- package/src/@claude-flow/cli/dist/src/commands/performance.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/plugins.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/providers.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/security.js +1 -1
- package/src/@claude-flow/cli/dist/src/commands/start.js +11 -11
- package/src/@claude-flow/cli/dist/src/commands/status.js +3 -3
- package/src/@claude-flow/cli/dist/src/commands/transfer-store.js +1 -1
- package/src/@claude-flow/cli/dist/src/config/moflo-config.d.ts +30 -0
- package/src/@claude-flow/cli/dist/src/config/moflo-config.js +103 -7
- package/src/@claude-flow/cli/dist/src/index.d.ts +1 -1
- package/src/@claude-flow/cli/dist/src/index.js +3 -3
- package/src/@claude-flow/cli/dist/src/init/claudemd-generator.js +1 -1
- package/src/@claude-flow/cli/dist/src/init/executor.js +485 -472
- package/src/@claude-flow/cli/dist/src/init/helpers-generator.js +640 -640
- package/src/@claude-flow/cli/dist/src/init/moflo-init.js +530 -66
- package/src/@claude-flow/cli/dist/src/init/settings-generator.js +7 -12
- package/src/@claude-flow/cli/dist/src/init/statusline-generator.d.ts +1 -1
- package/src/@claude-flow/cli/dist/src/init/statusline-generator.js +784 -784
- package/src/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js +12 -12
- package/src/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +122 -66
- package/src/@claude-flow/cli/dist/src/memory/intelligence.js +5 -1
- package/src/@claude-flow/cli/dist/src/memory/memory-initializer.d.ts +1 -1
- package/src/@claude-flow/cli/dist/src/memory/memory-initializer.js +371 -371
- package/src/@claude-flow/cli/dist/src/parser.d.ts +10 -0
- package/src/@claude-flow/cli/dist/src/parser.js +49 -3
- package/src/@claude-flow/cli/dist/src/plugins/store/discovery.js +1 -1
- package/src/@claude-flow/cli/dist/src/runtime/headless.js +30 -30
- package/src/@claude-flow/cli/dist/src/services/claim-service.js +1 -1
- package/src/@claude-flow/cli/dist/src/services/ruvector-training.js +11 -5
- package/src/@claude-flow/cli/dist/src/services/workflow-gate.d.ts +13 -3
- package/src/@claude-flow/cli/dist/src/services/workflow-gate.js +73 -5
- package/src/@claude-flow/cli/dist/src/types.d.ts +1 -1
- package/src/@claude-flow/cli/dist/src/types.js +1 -1
|
@@ -32,6 +32,16 @@ export declare class CommandParser {
|
|
|
32
32
|
private parseValue;
|
|
33
33
|
private normalizeKey;
|
|
34
34
|
private buildAliases;
|
|
35
|
+
/**
|
|
36
|
+
* Build aliases scoped to a specific command/subcommand.
|
|
37
|
+
* The resolved command's short flags take priority over global ones,
|
|
38
|
+
* fixing collisions where multiple subcommands use the same short flag (e.g. -t).
|
|
39
|
+
*/
|
|
40
|
+
private buildScopedAliases;
|
|
41
|
+
/**
|
|
42
|
+
* Get boolean flags scoped to a specific command/subcommand.
|
|
43
|
+
*/
|
|
44
|
+
private getScopedBooleanFlags;
|
|
35
45
|
private getBooleanFlags;
|
|
36
46
|
private applyDefaults;
|
|
37
47
|
validateFlags(flags: ParsedFlags, command?: Command): string[];
|
|
@@ -101,9 +101,23 @@ export class CommandParser {
|
|
|
101
101
|
positional: [],
|
|
102
102
|
raw: [...args]
|
|
103
103
|
};
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
// Pass 1: Identify command and subcommand (skip flags)
|
|
105
|
+
let resolvedCmd;
|
|
106
|
+
let resolvedSub;
|
|
107
|
+
for (const arg of args) {
|
|
108
|
+
if (arg.startsWith('-'))
|
|
109
|
+
continue;
|
|
110
|
+
if (!resolvedCmd && this.commands.has(arg)) {
|
|
111
|
+
resolvedCmd = this.commands.get(arg);
|
|
112
|
+
}
|
|
113
|
+
else if (resolvedCmd && !resolvedSub && resolvedCmd.subcommands) {
|
|
114
|
+
resolvedSub = resolvedCmd.subcommands.find(sc => sc.name === arg || sc.aliases?.includes(arg));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Pass 2: Build aliases scoped to the resolved subcommand
|
|
118
|
+
// Subcommand-specific aliases take priority over global ones
|
|
119
|
+
const aliases = this.buildScopedAliases(resolvedSub || resolvedCmd);
|
|
120
|
+
const booleanFlags = this.getScopedBooleanFlags(resolvedSub || resolvedCmd);
|
|
107
121
|
let i = 0;
|
|
108
122
|
let parsingFlags = true;
|
|
109
123
|
while (i < args.length) {
|
|
@@ -275,6 +289,38 @@ export class CommandParser {
|
|
|
275
289
|
}
|
|
276
290
|
return { ...aliases, ...this.options.aliases };
|
|
277
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* Build aliases scoped to a specific command/subcommand.
|
|
294
|
+
* The resolved command's short flags take priority over global ones,
|
|
295
|
+
* fixing collisions where multiple subcommands use the same short flag (e.g. -t).
|
|
296
|
+
*/
|
|
297
|
+
buildScopedAliases(resolvedCmd) {
|
|
298
|
+
// Start with global aliases as base
|
|
299
|
+
const aliases = this.buildAliases();
|
|
300
|
+
// Override with the resolved command's own options (these take priority)
|
|
301
|
+
if (resolvedCmd?.options) {
|
|
302
|
+
for (const opt of resolvedCmd.options) {
|
|
303
|
+
if (opt.short) {
|
|
304
|
+
aliases[opt.short] = opt.name;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return aliases;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Get boolean flags scoped to a specific command/subcommand.
|
|
312
|
+
*/
|
|
313
|
+
getScopedBooleanFlags(resolvedCmd) {
|
|
314
|
+
const flags = this.getBooleanFlags();
|
|
315
|
+
if (resolvedCmd?.options) {
|
|
316
|
+
for (const opt of resolvedCmd.options) {
|
|
317
|
+
if (opt.type === 'boolean') {
|
|
318
|
+
flags.add(this.normalizeKey(opt.name));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return flags;
|
|
323
|
+
}
|
|
278
324
|
getBooleanFlags() {
|
|
279
325
|
const flags = new Set();
|
|
280
326
|
for (const opt of this.globalOptions) {
|
|
@@ -491,7 +491,7 @@ export class PluginDiscoveryService {
|
|
|
491
491
|
id: '@claude-flow/plugins',
|
|
492
492
|
name: '@claude-flow/plugins',
|
|
493
493
|
displayName: 'Plugin SDK',
|
|
494
|
-
description: 'Unified Plugin SDK for
|
|
494
|
+
description: 'Unified Plugin SDK for MoFlo V4 - Worker, Hook, and Provider Integration. Create, test, and publish MoFlo plugins.',
|
|
495
495
|
version: '3.0.0-alpha.2',
|
|
496
496
|
cid: 'bafybeipluginsdk2024xyz',
|
|
497
497
|
size: 156000,
|
|
@@ -62,34 +62,34 @@ function parseArgs() {
|
|
|
62
62
|
* Show help message
|
|
63
63
|
*/
|
|
64
64
|
function showHelp() {
|
|
65
|
-
console.log(`
|
|
66
|
-
Headless Runtime for
|
|
67
|
-
|
|
68
|
-
Usage:
|
|
69
|
-
headless --worker <type> Run a specific worker
|
|
70
|
-
headless --daemon Start background daemon
|
|
71
|
-
headless --benchmark Run performance benchmarks
|
|
72
|
-
headless --status Show system status
|
|
73
|
-
|
|
74
|
-
Workers: ${HEADLESS_WORKER_TYPES.join(', ')}
|
|
75
|
-
|
|
76
|
-
Options:
|
|
77
|
-
-w, --worker <type> Worker type to run
|
|
78
|
-
-d, --daemon Run as daemon
|
|
79
|
-
-b, --benchmark Run benchmarks
|
|
80
|
-
-s, --status Show status
|
|
81
|
-
-t, --timeout <ms> Execution timeout (default: 60000)
|
|
82
|
-
-v, --verbose Verbose output
|
|
83
|
-
-h, --help Show help
|
|
84
|
-
|
|
85
|
-
Environment:
|
|
86
|
-
CLAUDE_FLOW_HEADLESS=true Enable headless mode
|
|
87
|
-
CLAUDE_CODE_HEADLESS=true Enable Claude Code headless
|
|
88
|
-
|
|
89
|
-
Examples:
|
|
90
|
-
headless --worker audit --timeout 120000
|
|
91
|
-
headless --daemon
|
|
92
|
-
headless --benchmark
|
|
65
|
+
console.log(`
|
|
66
|
+
Headless Runtime for MoFlo V4
|
|
67
|
+
|
|
68
|
+
Usage:
|
|
69
|
+
headless --worker <type> Run a specific worker
|
|
70
|
+
headless --daemon Start background daemon
|
|
71
|
+
headless --benchmark Run performance benchmarks
|
|
72
|
+
headless --status Show system status
|
|
73
|
+
|
|
74
|
+
Workers: ${HEADLESS_WORKER_TYPES.join(', ')}
|
|
75
|
+
|
|
76
|
+
Options:
|
|
77
|
+
-w, --worker <type> Worker type to run
|
|
78
|
+
-d, --daemon Run as daemon
|
|
79
|
+
-b, --benchmark Run benchmarks
|
|
80
|
+
-s, --status Show status
|
|
81
|
+
-t, --timeout <ms> Execution timeout (default: 60000)
|
|
82
|
+
-v, --verbose Verbose output
|
|
83
|
+
-h, --help Show help
|
|
84
|
+
|
|
85
|
+
Environment:
|
|
86
|
+
CLAUDE_FLOW_HEADLESS=true Enable headless mode
|
|
87
|
+
CLAUDE_CODE_HEADLESS=true Enable Claude Code headless
|
|
88
|
+
|
|
89
|
+
Examples:
|
|
90
|
+
headless --worker audit --timeout 120000
|
|
91
|
+
headless --daemon
|
|
92
|
+
headless --benchmark
|
|
93
93
|
`);
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
@@ -150,7 +150,7 @@ async function runDaemon() {
|
|
|
150
150
|
* Run benchmarks
|
|
151
151
|
*/
|
|
152
152
|
async function runBenchmarks() {
|
|
153
|
-
console.log('===
|
|
153
|
+
console.log('=== MoFlo V4 Performance Benchmarks ===\n');
|
|
154
154
|
// Initialize intelligence
|
|
155
155
|
await initializeIntelligence();
|
|
156
156
|
// SONA Benchmark
|
|
@@ -216,7 +216,7 @@ async function runBenchmarks() {
|
|
|
216
216
|
* Show system status
|
|
217
217
|
*/
|
|
218
218
|
async function showStatus() {
|
|
219
|
-
console.log('===
|
|
219
|
+
console.log('=== MoFlo V4 System Status ===\n');
|
|
220
220
|
// Check daemon
|
|
221
221
|
const daemon = getDaemon();
|
|
222
222
|
console.log('Daemon:');
|
|
@@ -675,7 +675,7 @@ export class GitHubSync {
|
|
|
675
675
|
const claimantStr = claimant.type === 'human'
|
|
676
676
|
? `@${claimant.name.replace(/[^a-zA-Z0-9_-]/g, '')}`
|
|
677
677
|
: `Agent: ${(claimant.agentType || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '')}`;
|
|
678
|
-
const comment = `🤖 **Issue claimed** by ${claimantStr}\n\n_Coordinated by
|
|
678
|
+
const comment = `🤖 **Issue claimed** by ${claimantStr}\n\n_Coordinated by MoFlo V4_`;
|
|
679
679
|
try {
|
|
680
680
|
execFileSync('gh', [
|
|
681
681
|
'issue', 'comment', String(issueNumber),
|
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Created with ❤️ by motailz.com
|
|
15
15
|
*/
|
|
16
|
+
/**
|
|
17
|
+
* ESM/CJS interop helper — handles `.default` for CJS modules.
|
|
18
|
+
* Uses `'default' in mod` check which is safer than `mod.default || mod`.
|
|
19
|
+
*/
|
|
20
|
+
async function importWithInterop(packageName) {
|
|
21
|
+
const mod = await import(packageName);
|
|
22
|
+
return ('default' in mod) ? mod.default : mod;
|
|
23
|
+
}
|
|
16
24
|
// Lazy-loaded WASM modules
|
|
17
25
|
let microLoRA = null;
|
|
18
26
|
let scopedLoRA = null;
|
|
@@ -62,7 +70,7 @@ export async function initializeTraining(config = {}) {
|
|
|
62
70
|
trajectoryBuffer = new learningWasm.WasmTrajectoryBuffer(config.trajectoryCapacity || 10000, dim);
|
|
63
71
|
features.push('TrajectoryBuffer');
|
|
64
72
|
// Initialize attention mechanisms
|
|
65
|
-
const attention = await
|
|
73
|
+
const attention = await importWithInterop('@ruvector/attention');
|
|
66
74
|
if (config.useFlashAttention !== false) {
|
|
67
75
|
flashAttention = new attention.FlashAttention(dim, 64);
|
|
68
76
|
features.push('FlashAttention');
|
|
@@ -96,10 +104,8 @@ export async function initializeTraining(config = {}) {
|
|
|
96
104
|
// Initialize SONA (optional, backward compatible)
|
|
97
105
|
if (config.useSona !== false) {
|
|
98
106
|
try {
|
|
99
|
-
const sona = await
|
|
107
|
+
const sona = await importWithInterop('@ruvector/sona');
|
|
100
108
|
const sonaRank = config.sonaRank || 4;
|
|
101
|
-
// SonaEngine constructor: (dim, rank, alpha, learningRate) - TypeScript types are wrong
|
|
102
|
-
// @ts-expect-error - SonaEngine accepts 4 positional args but types say 1
|
|
103
109
|
sonaEngine = new sona.SonaEngine(dim, sonaRank, alpha, lr);
|
|
104
110
|
sonaAvailable = true;
|
|
105
111
|
features.push(`SONA (${dim}-dim, rank-${sonaRank}, 624k learn/s)`);
|
|
@@ -291,7 +297,7 @@ export function mineHardNegatives(anchor, candidates) {
|
|
|
291
297
|
* Benchmark the training system
|
|
292
298
|
*/
|
|
293
299
|
export async function benchmarkTraining(dim, iterations) {
|
|
294
|
-
const attention = await
|
|
300
|
+
const attention = await importWithInterop('@ruvector/attention');
|
|
295
301
|
lastBenchmark = attention.benchmarkAttention(dim || 256, 100, iterations || 1000);
|
|
296
302
|
return lastBenchmark ?? [];
|
|
297
303
|
}
|
|
@@ -19,6 +19,7 @@ export interface WorkflowState {
|
|
|
19
19
|
tasksCreated: boolean;
|
|
20
20
|
taskCount: number;
|
|
21
21
|
memorySearched: boolean;
|
|
22
|
+
memoryRequired: boolean;
|
|
22
23
|
interactionCount: number;
|
|
23
24
|
sessionStart: string | null;
|
|
24
25
|
lastBlockedAt: string | null;
|
|
@@ -42,7 +43,8 @@ export declare class WorkflowGateService {
|
|
|
42
43
|
checkBeforeAgent(): GateResult;
|
|
43
44
|
/**
|
|
44
45
|
* Check if Glob/Grep is allowed.
|
|
45
|
-
*
|
|
46
|
+
* Blocks if memory is required AND not yet searched.
|
|
47
|
+
* Warns (but allows) if memory is not required.
|
|
46
48
|
*/
|
|
47
49
|
checkBeforeScan(pattern?: string, searchPath?: string): GateResult;
|
|
48
50
|
/**
|
|
@@ -57,11 +59,19 @@ export declare class WorkflowGateService {
|
|
|
57
59
|
* If so, auto-record memory as searched.
|
|
58
60
|
*/
|
|
59
61
|
checkBashMemory(command: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Classify whether a user prompt requires memory search.
|
|
64
|
+
* Directives (commit, rename, yes/no) don't need memory.
|
|
65
|
+
* Tasks (fix, implement, debug, /flo) do.
|
|
66
|
+
* Ambiguous prompts default to requiring memory.
|
|
67
|
+
*/
|
|
68
|
+
classifyPrompt(prompt: string): boolean;
|
|
60
69
|
/**
|
|
61
70
|
* Called on each new user prompt.
|
|
62
|
-
*
|
|
71
|
+
* Classifies prompt, resets memory gate, increments interaction count,
|
|
72
|
+
* returns context bracket.
|
|
63
73
|
*/
|
|
64
|
-
promptReminder(): {
|
|
74
|
+
promptReminder(userPrompt?: string): {
|
|
65
75
|
reminder?: string;
|
|
66
76
|
bracket?: string;
|
|
67
77
|
};
|
|
@@ -25,10 +25,41 @@ const DEFAULT_STATE = {
|
|
|
25
25
|
tasksCreated: false,
|
|
26
26
|
taskCount: 0,
|
|
27
27
|
memorySearched: false,
|
|
28
|
+
memoryRequired: true,
|
|
28
29
|
interactionCount: 0,
|
|
29
30
|
sessionStart: null,
|
|
30
31
|
lastBlockedAt: null,
|
|
31
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Patterns that indicate the prompt is a task requiring memory context.
|
|
35
|
+
* These are checked case-insensitively against the user's prompt.
|
|
36
|
+
*/
|
|
37
|
+
const TASK_PATTERNS = [
|
|
38
|
+
/\bfix\b/, /\bbug\b/, /\berror\b/, /\bfailing\b/, /\bbroken\b/, /\bcrash/,
|
|
39
|
+
/\bimplement\b/, /\badd\b/, /\bcreate\b/, /\bbuild\b/, /\bwrite\b/,
|
|
40
|
+
/\brefactor\b/, /\bmigrat/, /\bupgrade\b/, /\bupdate\b/,
|
|
41
|
+
/\bdebug\b/, /\binvestigat/, /\bdiagnos/, /\btroubleshoot/,
|
|
42
|
+
/\bwhy\s+(is|does|did|are|was|isn't|doesn't|won't)/, /\bhow\s+(do|does|did|can|should)/,
|
|
43
|
+
/\btest\b/, /\bspec\b/,
|
|
44
|
+
/\bfeature\b/, /\bstory\b/, /\bticket\b/, /\bissue\b/,
|
|
45
|
+
/\bintegrat/, /\bconnect\b/, /\bsetup\b/, /\bconfigur/,
|
|
46
|
+
/\boptimiz/, /\bperformance\b/, /\bslow\b/,
|
|
47
|
+
/\bsecurity\b/, /\bvulnerab/, /\bauth\b/,
|
|
48
|
+
/^\/flo\b/, /^\/fl\b/, /^\/cl\b/, // Skill invocations always require memory
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Patterns that indicate the prompt is a simple directive (no memory needed).
|
|
52
|
+
* Checked first — if matched, memory gate is skipped regardless of task patterns.
|
|
53
|
+
*/
|
|
54
|
+
const DIRECTIVE_PATTERNS = [
|
|
55
|
+
/^(yes|no|yeah|yep|nope|sure|ok|okay|correct|right|exactly|perfect)\b/i,
|
|
56
|
+
/\b(commit|push|pull|merge|rebase|cherry-pick)\b/,
|
|
57
|
+
/\b(rename|move|delete|remove)\b/,
|
|
58
|
+
/^(show|read|open|cat|look at|check)\s/,
|
|
59
|
+
/^(run|execute|start|stop|kill|restart)\s/,
|
|
60
|
+
/\bpublish\b/, /\bversion\b/, /\bnpm\b/,
|
|
61
|
+
/^let'?s\s+(commit|push|publish|deploy|ship|merge)/i,
|
|
62
|
+
];
|
|
32
63
|
const BRACKET_MESSAGES = {
|
|
33
64
|
MODERATE: 'Context: MODERATE. Re-state goal before architectural decisions. Use agents for >300 LOC.',
|
|
34
65
|
DEPLETED: 'Context: DEPLETED. Checkpoint progress. Recommend /compact or fresh session.',
|
|
@@ -119,7 +150,8 @@ export class WorkflowGateService {
|
|
|
119
150
|
}
|
|
120
151
|
/**
|
|
121
152
|
* Check if Glob/Grep is allowed.
|
|
122
|
-
*
|
|
153
|
+
* Blocks if memory is required AND not yet searched.
|
|
154
|
+
* Warns (but allows) if memory is not required.
|
|
123
155
|
*/
|
|
124
156
|
checkBeforeScan(pattern, searchPath) {
|
|
125
157
|
if (!this.config.memory_first) {
|
|
@@ -134,7 +166,11 @@ export class WorkflowGateService {
|
|
|
134
166
|
if (EXEMPT_PATTERNS.some(p => target.includes(p))) {
|
|
135
167
|
return { allowed: true };
|
|
136
168
|
}
|
|
137
|
-
//
|
|
169
|
+
// If memory is not required for this prompt, warn but allow
|
|
170
|
+
if (!state.memoryRequired) {
|
|
171
|
+
return { allowed: true };
|
|
172
|
+
}
|
|
173
|
+
// Memory IS required — block with deduplicated message
|
|
138
174
|
const now = Date.now();
|
|
139
175
|
const lastBlocked = state.lastBlockedAt ? new Date(state.lastBlockedAt).getTime() : 0;
|
|
140
176
|
let message;
|
|
@@ -161,6 +197,10 @@ export class WorkflowGateService {
|
|
|
161
197
|
if (!filePath?.includes('.claude/guidance/') && !filePath?.includes('.claude\\guidance\\')) {
|
|
162
198
|
return { allowed: true };
|
|
163
199
|
}
|
|
200
|
+
// If memory is not required for this prompt, allow guidance reads
|
|
201
|
+
if (!state.memoryRequired) {
|
|
202
|
+
return { allowed: true };
|
|
203
|
+
}
|
|
164
204
|
// Deduplicate
|
|
165
205
|
const now = Date.now();
|
|
166
206
|
const lastBlocked = state.lastBlockedAt ? new Date(state.lastBlockedAt).getTime() : 0;
|
|
@@ -198,13 +238,40 @@ export class WorkflowGateService {
|
|
|
198
238
|
// --------------------------------------------------------------------------
|
|
199
239
|
// Session lifecycle
|
|
200
240
|
// --------------------------------------------------------------------------
|
|
241
|
+
/**
|
|
242
|
+
* Classify whether a user prompt requires memory search.
|
|
243
|
+
* Directives (commit, rename, yes/no) don't need memory.
|
|
244
|
+
* Tasks (fix, implement, debug, /flo) do.
|
|
245
|
+
* Ambiguous prompts default to requiring memory.
|
|
246
|
+
*/
|
|
247
|
+
classifyPrompt(prompt) {
|
|
248
|
+
const trimmed = prompt.trim();
|
|
249
|
+
// Empty or very short prompts (single word confirmations) — no memory needed
|
|
250
|
+
if (trimmed.length < 4)
|
|
251
|
+
return false;
|
|
252
|
+
// Check directive patterns first — these never need memory
|
|
253
|
+
for (const pattern of DIRECTIVE_PATTERNS) {
|
|
254
|
+
if (pattern.test(trimmed))
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
// Check task patterns — these always need memory
|
|
258
|
+
for (const pattern of TASK_PATTERNS) {
|
|
259
|
+
if (pattern.test(trimmed))
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
// Ambiguous: if the prompt is long (likely a task description), require memory
|
|
263
|
+
// Short ambiguous prompts (follow-ups) don't need it
|
|
264
|
+
return trimmed.length > 80;
|
|
265
|
+
}
|
|
201
266
|
/**
|
|
202
267
|
* Called on each new user prompt.
|
|
203
|
-
*
|
|
268
|
+
* Classifies prompt, resets memory gate, increments interaction count,
|
|
269
|
+
* returns context bracket.
|
|
204
270
|
*/
|
|
205
|
-
promptReminder() {
|
|
271
|
+
promptReminder(userPrompt) {
|
|
206
272
|
const state = this.readState();
|
|
207
273
|
state.memorySearched = false;
|
|
274
|
+
state.memoryRequired = userPrompt ? this.classifyPrompt(userPrompt) : true;
|
|
208
275
|
state.interactionCount = (state.interactionCount || 0) + 1;
|
|
209
276
|
this.writeState(state);
|
|
210
277
|
const result = {};
|
|
@@ -276,7 +343,8 @@ export function processGateCommand(command, env = process.env) {
|
|
|
276
343
|
gate.recordMemorySearched();
|
|
277
344
|
process.exit(0);
|
|
278
345
|
case 'prompt-reminder': {
|
|
279
|
-
const
|
|
346
|
+
const userPrompt = env.CLAUDE_USER_PROMPT || '';
|
|
347
|
+
const { reminder, bracket } = gate.promptReminder(userPrompt);
|
|
280
348
|
if (reminder)
|
|
281
349
|
console.log(reminder);
|
|
282
350
|
if (bracket)
|