refactor: simplify memory command dispatch

Split memory CLI actions into focused handlers, keep dispatch below the project function-size guideline, and strengthen install-manifest assertions for the separately installed runtime.
This commit is contained in:
Affaan Mustafa
2026-07-26 05:01:27 -04:00
parent c64875d9c6
commit 27b7c673e2
3 changed files with 78 additions and 47 deletions
+66 -45
View File
@@ -401,6 +401,67 @@ function assertMutationAllowed(command) {
}
}
function runInitCommand({ command, options, positionals, roots }) {
requireNoPositionals(positionals, command);
return printInit(
initializeVault({ roots, scopes: options.scopes || undefined }),
options.json
);
}
function runWriteCommand({ command, options, positionals, roots }) {
requireNoPositionals(positionals, command);
if (!options.title) throw new Error('--title is required.');
if (command === 'handoff' && !options.from) {
throw new Error('--from is required for handoffs.');
}
if (command === 'handoff' && (!options.targets || options.targets.length === 0)) {
throw new Error('At least one --target is required for handoffs.');
}
return printWrite(
saveMemory(saveInput(options, command === 'handoff' ? 'handoff' : null), { roots }),
options.json
);
}
function runSearchCommand({ options, positionals, roots }) {
const query = positionals.join(' ');
return printSearch(query, searchMemories(query, {
roots,
scopes: options.scopes,
kinds: options.kinds,
targetHarness: options.targetHarness,
limit: options.limit,
}), options.json);
}
function runReadCommand({ options, positionals, roots }) {
if (positionals.length !== 1) {
throw new Error('read requires exactly one memory ID.');
}
return printRead(readMemoryById(positionals[0], {
roots,
scopes: options.scopes,
}), options.json);
}
function runDoctorCommand({ command, options, positionals, roots }) {
requireNoPositionals(positionals, command);
return printDoctor(doctorMemoryVault({
roots,
scopes: options.scopes,
}), options.json);
}
const COMMAND_HANDLERS = Object.freeze({
doctor: runDoctorCommand,
handoff: runWriteCommand,
init: runInitCommand,
read: runReadCommand,
save: runWriteCommand,
search: runSearchCommand,
});
function runCommand(parsed) {
const { command, options, positionals } = parsed;
if (options.help || command === 'help') {
@@ -411,51 +472,11 @@ function runCommand(parsed) {
assertMutationAllowed(command);
}
const roots = resolveVaultRoots();
if (command === 'init') {
requireNoPositionals(positionals, command);
return printInit(
initializeVault({ roots, scopes: options.scopes || undefined }),
options.json
);
}
if (command === 'save' || command === 'handoff') {
requireNoPositionals(positionals, command);
if (!options.title) throw new Error('--title is required.');
if (command === 'handoff' && !options.from) throw new Error('--from is required for handoffs.');
if (command === 'handoff' && (!options.targets || options.targets.length === 0)) {
throw new Error('At least one --target is required for handoffs.');
}
return printWrite(
saveMemory(saveInput(options, command === 'handoff' ? 'handoff' : null), { roots }),
options.json
);
}
if (command === 'search') {
const query = positionals.join(' ');
return printSearch(query, searchMemories(query, {
roots,
scopes: options.scopes,
kinds: options.kinds,
targetHarness: options.targetHarness,
limit: options.limit,
}), options.json);
}
if (command === 'read') {
if (positionals.length !== 1) throw new Error('read requires exactly one memory ID.');
return printRead(readMemoryById(positionals[0], {
roots,
scopes: options.scopes,
}), options.json);
}
if (command === 'doctor') {
requireNoPositionals(positionals, command);
return printDoctor(doctorMemoryVault({
roots,
scopes: options.scopes,
}), options.json);
}
throw new Error(`Unknown memory command: ${command}`);
const handler = Object.hasOwn(COMMAND_HANDLERS, command)
? COMMAND_HANDLERS[command]
: null;
if (!handler) throw new Error(`Unknown memory command: ${command}`);
return handler({ command, options, positionals, roots });
}
function main(argv = process.argv.slice(2)) {
+2 -1
View File
@@ -172,13 +172,14 @@ function runTests() {
const component = getInstallComponent('skill:unified-memory');
assert.deepStrictEqual(component.moduleIds, ['skill-unified-memory']);
assert.match(component.description, /ecc-universal/i);
assert.match(component.description, /separate|external|runtime/i);
assert.match(component.description, /separate|external/i);
const modules = listInstallModules();
const singleSkillModule = modules.find(module => module.id === 'skill-unified-memory');
const workflowModule = modules.find(module => module.id === 'workflow-quality');
assert.ok(singleSkillModule, 'Should define an explicit unified-memory module');
assert.match(singleSkillModule.description, /ecc-universal/i);
assert.match(singleSkillModule.description, /separate|external/i);
assert.match(workflowModule.description, /ecc-universal/i);
const plan = resolveInstallPlan({
+10 -1
View File
@@ -8,7 +8,11 @@ const { spawnSync } = require('child_process');
const MEMORY_SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'memory.js');
const ECC_SCRIPT = path.join(__dirname, '..', '..', 'scripts', 'ecc.js');
const { readBoundedStdin, sanitizeTerminalText } = require(MEMORY_SCRIPT);
const {
readBoundedStdin,
runCommand,
sanitizeTerminalText,
} = require(MEMORY_SCRIPT);
let passed = 0;
let failed = 0;
@@ -62,6 +66,11 @@ function json(result) {
console.log('\n=== Testing ecc memory CLI ===\n');
test('keeps runCommand focused on dispatch under the function-size guideline', () => {
const lineCount = runCommand.toString().split('\n').length;
assert.ok(lineCount < 50, `runCommand is ${lineCount} lines; expected fewer than 50`);
});
test('shows memory command help directly and through the ecc router', () => {
const fixture = createFixture();
try {