@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
@@ -0,0 +1,220 @@
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 { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
6
+ import { dirname } from "path";
7
+ import { loadVision, setObjectiveDone } from "./vision-file.js";
8
+ import { SignalInbox } from "./signals.js";
9
+ import {
10
+ SEVERITY_RANK
11
+ } from "./types.js";
12
+ function today() {
13
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
14
+ }
15
+ const realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
16
+ class VisionLoop {
17
+ opts;
18
+ inbox;
19
+ constructor(options) {
20
+ this.opts = { sleep: realSleep, ...options };
21
+ this.inbox = new SignalInbox(options.signalsPath);
22
+ }
23
+ readState() {
24
+ const base = {
25
+ day: today(),
26
+ iterationsToday: 0,
27
+ consecutiveFailures: 0,
28
+ lastTickAt: 0
29
+ };
30
+ if (!existsSync(this.opts.statePath)) return base;
31
+ try {
32
+ const s = JSON.parse(
33
+ readFileSync(this.opts.statePath, "utf-8")
34
+ );
35
+ if (s.day !== today()) return { ...s, day: today(), iterationsToday: 0 };
36
+ return s;
37
+ } catch {
38
+ return base;
39
+ }
40
+ }
41
+ writeState(s) {
42
+ const dir = dirname(this.opts.statePath);
43
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
44
+ writeFileSync(this.opts.statePath, JSON.stringify(s, null, 2));
45
+ }
46
+ /** Pick the next unit of work: pending signals outrank pending objectives. */
47
+ selectCandidate(vision) {
48
+ const signal = this.inbox.pending()[0];
49
+ if (signal) {
50
+ return {
51
+ kind: "signal",
52
+ id: signal.id,
53
+ text: signal.text,
54
+ priority: 100 + SEVERITY_RANK[signal.severity],
55
+ refs: signal.refs ?? []
56
+ };
57
+ }
58
+ const idx = vision.objectives.findIndex((o2) => !o2.done);
59
+ const o = idx >= 0 ? vision.objectives[idx] : void 0;
60
+ if (o) {
61
+ return {
62
+ kind: "objective",
63
+ id: o.id,
64
+ text: o.text,
65
+ priority: 50 - idx,
66
+ refs: []
67
+ };
68
+ }
69
+ return null;
70
+ }
71
+ checkGuardrails(state, vision, iterationThisRun) {
72
+ const l = vision.limits;
73
+ if (iterationThisRun >= l.maxIterations) {
74
+ return {
75
+ ok: false,
76
+ reason: `reached maxIterations (${l.maxIterations}) for this run`
77
+ };
78
+ }
79
+ if (state.iterationsToday >= l.maxIterationsPerDay) {
80
+ return {
81
+ ok: false,
82
+ reason: `reached maxIterationsPerDay (${l.maxIterationsPerDay})`
83
+ };
84
+ }
85
+ if (state.consecutiveFailures >= l.maxConsecutiveFailures) {
86
+ return {
87
+ ok: false,
88
+ reason: `circuit breaker: ${state.consecutiveFailures} consecutive failures (limit ${l.maxConsecutiveFailures})`
89
+ };
90
+ }
91
+ return { ok: true };
92
+ }
93
+ /** Has the brain already concluded this exact piece of work? */
94
+ priorConclusion(text) {
95
+ const hits = this.brainRecall(text);
96
+ const match = hits.find(
97
+ (e) => e.title.trim() === text.trim() && e.conclusion.trim().length > 0
98
+ );
99
+ return match?.conclusion;
100
+ }
101
+ brainRecall(text) {
102
+ return this.opts.brain.recall({ text, limit: 5 });
103
+ }
104
+ async tick(iterationThisRun, dryRun = false) {
105
+ const vision = loadVision(this.opts.visionPath);
106
+ if (!vision) {
107
+ return {
108
+ candidate: null,
109
+ guardrail: { ok: false, reason: "no VISION.md found" },
110
+ skippedAsKnown: false,
111
+ delegated: false
112
+ };
113
+ }
114
+ const state = this.readState();
115
+ const guardrail = this.checkGuardrails(state, vision, iterationThisRun);
116
+ if (!guardrail.ok) {
117
+ return {
118
+ candidate: null,
119
+ guardrail,
120
+ skippedAsKnown: false,
121
+ delegated: false
122
+ };
123
+ }
124
+ const candidate = this.selectCandidate(vision);
125
+ if (!candidate) {
126
+ return {
127
+ candidate: null,
128
+ guardrail: { ok: true },
129
+ skippedAsKnown: false,
130
+ delegated: false
131
+ };
132
+ }
133
+ const prior = this.priorConclusion(candidate.text);
134
+ if (prior) {
135
+ if (candidate.kind === "objective") {
136
+ setObjectiveDone(this.opts.visionPath, candidate.id, true);
137
+ } else {
138
+ this.inbox.resolve(candidate.id);
139
+ }
140
+ return {
141
+ candidate,
142
+ guardrail: { ok: true },
143
+ skippedAsKnown: true,
144
+ priorConclusion: prior,
145
+ delegated: false
146
+ };
147
+ }
148
+ if (dryRun || vision.limits.requireApproval) {
149
+ return {
150
+ candidate,
151
+ guardrail: { ok: true },
152
+ skippedAsKnown: false,
153
+ delegated: false
154
+ };
155
+ }
156
+ const outcome = await this.opts.delegate(candidate, vision);
157
+ this.opts.brain.record({
158
+ title: candidate.text,
159
+ summary: `Vision loop handled a ${candidate.kind} toward: ${vision.mission}`,
160
+ conclusion: outcome.conclusion,
161
+ kind: "experiment",
162
+ agent: "vision",
163
+ tags: ["vision", candidate.kind, outcome.success ? "success" : "failure"],
164
+ refs: [...candidate.refs, ...outcome.refs ?? []],
165
+ confidence: outcome.success ? 0.8 : 0.4
166
+ });
167
+ const next = this.readState();
168
+ if (outcome.success) {
169
+ next.iterationsToday += 1;
170
+ next.consecutiveFailures = 0;
171
+ if (candidate.kind === "objective") {
172
+ setObjectiveDone(this.opts.visionPath, candidate.id, true);
173
+ } else {
174
+ this.inbox.resolve(candidate.id);
175
+ }
176
+ } else {
177
+ next.consecutiveFailures += 1;
178
+ }
179
+ next.lastTickAt = Date.now();
180
+ this.writeState(next);
181
+ return {
182
+ candidate,
183
+ guardrail: { ok: true },
184
+ skippedAsKnown: false,
185
+ delegated: true,
186
+ outcome
187
+ };
188
+ }
189
+ /** Run ticks until a guardrail stops the loop or there's nothing left. */
190
+ async run(opts = {}) {
191
+ const vision = loadVision(this.opts.visionPath);
192
+ const max = opts.maxIterations ?? vision?.limits.maxIterations ?? 1;
193
+ const tickInterval = (vision?.limits.tickIntervalSec ?? 60) * 1e3;
194
+ const decisions = [];
195
+ let delegated = 0;
196
+ let skipped = 0;
197
+ let stopped = "completed run";
198
+ for (let i = 0; i < max; i++) {
199
+ const d = await this.tick(i, opts.dryRun);
200
+ decisions.push(d);
201
+ if (!d.guardrail.ok) {
202
+ stopped = d.guardrail.reason ?? "guardrail stop";
203
+ break;
204
+ }
205
+ if (!d.candidate) {
206
+ stopped = "no work remaining";
207
+ break;
208
+ }
209
+ if (d.skippedAsKnown) skipped++;
210
+ if (d.delegated) delegated++;
211
+ if (!opts.dryRun && i < max - 1) {
212
+ await this.opts.sleep(tickInterval);
213
+ }
214
+ }
215
+ return { decisions, stopped, delegated, skipped };
216
+ }
217
+ }
218
+ export {
219
+ VisionLoop
220
+ };
@@ -25,7 +25,8 @@ class WikiCompiler {
25
25
  entities: join(this.config.wikiDir, "entities"),
26
26
  concepts: join(this.config.wikiDir, "concepts"),
27
27
  sources: join(this.config.wikiDir, "sources"),
28
- synthesis: join(this.config.wikiDir, "synthesis")
28
+ synthesis: join(this.config.wikiDir, "synthesis"),
29
+ sops: join(this.config.wikiDir, "sops")
29
30
  };
30
31
  }
