@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.
- package/LICENSE +131 -64
- package/README.md +107 -24
- package/bin/claude-sm +16 -1
- package/bin/claude-smd +16 -1
- package/bin/codex-smd +16 -1
- package/bin/gemini-sm +16 -1
- package/bin/hermes-sm +21 -0
- package/bin/hermes-smd +21 -0
- package/bin/opencode-sm +16 -1
- package/dist/src/cli/claude-sm.js +266 -84
- package/dist/src/cli/codex-sm.js +225 -33
- package/dist/src/cli/commands/bench.js +209 -2
- package/dist/src/cli/commands/brain.js +206 -0
- package/dist/src/cli/commands/cache.js +126 -0
- package/dist/src/cli/commands/company-os.js +184 -0
- package/dist/src/cli/commands/context.js +5 -0
- package/dist/src/cli/commands/daemon.js +41 -0
- package/dist/src/cli/commands/handoff.js +40 -9
- package/dist/src/cli/commands/onboard.js +70 -3
- package/dist/src/cli/commands/operator.js +127 -0
- package/dist/src/cli/commands/optimize.js +117 -0
- package/dist/src/cli/commands/orchestrate.js +232 -5
- package/dist/src/cli/commands/orchestrator.js +315 -26
- package/dist/src/cli/commands/pack.js +322 -0
- package/dist/src/cli/commands/patterns.js +254 -0
- package/dist/src/cli/commands/portal.js +161 -0
- package/dist/src/cli/commands/scaffold.js +92 -0
- package/dist/src/cli/commands/search.js +40 -1
- package/dist/src/cli/commands/setup.js +178 -11
- package/dist/src/cli/commands/skills.js +10 -1
- package/dist/src/cli/commands/state.js +265 -0
- package/dist/src/cli/commands/sync.js +253 -0
- package/dist/src/cli/commands/tasks.js +130 -1
- package/dist/src/cli/commands/vision.js +221 -0
- package/dist/src/cli/gemini-sm.js +19 -29
- package/dist/src/cli/hermes-sm.js +224 -0
- package/dist/src/cli/index.js +105 -39
- package/dist/src/cli/opencode-sm.js +38 -21
- package/dist/src/cli/utils/determinism-watcher.js +66 -0
- package/dist/src/cli/utils/real-cli-bin.js +116 -0
- package/dist/src/core/brain/brain-store.js +187 -0
- package/dist/src/core/brain/brain-sync.js +193 -0
- package/dist/src/core/brain/index.js +78 -0
- package/dist/src/core/brain/types.js +10 -0
- package/dist/src/core/cache/content-cache.js +238 -0
- package/dist/src/{integrations/diffmem → core/cache}/index.js +5 -5
- package/dist/src/core/cache/token-estimator.js +39 -0
- package/dist/src/core/config/feature-flags.js +2 -6
- package/dist/src/core/context/frame-database.js +79 -27
- package/dist/src/core/context/recursive-context-manager.js +1 -1
- package/dist/src/core/context/rehydration.js +2 -1
- package/dist/src/core/cross-search/cross-project-search.js +269 -0
- package/dist/src/core/cross-search/index.js +10 -0
- package/dist/src/core/database/sqlite-adapter.js +14 -84
- package/dist/src/core/extensions/provider-adapter.js +5 -0
- package/dist/src/core/models/model-router.js +54 -2
- package/dist/src/core/models/provider-pricing.js +58 -4
- package/dist/src/core/monitoring/logger.js +2 -1
- package/dist/src/core/optimization/trace-optimizer.js +413 -0
- package/dist/src/core/patterns/index.js +22 -0
- package/dist/src/core/patterns/pattern-applier.js +39 -0
- package/dist/src/core/patterns/pattern-observer.js +157 -0
- package/dist/src/core/patterns/pattern-store.js +259 -0
- package/dist/src/core/patterns/types.js +19 -0
- package/dist/src/core/provenance/confidence-scorer.js +128 -0
- package/dist/src/core/provenance/index.js +40 -0
- package/dist/src/core/provenance/provenance-store.js +194 -0
- package/dist/src/core/provenance/types.js +82 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
- package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
- package/dist/src/core/session/project-handoff.js +64 -0
- package/dist/src/core/session/session-manager.js +28 -0
- package/dist/src/core/shared-state/canonical-store.js +564 -0
- package/dist/src/core/skill-packs/index.js +18 -0
- package/dist/src/core/skill-packs/parser.js +42 -0
- package/dist/src/core/skill-packs/registry.js +224 -0
- package/dist/src/core/skill-packs/types.js +79 -0
- package/dist/src/core/storage/cloud-sync-manager.js +116 -0
- package/dist/src/core/storage/cloud-sync.js +574 -0
- package/dist/src/core/storage/two-tier-storage.js +5 -1
- package/dist/src/core/tasks/master-tasks-template.js +43 -0
- package/dist/src/core/tasks/md-task-parser.js +138 -0
- package/dist/src/core/trace/trace-event-store.js +282 -0
- package/dist/src/core/vision/index.js +27 -0
- package/dist/src/core/vision/signals.js +79 -0
- package/dist/src/core/vision/types.js +22 -0
- package/dist/src/core/vision/vision-file.js +146 -0
- package/dist/src/core/vision/vision-loop.js +220 -0
- package/dist/src/core/wiki/wiki-compiler.js +103 -1
- package/dist/src/daemon/daemon-config.js +52 -0
- package/dist/src/daemon/services/desire-path-service.js +566 -0
- package/dist/src/daemon/services/github-service.js +126 -0
- package/dist/src/daemon/services/research-stream-service.js +320 -0
- package/dist/src/daemon/services/telemetry-service.js +192 -0
- package/dist/src/daemon/unified-daemon.js +58 -1
- package/dist/src/features/browser/cli-browser-agent.js +417 -0
- package/dist/src/features/browser/stagehand-workflows.js +578 -0
- package/dist/src/features/operator/adapter-factory.js +62 -0
- package/dist/src/features/operator/browser-adapter.js +109 -0
- package/dist/src/features/operator/desktop-adapter.js +125 -0
- package/dist/src/features/operator/index.js +39 -0
- package/dist/src/features/operator/llm-decision.js +137 -0
- package/dist/src/features/operator/operator-logger.js +92 -0
- package/dist/src/features/operator/overnight-runner.js +327 -0
- package/dist/src/features/operator/screen-adapter.js +91 -0
- package/dist/src/features/operator/session-manager.js +127 -0
- package/dist/src/features/operator/state-machine.js +227 -0
- package/dist/src/features/operator/task-queue.js +81 -0
- package/dist/src/features/portal/index.js +26 -0
- package/dist/src/features/portal/server.js +240 -0
- package/dist/src/features/portal/types.js +14 -0
- package/dist/src/features/portal/ui.js +195 -0
- package/dist/src/features/sweep/pty-wrapper.js +13 -5
- package/dist/src/features/tasks/task-aware-context.js +2 -1
- package/dist/src/features/tui/simple-monitor.js +0 -23
- package/dist/src/features/tui/swarm-monitor.js +8 -66
- package/dist/src/features/web/client/hooks/use-socket.js +12 -0
- package/dist/src/{core/merge/index.js → features/web/client/lib/utils.js} +8 -4
- package/dist/src/features/web/client/next-env.d.js +4 -0
- package/dist/src/features/web/client/stores/session-store.js +12 -0
- package/dist/src/features/web/server/gcp-billing.js +76 -0
- package/dist/src/features/web/server/index.js +10 -0
- package/dist/src/features/web/server/spend-calculator.js +228 -0
- package/dist/src/hooks/schemas.js +6 -1
- package/dist/src/integrations/anthropic/client.js +3 -2
- package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
- package/dist/src/integrations/claude-code/subagent-client.js +307 -11
- package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
- package/dist/src/integrations/github/pr-state.js +158 -0
- package/dist/src/integrations/linear/client.js +4 -1
- package/dist/src/integrations/linear/webhook-retry.js +196 -0
- package/dist/src/integrations/linear/webhook-server.js +18 -22
- package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
- package/dist/src/integrations/mcp/handlers/index.js +40 -84
- package/dist/src/integrations/mcp/server.js +542 -641
- package/dist/src/integrations/mcp/tool-alias-registry.js +297 -0
- package/dist/src/integrations/mcp/tool-definitions.js +152 -682
- package/dist/src/mcp/stackmemory-mcp-server.js +571 -231
- package/dist/src/orchestrators/multimodal/determinism.js +244 -0
- package/dist/src/orchestrators/multimodal/harness.js +149 -78
- package/dist/src/orchestrators/multimodal/providers.js +44 -3
- package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
- package/dist/src/utils/hook-installer.js +0 -8
- package/dist/src/utils/process-cleanup.js +1 -7
- package/docs/README.md +42 -0
- package/docs/guides/README_INSTALL.md +208 -0
- package/package.json +27 -9
- package/packs/coding/python-fastapi/instructions.md +60 -0
- package/packs/coding/python-fastapi/pack.yaml +28 -0
- package/packs/coding/typescript-react/instructions.md +47 -0
- package/packs/coding/typescript-react/pack.yaml +28 -0
- package/packs/core/commands/capture.md +32 -0
- package/packs/core/commands/learn.md +73 -0
- package/packs/core/commands/next.md +36 -0
- package/packs/core/commands/restart.md +58 -0
- package/packs/core/commands/restore.md +29 -0
- package/packs/core/commands/start.md +57 -0
- package/packs/core/commands/stop.md +65 -0
- package/packs/core/commands/summary.md +40 -0
- package/packs/core/manifest.json +24 -0
- package/packs/ops/decision-recovery/instructions.md +65 -0
- package/packs/ops/decision-recovery/pack.yaml +89 -0
- package/scripts/claude-code-wrapper.sh +11 -0
- package/scripts/claude-sm-setup.sh +12 -1
- package/scripts/codex-wrapper.sh +11 -0
- package/scripts/git-hooks/branch-context-manager.sh +11 -0
- package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
- package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
- package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
- package/scripts/hooks/cleanup-shell.sh +12 -1
- package/scripts/hooks/task-complete.sh +12 -1
- package/scripts/install-code-execution-hooks.sh +12 -1
- package/scripts/install-sweep-hook.sh +12 -0
- package/scripts/install.sh +11 -0
- package/scripts/opencode-wrapper.sh +11 -0
- package/scripts/portal/cloud-init.yaml +69 -0
- package/scripts/portal/setup.sh +69 -0
- package/scripts/portal/stackmemory-portal.service +34 -0
- package/scripts/setup-claude-integration.sh +12 -1
- package/scripts/smoke-init-db.sh +23 -0
- package/scripts/stackmemory-daemon.sh +11 -0
- package/scripts/verify-dist.cjs +11 -4
- package/dist/src/cli/commands/ralph.js +0 -1053
- package/dist/src/cli/commands/team.js +0 -168
- package/dist/src/core/context/shared-context-layer.js +0 -620
- package/dist/src/core/context/stack-merge-resolver.js +0 -748
- package/dist/src/core/merge/conflict-detector.js +0 -430
- package/dist/src/core/merge/resolution-engine.js +0 -557
- package/dist/src/core/merge/stack-diff.js +0 -531
- package/dist/src/core/merge/unified-merge-resolver.js +0 -302
- package/dist/src/hooks/diffmem-hooks.js +0 -376
- package/dist/src/integrations/diffmem/client.js +0 -208
- package/dist/src/integrations/diffmem/config.js +0 -14
- package/dist/src/integrations/greptile/client.js +0 -101
- package/dist/src/integrations/greptile/config.js +0 -14
- package/dist/src/integrations/greptile/index.js +0 -11
- package/dist/src/integrations/mcp/handlers/cord-handlers.js +0 -397
- package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
- package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
- package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
- package/dist/src/integrations/mcp/handlers/team-handlers.js +0 -211
- package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
- package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -391
- package/dist/src/integrations/ralph/index.js +0 -17
- package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -435
- package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
- package/dist/src/integrations/ralph/loopmax.js +0 -488
- package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
- package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
- package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
- package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
- package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
- package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
- package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
- package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
- package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
- package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1007
- package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
- package/scripts/ralph-loop-implementation.js +0 -404
- /package/dist/src/core/{merge → cache}/types.js +0 -0
- /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
- /package/dist/src/{integrations/greptile/types.js → core/trace/trace-event.js} +0 -0
- /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 }
|