@stackmemoryai/stackmemory 1.10.5 → 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 (225) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +107 -24
  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/claude-sm.js +266 -84
  11. package/dist/src/cli/codex-sm.js +225 -33
  12. package/dist/src/cli/commands/bench.js +209 -2
  13. package/dist/src/cli/commands/brain.js +206 -0
  14. package/dist/src/cli/commands/cache.js +126 -0
  15. package/dist/src/cli/commands/company-os.js +184 -0
  16. package/dist/src/cli/commands/context.js +5 -0
  17. package/dist/src/cli/commands/daemon.js +41 -0
  18. package/dist/src/cli/commands/handoff.js +40 -9
  19. package/dist/src/cli/commands/onboard.js +70 -3
  20. package/dist/src/cli/commands/operator.js +127 -0
  21. package/dist/src/cli/commands/optimize.js +117 -0
  22. package/dist/src/cli/commands/orchestrate.js +232 -5
  23. package/dist/src/cli/commands/orchestrator.js +315 -26
  24. package/dist/src/cli/commands/pack.js +322 -0
  25. package/dist/src/cli/commands/patterns.js +254 -0
  26. package/dist/src/cli/commands/portal.js +161 -0
  27. package/dist/src/cli/commands/scaffold.js +92 -0
  28. package/dist/src/cli/commands/search.js +40 -1
  29. package/dist/src/cli/commands/setup.js +178 -11
  30. package/dist/src/cli/commands/skills.js +10 -1
  31. package/dist/src/cli/commands/state.js +265 -0
  32. package/dist/src/cli/commands/sync.js +253 -0
  33. package/dist/src/cli/commands/tasks.js +130 -1
  34. package/dist/src/cli/commands/vision.js +221 -0
  35. package/dist/src/cli/gemini-sm.js +19 -29
  36. package/dist/src/cli/hermes-sm.js +224 -0
  37. package/dist/src/cli/index.js +105 -39
  38. package/dist/src/cli/opencode-sm.js +38 -21
  39. package/dist/src/cli/utils/determinism-watcher.js +66 -0
  40. package/dist/src/cli/utils/real-cli-bin.js +116 -0
  41. package/dist/src/core/brain/brain-store.js +187 -0
  42. package/dist/src/core/brain/brain-sync.js +193 -0
  43. package/dist/src/core/brain/index.js +78 -0
  44. package/dist/src/core/brain/types.js +10 -0
  45. package/dist/src/core/cache/content-cache.js +238 -0
  46. package/dist/src/{integrations/diffmem → core/cache}/index.js +5 -5
  47. package/dist/src/core/cache/token-estimator.js +39 -0
  48. package/dist/src/core/config/feature-flags.js +2 -6
  49. package/dist/src/core/context/frame-database.js +79 -27
  50. package/dist/src/core/context/recursive-context-manager.js +1 -1
  51. package/dist/src/core/context/rehydration.js +2 -1
  52. package/dist/src/core/cross-search/cross-project-search.js +269 -0
  53. package/dist/src/core/cross-search/index.js +10 -0
  54. package/dist/src/core/database/sqlite-adapter.js +14 -84
  55. package/dist/src/core/extensions/provider-adapter.js +5 -0
  56. package/dist/src/core/models/model-router.js +54 -2
  57. package/dist/src/core/models/provider-pricing.js +58 -4
  58. package/dist/src/core/monitoring/logger.js +2 -1
  59. package/dist/src/core/optimization/trace-optimizer.js +413 -0
  60. package/dist/src/core/patterns/index.js +22 -0
  61. package/dist/src/core/patterns/pattern-applier.js +39 -0
  62. package/dist/src/core/patterns/pattern-observer.js +157 -0
  63. package/dist/src/core/patterns/pattern-store.js +259 -0
  64. package/dist/src/core/patterns/types.js +19 -0
  65. package/dist/src/core/provenance/confidence-scorer.js +128 -0
  66. package/dist/src/core/provenance/index.js +40 -0
  67. package/dist/src/core/provenance/provenance-store.js +194 -0
  68. package/dist/src/core/provenance/types.js +82 -0
  69. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  70. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  71. package/dist/src/core/session/project-handoff.js +64 -0
  72. package/dist/src/core/session/session-manager.js +28 -0
  73. package/dist/src/core/shared-state/canonical-store.js +564 -0
  74. package/dist/src/core/skill-packs/index.js +18 -0
  75. package/dist/src/core/skill-packs/parser.js +42 -0
  76. package/dist/src/core/skill-packs/registry.js +224 -0
  77. package/dist/src/core/skill-packs/types.js +79 -0
  78. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  79. package/dist/src/core/storage/cloud-sync.js +574 -0
  80. package/dist/src/core/storage/two-tier-storage.js +5 -1
  81. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  82. package/dist/src/core/tasks/md-task-parser.js +138 -0
  83. package/dist/src/core/trace/trace-event-store.js +282 -0
  84. package/dist/src/core/vision/index.js +27 -0
  85. package/dist/src/core/vision/signals.js +79 -0
  86. package/dist/src/core/vision/types.js +22 -0
  87. package/dist/src/core/vision/vision-file.js +146 -0
  88. package/dist/src/core/vision/vision-loop.js +220 -0
  89. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  90. package/dist/src/daemon/daemon-config.js +52 -0
  91. package/dist/src/daemon/services/desire-path-service.js +566 -0
  92. package/dist/src/daemon/services/github-service.js +126 -0
  93. package/dist/src/daemon/services/research-stream-service.js +320 -0
  94. package/dist/src/daemon/services/telemetry-service.js +192 -0
  95. package/dist/src/daemon/unified-daemon.js +58 -1
  96. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  97. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  98. package/dist/src/features/operator/adapter-factory.js +62 -0
  99. package/dist/src/features/operator/browser-adapter.js +109 -0
  100. package/dist/src/features/operator/desktop-adapter.js +125 -0
  101. package/dist/src/features/operator/index.js +39 -0
  102. package/dist/src/features/operator/llm-decision.js +137 -0
  103. package/dist/src/features/operator/operator-logger.js +92 -0
  104. package/dist/src/features/operator/overnight-runner.js +327 -0
  105. package/dist/src/features/operator/screen-adapter.js +91 -0
  106. package/dist/src/features/operator/session-manager.js +127 -0
  107. package/dist/src/features/operator/state-machine.js +227 -0
  108. package/dist/src/features/operator/task-queue.js +81 -0
  109. package/dist/src/features/portal/index.js +26 -0
  110. package/dist/src/features/portal/server.js +240 -0
  111. package/dist/src/features/portal/types.js +14 -0
  112. package/dist/src/features/portal/ui.js +195 -0
  113. package/dist/src/features/sweep/pty-wrapper.js +13 -5
  114. package/dist/src/features/tasks/task-aware-context.js +2 -1
  115. package/dist/src/features/tui/simple-monitor.js +0 -23
  116. package/dist/src/features/tui/swarm-monitor.js +8 -66
  117. package/dist/src/features/web/client/hooks/use-socket.js +12 -0
  118. package/dist/src/{core/merge/index.js → features/web/client/lib/utils.js} +8 -4
  119. package/dist/src/features/web/client/next-env.d.js +4 -0
  120. package/dist/src/features/web/client/stores/session-store.js +12 -0
  121. package/dist/src/features/web/server/gcp-billing.js +76 -0
  122. package/dist/src/features/web/server/index.js +10 -0
  123. package/dist/src/features/web/server/spend-calculator.js +228 -0
  124. package/dist/src/hooks/schemas.js +6 -1
  125. package/dist/src/integrations/anthropic/client.js +3 -2
  126. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  127. package/dist/src/integrations/claude-code/subagent-client.js +307 -11
  128. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  129. package/dist/src/integrations/github/pr-state.js +158 -0
  130. package/dist/src/integrations/linear/client.js +4 -1
  131. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  132. package/dist/src/integrations/linear/webhook-server.js +18 -22
  133. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  134. package/dist/src/integrations/mcp/handlers/index.js +40 -84
  135. package/dist/src/integrations/mcp/server.js +542 -641
  136. package/dist/src/integrations/mcp/tool-alias-registry.js +297 -0
  137. package/dist/src/integrations/mcp/tool-definitions.js +152 -682
  138. package/dist/src/mcp/stackmemory-mcp-server.js +571 -231
  139. package/dist/src/orchestrators/multimodal/determinism.js +244 -0
  140. package/dist/src/orchestrators/multimodal/harness.js +149 -78
  141. package/dist/src/orchestrators/multimodal/providers.js +44 -3
  142. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  143. package/dist/src/utils/hook-installer.js +0 -8
  144. package/dist/src/utils/process-cleanup.js +1 -7
  145. package/docs/README.md +42 -0
  146. package/docs/guides/README_INSTALL.md +208 -0
  147. package/package.json +27 -9
  148. package/packs/coding/python-fastapi/instructions.md +60 -0
  149. package/packs/coding/python-fastapi/pack.yaml +28 -0
  150. package/packs/coding/typescript-react/instructions.md +47 -0
  151. package/packs/coding/typescript-react/pack.yaml +28 -0
  152. package/packs/core/commands/capture.md +32 -0
  153. package/packs/core/commands/learn.md +73 -0
  154. package/packs/core/commands/next.md +36 -0
  155. package/packs/core/commands/restart.md +58 -0
  156. package/packs/core/commands/restore.md +29 -0
  157. package/packs/core/commands/start.md +57 -0
  158. package/packs/core/commands/stop.md +65 -0
  159. package/packs/core/commands/summary.md +40 -0
  160. package/packs/core/manifest.json +24 -0
  161. package/packs/ops/decision-recovery/instructions.md +65 -0
  162. package/packs/ops/decision-recovery/pack.yaml +89 -0
  163. package/scripts/claude-code-wrapper.sh +11 -0
  164. package/scripts/claude-sm-setup.sh +12 -1
  165. package/scripts/codex-wrapper.sh +11 -0
  166. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  167. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  168. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  169. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  170. package/scripts/hooks/cleanup-shell.sh +12 -1
  171. package/scripts/hooks/task-complete.sh +12 -1
  172. package/scripts/install-code-execution-hooks.sh +12 -1
  173. package/scripts/install-sweep-hook.sh +12 -0
  174. package/scripts/install.sh +11 -0
  175. package/scripts/opencode-wrapper.sh +11 -0
  176. package/scripts/portal/cloud-init.yaml +69 -0
  177. package/scripts/portal/setup.sh +69 -0
  178. package/scripts/portal/stackmemory-portal.service +34 -0
  179. package/scripts/setup-claude-integration.sh +12 -1
  180. package/scripts/smoke-init-db.sh +23 -0
  181. package/scripts/stackmemory-daemon.sh +11 -0
  182. package/scripts/verify-dist.cjs +11 -4
  183. package/dist/src/cli/commands/ralph.js +0 -1053
  184. package/dist/src/cli/commands/team.js +0 -168
  185. package/dist/src/core/context/shared-context-layer.js +0 -620
  186. package/dist/src/core/context/stack-merge-resolver.js +0 -748
  187. package/dist/src/core/merge/conflict-detector.js +0 -430
  188. package/dist/src/core/merge/resolution-engine.js +0 -557
  189. package/dist/src/core/merge/stack-diff.js +0 -531
  190. package/dist/src/core/merge/unified-merge-resolver.js +0 -302
  191. package/dist/src/hooks/diffmem-hooks.js +0 -376
  192. package/dist/src/integrations/diffmem/client.js +0 -208
  193. package/dist/src/integrations/diffmem/config.js +0 -14
  194. package/dist/src/integrations/greptile/client.js +0 -101
  195. package/dist/src/integrations/greptile/config.js +0 -14
  196. package/dist/src/integrations/greptile/index.js +0 -11
  197. package/dist/src/integrations/mcp/handlers/cord-handlers.js +0 -397
  198. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  199. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  200. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  201. package/dist/src/integrations/mcp/handlers/team-handlers.js +0 -211
  202. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  203. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  204. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -391
  205. package/dist/src/integrations/ralph/index.js +0 -17
  206. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -435
  207. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  208. package/dist/src/integrations/ralph/loopmax.js +0 -488
  209. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  210. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  211. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  212. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  213. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  214. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  215. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  216. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  217. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  218. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  219. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1007
  220. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  221. package/scripts/ralph-loop-implementation.js +0 -404
  222. /package/dist/src/core/{merge → cache}/types.js +0 -0
  223. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  224. /package/dist/src/{integrations/greptile/types.js → core/trace/trace-event.js} +0 -0
  225. /package/dist/src/{integrations/ralph → features/operator}/types.js +0 -0
