UNPKG

@stackmemoryai/stackmemory

Version:

Lossless, project-scoped memory for AI coding tools. Durable context across sessions with 56 MCP tools, FTS5 search, conductor orchestrator, loop/watch monitoring, snapshot capture, pre-flight overlap checks, Claude/Codex/OpenCode wrappers, Linear sync, a

88 lines (87 loc) 3.07 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import { Command } from "commander"; import chalk from "chalk"; import { PreflightChecker } from "../../core/worktree/preflight.js"; function createPreflightCommand() { const cmd = new Command("preflight").alias("pf").description("Check file overlap before running parallel tasks").argument("<tasks...>", "Task descriptions (quoted strings)").option( "-k, --keywords <keywords>", "Comma-separated keywords per task (task1:kw1,kw2;task2:kw3)" ).option( "-f, --files <files>", "Comma-separated files per task (task1:file1,file2;task2:file3)" ).option("--json", "Output as JSON").action((taskArgs, options) => { const checker = new PreflightChecker(); const tasks = taskArgs.map((desc, i) => { const task = { name: `task-${i + 1}`, description: desc }; if (options.keywords) { const kwParts = options.keywords.split(";"); if (kwParts[i]) { const [, kws] = kwParts[i].split(":"); if (kws) task.keywords = kws.split(","); } } if (options.files) { const fileParts = options.files.split(";"); if (fileParts[i]) { const [, fs] = fileParts[i].split(":"); if (fs) task.files = fs.split(","); } } if (desc.length <= 40) { task.name = desc; } return task; }); const result = checker.check(tasks); if (options.json) { console.log(JSON.stringify(result, null, 2)); return; } console.log(chalk.cyan("\nPre-flight Check\n")); console.log(chalk.gray(`Tasks: ${tasks.length}`)); console.log(chalk.gray(`Overlaps: ${result.allOverlaps.length} `)); if (result.parallelSafe.length === 1 && result.allOverlaps.length === 0) { console.log(chalk.green("All tasks are parallel-safe.\n")); for (const task of result.parallelSafe[0]) { console.log(chalk.green(` + ${task.name}`)); } } else { for (let i = 0; i < result.parallelSafe.length; i++) { const group = result.parallelSafe[i]; console.log(chalk.cyan(`Group ${i + 1} (parallel-safe):`)); for (const task of group) { console.log(chalk.green(` + ${task.name}`)); } } } if (result.sequential.length > 0) { console.log(chalk.yellow("\nSequential (file overlaps detected):")); for (const entry of result.sequential) { console.log( chalk.yellow(` "${entry.task.name}" -> after "${entry.after}"`) ); for (const overlap of entry.overlaps.slice(0, 5)) { const conf = Math.round(overlap.confidence * 100); console.log( chalk.gray(` ${overlap.file} (${overlap.source}, ${conf}%)`) ); } } } console.log(chalk.gray(` ${result.summary}`)); }); return cmd; } export { createPreflightCommand };