@wrongstack/sdd 0.297.0 → 0.298.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/dist/index.js +32 -17
- package/dist/verify-task.d.ts +26 -4
- package/package.json +6 -5
- package/dist/auto-executor.d.ts.map +0 -1
- package/dist/board-types.d.ts.map +0 -1
- package/dist/conflict-resolver.d.ts.map +0 -1
- package/dist/critical-path.d.ts.map +0 -1
- package/dist/decompose-task.d.ts.map +0 -1
- package/dist/graph-split.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -7
- package/dist/kanban-sdd-session.d.ts.map +0 -1
- package/dist/plan-decompose.d.ts.map +0 -1
- package/dist/project-context.d.ts.map +0 -1
- package/dist/sdd-board-projector.d.ts.map +0 -1
- package/dist/sdd-board-store.d.ts.map +0 -1
- package/dist/sdd-interview-driver.d.ts.map +0 -1
- package/dist/sdd-lifecycle.d.ts.map +0 -1
- package/dist/sdd-parallel-run-types.d.ts.map +0 -1
- package/dist/sdd-parallel-run.d.ts.map +0 -1
- package/dist/sdd-run-registry.d.ts.map +0 -1
- package/dist/sdd-session-types.d.ts.map +0 -1
- package/dist/sdd-supervisor.d.ts.map +0 -1
- package/dist/sdd-task-decomposer.d.ts.map +0 -1
- package/dist/sdd-task-execution.d.ts.map +0 -1
- package/dist/spec-builder.d.ts.map +0 -1
- package/dist/spec-parser.d.ts.map +0 -1
- package/dist/spec-store.d.ts.map +0 -1
- package/dist/spec-templates.d.ts.map +0 -1
- package/dist/spec-versioning.d.ts.map +0 -1
- package/dist/start-sdd-run.d.ts.map +0 -1
- package/dist/task-flow.d.ts.map +0 -1
- package/dist/task-generator.d.ts.map +0 -1
- package/dist/task-graph-store.d.ts.map +0 -1
- package/dist/task-tracker.d.ts.map +0 -1
- package/dist/task-visualizer.d.ts.map +0 -1
- package/dist/verify-task.d.ts.map +0 -1
package/dist/index.js.map
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/spec-parser.ts", "../src/task-generator.ts", "../src/index.ts", "../src/task-flow.ts", "../src/spec-store.ts", "../src/task-graph-store.ts", "../src/board-types.ts", "../src/sdd-board-store.ts", "../src/sdd-board-projector.ts", "../src/sdd-run-registry.ts", "../src/sdd-interview-driver.ts", "../src/spec-builder.ts", "../src/sdd-session-types.ts", "../src/start-sdd-run.ts", "../src/sdd-parallel-run.ts", "../src/graph-split.ts", "../src/sdd-task-execution.ts", "../src/sdd-task-decomposer.ts", "../src/sdd-lifecycle.ts", "../src/kanban-sdd-session.ts", "../src/project-context.ts", "../src/spec-templates.ts", "../src/task-visualizer.ts", "../src/critical-path.ts", "../src/spec-versioning.ts", "../src/auto-executor.ts", "../src/sdd-supervisor.ts", "../src/verify-task.ts", "../src/decompose-task.ts", "../src/plan-decompose.ts", "../src/conflict-resolver.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n SpecAnalysis,\n Specification,\n SpecRequirement,\n SpecSection,\n SpecValidationResult,\n} from '@wrongstack/core/types';\n\nexport class SpecParser {\n parse(content: string): Specification {\n const lines = content.split('\\n');\n const sections = this.extractSections(lines);\n const requirements = this.extractRequirements(lines);\n const now = Date.now();\n\n return {\n id: crypto.randomUUID(),\n title: this.extractTitle(lines),\n version: this.extractVersion(lines),\n status: 'draft',\n overview: this.extractOverview(lines),\n sections,\n requirements,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n private extractTitle(lines: string[]): string {\n for (const line of lines) {\n const m = /^#\\s+(.+)/.exec(line.trim());\n if (m?.[1]) return m[1];\n }\n return 'Untitled Specification';\n }\n\n private extractVersion(lines: string[]): string {\n for (const line of lines) {\n const m = /version[:\\s]+(\\d+\\.\\d+\\.\\d+)/i.exec(line.trim());\n if (m?.[1]) return m[1];\n }\n return '0.0.1';\n }\n\n private extractOverview(lines: string[]): string {\n const overviewLines: string[] = [];\n let inOverview = false;\n let foundHeading = false;\n\n for (const line of lines) {\n if (/^##\\s+Overview/i.test(line.trim())) {\n inOverview = true;\n foundHeading = true;\n continue;\n }\n if (foundHeading && /^##\\s+/.test(line.trim())) break;\n if (inOverview) overviewLines.push(line);\n }\n\n return overviewLines.join('\\n').trim() || 'No overview provided';\n }\n\n private extractSections(lines: string[]): SpecSection[] {\n const sections: SpecSection[] = [];\n let currentSection: Partial<SpecSection> | null = null;\n let currentLines: string[] = [];\n let depth = 1;\n\n for (const line of lines) {\n const h2 = /^##\\s+(.+)/.exec(line.trim());\n const h3 = /^###\\s+(.+)/.exec(line.trim());\n\n if (h2) {\n if (currentSection && currentLines.length > 0) {\n sections.push({\n type: this.mapSectionType(currentSection.title!),\n title: currentSection.title!,\n level: depth,\n content: currentLines.join('\\n').trim(),\n });\n }\n currentSection = { title: h2[1]! };\n currentLines = [];\n depth = 2;\n continue;\n }\n\n if (h3) {\n currentLines.push(line);\n continue;\n }\n\n if (currentSection) {\n currentLines.push(line);\n }\n }\n\n if (currentSection && currentLines.length > 0) {\n sections.push({\n type: this.mapSectionType(currentSection.title!),\n title: currentSection.title!,\n level: depth,\n content: currentLines.join('\\n').trim(),\n });\n }\n\n return sections;\n }\n\n private extractRequirements(lines: string[]): SpecRequirement[] {\n const requirements: SpecRequirement[] = [];\n let inRequirements = false;\n let idCounter = 0;\n\n for (const line of lines) {\n if (/^##\\s+Requirements/i.test(line.trim())) {\n inRequirements = true;\n continue;\n }\n if (inRequirements && /^##\\s+/.test(line.trim())) break;\n\n if (inRequirements) {\n const req = this.parseRequirementLine(line, `REQ-${++idCounter}`);\n if (req) requirements.push(req);\n }\n }\n\n return requirements;\n }\n\n private parseRequirementLine(line: string, id: string): SpecRequirement | null {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) return null;\n\n const lower = trimmed.toLowerCase();\n const types: SpecRequirement['type'][] = [\n 'functional',\n 'non-functional',\n 'security',\n 'performance',\n 'ux',\n ];\n let type: SpecRequirement['type'] = 'functional';\n for (const t of types) {\n if (lower.includes(`[${t}]`)) type = t;\n }\n\n let priority: SpecRequirement['priority'] = 'medium';\n if (trimmed.includes('[critical]') || trimmed.includes('[prio:high]')) {\n priority = 'critical';\n } else if (trimmed.includes('[high]')) {\n priority = 'high';\n } else if (trimmed.includes('[low]')) {\n priority = 'low';\n }\n\n return {\n id,\n type,\n priority,\n description: trimmed.replace(/\\[[^\\]]+\\]/g, '').trim(),\n acceptanceCriteria: [],\n };\n }\n\n private mapSectionType(title: string): SpecSection['type'] {\n const t = title.toLowerCase();\n if (t.includes('overview')) return 'overview';\n if (t.includes('requirement')) return 'requirements';\n if (t.includes('architect')) return 'architecture';\n if (t.includes('api')) return 'api';\n if (t.includes('data')) return 'data';\n if (t.includes('security')) return 'security';\n if (t.includes('acceptance')) return 'acceptance';\n return 'overview';\n }\n\n analyze(spec: Specification): SpecAnalysis {\n const gaps: string[] = [];\n const suggestions: string[] = [];\n const risks: SpecAnalysis['risks'] = [];\n\n // Check completeness\n const hasOverview = spec.sections.some((s) => s.type === 'overview');\n const hasRequirements = spec.sections.some((s) => s.type === 'requirements');\n const hasAcceptance = spec.sections.some((s) => s.type === 'acceptance');\n\n if (!hasOverview) gaps.push('Missing Overview section');\n if (!hasRequirements) gaps.push('Missing Requirements section');\n if (!hasAcceptance) gaps.push('Missing Acceptance Criteria section');\n\n if (spec.requirements.length === 0) {\n gaps.push('No requirements defined');\n suggestions.push('Add specific functional and non-functional requirements');\n }\n\n const unverifiedReqs = spec.requirements.filter((r) => r.acceptanceCriteria.length === 0);\n if (unverifiedReqs.length > 0) {\n gaps.push(`${unverifiedReqs.length} requirements without acceptance criteria`);\n suggestions.push('Define clear acceptance criteria for each requirement');\n }\n\n const criticalUnresolved = spec.requirements.filter(\n (r) => r.priority === 'critical' && r.blockedBy && r.blockedBy.length > 0,\n );\n for (const req of criticalUnresolved) {\n risks.push({\n requirement: req.id,\n risk: `Critical requirement blocked by ${req.blockedBy?.length} other requirements`,\n severity: 'high',\n });\n }\n\n const completeness = Math.round(\n (((hasOverview ? 1 : 0) +\n (hasRequirements ? 1 : 0) +\n (hasAcceptance ? 1 : 0) +\n (spec.requirements.length > 0 ? 1 : 0) +\n (spec.sections.length > 3 ? 1 : 0)) /\n 5) *\n 100,\n );\n\n return {\n specId: spec.id,\n completeness,\n coverage: {\n requirements: spec.requirements.length,\n apiEndpoints: spec.apiEndpoints?.length ?? 0,\n edgeCases: 0,\n errorHandling: 0,\n },\n gaps,\n risks,\n suggestions,\n };\n }\n\n validate(spec: Specification): SpecValidationResult {\n const errors: SpecValidationResult['errors'] = [];\n const warnings: SpecValidationResult['warnings'] = [];\n\n if (!spec.title.trim()) {\n errors.push({ path: 'title', message: 'Title is required' });\n }\n\n if (!spec.version.trim()) {\n errors.push({ path: 'version', message: 'Version is required' });\n }\n\n for (const req of spec.requirements) {\n if (!req.description.trim()) {\n errors.push({ path: `requirement.${req.id}`, message: 'Requirement description is empty' });\n }\n if (req.acceptanceCriteria.length === 0) {\n warnings.push({ path: `requirement.${req.id}`, message: 'No acceptance criteria defined' });\n }\n }\n\n const reqIds = new Set(spec.requirements.map((r) => r.id));\n const blockedByIds = new Set(spec.requirements.flatMap((r) => r.blockedBy ?? []));\n for (const id of blockedByIds) {\n if (!reqIds.has(id)) {\n errors.push({\n path: 'requirements',\n message: `BlockedBy references non-existent requirement: ${id}`,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n }\n}\n", "import type { TaskStore, TaskTracker } from '@wrongstack/core/tasking';\nimport type { Specification, TaskGraph, TaskPriority, TaskType } from '@wrongstack/core/types';\nimport { type AtomicityRuleSetConfig, assessAtomicity } from '@wrongstack/kanban';\n\n/** Named estimate constants shared with the atomicity candidate mapping. */\nexport const OVERVIEW_ESTIMATE_HOURS = 4;\nexport const REQUIREMENT_ESTIMATE_HOURS: Record<string, number> = {\n critical: 8,\n high: 4,\n medium: 2,\n low: 1,\n};\nexport const API_PARENT_ESTIMATE_HOURS = 0;\nexport const API_BASE_ESTIMATE_HOURS = 2;\nexport const TESTS_ESTIMATE_HOURS = 4;\nexport const DOCS_ESTIMATE_HOURS = 2;\n\nexport interface TaskGeneratorOptions {\n taskTracker: TaskTracker;\n /**\n * Opt-in (default off): derive each task's completion-gate\n * `metadata.verificationCommand` from an acceptance criterion that carries a\n * runnable-command marker (`$ <cmd>`, or `run:`/`verify:`/`cmd:` prefix). Off\n * by default so the common case stays fast \u2014 auto-running a check per task is\n * exactly the slowness the robustness initiative set out to avoid; enable it\n * explicitly (the CLI gates it behind WRONGSTACK_SDD_VERIFY_FROM_ACCEPTANCE).\n */\n verificationFromAcceptance?: boolean | undefined;\n /**\n * Opt-in atomicity annotation: stamps each generated node's\n * `metadata.atomicity` with `{ verdict, score, reasons }` from the\n * deterministic kanban rule set. Advisory only; the planning decomposer\n * consumes 'needs_decomposition' verdicts.\n */\n atomicity?: { config?: AtomicityRuleSetConfig | undefined } | undefined;\n}\n\n/** Score a generated task with the deterministic atomicity rule set. */\nexport function assessGeneratedTaskAtomicity(\n task: {\n title: string;\n description: string;\n estimateHours?: number | undefined;\n acceptanceCriteria?: readonly string[] | undefined;\n },\n config?: AtomicityRuleSetConfig,\n): { verdict: string; score: number; reasons: string[] } {\n const criteria = task.acceptanceCriteria ?? [];\n const assessment = assessAtomicity(\n {\n title: task.title,\n description: task.description,\n estimatedHours: task.estimateHours,\n // Graph edges are wired after generation; fan-in is unknown here.\n dependencyCount: 0,\n successCriteriaCount: criteria.length,\n hasVerifiableOutput: extractVerificationCommand(criteria) !== undefined,\n childCount: 0,\n },\n config,\n );\n return {\n verdict: assessment.verdict,\n score: assessment.score,\n reasons: assessment.criteria.filter((c) => c.score < 1).map((c) => c.reason),\n };\n}\n\n/**\n * Pull a runnable verification command out of a requirement's acceptance\n * criteria. A criterion qualifies only when it carries an explicit marker \u2014\n * `$ <cmd>` (shell-prompt style) or a `run:` / `verify:` / `cmd:` prefix \u2014 so\n * free-text criteria are never mistaken for commands. Returns the first match.\n */\nexport function extractVerificationCommand(criteria: readonly string[]): string | undefined {\n const marker = /^\\s*(?:\\$\\s+|(?:run|verify|cmd)\\s*:\\s*)(.+\\S)\\s*$/i;\n for (const c of criteria) {\n const m = marker.exec(c);\n if (m?.[1]) return m[1].trim();\n }\n return undefined;\n}\n\nexport interface GeneratedTask {\n specRequirementId?: string | undefined;\n title: string;\n description: string;\n type: TaskType;\n priority: TaskPriority;\n estimateHours?: number | undefined;\n tags?: string[] | undefined;\n}\n\nexport class TaskGenerator {\n constructor(private readonly opts: TaskGeneratorOptions) {}\n\n /** metadata.atomicity payload when the option is enabled, else undefined. */\n private atomicityMetadata(task: {\n title: string;\n description: string;\n estimateHours?: number | undefined;\n acceptanceCriteria?: readonly string[] | undefined;\n }): Record<string, unknown> | undefined {\n if (!this.opts.atomicity) return undefined;\n return { atomicity: assessGeneratedTaskAtomicity(task, this.opts.atomicity.config) };\n }\n\n async generateFromSpec(spec: Specification): Promise<TaskGraph> {\n const graph = await this.opts.taskTracker.createGraph(spec.id, spec.title);\n\n // Overview task\n const overviewSection = spec.sections?.find((s) => s.type === 'overview');\n if (overviewSection?.content) {\n const overview = {\n title: `Implement: ${spec.title}`,\n description: overviewSection.content,\n estimateHours: OVERVIEW_ESTIMATE_HOURS,\n };\n const metadata = this.atomicityMetadata(overview);\n this.opts.taskTracker.addNode({\n title: overview.title,\n description: overview.description,\n type: 'feature',\n priority: 'high',\n status: 'pending',\n estimateHours: overview.estimateHours,\n ...(metadata ? { metadata } : {}),\n });\n }\n\n // Requirement tasks (sorted by priority)\n const priorityOrder: Record<string, number> = { critical: 0, high: 1, medium: 2, low: 3 };\n const sorted = [...(spec.requirements ?? [])].sort(\n (a, b) => (priorityOrder[a.priority] ?? 9) - (priorityOrder[b.priority] ?? 9),\n );\n\n for (const req of sorted) {\n const estimateHours = REQUIREMENT_ESTIMATE_HOURS[req.priority] ?? 1;\n\n const tags: string[] = [req.type, req.priority];\n\n const acLines = (req.acceptanceCriteria ?? []).map((ac) => `- ${ac}`).join('\\n');\n const blockedLine = req.blockedBy?.length\n ? `\\n\\n**Blocked by:** ${req.blockedBy.join(', ')}`\n : '';\n const description =\n `${req.description}\\n\\n**Type:** ${req.type}` +\n (acLines ? `\\n\\n**Acceptance Criteria:**\\n${acLines}` : '') +\n blockedLine;\n\n const metadata: Record<string, unknown> = {\n ...this.atomicityMetadata({\n title: req.description,\n description,\n estimateHours,\n acceptanceCriteria: req.acceptanceCriteria ?? [],\n }),\n };\n if (this.opts.verificationFromAcceptance) {\n const cmd = extractVerificationCommand(req.acceptanceCriteria ?? []);\n if (cmd) metadata.verificationCommand = cmd;\n }\n\n this.opts.taskTracker.addNode({\n title: req.description,\n description,\n type: 'feature',\n priority: req.priority,\n status: 'pending',\n estimateHours,\n tags,\n specRequirementId: req.id,\n ...(Object.keys(metadata).length > 0 ? { metadata } : {}),\n });\n }\n\n // API endpoint tasks\n if (spec.apiEndpoints?.length) {\n const apiParent = this.opts.taskTracker.addNode({\n title: 'API Implementation',\n description: 'Implement API endpoints as specified in the spec.',\n type: 'feature',\n priority: 'high',\n status: 'pending',\n estimateHours: API_PARENT_ESTIMATE_HOURS,\n });\n\n for (const ep of spec.apiEndpoints) {\n const authHours = ep.auth ? 1 : 0;\n const reqHours = ep.request ? 1 : 0;\n const endpoint = {\n title: `${ep.method} ${ep.path} \u2014 ${ep.description}`,\n description: `${ep.method} ${ep.path}: ${ep.description}`,\n estimateHours: API_BASE_ESTIMATE_HOURS + authHours + reqHours,\n };\n const metadata = this.atomicityMetadata(endpoint);\n this.opts.taskTracker.addNode({\n title: endpoint.title,\n description: endpoint.description,\n type: 'feature',\n priority: 'medium',\n status: 'pending',\n estimateHours: endpoint.estimateHours,\n parentId: apiParent.id,\n ...(metadata ? { metadata } : {}),\n });\n }\n }\n\n // Always add closing tasks\n const testsTask = {\n title: 'Write Tests',\n description: 'Write comprehensive tests for the implemented features.',\n estimateHours: TESTS_ESTIMATE_HOURS,\n };\n const testsMetadata = this.atomicityMetadata(testsTask);\n this.opts.taskTracker.addNode({\n title: testsTask.title,\n description: testsTask.description,\n type: 'test',\n priority: 'high',\n status: 'pending',\n estimateHours: testsTask.estimateHours,\n ...(testsMetadata ? { metadata: testsMetadata } : {}),\n });\n\n const docsTask = {\n title: 'Update Documentation',\n description: 'Update project documentation to reflect the changes.',\n estimateHours: DOCS_ESTIMATE_HOURS,\n };\n const docsMetadata = this.atomicityMetadata(docsTask);\n this.opts.taskTracker.addNode({\n title: docsTask.title,\n description: docsTask.description,\n type: 'docs',\n priority: 'low',\n status: 'pending',\n estimateHours: docsTask.estimateHours,\n ...(docsMetadata ? { metadata: docsMetadata } : {}),\n });\n\n return graph;\n }\n\n async generateSubtasks(parentTaskId: string, spec: Specification): Promise<void> {\n const reqId = this.opts.taskTracker.getNode(parentTaskId)?.specRequirementId;\n if (!reqId) return;\n const req = spec.requirements.find((r) => r.id === reqId);\n if (!req) return;\n if (req.acceptanceCriteria.length > 0) {\n for (const criterion of req.acceptanceCriteria) {\n this.opts.taskTracker.addNode({\n title: criterion,\n description: `Verify: ${criterion}`,\n type: 'test',\n priority: 'medium',\n status: 'pending',\n parentId: parentTaskId,\n });\n }\n }\n }\n}\n\nexport type { TaskStore };\n", "// SDD domain: spec-driven development \u2014 parsing, task generation, tracking, flow,\n// persistence, interactive building, visualization, and auto-execution.\n\nexport { SpecParser } from './spec-parser.js';\nexport {\n TaskGenerator,\n extractVerificationCommand,\n assessGeneratedTaskAtomicity,\n type TaskGeneratorOptions,\n type GeneratedTask,\n} from './task-generator.js';\n// TaskTracker and DefaultTaskStore moved to @wrongstack/core/tasking in\n// PR-10; re-exported here so existing `@wrongstack/sdd` consumers keep\n// working. New code should import directly from `@wrongstack/core/tasking`.\nexport {\n TaskTracker,\n DefaultTaskStore,\n type TaskStore,\n type TaskTrackerOptions,\n type TaskTransition,\n type TaskTrackerChange,\n type TaskTrackerListener,\n} from '@wrongstack/core/tasking';\nexport {\n TaskFlow,\n SpecDrivenDev,\n type TaskFlowPhase,\n type TaskFlowOptions,\n type TaskFlowExecutionContext,\n type TaskFlowEventMap,\n type TaskFlowEventName,\n type SpecDrivenDevOptions,\n} from './task-flow.js';\n\n// Persistence\nexport { SpecStore, type SpecStoreOptions, type SpecIndexEntry } from './spec-store.js';\nexport { TaskGraphStore, type TaskGraphStoreOptions, type TaskGraphIndexEntry } from './task-graph-store.js';\n\n// Live board model + persistence\nexport {\n buildBoardTasks,\n buildBoardSnapshot,\n shortIdMap,\n type SddBoardSnapshot,\n type SddBoardTask,\n type SddBoardColumn,\n type SddBoardStatus,\n type SddTaskDisplayStatus,\n type SddDeadlockChain,\n type SddBoardFeedEntry,\n} from './board-types.js';\nexport {\n SddBoardStore,\n type SddBoardStoreOptions,\n type SddBoardIndexEntry,\n type SddBoardEvent,\n} from './sdd-board-store.js';\nexport {\n SddBoardProjector,\n type SddBoardPersistence,\n type SddBoardProjectorOptions,\n} from './sdd-board-projector.js';\nexport { SddRunRegistry, type SddRunControl } from './sdd-run-registry.js';\nexport {\n SddInterviewDriver,\n isExplanatoryText,\n type SddInterviewDriverOptions,\n type SddInterviewSnapshot,\n type SddIngestResult,\n} from './sdd-interview-driver.js';\nexport {\n startSddRun,\n type StartSddRunOptions,\n type SddRunHandle,\n} from './start-sdd-run.js';\nexport {\n cleanupSddWorktrees,\n cleanupStaleWorktrees,\n cleanupStaleSddWorktrees,\n rollbackSddRunFromDisk,\n destroySddProject,\n applySddLifecycle,\n type RollbackFromDiskOptions,\n type DestroySddProjectOptions,\n type DestroySddProjectResult,\n type CleanupStaleSddOptions,\n type CleanupStaleSddResult,\n type SddLifecycleOp,\n type SddLifecycleOptions,\n type SddLifecycleResult,\n} from './sdd-lifecycle.js';\n\n// AI-Driven Interactive Builder\nexport {\n AISpecBuilder,\n type AISpecBuilderOptions,\n type AISpecPhase,\n type AISpecSession,\n type AISpecSessionPersistence,\n type CollectedAnswer,\n isAISpecSession,\n} from './spec-builder.js';\nexport { createKanbanSddSessionPersistence } from './kanban-sdd-session.js';\n\n// Project footprint for interview prompts (CLI + WebUI wizard share this)\nexport { gatherProjectContext } from './project-context.js';\n\n// Templates\nexport {\n SPEC_TEMPLATES,\n getTemplate,\n listTemplates,\n templateToMarkdown,\n} from './spec-templates.js';\n\n// Visualization\nexport {\n renderTaskGraph,\n renderProgress,\n renderTaskList,\n renderSpecAnalysis,\n} from './task-visualizer.js';\n\n// Critical Path\nexport { analyzeCriticalPath, type CriticalPathAnalysis, type BottleneckTask } from './critical-path.js';\n\n// Spec Versioning\nexport { SpecVersioning, type SpecVersion, type SpecDiff } from './spec-versioning.js';\n\n// Auto-Executor\nexport {\n AutoExecutor,\n createAutoExecutor,\n type AutoExecutorOptions,\n type TaskExecutionContext,\n type TaskExecutionResult,\n type ExecutionSummary,\n} from './auto-executor.js';\n\n// Parallel fan-out run (SDD TaskGraph \u2192 ParallelEternalEngine bridge)\nexport {\n SddTaskDecomposer,\n type SddTaskDecomposerOptions,\n type TaskBatch,\n} from './sdd-task-decomposer.js';\nexport {\n SddParallelRun,\n type SddParallelRunOptions,\n type SddProgress,\n type WaveResult,\n type RunResult,\n type SddSubtaskSpec,\n type SddSupervisorVerdict,\n} from './sdd-parallel-run.js';\nexport { SddSupervisor, type SddSupervisorOptions } from './sdd-supervisor.js';\nexport {\n makeAcceptanceCriteriaVerifier,\n makeCommandVerifier,\n makeCompositeVerifier,\n tokenizeCommand,\n type AcceptanceCriteriaVerifierOptions,\n type CommandVerifierOptions,\n type SddVerifyTask,\n} from './verify-task.js';\nexport {\n makeLlmSubtaskGenerator,\n makePlanningDecomposer,\n type PlanningDecomposer,\n type PlanningDecomposerOptions,\n type SubtaskGeneratorOptions,\n} from './decompose-task.js';\nexport { splitGraphNode, type SplitGraphNodeOptions } from './graph-split.js';\nexport {\n assessTaskNodeAtomicity,\n decomposeNonAtomicTasks,\n type DecompositionProposal,\n type PlanDecomposeOptions,\n type PlanDecomposeResult,\n} from './plan-decompose.js';\nexport {\n makePreferSideConflictResolver,\n makeLlmConflictResolver,\n resolveConflictText,\n hasConflictMarkers,\n type ConflictSide,\n type LlmConflictResolverOptions,\n} from './conflict-resolver.js';\n", "import type { EventBus } from '@wrongstack/core/kernel';\nimport { DefaultTaskStore, TaskTracker } from '@wrongstack/core/tasking';\nimport type {\n DoneCondition,\n SpecAnalysis,\n Specification,\n TaskGraph,\n TaskNode,\n} from '@wrongstack/core/types';\nimport { ERROR_CODES, SddError } from '@wrongstack/core/types';\nimport { expectDefined } from '@wrongstack/core/utils';\nimport { SpecParser } from './spec-parser.js';\nimport { TaskGenerator } from './task-generator.js';\n\n/**\n * Extended event map used internally by TaskFlow and multi-agent components.\n * These events are emitted on the injected EventBus and are a subset of\n * the full EventMap \u2014 they do not require a separate registration.\n */\nexport interface TaskFlowEventMap {\n 'phase.change': { from: TaskFlowPhase; to: TaskFlowPhase };\n 'task.started': { taskId: string };\n 'task.completed': { taskId: string; result?: unknown | undefined };\n 'task.failed': { taskId: string; error: string };\n 'task.review': { taskId: string };\n 'spec.analyzed': { analysis: SpecAnalysis };\n progress: { percent: number; message: string };\n done: { graph: TaskGraph };\n error: { phase: TaskFlowPhase; error: Error };\n}\n\nexport type TaskFlowPhase =\n | 'idle'\n | 'parsing'\n | 'analyzing'\n | 'generating'\n | 'executing'\n | 'reviewing'\n | 'completing'\n | 'done'\n | 'failed';\n\nexport type TaskFlowEventName = keyof TaskFlowEventMap;\n\nexport interface TaskFlowOptions {\n tracker: TaskTracker;\n events: EventBus;\n doneCondition?: DoneCondition | undefined;\n maxConcurrent?: number | undefined;\n}\n\nexport interface TaskFlowExecutionContext {\n executeTask: (task: TaskNode) => Promise<unknown>;\n onTaskComplete?: (task: TaskNode | undefined, result: unknown) => void;\n onTaskFail?: (task: TaskNode | undefined, error: Error) => void;\n}\n\nexport class TaskFlow {\n private phase: TaskFlowPhase = 'idle';\n private spec: Specification | null = null;\n private graph: TaskGraph | null = null;\n private stopped = false;\n\n constructor(private readonly opts: TaskFlowOptions) {\n this.setPhase('idle');\n }\n\n private emit<K extends TaskFlowEventName>(event: K, payload: TaskFlowEventMap[K]): void {\n (this.opts.events.emit as (event: string, payload: unknown) => void)(event, payload);\n }\n\n async fromSpec(specContent: string): Promise<TaskGraph> {\n this.setPhase('parsing');\n\n const parser = new SpecParser();\n this.spec = parser.parse(specContent);\n\n this.setPhase('analyzing');\n const analysis = parser.analyze(this.spec);\n this.emit('spec.analyzed', { analysis });\n\n if (analysis.completeness < 50) {\n const err = new SddError({\n message: `Spec completeness too low: ${analysis.completeness}%`,\n code: ERROR_CODES.SDD_VALIDATION_FAILED,\n context: { completeness: analysis.completeness },\n });\n this.emit('error', { phase: 'analyzing', error: err });\n this.setPhase('failed');\n throw err;\n }\n\n this.setPhase('generating');\n const generator = new TaskGenerator({\n taskTracker: this.opts.tracker,\n verificationFromAcceptance: process.env['WRONGSTACK_SDD_VERIFY_FROM_ACCEPTANCE'] === '1',\n });\n this.graph = await generator.generateFromSpec(this.spec);\n\n return this.graph;\n }\n\n async execute(ctx: TaskFlowExecutionContext): Promise<TaskGraph> {\n if (!this.graph)\n throw new SddError({\n message: 'No graph loaded. Call fromSpec first.',\n code: ERROR_CODES.SDD_INVALID_STATE,\n context: { phase: this.phase },\n });\n\n this.setPhase('executing');\n this.stopped = false;\n\n const pendingTasks = this.getExecutableTasks();\n const maxConcurrent = this.opts.maxConcurrent ?? 2;\n\n while (pendingTasks.length > 0 && !this.stopped) {\n const batch = pendingTasks.splice(0, maxConcurrent);\n const results = await Promise.allSettled(\n batch.map((task) => this.executeSingleTask(task, ctx)),\n );\n\n for (let i = 0; i < results.length; i++) {\n const result = expectDefined(results[i]);\n const task = expectDefined(batch[i]);\n\n if (result.status === 'rejected') {\n const reason = result.reason as Error | undefined;\n this.opts.tracker.updateNodeStatus(task.id, 'failed', reason?.message);\n this.emit('task.failed', { taskId: task.id, error: reason?.message ?? 'unknown' });\n ctx.onTaskFail?.(task, reason as Error);\n } else {\n this.opts.tracker.updateNodeStatus(task.id, 'completed');\n this.emit('task.completed', { taskId: task.id, result: result.value });\n ctx.onTaskComplete?.(task, result.value);\n }\n\n this.emitProgress();\n }\n\n // Re-evaluate pending tasks (some may have become unblocked)\n const stillPending = this.getExecutableTasks();\n pendingTasks.length = 0;\n pendingTasks.push(...stillPending);\n\n // Check done condition\n if (this.checkDoneCondition()) {\n break;\n }\n }\n\n this.setPhase('completing');\n this.emit('done', { graph: this.graph });\n this.setPhase('done');\n\n return this.graph;\n }\n\n async reviewTask(taskId: string, approved: boolean, comment?: string): Promise<void> {\n const task = this.opts.tracker.getNode(taskId);\n if (!task)\n throw new SddError({\n message: `Task ${taskId} not found`,\n code: ERROR_CODES.SDD_NOT_READY,\n context: { taskId },\n });\n\n if (approved) {\n this.opts.tracker.updateNodeStatus(taskId, 'completed', comment);\n this.emit('task.completed', { taskId });\n } else {\n this.opts.tracker.updateNodeStatus(taskId, 'in_progress', comment ?? 'Needs revision');\n this.emit('task.review', { taskId });\n }\n }\n\n stop(): void {\n this.stopped = true;\n }\n\n getPhase(): TaskFlowPhase {\n return this.phase;\n }\n\n getGraph(): TaskGraph | null {\n return this.graph;\n }\n\n getSpec(): Specification | null {\n return this.spec;\n }\n\n private setPhase(phase: TaskFlowPhase): void {\n const from = this.phase;\n this.phase = phase;\n this.emit('phase.change', { from, to: phase });\n }\n\n private getExecutableTasks(): TaskNode[] {\n return this.opts.tracker\n .getAllNodes({ status: ['pending', 'blocked'] })\n .filter((n) => n.status === 'pending' && this.opts.tracker.canStart(n.id))\n .sort((a, b) => {\n const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };\n return priorityOrder[a.priority] - priorityOrder[b.priority];\n });\n }\n\n private async executeSingleTask(task: TaskNode, ctx: TaskFlowExecutionContext): Promise<unknown> {\n this.opts.tracker.updateNodeStatus(task.id, 'in_progress');\n this.emit('task.started', { taskId: task.id });\n return ctx.executeTask(task);\n }\n\n private checkDoneCondition(): boolean {\n const condition = this.opts.doneCondition;\n if (!condition) {\n const progress = this.opts.tracker.getProgress();\n return progress.percentComplete === 100;\n }\n\n switch (condition.type) {\n case 'all_tasks_done': {\n const progress = this.opts.tracker.getProgress();\n return progress.pending === 0 && progress.inProgress === 0;\n }\n case 'iterations':\n return false; // Not tracked here\n case 'tool_calls':\n return false;\n default:\n return false;\n }\n }\n\n private emitProgress(): void {\n const progress = this.opts.tracker.getProgress();\n this.emit('progress', {\n percent: progress.percentComplete,\n message: `${progress.completed}/${progress.total} tasks completed`,\n });\n }\n}\n\nexport interface SpecDrivenDevOptions {\n workingDirectory: string;\n events: EventBus;\n doneCondition?: DoneCondition | undefined;\n}\n\nexport class SpecDrivenDev {\n private store: DefaultTaskStore;\n private tracker: TaskTracker;\n private readonly events: EventBus;\n private flows = new Map<string, TaskFlow>();\n\n constructor(opts: SpecDrivenDevOptions) {\n this.store = new DefaultTaskStore();\n this.tracker = new TaskTracker({ store: this.store });\n this.events = opts.events;\n }\n\n async createFlow(specContent: string, options?: Partial<TaskFlowOptions>): Promise<TaskFlow> {\n const flow = new TaskFlow({\n tracker: this.tracker,\n events: this.events,\n ...options,\n });\n\n const graph = await flow.fromSpec(specContent);\n this.flows.set(graph.id, flow);\n\n return flow;\n }\n\n getTracker(): TaskTracker {\n return this.tracker;\n }\n\n getFlow(graphId: string): TaskFlow | undefined {\n return this.flows.get(graphId);\n }\n\n listFlows(): { id: string; title: string; phase: TaskFlowPhase }[] {\n return Array.from(this.flows.entries()).map(([id, flow]) => ({\n id,\n title: flow.getGraph()?.title ?? 'Untitled',\n phase: flow.getPhase(),\n }));\n }\n}\n", "import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { atomicWrite, ensureDir } from '@wrongstack/core/utils';\nimport type { Specification, SpecStatus } from '@wrongstack/core/types';\n\nexport interface SpecStoreOptions {\n /** Directory where spec files are stored. Defaults to `.wrongstack/specs`. */\n baseDir: string;\n}\n\nexport interface SpecIndexEntry {\n id: string;\n title: string;\n version: string;\n status: SpecStatus;\n updatedAt: number;\n filePath: string;\n}\n\ninterface SpecIndex {\n version: 1;\n entries: SpecIndexEntry[];\n}\n\n/**\n * File-backed spec storage. Each spec is a JSON file under `baseDir/`.\n * An index file (`_index.json`) tracks all specs for fast listing.\n */\nexport class SpecStore {\n private readonly baseDir: string;\n private readonly indexPath: string;\n\n constructor(opts: SpecStoreOptions) {\n this.baseDir = opts.baseDir;\n this.indexPath = path.join(this.baseDir, '_index.json');\n }\n\n async save(spec: Specification): Promise<void> {\n await ensureDir(this.baseDir);\n const filePath = this.filePath(spec.id);\n await atomicWrite(filePath, JSON.stringify(spec, null, 2), { mode: 0o600 });\n await this.updateIndex(spec);\n }\n\n async load(id: string): Promise<Specification | null> {\n try {\n const raw = await fsp.readFile(this.filePath(id), 'utf8');\n return JSON.parse(raw) as Specification;\n } catch {\n return null;\n }\n }\n\n async list(): Promise<SpecIndexEntry[]> {\n const index = await this.readIndex();\n return index.entries.sort((a, b) => b.updatedAt - a.updatedAt);\n }\n\n async delete(id: string): Promise<boolean> {\n try {\n await fsp.unlink(this.filePath(id));\n await this.removeFromIndex(id);\n return true;\n } catch {\n return false;\n }\n }\n\n async exists(id: string): Promise<boolean> {\n try {\n await fsp.access(this.filePath(id));\n return true;\n } catch {\n return false;\n }\n }\n\n /** Create a new spec with defaults, assign ID, and persist. */\n async createDraft(title: string, overview?: string): Promise<Specification> {\n const now = Date.now();\n const spec: Specification = {\n id: randomUUID(),\n title,\n version: '0.1.0',\n status: 'draft',\n overview: overview ?? '',\n sections: [],\n requirements: [],\n createdAt: now,\n updatedAt: now,\n };\n await this.save(spec);\n return spec;\n }\n\n /** Update spec fields and persist. */\n async update(id: string, patch: Partial<Omit<Specification, 'id' | 'createdAt'>>): Promise<Specification | null> {\n const spec = await this.load(id);\n if (!spec) return null;\n const updated: Specification = {\n ...spec,\n ...patch,\n id: spec.id,\n createdAt: spec.createdAt,\n updatedAt: Date.now(),\n };\n await this.save(updated);\n return updated;\n }\n\n private filePath(id: string): string {\n return path.join(this.baseDir, `${id}.json`);\n }\n\n private async readIndex(): Promise<SpecIndex> {\n try {\n const raw = await fsp.readFile(this.indexPath, 'utf8');\n const parsed = JSON.parse(raw) as SpecIndex;\n if (parsed?.version === 1) return parsed;\n } catch {\n /* no index yet */\n }\n return { version: 1, entries: [] };\n }\n\n private async updateIndex(spec: Specification): Promise<void> {\n const index = await this.readIndex();\n const entry: SpecIndexEntry = {\n id: spec.id,\n title: spec.title,\n version: spec.version,\n status: spec.status,\n updatedAt: spec.updatedAt,\n filePath: this.filePath(spec.id),\n };\n const idx = index.entries.findIndex((e) => e.id === spec.id);\n if (idx >= 0) {\n index.entries[idx] = entry;\n } else {\n index.entries.push(entry);\n }\n await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 0o600 });\n }\n\n private async removeFromIndex(id: string): Promise<void> {\n const index = await this.readIndex();\n index.entries = index.entries.filter((e) => e.id !== id);\n await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 0o600 });\n }\n}\n", "import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { TaskStore } from '@wrongstack/core/tasking';\nimport type { TaskGraph, TaskNode } from '@wrongstack/core/types';\nimport { atomicWrite, ensureDir } from '@wrongstack/core/utils';\n\nexport interface TaskGraphStoreOptions {\n /** Directory where task graph files are stored. Defaults to `.wrongstack/task-graphs`. */\n baseDir: string;\n}\n\nexport interface TaskGraphIndexEntry {\n id: string;\n specId: string;\n title: string;\n nodeCount: number;\n completedCount: number;\n updatedAt: number;\n filePath: string;\n}\n\ninterface TaskGraphIndex {\n version: 1;\n entries: TaskGraphIndexEntry[];\n}\n\n/**\n * JSON serialisation helpers for TaskGraph (Map \u2192 Array round-trip).\n */\nfunction graphToJSON(graph: TaskGraph): string {\n const serialisable = {\n ...graph,\n nodes: Array.from(graph.nodes.entries()),\n };\n return JSON.stringify(serialisable, null, 2);\n}\n\nfunction graphFromJSON(raw: string): TaskGraph {\n const parsed = JSON.parse(raw) as Omit<TaskGraph, 'nodes'> & { nodes: [string, TaskNode][] };\n return {\n ...parsed,\n nodes: new Map(parsed.nodes),\n };\n}\n\n/**\n * File-backed task graph storage. Each graph is a JSON file under `baseDir/`.\n * An index file (`_index.json`) tracks all graphs for fast listing.\n */\nexport class TaskGraphStore implements TaskStore {\n private readonly baseDir: string;\n private readonly indexPath: string;\n private writeChain: Promise<void> = Promise.resolve();\n\n constructor(opts: TaskGraphStoreOptions) {\n this.baseDir = opts.baseDir;\n this.indexPath = path.join(this.baseDir, '_index.json');\n }\n\n async save(graph: TaskGraph): Promise<void> {\n const snapshot = graphFromJSON(graphToJSON(graph));\n const pending = this.writeChain.then(async () => {\n await ensureDir(this.baseDir);\n const filePath = this.filePath(snapshot.id);\n await atomicWrite(filePath, graphToJSON(snapshot), { mode: 0o600 });\n await this.updateIndex(snapshot);\n });\n this.writeChain = pending.catch(() => undefined);\n await pending;\n }\n\n async load(id: string): Promise<TaskGraph | null> {\n await this.writeChain;\n try {\n const raw = await fsp.readFile(this.filePath(id), 'utf8');\n return graphFromJSON(raw);\n } catch {\n return null;\n }\n }\n\n async list(): Promise<TaskGraphIndexEntry[]> {\n await this.writeChain;\n const index = await this.readIndex();\n return index.entries.sort((a, b) => b.updatedAt - a.updatedAt);\n }\n\n async delete(id: string): Promise<boolean> {\n await this.writeChain;\n try {\n await fsp.unlink(this.filePath(id));\n await this.removeFromIndex(id);\n return true;\n } catch {\n return false;\n }\n }\n\n async exists(id: string): Promise<boolean> {\n await this.writeChain;\n try {\n await fsp.access(this.filePath(id));\n return true;\n } catch {\n return false;\n }\n }\n\n saveGraph(graph: TaskGraph): Promise<void> {\n return this.save(graph);\n }\n\n loadGraph(id: string): Promise<TaskGraph | null> {\n return this.load(id);\n }\n\n async listGraphs(): Promise<Array<{ id: string; title: string; updatedAt: number }>> {\n return (await this.list()).map(({ id, title, updatedAt }) => ({ id, title, updatedAt }));\n }\n\n async deleteGraph(id: string): Promise<void> {\n await this.delete(id);\n }\n\n private filePath(id: string): string {\n return path.join(this.baseDir, `${id}.json`);\n }\n\n private async readIndex(): Promise<TaskGraphIndex> {\n try {\n const raw = await fsp.readFile(this.indexPath, 'utf8');\n const parsed = JSON.parse(raw) as TaskGraphIndex;\n if (parsed?.version === 1) return parsed;\n } catch {\n /* no index yet */\n }\n return { version: 1, entries: [] };\n }\n\n private async updateIndex(graph: TaskGraph): Promise<void> {\n const index = await this.readIndex();\n const completedCount = Array.from(graph.nodes.values()).filter(\n (n) => n.status === 'completed',\n ).length;\n const entry: TaskGraphIndexEntry = {\n id: graph.id,\n specId: graph.specId,\n title: graph.title,\n nodeCount: graph.nodes.size,\n completedCount,\n updatedAt: graph.updatedAt,\n filePath: this.filePath(graph.id),\n };\n const idx = index.entries.findIndex((e) => e.id === graph.id);\n if (idx >= 0) {\n index.entries[idx] = entry;\n } else {\n index.entries.push(entry);\n }\n await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 0o600 });\n }\n\n private async removeFromIndex(id: string): Promise<void> {\n const index = await this.readIndex();\n index.entries = index.entries.filter((e) => e.id !== id);\n await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 0o600 });\n }\n}\n", "/**\n * SDD live board model.\n *\n * A board snapshot is the canonical, surface-agnostic projection of a running\n * (or persisted) SDD TaskGraph: tasks laid into topological dependency columns,\n * each carrying its short id, status, blockers and the agent currently on it.\n * The projector (sdd-board-projector.ts) emits these over the EventBus and\n * persists them (sdd-board-store.ts); every surface (WebUI/TUI) renders the\n * same shape.\n */\n\nimport { computeTaskProgress } from '@wrongstack/core/tasking';\nimport type { TaskGraph, TaskNode, TaskProgress } from '@wrongstack/core/types';\n\nexport type SddBoardStatus =\n | 'idle'\n | 'running'\n | 'paused'\n | 'stopped'\n | 'completed'\n | 'failed'\n | 'deadlocked';\n\n/**\n * FORGE-style display status: `queued` = pending with all blockers done;\n * `cancelled` = a task the user stopped (stored as a terminal `failed` node\n * carrying `metadata.cancelled`, surfaced distinctly so it doesn't read as an\n * error). Display-only \u2014 not a core `TaskStatus`.\n */\nexport type SddTaskDisplayStatus = TaskNode['status'] | 'queued' | 'cancelled';\n\nexport interface SddBoardTask {\n id: string;\n /** Stable short id (t01, t02, \u2026) in creation order. */\n shortId: string;\n title: string;\n description: string;\n status: TaskNode['status'];\n displayStatus: SddTaskDisplayStatus;\n priority: TaskNode['priority'];\n type: TaskNode['type'];\n /** Short ids of the tasks that block this one (depends_on edges). */\n deps: string[];\n /** Worker on the task right now (scientist nickname), if any. */\n agentName?: string | undefined;\n /** Git worktree branch this task runs in, when isolated. */\n worktreeBranch?: string | undefined;\n startedAt?: number | undefined;\n completedAt?: number | undefined;\n retries: number;\n /** Per-task model assignment (overrides the run default), if set. */\n model?: string | undefined;\n /** Per-task provider assignment (overrides the run default), if set. */\n provider?: string | undefined;\n /** Per-task fallback model chain (overrides the run default), if set. */\n fallbackModels?: string[] | undefined;\n /** Per-task completion-gate verification command, if set. */\n verificationCommand?: string | undefined;\n /** Completion-gate outcome for the last worker attempt, if verification ran. */\n verificationState?: 'passed' | 'failed' | undefined;\n /** Failure reason when verificationState is 'failed'. */\n verificationDetail?: string | undefined;\n}\n\n/** A topological column: tasks whose deepest dependency chain is `depth`. */\nexport interface SddBoardColumn {\n label: string;\n /** Short ids of the tasks in this column (join against `tasks`). */\n taskIds: string[];\n}\n\nexport interface SddDeadlockChain {\n /** Short id of the blocked task. */\n blocked: string;\n /** Short ids of the failed/incomplete blockers holding it. */\n blockedBy: string[];\n}\n\n/** One entry in the live activity feed (the board's \"what just happened\" ticker). */\nexport interface SddBoardFeedEntry {\n ts: number;\n kind:\n | 'started'\n | 'completed'\n | 'failed'\n | 'retrying'\n | 'wave'\n | 'deadlock'\n | 'verification_failed'\n | 'conflict'\n | 'split'\n | 'supervisor'\n | 'tool'\n | 'file';\n /** Full task id for durable per-task history; older snapshots may only carry shortId. */\n taskId?: string | undefined;\n /** Short id of the task this entry concerns, when applicable. */\n taskShortId?: string | undefined;\n /** Worker involved, when applicable. */\n agentName?: string | undefined;\n /** Human-readable one-line summary. */\n text: string;\n /** Structured event-log fields used by richer board surfaces. */\n action?: string | undefined;\n detail?: string | undefined;\n filePath?: string | undefined;\n durationMs?: number | undefined;\n ok?: boolean | undefined;\n}\n\nexport interface SddBoardSnapshot {\n runId: string;\n specId?: string | undefined;\n graphId: string;\n title: string;\n status: SddBoardStatus;\n startedAt: number;\n updatedAt: number;\n progress: TaskProgress;\n /** Current wave index (0-based) of the parallel run. */\n wave: number;\n tasks: SddBoardTask[];\n columns: SddBoardColumn[];\n diagnostics?: { deadlockChains?: SddDeadlockChain[] } | undefined;\n /** Live activity feed \u2014 most recent first (capped). */\n feed?: SddBoardFeedEntry[] | undefined;\n /** Per-task event history \u2014 most recent first and capped independently per task. */\n taskEvents?: Record<string, SddBoardFeedEntry[]> | undefined;\n /** Run-level default worker model (task overrides take precedence). */\n defaultModel?: string | undefined;\n /** Run-level default worker provider. */\n defaultProvider?: string | undefined;\n /** Run-level default fallback model chain. */\n fallbackModels?: string[] | undefined;\n /** Base branch the run's squash commits land on (worktree runs only). */\n baseBranch?: string | undefined;\n /**\n * Squash commits the run landed on the base branch, in landing order. Lets a\n * post-run `/sdd rollback` revert them from disk after the live run is gone.\n */\n mergedCommits?: Array<{ taskId: string; sha: string; title: string }> | undefined;\n}\n\n/**\n * Lay a TaskGraph's nodes into topological dependency columns with stable short\n * ids and per-task blocker refs. Shared by the projector (live) and any static\n * board browser. Pure; no run state \u2014 `agentName`/`worktreeBranch`/`retries`\n * are read from the node's `assignee`/`metadata` so a reload reflects the last\n * persisted run.\n */\n/**\n * Stable short-id map (t01, t02, \u2026) for a graph's nodes in creation order.\n * Shared by the board renderer and the projector (deadlock-chain labelling).\n */\nexport function shortIdMap(graph: TaskGraph): Map<string, string> {\n const nodes = Array.from(graph.nodes.values()).sort((a, b) => a.createdAt - b.createdAt);\n const m = new Map<string, string>();\n nodes.forEach((n, i) => {\n m.set(n.id, `t${String(i + 1).padStart(2, '0')}`);\n });\n return m;\n}\n\nexport function buildBoardTasks(graph: TaskGraph): {\n tasks: SddBoardTask[];\n columns: SddBoardColumn[];\n} {\n const nodes = Array.from(graph.nodes.values()).sort((a, b) => a.createdAt - b.createdAt);\n const shortId = shortIdMap(graph);\n\n // Blockers per node (depends_on edges pointing at the node).\n const blockers = new Map<string, string[]>();\n for (const n of nodes) blockers.set(n.id, []);\n for (const e of graph.edges) {\n if (e.type === 'depends_on') blockers.get(e.to)?.push(e.from);\n }\n\n const statusOf = (id: string) => graph.nodes.get(id)?.status;\n\n // Memoized topological depth (longest blocker chain), cycle-guarded.\n const depthCache = new Map<string, number>();\n const depthOf = (id: string, seen = new Set<string>()): number => {\n const cached = depthCache.get(id);\n if (cached !== undefined) return cached;\n if (seen.has(id)) return 0;\n seen.add(id);\n const deps = blockers.get(id) ?? [];\n const d = deps.length === 0 ? 0 : 1 + Math.max(...deps.map((b) => depthOf(b, seen)));\n depthCache.set(id, d);\n return d;\n };\n\n const toTask = (n: TaskNode): SddBoardTask => {\n const deps = blockers.get(n.id)!;\n const allDepsDone = deps.every((b) => statusOf(b) === 'completed');\n const meta = (n.metadata ?? {}) as Record<string, unknown>;\n const cancelled = Boolean(meta['cancelled']);\n const displayStatus: SddTaskDisplayStatus = cancelled\n ? 'cancelled'\n : n.status === 'pending' && deps.length > 0 && allDepsDone\n ? 'queued'\n : n.status;\n return {\n id: n.id,\n shortId: shortId.get(n.id)!,\n title: n.title,\n description: n.description,\n status: n.status,\n displayStatus,\n priority: n.priority,\n type: n.type,\n deps: deps.map((b) => shortId.get(b) ?? b.slice(0, 6)),\n agentName: n.assignee,\n worktreeBranch:\n typeof meta['worktreeBranch'] === 'string' ? (meta['worktreeBranch'] as string) : undefined,\n startedAt: n.startedAt,\n completedAt: n.completedAt,\n retries: typeof meta['retries'] === 'number' ? (meta['retries'] as number) : 0,\n model: typeof meta['model'] === 'string' ? (meta['model'] as string) : undefined,\n provider: typeof meta['provider'] === 'string' ? (meta['provider'] as string) : undefined,\n fallbackModels: Array.isArray(meta['fallbackModels'])\n ? (meta['fallbackModels'] as string[])\n : undefined,\n verificationCommand:\n typeof meta['verificationCommand'] === 'string'\n ? (meta['verificationCommand'] as string)\n : undefined,\n verificationState:\n meta['verificationState'] === 'passed' || meta['verificationState'] === 'failed'\n ? (meta['verificationState'] as 'passed' | 'failed')\n : undefined,\n verificationDetail:\n typeof meta['verificationDetail'] === 'string'\n ? (meta['verificationDetail'] as string)\n : undefined,\n };\n };\n\n const tasks = nodes.map(toTask);\n\n const byDepth = new Map<number, string[]>();\n for (const n of nodes) {\n const d = depthOf(n.id);\n if (!byDepth.has(d)) byDepth.set(d, []);\n byDepth.get(d)!.push(shortId.get(n.id)!);\n }\n const columns: SddBoardColumn[] = [...byDepth.keys()]\n .sort((a, b) => a - b)\n .map((d) => ({ label: d === 0 ? 'Start' : `Phase ${d}`, taskIds: byDepth.get(d)! }));\n\n return { tasks, columns };\n}\n\n/**\n * Build a full board snapshot from a graph + run state. The projector calls\n * this on every (throttled) change.\n */\nexport function buildBoardSnapshot(\n graph: TaskGraph,\n run: {\n runId: string;\n specId?: string | undefined;\n status: SddBoardStatus;\n startedAt: number;\n wave: number;\n deadlockChains?: SddDeadlockChain[] | undefined;\n defaultModel?: string | undefined;\n defaultProvider?: string | undefined;\n fallbackModels?: string[] | undefined;\n baseBranch?: string | undefined;\n mergedCommits?: Array<{ taskId: string; sha: string; title: string }> | undefined;\n },\n now: number,\n): SddBoardSnapshot {\n const { tasks, columns } = buildBoardTasks(graph);\n return {\n runId: run.runId,\n specId: run.specId,\n graphId: graph.id,\n title: graph.title,\n status: run.status,\n startedAt: run.startedAt,\n updatedAt: now,\n progress: computeTaskProgress(graph),\n wave: run.wave,\n tasks,\n columns,\n diagnostics: run.deadlockChains?.length ? { deadlockChains: run.deadlockChains } : undefined,\n defaultModel: run.defaultModel,\n defaultProvider: run.defaultProvider,\n fallbackModels: run.fallbackModels,\n baseBranch: run.baseBranch,\n mergedCommits: run.mergedCommits?.length ? run.mergedCommits : undefined,\n };\n}\n", "import * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite, ensureDir, withFileLock } from '@wrongstack/core/utils';\nimport type { SddBoardSnapshot } from './board-types.js';\n\nconst DEFAULT_EVENT_MAX_BYTES = 16 * 1024 * 1024;\nconst DEFAULT_EVENT_KEEP_BYTES = 8 * 1024 * 1024;\nconst DEFAULT_EVENT_SIZE_CHECK_EVERY = 100;\n\nexport interface SddBoardStoreOptions {\n /** Directory for board snapshots + event logs (wpaths.projectSddBoards). */\n baseDir: string;\n /** Rotate an event log after this many bytes. Default 16 MiB. */\n eventMaxBytes?: number | undefined;\n /** Tail bytes retained after event-log rotation. Default 8 MiB. */\n eventKeepBytes?: number | undefined;\n /** Amortize event-log size stats across this many appends. Default 100. */\n eventSizeCheckEvery?: number | undefined;\n /** Injectable control-queue file operations for fault testing. */\n controlFileIO?: SddBoardControlFileIO | undefined;\n}\n\nexport interface SddBoardControlFileIO {\n stat(filePath: string): Promise<{ size: number }>;\n readFile(filePath: string, encoding: 'utf8'): Promise<string>;\n truncate(filePath: string, length: number): Promise<void>;\n}\n\nexport interface SddBoardIndexEntry {\n runId: string;\n specId?: string | undefined;\n title: string;\n status: string;\n total: number;\n completed: number;\n updatedAt: number;\n}\n\ninterface SddBoardIndex {\n version: 1;\n entries: SddBoardIndexEntry[];\n}\n\nexport interface IndexSignature {\n size: number;\n mtimeMs: number;\n ctimeMs: number;\n}\n\n/** One appended line in a board's JSONL event log. */\nexport interface SddBoardEvent {\n ts: number;\n type: string;\n payload?: unknown;\n}\n\n/**\n * Legacy-compatible SDD board storage. A board (= one parallel run) may have:\n * - `<runId>.json` \u2014 legacy snapshot imported into Kanban workflow state\n * - `<runId>.events.jsonl`\u2014 bounded tail event log (audit / recent replay)\n * - `<runId>.control.jsonl` \u2014 legacy command queue imported once by new runs\n * plus legacy `_index.json`. Production snapshot/control authority lives in the\n * project-scoped Kanban daemon; JSONL remains the append-only audit stream.\n */\nexport class SddBoardStore {\n private readonly baseDir: string;\n private readonly indexPath: string;\n private readonly eventMaxBytes: number;\n private readonly eventKeepBytes: number;\n private readonly eventSizeCheckEvery: number;\n private readonly controlFileIO: SddBoardControlFileIO;\n private readonly eventChains = new Map<string, Promise<void>>();\n private readonly eventWritesSinceCheck = new Map<string, number>();\n private readonly controlDrains = new Map<\n string,\n Promise<Array<{ ts: number; type: string; payload?: unknown }>>\n >();\n private baseDirReady: Promise<void> | undefined;\n private cachedIndex: SddBoardIndex | undefined;\n private cachedIndexSignature: IndexSignature | null = null;\n\n constructor(opts: SddBoardStoreOptions) {\n this.baseDir = opts.baseDir;\n this.indexPath = path.join(this.baseDir, '_index.json');\n this.eventMaxBytes = Math.max(1024, Math.floor(opts.eventMaxBytes ?? DEFAULT_EVENT_MAX_BYTES));\n this.eventKeepBytes = Math.min(\n this.eventMaxBytes,\n Math.max(0, Math.floor(opts.eventKeepBytes ?? DEFAULT_EVENT_KEEP_BYTES)),\n );\n this.eventSizeCheckEvery = Math.max(\n 1,\n Math.floor(opts.eventSizeCheckEvery ?? DEFAULT_EVENT_SIZE_CHECK_EVERY),\n );\n this.controlFileIO = opts.controlFileIO ?? fsp;\n }\n\n snapshotPath(runId: string): string {\n return path.join(this.baseDir, `${this.safe(runId)}.json`);\n }\n eventsPath(runId: string): string {\n return path.join(this.baseDir, `${this.safe(runId)}.events.jsonl`);\n }\n controlPath(runId: string): string {\n return path.join(this.baseDir, `${this.safe(runId)}.control.jsonl`);\n }\n\n async saveSnapshot(snapshot: SddBoardSnapshot): Promise<void> {\n await this.ensureBaseDir();\n await atomicWrite(this.snapshotPath(snapshot.runId), JSON.stringify(snapshot, null, 2), {\n mode: 0o600,\n });\n await this.updateIndex(snapshot);\n }\n\n async load(runId: string): Promise<SddBoardSnapshot | null> {\n try {\n const raw = await fsp.readFile(this.snapshotPath(runId), 'utf8');\n return JSON.parse(raw) as SddBoardSnapshot;\n } catch {\n return null;\n }\n }\n\n async list(): Promise<SddBoardIndexEntry[]> {\n const index = await this.readIndex();\n return index.entries.map((entry) => ({ ...entry }));\n }\n\n /** Latest board metadata without cloning/sorting the complete index. */\n async latest(): Promise<SddBoardIndexEntry | undefined> {\n const entry = (await this.readIndex()).entries[0];\n return entry ? { ...entry } : undefined;\n }\n\n async loadLatestForSpec(specId: string): Promise<SddBoardSnapshot | null> {\n const entry = (await this.list()).find((e) => e.specId === specId);\n return entry ? this.load(entry.runId) : null;\n }\n\n /** Append one line to the board's JSONL event log (best-effort, never throws). */\n async appendEvent(runId: string, event: SddBoardEvent): Promise<void> {\n const filePath = this.eventsPath(runId);\n const previous = this.eventChains.get(filePath) ?? Promise.resolve();\n const write = previous\n .then(() => this.appendEventInternal(filePath, event))\n .catch(() => undefined);\n this.eventChains.set(filePath, write);\n await write;\n if (this.eventChains.get(filePath) === write) this.eventChains.delete(filePath);\n }\n\n /** Append a legacy control command. Production readers use Kanban IPC. */\n async appendControl(\n runId: string,\n command: { ts: number; type: string; payload?: unknown },\n ): Promise<void> {\n await this.ensureBaseDir();\n const filePath = this.controlPath(runId);\n await withFileLock(filePath, () =>\n fsp.appendFile(filePath, `${JSON.stringify(command)}\\n`, { mode: 0o600 }),\n );\n }\n\n /** Read + truncate the legacy control queue for one-time migration. */\n async drainControl(\n runId: string,\n ): Promise<Array<{ ts: number; type: string; payload?: unknown }>> {\n const filePath = this.controlPath(runId);\n const active = this.controlDrains.get(filePath);\n if (active) {\n await active;\n return [];\n }\n const drain = this.drainControlInternal(filePath);\n this.controlDrains.set(filePath, drain);\n try {\n return await drain;\n } finally {\n this.controlDrains.delete(filePath);\n }\n }\n\n async delete(runId: string): Promise<void> {\n const eventPath = this.eventsPath(runId);\n await this.eventChains.get(eventPath);\n this.eventChains.delete(eventPath);\n await Promise.allSettled([\n fsp.unlink(this.snapshotPath(runId)),\n fsp.unlink(eventPath),\n fsp.unlink(this.controlPath(runId)),\n ]);\n this.eventWritesSinceCheck.delete(eventPath);\n await this.removeFromIndex(runId);\n }\n\n // \u2500\u2500 internal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private safe(runId: string): string {\n return runId.replace(/[^a-zA-Z0-9._-]/g, '_');\n }\n\n private async ensureBaseDir(): Promise<void> {\n this.baseDirReady ??= ensureDir(this.baseDir).catch((error: unknown) => {\n this.baseDirReady = undefined;\n throw error;\n });\n await this.baseDirReady;\n }\n\n private async appendEventInternal(filePath: string, event: SddBoardEvent): Promise<void> {\n await this.ensureBaseDir();\n await fsp.appendFile(filePath, `${JSON.stringify(event)}\\n`, { mode: 0o600 });\n\n const writes = (this.eventWritesSinceCheck.get(filePath) ?? 0) + 1;\n if (writes < this.eventSizeCheckEvery) {\n this.eventWritesSinceCheck.set(filePath, writes);\n return;\n }\n this.eventWritesSinceCheck.set(filePath, 0);\n\n const stat = await fsp.stat(filePath);\n if (stat.size <= this.eventMaxBytes) return;\n await this.compactEventTail(filePath, stat.size);\n }\n\n private async compactEventTail(filePath: string, size: number): Promise<void> {\n if (this.eventKeepBytes === 0) {\n await atomicWrite(filePath, '', { mode: 0o600 });\n return;\n }\n const handle = await fsp.open(filePath, 'r');\n let retained: Buffer;\n try {\n const length = Math.min(size, this.eventKeepBytes);\n const start = size - length;\n const buffer = Buffer.allocUnsafe(length);\n const { bytesRead } = await handle.read(buffer, 0, length, start);\n retained = buffer.subarray(0, bytesRead);\n\n const previous = Buffer.allocUnsafe(1);\n await handle.read(previous, 0, 1, start - 1);\n if (previous[0] !== 0x0a) {\n retained = retained.subarray(retained.indexOf(0x0a) + 1);\n }\n } finally {\n await handle.close();\n }\n // Close the reader before replacing the file. Windows rejects rename over\n // an open destination handle (EPERM/EBUSY), turning rotation into repeated\n // retry delays and leaving the log unbounded.\n await atomicWrite(filePath, retained, { mode: 0o600 });\n }\n\n private async drainControlInternal(\n filePath: string,\n ): Promise<Array<{ ts: number; type: string; payload?: unknown }>> {\n try {\n const stat = await this.controlFileIO.stat(filePath);\n if (stat.size === 0) return [];\n } catch {\n return [];\n }\n\n return withFileLock(filePath, async () => {\n let raw: string;\n try {\n const stat = await this.controlFileIO.stat(filePath);\n if (stat.size === 0) return [];\n raw = await this.controlFileIO.readFile(filePath, 'utf8');\n } catch {\n return [];\n }\n try {\n await this.controlFileIO.truncate(filePath, 0);\n } catch {\n // Leave the commands on disk for the next drain instead of applying\n // them repeatedly from a queue that could not be acknowledged.\n return [];\n }\n return raw\n .split('\\n')\n .filter((line) => line.trim())\n .map((line) => {\n try {\n return JSON.parse(line) as { ts: number; type: string; payload?: unknown };\n } catch {\n return null;\n }\n })\n .filter(\n (command): command is { ts: number; type: string; payload?: unknown } => command !== null,\n );\n });\n }\n\n private async readIndex(): Promise<SddBoardIndex> {\n const signature = await this.indexSignature();\n if (this.cachedIndex && sameIndexSignature(signature, this.cachedIndexSignature)) {\n return this.cachedIndex;\n }\n try {\n const raw = await fsp.readFile(this.indexPath, 'utf8');\n const parsed = JSON.parse(raw) as SddBoardIndex;\n if (parsed?.version === 1) {\n parsed.entries.sort((a, b) => b.updatedAt - a.updatedAt);\n this.cachedIndex = parsed;\n this.cachedIndexSignature = signature;\n return parsed;\n }\n } catch {\n /* no index yet */\n }\n this.cachedIndex = { version: 1, entries: [] };\n this.cachedIndexSignature = signature;\n return this.cachedIndex;\n }\n\n private async updateIndex(snapshot: SddBoardSnapshot): Promise<void> {\n const current = await this.readIndex();\n const index: SddBoardIndex = {\n version: 1,\n entries: current.entries.map((entry) => ({ ...entry })),\n };\n const entry: SddBoardIndexEntry = {\n runId: snapshot.runId,\n specId: snapshot.specId,\n title: snapshot.title,\n status: snapshot.status,\n total: snapshot.progress.total,\n completed: snapshot.progress.completed,\n updatedAt: snapshot.updatedAt,\n };\n const idx = index.entries.findIndex((e) => e.runId === snapshot.runId);\n if (idx >= 0) index.entries[idx] = entry;\n else index.entries.push(entry);\n index.entries.sort((a, b) => b.updatedAt - a.updatedAt);\n await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 0o600 });\n this.cachedIndex = index;\n this.cachedIndexSignature = await this.indexSignature();\n }\n\n private async removeFromIndex(runId: string): Promise<void> {\n const current = await this.readIndex();\n const index: SddBoardIndex = {\n version: 1,\n entries: current.entries\n .filter((entry) => entry.runId !== runId)\n .map((entry) => ({ ...entry })),\n };\n await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 0o600 });\n this.cachedIndex = index;\n this.cachedIndexSignature = await this.indexSignature();\n }\n\n private async indexSignature(): Promise<IndexSignature | null> {\n try {\n const stat = await fsp.stat(this.indexPath);\n return { size: stat.size, mtimeMs: stat.mtimeMs, ctimeMs: stat.ctimeMs };\n } catch {\n return null;\n }\n }\n}\n\nexport function sameIndexSignature(a: IndexSignature | null, b: IndexSignature | null): boolean {\n if (a === null || b === null) return a === b;\n return a.size === b.size && a.mtimeMs === b.mtimeMs && a.ctimeMs === b.ctimeMs;\n}\n", "/**\n * SddBoardProjector\n *\n * Composes a live SDD board snapshot from a running graph and streams it to\n * every surface. It subscribes to `TaskTracker` mutations (the source of truth\n * for task state) plus the run's `sdd.*` lifecycle events (status / wave /\n * deadlock), and on each change \u2014 throttled \u2014 rebuilds a `SddBoardSnapshot`,\n * emits `sdd.board.snapshot` on the EventBus, persists it (JSON) and appends the\n * triggering event to the board's JSONL log.\n *\n * The graph is the single source of truth: task status/assignee/worktree live\n * on the nodes (the run mutates them through the tracker), so the projector\n * mostly re-derives the snapshot and only tracks run-level status/wave/deadlock.\n */\n\nimport type { EventBus, EventMap } from '@wrongstack/core/kernel';\nimport { DefaultSecretScrubber } from '@wrongstack/core/security';\nimport type { TaskTracker } from '@wrongstack/core/tasking';\nimport type { SecretScrubber, TaskGraph } from '@wrongstack/core/types';\nimport {\n buildBoardSnapshot,\n type SddBoardFeedEntry,\n type SddBoardSnapshot,\n type SddBoardStatus,\n type SddDeadlockChain,\n shortIdMap,\n} from './board-types.js';\nimport type { SddBoardEvent } from './sdd-board-store.js';\n\nexport interface SddBoardPersistence {\n saveSnapshot(snapshot: SddBoardSnapshot): Promise<void>;\n appendEvent(runId: string, event: SddBoardEvent): Promise<void>;\n}\n\nfunction summarizeToolInput(input: unknown, scrubber: SecretScrubber): string | undefined {\n if (!input || typeof input !== 'object' || Array.isArray(input)) return undefined;\n const record = input as Record<string, unknown>;\n\n // Paths are useful task telemetry and have a narrow meaning. Commands,\n // queries, and patterns are arbitrary user-controlled text: even after the\n // credential scrubber runs they can contain short passwords or other values\n // that do not match a known secret shape, so never copy them into durable\n // board state.\n for (const key of ['filePath', 'path'] as const) {\n const value = record[key];\n if (typeof value === 'string' && value.trim()) {\n const compact = scrubber.scrub(value).replace(/\\s+/g, ' ').trim();\n return compact.length > 240 ? `${compact.slice(0, 239)}\u2026` : compact;\n }\n }\n if (typeof record['command'] === 'string' || typeof record['cmd'] === 'string') {\n return '[command omitted]';\n }\n if (typeof record['query'] === 'string' || typeof record['pattern'] === 'string') {\n return '[query omitted]';\n }\n return undefined;\n}\n\nexport interface SddBoardProjectorOptions {\n runId: string;\n graph: TaskGraph;\n tracker: TaskTracker;\n events: EventBus;\n /** Parent session id for emitted `sdd.board.snapshot` events. */\n sessionId?: string | (() => string | undefined) | undefined;\n /** Persist snapshots + audit events (optional \u2014 omit for in-memory only). */\n store?: SddBoardPersistence | undefined;\n specId?: string | undefined;\n /** Run-level default worker model/provider/fallbacks (shown in the board header). */\n defaultModel?: string | undefined;\n defaultProvider?: string | undefined;\n fallbackModels?: string[] | undefined;\n /** Base branch the run's squash commits land on (for the board + rollback). */\n baseBranch?: string | undefined;\n /** Snapshot coalescing window in ms (default 250). */\n throttleMs?: number | undefined;\n /** Clock injection for tests; defaults to Date.now. */\n now?: (() => number) | undefined;\n /** Scrubber used before worker telemetry becomes durable or user-visible. */\n secretScrubber?: SecretScrubber | undefined;\n}\n\nexport class SddBoardProjector {\n private readonly o: SddBoardProjectorOptions;\n private readonly now: () => number;\n private readonly throttleMs: number;\n private readonly shortId: Map<string, string>;\n private readonly scrubber: SecretScrubber;\n\n private status: SddBoardStatus = 'idle';\n private wave = 0;\n private startedAt: number;\n private deadlockChains: SddDeadlockChain[] = [];\n /** Live activity feed, most recent first (capped). */\n private feed: SddBoardFeedEntry[] = [];\n private static readonly FEED_CAP = 60;\n /** Rich history is retained independently so a busy board cannot erase a task's log. */\n private taskEvents = new Map<string, SddBoardFeedEntry[]>();\n private static readonly TASK_EVENT_CAP = 250;\n private finished = false;\n private runDeadlocked = false;\n private runStopped = false;\n /** Squash commits the run landed on the base branch (for post-run rollback). */\n private mergedCommits: Array<{ taskId: string; sha: string; title: string }> = [];\n /** Base branch reported by the run at start (overrides the constructor option). */\n private runBaseBranch: string | undefined;\n\n private timer: ReturnType<typeof setTimeout> | null = null;\n private readonly unsubs: Array<() => void> = [];\n /** Latest snapshot waiting behind an in-flight disk write. */\n private pendingSnapshot: SddBoardSnapshot | undefined;\n /** At most one persistence loop runs; intermediate snapshots are coalesced. */\n private saveLoop: Promise<void> | undefined;\n\n constructor(opts: SddBoardProjectorOptions) {\n this.o = opts;\n this.now = opts.now ?? Date.now;\n this.throttleMs = opts.throttleMs ?? 250;\n this.shortId = shortIdMap(opts.graph);\n this.scrubber = opts.secretScrubber ?? new DefaultSecretScrubber();\n this.startedAt = this.now();\n\n // Source of truth: any task mutation redraws the board.\n this.unsubs.push(opts.tracker.subscribe(() => this.markDirty()));\n\n // Run lifecycle \u2192 status/wave/deadlock + JSONL audit.\n this.onRun('sdd.run.started', (e) => {\n this.status = 'running';\n this.startedAt = this.now();\n if (e.baseBranch) this.runBaseBranch = e.baseBranch;\n this.markDirty();\n });\n this.onRun('sdd.run.finished', (e) => {\n this.finished = true;\n this.runDeadlocked = e.deadlocked;\n this.runStopped = e.stopped;\n this.flush(); // final snapshot persists synchronously\n });\n this.onRun('sdd.wave', (e) => {\n this.wave = e.wave;\n this.pushFeed({\n ts: this.now(),\n kind: 'wave',\n text: `Wave ${e.wave + 1} started \u00B7 ${e.batchSize} task(s) in parallel`,\n });\n this.markDirty();\n });\n this.onRun('sdd.deadlock', (e) => {\n this.deadlockChains = e.chains.map((c) => ({\n blocked: this.shortId.get(c.blocked) ?? c.blocked.slice(0, 6),\n blockedBy: c.blockedBy.map((b) => this.shortId.get(b) ?? b.slice(0, 6)),\n }));\n this.pushFeed({\n ts: this.now(),\n kind: 'deadlock',\n text: `Deadlock \u2014 ${e.chains.length} task(s) blocked by failed work`,\n });\n this.markDirty();\n });\n // Task lifecycle \u2192 live activity feed (task STATE comes from the tracker,\n // which already triggers a redraw; here we narrate \"what just happened\").\n this.onRun('sdd.task.started', (e) => {\n const sid = this.shortId.get(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'started',\n taskId: e.taskId,\n taskShortId: sid,\n agentName: e.agentName,\n text: `${e.agentName || 'a worker'} picked up ${sid ?? 'a task'}${this.titleOf(e.taskId)}`,\n });\n this.markDirty();\n });\n this.onRun('sdd.task.completed', (e) => {\n const sid = this.shortId.get(e.taskId);\n const agent = this.assigneeOf(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'completed',\n taskId: e.taskId,\n taskShortId: sid,\n agentName: agent,\n text: `${sid ?? 'task'}${this.titleOf(e.taskId)} completed${agent ? ` by ${agent}` : ''} \u00B7 ${(e.durationMs / 1000).toFixed(1)}s`,\n });\n this.markDirty();\n });\n this.onRun('sdd.task.failed', (e) => {\n const sid = this.shortId.get(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'failed',\n taskId: e.taskId,\n taskShortId: sid,\n agentName: this.assigneeOf(e.taskId),\n text: `${sid ?? 'task'}${this.titleOf(e.taskId)} failed \u2014 ${e.error}`,\n });\n this.markDirty();\n });\n this.onRun('sdd.task.retrying', (e) => {\n const sid = this.shortId.get(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'retrying',\n taskId: e.taskId,\n taskShortId: sid,\n text: `${sid ?? 'task'}${this.titleOf(e.taskId)} retrying (${e.attempt}/${e.maxRetries})`,\n });\n this.markDirty();\n });\n // Robustness events (completion gate / merge / supervisor / split) \u2014 narrate\n // \"why a task didn't just sail to done\" so the board never silently hides a\n // gate rejection, conflict, or supervisor verdict.\n this.onRun('sdd.task.verification_failed', (e) => {\n const sid = this.shortId.get(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'verification_failed',\n taskId: e.taskId,\n taskShortId: sid,\n agentName: this.assigneeOf(e.taskId),\n text: `${sid ?? 'task'}${this.titleOf(e.taskId)} failed verification \u2014 ${e.reason}`,\n });\n this.markDirty();\n });\n this.onRun('sdd.task.conflict', (e) => {\n const sid = this.shortId.get(e.taskId);\n const files = e.conflictFiles.length;\n this.pushFeed({\n ts: this.now(),\n kind: 'conflict',\n taskId: e.taskId,\n taskShortId: sid,\n agentName: this.assigneeOf(e.taskId),\n text: `${sid ?? 'task'}${this.titleOf(e.taskId)} merge conflict \u2014 ${files} file(s)${files ? `: ${e.conflictFiles.slice(0, 3).join(', ')}${files > 3 ? '\u2026' : ''}` : ''}`,\n });\n this.markDirty();\n });\n this.onRun('sdd.task.merged', (e) => {\n // Persist the run commit so a post-run rollback can revert it off disk.\n const title = this.o.graph.nodes.get(e.taskId)?.title ?? '';\n this.mergedCommits.push({ taskId: e.taskId, sha: e.sha, title });\n const sid = this.shortId.get(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'completed',\n taskId: e.taskId,\n taskShortId: sid,\n text: `${sid ?? 'task'}${this.titleOf(e.taskId)} merged \u2192 ${this.runBaseBranch ?? this.o.baseBranch ?? 'base'} (${e.sha.slice(0, 8)})`,\n });\n this.markDirty();\n });\n this.onRun('sdd.task.split', (e) => {\n const sid = this.shortId.get(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'split',\n taskId: e.taskId,\n taskShortId: sid,\n text: `${sid ?? 'task'}${this.titleOf(e.taskId)} split into ${e.subtaskIds.length} sub-task(s)`,\n });\n this.markDirty();\n });\n this.onRun('sdd.supervisor.decision', (e) => {\n const sid = this.shortId.get(e.taskId);\n this.pushFeed({\n ts: this.now(),\n kind: 'supervisor',\n taskId: e.taskId,\n taskShortId: sid,\n text: `supervisor \u2192 ${e.action} for ${sid ?? 'task'}${this.titleOf(e.taskId)}${e.rationale ? ` (${e.rationale})` : ''}`,\n });\n this.markDirty();\n });\n\n // Task-scoped worker telemetry \u2192 a readable audit log in the task drawer.\n // Require both run correlation and graph membership before accepting it.\n this.onTask('subagent.tool_executed', (e, taskId) => {\n const sid = this.shortId.get(taskId);\n const detail = summarizeToolInput(e.input, this.scrubber);\n const agentName = e.agentName ? this.scrubber.scrub(e.agentName) : undefined;\n const action = this.scrubber.scrub(e.name);\n this.pushFeed({\n ts: this.now(),\n kind: 'tool',\n taskId,\n taskShortId: sid,\n agentName,\n action,\n detail,\n durationMs: e.durationMs,\n ok: e.ok,\n text: `${agentName ?? 'worker'} ran ${action}${detail ? ` \u00B7 ${detail}` : ''}`,\n });\n void this.o.store?.appendEvent(this.o.runId, {\n ts: this.now(),\n type: 'subagent.tool_executed',\n payload: {\n runId: this.o.runId,\n taskId,\n subagentId: e.subagentId,\n agentName,\n name: action,\n durationMs: e.durationMs,\n ok: e.ok,\n detail,\n },\n });\n this.markDirty();\n });\n this.onTask('file.event', (e, taskId) => {\n if (e.scope !== 'task') return;\n const sid = this.shortId.get(taskId);\n const agentName = this.scrubber.scrub(e.agentName);\n const filePath = this.scrubber.scrub(e.filePath);\n this.pushFeed({\n ts: Date.parse(e.timestamp) || this.now(),\n kind: 'file',\n taskId,\n taskShortId: sid,\n agentName,\n action: e.operation,\n filePath,\n durationMs: e.durationMs,\n ok: true,\n text: `${e.operation} ${filePath}`,\n });\n void this.o.store?.appendEvent(this.o.runId, {\n ts: this.now(),\n type: 'file.event',\n payload: {\n runId: this.o.runId,\n taskId,\n agentName,\n operation: e.operation,\n filePath,\n toolName: this.scrubber.scrub(e.toolName),\n durationMs: e.durationMs,\n timestamp: e.timestamp,\n },\n });\n this.markDirty();\n });\n }\n\n private pushFeed(entry: SddBoardFeedEntry): void {\n this.feed.unshift(entry);\n if (this.feed.length > SddBoardProjector.FEED_CAP)\n this.feed.length = SddBoardProjector.FEED_CAP;\n if (entry.taskId) {\n const taskFeed = this.taskEvents.get(entry.taskId) ?? [];\n taskFeed.unshift(entry);\n if (taskFeed.length > SddBoardProjector.TASK_EVENT_CAP) {\n taskFeed.length = SddBoardProjector.TASK_EVENT_CAP;\n }\n this.taskEvents.set(entry.taskId, taskFeed);\n }\n }\n\n /** ` (title\u2026)` suffix for a feed line, or '' when the node/title is missing. */\n private titleOf(taskId: string): string {\n const t = this.o.graph.nodes.get(taskId)?.title;\n if (!t) return '';\n return ` (${t.length > 40 ? `${t.slice(0, 39)}\u2026` : t})`;\n }\n\n private assigneeOf(taskId: string): string | undefined {\n return this.o.graph.nodes.get(taskId)?.assignee;\n }\n\n /** Latest snapshot, built on demand (e.g. for a late-joining client). */\n snapshot() {\n return this.build();\n }\n\n /** Resolve once all in-flight snapshot persistence has settled. */\n async drain(): Promise<void> {\n while (this.saveLoop) await this.saveLoop;\n }\n\n /** Stop projecting and release subscriptions. */\n dispose(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n for (const u of this.unsubs) u();\n this.unsubs.length = 0;\n }\n\n // \u2500\u2500 internal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Subscribe to a run event scoped to this run id; also append to JSONL. */\n private onRun<K extends keyof EventMap>(event: K, handler: (e: EventMap[K]) => void): void {\n const wrapped = (e: EventMap[K]) => {\n if ((e as { runId?: string }).runId !== this.o.runId) return;\n void this.o.store?.appendEvent(this.o.runId, { ts: this.now(), type: event, payload: e });\n handler(e);\n };\n const off = this.o.events.on(event, wrapped as (p: EventMap[K]) => void);\n this.unsubs.push(off);\n }\n\n /** Subscribe to task-correlated telemetry and ignore events outside this graph. */\n private onTask<K extends keyof EventMap>(\n event: K,\n handler: (e: EventMap[K], taskId: string) => void,\n ): void {\n const wrapped = (e: EventMap[K]) => {\n const correlated = e as { taskId?: string; runId?: string };\n const taskId = correlated.taskId;\n if (!taskId || !this.o.graph.nodes.has(taskId)) return;\n if (correlated.runId !== this.o.runId) return;\n handler(e, taskId);\n };\n const off = this.o.events.on(event, wrapped as (p: EventMap[K]) => void);\n this.unsubs.push(off);\n }\n\n private resolveStatus(completed: number, total: number): SddBoardStatus {\n if (!this.finished) return this.status;\n if (this.runDeadlocked) return 'deadlocked';\n if (total > 0 && completed >= total) return 'completed';\n // A user-stopped run is a TERMINAL 'stopped' \u2014 distinct from a live 'paused'\n // run (which is still resumable). Surfaces must treat 'stopped' as inactive\n // so the post-run lifecycle controls (clean / rollback / destroy) apply.\n if (this.runStopped) return 'stopped';\n return 'failed';\n }\n\n private build() {\n const snap = buildBoardSnapshot(\n this.o.graph,\n {\n runId: this.o.runId,\n specId: this.o.specId,\n status: 'running',\n startedAt: this.startedAt,\n wave: this.wave,\n deadlockChains: this.deadlockChains,\n defaultModel: this.o.defaultModel,\n defaultProvider: this.o.defaultProvider,\n fallbackModels: this.o.fallbackModels,\n baseBranch: this.runBaseBranch ?? this.o.baseBranch,\n mergedCommits: this.mergedCommits,\n },\n this.now(),\n );\n snap.status = this.resolveStatus(snap.progress.completed, snap.progress.total);\n snap.feed = this.feed.slice(0, SddBoardProjector.FEED_CAP);\n snap.taskEvents = Object.fromEntries(\n [...this.taskEvents].map(([taskId, entries]) => [taskId, entries.slice()]),\n );\n return snap;\n }\n\n private markDirty(): void {\n if (this.timer || this.finished) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n this.flush();\n }, this.throttleMs);\n }\n\n private flush(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n const snap = this.build();\n const sessionId = this.currentSessionId();\n this.o.events.emit('sdd.board.snapshot', {\n ...(sessionId ? { sessionId } : {}),\n runId: this.o.runId,\n snapshot: snap,\n });\n if (this.o.store) {\n // Keep one write in flight and one latest pending snapshot. If disk is\n // slower than the projection cadence, obsolete intermediate snapshots\n // are replaced instead of building an unbounded Promise/write backlog.\n this.pendingSnapshot = snap;\n this.startSaveLoop(this.o.store);\n }\n }\n\n private startSaveLoop(store: SddBoardPersistence): void {\n if (this.saveLoop) return;\n const loop = this.persistPendingSnapshots(store);\n this.saveLoop = loop;\n void loop.finally(() => {\n this.saveLoop = undefined;\n });\n }\n\n private async persistPendingSnapshots(store: SddBoardPersistence): Promise<void> {\n while (this.pendingSnapshot) {\n const snapshot = this.pendingSnapshot;\n this.pendingSnapshot = undefined;\n await store.saveSnapshot(snapshot).catch(() => {});\n }\n }\n\n private currentSessionId(): string | undefined {\n const value = typeof this.o.sessionId === 'function' ? this.o.sessionId() : this.o.sessionId;\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n }\n}\n", "import type { SddBoardSnapshot } from './board-types.js';\nimport type { SddSubtaskSpec } from './sdd-parallel-run.js';\n\n/**\n * Control surface over a live SDD run, exposed to every steering surface\n * (TUI, CLI-hosted WebUI in-process; standalone WebUI via a control file the\n * run drains). The run itself stays CLI-owned \u2014 this is the only sanctioned\n * way to pause / retry / reassign from outside the run loop.\n */\nexport interface SddRunControl {\n runId: string;\n specId?: string | undefined;\n pause(): void;\n resume(): void;\n stop(): void;\n retryTask(taskId: string): boolean;\n /** Requeue every failed task to pending (board \"Retry all failed\"). Returns the count. */\n retryAllFailed(): number;\n reassignTask(taskId: string, agentName: string): boolean;\n /** Set/override a task's worker model (+ optional provider). Next dispatch. */\n setTaskModel(taskId: string, model: string | undefined, provider?: string | undefined): boolean;\n /** Set/override a task's fallback model chain. Next dispatch. */\n setTaskFallbacks(taskId: string, fallbackModels: string[] | undefined): boolean;\n /** Set/override a task's completion-gate verification command. Next dispatch. */\n setTaskVerification(taskId: string, verificationCommand: string | undefined): boolean;\n /** Cancel a task \u2014 abort it if running, else mark it cancelled. */\n cancelTask(taskId: string): Promise<boolean> | boolean;\n /** Delete a not-started task from the graph (refused while running). */\n deleteTask(taskId: string): boolean;\n /** Split a task into sub-tasks (refused while running). Returns the new leaf ids. */\n splitTask(taskId: string, subtasks: SddSubtaskSpec[]): string[];\n /**\n * Remove every git worktree + branch the run created (refused while running \u2014\n * stop first). Returns the number removed.\n */\n cleanupWorktrees(): Promise<number>;\n /**\n * Undo the run's merged commits by reverting each on the base branch (refused\n * while running). History-preserving; refuses on a dirty tree / revert conflict.\n */\n rollback(): Promise<{ ok: boolean; reverted: number; reason?: string }>;\n /** Base branch the run's squash commits land on (worktree runs only). */\n getBaseBranch(): string | undefined;\n /** Squash commits the run landed on the base branch, in landing order. */\n getMergedCommits(): ReadonlyArray<{ taskId: string; sha: string; title: string }>;\n /** Latest board snapshot (built on demand). */\n snapshot(): SddBoardSnapshot;\n isRunning(): boolean;\n}\n\n/**\n * In-process registry of the active SDD run. One run is active at a time (a\n * single fleet drives it); a new run replaces the previous. Lives in the CLI\n * process where the fleet runs.\n */\nexport class SddRunRegistry {\n private current: SddRunControl | null = null;\n\n register(control: SddRunControl): void {\n this.current = control;\n }\n\n clear(runId: string): void {\n if (this.current?.runId === runId) this.current = null;\n }\n\n getActive(): SddRunControl | null {\n return this.current;\n }\n}\n", "// SddInterviewDriver \u2014 a headless, REPL-free wrapper around AISpecBuilder that\n// drives the interactive Spec-Driven-Development interview (questioning \u2192 spec\n// \u2192 implementation plan \u2192 task graph) from any surface (WebUI, CLI, tests).\n//\n// The CLI `/sdd` slash command historically owned this loop via module-singleton\n// state (`sddState`) plus thin detection helpers in `packages/cli` \u2014 which the\n// WebUI cannot import (layer rule: webui \u21CF cli). This driver lifts the *pure*\n// logic into core so every surface shares one implementation: feed it the\n// agent's text output, it detects the spec / plan / task JSON, advances the\n// AISpecBuilder phases, and persists the resulting TaskGraph to disk so the run\n// machinery (SddParallelRun) can pick it up.\n//\n// The driver never runs the agent itself \u2014 the caller runs `agent.run(prompt)`\n// and feeds the output back via `ingestAgentOutput`. That keeps core free of any\n// agent-loop / provider coupling.\n\nimport { TaskTracker } from '@wrongstack/core/tasking';\nimport type { Specification, TaskGraph, TaskNode } from '@wrongstack/core/types';\nimport { buildBoardTasks, type SddBoardColumn, type SddBoardTask } from './board-types.js';\nimport { AISpecBuilder, type AISpecPhase, type AISpecSessionPersistence } from './spec-builder.js';\nimport type { SpecStore } from './spec-store.js';\nimport { TaskGenerator } from './task-generator.js';\nimport type { TaskGraphStore } from './task-graph-store.js';\n\nexport interface SddInterviewDriverOptions {\n /** Disk-backed spec store (`wpaths.projectSpecs`). */\n specStore: SpecStore;\n /** Disk-backed task-graph store (`wpaths.projectTaskGraphs`). */\n graphStore: TaskGraphStore;\n /** Persist the interview session here so a reconnect can resume it. */\n sessionPath?: string | undefined;\n /** Durable interview session owner. Takes precedence over `sessionPath`. */\n sessionPersistence?: AISpecSessionPersistence | undefined;\n /** Project context string injected into the questioning prompt. */\n projectContext?: string | undefined;\n minQuestions?: number | undefined;\n maxQuestions?: number | undefined;\n}\n\n/** A serialisable view of the interview, streamed to observing surfaces. */\nexport interface SddInterviewSnapshot {\n sessionId: string;\n phase: AISpecPhase;\n title: string;\n /** The operator's original goal prompt (verbatim). `title` is a short heading. */\n goal: string;\n questionCount: number;\n minQuestions: number;\n maxQuestions: number;\n answers: Array<{ question: string; answer: string }>;\n /** Last agent utterance (open question / plan prose) \u2014 used for resume UI. */\n lastAgentText?: string | undefined;\n /** Most recent run id started from this interview, if any. */\n lastRunId?: string | undefined;\n /** True when this snapshot was rehydrated from disk (not a fresh start). */\n resumed?: boolean | undefined;\n spec?:\n | {\n id: string;\n title: string;\n overview: string;\n requirements: Array<{ priority: string; description: string }>;\n }\n | undefined;\n graphId?: string | undefined;\n taskCount: number;\n /**\n * Topologically-laid-out task graph (once decomposed) \u2014 lets the wizard\n * render the same animated DAG as the live board (\"decomposition reveal\").\n */\n board?: { tasks: SddBoardTask[]; columns: SddBoardColumn[] } | undefined;\n /** The current AI prompt for this phase (what to send the agent next). */\n prompt: string;\n}\n\n/** What `ingestAgentOutput` detected and acted on. */\nexport interface SddIngestResult {\n specDetected: boolean;\n implementationDetected: boolean;\n tasksDetected: boolean;\n graphId?: string | undefined;\n}\n\nexport class SddInterviewDriver {\n readonly builder: AISpecBuilder;\n private readonly o: SddInterviewDriverOptions;\n private readonly minQuestions: number;\n private readonly maxQuestions: number;\n private tracker: TaskTracker | null = null;\n private graph: TaskGraph | null = null;\n /** Set when {@link loadExisting} successfully rehydrated a durable session. */\n private resumedFromDisk = false;\n\n constructor(opts: SddInterviewDriverOptions) {\n this.o = opts;\n this.minQuestions = opts.minQuestions ?? 2;\n this.maxQuestions = opts.maxQuestions ?? 10;\n this.builder = new AISpecBuilder({\n store: opts.specStore,\n sessionPath: opts.sessionPath,\n sessionPersistence: opts.sessionPersistence,\n projectContext: opts.projectContext,\n minQuestions: this.minQuestions,\n maxQuestions: this.maxQuestions,\n });\n }\n\n /** Begin a fresh interview. Returns the first AI prompt (a question kickoff). */\n start(title: string, intent?: string): string {\n this.builder.resetForNewInterview();\n this.builder.startSession(title, intent);\n this.tracker = null;\n this.graph = null;\n this.resumedFromDisk = false;\n return this.builder.getAIPrompt();\n }\n\n /**\n * Resume a previously-persisted interview. Re-hydrates the task\n * graph too when one was already produced. Returns true if a session loaded.\n */\n async loadExisting(): Promise<boolean> {\n const loaded = await this.builder.loadSession();\n if (!loaded) return false;\n const graphId = this.builder.getTaskGraphId();\n if (graphId) {\n const graph = await this.o.graphStore.load(graphId);\n if (graph) {\n this.graph = graph;\n const tracker = new TaskTracker({ store: this.o.graphStore });\n tracker.setGraph(graph);\n this.tracker = tracker;\n }\n }\n this.resumedFromDisk = true;\n return true;\n }\n\n /** Drop the durable session (if any) and clear in-memory interview state. */\n async discard(): Promise<void> {\n await this.builder.deleteSession();\n this.builder.resetForNewInterview();\n this.tracker = null;\n this.graph = null;\n this.resumedFromDisk = false;\n }\n\n setLastAgentText(text: string): Promise<void> {\n return this.builder.setLastAgentText(text);\n }\n\n getLastAgentText(): string | undefined {\n return this.builder.getLastAgentText();\n }\n\n setLastRunId(runId: string): Promise<void> {\n return this.builder.setLastRunId(runId);\n }\n\n getLastRunId(): string | undefined {\n return this.builder.getLastRunId();\n }\n\n wasResumed(): boolean {\n return this.resumedFromDisk;\n }\n\n phase(): AISpecPhase {\n return this.builder.getPhase();\n }\n\n currentPrompt(): string {\n return this.builder.getAIPrompt();\n }\n\n getTracker(): TaskTracker | null {\n return this.tracker;\n }\n\n getGraph(): TaskGraph | null {\n return this.graph;\n }\n\n /** Record a Q/A pair (the agent asked `question`, the user replied `answer`). */\n submitAnswer(question: string, answer: string): void {\n this.builder.addAnswer(question, answer);\n }\n\n /**\n * Feed the agent's text output back into the interview. Detects, in order:\n * 1. a Specification JSON \u2192 setSpec (phase \u2192 spec_review) + persist to SpecStore\n * 2. an implementation plan (implementation phase) \u2192 setImplementation\n * 3. a task JSON array \u2192 build + persist a TaskGraph\n * Each step is independent and best-effort; a malformed payload is ignored\n * rather than thrown, so a chatty agent turn never breaks the interview.\n */\n async ingestAgentOutput(text: string): Promise<SddIngestResult> {\n const result: SddIngestResult = {\n specDetected: false,\n implementationDetected: false,\n tasksDetected: false,\n };\n\n // 1. Spec JSON \u2192 spec_review.\n if (!this.builder.getSession().spec) {\n const spec = this.builder.tryParseSpecFromOutput(text);\n if (spec) {\n this.builder.setSpec(spec);\n await this.persistSpec(spec);\n result.specDetected = true;\n }\n }\n\n // 2. Implementation plan (only meaningful in the implementation phase).\n if (this.builder.getPhase() === 'implementation') {\n if (this.trySaveImplementationPlan(text)) result.implementationDetected = true;\n }\n\n // 3. Task JSON array \u2192 TaskGraph (requires a spec to anchor the graph).\n const session = this.builder.getSession();\n if (session.spec) {\n const built = await this.tryBuildTasksFromOutput(text);\n if (built) {\n result.tasksDetected = true;\n result.graphId = built;\n }\n }\n\n return result;\n }\n\n /**\n * Advance to the next phase (mirrors `/sdd approve`). When moving into the\n * executing phase, guarantees a task graph exists \u2014 deterministically\n * generating one from the approved spec if the agent never emitted a valid\n * task array. Returns the new phase and its AI prompt.\n */\n async approve(): Promise<{ phase: AISpecPhase; prompt: string }> {\n const phase = this.builder.approve();\n if (phase === 'executing') {\n await this.ensureTaskGraph();\n }\n return { phase, prompt: this.builder.getAIPrompt() };\n }\n\n /**\n * Ensure a TaskGraph exists for the approved spec. If the agent already\n * produced one (via `ingestAgentOutput`), returns it; otherwise builds a\n * deterministic graph from the spec's requirements via TaskGenerator. This is\n * the robustness backstop: a run can always start, even if the model never\n * emitted a parseable task array.\n */\n async ensureTaskGraph(): Promise<TaskGraph | null> {\n if (this.graph) return this.graph;\n const spec = this.builder.getSession().spec;\n if (!spec) return null;\n\n const tracker = new TaskTracker({ store: this.o.graphStore });\n const generator = new TaskGenerator({\n taskTracker: tracker,\n verificationFromAcceptance: process.env['WRONGSTACK_SDD_VERIFY_FROM_ACCEPTANCE'] === '1',\n });\n const graph = await generator.generateFromSpec(spec);\n this.tracker = tracker;\n this.graph = graph;\n await this.persistGraph(graph);\n await this.builder.setTaskGraphId(graph.id);\n // Flush the session synchronously so a reconnect (loadExisting) sees the\n // graphId \u2014 setTaskGraphId's own save is awaited; this is a defensive\n // double-flush that also keeps resume behaviour robust across edge cases.\n await this.builder.saveSession();\n return graph;\n }\n\n snapshot(): SddInterviewSnapshot {\n const s = this.builder.getSession();\n const spec = s.spec;\n return {\n sessionId: s.id,\n phase: s.phase,\n title: s.title,\n goal: s.userIntent || s.title,\n questionCount: s.questionCount,\n minQuestions: this.minQuestions,\n maxQuestions: this.maxQuestions,\n answers: s.answers.map((a) => ({ question: a.question, answer: a.answer })),\n lastAgentText: s.lastAgentText,\n lastRunId: s.lastRunId,\n resumed: this.resumedFromDisk || undefined,\n spec: spec\n ? {\n id: spec.id,\n title: spec.title,\n overview: spec.overview,\n requirements: spec.requirements.map((r) => ({\n priority: r.priority,\n description: r.description,\n })),\n }\n : undefined,\n graphId: s.taskGraphId,\n taskCount: this.graph ? this.graph.nodes.size : 0,\n board: this.graph ? buildBoardTasks(this.graph) : undefined,\n prompt: this.builder.getAIPrompt(),\n };\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async persistSpec(spec: Specification): Promise<void> {\n try {\n await this.o.specStore.save(spec);\n } catch {\n // best-effort \u2014 the in-memory session still has the spec\n }\n }\n\n private async persistGraph(graph: TaskGraph): Promise<void> {\n try {\n await this.o.graphStore.save(graph);\n } catch {\n // best-effort \u2014 the in-memory tracker still drives the run\n }\n }\n\n /**\n * Port of the CLI `trySaveImplementationPlan` operating on this driver's\n * builder. Captures the prose plan that precedes the task JSON block.\n */\n private trySaveImplementationPlan(text: string): boolean {\n const current = this.builder.getSession().implementation ?? '';\n const jsonStart = text.match(/```json\\s*\\[/);\n if (jsonStart?.index && jsonStart.index > 0) {\n const plan = text.substring(0, jsonStart.index).trim();\n if (plan.length > 50 && plan !== current && !isExplanatoryText(plan)) {\n this.builder.setImplementation(plan);\n return true;\n }\n }\n if (\n text.length > 100 &&\n !text.includes('```json') &&\n text.trim() !== current &&\n !isExplanatoryText(text)\n ) {\n this.builder.setImplementation(text.trim());\n return true;\n }\n return false;\n }\n\n /**\n * Port of the CLI `trySaveTasksFromAIOutput`: parse a task JSON array from the\n * agent output, build (or extend) the tracker + graph, persist to disk, and\n * link the graphId to the session. Returns the graphId on success.\n */\n private async tryBuildTasksFromOutput(text: string): Promise<string | undefined> {\n const json = this.builder.extractJSONArray(text);\n if (!json) return undefined;\n\n let tasks: Array<Record<string, unknown>>;\n try {\n tasks = JSON.parse(json) as Array<Record<string, unknown>>;\n } catch {\n return undefined;\n }\n const valid = tasks.filter(\n (t) => t && typeof t === 'object' && typeof t.title === 'string' && t.title.length > 0,\n );\n if (valid.length === 0) return undefined;\n\n // ingestAgentOutput only invokes this helper after confirming a spec.\n const spec = this.builder.getSession().spec!;\n\n if (!this.tracker) {\n const tracker = new TaskTracker({ store: this.o.graphStore });\n this.graph = await tracker.createGraph(spec.id, spec.title);\n this.tracker = tracker;\n }\n const tracker = this.tracker;\n const graph = this.graph!;\n // Two passes: (1) create every node, recording every reference key by which\n // a `dependsOn` entry might name it (declared id, positional `t1`/`1`, title);\n // (2) resolve each task's `dependsOn` refs into real `depends_on` edges. This\n // is what turns a flat task list into a true dependency DAG \u2014 the scheduler\n // then runs independent tasks in parallel and dependent ones in order.\n const refMap = new Map<string, string>();\n const created: Array<{ nodeId: string; task: Record<string, unknown> }> = [];\n valid.forEach((task, i) => {\n const node = addTaskToTracker(tracker, task);\n created.push({ nodeId: node.id, task });\n if (typeof task.id === 'string' && task.id.trim()) {\n refMap.set(task.id.trim().toLowerCase(), node.id);\n }\n refMap.set(`t${i + 1}`, node.id);\n refMap.set(String(i + 1), node.id);\n refMap.set(normalizeTaskRef(String(task.title)), node.id);\n });\n for (const { nodeId, task } of created) {\n const deps = Array.isArray(task.dependsOn) ? task.dependsOn : [];\n for (const ref of deps) {\n const depId = refMap.get(normalizeTaskRef(String(ref)));\n // addDependency self/duplicate/cycle-guards; a stale ref just no-ops.\n if (depId && depId !== nodeId) tracker.addDependency(depId, nodeId);\n }\n }\n await this.persistGraph(graph);\n await this.builder.setTaskGraphId(graph.id);\n // Flush so a reconnect resumes with the graph linked (see ensureTaskGraph).\n await this.builder.saveSession();\n return graph.id;\n }\n}\n\nconst TASK_TYPES = ['feature', 'bugfix', 'refactor', 'docs', 'test', 'chore'] as const;\nconst TASK_PRIORITIES = ['critical', 'high', 'medium', 'low'] as const;\n\n/** Normalize a dependsOn reference (id / positional / title) for map lookup. */\nfunction normalizeTaskRef(ref: string): string {\n return ref.trim().toLowerCase();\n}\n\nfunction addTaskToTracker(tracker: TaskTracker, task: Record<string, unknown>): TaskNode {\n return tracker.addNode({\n title: String(task.title),\n description: String(task.description ?? ''),\n type: (TASK_TYPES as readonly string[]).includes(String(task.type))\n ? (String(task.type) as (typeof TASK_TYPES)[number])\n : 'feature',\n priority: (TASK_PRIORITIES as readonly string[]).includes(String(task.priority))\n ? (String(task.priority) as (typeof TASK_PRIORITIES)[number])\n : 'medium',\n status: 'pending',\n estimateHours: Number(task.estimateHours) || 2,\n tags: Array.isArray(task.tags) ? task.tags.map(String) : [],\n });\n}\n\n/**\n * True when the text reads like conversational filler rather than a structured\n * implementation plan. Ported verbatim from the CLI detection so behaviour is\n * identical across surfaces.\n */\nexport function isExplanatoryText(text: string): boolean {\n const lower = text.toLowerCase();\n return (\n lower.startsWith(\"i'\") ||\n lower.startsWith('i will') ||\n lower.startsWith('let me') ||\n lower.startsWith(\"here's my\") ||\n lower.startsWith('here is my') ||\n lower.startsWith(\"i'm going to\") ||\n lower.startsWith('first, let me') ||\n lower.startsWith('sure') ||\n lower.startsWith('of course') ||\n lower.startsWith('okay') ||\n lower.startsWith('ok,') ||\n lower.startsWith('sounds good') ||\n lower.startsWith('no problem') ||\n (text.split('\\n').length < 3 && !text.includes('.'))\n );\n}\n", "import type { Specification, SpecRequirement, SpecSection } from '@wrongstack/core/types';\nimport { ERROR_CODES, SddError } from '@wrongstack/core/types';\nimport { expectDefined, toErrorMessage } from '@wrongstack/core/utils';\nimport {\n type AISpecPhase,\n type AISpecSession,\n type AISpecSessionPersistence,\n isAISpecSession,\n} from './sdd-session-types.js';\nimport type { SpecStore } from './spec-store.js';\n\n// \u2500\u2500\u2500 Session Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport {\n type AISpecPhase,\n type AISpecSession,\n type AISpecSessionPersistence,\n type CollectedAnswer,\n isAISpecSession,\n} from './sdd-session-types.js';\n\n// \u2500\u2500\u2500 Builder Options \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AISpecBuilderOptions {\n store: SpecStore;\n /** Minimum questions the AI should ask. Default: 2 */\n minQuestions?: number | undefined;\n /** Maximum questions before forcing spec generation. Default: 10 */\n maxQuestions?: number | undefined;\n /** Project context string (package.json, file structure, etc.) */\n projectContext?: string | undefined;\n /** Legacy file persistence path. Production hosts provide `sessionPersistence`. */\n sessionPath?: string | undefined;\n /** Durable session owner. Takes precedence over `sessionPath`. */\n sessionPersistence?: AISpecSessionPersistence | undefined;\n}\n\n// \u2500\u2500\u2500 AI Prompts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction buildQuestioningPrompt(session: AISpecSession, min: number, max: number): string {\n const answered = session.answers.length;\n const remaining = Math.max(0, min - answered);\n const budget = max - answered;\n\n const lines: string[] = [\n `\u2550\u2550\u2550 SDD Spec Builder \u2550\u2550\u2550`,\n `Feature: \"${session.title}\"`,\n session.userIntent ? `Intent: ${session.userIntent}` : '',\n `Phase: Questioning (${answered} answered, ${budget} remaining budget)`,\n '',\n '**Instructions for AI:**',\n '',\n 'You are conducting a specification interview. Your job is to ask the user',\n 'intelligent, contextual questions to understand what they want to build.',\n '',\n `You have asked ${answered} questions so far.`,\n ];\n\n if (remaining > 0) {\n lines.push(`You MUST ask at least ${remaining} more question(s) before generating the spec.`);\n } else if (budget <= 0) {\n lines.push('You have reached the maximum question budget. Generate the spec NOW.');\n } else {\n lines.push(\n 'You may ask more questions if needed, or generate the spec if you have enough information.',\n 'Ask a question ONLY if it reveals something you genuinely need to know.',\n );\n }\n\n lines.push(\n '',\n '**Rules:**',\n '- Ask ONE question at a time',\n '- Questions must be specific and contextual \u2014 never generic',\n '- Adapt based on previous answers',\n '- Cover: scope, constraints, edge cases, integrations, security, performance as relevant',\n '- When you have enough info, respond with the full specification in JSON format',\n '- This is a planning interview: respond with TEXT ONLY (a question, or the spec JSON).',\n ' Do NOT write or edit files, and do NOT run shell/terminal commands \u2014 the code is',\n ' written later, after the plan is approved.',\n '',\n `**Question budget:** ${budget}/${max} remaining`,\n `**Minimum required:** ${remaining > 0 ? remaining : 'met'}`,\n );\n\n if (session.projectContext) {\n lines.push('', '**Project Context:**', '```', session.projectContext, '```');\n }\n\n if (answered > 0) {\n lines.push('', '**Conversation so far:**');\n for (let i = 0; i < answered; i++) {\n const a = expectDefined(session.answers[i]);\n lines.push(``, `Q${i + 1}: ${a.question}`, `A${i + 1}: ${a.answer}`);\n }\n }\n\n lines.push(\n '',\n '---',\n 'Now either:',\n `1. Ask your next question (if you need more info)`,\n `2. Generate the complete specification as JSON (if ready)`,\n '',\n 'If generating spec, output JSON inside ```json code block with this structure:',\n '```json',\n '{',\n ' \"title\": \"...\",',\n ' \"overview\": \"...\",',\n ' \"sections\": [{ \"type\": \"overview|requirements|architecture|api|data|security|acceptance\", \"title\": \"...\", \"content\": \"...\", \"level\": 1 }],',\n ' \"requirements\": [{ \"id\": \"REQ-1\", \"type\": \"functional|non-functional|security|performance|ux\", \"priority\": \"critical|high|medium|low\", \"description\": \"...\", \"acceptanceCriteria\": [\"...\"] }]',\n '}',\n '```',\n );\n\n return lines.filter(Boolean).join('\\n');\n}\n\nfunction buildSpecReviewPrompt(session: AISpecSession): string {\n const spec = session.spec;\n if (!spec) return 'No spec generated yet.';\n\n const reqSummary = spec.requirements.map((r) => ` [${r.priority}] ${r.description}`).join('\\n');\n\n return [\n `\u2550\u2550\u2550 Spec Review \u2550\u2550\u2550`,\n `Feature: \"${spec.title}\"`,\n `Requirements: ${spec.requirements.length}`,\n '',\n '**Specification:**',\n spec.overview,\n '',\n '**Requirements:**',\n reqSummary,\n '',\n '---',\n 'Approve this spec? The AI will then generate an implementation plan and tasks.',\n 'Say \"approve\" to proceed, or describe what needs to change.',\n ].join('\\n');\n}\n\nfunction buildImplementationPrompt(session: AISpecSession): string {\n const spec = session.spec;\n if (!spec) return 'No spec to implement.';\n\n const reqList = spec.requirements.map((r) => ` - [${r.priority}] ${r.description}`).join('\\n');\n\n return [\n `\u2550\u2550\u2550 Implementation Planning \u2550\u2550\u2550`,\n `Feature: \"${spec.title}\"`,\n `Requirements: ${spec.requirements.length}`,\n '',\n '**Requirements to implement:**',\n reqList,\n '',\n '**Instructions for AI:**',\n 'Generate a detailed implementation plan for this specification.',\n 'This is a PLANNING step \u2014 describe the plan and emit the task JSON as TEXT. Do NOT',\n 'create or edit files and do NOT run shell/terminal commands here; the tasks you list',\n 'are executed later, one by one, after you approve them.',\n 'Include:',\n '1. Architecture decisions',\n '2. File structure changes',\n '3. Key implementation details',\n '4. Dependency requirements',\n '5. Testing strategy',\n '',\n '**IMPORTANT:** After the plan, you MUST generate executable tasks as a JSON array.',\n 'Each task should be a concrete, actionable step. Output the JSON inside a ```json code block:',\n '```json',\n '[',\n ' {',\n ' \"id\": \"t1\",',\n ' \"title\": \"Create auth middleware\",',\n ' \"description\": \"Implement JWT verification middleware for protected routes\",',\n ' \"type\": \"feature\",',\n ' \"priority\": \"critical\",',\n ' \"estimateHours\": 3,',\n ' \"dependsOn\": [],',\n ' \"tags\": [\"auth\", \"middleware\"]',\n ' },',\n ' {',\n ' \"id\": \"t2\",',\n ' \"title\": \"Write auth tests\",',\n ' \"description\": \"Unit and integration tests for authentication flow\",',\n ' \"type\": \"test\",',\n ' \"priority\": \"high\",',\n ' \"estimateHours\": 2,',\n ' \"dependsOn\": [\"t1\"],',\n ' \"tags\": [\"test\", \"auth\"]',\n ' }',\n ']',\n '```',\n '',\n 'Rules:',\n '- Give every task a short stable \"id\" (t1, t2, \u2026). Reference prerequisites in \"dependsOn\"',\n ' as a list of those ids \u2014 this builds the real dependency graph that drives parallel vs',\n ' sequential execution.',\n '- \"dependsOn\": [] means the task is independent and may run in parallel with other roots.',\n '- A task with dependsOn runs ONLY after every listed task completes. Model true ordering:',\n ' tests depend on the feature they test, docs/integration depend on the parts they cover.',\n '- Do NOT create cycles (t1\u2192t2\u2192t1). Keep chains as shallow as correctness allows so',\n ' independent work runs concurrently.',\n '- Use type: \"feature\" for code, \"test\" for tests, \"docs\" for documentation, \"chore\" for config',\n '- Use priority: \"critical\" for blockers, \"high\" for core features, \"medium\" for nice-to-haves, \"low\" for polish',\n ].join('\\n');\n}\n\nfunction buildTaskReviewPrompt(session: AISpecSession): string {\n return [\n `\u2550\u2550\u2550 Task Review \u2550\u2550\u2550`,\n `Feature: \"${session.spec?.title ?? session.title}\"`,\n '',\n session.implementation ?? 'No implementation plan yet.',\n '',\n '---',\n 'Ready to execute these tasks? Say \"execute\" to begin, or describe changes needed.',\n ].join('\\n');\n}\n\nfunction buildExecutingPrompt(session: AISpecSession): string {\n return [\n `\u2550\u2550\u2550 Task Execution \u2550\u2550\u2550`,\n `Feature: \"${session.spec?.title ?? session.title}\"`,\n '',\n '**Instructions for AI:**',\n 'Execute the tasks one by one in the order shown in the task list above.',\n '',\n 'For each task:',\n '1. Implement the code (create/modify files)',\n '2. Write tests if applicable',\n '3. After completing a task, tell the user to run: /sdd done <task number or title>',\n '4. Then move to the next task',\n '',\n '**Important:**',\n '- Focus on ONE task at a time',\n '- After completing each task, explicitly state what you did',\n '- Tell the user: \"Run /sdd done <N> to mark this task complete\"',\n '- Then proceed to the next task automatically',\n '- When ALL tasks are done, provide a summary of everything implemented',\n '',\n 'Start executing the first pending task now.',\n ].join('\\n');\n}\n\n// \u2500\u2500\u2500 Spec Builder Class \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * AI-driven specification builder. Instead of static questions, this builder\n * tracks conversation state and generates prompts that instruct the AI agent\n * to ask contextual questions and build specifications interactively.\n */\nexport class AISpecBuilder {\n private session: AISpecSession;\n private readonly store: SpecStore;\n private readonly minQuestions: number;\n private readonly maxQuestions: number;\n private readonly sessionPath?: string | undefined;\n private readonly sessionPersistence?: AISpecSessionPersistence | undefined;\n\n constructor(opts: AISpecBuilderOptions) {\n this.store = opts.store;\n this.minQuestions = opts.minQuestions ?? 2;\n this.maxQuestions = opts.maxQuestions ?? 10;\n this.sessionPath = opts.sessionPath;\n this.sessionPersistence = opts.sessionPersistence;\n this.session = {\n id: crypto.randomUUID(),\n phase: 'questioning',\n title: '',\n userIntent: '',\n projectContext: opts.projectContext ?? '',\n answers: [],\n questionCount: 0,\n approved: false,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n }\n\n // \u2500\u2500 Session Persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Save session state to the configured durable owner. */\n async saveSession(): Promise<void> {\n if (!this.sessionPersistence && !this.sessionPath) return;\n try {\n if (this.sessionPersistence) {\n await this.sessionPersistence.save(structuredClone(this.session));\n return;\n }\n const fsp = await import('node:fs/promises');\n const path = await import('node:path');\n const { atomicWrite } = await import('@wrongstack/core/utils');\n const sessionPath = expectDefined(this.sessionPath);\n await fsp.mkdir(path.dirname(sessionPath), { recursive: true });\n // atomicWrite: torn save would corrupt the SDD session JSON and the\n // next load would silently fall back to a fresh session.\n await atomicWrite(sessionPath, JSON.stringify(this.session, null, 2));\n } catch (error) {\n // Best-effort persistence \u2014 don't crash if save fails\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'sdd.persist.failed',\n message: String(error),\n timestamp: Date.now(),\n }),\n );\n }\n }\n\n /** Load session state from the configured durable owner. */\n async loadSession(): Promise<boolean> {\n if (this.sessionPersistence) {\n const loaded = await this.sessionPersistence.load();\n if (isAISpecSession(loaded)) {\n this.session = loaded;\n return true;\n }\n return false;\n }\n if (!this.sessionPath) return false;\n try {\n const fsp = await import('node:fs/promises');\n const raw = await fsp.readFile(this.sessionPath, 'utf8');\n const loaded = JSON.parse(raw) as AISpecSession;\n if (isAISpecSession(loaded)) {\n this.session = loaded;\n return true;\n }\n } catch {\n // No saved session or invalid file\n }\n return false;\n }\n\n /** Delete the saved session from the configured durable owner. */\n async deleteSession(): Promise<void> {\n if (this.sessionPersistence) {\n await this.sessionPersistence.delete();\n return;\n }\n if (!this.sessionPath) return;\n try {\n const fsp = await import('node:fs/promises');\n await fsp.unlink(this.sessionPath);\n } catch {\n // File might not exist\n }\n }\n\n /** Auto-save helper. saveSession() already handles best-effort persistence. */\n private autoSave(): void {\n void this.saveSession();\n }\n\n // \u2500\u2500 Session Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Start a new session with a title and optional intent. */\n startSession(title: string, intent?: string): void {\n this.session.title = title;\n this.session.userIntent = intent ?? '';\n this.session.phase = 'questioning';\n this.session.updatedAt = Date.now();\n this.autoSave();\n }\n\n /** Get current session state (readonly). */\n getSession(): Readonly<AISpecSession> {\n return { ...this.session };\n }\n\n /** Get the current phase. */\n getPhase(): AISpecPhase {\n return this.session.phase;\n }\n\n // \u2500\u2500 AI Prompt Generation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Get the AI prompt for the current phase.\n * This prompt is injected into the conversation so the AI agent knows\n * what to do next (ask a question, generate a spec, etc.).\n */\n getAIPrompt(): string {\n switch (this.session.phase) {\n case 'questioning':\n return buildQuestioningPrompt(this.session, this.minQuestions, this.maxQuestions);\n case 'spec_review':\n return buildSpecReviewPrompt(this.session);\n case 'implementation':\n return buildImplementationPrompt(this.session);\n case 'task_review':\n return buildTaskReviewPrompt(this.session);\n case 'executing':\n return buildExecutingPrompt(this.session);\n case 'done':\n return 'All tasks completed. Specification is fully implemented.';\n }\n }\n\n // \u2500\u2500 Answer Processing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Record a question/answer pair from the AI conversation.\n * Call this when the AI asks a question and the user responds.\n */\n addAnswer(question: string, answer: string): void {\n this.session.answers.push({ question, answer, timestamp: Date.now() });\n this.session.questionCount++;\n this.session.updatedAt = Date.now();\n this.autoSave();\n }\n\n /**\n * Check if more questions should be asked.\n * Returns false if max reached or if the AI has signaled it has enough info.\n */\n shouldContinueQuestioning(): boolean {\n return this.session.questionCount < this.maxQuestions;\n }\n\n /**\n * Check if minimum questions have been asked.\n */\n hasMetMinimumQuestions(): boolean {\n return this.session.questionCount >= this.minQuestions;\n }\n\n // \u2500\u2500 Phase Transitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Set the generated specification and move to spec_review phase.\n */\n setSpec(spec: Specification): void {\n this.session.spec = spec;\n this.session.phase = 'spec_review';\n this.session.updatedAt = Date.now();\n this.autoSave();\n }\n\n /**\n * Approve the current phase and advance to the next.\n * questioning \u2192 spec_review (requires spec to be set)\n * spec_review \u2192 implementation\n * implementation \u2192 task_review (requires implementation to be set)\n * task_review \u2192 executing\n * executing \u2192 done\n */\n approve(): AISpecPhase {\n switch (this.session.phase) {\n case 'questioning':\n if (!this.session.spec) {\n throw new SddError({\n message: 'Cannot approve: no spec generated yet.',\n code: ERROR_CODES.SDD_INVALID_STATE,\n context: { phase: 'questioning', sessionId: this.session.id },\n });\n }\n this.session.phase = 'spec_review';\n break;\n case 'spec_review':\n this.session.phase = 'implementation';\n break;\n case 'implementation':\n this.session.phase = 'task_review';\n break;\n case 'task_review':\n this.session.phase = 'executing';\n break;\n case 'executing':\n this.session.phase = 'done';\n break;\n case 'done':\n break;\n }\n this.session.approved = true;\n this.session.updatedAt = Date.now();\n this.autoSave();\n return this.session.phase;\n }\n\n /**\n * Set the implementation plan text.\n */\n setImplementation(plan: string): void {\n this.session.implementation = plan;\n this.session.phase = 'task_review';\n this.session.updatedAt = Date.now();\n this.autoSave();\n }\n\n /**\n * Mark session as done.\n */\n markDone(): void {\n this.session.phase = 'done';\n this.session.updatedAt = Date.now();\n this.autoSave();\n }\n\n /**\n * Set the task graph ID for this session. Awaits the save so a caller that\n * immediately follows with `await saveSession()` cannot end up with the\n * awaited write committing first and the fire-and-forget rename reverting\n * the persisted `taskGraphId` to its pre-set value. Same race window that\n * broke `setLastAgentText`/`setLastRunId` on the resume test.\n */\n async setTaskGraphId(graphId: string): Promise<void> {\n this.session.taskGraphId = graphId;\n await this.saveSession();\n }\n\n /**\n * Get the task graph ID for this session.\n */\n getTaskGraphId(): string | undefined {\n return this.session.taskGraphId;\n }\n\n /**\n * Persist the last agent utterance so resume can rehydrate the UI + Q/A\n * pairing. Awaits the save so the next mutation in the call chain (e.g.\n * `setLastRunId`) cannot fire a concurrent save that overwrites this one\n * with a stale snapshot \u2014 the fire-and-forget `autoSave()` pattern leaves\n * a race window where an earlier queued save may commit its rename after\n * a later one, silently reverting the persisted state.\n */\n async setLastAgentText(text: string): Promise<void> {\n this.session.lastAgentText = text;\n this.session.updatedAt = Date.now();\n await this.saveSession();\n }\n\n getLastAgentText(): string | undefined {\n return this.session.lastAgentText;\n }\n\n /** Record a run kicked off from this interview (board deep-link after restart). See {@link setLastAgentText} for the awaited-save rationale. */\n async setLastRunId(runId: string): Promise<void> {\n this.session.lastRunId = runId;\n this.session.updatedAt = Date.now();\n await this.saveSession();\n }\n\n getLastRunId(): string | undefined {\n return this.session.lastRunId;\n }\n\n /**\n * Hard-reset in-memory session fields while keeping the same session id /\n * store binding. Used when the operator abandons a resumed interview and\n * starts a brand-new goal (the next save overwrites the session file).\n */\n resetForNewInterview(): void {\n this.session.phase = 'questioning';\n this.session.title = '';\n this.session.userIntent = '';\n this.session.answers = [];\n this.session.questionCount = 0;\n this.session.spec = undefined;\n this.session.implementation = undefined;\n this.session.taskGraphId = undefined;\n this.session.lastAgentText = undefined;\n this.session.lastRunId = undefined;\n this.session.approved = false;\n this.session.updatedAt = Date.now();\n }\n\n // \u2500\u2500 Spec Persistence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Save the current spec to the store.\n */\n async saveSpec(): Promise<Specification> {\n if (!this.session.spec) {\n throw new SddError({\n message: 'No spec to save.',\n code: ERROR_CODES.SDD_NOT_READY,\n context: { sessionId: this.session.id },\n });\n }\n await this.store.save(this.session.spec);\n return this.session.spec;\n }\n\n // \u2500\u2500 Spec Generation Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Parse a spec from a JSON string (from AI output).\n * Validates and normalizes the structure.\n */\n parseSpecFromJSON(jsonStr: string): Specification {\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonStr);\n } catch (e) {\n throw new SddError({\n message: 'Invalid JSON for spec',\n code: ERROR_CODES.SDD_PARSE_FAILED,\n cause: e,\n context: { detail: toErrorMessage(e) },\n });\n }\n\n if (!parsed || typeof parsed !== 'object') {\n throw new SddError({\n message: 'Spec JSON must be an object',\n code: ERROR_CODES.SDD_VALIDATION_FAILED,\n context: { actualType: typeof parsed },\n });\n }\n\n const raw = parsed as Record<string, unknown>;\n const now = Date.now();\n\n const title = String(raw.title ?? this.session.title);\n const overview = String(raw.overview ?? '');\n\n // Validate overview is not empty\n if (!overview || overview === 'undefined') {\n throw new SddError({\n message: 'Spec must have an overview',\n code: ERROR_CODES.SDD_VALIDATION_FAILED,\n context: { field: 'overview', title },\n });\n }\n\n const rawSections = Array.isArray(raw.sections) ? raw.sections : [];\n const sections: SpecSection[] = rawSections\n .filter((s: unknown) => s && typeof s === 'object')\n .map((s: Record<string, unknown>) => ({\n type: ([\n 'overview',\n 'requirements',\n 'architecture',\n 'api',\n 'data',\n 'security',\n 'acceptance',\n ].includes(String(s.type))\n ? String(s.type)\n : 'overview') as SpecSection['type'],\n title: String(s.title ?? ''),\n content: String(s.content ?? ''),\n level: Number(s.level) || 1,\n }));\n\n const rawReqs = Array.isArray(raw.requirements) ? raw.requirements : [];\n const requirements: SpecRequirement[] = rawReqs\n .filter((r: unknown) => r && typeof r === 'object')\n .map((r: Record<string, unknown>, i: number) => ({\n id: String(r.id ?? `REQ-${i + 1}`),\n type: (['functional', 'non-functional', 'security', 'performance', 'ux'].includes(\n String(r.type),\n )\n ? String(r.type)\n : 'functional') as SpecRequirement['type'],\n priority: (['critical', 'high', 'medium', 'low'].includes(String(r.priority))\n ? String(r.priority)\n : 'medium') as SpecRequirement['priority'],\n description: String(r.description ?? ''),\n acceptanceCriteria: Array.isArray(r.acceptanceCriteria)\n ? r.acceptanceCriteria.map(String)\n : [],\n }));\n\n const spec: Specification = {\n id: crypto.randomUUID(),\n title,\n version: '0.1.0',\n status: 'draft',\n overview,\n sections,\n requirements,\n createdAt: now,\n updatedAt: now,\n metadata: {\n generatedBy: 'AISpecBuilder',\n sessionId: this.session.id,\n },\n };\n\n return spec;\n }\n\n /**\n * Extract JSON from AI output (handles ```json blocks and raw JSON).\n */\n extractJSON(text: string): string | null {\n // Try ```json ... ``` first\n const codeBlockMatch = text.match(/```json\\s*([\\s\\S]*?)```/);\n if (codeBlockMatch?.[1]) {\n return codeBlockMatch[1].trim();\n }\n\n // Try ``` ... ``` without language tag\n const genericBlockMatch = text.match(/```\\s*([\\s\\S]*?)```/);\n if (genericBlockMatch?.[1]) {\n const trimmed = genericBlockMatch[1].trim();\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n return trimmed;\n }\n }\n\n // Try raw JSON object\n const jsonMatch = text.match(/(\\{[\\s\\S]*\\})/);\n if (jsonMatch?.[1]) {\n try {\n JSON.parse(jsonMatch[1]);\n return jsonMatch[1];\n } catch {\n // not valid JSON\n }\n }\n\n return null;\n }\n\n /**\n * Detect if AI output contains a spec (JSON block).\n */\n hasSpecInOutput(text: string): boolean {\n return this.extractJSON(text) !== null;\n }\n\n /**\n * Try to parse a spec from AI output text.\n * Returns null if no valid spec found.\n */\n tryParseSpecFromOutput(text: string): Specification | null {\n const json = this.extractJSON(text);\n if (!json) return null;\n\n try {\n return this.parseSpecFromJSON(json);\n } catch {\n return null;\n }\n }\n\n // \u2500\u2500 JSON Array Extraction (for tasks) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Extract a JSON array from AI output (for task lists).\n */\n extractJSONArray(text: string): string | null {\n const codeBlockMatch = text.match(/```json\\s*([\\s\\S]*?)```/);\n if (codeBlockMatch?.[1]) {\n const trimmed = codeBlockMatch[1].trim();\n if (trimmed.startsWith('[')) return trimmed;\n }\n\n const arrayMatch = text.match(/(\\[[\\s\\S]*\\])/);\n if (arrayMatch?.[1]) {\n try {\n const parsed = JSON.parse(arrayMatch[1]);\n if (Array.isArray(parsed)) return arrayMatch[1];\n } catch {\n // not valid\n }\n }\n\n return null;\n }\n}\n", "import type { Specification } from '@wrongstack/core/types';\n\nexport type AISpecPhase =\n | 'questioning'\n | 'spec_review'\n | 'implementation'\n | 'task_review'\n | 'executing'\n | 'done';\n\nexport interface CollectedAnswer {\n question: string;\n answer: string;\n timestamp: number;\n}\n\nexport interface AISpecSession {\n id: string;\n phase: AISpecPhase;\n title: string;\n userIntent: string;\n projectContext: string;\n answers: CollectedAnswer[];\n questionCount: number;\n spec?: Specification | undefined;\n implementation?: string | undefined;\n taskGraphId?: string | undefined;\n /** Last agent message shown to the operator for reconnect continuity. */\n lastAgentText?: string | undefined;\n /** Most recent SDD run id started from this interview. */\n lastRunId?: string | undefined;\n approved: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\n/** Durable session adapter. Production uses project-scoped Kanban IPC. */\nexport interface AISpecSessionPersistence {\n load(): Promise<AISpecSession | null>;\n save(session: AISpecSession): Promise<void>;\n delete(): Promise<void>;\n}\n\nexport function isAISpecSession(value: unknown): value is AISpecSession {\n if (!value || typeof value !== 'object') return false;\n const session = value as Partial<AISpecSession>;\n return (\n typeof session.id === 'string' &&\n typeof session.phase === 'string' &&\n typeof session.title === 'string' &&\n typeof session.userIntent === 'string' &&\n Array.isArray(session.answers) &&\n typeof session.updatedAt === 'number'\n );\n}\n", "// startSddRun \u2014 the shared run-setup core for a multi-agent SDD parallel run.\n//\n// Extracted from the CLI `/sdd execute` handler so every surface (CLI slash\n// command + both WebUI servers) starts a run identically: orphan reset \u2192\n// SddParallelRun \u2192 live board projector \u2192 run registry \u2192 cross-process control\n// drain \u2192 run, with deterministic cleanup. The only thing that differs per\n// surface is the `subagentFactory` (CLI's director-backed factory vs the\n// runtime light factory) and whether git worktrees are available \u2014 both are\n// passed in, keeping this helper free of CLI/host coupling.\n\nimport type { Agent } from '@wrongstack/core/agent';\nimport type { AgentFactory } from '@wrongstack/core/coordination';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport { TOKENS } from '@wrongstack/core/kernel';\nimport type { TaskTracker } from '@wrongstack/core/tasking';\nimport type { SecretScrubber, TaskGraph } from '@wrongstack/core/types';\nimport type { WorktreeManager } from '@wrongstack/core/worktree';\nimport {\n drainKanbanWorkflowCommands,\n kanbanWorkflowId,\n subscribeKanbanWorkflowCommands,\n writeKanbanWorkflowState,\n} from '@wrongstack/kanban';\nimport { SddBoardProjector } from './sdd-board-projector.js';\nimport type { SddBoardStore } from './sdd-board-store.js';\nimport {\n type RunResult,\n SddParallelRun,\n type SddParallelRunOptions,\n type SddProgress,\n} from './sdd-parallel-run.js';\nimport type { SddRunRegistry } from './sdd-run-registry.js';\n\nexport interface StartSddRunOptions {\n tracker: TaskTracker;\n graph: TaskGraph;\n /** Leader agent \u2014 seeds the default factory and the run's project context. */\n agent: Agent;\n projectRoot: string;\n events: EventBus;\n /** Parent session id for all SDD EventBus emissions. */\n sessionId?: string | (() => string | undefined) | undefined;\n /** Per-task agent factory. Omit to run every task on the leader agent. */\n subagentFactory?: AgentFactory | undefined;\n /** Board snapshot/event compatibility cache. Durable control is owned by Kanban IPC. */\n boardStore: SddBoardStore;\n /** Registry the run is registered with for in-process control. */\n registry?: SddRunRegistry | undefined;\n parallelSlots?: number | undefined;\n /** Opt-in hard wall-clock cap per task (ms). Omit \u2192 no cap (idle reaper guards). */\n taskTimeoutMs?: number | undefined;\n /** Idle reaper per task (ms); resets on activity. Default 600_000 (10 min). */\n taskIdleTimeoutMs?: number | undefined;\n /** End-of-run failed-task auto-retry sweeps (bounded). Default 2. */\n maxFailedRetrySweeps?: number | undefined;\n /** Post-task verification gate (forwarded to SddParallelRun). Omit \u2192 no gate. */\n verifyTask?: SddParallelRunOptions['verifyTask'];\n /** Merge-conflict resolver (forwarded to SddParallelRun). Omit \u2192 retry-on-fresh-base then fail. */\n conflictResolver?: SddParallelRunOptions['conflictResolver'];\n /** Failure supervisor (forwarded to SddParallelRun). Omit \u2192 no rescue, plain terminal-fail. */\n superviseFailure?: SddParallelRunOptions['superviseFailure'];\n /** Run-level default worker model / provider / fallback chain (task overrides win). */\n defaultModel?: string | undefined;\n defaultProvider?: string | undefined;\n fallbackModels?: string[] | undefined;\n /** Per-task git worktree isolation. Omit \u2192 tasks share the working tree. */\n worktrees?: WorktreeManager | undefined;\n /** Bounded deadlock recovery rounds (default 1). */\n maxRecoveryRounds?: number | undefined;\n /** Progress callback (e.g. CLI renderer line). */\n onProgress?: ((p: SddProgress) => void) | undefined;\n /** Durable workflow-queue reconciliation interval in ms (default 500). */\n controlDrainMs?: number | undefined;\n /** Explicit compatibility mode for legacy file-codec tests and old hosts. */\n controlTransport?: 'kanban' | 'legacy-file' | undefined;\n /** Snapshot owner; defaults to Kanban IPC unless legacy control was requested. */\n boardStateTransport?: 'kanban' | 'legacy-file' | undefined;\n}\n\nexport interface SddRunHandle {\n run: SddParallelRun;\n runId: string;\n projector: SddBoardProjector;\n /** Resolves when the run finishes AND all teardown (drain/dispose/clear) is done. */\n completion: Promise<RunResult>;\n /** Request a clean stop (idempotent). */\n stop(): void;\n}\n\nexport interface SddControlCommand {\n type: string;\n payload?: unknown;\n}\n\n/** Apply one command drained from the cross-process board control channel. */\nexport function applySddControlCommand(run: SddParallelRun, command: SddControlCommand): void {\n const payload = (command.payload ?? {}) as {\n taskId?: string;\n agentName?: string;\n model?: string;\n provider?: string;\n fallbackModels?: string[];\n verificationCommand?: string;\n subtasks?: import('./sdd-parallel-run.js').SddSubtaskSpec[];\n };\n if (command.type === 'pause') run.pause();\n else if (command.type === 'resume') run.resume();\n else if (command.type === 'stop') run.stop();\n else if (command.type === 'retry' && payload.taskId) run.retryTask(payload.taskId);\n else if (command.type === 'retry_all_failed') run.retryAllFailed();\n else if (command.type === 'reassign' && payload.taskId)\n run.reassignTask(payload.taskId, payload.agentName ?? '');\n else if (command.type === 'set_task_model' && payload.taskId)\n run.setTaskModel(payload.taskId, payload.model, payload.provider);\n else if (command.type === 'set_task_fallbacks' && payload.taskId)\n run.setTaskFallbacks(payload.taskId, payload.fallbackModels);\n else if (command.type === 'set_task_verification' && payload.taskId)\n run.setTaskVerification(payload.taskId, payload.verificationCommand);\n else if (command.type === 'cancel_task' && payload.taskId)\n void run.cancelTask(payload.taskId).catch(() => {});\n else if (command.type === 'delete_task' && payload.taskId) run.deleteTask(payload.taskId);\n else if (command.type === 'split_task' && payload.taskId && payload.subtasks?.length)\n run.splitTask(payload.taskId, payload.subtasks);\n else if (command.type === 'cleanup_worktrees') void run.cleanupWorktrees().catch(() => {});\n else if (command.type === 'rollback') void run.rollback().catch(() => {});\n}\n\n/**\n * Wire up and start an SDD parallel run. Returns immediately with a handle whose\n * `completion` promise resolves once the run finishes and teardown is complete.\n * Orphaned in_progress tasks are reset up-front so a crashed prior run re-executes.\n */\nexport function startSddRun(opts: StartSddRunOptions): SddRunHandle {\n // Resume safety: orphaned in_progress tasks (from a prior crash, no agent\n // running them) are reset to pending so the run re-executes them.\n SddParallelRun.resetOrphans(opts.tracker);\n\n const run = new SddParallelRun({\n tracker: opts.tracker,\n graph: opts.graph,\n agent: opts.agent,\n projectRoot: opts.projectRoot,\n sessionId: opts.sessionId,\n parallelSlots: opts.parallelSlots,\n taskTimeoutMs: opts.taskTimeoutMs,\n taskIdleTimeoutMs: opts.taskIdleTimeoutMs,\n maxFailedRetrySweeps: opts.maxFailedRetrySweeps,\n verifyTask: opts.verifyTask,\n conflictResolver: opts.conflictResolver,\n superviseFailure: opts.superviseFailure,\n subagentFactory: opts.subagentFactory,\n events: opts.events,\n worktrees: opts.worktrees,\n maxRecoveryRounds: opts.maxRecoveryRounds ?? 1,\n onProgress: opts.onProgress,\n defaultModel: opts.defaultModel,\n defaultProvider: opts.defaultProvider,\n fallbackModels: opts.fallbackModels,\n });\n\n const workflowId = kanbanWorkflowId('sdd', run.runId);\n const legacyControl = opts.controlTransport === 'legacy-file';\n const legacyBoardState =\n opts.boardStateTransport === 'legacy-file' ||\n (opts.boardStateTransport === undefined && legacyControl);\n const boardPersistence = legacyBoardState\n ? opts.boardStore\n : {\n saveSnapshot: async (snapshot: import('./board-types.js').SddBoardSnapshot) => {\n await writeKanbanWorkflowState(opts.projectRoot, workflowId, snapshot);\n },\n // Detailed events remain append-only audit artifacts; they are not read\n // back as workflow authority.\n appendEvent: (runId: string, event: import('./sdd-board-store.js').SddBoardEvent) =>\n opts.boardStore.appendEvent(runId, event),\n };\n\n // Live board projector: streams sdd.board.snapshot, persists authoritative\n // state through Kanban IPC, and retains append-only audit events on disk.\n const projector = new SddBoardProjector({\n runId: run.runId,\n graph: opts.graph,\n tracker: opts.tracker,\n events: opts.events,\n store: boardPersistence,\n sessionId: opts.sessionId,\n specId: opts.graph.specId,\n defaultModel: opts.defaultModel,\n defaultProvider: opts.defaultProvider,\n fallbackModels: opts.fallbackModels,\n secretScrubber: opts.agent.container?.safeResolve(TOKENS.SecretScrubber) as\n | SecretScrubber\n | undefined,\n });\n\n opts.registry?.register({\n runId: run.runId,\n specId: opts.graph.specId,\n pause: () => run.pause(),\n resume: () => run.resume(),\n stop: () => run.stop(),\n retryTask: (id) => run.retryTask(id),\n retryAllFailed: () => run.retryAllFailed(),\n reassignTask: (id, name) => run.reassignTask(id, name),\n setTaskModel: (id, model, provider) => run.setTaskModel(id, model, provider),\n setTaskFallbacks: (id, fb) => run.setTaskFallbacks(id, fb),\n setTaskVerification: (id, cmd) => run.setTaskVerification(id, cmd),\n cancelTask: (id) => run.cancelTask(id),\n deleteTask: (id) => run.deleteTask(id),\n splitTask: (id, subtasks) => run.splitTask(id, subtasks),\n cleanupWorktrees: () => run.cleanupWorktrees(),\n rollback: () => run.rollback(),\n getBaseBranch: () => run.getBaseBranch(),\n getMergedCommits: () => run.getMergedCommits(),\n snapshot: () => projector.snapshot(),\n isRunning: () => run.isRunning(),\n });\n\n // Cross-process control channel: Kanban's elected project daemon owns an\n // atomic SQLite queue. Push notifications provide the fast path; a slow\n // reconciliation drain covers startup races and daemon restarts.\n let controlDrainInFlight = false;\n let controlDisposed = false;\n let unsubscribeControl: (() => void) | undefined;\n const drainControl = async (): Promise<void> => {\n if (controlDrainInFlight || controlDisposed) return;\n controlDrainInFlight = true;\n try {\n const commands = legacyControl\n ? await opts.boardStore.drainControl(run.runId)\n : await drainKanbanWorkflowCommands(opts.projectRoot, workflowId);\n for (const command of commands) applySddControlCommand(run, command);\n } catch (error) {\n // Kanban IPC is the SDD run's only cross-process control channel.\n // Silently swallowing a rejection here means a daemon outage, a\n // dropped socket, or a permissions error becomes a silent no-op\n // for the duration of the run \u2014 operators see a frozen board and\n // the run keeps running blind. Surface the error so the SDD log\n // records the loss and a follow-up reconciliation can retry.\n const message = error instanceof Error ? error.message : String(error);\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'sdd.control_drain_failed',\n runId: run.runId,\n workflowId,\n transport: legacyControl ? 'legacy-file' : 'kanban',\n message,\n timestamp: new Date().toISOString(),\n }),\n );\n } finally {\n controlDrainInFlight = false;\n }\n };\n\n if (!legacyControl) {\n void subscribeKanbanWorkflowCommands(opts.projectRoot, workflowId, () => {\n // `drainControl` already logs a structured warning on rejection;\n // the trailing `.catch` here only guards against unexpected throws\n // *outside* the drain (defensive \u2014 should never fire).\n void drainControl().catch(() => undefined);\n })\n .then((unsubscribe) => {\n if (controlDisposed) unsubscribe();\n else {\n unsubscribeControl = unsubscribe;\n void drainControl().catch(() => undefined);\n }\n })\n .catch((error) => {\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'sdd.control_subscribe_failed',\n runId: run.runId,\n workflowId,\n message: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n }),\n );\n });\n } else {\n // One-time compatibility import for commands left by a pre-IPC WebUI. New\n // commands are never written here in production. Same contract as the\n // kanban path: surface drain failures instead of swallowing them.\n void opts.boardStore\n .drainControl(run.runId)\n .then((commands) => {\n for (const command of commands) applySddControlCommand(run, command);\n })\n .catch((error) => {\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'sdd.control_drain_failed',\n runId: run.runId,\n workflowId,\n transport: 'legacy-file',\n message: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n }),\n );\n });\n }\n\n const drainMs = opts.controlDrainMs ?? 500;\n const controlTimer = setInterval(() => {\n void drainControl().catch(() => undefined);\n }, drainMs);\n // Best-effort: don't keep the event loop alive solely for the drain timer.\n (controlTimer as { unref?: () => void }).unref?.();\n\n const completion = (async (): Promise<RunResult> => {\n try {\n return await run.run();\n } finally {\n controlDisposed = true;\n clearInterval(controlTimer);\n unsubscribeControl?.();\n await projector.drain().catch(() => {});\n projector.dispose();\n opts.registry?.clear(run.runId);\n }\n })();\n\n return {\n run,\n runId: run.runId,\n projector,\n completion,\n stop: () => run.stop(),\n };\n}\n", "/**\n * SddParallelRun\n *\n * Drives a TaskGraph through ParallelEternalEngine's infrastructure\n * (DefaultMultiAgentCoordinator + AgentSubagentRunner) but powered by\n * SddTaskDecomposer \u2014 producing dependency-aware waves instead of\n * goal-driven iterations.\n *\n * One-shot: completes when all tasks are done OR a deadlock is detected.\n * Does NOT loop \u2014 each run() call is a discrete execution.\n *\n * Usage:\n * ```\n * const run = new SddParallelRun({ tracker, graph, agent, projectRoot });\n * await run.run({ onWave });\n * // or with progress callback:\n * await run.run({ onProgress: (p) => console.log(renderProgress(p)) });\n * ```\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { AgentFactory } from '@wrongstack/core/coordination';\nimport {\n DefaultMultiAgentCoordinator,\n makeAgentSubagentRunner,\n withDisabledToolFiltering,\n} from '@wrongstack/core/coordination';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type { TaskTracker } from '@wrongstack/core/tasking';\nimport type {\n MultiAgentConfig,\n SubagentConfig,\n TaskNode,\n TaskResult,\n} from '@wrongstack/core/types';\nimport type { WorktreeHandle } from '@wrongstack/core/worktree';\nimport { splitGraphNode } from './graph-split.js';\nimport { executeSddTask } from './sdd-task-execution.js';\nimport { SddTaskDecomposer, type TaskBatch } from './sdd-task-decomposer.js';\nimport type {\n RunResult,\n SddParallelRunOptions,\n SddProgress,\n SddSubtaskSpec,\n SddSupervisorVerdict,\n TaskOutcome,\n WaveResult,\n} from './sdd-parallel-run-types.js';\nexport type {\n RunResult,\n SddParallelRunOptions,\n SddProgress,\n SddSubtaskSpec,\n SddSupervisorVerdict,\n WaveResult,\n} from './sdd-parallel-run-types.js';\nexport class SddParallelRun {\n private readonly slots: number;\n /** Opt-in hard wall-clock cap (undefined \u2192 no cap; idle reaper guards instead). */\n private readonly timeoutMs: number | undefined;\n /** Idle reaper window (ms) \u2014 resets on activity; reaps only a genuine stall. */\n private readonly idleTimeoutMs: number;\n private readonly maxRetries: number;\n /** Max supervisor rescues per task before it must terminal-fail (loop guard). */\n private readonly maxSupervisorEscalations: number;\n /** Per-task count of supervisor rescues used (resets nothing \u2014 bounds the loop). */\n private supervisorEscalations = new Map<string, number>();\n /** Max end-of-run failed-task sweeps (see `maxFailedRetrySweeps`). */\n private readonly maxFailedSweeps: number;\n /** How many failed-task sweeps have run this `run()` so far. */\n private failedSweeps = 0;\n /** Completed-count snapshot at the last sweep, to detect a no-progress sweep. */\n private lastSweepCompleted = 0;\n private decomposer: SddTaskDecomposer;\n private coordinator: DefaultMultiAgentCoordinator | null = null;\n private stopRequested = false;\n private retryMap = new Map<string, number>();\n readonly runId: string;\n private readonly events?: EventBus | undefined;\n private readonly sessionIdSource: string | (() => string | undefined) | undefined;\n private readonly maxTotalWaves: number;\n private readonly maxWallClockMs?: number | undefined;\n private readonly maxRecoveryRounds: number;\n private recoveryRounds = 0;\n /** Per-run worker identities, so the board shows \"who is on what\". */\n private usedNicknames = new Set<string>();\n /** Per-task git worktree cwd (Layer 2 worktree isolation; empty otherwise). */\n private taskCwds = new Map<string, string>();\n /** Per-task git worktree branch, for board display. */\n private taskBranches = new Map<string, string>();\n /** Live worktree handles keyed by task id (for commit/merge/release). */\n private taskWorktrees = new Map<string, WorktreeHandle>();\n /** Live subagent id per running task \u2014 lets cancelTask() abort exactly one. */\n private taskSubagents = new Map<string, string>();\n /** Tasks the user cancelled mid-flight \u2014 skip retry, mark terminal-cancelled. */\n private cancelledTasks = new Set<string>();\n /**\n * Base branch the run's squash commits land on (captured once at start when\n * worktrees are enabled). Anchors a later `rollback()`.\n */\n private baseBranch: string | undefined;\n /**\n * Squash-merge commits this run landed on the base branch, in landing order.\n * `rollback()` reverts these (newest \u2192 oldest). Persisted via the board\n * snapshot so a post-run rollback can read them off disk.\n */\n private mergedCommits: Array<{ taskId: string; sha: string; title: string }> = [];\n /** Monotonic dispatch counter (unique subagent ids) + dispatch-round counter. */\n private dispatchSeq = 0;\n private round = 0;\n\n constructor(private readonly opts: SddParallelRunOptions) {\n this.slots = Math.min(16, Math.max(1, opts.parallelSlots ?? 2));\n // Wall-clock cap is OPT-IN (undefined \u2192 none). The idle reaper is the\n // default guard: it resets on every activity signal so a productive task\n // is never killed for running long \u2014 only a genuine stall is reaped.\n this.timeoutMs = opts.taskTimeoutMs;\n this.idleTimeoutMs = Math.max(1, opts.taskIdleTimeoutMs ?? 600_000);\n this.maxRetries = Math.max(0, opts.maxRetries ?? 3);\n this.maxSupervisorEscalations = Math.max(0, opts.maxSupervisorEscalations ?? 2);\n this.maxFailedSweeps = Math.max(0, opts.maxFailedRetrySweeps ?? 2);\n this.runId = opts.runId ?? `sdd-${randomUUID().slice(0, 8)}`;\n this.events = opts.events;\n this.sessionIdSource = opts.sessionId;\n // Backstop: even with retries + recovery the loop must terminate. Derive a\n // generous ceiling from the graph size unless the caller pins one.\n this.maxTotalWaves = opts.maxTotalWaves ?? opts.graph.nodes.size * (this.maxRetries + 2) + 10;\n this.maxWallClockMs = opts.maxWallClockMs;\n this.maxRecoveryRounds = Math.max(0, opts.maxRecoveryRounds ?? 0);\n this.decomposer = new SddTaskDecomposer(opts.tracker, opts.graph, {\n parallelSlots: this.slots,\n });\n }\n\n /** Type-safe emit on the optional EventBus (no-op when unwired). */\n private emit<K extends keyof import('@wrongstack/core/kernel').EventMap>(\n event: K,\n payload: import('@wrongstack/core/kernel').EventMap[K],\n ): void {\n const sessionId = this.currentSessionId();\n this.events?.emit(\n event,\n (sessionId\n ? { ...payload, sessionId }\n : payload) as import('@wrongstack/core/kernel').EventMap[K],\n );\n }\n\n private currentSessionId(): string | undefined {\n const value =\n typeof this.sessionIdSource === 'function' ? this.sessionIdSource() : this.sessionIdSource;\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n }\n\n // -------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------\n\n private paused = false;\n\n /** Trigger stop \u2014 causes run() to abort after the current wave. */\n stop(): void {\n this.stopRequested = true;\n this.paused = false;\n this.coordinator?.stopAll();\n }\n\n /** Pause: no new wave starts until resume() (the current wave finishes). */\n pause(): void {\n this.paused = true;\n }\n resume(): void {\n this.paused = false;\n }\n isPaused(): boolean {\n return this.paused;\n }\n isRunning(): boolean {\n return !this.stopRequested && !this.decomposer.isSettled();\n }\n\n /** Base branch the run's squash commits land on (undefined when worktrees off). */\n getBaseBranch(): string | undefined {\n return this.baseBranch;\n }\n\n /** Squash commits this run landed on the base branch, in landing order. */\n getMergedCommits(): ReadonlyArray<{ taskId: string; sha: string; title: string }> {\n return this.mergedCommits;\n }\n\n /**\n * Remove every git worktree + branch this run (and any prior run) created.\n * Refuses while the run is still live \u2014 cleaning a checkout under an active\n * worker would corrupt it. Stop first. Returns the number of worktrees removed\n * (0 when worktrees are disabled). Idempotent.\n */\n async cleanupWorktrees(): Promise<number> {\n if (this.isRunning()) return 0;\n const wt = this.opts.worktrees;\n if (!wt) return 0;\n // Release any handles this run still holds (kept on stop / needs-review).\n for (const [taskId, handle] of [...this.taskWorktrees]) {\n await wt.release(handle, { keep: false }).catch(() => {});\n this.forgetWorktree(taskId);\n }\n const { removed } = await wt.cleanupAllManaged();\n return removed;\n }\n\n /**\n * Undo the run's merged commits by reverting each on the base branch (history\n * preserving). Refuses while the run is still live (stop first). Returns the\n * revert outcome; a dirty tree or revert conflict surfaces as `ok:false`.\n */\n async rollback(): Promise<{ ok: boolean; reverted: number; reason?: string }> {\n if (this.isRunning())\n return { ok: false, reverted: 0, reason: 'run still active \u2014 stop it first' };\n const wt = this.opts.worktrees;\n if (!wt || !this.baseBranch) {\n return { ok: false, reverted: 0, reason: 'no worktree run to roll back' };\n }\n return wt.revertCommits(\n this.baseBranch,\n this.mergedCommits.map((c) => c.sha),\n );\n }\n\n /** Requeue a task to `pending` so the scheduler re-runs it (clears retries + cancel marker). */\n retryTask(taskId: string): boolean {\n if (!this.opts.tracker.getNode(taskId)) return false;\n this.retryMap.delete(taskId);\n this.persistRetries(taskId, 0);\n // Clear any cancel marker so a previously-cancelled task can run again.\n this.cancelledTasks.delete(taskId);\n this.opts.tracker.patchMetadata(taskId, { cancelled: undefined });\n this.opts.tracker.updateNodeStatus(taskId, 'pending', 'manual retry');\n return true;\n }\n\n /** Reassign a task to a specific agent name (reflected on the board). */\n reassignTask(taskId: string, agentName: string): boolean {\n if (!this.opts.tracker.getNode(taskId)) return false;\n this.opts.tracker.updateNode(taskId, { assignee: agentName });\n return true;\n }\n\n /**\n * Set/override a task's worker model (and optionally provider) \u2014 applied on its\n * NEXT dispatch (a running task must be cancelled + retried to take effect). The\n * assignment lives on node metadata so it survives crash \u2192 resume.\n */\n setTaskModel(taskId: string, model: string | undefined, provider?: string | undefined): boolean {\n if (!this.opts.tracker.getNode(taskId)) return false;\n this.opts.tracker.patchMetadata(taskId, {\n model,\n ...(provider !== undefined ? { provider } : {}),\n });\n return true;\n }\n\n /** Set/override a task's fallback model chain (applied on its next dispatch). */\n setTaskFallbacks(taskId: string, fallbackModels: string[] | undefined): boolean {\n if (!this.opts.tracker.getNode(taskId)) return false;\n this.opts.tracker.patchMetadata(taskId, { fallbackModels });\n return true;\n }\n\n /**\n * Set/override a task's verification command (the completion gate runs it in\n * the task's cwd and only lets the task complete on exit 0). Empty/undefined\n * clears it. Applied on the task's next verification \u2014 i.e. its next dispatch.\n */\n setTaskVerification(taskId: string, verificationCommand: string | undefined): boolean {\n if (!this.opts.tracker.getNode(taskId)) return false;\n const cmd = verificationCommand?.trim();\n this.opts.tracker.patchMetadata(taskId, { verificationCommand: cmd ? cmd : undefined });\n return true;\n }\n\n /**\n * Cancel a task. If it is currently running, abort its subagent and mark the\n * node terminally failed+cancelled (so the scheduler frees the slot and does\n * NOT retry it). If it has not started, it is simply marked cancelled. Use\n * `retryTask` to bring a cancelled task back. Returns false for an unknown task.\n */\n async cancelTask(taskId: string): Promise<boolean> {\n const node = this.opts.tracker.getNode(taskId);\n if (!node) return false;\n this.cancelledTasks.add(taskId);\n // Terminal failed + cancel marker: failed keeps dependents un-deadlocked,\n // the marker drives the \"Cancelled\" board look and blocks retry/auto-redispatch.\n this.opts.tracker.patchMetadata(taskId, { cancelled: true });\n this.opts.tracker.updateNodeStatus(taskId, 'failed', 'cancelled by user');\n this.emit('sdd.task.failed', {\n runId: this.runId,\n taskId,\n subagentId: '',\n error: 'cancelled by user',\n });\n const subagentId = this.taskSubagents.get(taskId);\n if (subagentId && this.coordinator) {\n await this.coordinator.stop(subagentId).catch(() => {});\n }\n return true;\n }\n\n /**\n * Delete a not-yet-started task from the graph (pending/blocked/failed only \u2014\n * never a running task; cancel it first). Removes the node and every edge\n * touching it; dependents lose this blocker. Returns false if missing or running.\n */\n deleteTask(taskId: string): boolean {\n const node = this.opts.tracker.getNode(taskId);\n if (!node) return false;\n if (node.status === 'in_progress' || this.taskSubagents.has(taskId)) return false;\n this.cancelledTasks.delete(taskId);\n this.retryMap.delete(taskId);\n return this.opts.tracker.removeNode(taskId);\n }\n\n /**\n * Split a task into sub-tasks and delegate them to separate workers. The new\n * leaves inherit the parent's blockers (so they don't start before the\n * parent's dependencies are met), every existing dependent is rewired to\n * depend on ALL leaves (so downstream work waits for the whole split), and the\n * parent becomes a `completed` container. Refuses a running task (cancel it\n * first) or empty subtask list. Returns the new leaf ids (empty on refusal).\n * The scheduler picks the new pending leaves up on its next dispatch pass.\n */\n splitTask(taskId: string, subtasks: SddSubtaskSpec[]): string[] {\n const leafIds = splitGraphNode(this.opts.tracker, taskId, subtasks, {\n isRunning: (id) => this.taskSubagents.has(id),\n });\n if (!leafIds.length) return [];\n this.retryMap.delete(taskId);\n this.persistRetries(taskId, 0);\n this.emit('sdd.task.split', { runId: this.runId, taskId, subtaskIds: leafIds });\n return leafIds;\n }\n\n private async waitWhilePaused(): Promise<void> {\n while (this.paused && !this.stopRequested) {\n await new Promise((r) => setTimeout(r, 100));\n }\n }\n\n /**\n * Continuous dependency-driven execution. Unlike a wave-barrier loop (where a\n * whole batch must finish before the next starts), this fills free worker\n * slots the instant a task's dependencies are satisfied: a fast task's\n * dependent starts immediately rather than waiting for a slow sibling. Truly\n * independent tasks run in parallel; dependency chains run in order. Returns\n * the final summary when the graph settles, deadlocks, stops, or hits a backstop.\n */\n async run(): Promise<RunResult> {\n this.stopRequested = false;\n this.restoreRetryMap();\n const startTime = Date.now();\n this.round = 0;\n this.dispatchSeq = 0;\n let totalDispatched = 0;\n\n this.buildCoordinator();\n\n // Capture the base branch once so a later rollback knows where the run's\n // squash commits landed (worktree path only; no-op without a manager).\n if (this.opts.worktrees && !this.baseBranch) {\n const base = await this.opts.worktrees.currentBase().catch(() => null);\n if (base) this.baseBranch = base.branch;\n }\n\n this.emit('sdd.run.started', {\n runId: this.runId,\n graphId: this.opts.graph.id,\n specId: this.opts.graph.specId,\n total: this.opts.graph.nodes.size,\n baseBranch: this.baseBranch,\n });\n\n this.recoveryRounds = 0;\n this.failedSweeps = 0;\n this.lastSweepCompleted = 0;\n let deadlocked = false;\n // node id \u2192 in-flight executeOne promise. size = live worker count.\n const running = new Map<string, Promise<TaskOutcome>>();\n\n const dispatch = (task: TaskNode): void => {\n totalDispatched++;\n const tracked = (async (): Promise<TaskOutcome> => {\n try {\n return await this.executeOne(task);\n } catch (err) {\n // A dispatch-time throw must not wedge the scheduler: mark the node\n // terminally failed (frees its dependents per failed-blocker rules).\n this.opts.tracker.updateNodeStatus(task.id, 'failed', `dispatch error: ${String(err)}`);\n this.emit('sdd.task.failed', {\n runId: this.runId,\n taskId: task.id,\n subagentId: '',\n error: String(err),\n });\n return { taskId: task.id, success: false };\n } finally {\n running.delete(task.id);\n }\n })();\n running.set(task.id, tracked);\n };\n\n while (!this.stopRequested) {\n // Run-level backstops \u2014 an autonomous run must always terminate.\n if (totalDispatched >= this.maxTotalWaves) break;\n if (this.maxWallClockMs && Date.now() - startTime >= this.maxWallClockMs) break;\n\n await this.waitWhilePaused();\n if (this.stopRequested) break;\n\n // Fill free slots with ready (dependency-satisfied) tasks not already running.\n let dispatchedThisRound = 0;\n const ready = this.decomposer.readyNodes().filter((t) => !running.has(t.id));\n for (const task of ready) {\n if (running.size >= this.slots) break;\n dispatch(task);\n dispatchedThisRound++;\n }\n if (dispatchedThisRound > 0) {\n this.emit('sdd.wave', {\n runId: this.runId,\n wave: this.round,\n batchSize: dispatchedThisRound,\n });\n this.round++;\n }\n\n if (running.size === 0) {\n // Nothing in flight and nothing dispatched this pass.\n if (this.decomposer.isSettled()) {\n // End-of-run failed-task sweep: requeue every terminal-failed\n // (non-cancelled) task and run them again, bounded by\n // maxFailedSweeps. Stop early once a sweep yields no new completions\n // (no progress) so a hopeless task can't spin the loop forever.\n const completed = this.opts.tracker.getProgress().completed;\n const madeProgress = this.failedSweeps === 0 || completed > this.lastSweepCompleted;\n if (\n this.failedSweeps < this.maxFailedSweeps &&\n madeProgress &&\n this.requeueFailedTasks() > 0\n ) {\n this.lastSweepCompleted = completed;\n this.failedSweeps++;\n continue;\n }\n break;\n }\n const chains = this.computeDeadlockChains();\n if (chains.length > 0) {\n this.emit('sdd.deadlock', { runId: this.runId, chains });\n if (this.recoveryRounds < this.maxRecoveryRounds && this.recoverFailedBlockers()) {\n this.recoveryRounds++;\n continue;\n }\n deadlocked = true;\n }\n // No running, no ready, no recoverable deadlock \u2192 no further progress.\n break;\n }\n\n // If we still have a free slot AND a ready task, loop to dispatch it now;\n // otherwise wait for any in-flight task to settle (which may unblock more).\n const moreReadyNow =\n running.size < this.slots && this.decomposer.readyNodes().some((t) => !running.has(t.id));\n if (!moreReadyNow) {\n await Promise.race(running.values());\n this.opts.onProgress?.(this.buildProgress());\n }\n }\n\n // Clean teardown on stop: interrupted tasks reset, worktrees released.\n if (this.stopRequested) await this.teardown();\n\n const finalProgress = this.opts.tracker.getProgress();\n\n this.emit('sdd.run.finished', {\n runId: this.runId,\n deadlocked,\n completed: finalProgress.completed,\n failed: finalProgress.failed,\n stopped: this.stopRequested,\n });\n\n return {\n totalWaves: this.round,\n totalCompleted: finalProgress.completed,\n totalFailed: finalProgress.failed,\n totalDurationMs: Date.now() - startTime,\n deadlocked,\n stopRequested: this.stopRequested,\n finalProgress,\n };\n }\n\n /**\n * Compute the blocking chains for a deadlock: every still-incomplete task and\n * the blockers (by node id) that are NOT completed. Failed blockers are\n * included since they're the usual deadlock cause once retries are exhausted.\n */\n private computeDeadlockChains(): Array<{ blocked: string; blockedBy: string[] }> {\n const tracker = this.opts.tracker;\n const chains: Array<{ blocked: string; blockedBy: string[] }> = [];\n for (const node of tracker.getAllNodes()) {\n if (node.status === 'completed' || node.status === 'failed') continue;\n const blockedBy = tracker\n .getBlockers(node.id)\n .filter((id) => tracker.getNode(id)?.status !== 'completed');\n if (blockedBy.length > 0) chains.push({ blocked: node.id, blockedBy });\n }\n return chains;\n }\n\n /** Requeue failed tasks that block an incomplete dependent. Returns true if any. */\n private recoverFailedBlockers(): boolean {\n const tracker = this.opts.tracker;\n let recovered = false;\n for (const node of tracker.getAllNodes({ status: ['failed'] })) {\n const blocksIncomplete = tracker.getDependents(node.id).some((d) => {\n const s = tracker.getNode(d)?.status;\n return s !== 'completed' && s !== 'failed';\n });\n if (blocksIncomplete) {\n this.retryMap.delete(node.id);\n this.persistRetries(node.id, 0);\n tracker.updateNodeStatus(node.id, 'pending', 'deadlock recovery');\n recovered = true;\n }\n }\n return recovered;\n }\n\n /**\n * Requeue every terminal-failed task that the user did NOT cancel, giving each\n * a fresh `maxRetries` budget. Shared by the automatic end-of-run sweep and\n * the manual \"retry all failed\" control. Returns the number requeued.\n */\n private requeueFailedTasks(reason = 'retry failed sweep'): number {\n const tracker = this.opts.tracker;\n let n = 0;\n for (const node of tracker.getAllNodes({ status: ['failed'] })) {\n if (this.cancelledTasks.has(node.id) || node.metadata?.cancelled) continue;\n this.retryMap.delete(node.id);\n this.persistRetries(node.id, 0);\n tracker.updateNodeStatus(node.id, 'pending', reason);\n this.emit('sdd.task.retrying', {\n runId: this.runId,\n taskId: node.id,\n attempt: 0,\n maxRetries: this.maxRetries,\n });\n n++;\n }\n return n;\n }\n\n /**\n * Manually requeue all failed tasks to `pending` (board \"Retry all failed\").\n * Unlike the automatic sweep this also clears any `cancelled` marker, so a\n * user can bring cancelled tasks back in the same action \u2014 mirroring\n * `retryTask`. Picked up by the running scheduler on its next dispatch pass.\n * Returns the number of tasks requeued.\n */\n retryAllFailed(): number {\n const failed = this.opts.tracker.getAllNodes({ status: ['failed'] });\n for (const node of failed) {\n this.cancelledTasks.delete(node.id);\n this.opts.tracker.patchMetadata(node.id, { cancelled: undefined });\n }\n return this.requeueFailedTasks('manual retry all');\n }\n\n /** Restore per-task retry counts persisted in node metadata (resume support). */\n private restoreRetryMap(): void {\n this.retryMap.clear();\n for (const node of this.opts.tracker.getAllNodes()) {\n const r = (node.metadata as { retries?: unknown } | undefined)?.retries;\n if (typeof r === 'number' && r > 0) this.retryMap.set(node.id, r);\n }\n }\n\n /**\n * Reset orphaned `in_progress` tasks (no agent runs them after a crash) back\n * to `pending` so a fresh run re-executes them. Call before constructing a run\n * from a reloaded graph. Static so callers don't need a run instance.\n */\n static resetOrphans(tracker: TaskTracker): number {\n let n = 0;\n for (const node of tracker.getAllNodes({ status: ['in_progress'] })) {\n tracker.updateNodeStatus(node.id, 'pending', 'resume: orphaned in_progress');\n n++;\n }\n return n;\n }\n\n /** Clean teardown after a stop: reset interrupted tasks + release worktrees. */\n private async teardown(): Promise<void> {\n for (const node of this.opts.tracker.getAllNodes({ status: ['in_progress'] })) {\n this.opts.tracker.updateNodeStatus(node.id, 'pending', 'run stopped');\n }\n const wt = this.opts.worktrees;\n if (wt) {\n for (const [taskId, handle] of [...this.taskWorktrees]) {\n await wt.release(handle, { keep: true }).catch(() => {});\n this.forgetWorktree(taskId);\n }\n }\n }\n\n // -------------------------------------------------------------------\n // Internal\n // -------------------------------------------------------------------\n\n private buildCoordinator(): void {\n const config: MultiAgentConfig = {\n coordinatorId: `sdd-parallel-${randomUUID().slice(0, 8)}`,\n maxConcurrent: this.slots,\n doneCondition: { type: 'all_tasks_done' },\n // Default budget guard for every spawned worker: idle reaper (resets on\n // activity) plus the opt-in wall-clock cap when one was configured. This\n // ensures the reaper applies even if a per-spawn config path is bypassed.\n defaultBudget: {\n idleTimeoutMs: this.idleTimeoutMs,\n ...(this.timeoutMs ? { timeoutMs: this.timeoutMs } : {}),\n },\n };\n this.coordinator = new DefaultMultiAgentCoordinator(config);\n // Wrap factory with disabled tool filtering to prevent subagents from\n // using the delegate tool (or any other disabledTools in their config)\n const baseFactory = this.opts.subagentFactory ?? this.defaultFactory();\n const filteredFactory = withDisabledToolFiltering(baseFactory);\n const runner = makeAgentSubagentRunner({\n factory: filteredFactory,\n hostEvents: this.events,\n } as Parameters<typeof makeAgentSubagentRunner>[0] & { hostEvents?: EventBus });\n this.coordinator.setRunner?.(runner);\n }\n\n private defaultFactory(): AgentFactory {\n return async (_config: SubagentConfig) => ({\n agent: this.opts.agent,\n events: this.opts.agent.events,\n });\n }\n\n /**\n * Execute a batch of tasks together. Retained as a thin wrapper over the\n * single-task primitive `executeOne` so the wave-oriented tests and any\n * batch callers keep working; the continuous scheduler in `run()` calls\n * `executeOne` directly. Throws if no coordinator is wired or a spawn fails\n * (surfaced from `executeOne`), preserving the original all-or-nothing contract.\n */\n async executeWave(batch: TaskBatch): Promise<WaveResult> {\n const waveStart = Date.now();\n const outcomes = await Promise.all(batch.tasks.map((task) => this.executeOne(task)));\n const results = outcomes.map((o) => o.result).filter((r): r is TaskResult => Boolean(r));\n const successCount = outcomes.filter((o) => o.success).length;\n const failCount = outcomes.length - successCount;\n return {\n wave: batch.wave,\n batch,\n results,\n successCount,\n failCount,\n durationMs: Date.now() - waveStart,\n stopRequested: this.stopRequested,\n };\n }\n\n /**\n * Execute one task end-to-end: assign a worker identity, allocate its worktree,\n * spawn + assign the subagent, await its result, then update tracker status\n * (success / retry / terminal-fail / cancelled) and resolve the worktree. This\n * is the unit the continuous scheduler dispatches into a free slot. Throws on a\n * missing coordinator or failed spawn so callers can enforce all-or-nothing.\n */\n async executeOne(task: TaskNode): Promise<TaskOutcome> {\n const outcome = await executeSddTask({\n task,\n opts: this.opts,\n coordinator: this.coordinator,\n usedNicknames: this.usedNicknames,\n idleTimeoutMs: this.idleTimeoutMs,\n timeoutMs: this.timeoutMs,\n runId: this.runId,\n nextSubagentId: () => `sdd-d${this.dispatchSeq++}`,\n emit: (event, payload) => this.emit(event, payload),\n taskCwds: this.taskCwds,\n taskBranches: this.taskBranches,\n taskSubagents: this.taskSubagents,\n cancelledTasks: this.cancelledTasks,\n allocateWorktrees: (tasks) => this.allocateWorktrees(tasks),\n resolveWorktrees: (tasks) => this.resolveWorktrees(tasks),\n integrateWorktree: (taskNode, result) => this.integrateWorktree(taskNode, result),\n applyTaskFailure: (taskId, subagentId, errMsg) =>\n this.applyTaskFailure(taskId, subagentId, errMsg),\n });\n if (outcome.success) {\n this.retryMap.delete(task.id);\n this.persistRetries(task.id, 0);\n }\n return outcome;\n }\n\n /**\n * Apply a task failure: retry (\u2192 pending, bump retry count) while attempts\n * remain, else consult the optional supervisor (which can rescue via\n * retry/reassign/split), else terminal-fail (\u2192 failed). Shared by the\n * worker-failure, verification-gate, and merge-conflict paths so all three\n * negotiate the same retry budget and emit the same events.\n */\n private async applyTaskFailure(\n taskId: string,\n subagentId: string,\n errMsg: string,\n ): Promise<void> {\n const currentRetries = this.retryMap.get(taskId) ?? 0;\n if (currentRetries < this.maxRetries) {\n this.retryMap.set(taskId, currentRetries + 1);\n this.persistRetries(taskId, currentRetries + 1);\n this.opts.tracker.updateNodeStatus(\n taskId,\n 'pending',\n `Retry ${currentRetries + 1}/${this.maxRetries}: ${errMsg}`,\n );\n this.emit('sdd.task.retrying', {\n runId: this.runId,\n taskId,\n attempt: currentRetries + 1,\n maxRetries: this.maxRetries,\n });\n return;\n }\n\n // Retries exhausted \u2014 give the supervisor a bounded chance to rescue the\n // task before it goes terminal, so a run \"decides\" rather than dead-ends.\n if (await this.trySupervisorRescue(taskId, errMsg)) return;\n\n this.opts.tracker.updateNodeStatus(taskId, 'failed', errMsg);\n this.emit('sdd.task.failed', { runId: this.runId, taskId, subagentId, error: errMsg });\n }\n\n /**\n * Consult `superviseFailure` for a task that has exhausted its retries.\n * Applies the verdict (retry / reassign+retry / split) and returns true when\n * the task was rescued (caller must NOT terminal-fail it). Bounded per task by\n * `maxSupervisorEscalations` so an always-\"retry\" supervisor can't loop forever.\n */\n private async trySupervisorRescue(taskId: string, errMsg: string): Promise<boolean> {\n const supervise = this.opts.superviseFailure;\n if (!supervise) return false;\n const used = this.supervisorEscalations.get(taskId) ?? 0;\n if (used >= this.maxSupervisorEscalations) return false;\n const node = this.opts.tracker.getNode(taskId);\n if (!node) return false;\n\n let verdict: SddSupervisorVerdict | undefined;\n try {\n verdict = await supervise({ task: node, error: errMsg, attempts: used });\n } catch {\n return false; // a flaky supervisor must not block terminal failure\n }\n if (!verdict || verdict.action === 'fail') return false;\n\n this.supervisorEscalations.set(taskId, used + 1);\n const requeue = (reason: string) => {\n this.retryMap.delete(taskId);\n this.persistRetries(taskId, 0);\n this.opts.tracker.updateNodeStatus(taskId, 'pending', reason);\n };\n\n if (verdict.action === 'reassign') {\n this.setTaskModel(taskId, verdict.model, verdict.provider);\n requeue(`supervisor reassign: ${verdict.model ?? 'default'}`);\n this.emit('sdd.supervisor.decision', { runId: this.runId, taskId, action: 'reassign' });\n return true;\n }\n if (verdict.action === 'split') {\n const ids = this.splitTask(taskId, verdict.subtasks);\n if (ids.length === 0) return false; // split refused (e.g. running) \u2192 let it fail\n this.emit('sdd.supervisor.decision', { runId: this.runId, taskId, action: 'split' });\n return true;\n }\n // 'retry'\n requeue('supervisor retry');\n this.emit('sdd.supervisor.decision', { runId: this.runId, taskId, action: 'retry' });\n return true;\n }\n\n /**\n * Integrate a verified-successful task's worktree into the base branch.\n * Commits, squash-merges (optionally running `conflictResolver` first), and on\n * success releases the worktree. On an UNRESOLVED conflict it returns\n * `{ok:false}` with the conflicting files so the caller routes the task into\n * the failure path (a retry forks a fresh worktree off the now-advanced base,\n * which usually clears the conflict). No-op `{ok:true}` when worktrees are\n * disabled or none was allocated for this task. Never throws \u2014 a merge hiccup\n * degrades to a (retryable) failure rather than wedging the run.\n */\n private async integrateWorktree(\n task: TaskNode,\n result?: TaskResult,\n ): Promise<{ ok: boolean; conflictFiles?: string[]; reason?: string }> {\n const wt = this.opts.worktrees;\n if (!wt) return { ok: true };\n const handle = this.taskWorktrees.get(task.id);\n if (!handle) return { ok: true };\n try {\n await wt.commitAll(handle, `sdd(${task.title}): ${task.id}`);\n // Capture the base tip before merging so a regressed conflict-resolution\n // can be reverted to exactly this commit (see the re-verify branch below),\n // and so we can tell whether this merge actually advanced the base (an\n // empty squash creates no commit \u2192 nothing to record for rollback).\n const baseShaBefore = await wt.baseHead(handle);\n const baseSha = this.opts.conflictResolver ? baseShaBefore : null;\n const res = await wt.merge(handle, {\n squash: true,\n ...(this.opts.conflictResolver\n ? {\n resolve: (info: { conflictFiles: string[]; cwd: string }) =>\n this.opts.conflictResolver!({\n task,\n conflictFiles: info.conflictFiles,\n cwd: info.cwd,\n }),\n }\n : {}),\n });\n if (res.ok) {\n // A merge that only landed because the conflictResolver rewrote files is\n // not trusted blindly: re-run the completion gate against the INTEGRATED\n // base. If it regresses, revert the squash commit so the auto-resolution\n // never sticks, and treat the task as a (retryable) failure.\n if (res.resolved && this.opts.verifyTask && baseSha) {\n let regressed: string | undefined;\n try {\n const verdict = await this.opts.verifyTask({\n task,\n result: result ?? ({} as TaskResult),\n cwd: this.opts.projectRoot,\n });\n if (!verdict.ok)\n regressed = verdict.reason ?? 'verification failed after conflict resolution';\n } catch (err) {\n regressed = `verification error after conflict resolution: ${String(err)}`;\n }\n if (regressed) {\n await wt.revertBaseTo(handle, baseSha).catch(() => {});\n await wt.release(handle, { keep: false }).catch(() => {});\n this.forgetWorktree(task.id, { keepBranchLabel: true });\n return { ok: false, conflictFiles: [], reason: regressed };\n }\n }\n // Record the squash commit for rollback \u2014 but only if the merge actually\n // advanced the base tip (an empty/no-op squash leaves it unchanged).\n const baseShaAfter = await wt.baseHead(handle);\n if (baseShaAfter && baseShaAfter !== baseShaBefore) {\n this.mergedCommits.push({ taskId: task.id, sha: baseShaAfter, title: task.title });\n this.emit('sdd.task.merged', { runId: this.runId, taskId: task.id, sha: baseShaAfter });\n }\n await wt.release(handle, { keep: false });\n this.forgetWorktree(task.id);\n return { ok: true };\n }\n // Unresolved conflict: the manager already hard-reset the base and parked\n // the handle as `needs-review` (force-kept for inspection). Drop our handle\n // reference so a retry allocates a fresh worktree off the advanced base.\n await wt.release(handle, { keep: false }).catch(() => {});\n this.forgetWorktree(task.id, { keepBranchLabel: true });\n return { ok: false, conflictFiles: res.conflictFiles ?? [] };\n } catch {\n // Commit/merge hiccup \u2014 don't wedge the run; treat as a retryable failure.\n this.forgetWorktree(task.id);\n return { ok: false, conflictFiles: [] };\n }\n }\n\n /** Allocate a fresh git worktree per task in the batch (no-op without a manager). */\n private async allocateWorktrees(tasks: TaskNode[]): Promise<void> {\n const wt = this.opts.worktrees;\n if (!wt) return;\n for (const task of tasks) {\n if (this.taskWorktrees.has(task.id)) continue;\n try {\n const handle = await wt.allocate(`sdd-${task.id}`, {\n slugHint: task.title,\n ownerLabel: task.title,\n });\n if (handle.status === 'active') {\n this.taskWorktrees.set(task.id, handle);\n this.taskCwds.set(task.id, handle.dir);\n this.taskBranches.set(task.id, handle.branch);\n const node = this.opts.tracker.getNode(task.id);\n if (node) node.metadata = { ...node.metadata, worktreeBranch: handle.branch };\n }\n } catch {\n // Allocation failed \u2192 this task runs on the shared working tree.\n }\n }\n }\n\n /**\n * Resolve each task's worktree after its result is known. Serialized merges\n * (one at a time) keep the base branch consistent; the wave structure already\n * guarantees dependency order (a task's blockers merged in an earlier wave).\n */\n private async resolveWorktrees(tasks: TaskNode[]): Promise<void> {\n const wt = this.opts.worktrees;\n if (!wt) return;\n for (const task of tasks) {\n const handle = this.taskWorktrees.get(task.id);\n if (!handle) continue;\n const node = this.opts.tracker.getNode(task.id);\n const status = node?.status;\n const cancelled = Boolean(node?.metadata?.cancelled);\n try {\n if (cancelled) {\n // User cancelled \u2192 throw away the partial checkout, don't merge it.\n await wt.release(handle, { keep: false });\n this.forgetWorktree(task.id, { keepBranchLabel: false });\n } else if (status === 'completed') {\n await wt.commitAll(handle, `sdd(${task.title}): ${task.id}`);\n await wt.merge(handle, { squash: true });\n await wt.release(handle, { keep: false });\n this.forgetWorktree(task.id);\n } else if (status === 'failed') {\n // Discard the failed checkout so worktrees don't pile up across a run\n // with many failures. (A genuine merge-conflict handle \u2014 status\n // 'needs-review'/'failed' \u2014 is force-kept by the manager regardless,\n // so conflicts that actually need a human still stay on disk.)\n await wt.release(handle, { keep: false });\n this.forgetWorktree(task.id, { keepBranchLabel: false });\n } else {\n // Pending again (retry) \u2192 discard so the next wave starts clean.\n await wt.release(handle, { keep: false });\n this.forgetWorktree(task.id, { keepBranchLabel: false });\n }\n } catch {\n // Merge/release hiccup must not abort the run; leave the handle parked.\n this.forgetWorktree(task.id);\n }\n }\n }\n\n private forgetWorktree(taskId: string, opts: { keepBranchLabel?: boolean } = {}): void {\n this.taskWorktrees.delete(taskId);\n this.taskCwds.delete(taskId);\n if (!opts.keepBranchLabel) this.taskBranches.delete(taskId);\n }\n\n /** Persist a task's retry count into node metadata (survives crash \u2192 resume). */\n private persistRetries(taskId: string, retries: number): void {\n const node = this.opts.tracker.getNode(taskId);\n if (node) node.metadata = { ...node.metadata, retries };\n }\n\n private buildProgress(): SddProgress {\n const gp = this.opts.tracker.getProgress();\n const isDeadlocked = !this.decomposer.isDone() && this.decomposer.nextBatch().deadlocked;\n return {\n wave: this.decomposer.getWaveCount(),\n total: gp.total,\n completed: gp.completed,\n inProgress: gp.inProgress,\n failed: gp.failed,\n blocked: gp.blocked,\n pending: gp.pending,\n percent: gp.percentComplete,\n deadlocked: isDeadlocked,\n };\n }\n}\n", "/**\n * splitGraphNode \u2014 the single code path for graph node decomposition, shared by\n * run-time splits (SddParallelRun.splitTask, supervisor `split` verdicts) and\n * planning-time splits (plan-decompose.ts).\n *\n * Semantics (extracted verbatim from SddParallelRun.splitTask):\n * - new leaves inherit the parent's blockers, so they cannot start before the\n * parent's dependencies are met;\n * - every existing dependent is rewired to depend on ALL leaves, so\n * downstream work waits for the whole split;\n * - the parent becomes a `completed` container (its real work lives in the\n * leaves).\n */\n\nimport type { TaskTracker } from '@wrongstack/core/tasking';\nimport type { SddSubtaskSpec } from './sdd-parallel-run.js';\n\nexport interface SplitGraphNodeOptions {\n /** Extra refusal predicate, e.g. \"task currently has a live subagent\". */\n isRunning?: ((taskId: string) => boolean) | undefined;\n}\n\n/**\n * Split a task node into sub-task leaves. Refuses a missing/in-progress/running\n * task or an empty subtask list, returning []. Returns the new leaf ids.\n */\nexport function splitGraphNode(\n tracker: TaskTracker,\n taskId: string,\n subtasks: SddSubtaskSpec[],\n options: SplitGraphNodeOptions = {},\n): string[] {\n const node = tracker.getNode(taskId);\n if (!node) return [];\n if (node.status === 'in_progress' || options.isRunning?.(taskId)) return [];\n if (!subtasks.length) return [];\n\n const blockers = tracker.getBlockers(taskId);\n const dependents = tracker.getDependents(taskId);\n\n const leafIds = subtasks.map((s) => {\n const criterion = s.successCriterion?.trim();\n const description = criterion\n ? `${s.description}\\n\\n**Acceptance Criteria:**\\n- ${criterion}`\n : s.description;\n return tracker.addNode({\n title: s.title,\n description,\n type: s.type ?? node.type,\n priority: s.priority ?? node.priority,\n status: 'pending',\n parentId: taskId,\n } as never).id;\n });\n\n for (const leaf of leafIds) {\n // Each leaf inherits the parent's dependencies\u2026\n for (const b of blockers) tracker.addDependency(b, leaf);\n // \u2026and every prior dependent of the parent now waits on every leaf.\n for (const dep of dependents) tracker.addDependency(leaf, dep);\n }\n\n // The parent is now just a grouping node \u2014 mark it completed so the graph\n // can settle (its real work lives in the leaves).\n tracker.updateNodeStatus(taskId, 'completed', `split into ${leafIds.length} subtasks`);\n return leafIds;\n}\n", "import { randomUUID } from 'node:crypto';\nimport { expectDefined } from '@wrongstack/core/utils';\nimport { assignNickname, type DefaultMultiAgentCoordinator } from '@wrongstack/core/coordination';\nimport type { EventMap } from '@wrongstack/core/kernel';\nimport type { TaskNode, TaskResult } from '@wrongstack/core/types';\nimport { ERROR_CODES, SddError } from '@wrongstack/core/types';\nimport type { SddParallelRunOptions, TaskOutcome } from './sdd-parallel-run-types.js';\n\nexport async function executeSddTask(params: {\n task: TaskNode;\n opts: SddParallelRunOptions;\n coordinator: DefaultMultiAgentCoordinator | null;\n usedNicknames: Set<string>;\n idleTimeoutMs: number;\n timeoutMs: number | undefined;\n runId: string;\n nextSubagentId: () => string;\n emit: <K extends keyof EventMap>(event: K, payload: EventMap[K]) => void;\n taskCwds: ReadonlyMap<string, string>;\n taskBranches: ReadonlyMap<string, string>;\n taskSubagents: Map<string, string>;\n cancelledTasks: ReadonlySet<string>;\n allocateWorktrees: (tasks: TaskNode[]) => Promise<void>;\n resolveWorktrees: (tasks: TaskNode[]) => Promise<void>;\n integrateWorktree: (\n task: TaskNode,\n result?: TaskResult,\n ) => Promise<{ ok: boolean; conflictFiles?: string[]; reason?: string }>;\n applyTaskFailure: (taskId: string, subagentId: string, errMsg: string) => Promise<void>;\n}): Promise<TaskOutcome> {\n const { task, opts } = params;\n const taskId = task.id;\n let agentName = task.assignee;\n if (!agentName) {\n const nick = assignNickname('executor', params.usedNicknames);\n params.usedNicknames.add(nick.key);\n agentName = nick.display.replace(/\\s*\\([^)]*\\)\\s*$/, '');\n opts.tracker.updateNode(taskId, { assignee: agentName });\n }\n\n opts.tracker.updateNodeStatus(taskId, 'in_progress');\n await params.allocateWorktrees([task]);\n\n if (!params.coordinator)\n throw new SddError({\n message: 'SDD parallel runner requires a coordinator',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n const coordinator = params.coordinator;\n\n const subagentId = params.nextSubagentId();\n const correlationId = randomUUID();\n const meta = (task.metadata ?? {}) as Record<string, unknown>;\n const model = (typeof meta.model === 'string' ? meta.model : undefined) ?? opts.defaultModel;\n const provider =\n (typeof meta.provider === 'string' ? meta.provider : undefined) ?? opts.defaultProvider;\n const fallbackModels = Array.isArray(meta.fallbackModels)\n ? (meta.fallbackModels as string[])\n : opts.fallbackModels;\n\n const spawnResult = await coordinator.spawn({\n id: subagentId,\n name: agentName,\n role: 'executor',\n idleTimeoutMs: params.idleTimeoutMs,\n ...(params.timeoutMs ? { timeoutMs: params.timeoutMs } : {}),\n cwd: params.taskCwds.get(taskId),\n disabledTools: ['delegate'],\n ...(model ? { model } : {}),\n ...(provider ? { provider } : {}),\n ...(fallbackModels?.length ? { fallbackModels } : {}),\n });\n if (!spawnResult.subagentId) {\n throw new SddError({\n message: 'One or more subagent spawns failed',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n }\n\n params.taskSubagents.set(taskId, subagentId);\n params.emit('sdd.task.started', {\n runId: params.runId,\n taskId,\n subagentId,\n agentName,\n worktreeBranch: params.taskBranches.get(taskId),\n });\n\n await coordinator.assign({\n id: correlationId,\n description: buildTaskDirective(opts.graph.title, task),\n subagentId,\n ...(params.timeoutMs ? { timeoutMs: params.timeoutMs } : {}),\n context: {\n telemetryTaskId: taskId,\n telemetryRunId: params.runId,\n telemetryBoardId: opts.graph.id,\n },\n });\n\n let result: TaskResult;\n try {\n const got = await coordinator.awaitTasks([correlationId]);\n result = expectDefined(got[0]);\n } catch (err) {\n result = {\n subagentId,\n taskId: correlationId,\n status: 'failed',\n error: { kind: 'unknown', message: String(err), retryable: false },\n iterations: 0,\n toolCalls: 0,\n durationMs: 0,\n };\n }\n\n params.taskSubagents.delete(taskId);\n\n if (params.cancelledTasks.has(taskId)) {\n await params.resolveWorktrees([task]);\n return { taskId, success: false, result };\n }\n\n const verificationFailReason = await verifyTaskResult(params, result);\n let success = false;\n if (result.status === 'success' && !verificationFailReason) {\n const merged = await params.integrateWorktree(task, result);\n if (merged.ok) {\n success = true;\n opts.tracker.updateNodeStatus(taskId, 'completed');\n params.emit('sdd.task.completed', {\n runId: params.runId,\n taskId,\n subagentId,\n durationMs: result.durationMs,\n });\n } else if (merged.reason) {\n params.emit('sdd.task.verification_failed', {\n runId: params.runId,\n taskId,\n reason: merged.reason,\n });\n await params.applyTaskFailure(taskId, subagentId, merged.reason);\n } else {\n const conflictFiles = merged.conflictFiles ?? [];\n params.emit('sdd.task.conflict', { runId: params.runId, taskId, conflictFiles });\n const reason = `merge conflict${conflictFiles.length ? `: ${conflictFiles.join(', ')}` : ''}`;\n await params.applyTaskFailure(taskId, subagentId, reason);\n }\n } else {\n const errMsg =\n verificationFailReason ??\n (result.error?.kind\n ? `${result.error.kind}: ${result.error.message}`\n : (result.error?.message ?? 'unknown error'));\n await params.applyTaskFailure(taskId, subagentId, errMsg);\n await params.resolveWorktrees([task]);\n }\n\n return { taskId, success, result };\n}\n\nfunction buildTaskDirective(graphTitle: string, task: TaskNode): string {\n const directivePreamble = [\n '\u2550\u2550\u2550 SDD PARALLEL EXECUTION \u2550\u2550\u2550',\n '',\n `Graph: ${graphTitle}`,\n '',\n '\u2500\u2500 EXECUTION PROTOCOL \u2500\u2500',\n '\u2022 Execute the assigned SDD task end-to-end using multiple tool calls.',\n '\u2022 Mark the task [done] in the tracker when complete.',\n '\u2022 Do not ask before routine in-project tool use; if a permission gate appears, wait for that flow.',\n '\u2022 Keep output concise \u2014 summarize changes, do not transcribe files.',\n ].join('\\n');\n\n return [\n directivePreamble,\n '',\n `\u2500\u2500 TASK \u2500\u2500`,\n `[${task.priority.toUpperCase()}] ${task.title}`,\n '',\n task.description,\n ].join('\\n');\n}\n\nasync function verifyTaskResult(\n params: Parameters<typeof executeSddTask>[0],\n result: TaskResult,\n): Promise<string | undefined> {\n const { task, opts, taskCwds } = params;\n if (result.status !== 'success' || !opts.verifyTask) return undefined;\n\n const taskId = task.id;\n const cwd = taskCwds.get(taskId) ?? opts.projectRoot;\n let verificationFailReason: string | undefined;\n try {\n const verdict = await opts.verifyTask({ task, result, cwd });\n if (!verdict.ok) {\n verificationFailReason = `verification failed: ${verdict.reason ?? 'acceptance criteria not met'}`;\n }\n } catch (err) {\n verificationFailReason = `verification error: ${String(err)}`;\n }\n\n const hadVerifiable =\n typeof task.metadata?.['verificationCommand'] === 'string' ||\n task.description.includes('**Acceptance Criteria:**');\n if (verificationFailReason) {\n opts.tracker.patchMetadata(taskId, {\n verificationState: 'failed',\n verificationDetail: verificationFailReason,\n });\n params.emit('sdd.task.verification_failed', {\n runId: params.runId,\n taskId,\n reason: verificationFailReason,\n });\n } else if (hadVerifiable) {\n opts.tracker.patchMetadata(taskId, {\n verificationState: 'passed',\n verificationDetail: undefined,\n });\n }\n return verificationFailReason;\n}\n", "/**\n * SddTaskDecomposer\n *\n * Converts a TaskGraph (from SDD's TaskGenerator) into a dependency-aware\n * sequence of batches for ParallelEternalEngine.\n *\n * Key behaviour:\n * - Each `nextBatch()` call returns up to `parallelSlots` ready tasks\n * (all blockers completed, sorted by priority).\n * - Tasks that are blocked by an in-progress task are NOT included\n * in the batch \u2014 they wait for the blocker to complete.\n * - When `isDone()` returns true the whole graph is either completed\n * or deadlocked (all remaining tasks are blocked by failed tasks).\n *\n * Usage:\n * ```\n * const decomposer = new SddTaskDecomposer(tracker, graph, { parallelSlots: 4 });\n * while (!decomposer.isDone()) {\n * const batch = decomposer.nextBatch();\n * if (batch.length === 0) break; // deadlock\n * await fanOut(batch);\n * decomposer.acknowledgeBatch(batch.map(t => t.id));\n * }\n * ```\n */\n\nimport type { TaskNode, TaskGraph } from '@wrongstack/core/types';\nimport type { TaskTracker } from '@wrongstack/core/tasking';\n\nexport interface SddTaskDecomposerOptions {\n /** Max tasks per batch. Default: 4. Range 1\u201316. */\n parallelSlots?: number | undefined;\n}\n\nexport interface TaskBatch {\n /** Tasks ready to execute in this wave. */\n tasks: TaskNode[];\n /** 0-based wave number since the decomposer was constructed. */\n wave: number;\n /** True when every node in the graph is either completed or failed. */\n allDone: boolean;\n /** True when no batch was produced because remaining tasks are all blocked by failed nodes. */\n deadlocked: boolean;\n}\n\nexport class SddTaskDecomposer {\n private readonly slots: number;\n private wave = 0;\n\n constructor(\n private readonly tracker: TaskTracker,\n _graph: TaskGraph,\n opts: SddTaskDecomposerOptions = {},\n ) {\n this.slots = Math.min(16, Math.max(1, opts.parallelSlots ?? 4));\n }\n\n // -------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------\n\n /**\n * Return the next batch of runnable tasks.\n * Returns `allDone: true` when every node is completed.\n * Returns `deadlocked: true` when no batch can be produced because\n * all remaining tasks are blocked by failed nodes.\n */\n nextBatch(): TaskBatch {\n if (this.isDone()) {\n return { tasks: [], wave: this.wave, allDone: true, deadlocked: false };\n }\n\n const pending = this.pendingReadyNodes();\n\n if (pending.length === 0) {\n // No runnable tasks \u2014 check for deadlock\n const hasBlockedTasks = this.hasAnyBlockedTasks();\n return { tasks: [], wave: this.wave, allDone: false, deadlocked: hasBlockedTasks };\n }\n\n const batch = pending.slice(0, this.slots);\n return { tasks: batch, wave: this.wave, allDone: false, deadlocked: false };\n }\n\n /**\n * Advance the wave counter after a batch completes.\n * Call this once per `nextBatch()` result that was fan-out.\n */\n acknowledgeBatch(_completedTaskIds: string[]): void {\n this.wave++;\n }\n\n /**\n * True when every node in the graph is completed.\n * Use this to exit the fan-out loop after `isDone() || deadlocked`.\n */\n isDone(): boolean {\n const progress = this.tracker.getProgress();\n return progress.total > 0 && progress.completed === progress.total;\n }\n\n /**\n * Total waves produced so far.\n */\n getWaveCount(): number {\n return this.wave;\n }\n\n /**\n * All ready (dependency-satisfied) pending tasks, priority-sorted \u2014 UNSLICED.\n * The continuous scheduler fills its own free slots from this list, so unlike\n * `nextBatch()` it does not cap at `slots`.\n */\n readyNodes(): TaskNode[] {\n return this.pendingReadyNodes();\n }\n\n /**\n * True when every node has reached a terminal state (completed or failed).\n * This \u2014 not `isDone()` (which requires ALL completed) \u2014 is the correct loop\n * exit for the continuous scheduler: a terminally-failed task must not keep\n * the run spinning to its backstop.\n */\n isSettled(): boolean {\n const nodes = this.tracker.getAllNodes();\n return nodes.length > 0 && nodes.every((n) => n.status === 'completed' || n.status === 'failed');\n }\n\n // -------------------------------------------------------------------\n // Internal helpers\n // -------------------------------------------------------------------\n\n /**\n * Return pending nodes whose blockers are all completed.\n * Sorted by priority (critical first), then by creation time.\n */\n private pendingReadyNodes(): TaskNode[] {\n const allPending = this.tracker.getAllNodes({ status: ['pending'] });\n const ready: TaskNode[] = [];\n\n for (const node of allPending) {\n if (this.tracker.canStart(node.id)) {\n ready.push(node);\n }\n }\n\n // Sort by priority first, then by createdAt\n const priorityRank: Record<TaskNode['priority'], number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n };\n\n ready.sort((a, b) => {\n const pr = priorityRank[a.priority] - priorityRank[b.priority];\n if (pr !== 0) return pr;\n return a.createdAt - b.createdAt;\n });\n\n return ready;\n }\n\n /** True when at least one non-completed, non-failed task is blocked. */\n private hasAnyBlockedTasks(): boolean {\n const nodes = this.tracker.getAllNodes({\n status: ['pending', 'in_progress', 'blocked'],\n });\n return nodes.some((n) => n.status === 'blocked');\n }\n}", "// SDD run lifecycle \u2014 post-run, durable-state operations.\n//\n// While a run is live, the in-process `SddRunControl` (registered in\n// `SddRunRegistry`) owns stop / cleanup / rollback. Once a run finishes the\n// registry is cleared and its `WorktreeManager` is gone, so these helpers\n// re-derive everything from durable state: a fresh `WorktreeManager` for git\n// surgery and the persisted board snapshot for base branch + merged commits.\n//\n// Used by the CLI/WebUI when there is no active run (e.g. `/sdd rollback` after\n// the run already settled, or `/sdd destroy` to wipe the project).\n\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport { WorktreeManager } from '@wrongstack/core/worktree';\nimport {\n deleteKanbanWorkflowState,\n kanbanWorkflowId,\n listBoards,\n listKanbanWorkflowStates,\n readKanbanWorkflowState,\n removeBoard,\n writeKanbanWorkflowState,\n} from '@wrongstack/kanban';\nimport type { SddBoardSnapshot } from './board-types.js';\nimport { SddBoardStore } from './sdd-board-store.js';\n\ntype SddStateTransport = 'kanban' | 'legacy-file';\n\nasync function listSddSnapshots(\n projectRoot: string,\n boardsDir: string,\n transport: SddStateTransport | undefined,\n): Promise<SddBoardSnapshot[]> {\n const legacyStore = new SddBoardStore({ baseDir: boardsDir });\n if (transport === 'kanban') {\n const states = await listKanbanWorkflowStates(projectRoot, 'sdd:');\n const snapshots = states\n .map((state) => state.value)\n .filter(isSddBoardSnapshot)\n .sort((a, b) => b.updatedAt - a.updatedAt);\n if (snapshots.length > 0) return snapshots;\n\n // One-time compatibility migration for runs persisted before workflow state.\n const legacy = await loadLegacySnapshots(legacyStore);\n for (const snapshot of legacy) {\n await writeKanbanWorkflowState(\n projectRoot,\n kanbanWorkflowId('sdd', snapshot.runId),\n snapshot,\n );\n }\n return legacy;\n }\n return loadLegacySnapshots(legacyStore);\n}\n\nasync function loadSddSnapshot(\n projectRoot: string,\n boardsDir: string,\n runId: string,\n transport: SddStateTransport | undefined,\n): Promise<SddBoardSnapshot | null> {\n const legacyStore = new SddBoardStore({ baseDir: boardsDir });\n if (transport !== 'kanban') return legacyStore.load(runId);\n const state = await readKanbanWorkflowState(projectRoot, kanbanWorkflowId('sdd', runId));\n if (isSddBoardSnapshot(state?.value)) return state.value;\n const legacy = await legacyStore.load(runId);\n if (legacy) {\n await writeKanbanWorkflowState(projectRoot, kanbanWorkflowId('sdd', runId), legacy);\n }\n return legacy;\n}\n\nasync function loadLegacySnapshots(store: SddBoardStore): Promise<SddBoardSnapshot[]> {\n const snapshots: SddBoardSnapshot[] = [];\n for (const entry of await store.list()) {\n const snapshot = await store.load(entry.runId);\n if (snapshot) snapshots.push(snapshot);\n }\n return snapshots.sort((a, b) => b.updatedAt - a.updatedAt);\n}\n\nfunction isSddBoardSnapshot(value: unknown): value is SddBoardSnapshot {\n if (!value || typeof value !== 'object') return false;\n const snapshot = value as Partial<SddBoardSnapshot>;\n return (\n typeof snapshot.runId === 'string' &&\n typeof snapshot.updatedAt === 'number' &&\n typeof snapshot.status === 'string' &&\n Array.isArray(snapshot.tasks)\n );\n}\n\n/** Force-remove every git worktree + branch a previous run left behind. */\nexport async function cleanupSddWorktrees(projectRoot: string): Promise<{ removed: number }> {\n const wt = new WorktreeManager({ projectRoot });\n return wt.cleanupAllManaged();\n}\n\n/**\n * Detect and clean up stale worktrees from a crashed previous run.\n * No-op when the project is clean. Called on SDD/Director boot to\n * prevent orphaned worktrees from conflicting with the next run's\n * `allocate()`.\n *\n * P2 #B6 (sprint2 audit).\n */\nexport async function cleanupStaleWorktrees(\n projectRoot: string,\n): Promise<{ removed: number; detected: number }> {\n const wt = new WorktreeManager({ projectRoot });\n return wt.cleanupStale();\n}\n\nexport interface CleanupStaleSddOptions {\n projectRoot: string;\n /** Board snapshot dir (`wpaths.projectSddBoards`) \u2014 read for the liveness guard. */\n boardsDir: string;\n /** Durable snapshot owner. Legacy remains the default for API compatibility. */\n stateTransport?: SddStateTransport | undefined;\n /** A `running` board updated within this window is treated as live \u2192 skip. Default 120_000 (2 min). */\n runningLiveMs?: number | undefined;\n /** A `paused` board updated within this window is treated as live \u2192 skip. Default 1_800_000 (30 min). */\n pausedLiveMs?: number | undefined;\n /** Injectable clock for tests. */\n now?: (() => number) | undefined;\n}\n\nexport interface CleanupStaleSddResult {\n /** True when a sweep ran (orphans were found and removed). */\n swept: boolean;\n removed: number;\n detected: number;\n /** Set when the sweep was skipped because a run appears live. */\n skippedReason?: string | undefined;\n}\n\n/**\n * Liveness-guarded stale-worktree sweep for boot + run-start. Worktrees live\n * under `<projectRoot>/.wrongstack/worktrees` and a sweep force-removes ALL of\n * them \u2014 so it must NEVER run under a genuinely live run (possibly in another\n * process). The guard reads the latest board: a `running` board updated within\n * `runningLiveMs`, or a `paused` one within `pausedLiveMs`, is treated as live\n * and the sweep is skipped. A crashed run leaves its board frozen as `running`\n * \u2192 once it ages past the window it is correctly swept. Any other status\n * (completed / failed / stopped / deadlocked / idle) is always sweepable.\n * Never throws \u2014 best-effort cleanup.\n */\nexport async function cleanupStaleSddWorktrees(\n opts: CleanupStaleSddOptions,\n): Promise<CleanupStaleSddResult> {\n const now = opts.now?.() ?? Date.now();\n let latest: SddBoardSnapshot | undefined;\n try {\n latest = (await listSddSnapshots(opts.projectRoot, opts.boardsDir, opts.stateTransport))[0];\n } catch {\n // A failed authoritative-state read cannot prove that no run is live.\n // Fail closed instead of force-removing another process's worktrees.\n return {\n swept: false,\n removed: 0,\n detected: 0,\n skippedReason: 'SDD workflow state is unavailable',\n };\n }\n if (latest) {\n const age = now - latest.updatedAt;\n if (latest.status === 'running' && age < (opts.runningLiveMs ?? 120_000)) {\n return {\n swept: false,\n removed: 0,\n detected: 0,\n skippedReason: 'a run appears live (running)',\n };\n }\n if (latest.status === 'paused' && age < (opts.pausedLiveMs ?? 1_800_000)) {\n return { swept: false, removed: 0, detected: 0, skippedReason: 'a run is paused' };\n }\n }\n try {\n const wt = new WorktreeManager({ projectRoot: opts.projectRoot });\n const { removed, detected } = await wt.cleanupStale();\n return { swept: detected > 0, removed, detected };\n } catch {\n return { swept: false, removed: 0, detected: 0 };\n }\n}\n\nexport interface RollbackFromDiskOptions {\n projectRoot: string;\n /** Directory holding persisted board snapshots (`wpaths.projectSddBoards`). */\n boardsDir: string;\n /** Specific run to roll back. Omit \u2192 the most recently updated board. */\n runId?: string | undefined;\n /** Durable snapshot owner. Legacy remains the default for API compatibility. */\n stateTransport?: SddStateTransport | undefined;\n}\n\n/**\n * Roll back a finished run's merged commits by reading its persisted board\n * snapshot (base branch + commit SHAs) and reverting each. History-preserving;\n * refuses on a dirty tree or revert conflict (surfaced in `reason`). Returns\n * `ok:false` with a reason when there is no board, no base branch, or nothing to\n * revert.\n */\nexport async function rollbackSddRunFromDisk(\n opts: RollbackFromDiskOptions,\n): Promise<{ ok: boolean; reverted: number; reason?: string }> {\n const snapshots = await listSddSnapshots(opts.projectRoot, opts.boardsDir, opts.stateTransport);\n const runId = opts.runId ?? snapshots[0]?.runId;\n if (!runId) return { ok: false, reverted: 0, reason: 'no SDD board found to roll back' };\n\n const snap =\n snapshots.find((snapshot) => snapshot.runId === runId) ??\n (await loadSddSnapshot(opts.projectRoot, opts.boardsDir, runId, opts.stateTransport));\n if (!snap) return { ok: false, reverted: 0, reason: `board \"${runId}\" not found` };\n if (!snap.baseBranch) {\n return {\n ok: false,\n reverted: 0,\n reason: 'this run did not record a base branch (no worktree run)',\n };\n }\n const shas = (snap.mergedCommits ?? []).map((c) => c.sha);\n if (shas.length === 0) {\n return { ok: false, reverted: 0, reason: 'no merged commits recorded for this run' };\n }\n\n const wt = new WorktreeManager({ projectRoot: opts.projectRoot });\n return wt.revertCommits(snap.baseBranch, shas);\n}\n\nexport interface DestroySddProjectOptions {\n projectRoot: string;\n /** Resolved wstack paths to delete. */\n paths: {\n projectSpecs: string;\n projectTaskGraphs: string;\n projectSddSession: string;\n projectSddBoards: string;\n };\n /**\n * Also revert this run's already-merged squash commits (history-preserving\n * `git revert`) BEFORE deleting the board that records them. Off by default \u2014\n * a plain destroy wipes worktrees + artifacts but leaves merged commits on the\n * base branch (un-merged worktree work is destroyed regardless, since its\n * branch is force-removed). When on and the working tree is dirty, the revert\n * is refused and surfaced in `revertReason` (the destroy still proceeds).\n */\n revertMerged?: boolean | undefined;\n /** Which run's merged commits to revert. Omit \u2192 the most recently updated board. */\n runId?: string | undefined;\n /** Durable snapshot owner. Legacy remains the default for API compatibility. */\n stateTransport?: SddStateTransport | undefined;\n}\n\nexport interface DestroySddProjectResult {\n worktreesRemoved: number;\n /** Human labels of the artifacts that were deleted. */\n deleted: string[];\n /** Number of merged commits reverted (only when `revertMerged` was set). */\n reverted: number;\n /** Whether the optional merged-commit revert succeeded (undefined \u2192 not requested). */\n revertOk?: boolean | undefined;\n /** Why the revert did not fully apply (dirty tree, conflict, nothing to revert). */\n revertReason?: string | undefined;\n}\n\n/**\n * Destroy an SDD project: optionally revert its merged commits, then clean every\n * worktree + branch, then delete the on-disk artifacts (specs, task-graphs,\n * session, boards). The revert is opt-in (`revertMerged`) and runs FIRST \u2014 it\n * reads the board snapshot that the artifact deletion removes. Best-effort: a\n * missing path is simply skipped. The caller is responsible for stopping any\n * active run first.\n */\nexport async function destroySddProject(\n opts: DestroySddProjectOptions,\n): Promise<DestroySddProjectResult> {\n // 1. Optional merged-commit revert \u2014 must read the board before we delete it.\n let reverted = 0;\n let revertOk: boolean | undefined;\n let revertReason: string | undefined;\n if (opts.revertMerged) {\n const r = await rollbackSddRunFromDisk({\n projectRoot: opts.projectRoot,\n boardsDir: opts.paths.projectSddBoards,\n runId: opts.runId,\n stateTransport: opts.stateTransport,\n }).catch((err) => ({ ok: false, reverted: 0, reason: toErrorMessage(err) }));\n reverted = r.reverted;\n revertOk = r.ok;\n revertReason = r.reason;\n }\n\n // 2. Force-remove every worktree + branch (incl. un-merged work).\n const { removed } = await cleanupSddWorktrees(opts.projectRoot).catch(() => ({ removed: 0 }));\n\n // 3. Delete the on-disk artifacts.\n const deleted: string[] = [];\n const rmDir = async (dir: string, label: string) => {\n try {\n await fsp.rm(dir, { recursive: true, force: true });\n deleted.push(label);\n } catch {\n // already gone\n }\n };\n const rmFile = async (file: string, label: string) => {\n try {\n await fsp.unlink(file);\n deleted.push(label);\n } catch {\n // already gone\n }\n };\n\n await rmFile(opts.paths.projectSddSession, 'session');\n // Legacy WebUI wizard path (pre-unification) \u2014 keep destroy thorough.\n await rmFile(\n path.join(path.dirname(opts.paths.projectSddSession), 'sdd-wizard-session.json'),\n 'wizard-session',\n );\n await rmDir(opts.paths.projectSpecs, 'specs');\n await rmDir(opts.paths.projectTaskGraphs, 'task-graphs');\n await rmDir(opts.paths.projectSddBoards, 'boards');\n\n if (opts.stateTransport === 'kanban') {\n const states = await listKanbanWorkflowStates(opts.projectRoot, 'sdd:').catch(() => []);\n let removedStates = 0;\n for (const state of states) {\n if (await deleteKanbanWorkflowState(opts.projectRoot, state.workflowId).catch(() => false)) {\n removedStates++;\n }\n }\n if (removedStates > 0) deleted.push(`workflow-states(${removedStates})`);\n }\n\n // 4. Drop KanbanRunMirror boards tagged `sdd` so the Kanban view does not\n // keep stale run cards after the project is wiped.\n try {\n const mirrors = (await listBoards(opts.projectRoot)).filter((b) => b.tags?.includes('sdd'));\n let mirrorsRemoved = 0;\n for (const b of mirrors) {\n if (await removeBoard(opts.projectRoot, b.id)) mirrorsRemoved++;\n }\n if (mirrorsRemoved > 0) deleted.push(`kanban-mirrors(${mirrorsRemoved})`);\n } catch {\n // Kanban store missing / unreadable \u2014 destroy still succeeded on SDD artifacts.\n }\n\n return { worktreesRemoved: removed, deleted, reverted, revertOk, revertReason };\n}\n\n/** Lifecycle operation kinds shared by every surface (WebUI / TUI / CLI). */\nexport type SddLifecycleOp = 'cleanup_worktrees' | 'rollback' | 'destroy';\n\nexport interface SddLifecycleOptions {\n projectRoot: string;\n /** Resolved wstack paths (required for `destroy`; boards dir is enough for `rollback`). */\n paths: {\n projectSpecs: string;\n projectTaskGraphs: string;\n projectSddSession: string;\n projectSddBoards: string;\n };\n /** Target a specific run (rollback / destroy). Omit \u2192 most recently updated board. */\n runId?: string | undefined;\n /** `destroy` only: also revert merged commits before wiping. */\n revertMerged?: boolean | undefined;\n /** Durable snapshot owner. Legacy remains the default for API compatibility. */\n stateTransport?: SddStateTransport | undefined;\n}\n\n/** Uniform result for any lifecycle op \u2014 drives identical UI wording everywhere. */\nexport interface SddLifecycleResult {\n op: SddLifecycleOp;\n ok: boolean;\n /** Worktrees removed (cleanup_worktrees / destroy). */\n removed?: number | undefined;\n /** Merged commits reverted (rollback / destroy with revertMerged). */\n reverted?: number | undefined;\n /** Artifact labels deleted (destroy). */\n deleted?: string[] | undefined;\n /** Failure / partial reason, surfaced verbatim in the UI. */\n reason?: string | undefined;\n}\n\n/**\n * Apply a post-run SDD lifecycle operation from durable state and return a uniform result.\n * The single entry point shared by the WebUI board handler, the TUI overlay, and\n * the CLI `/sdd` host so every surface reports the same thing. The caller must\n * ensure no run is active (these operate on git + on-disk state, not the live\n * run) \u2014 `cleanup`/`destroy` force-remove worktrees, `rollback` refuses on a\n * dirty tree. Never throws.\n */\nexport async function applySddLifecycle(\n op: SddLifecycleOp,\n opts: SddLifecycleOptions,\n): Promise<SddLifecycleResult> {\n try {\n if (op === 'cleanup_worktrees') {\n const { removed } = await cleanupSddWorktrees(opts.projectRoot);\n return { op, ok: true, removed };\n }\n if (op === 'rollback') {\n const r = await rollbackSddRunFromDisk({\n projectRoot: opts.projectRoot,\n boardsDir: opts.paths.projectSddBoards,\n runId: opts.runId,\n stateTransport: opts.stateTransport,\n });\n return { op, ok: r.ok, reverted: r.reverted, reason: r.reason };\n }\n // destroy\n const r = await destroySddProject({\n projectRoot: opts.projectRoot,\n paths: opts.paths,\n revertMerged: opts.revertMerged,\n runId: opts.runId,\n stateTransport: opts.stateTransport,\n });\n return {\n op,\n // The wipe itself is best-effort and always \"ok\"; a requested-but-refused\n // revert is surfaced via reason without failing the destroy.\n ok: true,\n removed: r.worktreesRemoved,\n reverted: r.reverted,\n deleted: r.deleted,\n reason: r.revertOk === false ? r.revertReason : undefined,\n };\n } catch (err) {\n return { op, ok: false, reason: toErrorMessage(err) };\n }\n}\n", "import * as fsp from 'node:fs/promises';\nimport {\n deleteKanbanWorkflowState,\n kanbanWorkflowId,\n readKanbanWorkflowState,\n writeKanbanWorkflowState,\n} from '@wrongstack/kanban';\nimport {\n type AISpecSession,\n type AISpecSessionPersistence,\n isAISpecSession,\n} from './sdd-session-types.js';\n\nconst SDD_SESSION_WORKFLOW_ID = kanbanWorkflowId('sdd', 'session');\n\n/**\n * Project-scoped SDD interview persistence. The Kanban daemon is authoritative;\n * an old session JSON file is imported and removed on the first successful read.\n */\nexport function createKanbanSddSessionPersistence(\n projectRoot: string,\n legacySessionPath?: string,\n): AISpecSessionPersistence {\n let revision: number | undefined;\n let writeChain: Promise<void> = Promise.resolve();\n\n return {\n async load(): Promise<AISpecSession | null> {\n await writeChain;\n const state = await readKanbanWorkflowState(projectRoot, SDD_SESSION_WORKFLOW_ID);\n if (state) {\n revision = state.revision;\n return isAISpecSession(state.value) ? structuredClone(state.value) : null;\n }\n\n const legacy = await readLegacySession(legacySessionPath);\n if (!legacy) {\n revision = 0;\n return null;\n }\n\n const imported = await writeKanbanWorkflowState(\n projectRoot,\n SDD_SESSION_WORKFLOW_ID,\n legacy,\n 0,\n );\n revision = imported.revision;\n if (legacySessionPath) await fsp.unlink(legacySessionPath).catch(() => undefined);\n return structuredClone(legacy);\n },\n\n async save(session: AISpecSession): Promise<void> {\n const pending = writeChain.then(async () => {\n if (revision === undefined) {\n const current = await readKanbanWorkflowState(projectRoot, SDD_SESSION_WORKFLOW_ID);\n revision = current?.revision ?? 0;\n }\n const saved = await writeKanbanWorkflowState(\n projectRoot,\n SDD_SESSION_WORKFLOW_ID,\n session,\n revision,\n );\n revision = saved.revision;\n });\n writeChain = pending.catch(() => undefined);\n await pending;\n },\n\n async delete(): Promise<void> {\n await writeChain;\n await deleteKanbanWorkflowState(projectRoot, SDD_SESSION_WORKFLOW_ID);\n revision = 0;\n if (legacySessionPath) await fsp.unlink(legacySessionPath).catch(() => undefined);\n },\n };\n}\n\nasync function readLegacySession(sessionPath?: string): Promise<AISpecSession | null> {\n if (!sessionPath) return null;\n try {\n const value = JSON.parse(await fsp.readFile(sessionPath, 'utf8')) as unknown;\n return isAISpecSession(value) ? value : null;\n } catch {\n return null;\n }\n}\n", "/**\n * Lightweight project context for SDD interviews. Shared by CLI `/sdd` and the\n * WebUI wizard so both surfaces inject the same footprint into AI prompts\n * (package.json, TypeScript, top-level src layout) without depending on each other.\n */\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Build a short, model-friendly summary of the project root. Best-effort \u2014\n * missing files simply omit their section; never throws.\n */\nexport async function gatherProjectContext(projectRoot: string): Promise<string> {\n const parts: string[] = [];\n const root = projectRoot.trim() || process.cwd();\n\n try {\n const pkgPath = path.join(root, 'package.json');\n const pkgRaw = await fsp.readFile(pkgPath, 'utf8');\n const pkg = JSON.parse(pkgRaw) as Record<string, unknown>;\n parts.push(`Project: ${String(pkg.name ?? 'unknown')}`);\n parts.push(`Description: ${String(pkg.description ?? 'none')}`);\n if (pkg.dependencies && typeof pkg.dependencies === 'object') {\n const deps = Object.keys(pkg.dependencies as Record<string, unknown>);\n parts.push(`Dependencies: ${deps.slice(0, 20).join(', ')}${deps.length > 20 ? '...' : ''}`);\n }\n if (pkg.devDependencies && typeof pkg.devDependencies === 'object') {\n const devDeps = Object.keys(pkg.devDependencies as Record<string, unknown>);\n parts.push(\n `Dev Dependencies: ${devDeps.slice(0, 15).join(', ')}${devDeps.length > 15 ? '...' : ''}`,\n );\n }\n } catch {\n /* no package.json */\n }\n\n try {\n await fsp.access(path.join(root, 'tsconfig.json'));\n parts.push('Language: TypeScript');\n } catch {\n /* no tsconfig */\n }\n\n try {\n const srcDir = path.join(root, 'src');\n const entries = await fsp.readdir(srcDir, { withFileTypes: true });\n const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n if (dirs.length > 0) parts.push(`Source structure: src/${dirs.join(', src/')}`);\n } catch {\n /* no src dir */\n }\n\n // Monorepo packages/ layout (WrongStack-style) \u2014 useful when no root package.json deps.\n try {\n const packagesDir = path.join(root, 'packages');\n const entries = await fsp.readdir(packagesDir, { withFileTypes: true });\n const pkgs = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n if (pkgs.length > 0) {\n parts.push(\n `Packages: ${pkgs.slice(0, 25).join(', ')}${pkgs.length > 25 ? '...' : ''}`,\n );\n }\n } catch {\n /* no packages/ */\n }\n\n return parts.join('\\n');\n}\n", "import type { SpecTemplate } from '@wrongstack/core/types';\n\n/**\n * Built-in spec templates for common development scenarios.\n */\nexport const SPEC_TEMPLATES: SpecTemplate[] = [\n {\n id: 'feature',\n name: 'New Feature',\n description: 'Template for new feature development',\n sections: [\n { type: 'overview', title: 'Overview', level: 2 },\n { type: 'requirements', title: 'Requirements', level: 2 },\n { type: 'architecture', title: 'Architecture', level: 2 },\n { type: 'api', title: 'API Design', level: 2 },\n { type: 'data', title: 'Data Model', level: 2 },\n { type: 'security', title: 'Security', level: 2 },\n { type: 'acceptance', title: 'Acceptance Criteria', level: 2 },\n ],\n defaultRequirements: [\n { type: 'functional', priority: 'high', acceptanceCriteria: [], blockedBy: [], implements: [] },\n { type: 'non-functional', priority: 'medium', acceptanceCriteria: [], blockedBy: [], implements: [] },\n ],\n },\n {\n id: 'bugfix',\n name: 'Bug Fix',\n description: 'Template for bug fix specifications',\n sections: [\n { type: 'overview', title: 'Bug Description', level: 2 },\n { type: 'requirements', title: 'Root Cause Analysis', level: 2 },\n { type: 'acceptance', title: 'Fix Verification', level: 2 },\n ],\n defaultRequirements: [\n { type: 'functional', priority: 'critical', acceptanceCriteria: [], blockedBy: [], implements: [] },\n ],\n },\n {\n id: 'refactor',\n name: 'Refactor',\n description: 'Template for code refactoring',\n sections: [\n { type: 'overview', title: 'Current State', level: 2 },\n { type: 'requirements', title: 'Refactoring Goals', level: 2 },\n { type: 'architecture', title: 'Target Architecture', level: 2 },\n { type: 'acceptance', title: 'Verification', level: 2 },\n ],\n defaultRequirements: [\n { type: 'non-functional', priority: 'high', acceptanceCriteria: [], blockedBy: [], implements: [] },\n ],\n },\n {\n id: 'infra',\n name: 'Infrastructure',\n description: 'Template for infrastructure/tooling changes',\n sections: [\n { type: 'overview', title: 'What and Why', level: 2 },\n { type: 'requirements', title: 'Requirements', level: 2 },\n { type: 'architecture', title: 'Design', level: 2 },\n { type: 'security', title: 'Security Impact', level: 2 },\n { type: 'acceptance', title: 'Rollout Plan', level: 2 },\n ],\n defaultRequirements: [\n { type: 'functional', priority: 'high', acceptanceCriteria: [], blockedBy: [], implements: [] },\n { type: 'security', priority: 'high', acceptanceCriteria: [], blockedBy: [], implements: [] },\n ],\n },\n {\n id: 'integration',\n name: 'Integration',\n description: 'Template for integrating external services or APIs',\n sections: [\n { type: 'overview', title: 'Integration Overview', level: 2 },\n { type: 'requirements', title: 'Integration Requirements', level: 2 },\n { type: 'api', title: 'API Contract', level: 2 },\n { type: 'architecture', title: 'Architecture', level: 2 },\n { type: 'security', title: 'Auth & Security', level: 2 },\n { type: 'acceptance', title: 'Testing Strategy', level: 2 },\n ],\n defaultRequirements: [\n { type: 'functional', priority: 'high', acceptanceCriteria: [], blockedBy: [], implements: [] },\n { type: 'security', priority: 'critical', acceptanceCriteria: [], blockedBy: [], implements: [] },\n { type: 'performance', priority: 'medium', acceptanceCriteria: [], blockedBy: [], implements: [] },\n ],\n },\n {\n id: 'cli-command',\n name: 'CLI Command',\n description: 'Template for new CLI commands/slash commands',\n sections: [\n { type: 'overview', title: 'Command Overview', level: 2 },\n { type: 'requirements', title: 'Command Requirements', level: 2 },\n { type: 'api', title: 'Command Interface', level: 2 },\n { type: 'acceptance', title: 'Usage Examples', level: 2 },\n ],\n defaultRequirements: [\n { type: 'ux', priority: 'high', acceptanceCriteria: [], blockedBy: [], implements: [] },\n { type: 'functional', priority: 'high', acceptanceCriteria: [], blockedBy: [], implements: [] },\n ],\n },\n];\n\n/**\n * Get a template by ID.\n */\nexport function getTemplate(id: string): SpecTemplate | undefined {\n return SPEC_TEMPLATES.find((t) => t.id === id);\n}\n\n/**\n * List all available templates.\n */\nexport function listTemplates(): Array<{ id: string; name: string; description: string }> {\n return SPEC_TEMPLATES.map((t) => ({ id: t.id, name: t.name, description: t.description }));\n}\n\n/**\n * Generate a markdown skeleton from a template.\n */\nexport function templateToMarkdown(template: SpecTemplate, title?: string): string {\n const lines: string[] = [];\n lines.push(`# ${title ?? 'Untitled Specification'}`);\n lines.push('Version: 0.1.0');\n lines.push('');\n\n for (const section of template.sections) {\n lines.push(`${'#'.repeat(section.level + 1)} ${section.title}`);\n lines.push(`_<!-- ${section.type} section content -->_`);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n", "import { computeTaskProgress } from '@wrongstack/core/tasking';\nimport type { Specification, TaskGraph, TaskNode, TaskProgress } from '@wrongstack/core/types';\nimport { expectDefined, truncate } from '@wrongstack/core/utils';\n\nconst STATUS_ICON: Record<TaskNode['status'], string> = {\n pending: '\u25CB',\n in_progress: '\u25D0',\n blocked: '\u2298',\n failed: '\u2717',\n review: '\u25D1',\n completed: '\u25CF',\n};\n\nconst PRIORITY_ICON: Record<TaskNode['priority'], string> = {\n critical: '\uD83D\uDD34',\n high: '\uD83D\uDFE0',\n medium: '\uD83D\uDFE1',\n low: '\uD83D\uDFE2',\n};\n\nconst TYPE_ICON: Record<TaskNode['type'], string> = {\n feature: '\u26A1',\n bugfix: '\uD83D\uDC1B',\n refactor: '\u267B\uFE0F',\n docs: '\uD83D\uDCDD',\n test: '\uD83E\uDDEA',\n chore: '\uD83D\uDD27',\n};\n\n/**\n * Render a task graph as ASCII art for terminal display.\n */\nexport function renderTaskGraph(\n graph: TaskGraph,\n opts?: { compact?: boolean | undefined },\n): string {\n const lines: string[] = [];\n const compact = opts?.compact ?? false;\n\n // Header\n lines.push(`\u256D\u2500 Task Graph: ${graph.title} \u2500\u256E`);\n lines.push(\n `\u2502 Spec: ${graph.specId.slice(0, 8)}... \u2502 Nodes: ${graph.nodes.size} \u2502 Edges: ${graph.edges.length} \u2502`,\n );\n lines.push('\u2570' + '\u2500'.repeat(Math.max(50, graph.title.length + 30)) + '\u256F');\n lines.push('');\n\n // Progress bar\n const progress = computeTaskProgress(graph);\n lines.push(renderProgress(progress));\n lines.push('');\n\n // Build adjacency for display\n const childrenMap = new Map<string, string[]>();\n for (const edge of graph.edges) {\n if (edge.type === 'depends_on') {\n // edge.from depends on edge.to \u2192 edge.to is a blocker\n const deps = childrenMap.get(edge.from) ?? [];\n deps.push(edge.to);\n childrenMap.set(edge.from, deps);\n }\n }\n\n // Render root nodes and their dependents\n const rendered = new Set<string>();\n const rootNodes = graph.rootNodes.filter((id) => graph.nodes.has(id));\n\n // If no root nodes, use all nodes\n const startNodes =\n rootNodes.length > 0\n ? rootNodes\n : Array.from(graph.nodes.keys()).filter((id) => {\n const deps = childrenMap.get(id);\n return !deps || deps.length === 0;\n });\n\n for (const rootId of startNodes) {\n renderNode(graph, rootId, lines, rendered, childrenMap, compact, '');\n }\n\n // Render any orphan nodes\n for (const [id] of graph.nodes) {\n if (!rendered.has(id)) {\n renderNode(graph, id, lines, rendered, childrenMap, compact, '');\n }\n }\n\n // Legend\n lines.push('');\n lines.push('Legend: \u25CF done \u25D0 in-progress \u25CB pending \u2297 blocked \u2717 failed \u25D2 review');\n\n return lines.join('\\n');\n}\n\nfunction renderNode(\n graph: TaskGraph,\n nodeId: string,\n lines: string[],\n rendered: Set<string>,\n childrenMap: Map<string, string[]>,\n compact: boolean,\n prefix: string,\n): void {\n if (rendered.has(nodeId)) return;\n rendered.add(nodeId);\n\n const node = expectDefined(graph.nodes.get(nodeId));\n\n const icon = STATUS_ICON[node.status];\n const prioIcon = PRIORITY_ICON[node.priority];\n const typeIcon = TYPE_ICON[node.type];\n const title = compact ? truncate(node.title, 40) : node.title;\n\n const blockedBy = childrenMap.get(nodeId) ?? [];\n const depsStr =\n blockedBy.length > 0\n ? ` \u2190 [${blockedBy.map((d) => graph.nodes.get(d)?.title?.slice(0, 12) ?? '?').join(', ')}]`\n : '';\n\n lines.push(`${prefix}${icon} ${typeIcon} ${prioIcon} ${title}${depsStr}`);\n\n if (!compact && node.description) {\n const descLines = node.description.split('\\n').slice(0, 3);\n for (const dl of descLines) {\n lines.push(`${prefix} \u2514 ${truncate(dl, 60)}`);\n }\n }\n\n // Render nodes that depend on this one\n const dependents = graph.edges\n .filter((e) => e.type === 'depends_on' && e.to === nodeId)\n .map((e) => e.from)\n .filter((id) => graph.nodes.has(id));\n\n for (const depId of dependents) {\n renderNode(graph, depId, lines, rendered, childrenMap, compact, prefix + ' ');\n }\n}\n\n/**\n * Render a progress bar.\n */\nexport function renderProgress(progress: TaskProgress): string {\n const barWidth = 30;\n const filled = Math.round((progress.percentComplete / 100) * barWidth);\n const empty = barWidth - filled;\n const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(empty);\n\n return [\n `Progress: [${bar}] ${progress.percentComplete}%`,\n ` ${progress.completed} done \u2502 ${progress.inProgress} active \u2502 ${progress.pending} pending \u2502 ${progress.blocked} blocked \u2502 ${progress.failed} failed`,\n ].join('\\n');\n}\n\n/**\n * Render a compact task list (for quick status checks).\n */\nexport function renderTaskList(graph: TaskGraph): string {\n const lines: string[] = [];\n const nodes = Array.from(graph.nodes.values());\n\n // Group by status\n const groups: Record<TaskNode['status'], TaskNode[]> = {\n in_progress: [],\n pending: [],\n blocked: [],\n review: [],\n failed: [],\n completed: [],\n };\n\n for (const node of nodes) {\n groups[node.status].push(node);\n }\n\n for (const [status, group] of Object.entries(groups)) {\n if (group.length === 0) continue;\n const icon = STATUS_ICON[status as TaskNode['status']];\n lines.push(`${icon} ${status.toUpperCase()} (${group.length})`);\n for (const node of group) {\n const prio = PRIORITY_ICON[node.priority];\n const type = TYPE_ICON[node.type];\n lines.push(` ${type} ${prio} ${node.title}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Render spec analysis summary.\n */\nexport function renderSpecAnalysis(\n spec: Specification,\n analysis: { completeness: number; gaps: string[]; risks: string[]; suggestions: string[] },\n): string {\n const lines: string[] = [];\n\n lines.push(`\u256D\u2500 Spec Analysis: ${spec.title} \u2500\u256E`);\n lines.push('');\n\n // Completeness\n const barWidth = 20;\n const filled = Math.round((analysis.completeness / 100) * barWidth);\n const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(barWidth - filled);\n lines.push(`Completeness: [${bar}] ${analysis.completeness}%`);\n lines.push('');\n\n if (analysis.gaps.length > 0) {\n lines.push('\u26A0 Gaps:');\n for (const gap of analysis.gaps) {\n lines.push(` \u2022 ${gap}`);\n }\n lines.push('');\n }\n\n if (analysis.risks.length > 0) {\n lines.push('\uD83D\uDD34 Risks:');\n for (const risk of analysis.risks) {\n lines.push(` \u2022 ${risk}`);\n }\n lines.push('');\n }\n\n if (analysis.suggestions.length > 0) {\n lines.push('\uD83D\uDCA1 Suggestions:');\n for (const sug of analysis.suggestions) {\n lines.push(` \u2022 ${sug}`);\n }\n }\n\n return lines.join('\\n');\n}\n", "import { topologicalSort } from '@wrongstack/core/tasking';\nimport type { TaskGraph } from '@wrongstack/core/types';\nimport { expectDefined } from '@wrongstack/core/utils';\n/**\n * Enhanced critical path analysis with bottleneck detection,\n * parallel execution groups, and time estimation.\n */\nexport interface CriticalPathAnalysis {\n /** Ordered list of critical path task IDs. */\n criticalPath: string[];\n /** Total estimated hours for the critical path. */\n totalHours: number;\n /** Tasks that block the most downstream work. */\n bottlenecks: BottleneckTask[];\n /** Groups of tasks that can run in parallel. */\n parallelGroups: string[][];\n /** Recommended execution order respecting dependencies. */\n executionOrder: string[];\n /** Tasks with no blockers (can start immediately). */\n readyTasks: string[];\n /** Tasks that are blocked and cannot start. */\n blockedTasks: string[];\n}\n\nexport interface BottleneckTask {\n taskId: string;\n title: string;\n /** Number of tasks directly or transitively blocked by this task. */\n blockedCount: number;\n /** Total estimated hours of blocked downstream work. */\n blockedHours: number;\n /** Severity score (0-100). */\n severity: number;\n}\n\n/**\n * Analyze a task graph and return critical path analysis.\n */\nexport function analyzeCriticalPath(graph: TaskGraph): CriticalPathAnalysis {\n const nodes = Array.from(graph.nodes.values());\n const topoOrder = topologicalSort(graph);\n\n // Build adjacency: blocker \u2192 blocked tasks\n const blockedByMap = new Map<string, Set<string>>();\n const blocksMap = new Map<string, Set<string>>();\n\n for (const edge of graph.edges) {\n if (edge.type === 'depends_on') {\n // edge.from depends on edge.to\n if (!blockedByMap.has(edge.from)) blockedByMap.set(edge.from, new Set());\n blockedByMap.get(edge.from)?.add(edge.to);\n\n if (!blocksMap.has(edge.to)) blocksMap.set(edge.to, new Set());\n blocksMap.get(edge.to)?.add(edge.from);\n }\n }\n\n // Find ready tasks (no blockers or all blockers completed)\n const readyTasks: string[] = [];\n const blockedTasks: string[] = [];\n\n for (const node of nodes) {\n if (node.status === 'completed') continue;\n const blockers = blockedByMap.get(node.id);\n if (!blockers || blockers.size === 0) {\n readyTasks.push(node.id);\n } else {\n const allCompleted = Array.from(blockers).every((id) => {\n const n = graph.nodes.get(id);\n return n?.status === 'completed';\n });\n if (allCompleted) {\n readyTasks.push(node.id);\n } else {\n blockedTasks.push(node.id);\n }\n }\n }\n\n // Compute bottleneck scores\n const bottlenecks: BottleneckTask[] = [];\n for (const node of nodes) {\n if (node.status === 'completed') continue;\n const downstream = getTransitiveBlocked(graph, node.id, blocksMap);\n if (downstream.size > 0) {\n const blockedHours = Array.from(downstream).reduce((sum, id) => {\n const n = graph.nodes.get(id);\n return sum + (n?.estimateHours ?? 0);\n }, 0);\n bottlenecks.push({\n taskId: node.id,\n title: node.title,\n blockedCount: downstream.size,\n blockedHours,\n severity: Math.min(100, Math.round((downstream.size / nodes.length) * 100)),\n });\n }\n }\n\n bottlenecks.sort((a, b) => b.severity - a.severity);\n\n // Compute critical path (longest path by estimated hours)\n const criticalPath = computeCriticalPath(graph, topoOrder, blockedByMap);\n\n // Total hours on critical path\n const totalHours = criticalPath.reduce((sum, id) => {\n return sum + (graph.nodes.get(id)!.estimateHours ?? 0);\n }, 0);\n\n // Parallel execution groups\n const parallelGroups = computeParallelGroups(graph, blockedByMap);\n\n // Execution order: topo sort filtered to non-completed tasks\n const executionOrder = topoOrder.filter((id) => {\n const n = graph.nodes.get(id);\n return n && n.status !== 'completed';\n });\n\n return {\n criticalPath,\n totalHours,\n bottlenecks,\n parallelGroups,\n executionOrder,\n readyTasks,\n blockedTasks,\n };\n}\n\n/**\n * Get all tasks transitively blocked by a given task.\n */\nfunction getTransitiveBlocked(\n _graph: TaskGraph,\n taskId: string,\n blocksMap: Map<string, Set<string>>,\n): Set<string> {\n const visited = new Set<string>();\n const queue = [taskId];\n\n while (queue.length > 0) {\n const current = expectDefined(queue.shift());\n const blocked = blocksMap.get(current);\n if (!blocked) continue;\n for (const id of blocked) {\n if (!visited.has(id) && id !== taskId) {\n visited.add(id);\n queue.push(id);\n }\n }\n }\n\n return visited;\n}\n\n/**\n * Compute the critical path (longest path by estimated hours).\n */\nfunction computeCriticalPath(\n graph: TaskGraph,\n _topoOrder: string[],\n blockedByMap: Map<string, Set<string>>,\n): string[] {\n // Use all nodes in the graph, not just topo-reachable ones\n const allIds = Array.from(graph.nodes.keys());\n if (allIds.length === 0) return [];\n\n const dist = new Map<string, number>();\n const prev = new Map<string, string | null>();\n\n // Initialize each node's distance to its own estimate\n for (const id of allIds) {\n dist.set(id, graph.nodes.get(id)?.estimateHours ?? 1);\n prev.set(id, null);\n }\n\n // Build reverse map: blocker \u2192 tasks it blocks\n const blocksMap = new Map<string, Set<string>>();\n for (const [taskId, blockers] of blockedByMap) {\n for (const blockerId of blockers) {\n if (!blocksMap.has(blockerId)) blocksMap.set(blockerId, new Set());\n blocksMap.get(blockerId)?.add(taskId);\n }\n }\n\n // Relax edges repeatedly (Bellman-Ford style) since topoOrder may be incomplete.\n // Run N-1 iterations to handle longest path in DAG.\n const n = allIds.length;\n for (let i = 0; i < n - 1; i++) {\n let changed = false;\n for (const id of allIds) {\n const blocked = blocksMap.get(id);\n if (!blocked) continue;\n for (const blockedId of blocked) {\n const candidateDist = dist.get(id)! + (graph.nodes.get(blockedId)?.estimateHours ?? 1);\n if (candidateDist > (dist.get(blockedId) ?? 0)) {\n dist.set(blockedId, candidateDist);\n prev.set(blockedId, id);\n changed = true;\n }\n }\n }\n if (!changed) break;\n }\n\n // Find the node with maximum distance (end of critical path)\n let maxDist = 0;\n let maxId = expectDefined(allIds[0]);\n for (const id of allIds) {\n const d = dist.get(id)!;\n if (d > maxDist) {\n maxDist = d;\n maxId = id;\n }\n }\n\n // Trace back the critical path\n const path: string[] = [];\n let current: string | null = maxId;\n const visited = new Set<string>();\n while (current && !visited.has(current)) {\n visited.add(current);\n path.unshift(current);\n current = prev.get(current) ?? null;\n }\n\n return path;\n}\n\n/**\n * Compute groups of tasks that can run in parallel.\n * Tasks in the same group have no dependencies on each other.\n */\nfunction computeParallelGroups(\n graph: TaskGraph,\n blockedByMap: Map<string, Set<string>>,\n): string[][] {\n const groups: string[][] = [];\n const assigned = new Set<string>();\n const nodes = Array.from(graph.nodes.values()).filter((n) => n.status !== 'completed');\n\n // Topological levels\n const remaining = new Set(nodes.map((n) => n.id));\n\n while (remaining.size > 0) {\n const group: string[] = [];\n for (const id of remaining) {\n const blockers = blockedByMap.get(id);\n if (!blockers || blockers.size === 0) {\n group.push(id);\n } else {\n const allAssigned = Array.from(blockers).every((b) => assigned.has(b));\n if (allAssigned) {\n group.push(id);\n }\n }\n }\n\n if (group.length === 0) {\n // Circular dependency or all remaining are blocked by non-completed\n // Just take the first remaining\n group.push(expectDefined(Array.from(remaining)[0]));\n }\n\n for (const id of group) {\n assigned.add(id);\n remaining.delete(id);\n }\n groups.push(group);\n }\n\n return groups;\n}\n", "import type { Specification, SpecRequirement, TaskGraph, TaskNode } from '@wrongstack/core/types';\nimport { assertNever } from '@wrongstack/core/utils';\n\nexport interface SpecVersion {\n version: string;\n spec: Specification;\n timestamp: number;\n changeDescription?: string | undefined;\n}\n\nexport interface SpecDiff {\n added: SpecRequirement[];\n removed: SpecRequirement[];\n modified: Array<{\n requirement: SpecRequirement;\n previousVersion: SpecRequirement;\n changes: string[];\n }>;\n summary: string;\n}\n\n/**\n * Track spec versions and compute diffs between versions.\n */\nexport class SpecVersioning {\n private versions = new Map<string, SpecVersion[]>();\n\n /** Record a new version of a spec. */\n recordVersion(spec: Specification, changeDescription?: string): SpecVersion {\n const version: SpecVersion = {\n version: spec.version,\n spec: { ...spec },\n timestamp: Date.now(),\n changeDescription,\n };\n\n const history = this.versions.get(spec.id) ?? [];\n history.push(version);\n this.versions.set(spec.id, history);\n\n return version;\n }\n\n /** Get version history for a spec. */\n getHistory(specId: string): SpecVersion[] {\n return this.versions.get(specId) ?? [];\n }\n\n /** Get a specific version of a spec. */\n getVersion(specId: string, version: string): SpecVersion | undefined {\n const history = this.versions.get(specId) ?? [];\n return history.find((v) => v.version === version);\n }\n\n /** Get the latest version of a spec. */\n getLatest(specId: string): SpecVersion | undefined {\n const history = this.versions.get(specId) ?? [];\n return history[history.length - 1];\n }\n\n /** Compute diff between two versions of a spec. */\n diff(oldSpec: Specification, newSpec: Specification): SpecDiff {\n const oldReqs = new Map(oldSpec.requirements.map((r) => [r.id, r]));\n const newReqs = new Map(newSpec.requirements.map((r) => [r.id, r]));\n\n const added: SpecRequirement[] = [];\n const removed: SpecRequirement[] = [];\n const modified: SpecDiff['modified'] = [];\n\n // Find added and modified\n for (const [id, newReq] of newReqs) {\n const oldReq = oldReqs.get(id);\n if (!oldReq) {\n added.push(newReq);\n } else {\n const changes = this.compareRequirements(oldReq, newReq);\n if (changes.length > 0) {\n modified.push({\n requirement: newReq,\n previousVersion: oldReq,\n changes,\n });\n }\n }\n }\n\n // Find removed\n for (const [id, oldReq] of oldReqs) {\n if (!newReqs.has(id)) {\n removed.push(oldReq);\n }\n }\n\n const parts: string[] = [];\n if (added.length > 0) parts.push(`${added.length} added`);\n if (removed.length > 0) parts.push(`${removed.length} removed`);\n if (modified.length > 0) parts.push(`${modified.length} modified`);\n\n return {\n added,\n removed,\n modified,\n summary: parts.length > 0 ? parts.join(', ') : 'No changes',\n };\n }\n\n /**\n * Update a task graph incrementally based on spec changes.\n * - Added requirements \u2192 new tasks\n * - Removed requirements \u2192 remove tasks\n * - Modified requirements \u2192 update task descriptions\n * Returns the updated graph and list of changes made.\n */\n updateTaskGraph(\n graph: TaskGraph,\n oldSpec: Specification,\n newSpec: Specification,\n ): { graph: TaskGraph; changes: string[] } {\n const specDiff = this.diff(oldSpec, newSpec);\n const changes: string[] = [];\n\n // Map requirement IDs to task nodes\n const reqToTask = new Map<string, TaskNode>();\n for (const node of graph.nodes.values()) {\n if (node.specRequirementId) {\n reqToTask.set(node.specRequirementId, node);\n }\n }\n\n // Remove tasks for removed requirements\n for (const req of specDiff.removed) {\n const task = reqToTask.get(req.id);\n if (task) {\n graph.nodes.delete(task.id);\n graph.edges = graph.edges.filter((e) => e.from !== task.id && e.to !== task.id);\n changes.push(`Removed task: ${task.title}`);\n }\n }\n\n // Update tasks for modified requirements\n for (const mod of specDiff.modified) {\n const task = reqToTask.get(mod.requirement.id);\n if (task) {\n task.title = mod.requirement.description;\n task.description = this.buildTaskDescription(mod.requirement);\n task.priority = mod.requirement.priority;\n task.updatedAt = Date.now();\n changes.push(`Updated task: ${task.title} (${mod.changes.join(', ')})`);\n }\n }\n\n // Add tasks for new requirements\n for (const req of specDiff.added) {\n const now = Date.now();\n const newTask: TaskNode = {\n id: crypto.randomUUID(),\n title: req.description,\n description: this.buildTaskDescription(req),\n type: this.mapReqType(req.type),\n priority: req.priority,\n status: 'pending',\n specRequirementId: req.id,\n tags: [req.type, req.priority],\n createdAt: now,\n updatedAt: now,\n };\n graph.nodes.set(newTask.id, newTask);\n graph.rootNodes.push(newTask.id);\n changes.push(`Added task: ${newTask.title}`);\n }\n\n graph.updatedAt = Date.now();\n return { graph, changes };\n }\n\n private compareRequirements(old: SpecRequirement, current: SpecRequirement): string[] {\n const changes: string[] = [];\n if (old.description !== current.description) changes.push('description');\n if (old.priority !== current.priority) changes.push('priority');\n if (old.type !== current.type) changes.push('type');\n if (JSON.stringify(old.acceptanceCriteria) !== JSON.stringify(current.acceptanceCriteria)) {\n changes.push('acceptance criteria');\n }\n if (JSON.stringify(old.blockedBy) !== JSON.stringify(current.blockedBy)) {\n changes.push('dependencies');\n }\n return changes;\n }\n\n private buildTaskDescription(req: SpecRequirement): string {\n const lines = [req.description, '', `**Type:** ${req.type}`, `**Priority:** ${req.priority}`];\n if (req.acceptanceCriteria.length > 0) {\n lines.push('', '**Acceptance Criteria:**');\n for (const ac of req.acceptanceCriteria) {\n lines.push(`- ${ac}`);\n }\n }\n return lines.join('\\n');\n }\n\n private mapReqType(type: SpecRequirement['type']): TaskNode['type'] {\n switch (type) {\n case 'functional':\n return 'feature';\n case 'non-functional':\n return 'feature';\n case 'security':\n return 'feature';\n case 'performance':\n return 'feature';\n case 'ux':\n return 'feature';\n default:\n return assertNever(type);\n }\n }\n}\n", "import type { EventBus } from '@wrongstack/core/kernel';\nimport type { TaskTracker } from '@wrongstack/core/tasking';\nimport type { Specification, TaskGraph, TaskNode } from '@wrongstack/core/types';\nimport { analyzeCriticalPath } from './critical-path.js';\n\nexport interface AutoExecutorOptions {\n tracker: TaskTracker;\n events: EventBus;\n /** Maximum concurrent tasks. Defaults to 1 (sequential). */\n maxConcurrent?: number | undefined;\n /** Maximum retry attempts for failed tasks. */\n maxRetries?: number | undefined;\n /** Custom task executor function. */\n executeTask: (task: TaskNode, context: TaskExecutionContext) => Promise<TaskExecutionResult>;\n /** Called before each task starts. */\n onTaskStart?: ((task: TaskNode) => void) | undefined;\n /** Called after each task completes. */\n onTaskComplete?: (task: TaskNode, result: TaskExecutionResult) => void;\n /** Called when a task fails. */\n onTaskFail?: (task: TaskNode, error: Error, retryCount: number) => void;\n /** Called when all tasks are done or no more can execute. */\n onDone?: ((summary: ExecutionSummary) => void) | undefined;\n}\n\nexport interface TaskExecutionContext {\n /** The spec being implemented. */\n spec: Specification;\n /** The full task graph. */\n graph: TaskGraph;\n /** The current task being executed. */\n task: TaskNode;\n /** Tasks that this task depends on. */\n dependencies: TaskNode[];\n /** Tasks that depend on this task. */\n dependents: TaskNode[];\n /** Retry count for this task (0 = first attempt). */\n retryCount: number;\n}\n\nexport interface TaskExecutionResult {\n success: boolean;\n output?: string | undefined;\n error?: string | undefined;\n /** If true, the task will be retried. */\n retry?: boolean | undefined;\n}\n\nexport interface ExecutionSummary {\n total: number;\n completed: number;\n failed: number;\n skipped: number;\n retried: number;\n duration: number;\n criticalPath: string[];\n}\n\n/**\n * Auto-executor that drives task execution with dependency resolution,\n * retry logic, and critical path awareness.\n */\nexport class AutoExecutor {\n private readonly opts: AutoExecutorOptions;\n private stopped = false;\n private retryMap = new Map<string, number>();\n\n constructor(opts: AutoExecutorOptions) {\n this.opts = opts;\n }\n\n /**\n * Execute all tasks in the graph, respecting dependencies.\n */\n async execute(graph: TaskGraph, spec: Specification): Promise<ExecutionSummary> {\n this.stopped = false;\n this.retryMap.clear();\n const startTime = Date.now();\n\n const critical = analyzeCriticalPath(graph);\n let completed = 0;\n let failed = 0;\n const skipped = 0;\n let retried = 0;\n\n while (!this.stopped) {\n const readyTasks = this.getReadyTasks(graph);\n\n if (readyTasks.length === 0) {\n // Check if all tasks are done\n const allDone = Array.from(graph.nodes.values()).every(\n (n) => n.status === 'completed' || n.status === 'failed',\n );\n if (allDone) break;\n\n // Check for deadlock (all remaining tasks are blocked by failed tasks)\n const hasDeadlock = this.detectDeadlock(graph);\n if (hasDeadlock) break;\n\n break;\n }\n\n // Execute batch\n const batch = readyTasks.slice(0, this.opts.maxConcurrent ?? 1);\n\n const results = await Promise.allSettled(\n batch.map((task) => this.executeTaskWithRetry(task, graph, spec)),\n );\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i]!;\n const task = batch[i]!;\n\n if (result.status === 'fulfilled') {\n const { result: execResult, retries } = result.value;\n if (execResult.success) {\n this.opts.tracker.updateNodeStatus(task.id, 'completed');\n completed++;\n if (retries > 0) retried++;\n this.opts.onTaskComplete?.(task, execResult);\n } else if (execResult.retry) {\n retried++;\n // Task will be retried on next iteration\n } else {\n this.opts.tracker.updateNodeStatus(task.id, 'failed', execResult.error);\n failed++;\n }\n } else {\n this.opts.tracker.updateNodeStatus(task.id, 'failed', String(result.reason));\n failed++;\n this.opts.onTaskFail?.(task, result.reason as Error, 0);\n }\n }\n }\n\n const duration = Date.now() - startTime;\n const summary: ExecutionSummary = {\n total: graph.nodes.size,\n completed,\n failed,\n skipped,\n retried,\n duration,\n criticalPath: critical.criticalPath,\n };\n\n this.opts.onDone?.(summary);\n return summary;\n }\n\n /** Stop execution. */\n stop(): void {\n this.stopped = true;\n }\n\n /** Get tasks that are ready to execute (all dependencies completed). */\n private getReadyTasks(graph: TaskGraph): TaskNode[] {\n const ready: TaskNode[] = [];\n\n for (const node of graph.nodes.values()) {\n if (node.status !== 'pending') continue;\n\n // Check if all blockers are completed\n const blockers = graph.edges\n .filter((e) => e.type === 'depends_on' && e.from === node.id)\n .map((e) => graph.nodes.get(e.to))\n .filter(Boolean) as TaskNode[];\n\n const allBlockersDone = blockers.every((b) => b.status === 'completed');\n if (allBlockersDone) {\n ready.push(node);\n }\n }\n\n // Sort by priority\n const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };\n ready.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);\n\n return ready;\n }\n\n /** Execute a single task with retry logic. */\n private async executeTaskWithRetry(\n task: TaskNode,\n graph: TaskGraph,\n spec: Specification,\n ): Promise<{ result: TaskExecutionResult; retries: number }> {\n const maxRetries = this.opts.maxRetries ?? 2;\n let retryCount = this.retryMap.get(task.id) ?? 0;\n\n while (true) {\n this.opts.tracker.updateNodeStatus(task.id, 'in_progress');\n this.opts.onTaskStart?.(task);\n\n const dependencies = this.getTaskDependencies(task.id, graph);\n const dependents = this.getTaskDependents(task.id, graph);\n\n const context: TaskExecutionContext = {\n spec,\n graph,\n task,\n dependencies,\n dependents,\n retryCount,\n };\n\n try {\n const result = await this.opts.executeTask(task, context);\n\n if (result.success) {\n const retriesForTask = this.retryMap.get(task.id) ?? 0;\n this.retryMap.delete(task.id);\n return { result, retries: retriesForTask };\n }\n\n if (result.retry && retryCount < maxRetries) {\n retryCount++;\n this.retryMap.set(task.id, retryCount);\n this.opts.tracker.updateNodeStatus(task.id, 'pending');\n continue;\n }\n\n return { result, retries: retryCount };\n } catch (error) {\n if (retryCount < maxRetries) {\n retryCount++;\n this.retryMap.set(task.id, retryCount);\n this.opts.tracker.updateNodeStatus(task.id, 'pending');\n this.opts.onTaskFail?.(task, error as Error, retryCount);\n continue;\n }\n\n return {\n result: {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n },\n retries: retryCount,\n };\n }\n }\n }\n\n /** Get tasks that this task depends on. */\n private getTaskDependencies(taskId: string, graph: TaskGraph): TaskNode[] {\n return graph.edges\n .filter((e) => e.type === 'depends_on' && e.from === taskId)\n .map((e) => graph.nodes.get(e.to))\n .filter(Boolean) as TaskNode[];\n }\n\n /** Get tasks that depend on this task. */\n private getTaskDependents(taskId: string, graph: TaskGraph): TaskNode[] {\n return graph.edges\n .filter((e) => e.type === 'depends_on' && e.to === taskId)\n .map((e) => graph.nodes.get(e.from))\n .filter(Boolean) as TaskNode[];\n }\n\n /** Detect deadlock: all remaining tasks are blocked by failed tasks. */\n private detectDeadlock(graph: TaskGraph): boolean {\n const remaining = Array.from(graph.nodes.values()).filter(\n (n) => n.status === 'pending' || n.status === 'blocked',\n );\n\n if (remaining.length === 0) return false;\n\n return remaining.every((node) => {\n const blockers = graph.edges\n .filter((e) => e.type === 'depends_on' && e.from === node.id)\n .map((e) => graph.nodes.get(e.to))\n .filter(Boolean) as TaskNode[];\n\n return blockers.some((b) => b.status === 'failed');\n });\n }\n}\n\n/**\n * Create an auto-executor that works with TaskFlow.\n */\nexport function createAutoExecutor(opts: {\n tracker: TaskTracker;\n events: EventBus;\n executeTask: AutoExecutorOptions['executeTask'];\n maxConcurrent?: number | undefined;\n maxRetries?: number | undefined;\n}): AutoExecutor {\n return new AutoExecutor({\n tracker: opts.tracker,\n events: opts.events,\n executeTask: opts.executeTask,\n maxConcurrent: opts.maxConcurrent,\n maxRetries: opts.maxRetries,\n });\n}\n", "// SddSupervisor \u2014 a decision agent over an SDD parallel run.\n//\n// When a task has exhausted its retries and is about to go terminal, the\n// SddParallelRun consults `superviseFailure` (see SddParallelRunOptions). This\n// supervisor answers that consult by asking a BrainArbiter (policy \u2192 LLM \u2192\n// human, reused from the coordination layer) whether to retry, reassign to a\n// different model, split the task into sub-tasks, or give up. The goal is the\n// user's: a run should \"decide\" rather than dead-end \u2014 never silently get stuck.\n//\n// Safe by default: with the conservative DefaultBrainArbiter (no LLM) the\n// `fallback: 'continue'` policy resolves to a plain retry, so wiring a supervisor\n// never makes a run worse \u2014 it only adds intelligence when an LLM brain is wired.\n\nimport { parseModelRef } from '@wrongstack/core/agent';\nimport type { BrainArbiter } from '@wrongstack/core/coordination';\nimport type { TaskNode } from '@wrongstack/core/types';\nimport type { SddSubtaskSpec, SddSupervisorVerdict } from './sdd-parallel-run.js';\n\nexport interface SddSupervisorOptions {\n /** Decision authority (policy/LLM/human). Reuse the session's TOKENS.BrainArbiter. */\n brain: BrainArbiter;\n /**\n * Models to rotate through on a `reassign` verdict (e.g. the run's fallback\n * chain). Omit to drop the reassign option entirely.\n */\n reassignModels?: string[] | undefined;\n /**\n * Optional sub-task generator for a `split` verdict \u2014 typically an LLM call\n * that decomposes the failing task into smaller pieces. Omit to drop the split\n * option. Returning an empty array degrades the split into a retry.\n */\n generateSubtasks?:\n | ((info: { task: TaskNode; error: string }) => Promise<SddSubtaskSpec[]>)\n | undefined;\n /**\n * Let the tiered brain's LLM layer actually pick the verdict.\n *\n * Default (false) requests `fallback: 'continue'`, which the policy layer\n * answers immediately (a bounded retry) \u2014 the LLM never runs, so `reassign`/\n * `split` can't be chosen. Set true to request `fallback: 'ask_human'`, which\n * makes the policy escalate so the autonomous (LLM) layer decides.\n *\n * ONLY enable this when the supplied `brain` will NOT block on a human prompt\n * for an unresolved decision (i.e. it has an autonomous layer and is NOT\n * wrapped in `HumanEscalatingBrainArbiter`). When the LLM can't decide (no\n * autonomous layer / over the risk ceiling / LLM down) the brain returns\n * `ask_human`, which the supervisor degrades to a **bounded retry** (never a\n * block, never a dead-end). A human-escalating brain would instead block\n * inside `decide()` and wedge the run \u2014 keep this false there.\n */\n requestLlmVerdict?: boolean | undefined;\n}\n\nexport class SddSupervisor {\n constructor(private readonly opts: SddSupervisorOptions) {}\n\n /**\n * Bind this as `SddParallelRunOptions.superviseFailure`. Returns a verdict the\n * run applies, or `undefined`/`{action:'fail'}` to let the task terminal-fail.\n */\n readonly superviseFailure = async (info: {\n task: TaskNode;\n error: string;\n attempts: number;\n }): Promise<SddSupervisorVerdict | undefined> => {\n const { task, error, attempts } = info;\n const canReassign = (this.opts.reassignModels?.length ?? 0) > 0;\n const canSplit = Boolean(this.opts.generateSubtasks);\n\n const decision = await this.opts.brain.decide({\n id: `sdd-supervisor-${task.id}-${attempts}`,\n source: 'system',\n question: `SDD task \"${task.title}\" exhausted its retries. How should the run proceed?`,\n context: `Error: ${error}\\nSupervisor rescues already used: ${attempts}`,\n options: [\n { id: 'retry', label: 'Retry the task as-is', recommended: true },\n ...(canReassign ? [{ id: 'reassign', label: 'Reassign to a different model' }] : []),\n ...(canSplit ? [{ id: 'split', label: 'Split into smaller sub-tasks' }] : []),\n { id: 'fail', label: 'Give up and mark the task failed' },\n ],\n // Higher risk once we've already rescued it once \u2014 pushes a wired LLM/human\n // toward a decisive verdict instead of looping retries.\n risk: attempts >= 1 ? 'high' : 'medium',\n // `continue` \u2192 policy answers in place (bounded retry, LLM never runs).\n // `ask_human` \u2192 policy escalates so the autonomous LLM layer can actually\n // pick reassign/split (see requestLlmVerdict's safety contract).\n fallback: this.opts.requestLlmVerdict ? 'ask_human' : 'continue',\n });\n\n // A hard deny is a decisive \"give up\" \u2192 terminal fail. An unresolved\n // escalation (`ask_human`: the LLM declined / was unavailable / over the\n // ceiling) degrades to a bounded retry so the run keeps moving rather than\n // dead-ending \u2014 the never-stuck invariant. (A human-escalating brain would\n // have blocked inside decide() already; requestLlmVerdict forbids that.)\n if (decision.type === 'deny') return { action: 'fail' };\n if (decision.type !== 'answer') return { action: 'retry' };\n // DefaultBrainArbiter's 'continue' answer carries no optionId \u2192 retry.\n const choice = decision.optionId ?? 'retry';\n\n if (choice === 'fail') return { action: 'fail' };\n if (choice === 'reassign' && canReassign) {\n const models = this.opts.reassignModels as string[];\n // Rotate through the chain by rescue count; a `provider/model` entry sets\n // both fields so the worker dispatches on the right provider (a bare model\n // keeps the task's current provider).\n const ref = models[attempts % models.length];\n const parsed = ref ? parseModelRef(ref) : undefined;\n return { action: 'reassign', model: parsed?.model, provider: parsed?.provider };\n }\n if (choice === 'split' && this.opts.generateSubtasks) {\n const subtasks = await this.opts\n .generateSubtasks({ task, error })\n .catch(() => [] as SddSubtaskSpec[]);\n return subtasks.length ? { action: 'split', subtasks } : { action: 'retry' };\n }\n return { action: 'retry' };\n };\n}\n", "// makeCommandVerifier \u2014 the shared completion-gate verifier for an SDD parallel\n// run. Both surfaces that start a run (the CLI `/sdd parallel` handler and the\n// standalone WebUI wizard) need an identical `verifyTask`: when a task declares\n// `metadata.verificationCommand`, run it in the task's worktree cwd and only let\n// the task complete on exit 0. No command \u2192 no-op. Bounded by a timeout so a\n// hung verifier can't wedge the run.\n//\n// SECURITY: verification commands are spawned as executable + argv with\n// `shell: false`. The command string is tokenized into an argv array *without*\n// shell interpolation, so metacharacters (; && | $() etc.) are passed as\n// literal arguments to the executable rather than being interpreted by a shell.\n// This is defense-in-depth: even if the authorization gate on\n// `set_task_verification` were bypassed, an attacker cannot achieve shell\n// injection through the verification command.\n\nimport { spawn } from 'node:child_process';\nimport type { TaskNode, TaskResult } from '@wrongstack/core/types';\n\nexport interface CommandVerifierOptions {\n /** Metadata key holding the verification command. Default 'verificationCommand'. */\n metadataKey?: string;\n /** Kill + fail the verification after this many ms. Default 180_000 (3 min). */\n timeoutMs?: number;\n}\n\n/**\n * Tokenize a command string into an argv array **without** shell interpolation.\n *\n * Splits on whitespace while respecting single and double quotes (matching\n * POSIX shell quoting rules for the common cases). Shell metacharacters\n * (`;`, `|`, `&&`, `$()`, backticks, `>`, `<`) that appear *inside* a token\n * are preserved as literal characters \u2014 they are passed to the executable as\n * argument data, never interpreted by a shell.\n *\n * Returns `undefined` when the input is empty/whitespace or contains\n * unbalanced quotes (which would indicate a malformed command).\n */\nexport function tokenizeCommand(command: string): string[] | undefined {\n const trimmed = command.trim();\n if (!trimmed) return undefined;\n\n const argv: string[] = [];\n let current = '';\n let inSingle = false;\n let inDouble = false;\n let hasToken = false;\n\n for (let i = 0; i < trimmed.length; i++) {\n const ch = trimmed[i]!;\n\n if (inSingle) {\n if (ch === \"'\") {\n inSingle = false;\n } else {\n current += ch;\n }\n continue;\n }\n\n if (inDouble) {\n if (ch === '\"') {\n inDouble = false;\n } else if (ch === '\\\\' && i + 1 < trimmed.length) {\n // Inside double quotes, backslash escapes only \", \\, $, and `.\n const next = trimmed[i + 1]!;\n if (next === '\"' || next === '\\\\' || next === '$' || next === '`') {\n current += next;\n i++;\n } else {\n current += ch;\n }\n } else {\n current += ch;\n }\n continue;\n }\n\n if (ch === \"'\") {\n inSingle = true;\n hasToken = true;\n continue;\n }\n\n if (ch === '\"') {\n inDouble = true;\n hasToken = true;\n continue;\n }\n\n if (ch === '\\\\' && i + 1 < trimmed.length) {\n // Outside quotes, backslash escapes the next character literally.\n current += trimmed[i + 1]!;\n i++;\n hasToken = true;\n continue;\n }\n\n if (ch === ' ' || ch === '\\t') {\n if (hasToken) {\n argv.push(current);\n current = '';\n hasToken = false;\n }\n continue;\n }\n\n current += ch;\n hasToken = true;\n }\n\n // Unbalanced quote \u2014 refuse to execute.\n if (inSingle || inDouble) return undefined;\n\n if (hasToken) argv.push(current);\n\n return argv.length > 0 ? argv : undefined;\n}\n\n/** Shape shared by every SDD task verifier (matches SddParallelRunOptions.verifyTask). */\nexport type SddVerifyTask = (info: {\n task: TaskNode;\n result: TaskResult;\n cwd: string;\n}) => Promise<{ ok: boolean; reason?: string }>;\n\n/**\n * AND-compose verifiers: run in order, first failure wins (its reason\n * propagates); later parts are skipped once one fails.\n */\nexport function makeCompositeVerifier(parts: SddVerifyTask[]): SddVerifyTask {\n return async function verifyTask(info) {\n for (const part of parts) {\n const outcome = await part(info);\n if (!outcome.ok) return outcome;\n }\n return { ok: true };\n };\n}\n\nexport interface AcceptanceCriteriaVerifierOptions {\n /** Runs one self-contained, isolated LLM turn and resolves its final text. */\n run: (prompt: string) => Promise<string>;\n /** Cap on the result excerpt included in the prompt. Default 4000 chars. */\n maxResultChars?: number;\n}\n\n/**\n * LLM acceptance-criteria check: when a task's description carries an\n * \"**Acceptance Criteria:**\" block, ask an isolated judge turn whether the\n * worker's reported result satisfies the criteria. Fails CLOSED only on an\n * explicit FAIL verdict \u2014 judge errors or ambiguous output pass with the\n * command verifier remaining the deterministic backstop, so a flaky judge\n * can never wedge a run.\n */\nexport function makeAcceptanceCriteriaVerifier(\n options: AcceptanceCriteriaVerifierOptions,\n): SddVerifyTask {\n const maxResultChars = options.maxResultChars ?? 4000;\n return async function verifyTask(info) {\n const description = info.task.description ?? '';\n const marker = description.indexOf('**Acceptance Criteria:**');\n if (marker === -1) return { ok: true };\n const criteria = description.slice(marker);\n const resultText =\n typeof info.result.result === 'string'\n ? info.result.result.slice(0, maxResultChars)\n : JSON.stringify(info.result.result ?? '').slice(0, maxResultChars);\n\n let text: string;\n try {\n text = await options.run(\n [\n 'You are a strict acceptance reviewer for one completed engineering task.',\n `Task: ${info.task.title}`,\n '',\n criteria,\n '',\n \"Worker's reported result:\",\n resultText || '(no result text)',\n '',\n 'Does the reported result plausibly satisfy EVERY acceptance criterion?',\n 'Answer with exactly one line: \"VERDICT: PASS\" or \"VERDICT: FAIL \u2014 <short reason>\".',\n ].join('\\n'),\n );\n } catch {\n return { ok: true };\n }\n const match = text.match(/VERDICT:\\s*(PASS|FAIL)(?:\\s*[\u2014-]\\s*(.*))?/i);\n if (!match) return { ok: true };\n if (match[1]!.toUpperCase() === 'PASS') return { ok: true };\n return {\n ok: false,\n reason: `acceptance criteria not met: ${match[2]?.trim() || 'judge rejected the result'}`,\n };\n };\n}\n\n/**\n * Build a `verifyTask` closure (shape matches {@link SddParallelRunOptions.verifyTask}).\n * Returns `{ ok: true }` immediately when the task carries no verification command,\n * otherwise spawns the command in `cwd` as `executable + argv` with `shell: false`\n * (no shell interpolation), and resolves `{ ok: false, reason }` on non-zero exit,\n * spawn error, malformed command, or timeout.\n *\n * Defense-in-depth: even if the authorization gate on `set_task_verification`\n * were bypassed, shell metacharacters (`;`, `|`, `&&`, `$()`, etc.) are tokenized\n * into literal arguments rather than being interpreted by a shell.\n */\nexport function makeCommandVerifier(options: CommandVerifierOptions = {}) {\n const metadataKey = options.metadataKey ?? 'verificationCommand';\n const timeoutMs = options.timeoutMs ?? 180_000;\n\n return async function verifyTask(info: {\n task: TaskNode;\n result: TaskResult;\n cwd: string;\n }): Promise<{ ok: boolean; reason?: string }> {\n const rawCommand = info.task.metadata?.[metadataKey];\n if (typeof rawCommand !== 'string' || !rawCommand.trim()) return { ok: true };\n\n // Tokenize the command string into executable + argv WITHOUT shell\n // interpolation. Metacharacters become literal argument data.\n const argv = tokenizeCommand(rawCommand);\n if (!argv || argv.length === 0) {\n return { ok: false, reason: `verification command is malformed: ${rawCommand}` };\n }\n\n const [executable, ...args] = argv;\n\n return await new Promise((resolve) => {\n const child = spawn(executable!, args, {\n cwd: info.cwd,\n shell: false,\n windowsHide: true,\n stdio: 'ignore',\n });\n let timedOut = false;\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill();\n resolve({ ok: false, reason: `verification timed out: ${rawCommand}` });\n }, timeoutMs);\n child.on('exit', (code) => {\n clearTimeout(timer);\n // Don't overwrite the timeout reason once the timer has fired.\n if (timedOut) return;\n resolve(\n code === 0\n ? { ok: true }\n : { ok: false, reason: `verification failed (exit ${code}): ${rawCommand}` },\n );\n });\n child.on('error', (err) => {\n clearTimeout(timer);\n resolve({ ok: false, reason: `verification spawn error: ${String(err)}` });\n });\n });\n };\n}\n", "// makeLlmSubtaskGenerator \u2014 the LLM auto-split backing for the SDD supervisor.\n//\n// When the supervisor's brain returns a `split` verdict for a retry-exhausted\n// task, it calls `generateSubtasks(task, error)` to decompose the failing task\n// into smaller pieces. This helper produces that closure from a single `run`\n// callback (one isolated LLM turn \u2192 text), so core stays free of agent-spawning\n// coupling: each surface supplies the runner via its own subagent factory (the\n// same isolated-turn pattern as the interview driver).\n//\n// Safety: the result is heavily validated and bounded. A leaf can only be split\n// into \u22652 well-formed sub-tasks; anything else (parse failure, 0/1 items, junk)\n// returns [] and the supervisor degrades the split into a bounded retry. The\n// per-task `maxSupervisorEscalations` guard already caps how often this runs, so\n// recursive splitting can't run away.\n\nimport type { TaskNode, TaskPriority, TaskType } from '@wrongstack/core/types';\nimport { readBundledInstructionText, renderInstructionTemplate } from '@wrongstack/core/utils';\nimport type { SddSubtaskSpec } from './sdd-parallel-run.js';\n\nconst TASK_TYPES = new Set<TaskType>(['feature', 'bugfix', 'refactor', 'docs', 'test', 'chore']);\nconst PRIORITIES = new Set<TaskPriority>(['critical', 'high', 'medium', 'low']);\n\nexport interface SubtaskGeneratorOptions {\n /** Runs one self-contained, isolated LLM turn and resolves its final text. */\n run: (prompt: string) => Promise<string>;\n /** Minimum well-formed sub-tasks required to accept a split. Default 2. */\n minSubtasks?: number;\n /** Maximum sub-tasks kept (excess is dropped). Default 4. */\n maxSubtasks?: number;\n}\n\n/** Extract a JSON array from model output (```json fence or first bare `[...]`). */\nfunction extractJsonArray(text: string): string | null {\n const fence = text.match(/```(?:json)?\\s*(\\[[\\s\\S]*?\\])\\s*```/);\n if (fence?.[1]) return fence[1].trim();\n const bare = text.match(/(\\[[\\s\\S]*\\])/);\n if (bare?.[1]) {\n try {\n if (Array.isArray(JSON.parse(bare[1]))) return bare[1];\n } catch {\n // not valid JSON \u2014 fall through\n }\n }\n return null;\n}\n\nfunction buildPrompt(task: TaskNode, error: string, min: number, max: number): string {\n return renderInstructionTemplate(readBundledInstructionText('sdd/decompose-task.md'), {\n minSubtasks: String(min),\n maxSubtasks: String(max),\n title: task.title,\n description: task.description,\n error: error || '(none recorded)',\n });\n}\n\n/** Parse and validate model output into SddSubtaskSpec[] (shared by both generators). */\nfunction parseSubtaskSpecs(\n text: string,\n min: number,\n max: number,\n options: { acceptSuccessCriterion?: boolean } = {},\n): SddSubtaskSpec[] {\n const json = extractJsonArray(text ?? '');\n if (!json) return [];\n\n let raw: unknown;\n try {\n raw = JSON.parse(json);\n } catch {\n return [];\n }\n // extractJsonArray only returns bracketed JSON arrays.\n const items = raw as unknown[];\n\n const specs: SddSubtaskSpec[] = [];\n for (const item of items) {\n if (!item || typeof item !== 'object') continue;\n const r = item as Record<string, unknown>;\n const title = typeof r['title'] === 'string' ? r['title'].trim() : '';\n const description = typeof r['description'] === 'string' ? r['description'].trim() : '';\n if (!title || !description) continue;\n const type = TASK_TYPES.has(r['type'] as TaskType) ? (r['type'] as TaskType) : undefined;\n const priority = PRIORITIES.has(r['priority'] as TaskPriority)\n ? (r['priority'] as TaskPriority)\n : undefined;\n const successCriterion =\n options.acceptSuccessCriterion && typeof r['successCriterion'] === 'string'\n ? r['successCriterion'].trim() || undefined\n : undefined;\n specs.push({ title, description, type, priority, successCriterion });\n if (specs.length >= max) break;\n }\n\n // A split must yield at least `min` genuinely smaller pieces \u2014 otherwise it's\n // not a decomposition.\n return specs.length >= min ? specs : [];\n}\n\nexport interface PlanningDecomposerOptions {\n /** Runs one self-contained, isolated LLM turn and resolves its final text. */\n run: (prompt: string) => Promise<string>;\n /** Minimum well-formed sub-tasks required to accept a split. Default 2. */\n minSubtasks?: number;\n /** Maximum sub-tasks kept (excess is dropped). Default 5. */\n maxSubtasks?: number;\n}\n\nexport type PlanningDecomposer = (info: {\n title: string;\n description: string;\n reasons: string[];\n}) => Promise<SddSubtaskSpec[]>;\n\n/**\n * Planning-time LLM decomposer: splits a task judged `needs_decomposition` by\n * the atomicity engine BEFORE execution starts, requesting one verifiable\n * success criterion per sub-task. Same injected isolated-turn pattern and the\n * same safe degrade ([]) as the reactive `makeLlmSubtaskGenerator`, which is\n * intentionally untouched.\n */\nexport function makePlanningDecomposer(opts: PlanningDecomposerOptions): PlanningDecomposer {\n const min = Math.max(2, opts.minSubtasks ?? 2);\n const max = Math.max(min, opts.maxSubtasks ?? 5);\n\n return async function decompose(info): Promise<SddSubtaskSpec[]> {\n let text: string;\n try {\n text = await opts.run(\n renderInstructionTemplate(readBundledInstructionText('sdd/decompose-task-planning.md'), {\n minSubtasks: String(min),\n maxSubtasks: String(max),\n title: info.title,\n description: info.description,\n reasons: info.reasons.length\n ? info.reasons.map((r) => `- ${r}`).join('\\n')\n : '- (unspecified)',\n }),\n );\n } catch {\n return [];\n }\n return parseSubtaskSpecs(text, min, max, { acceptSuccessCriterion: true });\n };\n}\n\n/**\n * Build a `SddSupervisorOptions.generateSubtasks` closure backed by an LLM turn.\n * Returns [] on any failure (parse error, too few valid items, runner throw), so\n * the supervisor safely degrades a `split` verdict into a retry.\n */\nexport function makeLlmSubtaskGenerator(opts: SubtaskGeneratorOptions) {\n const min = Math.max(2, opts.minSubtasks ?? 2);\n const max = Math.max(min, opts.maxSubtasks ?? 4);\n\n return async function generateSubtasks(info: {\n task: TaskNode;\n error: string;\n }): Promise<SddSubtaskSpec[]> {\n let text: string;\n try {\n text = await opts.run(buildPrompt(info.task, info.error, min, max));\n } catch {\n return [];\n }\n return parseSubtaskSpecs(text, min, max);\n };\n}\n", "/**\n * Planning-time proactive decomposition pass.\n *\n * Walks the pending leaves of a generated TaskGraph, scores each with the\n * deterministic atomicity rule set, and for every `needs_decomposition`\n * verdict asks the injected LLM decomposer for sub-tasks:\n * - mode 'auto': applies the split immediately via splitGraphNode (the same\n * code path run-time splits use);\n * - mode 'propose': returns proposals for approval (WebUI surfaces them).\n *\n * Bounded and non-recursive: children created here are never re-decomposed in\n * the same pass, and `maxDecompositions` caps LLM spend per graph.\n */\n\nimport {\n assessAtomicity,\n type AtomicityRuleSetConfig,\n type KanbanAtomicityAssessment,\n} from '@wrongstack/kanban';\nimport type { TaskTracker } from '@wrongstack/core/tasking';\nimport type { TaskNode } from '@wrongstack/core/types';\nimport type { PlanningDecomposer } from './decompose-task.js';\nimport { splitGraphNode } from './graph-split.js';\nimport type { SddSubtaskSpec } from './sdd-parallel-run.js';\nimport { extractVerificationCommand } from './task-generator.js';\n\nexport interface DecompositionProposal {\n nodeId: string;\n title: string;\n reasons: string[];\n subtasks: SddSubtaskSpec[];\n}\n\nexport interface PlanDecomposeOptions {\n tracker: TaskTracker;\n decompose: PlanningDecomposer;\n config?: AtomicityRuleSetConfig | undefined;\n /** 'auto' applies splits immediately; 'propose' returns them for approval. */\n mode: 'auto' | 'propose';\n /** LLM budget guard: max decompositions per graph. Default 10. */\n maxDecompositions?: number | undefined;\n}\n\nexport interface PlanDecomposeResult {\n /** Node ids that were split (auto mode). */\n applied: Array<{ nodeId: string; subtaskIds: string[] }>;\n /** Proposals awaiting approval (propose mode). */\n proposals: DecompositionProposal[];\n /** Node ids assessed as needing decomposition (superset of applied+proposals). */\n flagged: string[];\n}\n\n/** Count \"- ...\" bullets under an \"**Acceptance Criteria:**\" block. */\nfunction countAcceptanceCriteria(description: string): number {\n const marker = description.indexOf('**Acceptance Criteria:**');\n if (marker === -1) return 0;\n const tail = description.slice(marker);\n return (tail.match(/^\\s*-\\s+\\S/gm) ?? []).length;\n}\n\nexport function assessTaskNodeAtomicity(\n tracker: TaskTracker,\n node: TaskNode,\n config?: AtomicityRuleSetConfig,\n): KanbanAtomicityAssessment {\n const criteriaCount = countAcceptanceCriteria(node.description ?? '');\n const verificationCommand =\n (node.metadata?.['verificationCommand'] as string | undefined) ??\n extractVerificationCommand([node.description ?? '']);\n return assessAtomicity(\n {\n title: node.title,\n description: node.description,\n estimatedHours: node.estimateHours,\n dependencyCount: tracker.getBlockers(node.id).length,\n successCriteriaCount: criteriaCount,\n hasVerifiableOutput: Boolean(verificationCommand),\n childCount: tracker.getAllNodes().filter((n) => n.parentId === node.id).length,\n },\n config,\n );\n}\n\nexport async function decomposeNonAtomicTasks(\n opts: PlanDecomposeOptions,\n): Promise<PlanDecomposeResult> {\n const maxDecompositions = Math.max(1, opts.maxDecompositions ?? 10);\n const result: PlanDecomposeResult = { applied: [], proposals: [], flagged: [] };\n\n const nodes = opts.tracker.getAllNodes();\n const childCounts = new Map<string, number>();\n for (const node of nodes) {\n if (node.parentId) childCounts.set(node.parentId, (childCounts.get(node.parentId) ?? 0) + 1);\n }\n // Snapshot the candidate list before any split so children created by this\n // pass are never re-decomposed (no recursion).\n const candidates = nodes.filter(\n (node) => node.status === 'pending' && !childCounts.get(node.id),\n );\n\n let spent = 0;\n for (const node of candidates) {\n if (spent >= maxDecompositions) break;\n const assessment = assessTaskNodeAtomicity(opts.tracker, node, opts.config);\n // Stamp the assessment so downstream surfaces (board projector, mirror)\n // can show why a task was or wasn't split.\n opts.tracker.patchMetadata(node.id, {\n atomicity: {\n verdict: assessment.verdict,\n score: assessment.score,\n reasons: assessment.criteria.filter((c) => c.score < 1).map((c) => c.reason),\n },\n });\n if (assessment.verdict !== 'needs_decomposition') continue;\n result.flagged.push(node.id);\n spent += 1;\n\n const reasons = assessment.criteria.filter((c) => c.score < 1).map((c) => c.reason);\n const subtasks = await opts.decompose({\n title: node.title,\n description: node.description ?? '',\n reasons,\n });\n if (!subtasks.length) continue;\n\n if (opts.mode === 'auto') {\n const subtaskIds = splitGraphNode(opts.tracker, node.id, subtasks);\n if (subtaskIds.length) result.applied.push({ nodeId: node.id, subtaskIds });\n } else {\n result.proposals.push({ nodeId: node.id, title: node.title, reasons, subtasks });\n }\n }\n return result;\n}\n", "// makePreferSideConflictResolver \u2014 a conservative, opt-in merge-conflict resolver\n// for an SDD parallel run's worktree integration.\n//\n// Wired as `SddParallelRunOptions.conflictResolver`, it is consulted when a\n// completed task's worktree can't squash-merge cleanly. It rewrites each\n// conflicted file by keeping ONE side of every conflict hunk:\n// \u2022 'incoming' \u2014 the worktree's changes (theirs); good for generated artefacts\n// a worker is expected to regenerate wholesale.\n// \u2022 'base' \u2014 the already-merged base (ours); discards the worktree's edit.\n// The WorktreeManager re-stages and REJECTS the resolution if any conflict marker\n// survives (`git diff --cached --check`), so a malformed rewrite degrades safely\n// to the conservative retry-on-fresh-base path rather than corrupting the base.\n//\n// This is intentionally blunt (no semantic merge). It is OFF by default \u2014 callers\n// opt in explicitly \u2014 because auto-picking a side can silently drop work.\n\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { isAbsolute, join } from 'node:path';\nimport type { TaskNode } from '@wrongstack/core/types';\nimport { readBundledInstructionText, renderInstructionTemplate } from '@wrongstack/core/utils';\n\nexport type ConflictSide = 'incoming' | 'base';\n\nexport interface ConflictFileIO {\n read(path: string): Promise<string>;\n write(path: string, content: string): Promise<void>;\n}\n\nconst defaultFileIO: ConflictFileIO = {\n read: (path) => readFile(path, 'utf8'),\n write: async (path, content) => {\n await writeFile(path, content, 'utf8');\n },\n};\n\nconst START = '<<<<<<<';\nconst BASE = '|||||||';\nconst SEP = '=======';\nconst END = '>>>>>>>';\n\n/**\n * Resolve every standard git conflict hunk in `text` by keeping `side`. Handles\n * both 2-way (`<<<<<<< / ======= / >>>>>>>`) and diff3 (`||||||| base`) markers.\n * Returns the rewritten text (markers removed).\n */\nexport function resolveConflictText(text: string, side: ConflictSide): string {\n const out: string[] = [];\n // 'normal' | 'ours' | 'base' | 'theirs'\n let state: 'normal' | 'ours' | 'base' | 'theirs' = 'normal';\n for (const line of text.split('\\n')) {\n const marker = line.slice(0, 7);\n if (state === 'normal' && marker === START) {\n state = 'ours';\n continue;\n }\n if (state !== 'normal' && marker === BASE) {\n state = 'base';\n continue;\n }\n if (state !== 'normal' && marker === SEP) {\n state = 'theirs';\n continue;\n }\n if (state !== 'normal' && marker === END) {\n state = 'normal';\n continue;\n }\n if (state === 'normal') out.push(line);\n else if (state === 'ours' && side === 'base') out.push(line);\n else if (state === 'theirs' && side === 'incoming') out.push(line);\n // 'base' section + the non-selected side are dropped.\n }\n return out.join('\\n');\n}\n\n/** True when `text` still contains a git conflict marker line. */\nexport function hasConflictMarkers(text: string): boolean {\n return text.split('\\n').some((l) => {\n const m = l.slice(0, 7);\n return m === START || m === SEP || m === END || m === BASE;\n });\n}\n\n/**\n * Build a `conflictResolver` that keeps `side` of every hunk in each conflicted\n * file. Returns false (abort \u2192 conservative fail) if any file can't be read,\n * written, or still has markers after the rewrite.\n */\nexport function makePreferSideConflictResolver(\n side: ConflictSide,\n io: ConflictFileIO = defaultFileIO,\n) {\n return async function conflictResolver(info: {\n task: TaskNode;\n conflictFiles: string[];\n cwd: string;\n }): Promise<boolean> {\n if (info.conflictFiles.length === 0) return false;\n for (const rel of info.conflictFiles) {\n const abs = isAbsolute(rel) ? rel : join(info.cwd, rel);\n let content: string;\n try {\n content = await io.read(abs);\n } catch {\n return false; // can't read \u2192 don't risk a partial resolution\n }\n const resolved = resolveConflictText(content, side);\n if (hasConflictMarkers(resolved)) return false; // refuse a half-resolved file\n try {\n await io.write(abs, resolved);\n } catch {\n return false;\n }\n }\n return true;\n };\n}\n\nexport interface LlmConflictResolverOptions {\n /** Runs one self-contained, isolated LLM turn and resolves its final text. */\n run: (prompt: string) => Promise<string>;\n /**\n * Reject a resolution that shrinks the file below this fraction of its original\n * non-marker line count \u2014 a crude guard against the model dropping content.\n * Default 0.5.\n */\n minRetainedFraction?: number;\n /** Optional filesystem seam for deterministic hosts and failure tests. */\n io?: ConflictFileIO;\n}\n\n/** Strip a single surrounding ``` code fence (any/no language) if present. */\nfunction unfence(text: string): string {\n const m = text.match(/^[\\s\\S]*?```[^\\n]*\\n([\\s\\S]*?)\\n```[\\s\\S]*$/);\n return m?.[1] !== undefined ? m[1] : text.trim();\n}\n\n/** Original line count ignoring conflict-marker lines (the resolution baseline). */\nfunction nonMarkerLineCount(text: string): number {\n return text.split('\\n').filter((l) => {\n const m = l.slice(0, 7);\n return m !== START && m !== SEP && m !== END && m !== BASE;\n }).length;\n}\n\n/**\n * Build an LLM-backed `conflictResolver`: for each conflicted file it asks the\n * model (via one isolated `run` turn) to produce the fully resolved file and\n * writes it back. Heavily guarded \u2014 returns false (\u2192 conservative abort/retry)\n * if the model leaves a marker, returns junk, or drops too much content. The\n * WorktreeManager STILL rejects any surviving marker, and (when a `verifyTask`\n * is configured) the run re-verifies the integrated base and reverts a\n * regression \u2014 so a bad LLM merge can never silently stick. OFF by default.\n */\nexport function makeLlmConflictResolver(opts: LlmConflictResolverOptions) {\n const minFraction = opts.minRetainedFraction ?? 0.5;\n const io = opts.io ?? defaultFileIO;\n\n return async function conflictResolver(info: {\n task: TaskNode;\n conflictFiles: string[];\n cwd: string;\n }): Promise<boolean> {\n if (info.conflictFiles.length === 0) return false;\n for (const rel of info.conflictFiles) {\n const abs = isAbsolute(rel) ? rel : join(info.cwd, rel);\n let content: string;\n try {\n content = await io.read(abs);\n } catch {\n return false;\n }\n if (!hasConflictMarkers(content)) continue; // already clean \u2014 nothing to do\n\n const prompt = renderInstructionTemplate(\n readBundledInstructionText('sdd/merge-conflict-resolver.md'),\n {\n file: rel,\n content,\n },\n );\n\n let out: string;\n try {\n out = await opts.run(prompt);\n } catch {\n return false;\n }\n const resolved = unfence(out ?? '');\n if (!resolved.trim() || hasConflictMarkers(resolved)) return false;\n // Content-drop guard: a resolution far smaller than the original almost\n // certainly lost real work \u2014 abort rather than write it.\n if (resolved.split('\\n').length < Math.floor(nonMarkerLineCount(content) * minFraction)) {\n return false;\n }\n try {\n await io.write(abs, resolved);\n } catch {\n return false;\n }\n }\n return true;\n };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["TaskTracker", "DefaultTaskStore", "fsp", "path", "atomicWrite", "ensureDir", "fsp", "path", "atomicWrite", "ensureDir", "stat", "entry", "TaskTracker", "ERROR_CODES", "SddError", "expectDefined", "expectDefined", "fsp", "path", "atomicWrite", "SddError", "ERROR_CODES", "TaskTracker", "tracker", "randomUUID", "randomUUID", "expectDefined", "ERROR_CODES", "SddError", "randomUUID", "fsp", "path", "toErrorMessage", "kanbanWorkflowId", "writeKanbanWorkflowState", "writeKanbanWorkflowState", "kanbanWorkflowId", "toErrorMessage", "r", "fsp", "deleteKanbanWorkflowState", "kanbanWorkflowId", "readKanbanWorkflowState", "writeKanbanWorkflowState", "kanbanWorkflowId", "readKanbanWorkflowState", "writeKanbanWorkflowState", "deleteKanbanWorkflowState", "fsp", "path", "computeTaskProgress", "expectDefined", "expectDefined", "path", "TASK_TYPES", "assessAtomicity", "assessAtomicity", "readFile", "join", "readBundledInstructionText", "renderInstructionTemplate", "path"]
|
|
7
|
-
}
|