@@ -4,6 +4,9 @@ import { dirname as __pathDirname } from 'path';
4
4
  const __filename = __fileURLToPath(import.meta.url);
5
5
  const __dirname = __pathDirname(__filename);
6
6
  process.env["STACKMEMORY_CLI"] = "true";
7
+ if (!process.env["STACKMEMORY_LOG_LEVEL"] && process.argv.includes("--json")) {
8
+ process.env["STACKMEMORY_LOG_LEVEL"] = "ERROR";
9
+ }
7
10
  import { config as loadDotenv } from "dotenv";
8
11
  loadDotenv({ quiet: true });
9
12
  import { initializeTracing, trace } from "../core/trace/index.js";
@@ -12,7 +15,6 @@ import { program } from "commander";
12
15
  import { logger } from "../core/monitoring/logger.js";
13
16
  import { FrameManager } from "../core/context/index.js";
14
17
  import { sessionManager, FrameQueryMode } from "../core/session/index.js";
15
- import { sharedContextLayer } from "../core/context/shared-context-layer.js";
16
18
  import { UpdateChecker } from "../core/utils/update-checker.js";
17
19
  import { ProgressTracker } from "../core/monitoring/progress-tracker.js";
18
20
  import { registerProjectCommands } from "./commands/projects.js";
