@stackmemoryai/stackmemory 1.12.0 → 1.14.0

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.
Files changed (162) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +3 -1
  3. package/bin/claude-sm +16 -1
  4. package/bin/claude-smd +16 -1
  5. package/bin/codex-smd +16 -1
  6. package/bin/gemini-sm +16 -1
  7. package/bin/hermes-sm +21 -0
  8. package/bin/hermes-smd +21 -0
  9. package/bin/opencode-sm +16 -1
  10. package/dist/src/cli/codex-sm.js +51 -11
  11. package/dist/src/cli/commands/brain.js +206 -0
  12. package/dist/src/cli/commands/company-os.js +184 -0
  13. package/dist/src/cli/commands/context.js +5 -0
  14. package/dist/src/cli/commands/operator.js +127 -0
  15. package/dist/src/cli/commands/orchestrate.js +2 -0
  16. package/dist/src/cli/commands/orchestrator.js +3 -2
  17. package/dist/src/cli/commands/patterns.js +254 -0
  18. package/dist/src/cli/commands/portal.js +161 -0
  19. package/dist/src/cli/commands/scaffold.js +92 -0
  20. package/dist/src/cli/commands/setup.js +1 -4
  21. package/dist/src/cli/commands/sync.js +253 -0
  22. package/dist/src/cli/commands/tasks.js +130 -1
  23. package/dist/src/cli/commands/vision.js +221 -0
  24. package/dist/src/cli/hermes-sm.js +224 -0
  25. package/dist/src/cli/index.js +15 -10
  26. package/dist/src/cli/utils/real-cli-bin.js +72 -0
  27. package/dist/src/core/brain/brain-store.js +187 -0
  28. package/dist/src/core/brain/brain-sync.js +193 -0
  29. package/dist/src/core/brain/index.js +78 -0
  30. package/dist/src/core/brain/types.js +10 -0
  31. package/dist/src/core/cache/token-estimator.js +24 -1
  32. package/dist/src/core/config/feature-flags.js +2 -6
  33. package/dist/src/core/context/frame-database.js +44 -0
  34. package/dist/src/core/context/recursive-context-manager.js +1 -1
  35. package/dist/src/core/context/rehydration.js +2 -1
  36. package/dist/src/core/database/sqlite-adapter.js +14 -1
  37. package/dist/src/core/models/model-router.js +33 -1
  38. package/dist/src/core/models/provider-pricing.js +58 -4
  39. package/dist/src/core/patterns/index.js +22 -0
  40. package/dist/src/core/patterns/pattern-applier.js +39 -0
  41. package/dist/src/core/patterns/pattern-observer.js +157 -0
  42. package/dist/src/core/patterns/pattern-store.js +259 -0
  43. package/dist/src/core/patterns/types.js +19 -0
  44. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  45. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  46. package/dist/src/core/skill-packs/types.js +14 -1
  47. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  48. package/dist/src/core/storage/cloud-sync.js +574 -0
  49. package/dist/src/core/storage/two-tier-storage.js +5 -1
  50. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  51. package/dist/src/core/tasks/md-task-parser.js +138 -0
  52. package/dist/src/core/vision/index.js +27 -0
  53. package/dist/src/core/vision/signals.js +79 -0
  54. package/dist/src/core/vision/types.js +22 -0
  55. package/dist/src/core/vision/vision-file.js +146 -0
  56. package/dist/src/core/vision/vision-loop.js +220 -0
  57. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  58. package/dist/src/daemon/daemon-config.js +45 -0
  59. package/dist/src/daemon/services/desire-path-service.js +566 -0
  60. package/dist/src/daemon/services/research-stream-service.js +320 -0
  61. package/dist/src/daemon/services/telemetry-service.js +192 -0
  62. package/dist/src/daemon/unified-daemon.js +28 -1
  63. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  64. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  65. package/dist/src/features/operator/adapter-factory.js +62 -0
  66. package/dist/src/features/operator/browser-adapter.js +109 -0
  67. package/dist/src/features/operator/desktop-adapter.js +125 -0
  68. package/dist/src/features/operator/index.js +39 -0
  69. package/dist/src/features/operator/llm-decision.js +137 -0
  70. package/dist/src/features/operator/operator-logger.js +92 -0
  71. package/dist/src/features/operator/overnight-runner.js +327 -0
  72. package/dist/src/features/operator/screen-adapter.js +91 -0
  73. package/dist/src/features/operator/session-manager.js +127 -0
  74. package/dist/src/features/operator/state-machine.js +227 -0
  75. package/dist/src/features/operator/task-queue.js +81 -0
  76. package/dist/src/features/portal/index.js +26 -0
  77. package/dist/src/features/portal/server.js +240 -0
  78. package/dist/src/features/portal/types.js +14 -0
  79. package/dist/src/features/portal/ui.js +195 -0
  80. package/dist/src/features/tasks/task-aware-context.js +2 -1
  81. package/dist/src/features/tui/simple-monitor.js +0 -23
  82. package/dist/src/features/tui/swarm-monitor.js +8 -66
  83. package/dist/src/{integrations/diffmem/index.js → features/web/client/hooks/use-socket.js} +6 -5
  84. package/dist/src/features/web/client/lib/utils.js +12 -0
  85. package/dist/src/features/web/client/stores/session-store.js +12 -0
  86. package/dist/src/features/web/server/gcp-billing.js +76 -0
  87. package/dist/src/features/web/server/index.js +10 -0
  88. package/dist/src/features/web/server/spend-calculator.js +228 -0
  89. package/dist/src/hooks/schemas.js +4 -1
  90. package/dist/src/integrations/anthropic/client.js +3 -2
  91. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  92. package/dist/src/integrations/claude-code/subagent-client.js +218 -11
  93. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  94. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  95. package/dist/src/integrations/linear/webhook-server.js +18 -22
  96. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  97. package/dist/src/integrations/mcp/handlers/index.js +27 -52
  98. package/dist/src/integrations/mcp/server.js +122 -335
  99. package/dist/src/integrations/mcp/tool-alias-registry.js +0 -73
  100. package/dist/src/integrations/mcp/tool-definitions.js +111 -510
  101. package/dist/src/mcp/stackmemory-mcp-server.js +404 -379
  102. package/dist/src/orchestrators/multimodal/determinism.js +2 -1
  103. package/dist/src/orchestrators/multimodal/harness.js +2 -1
  104. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  105. package/dist/src/utils/process-cleanup.js +1 -7
  106. package/docs/README.md +42 -0
  107. package/docs/guides/README_INSTALL.md +208 -0
  108. package/package.json +18 -9
  109. package/scripts/claude-code-wrapper.sh +11 -0
  110. package/scripts/claude-sm-setup.sh +12 -1
  111. package/scripts/codex-wrapper.sh +11 -0
  112. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  113. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  114. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  115. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  116. package/scripts/hooks/cleanup-shell.sh +12 -1
  117. package/scripts/hooks/task-complete.sh +12 -1
  118. package/scripts/install-code-execution-hooks.sh +12 -1
  119. package/scripts/install-sweep-hook.sh +12 -0
  120. package/scripts/install.sh +11 -0
  121. package/scripts/opencode-wrapper.sh +11 -0
  122. package/scripts/portal/cloud-init.yaml +69 -0
  123. package/scripts/portal/setup.sh +69 -0
  124. package/scripts/portal/stackmemory-portal.service +34 -0
  125. package/scripts/setup-claude-integration.sh +12 -1
  126. package/scripts/smoke-init-db.sh +23 -0
  127. package/scripts/stackmemory-daemon.sh +11 -0
  128. package/scripts/verify-dist.cjs +11 -4
  129. package/dist/src/cli/commands/ralph.js +0 -1053
  130. package/dist/src/hooks/diffmem-hooks.js +0 -376
  131. package/dist/src/integrations/diffmem/client.js +0 -208
  132. package/dist/src/integrations/diffmem/config.js +0 -14
  133. package/dist/src/integrations/greptile/client.js +0 -101
  134. package/dist/src/integrations/greptile/config.js +0 -14
  135. package/dist/src/integrations/greptile/index.js +0 -11
  136. package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +0 -188
  137. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  138. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  139. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  140. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  141. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  142. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -354
  143. package/dist/src/integrations/ralph/index.js +0 -17
  144. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -416
  145. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  146. package/dist/src/integrations/ralph/loopmax.js +0 -488
  147. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  148. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  149. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  150. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  151. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  152. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  153. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  154. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  155. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  156. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  157. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1005
  158. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  159. package/scripts/ralph-loop-implementation.js +0 -404
  160. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  161. /package/dist/src/{integrations/greptile → features/operator}/types.js +0 -0
  162. /package/dist/src/{integrations/ralph/types.js → features/web/client/next-env.d.js} +0 -0
