@ekkos/cli 0.3.3 → 1.0.1

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 (81) hide show
  1. package/README.md +57 -0
  2. package/dist/agent/daemon.d.ts +27 -0
  3. package/dist/agent/daemon.js +254 -29
  4. package/dist/agent/health-check.d.ts +35 -0
  5. package/dist/agent/health-check.js +243 -0
  6. package/dist/agent/pty-runner.d.ts +1 -0
  7. package/dist/agent/pty-runner.js +6 -1
  8. package/dist/capture/transcript-repair.d.ts +1 -0
  9. package/dist/capture/transcript-repair.js +12 -1
  10. package/dist/commands/agent.d.ts +6 -0
  11. package/dist/commands/agent.js +244 -0
  12. package/dist/commands/dashboard.d.ts +25 -0
  13. package/dist/commands/dashboard.js +1175 -0
  14. package/dist/commands/run.d.ts +3 -0
  15. package/dist/commands/run.js +503 -350
  16. package/dist/commands/setup-remote.js +146 -37
  17. package/dist/commands/swarm-dashboard.d.ts +20 -0
  18. package/dist/commands/swarm-dashboard.js +735 -0
  19. package/dist/commands/swarm-setup.d.ts +10 -0
  20. package/dist/commands/swarm-setup.js +956 -0
  21. package/dist/commands/swarm.d.ts +46 -0
  22. package/dist/commands/swarm.js +441 -0
  23. package/dist/commands/test-claude.d.ts +16 -0
  24. package/dist/commands/test-claude.js +156 -0
  25. package/dist/commands/usage/blocks.d.ts +8 -0
  26. package/dist/commands/usage/blocks.js +60 -0
  27. package/dist/commands/usage/daily.d.ts +9 -0
  28. package/dist/commands/usage/daily.js +96 -0
  29. package/dist/commands/usage/dashboard.d.ts +8 -0
  30. package/dist/commands/usage/dashboard.js +104 -0
  31. package/dist/commands/usage/formatters.d.ts +41 -0
  32. package/dist/commands/usage/formatters.js +147 -0
  33. package/dist/commands/usage/index.d.ts +13 -0
  34. package/dist/commands/usage/index.js +87 -0
  35. package/dist/commands/usage/monthly.d.ts +8 -0
  36. package/dist/commands/usage/monthly.js +66 -0
  37. package/dist/commands/usage/session.d.ts +11 -0
  38. package/dist/commands/usage/session.js +193 -0
  39. package/dist/commands/usage/weekly.d.ts +9 -0
  40. package/dist/commands/usage/weekly.js +61 -0
  41. package/dist/deploy/instructions.d.ts +5 -2
  42. package/dist/deploy/instructions.js +11 -8
  43. package/dist/index.js +256 -20
  44. package/dist/lib/tmux-scrollbar.d.ts +14 -0
  45. package/dist/lib/tmux-scrollbar.js +296 -0
  46. package/dist/lib/usage-parser.d.ts +95 -5
  47. package/dist/lib/usage-parser.js +416 -71
  48. package/dist/utils/log-rotate.d.ts +18 -0
  49. package/dist/utils/log-rotate.js +74 -0
  50. package/dist/utils/platform.d.ts +2 -0
  51. package/dist/utils/platform.js +3 -1
  52. package/dist/utils/session-binding.d.ts +5 -0
  53. package/dist/utils/session-binding.js +46 -0
  54. package/dist/utils/state.js +4 -0
  55. package/dist/utils/verify-remote-terminal.d.ts +10 -0
  56. package/dist/utils/verify-remote-terminal.js +415 -0
  57. package/package.json +16 -11
  58. package/templates/CLAUDE.md +135 -23
  59. package/templates/cursor-hooks/after-agent-response.sh +0 -0
  60. package/templates/cursor-hooks/before-submit-prompt.sh +0 -0
  61. package/templates/cursor-hooks/stop.sh +0 -0
  62. package/templates/ekkos-manifest.json +5 -5
  63. package/templates/hooks/assistant-response.sh +0 -0
  64. package/templates/hooks/lib/contract.sh +43 -31
  65. package/templates/hooks/lib/count-tokens.cjs +86 -0
  66. package/templates/hooks/lib/ekkos-reminders.sh +98 -0
  67. package/templates/hooks/lib/state.sh +53 -1
  68. package/templates/hooks/session-start.sh +0 -0
  69. package/templates/hooks/stop.sh +150 -388
  70. package/templates/hooks/user-prompt-submit.sh +353 -443
  71. package/templates/plan-template.md +0 -0
  72. package/templates/spec-template.md +0 -0
  73. package/templates/windsurf-hooks/README.md +212 -0
  74. package/templates/windsurf-hooks/hooks.json +9 -2
  75. package/templates/windsurf-hooks/install.sh +148 -0
  76. package/templates/windsurf-hooks/lib/contract.sh +2 -0
  77. package/templates/windsurf-hooks/post-cascade-response.sh +251 -0
  78. package/templates/windsurf-hooks/pre-user-prompt.sh +435 -0
  79. package/templates/windsurf-skills/ekkos-memory/SKILL.md +219 -0
  80. package/LICENSE +0 -21
  81. package/templates/windsurf-hooks/before-submit-prompt.sh +0 -238