@@ -36,12 +38,14 @@ import {
36
38
  } from "./commands/decision.js";
37
39
  import clearCommand from "./commands/clear.js";
38
40
  import serviceCommand from "./commands/service.js";
39
- import { registerLoginCommand } from "./commands/login.js";
40
41
  import { registerSignupCommand } from "./commands/signup.js";
42
+ import { createSyncCommand, createLoginCommand } from "./commands/sync.js";
41
43
  import { registerLogoutCommand, registerDbCommands } from "./commands/db.js";
42
44
  import { createHooksCommand } from "./commands/hooks.js";
43
45
  import { createDaemonCommand } from "./commands/daemon.js";
44
46
  import { createSweepCommand } from "./commands/sweep.js";
47
+ import { createPortalCommand } from "./commands/portal.js";
48
+ import { createBrainCommand } from "./commands/brain.js";
45
49
  import { createShellCommand } from "./commands/shell.js";
46
50
  import { createAPICommand } from "./commands/api.js";
47
51
  import { createCleanupProcessesCommand } from "./commands/cleanup-processes.js";
@@ -54,21 +58,33 @@ import { createPingCommand } from "./commands/ping.js";
54
58
  import { createAuditCommand } from "./commands/audit.js";
55
59
  import { createStatsCommand } from "./commands/stats.js";
56
60
  import { createBenchCommand } from "./commands/bench.js";
61
+ import { createOptimizeCommand } from "./commands/optimize.js";
62
+ import { createStateCommand } from "./commands/state.js";
57
63
  import { createDigestCommands } from "./commands/digest.js";
58
- import { createTeamCommands } from "./commands/team.js";
59
64
  import { createDesiresCommands } from "./commands/desires.js";
60
65
  import { createConductorCommands } from "./commands/orchestrate.js";
66
+ import { createOperatorCommands } from "./commands/operator.js";
67
+ import { createPatternsCommand } from "./commands/patterns.js";
61
68
  import { createPreflightCommand } from "./commands/preflight.js";
