Commit 4d22836
feat(webhook): add persistent retry with exponential backoff (#19)
* feat(teleop): add native voice control prototype
* feat(cli): add scaffold command for Company OS folder structure
stackmemory scaffold creates company/, wiki/, skills/, clients/, raw/,
and .stackmemory/config.yml. Enables local context management with
file-based skill rot detection and tenant isolation.
* feat(daemon): add opt-out telemetry service
New DaemonTelemetryService collects anonymous usage snapshots:
- Daemon health (uptime, context saves, memory triggers, errors)
- Session counts (total heartbeats, active now)
- Skill audit entries, handoff counts
- No PII — instance ID is random hex
Runs daily (default 24h interval, first at boot+30s).
Stores rolling 90-snapshot history in ~/.stackmemory/telemetry.json.
Opt out: STACKMEMORY_TELEMETRY=0 or telemetry.enabled: false in config.
* feat(hooks): add self-healing daemon health check for SessionStart
* feat(daemon): add desire-path detector — auto-discover workflows, suggest skills
Three-component system in DaemonDesirePathService:
1. ActionStreamLogger — PostToolUse hook captures tool:target pairs
to ~/.stackmemory/desire-paths/action-stream.jsonl (no data/content)
2. PatternDetector — sliding window extracts repeated sequences,
filters by min 3 occurrences across 2+ sessions, scores by freq×sessions
3. SkillSuggester — generates skill.md files from top patterns with
inputs/outputs inferred from sequence endpoints
- 10MB JSONL rotation, 10K entry scan cap for performance
- Opt out: STACKMEMORY_DESIRE_PATHS=0 or desirePaths.enabled: false
- Scans every 6h, first at boot+2m
- Suggestions written to ~/.stackmemory/desire-paths/suggestions/
- 3 adversarial review rounds: fixed separator injection, added scan cap,
improved skill naming with target directory context
* fix(desire-paths): adaptive backoff — hourly when active, exponential to 12h when idle
* feat(cli): add hermes-sm wrapper with StackMemory integration
- Auto-starts daemon on session boot
- Writes session heartbeats for telemetry tracking
- Restores handoff context from previous sessions
- Sets STACKMEMORY_SESSION env for desire-path hook
- Determinism watcher + tracing
- bin/hermes-sm and bin/hermes-smd registered in package.json
* feat(desire-paths): auto-promote skills above 0.8 confidence + 5 sessions
* feat(daemon): add research stream scanner for market signal detection
* fix(test): replace bun:test import with vitest in desire-path-service test
* feat(tokens): replace char/4 heuristic with js-tiktoken (cl100k_base)
Centralizes token estimation across 14 files through
src/core/cache/token-estimator.ts and packages/sdk/src/token-estimator.ts.
Lazy-loads cl100k_base encoder with char/4 fallback if WASM fails.
Also ports context-budget hook to codex-sm exit handler for
compact/restart nudges matching Claude Code behavior.
* feat(skill-packs): add content licenses (CC-BY-4.0) to registry metadata
Skills are often prompt text (content) not code — content licenses like
CC-BY-4.0 fit better than MIT for these. Adds KnownLicenseSchema enum
with both code (MIT, Apache-2.0, ISC, BSD) and content (CC-BY-4.0,
CC-BY-SA-4.0, CC0-1.0) licenses while keeping the field open for custom
SPDX identifiers.
* feat(tasks): add local-first master-tasks.md task management
Markdown table parser + CLI commands + MCP tools for local-first task
steering. Tasks live in master-tasks.md, optionally sync to Linear/GH.
- Parser: parse/serialize/update/add/getNext for pipe-delimited md tables
- CLI: stackmemory tasks init/md list/md next/md add/md update
- MCP: get_next_master_task, update_master_task, create_master_task
- 19 tests covering parse, round-trip, priority sorting, file ops
* feat(hooks): token optimization — dedup escalation, auto-route, prewarm, script-suggest
- dedup-reads: escalate to [STOP] at 5+ reads (was soft-only at 3+)
- desire-path-hook: auto-route Bash→Glob/Read/Grep with inline suggestions
- prewarm-tools: SessionStart hook emits top deferred tool pre-fetch hint
- script-suggest: detects multi-tool patterns matching existing scripts
* feat(bench): add hook benchmark script + baseline report
Replays 7,589 action-stream entries through hook logic.
Result: 324K token savings projected (22% waste reduction).
* feat(hooks): weekly skill-mine reminder on SessionStart
Emits reminder when >7 days since last mine and new suggested
skills exist. Points to /workflow-skill-miner.
* fix(desire-paths): filter trivial patterns from suggestions + auto-delete
- Skip patterns with <2 unique tools or <3 steps in generateSuggestions()
- Add cleanTrivialSuggestion() to auto-delete stale suggestion files
- Remove duplicate quality gate from autoPromote (filtering now upstream)
- Prevents bloat: 19/20 current patterns were trivial (git×2, Edit×3, etc.)
* feat(subagent): design delegation — Claude-first routing for frontend/UI tasks
Design tasks bypass subscription-first cascade (Codex→Grok→API) and route
directly to Claude CLI, which excels at creative UI/UX decisions.
- Add 'design' task type to SubagentRequest, TaskType, ModelRouterConfig
- Add forceProvider field for explicit provider override
- Add design prompt (opinionated, production-ready, no-ask-just-decide)
- Add delegateDesign() convenience method for wrapper CLIs
* docs: rewrite CLAUDE.md as tool-agnostic agent guide
Consolidate from StackMemory-specific config to a generic agent
reference covering stack, structure, commands, and key patterns.
* feat(hooks): project-aware prewarm tool cache
Filter action-stream by current project directory so prewarm
suggestions are scoped to the repo you're working in. Falls back
to global stats when no project-specific data exists.
* feat(hooks): memory-loader SessionStart hook
Reads MEMORY.md index at session start, scores entries by relevance
to current project context, and surfaces the most useful memories.
* feat(hooks): image preprocessing + MCP vision extraction
image-preprocess: PreToolUse hook that intercepts Read calls on image
files and routes them through vision-capable models.
image-extract-mcp: stdio MCP server providing a describe_image tool
for text extraction from images via vision model APIs.
* feat(gepa): daemon watcher + session hook updates
daemon.js: persistent file watcher for all GEPA targets — triggers
optimization on CLAUDE.md changes.
Session hook and .before-optimize baseline updated for current
optimization state.
* chore(gepa): gen-001 variant updates from optimization run
* feat(browser): Stagehand workflow capture, cache, replay + benchmark harness
End-to-end integration bridging Stagehand browser automation with
StackMemory's desire-path system for workflow discovery and replay.
- StagehandWorkflowCapture: wraps act/extract/observe, emits to action-stream
- WorkflowCache: persists workflows, bridges to desire-path patterns.json
- WorkflowReplayer: cached (0 tokens), AI (self-healing), hybrid modes
- WorkflowBenchmark: compare stagehand-ai vs cached vs playwright-code
- 4 MCP tools: workflow_list, workflow_get, workflow_replay, workflow_benchmarks
- Benchmark script with 3 test workflows (GitHub, HN, NPM)
Stagehand is a peer dependency — not required for core functionality.
* feat(browser): CLI browser agent + benchmark updates
CliBrowserAgent: Playwright + claude/codex CLI hybrid that routes
AI understanding through subscription CLIs instead of direct API.
Falls back to Anthropic API when CLI hooks interfere.
- Playwright handles browser control (fast, deterministic)
- claude --print / codex -q handles extraction/action interpretation
- Results cached locally for zero-LLM replay on subsequent runs
- Benchmark script supports --cli mode vs --api mode
Known: claude --print triggers SessionEnd hooks that timeout.
TODO: fix hook interference or add CLAUDE_CODE_SKIP_HOOKS support.
* fix(hooks): add DISABLE_HOOKS skip guard to all Stop/SessionEnd hooks
When DISABLE_HOOKS=1 env var is set, all session lifecycle hooks
exit immediately. Prevents timeout/cancellation when claude --print
is invoked as a subprocess (e.g., from CliBrowserAgent).
Hooks patched: chime-on-stop.sh, stop-checkpoint.js, session-rescue.sh,
wiki-update.js, token-meter-finalize.js, gepa-session-hook.js
* fix(browser): accept CLI output on non-zero exit from hook failures
claude --print produces valid output before SessionEnd hooks fire.
Exit 143 from hook cancellation shouldn't reject — check stdout
content instead of exit code.
* chore(deps): add stagehand + playwright for browser workflows
* docs(research): agent-readable web standards landscape 2026
* chore(gepa): update generation variants + daemon state
* feat(mcp): wire workflow tools into main MCP server
Register workflow_list, workflow_get, workflow_replay, workflow_benchmarks
in MCPToolDefinitions and MCPHandlerFactory. Routes through handleWorkflowTool
from browser/workflow-mcp-tools.ts.
* feat(hooks): add cd-thrash, linear-dedup, and bash-dominance guardrails
- cd-thrash-guard: warns on 3+ cd commands in 10 tool calls
- linear-dedup: detects duplicate Linear API calls within 60s
- bash-dominance-guard: suggests Read/Grep/Glob/Edit over Bash equivalents
* fix(benchmark): fix NPM selector timeout + use page.evaluate extraction
* chore(gepa): update daemon state + generation variants
* chore(gepa): update hook state + scores
* chore(gepa): auto-optimizer state + eval results
* chore(gepa): daemon state update
* chore(gepa): auto-optimizer state update
* feat(skill-packs): add ops/log-investigation pack
Distributable investigation skill teaching agents to debug production
issues from structured wide-format logs. Encodes the tenant-context +
domain-extras + timeline-reconstruction pattern.
* fix(tests): update token estimator + subagent routing test expectations
Token estimator tests assumed ceil(length/4) heuristic but implementation
now uses js-tiktoken (cl100k_base). Subagent routing tests failed because
codex CLI is installed locally, causing isCodexAvailable() to short-circuit
multiProvider/batch/Kimi paths — fixed by spying on private methods.
* feat(tracing): instrument MCP server with Raindrop Workshop
Every MCP tool call now emits begin/finish traces to Raindrop Workshop
when RAINDROP_LOCAL_DEBUGGER env is set. Conditional — zero overhead
when env var is absent. Flush on SIGINT shutdown.
* chore(gepa): auto-optimizer state update
* chore: add Raindrop Workshop agent config files
* refactor(mcp): extract handleTool from IIFE wrapper
Replace async IIFE wrapping the tool dispatch switch with a named
handleTool() function. Removes one indentation level from ~500 lines,
makes the Raindrop tracing wrapper cleaner, and shrinks the bundle.
* feat(operator): autonomous Claude Code driver via screen control
Three adapter modes behind a unified ScreenAdapter interface:
- TmuxAdapter: reads pane buffer as text, sends keys (CLI, no API needed)
- DesktopAdapter: macOS screenshots + AppleScript + Haiku VLM
- BrowserAdapter: Playwright DOM reads for claude.ai/code web app
Rule-based state machine detects: IDLE, WORKING, PERMISSION_PROMPT,
ERROR, RATE_LIMITED, STUCK, SESSION_ENDED from screen content.
LLM decision layer (Haiku) handles ambiguous states and generates
nudges for stuck sessions instead of blind restarts.
CLI: stackmemory operator start/stop/status/attach
- Drains master-tasks.md queue overnight on Max plan
- Auto-approves permission prompts, exponential backoff on rate limits
- JSONL logging + checkpoint file for monitoring
- 31 tests passing
* fix(operator): nudge-then-escalate for stuck sessions + barrel export
- STUCK now nudges twice before marking blocked (was: immediate block)
- Track nudgeCount per task in checkpoint, reset on new task
- Fix ScreenshotAdapter adapterType to match union type
- Add index.ts barrel export for clean imports
- 32 tests passing
* feat(patterns): first-party learned patterns system (observe → learn → apply)
Repackages the external instincts/continuous-learning concept into
StackMemory as a native feature backed by SQLite.
New modules:
- PatternStore: CRUD with confidence scoring, decay, pruning
- PatternObserver: extracts patterns from trace events at session end
(tool sequences, error→fix pairs, tool preferences)
- PatternApplier: surfaces relevant patterns in context retrieval
- CLI: stackmemory patterns list|learn|stats|prune|export|import
Schema: adds `patterns` table with domain, trigger, action,
confidence scoring (0.3→0.85 based on observation count),
project-scoping, and weekly confidence decay.
16 tests passing.
* feat(patterns): add promote, projects, evolve commands — full CL-v2 parity
Fills 3 feature gaps vs continuous-learning-v2:
- promote: project→global (manual or auto-detect cross-project patterns)
- projects: list projects with pattern counts
- evolve: cluster related patterns, identify skill/command candidates
PatternStore gains: promote(), projects(), promotionCandidates(), findClusters()
CL-v2 for stackmemory is now retired — observer was already disabled,
no hooks registered. Patterns system is the native replacement.
* chore: handoff checkpoint on main
* chore: handoff checkpoint on main
* chore: handoff checkpoint on main
* fix(test): skip OpenRouter live tests on invalid/missing API key
Tests already skipped when OPENROUTER_API_KEY env var is unset, but
still failed with 401 when the key existed but was expired or invalid.
Now catch auth errors (401/403) and skip gracefully via ctx.skip().
* feat(webhook): add persistent retry with exponential backoff
Replace in-memory webhook event queue with SQLite-backed delivery queue.
Failed webhook events are now retried up to 5 times with exponential
backoff (1s, 2s, 4s, 8s, 16s, capped at 300s) and jitter. Deliveries
persist across process restarts.
- WebhookDeliveryQueue: SQLite persistence, atomic claim, background worker
- Reuses existing calculateBackoff() from core/errors/recovery.ts
- Health endpoint now returns delivery stats by status
- 11 tests covering enqueue, retry, dead letter, concurrency, stats
* fix(lint): resolve 46 pre-existing eslint errors across 8 files
- Fix prettier formatting in hermes-sm, daemon-config, research-stream-service, telemetry-service
- Add eslint-disable for dynamic require() in operator, adapter-factory
- Replace inline require() with top-level imports in operator-logger, subagent-client
* fix(storage): make redis import lazy in two-tier-storage
Redis is optional (only needed for remote tier). The hard import
crashed when redis wasn't installed, causing test suite failures.
Now uses lazy require() with graceful fallback.
* chore: handoff checkpoint on feature/webhook-retry-backoff
* fix: auto-load nvm in all scripts to prevent Node version mismatch
Ensures every bash script that invokes stackmemory or node loads
the correct Node version from .nvmrc before executing. Prevents
better-sqlite3 NODE_MODULE_VERSION errors when hooks, wrappers,
or daemons run in contexts without nvm initialized (git GUIs,
IDE integrations, background processes, subprocesses).
* docs: mark webhook retry backoff acceptance criteria as complete
---------
Co-authored-by: StackMemory Bot (CLI) <bot@stackmemory.ai>1 parent 64a3674 commit 4d22836
1,186 files changed
Lines changed: 63491 additions & 775 deletions
File tree
- .claude/skills
- .codex
- .cursor
- docs
- plans
- research
- scripts
- conductor
- gepa
- cache
- generations
- gen-000
- gen-001
- gen-002
- gen-003
- gen-004
- hooks
- results
- git-hooks
- hooks
- testing
- skill-packs/ops/log-investigation
- src
- cli
- commands
- utils
- __tests__
- core
- brain/__tests__
- cache/__tests__
- context
- extensions/__tests__
- models
- __tests__
- patterns
- __tests__
- storage
- vision/__tests__
- daemon/services
- features
- browser
- operator
- __tests__
- portal/__tests__
- hooks
- integrations
- claude-code
- __tests__
- linear
- __tests__
- mcp
- handlers
- __tests__
- mcp
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
2 | 11 | | |
3 | 12 | | |
4 | 13 | | |
5 | 14 | | |
6 | 15 | | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
36 | 25 | | |
37 | 26 | | |
38 | 27 | | |
| |||
69 | 58 | | |
70 | 59 | | |
71 | 60 | | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
104 | 66 | | |
105 | 67 | | |
106 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
107 | 76 | | |
108 | | - | |
109 | | - | |
110 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
111 | 83 | | |
112 | | - | |
| 84 | + | |
113 | 85 | | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
| 86 | + | |
| 87 | + | |
119 | 88 | | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
| 89 | + | |
124 | 90 | | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
130 | 96 | | |
131 | | - | |
| 97 | + | |
132 | 98 | | |
133 | | - | |
| 99 | + | |
134 | 100 | | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
141 | 107 | | |
142 | | - | |
| 108 | + | |
143 | 109 | | |
144 | | - | |
145 | | - | |
146 | | - | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
147 | 119 | | |
148 | 120 | | |
149 | 121 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
0 commit comments