31
32
  /** Initialize wiki directory structure */
@@ -92,6 +93,8 @@ class WikiCompiler {
92
93
  this.writeArticle(path, this.buildSessionSource(ctx.sessionDigest));
93
94
  created.push(path);
94
95
  }
96
+ const derivedSops = this.generateDerivedSops(ctx.anchors);
97
+ created.push(...derivedSops);
95
98
  this.updateIndex();
96
99
  this.appendLog(
97
100
  `## [${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}] create | full wiki`,
@@ -174,6 +177,8 @@ class WikiCompiler {
174
177
  if (existsSync(filepath)) updated.push(path);
175
178
  else created.push(path);
176
179
  }
180
+ const derivedSops = this.generateDerivedSops(ctx.anchors);
181
+ created.push(...derivedSops);
177
182
  if (created.length > 0 || updated.length > 0) {
178
183
  this.updateIndex();
179
184
  this.appendLog(
@@ -525,6 +530,11 @@ class WikiCompiler {
525
530
  (f) => f.endsWith(".md")
526
531
  ).length;
527
532
  }
533
+ byCategory["entities"] ??= 0;
534
+ byCategory["concepts"] ??= 0;
535
+ byCategory["sources"] ??= 0;
536
+ byCategory["synthesis"] ??= 0;
537
+ byCategory["sops"] ??= 0;
528
538
  const logPath = join(this.dirs.root, "log.md");
529
539
  let lastCompile = null;
530
540
  if (existsSync(logPath)) {
@@ -826,6 +836,98 @@ class WikiCompiler {
826
836
  }
827
837
  return groups;
828
838
  }
839
+ /**
840
+ * Derive Company OS SOPs from recurring frame anchors.
841
+ * Creates lightweight SOP drafts in wiki/sops/ for DECISION, CONSTRAINT, RISK, FACT anchors.
842
+ */
843
+ generateDerivedSops(anchors) {
844
+ const created = [];
845
+ const derivedConfig = [
846
+ {
847
+ type: "DECISION",
848
+ id: 401,
849
+ name: "Decision-derived Process",
850
+ proseId: "E.9",
851
+ objective: "Preserve recurring decisions as repeatable guidance so the team does not re-debate settled questions."
852
+ },
853
+ {
854
+ type: "CONSTRAINT",
855
+ id: 402,
856
+ name: "Constraint-derived Process",
857
+ proseId: "E.10",
858
+ objective: "Preserve recurring constraints as repeatable guidance so the team respects known boundaries."
859
+ },
860
+ {
861
+ type: "RISK",
862
+ id: 403,
863
+ name: "Risk-derived Process",
864
+ proseId: "E.11",
865
+ objective: "Preserve recurring risks as repeatable guidance so the team mitigates them consistently."
866
+ },
867
+ {
868
+ type: "FACT",
869
+ id: 404,
870
+ name: "Fact-derived Process",
871
+ proseId: "E.12",
872
+ objective: "Preserve recurring facts as repeatable guidance so the team operates from shared knowledge."
873
+ }
874
+ ];
875
+ for (const config of derivedConfig) {
876
+ const typeAnchors = anchors.filter((a) => a.type === config.type);
877
+ if (typeAnchors.length === 0) continue;
878
+ const path = `sops/SOP-${config.id}-${this.slugify(config.name)}.md`;
879
+ const items = typeAnchors.slice(-20).map((a) => {
880
+ const date = new Date(a.created_at * 1e3).toISOString().slice(0, 10);
881
+ return `- ${a.text} _(observed ${date} in [[sources/${this.slugify(a.frame_name)}]])_`;
882
+ }).join("\n");
883
+ const article = [
884
+ "---",
885
+ `title: "SOP-${config.id} ${config.name}"`,
886
+ `category: sop`,
887
+ `derived_from: "${config.type} anchors"`,
888
+ `created: ${(/* @__PURE__ */ new Date()).toISOString()}`,
889
+ `updated: ${(/* @__PURE__ */ new Date()).toISOString()}`,
890
+ `tags: [sop, derived, ${config.type.toLowerCase()}]`,
891
+ "---",
892
+ "",
893
+ `# SOP-${config.id} ${config.name}`,
894
+ "",
895
+ "**Owner:** Derived from frame anchors ",
896
+ "**Status:** Active ",
897
+ `**Related PROSE Expectation:** [${config.proseId} ${config.name}](../../docs/specs/COMPANY-OS-PROSE.md)`,
898
+ "",
899
+ "## Objective",
900
+ config.objective,
901
+ "",
902
+ "## Procedure",
903
+ "",
904
+ `1. **Review**`,
905
+ ` - Review the latest ${config.type} anchors below before taking action.`,
906
+ "",
907
+ `2. **Apply**`,
908
+ ` - Treat these ${config.type.toLowerCase()}s as guidance for current and future work.`,
909
+ "",
910
+ `3. **Update**`,
911
+ ` - When a ${config.type.toLowerCase()} changes, record the new state in a frame so this SOP can be regenerated.`,
912
+ "",
913
+ "## Verification",
914
+ "",
915
+ `- Run \`stackmemory company-os audit ${config.type.toLowerCase()}-derived\``,
916
+ `- Expected result: the derived ${config.type.toLowerCase()}s below are reflected in current work.`,
917
+ "",
918
+ "### Derived anchors",
919
+ `${items}`,
920
+ "",
921
+ "## Non-compliance",
922
+ "",
923
+ `Ignoring or overriding these ${config.type.toLowerCase()}s without a new recorded decision is non-compliant.`,
924
+ ""
925
+ ].join("\n");
926
+ this.writeArticle(path, article);
927
+ created.push(path);
928
+ }
929
+ return created;
930
+ }
829
931
  // ── Reading helpers ──
830
932
  readExistingSources() {
831
933
  const sources = [];
@@ -23,6 +23,10 @@ const DEFAULT_DAEMON_CONFIG = {
23
23
  retryAttempts: 3,
24
24
  retryDelay: 3e4
25
25
  },
26
+ github: {
27
+ enabled: false,
28
+ interval: 5
29
+ },
26
30
  maintenance: {
27
31
  enabled: true,
28
32
  interval: 360,
@@ -53,6 +57,51 @@ const DEFAULT_DAEMON_CONFIG = {
53
57
  ignore: ["node_modules", ".git", "dist", "build", ".stackmemory"],
54
58
  debounceMs: 2e3
55
59
  },
60
+ telemetry: {
61
+ enabled: true,
62
+ // opt-out via STACKMEMORY_TELEMETRY=0
63
+ interval: 1440,
64
+ // 24 hours
65
+ maxSnapshots: 90
66
+ // ~3 months of daily
67
+ },
68
+ desirePaths: {
69
+ enabled: true,
70
+ // opt-out via STACKMEMORY_DESIRE_PATHS=0
71
+ interval: 360,
72
+ // scan every 6 hours
73
+ minFrequency: 3,
74
+ // 3+ occurrences to be a pattern
75
+ minSessions: 2,
76
+ // across 2+ distinct sessions
77
+ maxLogSizeBytes: 10 * 1024 * 1024,
78
+ // 10MB rotation
79
+ retentionDays: 30,
80
+ maxSequenceLength: 8,
81
+ autoPromoteThreshold: 0.8,
82
+ autoPromoteMinSessions: 5
83
+ },
84
+ researchStream: {
85
+ enabled: true,
86
+ // opt-out via STACKMEMORY_RESEARCH_STREAM=0
87
+ interval: 360,
88
+ // every 6 hours
89
+ keywords: [
90
+ "agent",
91
+ "ai",
92
+ "llm",
93
+ "mcp",
94
+ "context",
95
+ "memory",
96
+ "orchestration",
97
+ "skill",
98
+ "workflow",
99
+ "automation",
100
+ "browser agent",
101
+ "coding assistant"
102
+ ],
103
+ maxSignalsPerScan: 50
104
+ },
56
105
  heartbeatInterval: 60,
57
106
  // 1 minute
58
107
  inactivityTimeout: 0,
@@ -96,6 +145,7 @@ function loadDaemonConfig() {
96
145
  ...config,
97
146
  context: { ...DEFAULT_DAEMON_CONFIG.context, ...config.context },
98
147
  linear: { ...DEFAULT_DAEMON_CONFIG.linear, ...config.linear },
148
+ github: { ...DEFAULT_DAEMON_CONFIG.github, ...config.github },
99
149
  maintenance: {
100
150
  ...DEFAULT_DAEMON_CONFIG.maintenance,
101
151
  ...config.maintenance
@@ -115,6 +165,7 @@ function saveDaemonConfig(config) {
115
165
  ...config,
116
166
  context: { ...currentConfig.context, ...config.context },
117
167
  linear: { ...currentConfig.linear, ...config.linear },
168
+ github: { ...currentConfig.github, ...config.github },
118
169
  maintenance: { ...currentConfig.maintenance, ...config.maintenance },
119
170
  memory: { ...currentConfig.memory, ...config.memory },
120
171
  fileWatch: { ...currentConfig.fileWatch, ...config.fileWatch }
@@ -128,6 +179,7 @@ function readDaemonStatus() {
128
179
  services: {
129
180
  context: { enabled: false },
130
181
  linear: { enabled: false },
182
+ github: { enabled: false },
131
183
  maintenance: { enabled: false },
132
184
  memory: { enabled: false },
133
185
  fileWatch: { enabled: false }