@@ -23,7 +23,12 @@ import {
23
23
  } from "fs";
24
24
  import { homedir } from "os";
25
25
  import { compactPlan } from "../../orchestrators/multimodal/utils.js";
26
- import { filterPending } from "./pending-utils.js";
26
+ import {
27
+ parseMasterTasks,
28
+ getNextTask,
29
+ addTaskToFile,
30
+ updateTaskInFile
31
+ } from "../../core/tasks/md-task-parser.js";
27
32
  import { join, dirname } from "path";
28
33
  import { execSync } from "child_process";
29
34
  import { FrameManager } from "../../core/context/index.js";
@@ -35,9 +40,6 @@ import { BrowserMCPIntegration } from "../../features/browser/browser-mcp.js";
35
40
  import { TraceDetector } from "../../core/trace/trace-detector.js";
36
41
  import { LLMContextRetrieval } from "../../core/retrieval/index.js";
37
42
  import { DiscoveryHandlers } from "./handlers/discovery-handlers.js";
38
- import { DiffMemHandlers } from "./handlers/diffmem-handlers.js";
39
- import { GreptileHandlers } from "./handlers/greptile-handlers.js";
40
- import { CrossSearchHandlers } from "./handlers/cross-search-handlers.js";
41
43
  import {
42
44
  generateChronologicalDigest
43
45
  } from "../../core/digest/chronological-digest.js";
