@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
319 lines (318 loc) • 9.41 kB
JavaScript
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
};