62
69
  import { createRulesCommand } from "./commands/rules.js";
63
70
  import { createSnapshotCommand } from "./commands/snapshot.js";
64
71
  import { createWikiCommand } from "./commands/wiki.js";
65
72
  import { createLoopCommand } from "./commands/loop.js";
66
73
  import { createSkillCommand } from "./commands/skill.js";
74
+ import { createPackCommand } from "./commands/pack.js";
75
+ import { createCacheCommand } from "./commands/cache.js";
76
+ import { createScaffoldCommand } from "./commands/scaffold.js";
77
+ import { createCompanyOsCommand } from "./commands/company-os.js";
67
78
  import chalk from "chalk";
68
79
  import * as fs from "fs";
69
80
  import * as path from "path";
70
81
  import { filterPending } from "../integrations/mcp/pending-utils.js";
82
+ import {
83
+ getCurrentRepoGitHubInfo,
84
+ refreshCurrentRepoPullRequestState
85
+ } from "../integrations/github/pr-state.js";
71
86
  import { ProjectManager } from "../core/projects/project-manager.js";
87
+ import { canonicalStateStore } from "../core/shared-state/canonical-store.js";
72
88
  import { join } from "path";
73
89
  import { existsSync, mkdirSync } from "fs";
74
90
  import { createRequire } from "module";
@@ -105,10 +121,13 @@ async function openDatabase(dbPath) {
105
121
  function isTestEnv() {
106
122
  return process.env["VITEST"] === "true" || process.env["NODE_ENV"] === "test" || process.env["STACKMEMORY_TEST_SKIP_DB"] === "1";
107
123
  }
124
+ function collectRepeatedOption(value, previous = []) {
125
+ return [...previous, value];
126
+ }
108
127
  UpdateChecker.checkForUpdates(VERSION, true).catch(() => {
109
128
  });
110
129
  program.name("stackmemory").description(
111
- "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention"
130
+ "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with infinite retention"
112
131
  ).version(VERSION);
113
132
  program.command("init").description(
114
133
  "Initialize StackMemory in current project (zero-config by default)"
@@ -198,33 +217,24 @@ program.command("status").description("Show current StackMemory status").option(
198
217
  }
199
218
  await UpdateChecker.checkForUpdates(VERSION);
200
219
  await sessionManager.initialize();
201
- await sharedContextLayer.initialize();
202
220
  const { initObsidianVault } = await import("../core/storage/obsidian-vault-adapter.js");
203
221
  await initObsidianVault();
204
222
  const session = await sessionManager.getOrCreateSession({
205
223
  projectPath: projectRoot,
206
224
  sessionId: options.session
207
225
  });
208
- const contextDiscovery = await sharedContextLayer.autoDiscoverContext();
209
- if (contextDiscovery.hasSharedContext && contextDiscovery.sessionCount > 1) {
210
- console.log(`
211
- \u{1F4A1} Shared Context Available:`);
212
- console.log(
213
- ` ${contextDiscovery.sessionCount} sessions with shared context`
214
- );
215
- if (contextDiscovery.recentPatterns.length > 0) {
216
- console.log(` Recent patterns:`);
217
- contextDiscovery.recentPatterns.slice(0, 3).forEach((p) => {
218
- console.log(
219
- ` \u2022 ${p.type}: ${p.pattern.slice(0, 50)} (${p.frequency}x)`
220
- );
221
- });
222
- }
223
- if (contextDiscovery.lastDecisions.length > 0) {
224
- console.log(
225
- ` Last decision: ${contextDiscovery.lastDecisions[0].decision.slice(0, 60)}`
226
- );
227
- }
226
+ const sharedProjectState = await canonicalStateStore.getProjectSummary({
227
+ projectId: session.projectId,
228
+ projectPath: projectRoot,
229
+ eventLimit: 5
230
+ });
231
+ const githubInfo = getCurrentRepoGitHubInfo(projectRoot);
232
+ let githubProjection = githubInfo && await canonicalStateStore.getGitHubPullRequest({
233
+ repo: githubInfo.repo,
234
+ branch: githubInfo.branch
235
+ });
236
+ if (githubInfo && (!githubProjection || Date.now() - githubProjection.lastSyncedAt > 2 * 60 * 1e3)) {
237
+ githubProjection = await refreshCurrentRepoPullRequestState(projectRoot) || githubProjection;
228
238
  }
229
239
  const db = await openDatabase(dbPath);
230
240
  const frameManager = new FrameManager(db, session.projectId);
@@ -276,6 +286,23 @@ program.command("status").description("Show current StackMemory status").option(
276
286
  console.log(
277
287
  ` Cached contexts: ${contextCount.count || 0} (global)`
278
288
  );
289
+ console.log(
290
+ ` Shared sessions: ${sharedProjectState.activeSessions.length}`
291
+ );
292
+ console.log(
293
+ ` Shared instances: ${sharedProjectState.activeInstances.length}`
294
+ );
295
+ console.log(
296
+ ` Shared claims: ${sharedProjectState.activeClaims.length}`
297
+ );
298
+ const branchClaim = sharedProjectState.activeClaims.find(
299
+ (claim) => claim.branch && claim.branch === session.branch
300
+ );
301
+ if (branchClaim) {
302
+ console.log(
303
+ ` Branch owner: ${branchClaim.tool} ${branchClaim.instanceId || branchClaim.sessionId || branchClaim.claimId.slice(0, 8)}`
304
+ );
305
+ }
279
306
  const recentFrames = db.prepare(
280
307
  `
281
308
  SELECT name, type, state, datetime(created_at, 'unixepoch') as created
@@ -295,6 +322,22 @@ program.command("status").description("Show current StackMemory status").option(
295
322
  );
296
323
  });
297
324
  }
325
+ if (githubProjection) {
326
+ console.log(`
327
+ GitHub PR:`);
328
+ console.log(
329
+ ` #${githubProjection.prNumber} ${githubProjection.state} ${githubProjection.title}`
330
+ );
331
+ console.log(
332
+ ` ${githubProjection.headRefName} -> ${githubProjection.baseRefName}`
333
+ );
334
+ if (githubProjection.reviewDecision) {
335
+ console.log(` Review: ${githubProjection.reviewDecision}`);
336
+ }
337
+ if (githubProjection.statusCheckRollup) {
338
+ console.log(` Checks: ${githubProjection.statusCheckRollup}`);
339
+ }
340
+ }
298
341
  console.log(`
299
342
  Current Session:`);
300
343
  console.log(` Stack depth: ${stackDepth}`);
@@ -460,7 +503,7 @@ program.command("context:test").description("Test context persistence by creatin
460
503
  });
461
504
  registerOnboardingCommand(program);
462
505
  registerSignupCommand(program);
463
- registerLoginCommand(program);
506
+ program.addCommand(createLoginCommand());
464
507
  registerLogoutCommand(program);
465
508
  registerDbCommands(program);
466
509
  registerProjectCommands(program);
@@ -478,6 +521,7 @@ program.addCommand(createConfigCommand());
478
521
  program.addCommand(createCaptureCommand());
479
522
  program.addCommand(createRestoreCommand());
480
523
  program.addCommand(createAutoCaptureCommand());
524
+ program.addCommand(createSyncCommand());
481
525
  program.addCommand(createDecisionCommand());
482
526
  program.addCommand(createMemoryCommand());
483
527
  program.addCommand(clearCommand);
@@ -550,16 +594,10 @@ if (isFeatureEnabled("skills")) {
550
594
  })
551
595
  );