@@ -79,13 +81,6 @@ const CACHEABLE_TOOLS = /* @__PURE__ */ new Set([
79
81
  "sm_cross_search",
80
82
  "sm_cross_discover",
81
83
  "sm_cross_list",
82
- "diffmem_get_user_context",
83
- "diffmem_search",
84
- "diffmem_status",
85
- "greptile_list_prs",
86
- "greptile_pr_details",
87
- "greptile_pr_comments",
88
- "greptile_status",
89
84
  "linear_get_tasks",
90
85
  "linear_status",
91
86
  "provenant_search",
@@ -106,11 +101,7 @@ class LocalStackMemoryMCP {
106
101
  traceDetector;
107
102
  contextRetrieval;
108
103
  discoveryHandlers;
109
- diffMemHandlers;
110
- greptileHandlers;
111
104
  providerHandlers = null;
112
- crossSearchHandlers;
113
- pendingPlans = /* @__PURE__ */ new Map();
114
105
  contentCache;
115
106
  traceEventStore;
116
107
  sessionId;
@@ -190,10 +181,6 @@ class LocalStackMemoryMCP {
190
181
  db: this.db,
191
182
  projectRoot: this.projectRoot
192
183
  });
193
- this.diffMemHandlers = new DiffMemHandlers();
194
- this.greptileHandlers = new GreptileHandlers();
195
- this.crossSearchHandlers = new CrossSearchHandlers({});
196
- this.initProviderHandlers();
197
184
  this.setupHandlers();
198
185
  this.loadInitialContext();
199
186
  this.loadPendingPlans();
@@ -416,16 +403,6 @@ ${summary}...`, 0.8);
416
403
  this.contexts.set(ctx.id, ctx);
417
404
  });
418
405
  }
419
- async initProviderHandlers() {
420
- if (!isFeatureEnabled("multiProvider")) return;
421
- try {
422
- const { ProviderHandlers } = await import("./handlers/provider-handlers.js");
423
- this.providerHandlers = new ProviderHandlers();
424
- logger.info("Provider handlers initialized (multiProvider enabled)");
425
- } catch (error) {
426
- logger.warn("Failed to initialize provider handlers", { error });
427
- }
428
- }
429
406
  setupHandlers() {
430
407
  this.server.setRequestHandler(
431
408
  z.object({
@@ -454,7 +431,6 @@ ${summary}...`, 0.8);
454
431
  // Planning tools (only when ANTHROPIC_API_KEY is set)
455
432
  ...process.env.ANTHROPIC_API_KEY ? [
456
433
  {
457
- name: "plan_gate",
458
434
  description: "Phase 1: Generate a plan and return an approvalId for later execution",
459
435
  inputSchema: {
460
436
  type: "object",
@@ -472,14 +448,12 @@ ${summary}...`, 0.8);
472
448
  }
473
449
  },
474
450
  {
475
- name: "approve_plan",
476
451
  description: "Phase 2: Execute a previously generated plan by approvalId",
477
452
  inputSchema: {
478
453
  type: "object",
479
454
  properties: {
480
455
  approvalId: {
481
- type: "string",
482
- description: "Id from plan_gate"
456
+ type: "string"
483
457
  },
484
458
  implementer: {
485
459
  type: "string",
@@ -558,15 +532,13 @@ ${summary}...`, 0.8);
558
532
  type: "object",
559
533
  properties: {
560
534
  approvalId: {
561
- type: "string",
562
- description: "Approval id from plan_gate"
535
+ type: "string"
563
536
  }
564
537
  },
565
538
  required: ["approvalId"]
566
539
  }
567
540
  },
568
541
  {
569
- name: "plan_only",
570
542
  description: "Generate an implementation plan (Claude) and return JSON only",
571
543
  inputSchema: {
572
544
  type: "object",
@@ -584,7 +556,6 @@ ${summary}...`, 0.8);
584
556
  }
585
557
  },
586
558
  {
587
- name: "call_codex",
588
559
  description: "Invoke Codex via codex-sm with a prompt and args; dry-run by default",
589
560
  inputSchema: {
590
561
  type: "object",
@@ -608,7 +579,6 @@ ${summary}...`, 0.8);
608
579
  }
609
580
  },