@@ -0,0 +1,435 @@
1
+ #!/bin/bash
2
+ # ═══════════════════════════════════════════════════════════════════════════
3
+ # ekkOS_ Hook: pre_user_prompt (Windsurf Cascade) - RETRIEVE + INJECT + CONTRACT
4
+ #
5
+ # ARCHITECTURE: Dumb Hook, Smart Backend
6
+ # ═══════════════════════════════════════════════════════════════════════════
7
+ # This hook runs BEFORE the user prompt is processed by Cascade.
8
+ # It is THE CANONICAL retrieval path for Windsurf Cascade.
9
+ #
10
+ # FEATURES:
11
+ # - Proactive pattern retrieval from all memory layers
12
+ # - Endless Context automatic restoration
13
+ # - Time Machine "Continue from here" support
14
+ # - STRICT mode support (block on failed retrieval)
15
+ # - Golden Loop compliance: Turn contract + PatternGuard + Footer
16
+ #
17
+ # Windsurf Hook Input:
18
+ # {
19
+ # "agent_action_name": "pre_user_prompt",
20
+ # "trajectory_id": "...",
21
+ # "execution_id": "...",
22
+ # "timestamp": "...",
23
+ # "tool_info": {"user_prompt": "..."}
24
+ # }
25
+ #
26
+ # Output Format:
27
+ # {"continue": true, "user_message": "augmented prompt"}
28
+ # ═══════════════════════════════════════════════════════════════════════════
29
+
30
+ set +e # Don't exit on errors - be bulletproof
31
+
32
+ # Get project root
33
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
34
+ PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
35
+ STATE_DIR="$PROJECT_ROOT/.windsurf/state"
36
+ mkdir -p "$STATE_DIR" 2>/dev/null || true
37
+
38
+ # Load turn contract library
39
+ if [ -f "$SCRIPT_DIR/lib/contract.sh" ]; then
40
+ source "$SCRIPT_DIR/lib/contract.sh" 2>/dev/null || true
41
+ fi
42
+
43
+ # Fallback functions if library didn't load
44
+ if ! command -v write_turn_contract >/dev/null 2>&1; then
45
+ write_turn_contract() { return 0; }
46
+ fi
47
+ if ! command -v generate_query_hash >/dev/null 2>&1; then
48
+ generate_query_hash() { echo "$(date +%s)"; }
49
+ fi
50
+ if ! command -v is_strict_mode >/dev/null 2>&1; then
51
+ is_strict_mode() { [ "${EKKOS_STRICT:-0}" = "1" ]; }
52
+ fi
53
+ if ! command -v get_strict_blocker_message >/dev/null 2>&1; then
54
+ get_strict_blocker_message() { echo "⛔ EKKOS_STRICT: Retrieval failed - DO NOT ANSWER"; }
55
+ fi
56
+
57
+ # ═══════════════════════════════════════════════════════════════════════════
58
+ # Read JSON input from stdin (Windsurf format)
59
+ # ═══════════════════════════════════════════════════════════════════════════
60
+ INPUT=$(cat)
61
+
62
+ # Extract prompt text from Windsurf format
63
+ PROMPT_TEXT=$(echo "$INPUT" | jq -r '.tool_info.user_prompt // ""' 2>/dev/null || echo "")
64
+
65
+ # Extract trajectory/session info
66
+ TRAJECTORY_ID=$(echo "$INPUT" | jq -r '.trajectory_id // ""' 2>/dev/null || echo "")
67
+ EXECUTION_ID=$(echo "$INPUT" | jq -r '.execution_id // ""' 2>/dev/null || echo "")
68
+
69
+ # Generate session ID if not provided
70
+ if [ -z "$TRAJECTORY_ID" ] || [ "$TRAJECTORY_ID" = "null" ]; then
71
+ TRAJECTORY_ID="windsurf-$(date +%s)-$$"
72
+ fi
73
+
74
+ SESSION_ID="$TRAJECTORY_ID"
75
+
76
+ # Skip if empty prompt
77
+ if [ -z "$PROMPT_TEXT" ] || [ "$PROMPT_TEXT" = "null" ]; then
78
+ echo '{"continue": true}'
79
+ exit 0
80
+ fi
81
+
82
+ # Generate query hash for contract
83
+ QUERY_HASH=$(generate_query_hash "$PROMPT_TEXT")
84
+
85
+ # ═══════════════════════════════════════════════════════════════════════════
86
+ # Load auth token - PORTABLE: Check 3 sources in priority order
87
+ # ═══════════════════════════════════════════════════════════════════════════
88
+ EKKOS_CONFIG="$HOME/.ekkos/config.json"
89
+ AUTH_TOKEN=""
90
+ USER_ID=""
91
+
92
+ # 1. First try ~/.ekkos/config.json (set by VS Code extension - most portable)
93
+ # Prefer hookApiKey (scoped key for hooks) over apiKey (legacy)
94
+ if [ -f "$EKKOS_CONFIG" ]; then
95
+ AUTH_TOKEN=$(jq -r '.hookApiKey // .apiKey // ""' "$EKKOS_CONFIG" 2>/dev/null || echo "")
96
+ USER_ID=$(jq -r '.userId // ""' "$EKKOS_CONFIG" 2>/dev/null || echo "")
97
+ fi
98
+
99
+ # 2. Then try project .env.local (for developers)
100
+ if [ -z "$AUTH_TOKEN" ] && [ -f "$PROJECT_ROOT/.env.local" ]; then
101
+ AUTH_TOKEN=$(grep -E "^SUPABASE_SECRET_KEY=" "$PROJECT_ROOT/.env.local" | cut -d'=' -f2- | tr -d '"' | tr -d "'" | tr -d '\r')
102
+ fi
103
+
104
+ # 3. Finally try environment variable
105
+ if [ -z "$AUTH_TOKEN" ]; then
106
+ AUTH_TOKEN="${SUPABASE_SECRET_KEY:-}"
107
+ fi
108
+
109
+ # Track retrieval status
110
+ RETRIEVAL_OK="false"
111
+ RETRIEVED_PATTERN_IDS=""
112
+ RETRIEVED_DIRECTIVE_IDS=""
113
+
114
+ # Skip if no auth
115
+ if [ -z "$AUTH_TOKEN" ]; then
116
+ # STRICT MODE: Block turn if no auth
117
+ if is_strict_mode; then
118
+ BLOCKER_MSG=$(get_strict_blocker_message)
119
+ write_turn_contract "$SESSION_ID" "false" "windsurf" "" "" "$QUERY_HASH" "$PROJECT_ROOT"
120
+ echo "{\"continue\": false, \"user_message\": $(echo "$BLOCKER_MSG" | jq -R -s .)}"
121
+ exit 0
122
+ fi
123
+
124
+ write_turn_contract "$SESSION_ID" "false" "windsurf" "" "" "$QUERY_HASH" "$PROJECT_ROOT"
125
+ echo '{"continue": true, "user_message": "[ekkOS] No auth token. Run ekkOS: Connect in VS Code."}'
126
+ exit 0
127
+ fi
128
+
129
+ # Cloud API
130
+ MEMORY_API_URL="https://mcp.ekkos.dev"
131
+
132
+ # ═══════════════════════════════════════════════════════════════════════════
133
+ # [ENDLESS CONTEXT] Automatic context restoration (like Claude Code)
134
+ # ═══════════════════════════════════════════════════════════════════════════
135
+ # Cascade loses context silently - we detect and restore automatically.
136
+ # Triggers: new session, time gap, or explicit request.
137
+ # ═══════════════════════════════════════════════════════════════════════════
138
+ ENDLESS_CONTEXT=""
139
+ SESSION_FLAG="$STATE_DIR/session-active.flag"
140
+ LAST_INTERACTION_FILE="$STATE_DIR/last-interaction.txt"
141
+ TURN_COUNTER_FILE="$STATE_DIR/cascade-turn.txt"
142
+
143
+ # Get current turn count
144
+ CURRENT_TURN=1
145
+ if [ -f "$TURN_COUNTER_FILE" ]; then
146
+ CURRENT_TURN=$(cat "$TURN_COUNTER_FILE" 2>/dev/null || echo "0")
147
+ CURRENT_TURN=$((CURRENT_TURN + 1))
148
+ fi
149
+ echo "$CURRENT_TURN" > "$TURN_COUNTER_FILE" 2>/dev/null || true
150
+
151
+ # Determine if we should restore context
152
+ SHOULD_RESTORE_CONTEXT=false
153
+ RESTORE_REASON=""
154
+
155
+ # 1. First turn of new session
156
+ if [ ! -f "$SESSION_FLAG" ]; then
157
+ SHOULD_RESTORE_CONTEXT=true
158
+ RESTORE_REASON="new session"
159
+ fi
160
+
161
+ # 2. Time gap detection (context likely compacted)
162
+ if [ -f "$LAST_INTERACTION_FILE" ]; then
163
+ LAST_INTERACTION=$(cat "$LAST_INTERACTION_FILE" 2>/dev/null || echo "0")
164
+ NOW=$(date +%s)
165
+ SECONDS_AGO=$((NOW - LAST_INTERACTION))
166
+
167
+ # 10 minutes = likely new conversation / compacted
168
+ if [ "$SECONDS_AGO" -gt 600 ]; then
169
+ SHOULD_RESTORE_CONTEXT=true
170
+ RESTORE_REASON="10min gap"
171
+ rm -f "$SESSION_FLAG" 2>/dev/null || true
172
+ CURRENT_TURN=1
173
+ echo "1" > "$TURN_COUNTER_FILE" 2>/dev/null || true
174
+ fi
175
+ fi
176
+
177
+ # 3. User explicitly asks
178
+ PROMPT_LOWER=$(echo "$PROMPT_TEXT" | tr '[:upper:]' '[:lower:]')
179
+ if echo "$PROMPT_LOWER" | grep -qE "(recall|where were we|what were we|continue|restore context|load context|what did we)"; then
180
+ SHOULD_RESTORE_CONTEXT=true
181
+ RESTORE_REASON="user request"
182
+ fi
183
+
184
+ # Update last interaction
185
+ date +%s > "$LAST_INTERACTION_FILE" 2>/dev/null || true
186
+
187
+ # Auto-restore when triggered
188
+ if [ "$SHOULD_RESTORE_CONTEXT" = true ] && [ -n "$USER_ID" ]; then
189
+ # Fetch recent turns from L2
190
+ RECENT_RESPONSE=$(curl -s -X POST "$MEMORY_API_URL/api/v1/turns/recall" \
191
+ -H "Authorization: Bearer $AUTH_TOKEN" \
192
+ -H "Content-Type: application/json" \
193
+ -d "{\"user_id\": \"$USER_ID\", \"last_n\": 10, \"format\": \"summary\"}" \
194
+ --connect-timeout 3 \
195
+ --max-time 5 2>/dev/null || echo '{}')
196
+
197
+ RECENT_COUNT=$(echo "$RECENT_RESPONSE" | jq '.turns // [] | length' 2>/dev/null || echo "0")
198
+
199
+ if [ "$RECENT_COUNT" -gt 0 ]; then
200
+ RECENT_CONTEXT=$(echo "$RECENT_RESPONSE" | jq -r '.formatted_context // ""' 2>/dev/null)
201
+ TOTAL_TURNS=$(echo "$RECENT_RESPONSE" | jq -r '.total_turns_in_session // 0' 2>/dev/null)
202
+
203
+ if [ -n "$RECENT_CONTEXT" ] && [ "$RECENT_CONTEXT" != "null" ]; then
204
+ ENDLESS_CONTEXT="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
205
+ 🧠 ENDLESS CONTEXT · Auto-restored ($RESTORE_REASON)
206
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
207
+
208
+ $RECENT_CONTEXT
209
+
210
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
211
+ Turn $CURRENT_TURN · Session has $TOTAL_TURNS turns saved
212
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
213
+
214
+ # Mark session as active
215
+ echo "$(date +%s)" > "$SESSION_FLAG" 2>/dev/null || true
216
+ fi
217
+ fi
218
+ fi
219
+
220
+ # ═══════════════════════════════════════════════════════════════════════════
221
+ # [TIME MACHINE] Check for pending "Continue from here" requests
222
+ # ═══════════════════════════════════════════════════════════════════════════
223
+ TIME_MACHINE_CONTEXT=""
224
+ TIME_MACHINE_FLAG="$STATE_DIR/time-machine-consumed.flag"
225
+
226
+ # Only check if we haven't already consumed a request this session
227
+ if [ -n "$USER_ID" ] && [ ! -f "$TIME_MACHINE_FLAG" ]; then
228
+ PENDING_RESPONSE=$(curl -s -X GET "$MEMORY_API_URL/api/v1/context/restore-request/pending?user_id=$USER_ID" \
229
+ -H "Authorization: Bearer $AUTH_TOKEN" \
230
+ --connect-timeout 2 \
231
+ --max-time 3 2>/dev/null || echo '{}')
232
+
233
+ IS_PENDING=$(echo "$PENDING_RESPONSE" | jq -r '.pending // false' 2>/dev/null)
234
+
235
+ if [ "$IS_PENDING" = "true" ]; then
236
+ TM_SESSION=$(echo "$PENDING_RESPONSE" | jq -r '.request.session_id // ""')
237
+ TM_FROM_TURN=$(echo "$PENDING_RESPONSE" | jq -r '.request.from_turn // ""')
238
+ TM_REQUEST_ID=$(echo "$PENDING_RESPONSE" | jq -r '.request.request_id // ""')
239
+
240
+ if [ -n "$TM_SESSION" ]; then
241
+ # Build recall request
242
+ RECALL_BODY="{\"session_id\": \"$TM_SESSION\", \"last_n\": 15, \"format\": \"summary\"}"
243
+ if [ -n "$TM_FROM_TURN" ] && [ "$TM_FROM_TURN" != "null" ]; then
244
+ RECALL_BODY="{\"session_id\": \"$TM_SESSION\", \"from_turn\": $TM_FROM_TURN, \"format\": \"summary\"}"
245
+ fi
246
+
247
+ # Fetch turns
248
+ TM_RESPONSE=$(curl -s -X POST "$MEMORY_API_URL/api/v1/turns/recall" \
249
+ -H "Authorization: Bearer $AUTH_TOKEN" \
250
+ -H "Content-Type: application/json" \
251
+ -d "$RECALL_BODY" \
252
+ --connect-timeout 3 \
253
+ --max-time 5 2>/dev/null || echo '{}')
254
+
255
+ TM_TURNS=$(echo "$TM_RESPONSE" | jq -r '.formatted_context // ""' 2>/dev/null)
256
+
257
+ if [ -n "$TM_TURNS" ] && [ "$TM_TURNS" != "null" ]; then
258
+ TIME_MACHINE_CONTEXT="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
259
+ ⏰ TIME MACHINE - Restored from past session
260
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
261
+
262
+ $TM_TURNS
263
+
264
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
265
+ Continue from where you left off!
266
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
267
+
268
+ # Mark request as consumed
269
+ curl -s -X POST "$MEMORY_API_URL/api/v1/context/restore-request/consume" \
270
+ -H "Authorization: Bearer $AUTH_TOKEN" \
271
+ -H "Content-Type: application/json" \
272
+ -d "{\"request_id\": \"$TM_REQUEST_ID\"}" \
273
+ --connect-timeout 2 \
274
+ --max-time 3 >/dev/null 2>&1 || true
275
+
276
+ # Set flag so we don't check again this session
277
+ echo "$TM_REQUEST_ID" > "$TIME_MACHINE_FLAG" 2>/dev/null || true
278
+ fi
279
+ fi
280
+ fi
281
+ fi
282
+
283
+ # ═══════════════════════════════════════════════════════════════════════════
284
+ # [ekkOS_RETRIEVE] Search memory for patterns (all 8 queryable layers)
285
+ # ═══════════════════════════════════════════════════════════════════════════
286
+ JSON_PAYLOAD=$(jq -n \
287
+ --arg query "$PROMPT_TEXT" \
288
+ --arg user_id "${USER_ID:-system}" \
289
+ --arg session "windsurf-$SESSION_ID" \
290
+ '{
291
+ query: $query,
292
+ user_id: $user_id,
293
+ session_id: $session,
294
+ max_per_layer: 5,
295
+ include_layers: ["working", "episodic", "semantic", "patterns", "procedural", "collective", "codebase", "directives"],
296
+ metadata: { source: "windsurf-cascade-hook" }
297
+ }' 2>/dev/null || echo '{}')
298
+
299
+ API_RESPONSE=$(curl -s -X POST "$MEMORY_API_URL/api/v1/context/retrieve" \
300
+ -H "Authorization: Bearer $AUTH_TOKEN" \
301
+ -H "Content-Type: application/json" \
302
+ -d "$JSON_PAYLOAD" \
303
+ --connect-timeout 3 \
304
+ --max-time 5 2>/dev/null || echo '{"error":"timeout"}')
305
+
306
+ # Check if retrieval succeeded
307
+ if echo "$API_RESPONSE" | jq -e '.layers' >/dev/null 2>&1; then
308
+ RETRIEVAL_OK="true"
309
+ else
310
+ # STRICT MODE: Block turn if retrieval failed
311
+ if is_strict_mode; then
312
+ BLOCKER_MSG=$(get_strict_blocker_message)
313
+ write_turn_contract "$SESSION_ID" "false" "windsurf" "" "" "$QUERY_HASH" "$PROJECT_ROOT"
314
+ echo "{\"continue\": false, \"user_message\": $(echo "$BLOCKER_MSG" | jq -R -s .)}"
315
+ exit 0
316
+ fi
317
+
318
+ API_RESPONSE='{"error":"timeout","formatted_context":"","layers":{"patterns":[],"directives":[]}}'
319
+ fi
320
+
321
+ # Extract counts
322
+ PATTERN_COUNT=$(echo "$API_RESPONSE" | jq '.layers.patterns // [] | length' 2>/dev/null || echo "0")
323
+ DIRECTIVE_COUNT=$(echo "$API_RESPONSE" | jq '.layers.directives // [] | length' 2>/dev/null || echo "0")
324
+ TOTAL_COUNT=$((PATTERN_COUNT + DIRECTIVE_COUNT))
325
+
326
+ # Extract pattern and directive IDs for turn contract
327
+ RETRIEVED_PATTERN_IDS=$(echo "$API_RESPONSE" | jq -r '.layers.patterns // [] | map(.pattern_id // .id) | join(",")' 2>/dev/null || echo "")
328
+ RETRIEVED_DIRECTIVE_IDS=$(echo "$API_RESPONSE" | jq -r '.layers.directives // [] | map(.directive_id // .id) | join(",")' 2>/dev/null || echo "")
329
+
330
+ # ═══════════════════════════════════════════════════════════════════════════
331
+ # [ekkOS_CONTRACT] Write turn contract as evidence of retrieval
332
+ # ═══════════════════════════════════════════════════════════════════════════
333
+ write_turn_contract "$SESSION_ID" "$RETRIEVAL_OK" "windsurf" "$RETRIEVED_PATTERN_IDS" "$RETRIEVED_DIRECTIVE_IDS" "$QUERY_HASH" "$PROJECT_ROOT"
334
+
335
+ # Save session ID and query for post_cascade_response hook
336
+ echo "$SESSION_ID" > "$STATE_DIR/current_session_id.txt" 2>/dev/null || true
337
+ echo "$PROMPT_TEXT" > "$STATE_DIR/last_query.txt" 2>/dev/null || true
338
+
339
+ # ═══════════════════════════════════════════════════════════════════════════
340
+ # [ekkOS_INJECT] Build user message with patterns + footer requirement
341
+ # ═══════════════════════════════════════════════════════════════════════════
342
+ MESSAGE=""
343
+
344
+ # Add Endless Context if present (auto-restored recent turns)
345
+ if [ -n "$ENDLESS_CONTEXT" ]; then
346
+ MESSAGE="$ENDLESS_CONTEXT
347
+
348
+ "
349
+ fi
350
+
351
+ # Add Time Machine context if present (overrides Endless Context)
352
+ if [ -n "$TIME_MACHINE_CONTEXT" ]; then
353
+ MESSAGE="$TIME_MACHINE_CONTEXT
354
+
355
+ "
356
+ fi
357
+
358
+ if [ "$PATTERN_COUNT" -gt 0 ]; then
359
+ # Get formatted context
360
+ FORMATTED=$(echo "$API_RESPONSE" | jq -r '.formatted_context // ""' 2>/dev/null)
361
+
362
+ # Get pattern IDs for PatternGuard
363
+ PATTERN_ID_LIST=$(echo "$API_RESPONSE" | jq -r '.layers.patterns[:5][] | .pattern_id // .id' 2>/dev/null || echo "")
364
+
365
+ if [ -n "$FORMATTED" ] && [ "$FORMATTED" != "null" ]; then
366
+ MESSAGE="${MESSAGE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
367
+ 🧠 ekkOS™ Memory Substrate
368
+ ✓ $PATTERN_COUNT patterns loaded from memory
369
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
370
+
371
+ $FORMATTED
372
+
373
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
374
+ ⚠️ PATTERNGUARD REQUIRED
375
+
376
+ You MUST acknowledge ALL $PATTERN_COUNT pattern(s) above.
377
+
378
+ Pattern IDs to acknowledge:
379
+ $PATTERN_ID_LIST
380
+
381
+ For patterns you USE:
382
+ [ekkOS_SELECT]
383
+ - id: <pattern-uuid>
384
+ reason: <why using>
385
+ confidence: <0.0-1.0>
386
+ [/ekkOS_SELECT]
387
+
388
+ For patterns you DO NOT use:
389
+ [ekkOS_SKIP]
390
+ - id: <pattern-uuid>
391
+ reason: <why not relevant>
392
+ [/ekkOS_SKIP]
393
+
394
+ Coverage MUST be 100% (all IDs acknowledged).
395
+
396
+ RESPONSE FORMAT: End with:
397
+ 🧠 **ekkOS_™** · 📅 YYYY-MM-DD H:MM AM/PM TZ
398
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
399
+ else
400
+ # Fallback: minimal injection
401
+ MESSAGE="${MESSAGE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
402
+ 🧠 ekkOS™: $PATTERN_COUNT patterns found
403
+
404
+ Pattern IDs to acknowledge with [ekkOS_SELECT] or [ekkOS_SKIP]:
405
+ $PATTERN_ID_LIST
406
+
407
+ End response with: 🧠 **ekkOS_™** · 📅 YYYY-MM-DD
408
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
409
+ fi
410
+
411
+ # Save patterns for post_cascade_response hook
412
+ echo "$API_RESPONSE" | jq '.layers.patterns // []' > "$STATE_DIR/patterns-${SESSION_ID}.json" 2>/dev/null || true
413
+
414
+ echo "{\"continue\": true, \"user_message\": $(echo "$MESSAGE" | jq -R -s .)}" | jq -c .
415
+ elif [ -n "$TIME_MACHINE_CONTEXT" ] || [ -n "$ENDLESS_CONTEXT" ]; then
416
+ # Time Machine or Endless Context only, no patterns - still require footer
417
+ MESSAGE="${MESSAGE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
418
+ 🧠 ekkOS™: Context restored, no new patterns
419
+
420
+ End response with: 🧠 **ekkOS_™** · 📅 YYYY-MM-DD
421
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
422
+
423
+ echo "{\"continue\": true, \"user_message\": $(echo "$MESSAGE" | jq -R -s .)}" | jq -c .
424
+ else
425
+ # No Time Machine, no patterns - still write contract and remind about footer
426
+ MESSAGE="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
427
+ 🧠 ekkOS™: No patterns found (new territory)
428
+
429
+ End response with: 🧠 **ekkOS_™** · 📅 YYYY-MM-DD
430
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
431
+
432
+ echo "{\"continue\": true, \"user_message\": $(echo "$MESSAGE" | jq -R -s .)}" | jq -c .
433
+ fi
434
+
435
+ exit 0
@@ -0,0 +1,219 @@
1
+ ---
2
+ title: ekkOS Memory System
3
+ description: AI-native cognitive memory with 31 MCP tools for persistent learning and context continuity
4
+ trigger: always_on
5
+ author: ekkOS Technologies
6
+ tags: [memory, patterns, learning, context]
7
+ ---
8
+
9
+ # ekkOS Memory System Skill
10
+
11
+ This skill enables Cascade to leverage the full ekkOS 11-layer cognitive memory system for persistent learning, pattern recognition, and context continuity across sessions.
12
+
13
+ ## When to Use This Skill
14
+
15
+ **ALWAYS USE** for:
16
+ - Technical questions (before answering, search memory)
17
+ - Bug fixes (forge patterns after solving)
18
+ - Architecture decisions (check for existing patterns)
19
+ - Code reviews (retrieve relevant patterns)
20
+ - Refactoring (find proven approaches)
21
+
22
+ ## Core Workflow
23
+
24
+ ### 1. Search Before Answering (MANDATORY)
25
+
26
+ ```
27
+ Before answering ANY technical question:
28
+
29
+ 1. Call ekkOS_Search with the query
30
+ 2. Review retrieved patterns
31
+ 3. Acknowledge ALL patterns with [ekkOS_SELECT] or [ekkOS_SKIP]
32
+ 4. THEN provide your answer
33
+ ```
34
+
35
+ ### 2. PatternGuard Acknowledgment
36
+
37
+ For every pattern retrieved, you MUST acknowledge it:
38
+
39
+ ```
40
+ [ekkOS_SELECT]
41
+ - id: <pattern-uuid>
42
+ reason: Using this because...
43
+ confidence: 0.95
44
+ [/ekkOS_SELECT]
45
+
46
+ [ekkOS_SKIP]
47
+ - id: <pattern-uuid>
48
+ reason: Not relevant because...
49
+ [/ekkOS_SKIP]
50
+ ```
51
+
52
+ **Coverage must be 100%** - every pattern ID must be acknowledged.
53
+
54
+ ### 3. Forge What You Learn
55
+
56
+ After fixing bugs, solving problems, or discovering gotchas:
57
+
58
+ ```
59
+ Call ekkOS_Forge with:
60
+ - Problem: What was broken
61
+ - Solution: How you fixed it
62
+ - Tags: [language, framework, error-type]
63
+ ```
64
+
65
+ ## MCP Tools Reference
66
+
67
+ ### Core Memory (8 tools)
68
+
69
+ | Tool | Purpose | When to Use |
70
+ |------|---------|-------------|
71
+ | `ekkOS_Search` | Search all 11 memory layers | **Before EVERY technical answer** |
72
+ | `ekkOS_Context` | Get relevant task context | When starting multi-step tasks |
73
+ | `ekkOS_Capture` | Capture memory events | Log significant actions |
74
+ | `ekkOS_Forge` | Create patterns from solutions | After fixing bugs/discoveries |
75
+ | `ekkOS_Directive` | Create MUST/NEVER/PREFER/AVOID rules | When user states preferences |
76
+ | `ekkOS_Outcome` | Track success/failure | After applying patterns |
77
+ | `ekkOS_Detect` | Auto-detect pattern usage | In responses |
78
+ | `ekkOS_Recall` | Recall past conversations | When user asks "what did we" |
79
+
80
+ ### Schema Awareness (2 tools)
81
+
82
+ | Tool | Purpose | When to Use |
83
+ |------|---------|-------------|
84
+ | `ekkOS_IndexSchema` | Index database schemas | With Supabase/Prisma projects |
85
+ | `ekkOS_GetSchema` | Get specific table schema | When writing queries |
86
+
87
+ ### Plan Management (9 tools)
88
+
89
+ | Tool | Purpose | When to Use |
90
+ |------|---------|-------------|
91
+ | `ekkOS_Plan` | Create structured plans | Multi-step features |
92
+ | `ekkOS_Generate` | AI-generate plans | Complex tasks |
93
+ | `ekkOS_PlanStatus` | Update plan status | Marking steps complete |
94
+ | `ekkOS_PlanStep` | Mark step done | Step completion |
95
+ | `ekkOS_SaveTemplate` | Save as template | Reusable workflows |
96
+ | `ekkOS_Templates` | List templates | Finding existing plans |
97
+ | `ekkOS_FromTemplate` | Create from template | Starting from template |
98
+
99
+ ### Portability & Secrets (8 tools)
100
+
101
+ | Tool | Purpose | When to Use |
102
+ |------|---------|-------------|
103
+ | `ekkOS_Export` | Export as backup | Before major changes |
104
+ | `ekkOS_Import` | Import from backup | Restoring context |
105
+ | `ekkOS_StoreSecret` | Encrypt credentials | Storing API keys |
106
+ | `ekkOS_GetSecret` | Retrieve secrets | Using stored credentials |
107
+ | `ekkOS_ListSecrets` | List secret metadata | Checking what's stored |
108
+ | `ekkOS_RotateSecret` | Rotate secret values | Key rotation |
109
+
110
+ ### System Health (4 tools)
111
+
112
+ | Tool | Purpose | When to Use |
113
+ |------|---------|-------------|
114
+ | `ekkOS_Stats` | Get layer statistics | Health checks |
115
+ | `ekkOS_Summary` | Get activity summary | Progress updates |
116
+ | `ekkOS_Conflict` | Check for conflicts | Before dangerous ops |
117
+ | `ekkOS_Reflect` | Analyze for improvements | Post-task review |
118
+
119
+ ## 11-Layer Architecture
120
+
121
+ | Layer | Purpose | Example Content |
122
+ |-------|---------|-----------------|
123
+ | 1 | Working | Current session context |
124
+ | 2 | Episodic | Past conversation turns |
125
+ | 3 | Semantic | Embeddings/vectors |
126
+ | 4 | Patterns | Proven solutions |
127
+ | 5 | Procedural | Step-by-step guides |
128
+ | 6 | Collective | Community patterns |
129
+ | 7 | Meta | Pattern effectiveness |
130
+ | 8 | Codebase | Project code context |
131
+ | 9 | Directives | User rules (MUST/NEVER) |
132
+ | 10 | Conflict | Auto-resolution rules |
133
+ | 11 | Secrets | Encrypted credentials |
134
+
135
+ ## Forge Triggers
136
+
137
+ **Always forge when you:**
138
+ - Fix a bug (create anti-pattern from the bug)
139
+ - Find a better approach (update existing pattern)
140
+ - Discover a gotcha (create warning pattern)
141
+ - Get corrected by user (learn from correction)
142
+ - Solve auth/config issues (create setup pattern)
143
+ - Make architecture decisions (document rationale)
144
+ - Debug non-trivially (capture the journey)
145
+
146
+ ## Response Format
147
+
148
+ End EVERY response with:
149
+
150
+ ```
151
+ 🧠 **ekkOS_™** · 📅 YYYY-MM-DD H:MM AM/PM TZ
152
+ ```
153
+
154
+ ## Examples
155
+
156
+ ### Example 1: Technical Question
157
+
158
+ User: "How do I fix CORS in Next.js?"
159
+
160
+ Your workflow:
161
+ 1. Call `ekkOS_Search` with query: "Next.js CORS fix"
162
+ 2. Review retrieved patterns
163
+ 3. Acknowledge all patterns with SELECT/SKIP
164
+ 4. Provide answer based on patterns + your knowledge
165
+ 5. End with footer
166
+
167
+ ### Example 2: Bug Fix
168
+
169
+ User: "The build is failing with this error..."
170
+
171
+ Your workflow:
172
+ 1. Call `ekkOS_Search` with error message
173
+ 2. Apply relevant patterns
174
+ 3. Acknowledge with SELECT
175
+ 4. Fix the bug
176
+ 5. Call `ekkOS_Forge` with the solution
177
+ 6. Call `ekkOS_Outcome` to track success
178
+
179
+ ### Example 3: User Preference
180
+
181
+ User: "I always want TypeScript strict mode"
182
+
183
+ Your workflow:
184
+ 1. Call `ekkOS_Directive`:
185
+ - type: PREFER
186
+ - rule: "Use TypeScript strict mode"
187
+ - scope: project
188
+ 2. Acknowledge in future responses
189
+
190
+ ## Best Practices
191
+
192
+ 1. **Search first** - Never answer without searching
193
+ 2. **Acknowledge all** - 100% PatternGuard coverage required
194
+ 3. **Forge immediately** - Don't wait to capture learnings
195
+ 4. **Track outcomes** - Success/failure feedback improves patterns
196
+ 5. **Use directives** - Convert user preferences to rules
197
+ 6. **Export regularly** - Backup before major changes
198
+ 7. **End with footer** - Every response needs the ekkOS footer
199
+
200
+ ## Troubleshooting
201
+
202
+ **"No patterns found"**
203
+ → You're in new territory. Forge what you discover.
204
+
205
+ **"Pattern retrieval failed"**
206
+ → Check auth: `~/.ekkos/config.json` should have hookApiKey
207
+
208
+ **"How do I continue from last session?"**
209
+ → Ask: "recall our last conversation" or "where were we"
210
+
211
+ ## Resources
212
+
213
+ - Website: https://ekkos.dev
214
+ - Docs: https://docs.ekkos.dev
215
+ - Support: support@ekkos.dev
216
+
217
+ ---
218
+
219
+ 🧠 **ekkOS_™** · Built for infinite context
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Ekkos Technologies Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.