552
596
  }
553
- if (isFeatureEnabled("ralph")) {
554
- lazyCommands.push(
555
- import("./commands/ralph.js").then(
556
- ({ default: createRalphCommand }) => program.addCommand(createRalphCommand())
557
- ).catch(() => {
558
- })
559
- );
560
- }
561
597
  program.addCommand(createDaemonCommand());
562
598
  program.addCommand(createSweepCommand());
599
+ program.addCommand(createPortalCommand());
600
+ program.addCommand(createBrainCommand());
563
601
  program.addCommand(createShellCommand());
564
602
  program.addCommand(createAPICommand());
565
603
  program.addCommand(createCleanupProcessesCommand());
@@ -571,16 +609,23 @@ program.addCommand(createModelCommand());
571
609
  program.addCommand(createAuditCommand());
572
610
  program.addCommand(createStatsCommand());
573
611
  program.addCommand(createBenchCommand());
612
+ program.addCommand(createOptimizeCommand());
613
+ program.addCommand(createStateCommand());
574
614
  program.addCommand(createDigestCommands());
575
- program.addCommand(createTeamCommands());
576
615
  program.addCommand(createDesiresCommands());
577
616
  program.addCommand(createConductorCommands());
617
+ program.addCommand(createOperatorCommands());
618
+ program.addCommand(createPatternsCommand());
578
619
  program.addCommand(createPreflightCommand());
579
620
  program.addCommand(createSnapshotCommand());
580
621
  program.addCommand(createWikiCommand());
581
622
  program.addCommand(createLoopCommand());
582
623
  program.addCommand(createRulesCommand());
583
624
  program.addCommand(createSkillCommand());
625
+ program.addCommand(createPackCommand());
626
+ program.addCommand(createCacheCommand());
627
+ program.addCommand(createScaffoldCommand());
628
+ program.addCommand(createCompanyOsCommand());
584
629
  registerSetupCommands(program);