610
581
  {
611
- name: "call_claude",
612
582
  description: "Invoke Claude with a prompt (Anthropic SDK)",
613
583
  inputSchema: {
614
584
  type: "object",
@@ -1094,10 +1064,8 @@ ${summary}...`, 0.8);
1094
1064
  required: ["query"]
1095
1065
  }
1096
1066
  },
1097
- // DiffMem tools (only when DIFFMEM_ENDPOINT or DIFFMEM_ENABLED is set)
1098
1067
  ...process.env.DIFFMEM_ENDPOINT || process.env.DIFFMEM_ENABLED === "true" ? this.diffMemHandlers.getToolDefinitions() : [],
1099
1068
  // Greptile tools (only active when GREPTILE_API_KEY is set)
1100
- ...process.env.GREPTILE_API_KEY ? this.greptileHandlers.getToolDefinitions() : [],
1101
1069
  // Provider tools (only active when STACKMEMORY_MULTI_PROVIDER=true)
1102
1070
  ...isFeatureEnabled("multiProvider") ? [
1103
1071
  {
@@ -1483,20 +1451,10 @@ ${summary}...`, 0.8);
1483
1451
  case "compress_old_traces":
1484
1452
  result = await this.handleCompressOldTraces(args);
1485
1453
  break;
1486
- case "plan_only":
1487
- result = await this.handlePlanOnly(args);
1488
1454
  break;
1489
- case "call_codex":
1490
- result = await this.handleCallCodex(args);
1491
1455
  break;
1492
- case "call_claude":
1493
- result = await this.handleCallClaude(args);
1494
1456
  break;
1495
- case "plan_gate":
1496
- result = await this.handlePlanGate(args);
1497
1457
  break;
1498
- case "approve_plan":
1499
- result = await this.handleApprovePlan(args);
1500
1458
  break;
1501
1459
  case "pending_list":
1502
1460
  result = await this.handlePendingList();
@@ -1526,41 +1484,15 @@ ${summary}...`, 0.8);
1526
1484
  case "sm_search":
1527
1485
  result = await this.handleSmSearch(args);
1528
1486
  break;
1529
- // DiffMem handlers
1530
- case "diffmem_get_user_context":
1531
1487
  result = await this.diffMemHandlers.handleGetUserContext(args);
1532
1488
  break;
1533
- case "diffmem_store_learning":
1534
1489
  result = await this.diffMemHandlers.handleStoreLearning(args);
1535
1490
  break;
1536
- case "diffmem_search":
1537
1491
  result = await this.diffMemHandlers.handleSearch(args);
1538
1492
  break;
1539
- case "diffmem_status":
1540
1493
  result = await this.diffMemHandlers.handleStatus();
1541
1494
  break;
1542
1495
  // Greptile handlers
1543
- case "greptile_pr_comments":
1544
- result = await this.greptileHandlers.handleListPRComments(args);
1545
- break;
1546
- case "greptile_pr_details":
1547
- result = await this.greptileHandlers.handleGetMergeRequest(args);
1548
- break;
1549
- case "greptile_list_prs":
1550
- result = await this.greptileHandlers.handleListPullRequests(args);
1551
- break;
1552
- case "greptile_trigger_review":
1553
- result = await this.greptileHandlers.handleTriggerCodeReview(args);
1554
- break;
1555
- case "greptile_search_patterns":
1556
- result = await this.greptileHandlers.handleSearchPatterns(args);
1557
- break;
1558
- case "greptile_create_pattern":
1559
- result = await this.greptileHandlers.handleCreatePattern(args);
1560
- break;
1561
- case "greptile_status":
1562
- result = await this.greptileHandlers.handleStatus();
1563
- break;
1564
1496
  case "sm_edit":
1565
1497
  result = await this.handleSmEdit(args);
1566
1498
  break;
@@ -1651,6 +1583,15 @@ ${summary}...`, 0.8);
1651
1583
  case "trace_event_annotate":
