UNPKG

@stackmemoryai/stackmemory

Version:

Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.

320 lines (319 loc) 9.45 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); class WorkflowTemplates { frameManager; constructor(frameManager) { this.frameManager = frameManager; } /** * TDD Workflow: Red → Green → Refactor */ static TDD = { name: "tdd", description: "Test-Driven Development workflow", phases: [ { name: "write-failing-tests", requiredOutputs: ["test_file", "test_count"], validationRules: [(frame) => frame.metadata?.tests_failing === true] }, { name: "implement-minimal", requiredOutputs: ["implementation_file"], validationRules: [(frame) => frame.metadata?.tests_passing === true] }, { name: "refactor", requiredOutputs: ["refactored_files"], validationRules: [ (frame) => frame.metadata?.tests_passing === true, (frame) => frame.metadata?.complexity_reduced === true ], autoTransition: true } ] }; /** * Feature Development Workflow */ static FEATURE = { name: "feature", description: "Feature development workflow", phases: [ { name: "research", requiredOutputs: ["requirements", "constraints", "dependencies"], validationRules: [ (frame) => frame.metadata?.research_complete === true ] }, { name: "design", requiredOutputs: ["architecture_decision", "api_design"], validationRules: [(frame) => frame.metadata?.design_reviewed === true] }, { name: "implement", requiredOutputs: ["implementation_files", "tests"], validationRules: [ (frame) => frame.metadata?.tests_passing === true, (frame) => frame.metadata?.lint_passing === true ] }, { name: "validate", requiredOutputs: ["test_results", "performance_metrics"], validationRules: [ (frame) => frame.metadata?.validation_complete === true ], autoTransition: true } ] }; /** * Bug Fix Workflow */ static BUGFIX = { name: "bugfix", description: "Bug fixing workflow", phases: [ { name: "reproduce", requiredOutputs: ["reproduction_steps", "failing_test"], validationRules: [(frame) => frame.metadata?.bug_reproduced === true] }, { name: "diagnose", requiredOutputs: ["root_cause", "affected_code"], validationRules: [(frame) => frame.metadata?.cause_identified === true] }, { name: "fix", requiredOutputs: ["fix_commits", "updated_tests"], validationRules: [(frame) => frame.metadata?.fix_applied === true] }, { name: "verify", requiredOutputs: ["verification_results", "regression_tests"], validationRules: [ (frame) => frame.metadata?.bug_fixed === true, (frame) => frame.metadata?.no_regressions === true ], autoTransition: true } ] }; /** * Refactoring Workflow */ static REFACTOR = { name: "refactor", description: "Code refactoring workflow", phases: [ { name: "analyze", requiredOutputs: [ "code_metrics", "smell_detection", "complexity_report" ], validationRules: [ (frame) => frame.metadata?.analysis_complete === true ] }, { name: "plan", requiredOutputs: ["refactor_plan", "risk_assessment"], validationRules: [(frame) => frame.metadata?.plan_approved === true] }, { name: "refactor", requiredOutputs: ["refactored_code", "preserved_tests"], validationRules: [(frame) => frame.metadata?.tests_passing === true] }, { name: "validate", requiredOutputs: ["before_after_metrics", "performance_comparison"], validationRules: [ (frame) => frame.metadata?.metrics_improved === true, (frame) => frame.metadata?.behavior_preserved === true ], autoTransition: true } ] }; /** * Start a workflow, creating the parent frame and first phase frame */ async startWorkflow(template, parentFrameId) { const workflowFrame = await this.frameManager.push( { type: "workflow", description: `${template.name} workflow`, metadata: { workflow: template.name, current_phase: 0, phases: template.phases.map((p) => p.name), started_at: (/* @__PURE__ */ new Date()).toISOString() } }, parentFrameId ); await this.startPhase(workflowFrame.id, 0); return workflowFrame; } /** * Transition to next phase if current phase is complete */ async transitionPhase(frameId) { const frame = await this.frameManager.getFrame(frameId); if (!frame || frame.type !== "workflow") return false; const currentPhase = frame.metadata?.current_phase || 0; const template = this.getTemplate(frame.metadata?.workflow); if (!template) return false; const phaseFrame = await this.getCurrentPhaseFrame(frameId); if (!phaseFrame) return false; const phase = template.phases[currentPhase]; const isComplete = await this.validatePhase(phaseFrame, phase); if (!isComplete) { console.log(`Phase ${phase.name} validation failed`); return false; } await this.frameManager.close(phaseFrame.id, { completed: true, phase: phase.name }); if (currentPhase >= template.phases.length - 1) { await this.frameManager.close(frameId, { workflow_complete: true, completed_at: (/* @__PURE__ */ new Date()).toISOString() }); return true; } await this.frameManager.updateMetadata(frameId, { current_phase: currentPhase + 1 }); await this.startPhase(frameId, currentPhase + 1); return true; } /** * Start a specific phase within a workflow */ async startPhase(workflowFrameId, phaseIndex) { const frame = await this.frameManager.getFrame(workflowFrameId); const template = this.getTemplate(frame?.metadata?.workflow); if (!template || phaseIndex >= template.phases.length) { throw new Error("Invalid phase index"); } const phase = template.phases[phaseIndex]; return await this.frameManager.push( { type: "phase", description: `Phase: ${phase.name}`, metadata: { phase_name: phase.name, phase_index: phaseIndex, required_outputs: phase.requiredOutputs, started_at: (/* @__PURE__ */ new Date()).toISOString() } }, workflowFrameId ); } /** * Validate a phase frame against its requirements */ async validatePhase(frame, phase) { if (phase.requiredOutputs) { for (const output of phase.requiredOutputs) { if (!frame.metadata?.[output]) { return false; } } } if (phase.validationRules) { for (const rule of phase.validationRules) { if (!rule(frame)) { return false; } } } return true; } /** * Get current phase frame for a workflow */ async getCurrentPhaseFrame(workflowFrameId) { const children = await this.frameManager.getChildren(workflowFrameId); return children.find((f) => f.type === "phase" && f.status === "open") || null; } /** * Get template by name */ getTemplate(name) { if (!name) return null; const templates = { tdd: WorkflowTemplates.TDD, feature: WorkflowTemplates.FEATURE, bugfix: WorkflowTemplates.BUGFIX, refactor: WorkflowTemplates.REFACTOR }; return templates[name] || null; } /** * List available workflow templates */ static listTemplates() { return [ WorkflowTemplates.TDD, WorkflowTemplates.FEATURE, WorkflowTemplates.BUGFIX, WorkflowTemplates.REFACTOR ]; } } const workflowTemplates = { tdd: { name: "Test-Driven Development", description: "Write tests first, then implement", phases: [ { name: "write-failing-tests", description: "Write tests that fail" }, { name: "implement-code", description: "Make tests pass" }, { name: "refactor", description: "Clean up code" } ] }, feature: { name: "Feature Development", description: "Develop a new feature", phases: [ { name: "design", description: "Design the feature" }, { name: "implement", description: "Build the feature" }, { name: "test", description: "Test the feature" } ] }, bugfix: { name: "Bug Fix", description: "Fix a reported bug", phases: [ { name: "reproduce", description: "Reproduce the bug" }, { name: "fix", description: "Fix the bug" }, { name: "verify", description: "Verify the fix" } ] }, refactor: { name: "Refactoring", description: "Improve code structure", phases: [ { name: "analyze", description: "Analyze current code" }, { name: "refactor", description: "Refactor code" }, { name: "test", description: "Ensure no regressions" } ] } }; export { WorkflowTemplates, workflowTemplates }; //# sourceMappingURL=workflow-templates.js.map