585
630
  program.command("mm-spike").description(
586
631
  "Run multi-agent planning/implementation spike (planner/implementer/critic)"
@@ -600,7 +645,16 @@ program.command("mm-spike").description(
600
645
  "--execute",
601
646
  "Execute implementer (codex-sm) instead of dry-run",
602
647
  false
603
- ).option("--implementer <name>", "codex|claude", "codex").option("--max-iters <n>", "Retry loop iterations", "2").option("--audit-dir <path>", "Persist spike results to directory").option("--record-frame", "Record as real frame with anchors", false).option("--record", "Record plan & critique into StackMemory context", false).option("--json", "Emit single JSON result (UI-friendly)", false).option("--quiet", "Minimal output (default)", true).option("--verbose", "Verbose sectioned output", false).option(
648
+ ).option("--implementer <name>", "codex|claude", "codex").option("--max-iters <n>", "Retry loop iterations", "2").option("--audit-dir <path>", "Persist spike results to directory").option(
649
+ "--verify <cmd>",
650
+ "Verification command to run after each implementation attempt; repeatable",
651
+ collectRepeatedOption,
652
+ []
653
+ ).option("--record-frame", "Record as real frame with anchors", false).option("--record", "Record plan & critique into StackMemory context", false).option(
654
+ "--deterministic-fixture",
655
+ "Use deterministic fixture planner/critic for replayable smoke runs",
656
+ false
657
+ ).option("--json", "Emit single JSON result (UI-friendly)", false).option("--quiet", "Minimal output (default)", true).option("--verbose", "Verbose sectioned output", false).option(
604
658
  "--log",
605
659
  "Pretty print interaction log (planner/implementer/critic)",
606
660
  false
@@ -619,8 +673,10 @@ program.command("mm-spike").description(
619
673
  maxIters: parseInt(opts.maxIters),
620
674
  dryRun: !opts.execute,
621
675
  auditDir: opts.auditDir,
676
+ verificationCommands: opts.verify,
622
677
  recordFrame: Boolean(opts.recordFrame),
623
- record: Boolean(opts.record)
678
+ record: Boolean(opts.record),
679
+ deterministicFixture: Boolean(opts.deterministicFixture)
624
680
  }
625
681
  );
626
682
  if (opts.log) {
@@ -677,7 +733,15 @@ program.command("build").description(
677
733
  "--reviewer-model <name>",
678
734
  "Claude model for review",
679
735
  "claude-sonnet-4-20250514"
680
- ).option("--execute", "Execute implementer (default: true)", true).option("--dry-run", "Skip execution, show commands only").option("--implementer <name>", "codex|claude", "codex").option("--max-iters <n>", "Retry loop iterations", "2").option("--audit-dir <path>", "Persist spike results to directory").option("--record-frame", "Record as real frame with anchors").option("--record", "Record plan & critique into StackMemory context").option("--json", "Emit single JSON result (UI-friendly)").option("--quiet", "Minimal output").option("--verbose", "Verbose sectioned output").option("--log", "Pretty print interaction log (default: true)", true).option("-C, --cwd <path>", "Working directory for implementation").action(async (taskArg, opts) => {
736
+ ).option("--execute", "Execute implementer (default: true)", true).option("--dry-run", "Skip execution, show commands only").option("--implementer <name>", "codex|claude", "codex").option("--max-iters <n>", "Retry loop iterations", "2").option("--audit-dir <path>", "Persist spike results to directory").option(
737
+ "--verify <cmd>",
738
+ "Verification command to run after each implementation attempt; repeatable",
739
+ collectRepeatedOption,
740
+ []
741
+ ).option("--record-frame", "Record as real frame with anchors").option("--record", "Record plan & critique into StackMemory context").option(
742
+ "--deterministic-fixture",
743
+ "Use deterministic fixture planner/critic for replayable smoke runs"
744
+ ).option("--json", "Emit single JSON result (UI-friendly)").option("--quiet", "Minimal output").option("--verbose", "Verbose sectioned output").option("--log", "Pretty print interaction log (default: true)", true).option("-C, --cwd <path>", "Working directory for implementation").action(async (taskArg, opts) => {
681
745
  try {
682
746
  const task = typeof taskArg === "string" && taskArg.length > 0 ? taskArg : opts.task;
683
747
  if (!task) {
@@ -713,8 +777,10 @@ program.command("build").description(
713
777
  maxIters: parseInt(opts.maxIters),
714
778
  dryRun,
715
779
  auditDir: opts.auditDir,
780
+ verificationCommands: opts.verify,
716
781
  recordFrame: Boolean(opts.recordFrame),
717
- record: Boolean(opts.record)
782
+ record: Boolean(opts.record),
783
+ deterministicFixture: Boolean(opts.deterministicFixture)
718
784
  }
719
785
  );
720
786
  if (opts.log) {
@@ -13,6 +13,11 @@ import { program } from "commander";
13
13
  import { v4 as uuidv4 } from "uuid";
14
14
  import chalk from "chalk";
15
15
  import { initializeTracing, trace } from "../core/trace/index.js";
16
+ import { resolveRealCliBin } from "./utils/real-cli-bin.js";
17
+ import {
18
+ startDeterminismWatcher,
19
+ stopDeterminismWatcher
20
+ } from "./utils/determinism-watcher.js";
16
21
  const DEFAULT_SM_CONFIG = {
17
22
  defaultWorktree: false,
18
23
  defaultTracing: true
@@ -43,6 +48,7 @@ class OpencodeSM {
43
48
  config;
44
49
  stackmemoryPath;
45
50
  smConfig;
51
+ determinismWatcher;
46
52
  constructor() {
47
53
  this.smConfig = loadSMConfig();
48
54
  this.config = {
@@ -54,6 +60,7 @@ class OpencodeSM {
54
60
  sessionStartTime: Date.now()
55
61
  };
56
62
  this.stackmemoryPath = this.findStackMemory();
63
+ this.determinismWatcher = null;
57
64
  }
58
65
  getRepoRoot() {
59
66
  try {
@@ -127,27 +134,16 @@ class OpencodeSM {
127
134
  }
128
135
  }
129
136
  resolveOpencodeBin() {
130
- if (this.config.opencodeBin && this.config.opencodeBin.trim()) {
131
- return this.config.opencodeBin.trim();
132
- }
133
- const envBin = process.env["OPENCODE_BIN"];
134
- if (envBin && envBin.trim()) return envBin.trim();
135
- const possiblePaths = [
136
- path.join(os.homedir(), ".opencode", "bin", "opencode"),
137
- "/usr/local/bin/opencode",
138
- "/opt/homebrew/bin/opencode"
139
- ];
140
- for (const binPath of possiblePaths) {
141
- if (fs.existsSync(binPath)) {
142
- return binPath;
143
- }
144
- }
145
- try {
146
- execSync("which opencode", { stdio: "ignore" });
147
- return "opencode";
148
- } catch {
149
- }
150
- return null;
137
+ return resolveRealCliBin({
138
+ explicitBin: this.config.opencodeBin,
139
+ envBin: process.env["OPENCODE_BIN"],
140
+ preferredPaths: [
141
+ path.join(os.homedir(), ".opencode", "bin", "opencode"),
142
+ "/usr/local/bin/opencode",
143
+ "/opt/homebrew/bin/opencode"
144
+ ],
145
+ pathCommands: ["opencode"]
146
+ });
151
147
  }
152
148
  setupWorktree() {
153
149
  if (!this.config.useWorktree || !this.isGitRepo()) {
@@ -251,6 +247,23 @@ class OpencodeSM {
251
247
  );
252
248
  }
253
249
  }
250
+ startDeterminismWatcher() {
251
+ this.determinismWatcher = startDeterminismWatcher({
252
+ stackmemoryBin: this.stackmemoryPath,
253
+ cwd: process.cwd(),
254
+ task: this.config.task,
255
+ instanceId: this.config.instanceId,
256
+ tool: "opencode"
257
+ });
258
+ if (this.determinismWatcher) {
259
+ const modeLabel = this.determinismWatcher.mode === "targeted" ? "targeted" : "repo-root fallback";
260
+ console.log(chalk.gray(`Determinism: ${modeLabel}`));
261
+ }
262
+ }
263
+ stopDeterminismWatcher() {
264
+ stopDeterminismWatcher(this.determinismWatcher);
265
+ this.determinismWatcher = null;
266
+ }
254
267
  async run(args) {
255
268
  const opencodeArgs = [];
256
269
  let i = 0;
@@ -354,6 +367,7 @@ class OpencodeSM {
354
367
  if (this.config.worktreePath) {
355
368
  process.env["OPENCODE_WORKTREE_PATH"] = this.config.worktreePath;
356
369
  }
370
+ this.startDeterminismWatcher();
357
371
  console.log(chalk.gray(`Instance: ${this.config.instanceId}`));
358
372
  console.log(chalk.gray(`Working in: ${process.cwd()}`));
359
373
  if (this.config.tracingEnabled) {
@@ -391,6 +405,7 @@ class OpencodeSM {
391
405
  process.exit(1);
392
406
  });
393
407
  opencode.on("exit", async (code) => {
408
+ this.stopDeterminismWatcher();
394
409
  this.saveContext("OpenCode session ended", {
395
410
  action: "session_end",
396
411
  exitCode: code
@@ -411,12 +426,14 @@ class OpencodeSM {
411
426
  process.exit(code || 0);
412
427
  });
413
428
  process.on("SIGINT", () => {
429
+ this.stopDeterminismWatcher();
414
430
  this.saveContext("OpenCode session interrupted", {
415
431
  action: "session_interrupt"
416
432
  });
417
433
  opencode.kill("SIGINT");
418
434
  });
419
435
  process.on("SIGTERM", () => {
436
+ this.stopDeterminismWatcher();
420
437
  this.saveContext("OpenCode session terminated", {
421
438
  action: "session_terminate"
422
439
  });
@@ -0,0 +1,66 @@
1
+ import { fileURLToPath as __fileURLToPath } from 'url';
2
+ import { dirname as __pathDirname } from 'path';
3
+ const __filename = __fileURLToPath(import.meta.url);
4
+ const __dirname = __pathDirname(__filename);
5
+ import { spawn } from "child_process";
6
+ import * as fs from "fs";
7
+ import * as path from "path";
8
+ import { getDeterminismWatchTargets } from "../../orchestrators/multimodal/determinism.js";
9
+ function shouldAutoStartDeterminismWatcher(cwd) {
10
+ if (process.env["STACKMEMORY_DETERMINISM_AUTO"] === "0") {
11
+ return false;
12
+ }
13
+ return fs.existsSync(path.join(cwd, ".git"));
14
+ }
15
+ function startDeterminismWatcher(options) {
16
+ if (!shouldAutoStartDeterminismWatcher(options.cwd)) {
17
+ return null;
18
+ }
19
+ const runs = process.env["STACKMEMORY_DETERMINISM_RUNS"] || "3";
20
+ const task = options.task || process.env["STACKMEMORY_DETERMINISM_TASK"] || "Determinism probe";
21
+ const targets = getDeterminismWatchTargets(options.cwd);
22
+ const mode = targets.length === 1 && targets[0] === "." ? "repo-root" : "targeted";
23
+ const child = spawn(
24
+ options.stackmemoryBin,
25
+ [
26
+ "bench",
27
+ "determinism",
28
+ "--task",
29
+ task,
30
+ "--runs",
31
+ runs,
32
+ "--watch",
33
+ "--json"
34
+ ],
35
+ {
36
+ cwd: options.cwd,
37
+ stdio: "ignore",
38
+ env: {
39
+ ...process.env,
40
+ STACKMEMORY_DETERMINISM_PARENT_TOOL: options.tool,
41
+ STACKMEMORY_DETERMINISM_PARENT_INSTANCE: options.instanceId || "",
42
+ STACKMEMORY_DETERMINISM_PARENT_SESSION: options.sessionId || ""
43
+ }
44
+ }
45
+ );
46
+ return {
47
+ child,
48
+ mode,
49
+ targets
50
+ };
51
+ }
52
+ function stopDeterminismWatcher(handle) {
53
+ const child = handle?.child ?? null;
54
+ if (!child || child.killed) {
55
+ return;
56
+ }
57
+ try {
58
+ child.kill("SIGTERM");
59
+ } catch {
60
+ }
61
+ }
62
+ export {
63
+ shouldAutoStartDeterminismWatcher,
64
+ startDeterminismWatcher,
65
+ stopDeterminismWatcher
66
+ };
@@ -0,0 +1,116 @@
1
+ import { fileURLToPath as __fileURLToPath } from 'url';
2
+ import { dirname as __pathDirname } from 'path';
3
+ const __filename = __fileURLToPath(import.meta.url);
4
+ const __dirname = __pathDirname(__filename);
5
+ import { execSync } from "child_process";
6
+ import { createRequire } from "node:module";
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ const DEFAULT_WRAPPER_PATH_SNIPPETS = [
10
+ "/Applications/cmux.app/Contents/Resources/bin/"
11
+ ];
12
+ function isWrapperPath(candidate, wrapperPathSnippets) {
13
+ const normalized = candidate.trim();
14
+ return wrapperPathSnippets.some((snippet) => normalized.includes(snippet));
15
+ }
16
+ function resolveRealCliBin(options) {
17
+ if (options.explicitBin?.trim()) {
18
+ return options.explicitBin.trim();
19
+ }
20
+ if (options.envBin?.trim()) {
21
+ return options.envBin.trim();
22
+ }
23
+ const wrapperPathSnippets = options.wrapperPathSnippets || DEFAULT_WRAPPER_PATH_SNIPPETS;
24
+ for (const candidate of options.preferredPaths || []) {
25
+ if (fs.existsSync(candidate) && !isWrapperPath(candidate, wrapperPathSnippets)) {
26
+ return candidate;
27
+ }
28
+ }
29
+ for (const command of options.pathCommands) {
30
+ try {
31
+ const output = execSync(`which -a ${command}`, {
32
+ encoding: "utf8",
33
+ stdio: ["ignore", "pipe", "ignore"]
34
+ });
35
+ const resolved = output.split("\n").map((line) => line.trim()).filter(Boolean).find((candidate) => !isWrapperPath(candidate, wrapperPathSnippets));
36
+ if (resolved) {
37
+ return resolved;
38
+ }
39
+ } catch {
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ const CODEX_PLATFORM_TRIPLES = {
45
+ darwin: { x64: "x86_64-apple-darwin", arm64: "aarch64-apple-darwin" },
46
+ linux: {
47
+ x64: "x86_64-unknown-linux-musl",
48
+ arm64: "aarch64-unknown-linux-musl"
49
+ },
50
+ win32: { x64: "x86_64-pc-windows-msvc", arm64: "aarch64-pc-windows-msvc" }
51
+ };
52
+ function resolveNativeCodexBin() {
53
+ const triple = CODEX_PLATFORM_TRIPLES[process.platform]?.[process.arch];
54
+ if (!triple) return [];
55
+ const binaryName = process.platform === "win32" ? "codex.exe" : "codex";
56
+ const platformPkg = `@openai/codex-${process.platform}-${process.arch === "arm64" ? "arm64" : "x64"}`;
57
+ const candidates = [];
58
+ try {
59
+ const req = createRequire(
60
+ path.join(
61
+ process.execPath,
62
+ "..",
63
+ "..",
64
+ "lib",
65
+ "node_modules",
66
+ "@openai",
67
+ "codex",
68
+ "package.json"
69
+ )
70
+ );
71
+ const pkgJson = req.resolve(`${platformPkg}/package.json`);
72
+ const vendorBin = path.join(
73
+ path.dirname(pkgJson),
74
+ "vendor",
75
+ triple,
76
+ "bin",
77
+ binaryName
78
+ );
79
+ if (fs.existsSync(vendorBin)) candidates.push(vendorBin);
80
+ } catch {
81
+ }
82
+ try {
83
+ const nodeDir = path.dirname(process.execPath);
84
+ const globalModules = path.join(nodeDir, "..", "lib", "node_modules");
85
+ const vendorBin = path.join(
86
+ globalModules,
87
+ "@openai",
88
+ "codex",
89
+ "node_modules",
90
+ platformPkg,
91
+ "vendor",
92
+ triple,
93
+ "bin",
94
+ binaryName
95
+ );
96
+ if (fs.existsSync(vendorBin) && !candidates.includes(vendorBin)) {
97
+ candidates.push(vendorBin);
98
+ }
99
+ } catch {
100
+ }
101
+ return candidates;
102
+ }
103
+ function resolveNvmBin(name) {
104
+ try {
105
+ const nodeDir = path.dirname(process.execPath);
106
+ const candidate = path.join(nodeDir, name);
107
+ if (fs.existsSync(candidate)) return candidate;
108
+ } catch {
109
+ }
110
+ return void 0;
111
+ }
112
+ export {
113
+ resolveNativeCodexBin,
114
+ resolveNvmBin,
115
+ resolveRealCliBin
116
+ };