1652
1584
  result = this.handleTraceEventAnnotate(args);
1653
1585
  break;
1586
+ case "get_next_master_task":
1587
+ result = this.handleGetNextMasterTask(args);
1588
+ break;
1589
+ case "update_master_task":
1590
+ result = this.handleUpdateMasterTask(args);
1591
+ break;
1592
+ case "create_master_task":
1593
+ result = this.handleCreateMasterTask(args);
1594
+ break;
1654
1595
  default:
1655
1596
  throw new Error(`Unknown tool: ${name}`);
1656
1597
  }
@@ -1795,60 +1736,6 @@ ${summary}...`, 0.8);
1795
1736
  isError: false
1796
1737
  };
1797
1738
  }
1798
- async handlePlanOnly(args) {
1799
- const { runPlanOnly } = await import("../../orchestrators/multimodal/harness.js");
1800
- const task = String(args.task || "Plan change");
1801
- const plannerModel = args.plannerModel || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL;
1802
- const plan = await runPlanOnly(
1803
- { task, repoPath: this.projectRoot },
1804
- { plannerModel }
1805
- );
1806
- return {
1807
- content: [
1808
- {
1809
- type: "text",
1810
- text: JSON.stringify({ ok: true, plan })
1811
- }
1812
- ],
1813
- isError: false
1814
- };
1815
- }
1816
- async handleCallCodex(args) {
1817
- const { callCodexCLI } = await import("../../orchestrators/multimodal/providers.js");
1818
- const prompt = String(args.prompt || "");
1819
- const extraArgs = Array.isArray(args.args) ? args.args : [];
1820
- const execute = Boolean(args.execute);
1821
- const resp = callCodexCLI(prompt, extraArgs, !execute);
1822
- return {
1823
- content: [
1824
- {
1825
- type: "text",
1826
- text: JSON.stringify({
1827
- ok: resp.ok,
1828
- command: resp.command,
1829
- output: resp.output
1830
- })
1831
- }
1832
- ],
1833
- isError: false
1834
- };
1835
- }
1836
- async handleCallClaude(args) {
1837
- const { callClaude } = await import("../../orchestrators/multimodal/providers.js");
1838
- const prompt = String(args.prompt || "");
1839
- const model = args.model || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL;
1840
- const system = args.system || "You are a precise assistant. Return plain text unless asked for JSON.";
1841
- const text = await callClaude(prompt, { model, system });
1842
- return {
1843
- content: [
1844
- {
1845
- type: "text",
1846
- text: JSON.stringify({ ok: true, text })
1847
- }
1848
- ],
1849
- isError: false
1850
- };
1851
- }
1852
1739
  // Pending plan persistence (best-effort)
1853
1740
  getPendingStoreDir() {
1854
1741
  return join(this.projectRoot, ".stackmemory", "build");
@@ -1872,7 +1759,6 @@ ${summary}...`, 0.8);
1872
1759
  }
1873
1760
  const data = JSON.parse(readFileSync(sourceFile, "utf-8"));
1874
1761
  if (data && typeof data === "object") {
1875
- this.pendingPlans = new Map(Object.entries(data));
1876
1762
  if (sourceFile !== file) this.savePendingPlans();
1877
1763
  }
1878
1764
  } catch {
@@ -1883,214 +1769,11 @@ ${summary}...`, 0.8);
1883
1769
  const dir = this.getPendingStoreDir();
1884
1770
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
1885
1771
  const file = this.getPendingStorePath();
1886
- const obj = Object.fromEntries(this.pendingPlans);
1887
1772
  writeFileSync(file, JSON.stringify(obj, null, 2));
1888
1773
  } catch {
1889
1774
  }
1890
1775
  }
1891
- async handlePlanGate(args) {
1892
- const { runPlanOnly } = await import("../../orchestrators/multimodal/harness.js");
1893
- const task = String(args.task || "Plan change");
1894
- const plannerModel = args.plannerModel || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL;
1895
- const plan = await runPlanOnly(
1896
- { task, repoPath: this.projectRoot },
1897
- { plannerModel }
1898
- );
1899
- const approvalId = `appr_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1900
- this.pendingPlans.set(approvalId, { task, plan, createdAt: Date.now() });
1901
- this.savePendingPlans();
1902
- const compact = Boolean(args.compact);
1903
- const planOut = compact ? compactPlan(plan) : plan;
1904
- return {
1905
- content: [
1906
- {
1907
- type: "text",
1908
- text: JSON.stringify({ ok: true, approvalId, plan: planOut })
1909
- }
1910
- ],
1911
- isError: false
1912
- };
1913
- }
1914
- async handleApprovePlan(args) {
1915
- const { runSpike } = await import("../../orchestrators/multimodal/harness.js");
1916
- const approvalId = String(args.approvalId || "");
1917
- const pending = this.pendingPlans.get(approvalId);
1918
- if (!pending) {
1919
- return {
1920
- content: [
1921
- {
1922
- type: "text",
1923
- text: JSON.stringify({ ok: false, error: "Invalid approvalId" })
1924
- }
1925
- ],
1926
- isError: false
1927
- };
1928
- }
1929
- const implementer = args.implementer || process.env["STACKMEMORY_MM_IMPLEMENTER"] || DEFAULT_IMPLEMENTER;
1930
- const maxIters = Number(
1931
- args.maxIters ?? process.env["STACKMEMORY_MM_MAX_ITERS"] ?? DEFAULT_MAX_ITERS
1932
- );
1933
- const recordFrame = args.recordFrame !== false;
1934
- const execute = args.execute !== false;
1935
- const verificationCommands = this.getVerificationCommands(args);
1936
- const result = await runSpike(
1937
- { task: pending.task, repoPath: this.projectRoot },
1938
- {
1939
- plannerModel: process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL,
1940
- reviewerModel: process.env["STACKMEMORY_MM_REVIEWER_MODEL"] || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL,
1941
- implementer: implementer === "claude" ? "claude" : "codex",
1942
- maxIters: isFinite(maxIters) ? Math.max(1, maxIters) : 2,
1943
- dryRun: !execute,
1944
- verificationCommands,
1945
- recordFrame
1946
- }
1947
- );
1948
- this.pendingPlans.delete(approvalId);
1949
- this.savePendingPlans();
1950
- const compact = Boolean(args.compact);
1951
- const payload = compact ? { ...result, plan: compactPlan(result.plan) } : result;
1952
- return {
1953
- content: [
1954
- {
1955
- type: "text",
1956
- text: JSON.stringify({ ok: true, approvalId, result: payload })
1957
- }
1958
- ],
1959
- isError: false
1960
- };
1961
- }
1962
- async handlePendingList(args) {
1963
- const schema = z.object({
1964
- taskContains: z.string().optional(),
1965
- olderThanMs: z.number().optional(),
1966
- newerThanMs: z.number().optional(),
1967
- sort: z.enum(["asc", "desc"]).optional(),
1968
- limit: z.number().int().positive().optional()
1969
- }).optional();
1970
- const parsed = schema.safeParse(args);
1971
- if (args && !parsed.success) {
1972
- return {
1973
- content: [
1974
- {
1975
- type: "text",
1976
- text: JSON.stringify({
1977
- ok: false,
1978
- error: "Invalid arguments",
1979
- details: parsed.error.issues
1980
- })
1981
- }
1982
- ],
1983
- isError: false
1984
- };
1985
- }
1986
- const a = parsed.success && parsed.data ? parsed.data : {};
1987
- const now = Date.now();
1988
- let items = Array.from(this.pendingPlans.entries()).map(
1989
- ([approvalId, data]) => ({
1990
- approvalId,
1991
- task: data?.task,
1992
- createdAt: Number(data?.createdAt || 0) || null
1993
- })
1994
- );
1995
- items = filterPending(items, a, now);
1996
- return {
1997
- content: [
1998
- { type: "text", text: JSON.stringify({ ok: true, pending: items }) }
1999
- ],
2000
- isError: false
2001
- };
2002
- }
2003
- async handlePendingClear(args) {
2004
- const removed = [];
2005
- const now = Date.now();
2006
- const all = Boolean(args?.all);
2007
- const approvalId = args?.approvalId ? String(args.approvalId) : void 0;
2008
- const olderThanMs = Number.isFinite(Number(args?.olderThanMs)) ? Number(args.olderThanMs) : void 0;
2009
- if (all) {
2010
- for (const id of this.pendingPlans.keys()) removed.push(id);
2011
- this.pendingPlans.clear();
2012
- this.savePendingPlans();
2013
- return {
2014
- content: [
2015
- { type: "text", text: JSON.stringify({ ok: true, removed }) }
2016
- ],
2017
- isError: false
2018
- };
2019
- }
2020
- if (approvalId) {
2021
- if (this.pendingPlans.has(approvalId)) {
2022
- this.pendingPlans.delete(approvalId);
2023
- removed.push(approvalId);
2024
- this.savePendingPlans();
2025
- }
2026
- return {
2027
- content: [
2028
- { type: "text", text: JSON.stringify({ ok: true, removed }) }
2029
- ],
2030
- isError: false
2031
- };
2032
- }
2033
- if (olderThanMs !== void 0 && olderThanMs >= 0) {
2034
- for (const [id, data] of this.pendingPlans.entries()) {
2035
- const ts = Number(data?.createdAt || 0);
2036
- if (ts && now - ts > olderThanMs) {
2037
- this.pendingPlans.delete(id);
2038
- removed.push(id);
2039
- }
2040
- }
2041
- this.savePendingPlans();
2042
- return {
2043
- content: [
2044
- { type: "text", text: JSON.stringify({ ok: true, removed }) }
2045
- ],
2046
- isError: false
2047
- };
2048
- }
2049
- return {
2050
- content: [
2051
- {
2052
- type: "text",
2053
- text: JSON.stringify({
2054
- ok: false,
2055
- error: "Specify approvalId, all=true, or olderThanMs"
2056
- })
2057
- }
2058
- ],
2059
- isError: false
2060
- };
2061
- }
2062
- async handlePendingShow(args) {
2063
- const approvalId = String(args?.approvalId || "");
2064
- const data = this.pendingPlans.get(approvalId);
2065
- if (!data) {
2066
- return {
2067
- content: [
2068
- {
2069
- type: "text",
2070
- text: JSON.stringify({ ok: false, error: "Invalid approvalId" })
2071
- }
2072
- ],
2073
- isError: false
2074
- };
2075
- }
2076
- const compact = Boolean(args.compact);
2077
- const planOut = compact ? compactPlan(data.plan) : data.plan;
2078
- return {
2079
- content: [
2080
- {
2081
- type: "text",
2082
- text: JSON.stringify({
2083
- ok: true,
2084
- approvalId,
2085
- task: data.task,
2086
- plan: planOut,
2087
- createdAt: data.createdAt || null
2088
- })
2089
- }
2090
- ],
2091
- isError: false
2092
- };
2093
- }
1776
+ // [REMOVED in v1.14] Conductor/multimodal handlers + pending plan handlers
2094
1777
  async handleGetContext(args) {
2095
1778
  const { query: query2 = "", limit = 10 } = args;
2096
1779
  const contexts = Array.from(this.contexts.values()).sort((a, b) => b.importance - a.importance).slice(0, limit);
@@ -3456,6 +3139,110 @@ ${catLines.join("\n")}`
3456
3139
  process.on("SIGTERM", printCacheSummary);
3457
3140
  process.on("exit", printCacheSummary);
3458
3141
  }
3142
+ // ── Master Task Handlers ───────────────────────────────────
3143
+ resolveMasterTasksPath() {
3144
+ const smPath = join(
3145
+ this.projectRoot,
3146
+ ".stackmemory",
3147
+ "tasks",
3148
+ "master-tasks.md"
3149
+ );
3150
+ if (existsSync(smPath)) return smPath;
3151
+ const rootPath = join(this.projectRoot, "master-tasks.md");
3152
+ if (existsSync(rootPath)) return rootPath;
3153
+ return null;
3154
+ }
3155
+ handleGetNextMasterTask(args) {
3156
+ const mdPath = this.resolveMasterTasksPath();
3157
+ if (!mdPath) {
3158
+ return {
3159
+ content: [
3160
+ {
3161
+ type: "text",
3162
+ text: 'No master-tasks.md found. Run "stackmemory tasks init" to create one.'
3163
+ }
3164
+ ]
3165
+ };
3166
+ }
3167
+ let tasks = parseMasterTasks(readFileSync(mdPath, "utf-8"));
3168
+ if (args.owner) {
3169
+ tasks = tasks.filter((t) => t.owner === String(args.owner));
3170
+ }
3171
+ const next = getNextTask(tasks);
3172
+ if (!next) {
3173
+ return {
3174
+ content: [{ type: "text", text: "No actionable tasks found." }]
3175
+ };
3176
+ }
3177
+ return {
3178
+ content: [{ type: "text", text: JSON.stringify(next, null, 2) }]
3179
+ };
3180
+ }
3181
+ handleUpdateMasterTask(args) {
3182
+ const mdPath = this.resolveMasterTasksPath();
3183
+ if (!mdPath) {
3184
+ return {
3185
+ content: [{ type: "text", text: "No master-tasks.md found." }]
3186
+ };
3187
+ }
3188
+ const taskId = String(args.task_id || "").toUpperCase();
3189
+ if (!taskId) {
3190
+ return {
3191
+ content: [{ type: "text", text: "task_id is required." }],
3192
+ isError: true
3193
+ };
3194
+ }
3195
+ const updates = {};
3196
+ if (args.status) updates.status = String(args.status);
3197
+ if (args.priority) updates.priority = String(args.priority);
3198
+ if (args.owner) updates.owner = String(args.owner);
3199
+ if (args.branch_pr) updates.branchPr = String(args.branch_pr);
3200
+ if (args.notes) updates.notes = String(args.notes);
3201
+ if (args.sync) updates.sync = String(args.sync);
3202
+ try {
3203
+ updateTaskInFile(mdPath, taskId, updates);
3204
+ return {
3205
+ content: [{ type: "text", text: `Updated ${taskId}` }]
3206
+ };
3207
+ } catch (err) {
3208
+ return {
3209
+ content: [{ type: "text", text: err.message }],
3210
+ isError: true
3211
+ };
3212
+ }
3213
+ }
3214
+ handleCreateMasterTask(args) {
3215
+ const mdPath = this.resolveMasterTasksPath();
3216
+ if (!mdPath) {
3217
+ return {
3218
+ content: [
3219
+ {
3220
+ type: "text",
3221
+ text: 'No master-tasks.md found. Run "stackmemory tasks init" to create one.'
3222
+ }
3223
+ ]
3224
+ };
3225
+ }
3226
+ const task = String(args.task || "");
3227
+ if (!task) {
3228
+ return {
3229
+ content: [{ type: "text", text: "task description is required." }],
3230
+ isError: true
3231
+ };
3232
+ }
3233
+ const id = addTaskToFile(mdPath, {
3234
+ priority: String(args.priority || "P1"),
3235
+ status: "todo",
3236
+ owner: String(args.owner || "@me"),
3237
+ sync: String(args.sync || "local"),
3238
+ task,
3239
+ branchPr: "",
3240
+ notes: String(args.notes || "")
3241
+ });
3242
+ return {
3243
+ content: [{ type: "text", text: `Created ${id}: ${task}` }]
3244
+ };
3245
+ }
3459
3246
  }
3460
3247
  var server_default = LocalStackMemoryMCP;
3461
3248
  async function runMCPServer() {