olympus-ai 2.7.4 → 3.2.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 (104) hide show
  1. package/.claude/.olympus-version.json +6 -0
  2. package/.claude/CLAUDE.md +84 -61
  3. package/.claude/agents/document-writer.md +152 -0
  4. package/.claude/agents/explore-medium.md +25 -0
  5. package/.claude/agents/explore.md +86 -0
  6. package/.claude/agents/frontend-engineer-high.md +17 -0
  7. package/.claude/agents/frontend-engineer-low.md +17 -0
  8. package/.claude/agents/frontend-engineer.md +80 -0
  9. package/.claude/agents/librarian-low.md +22 -0
  10. package/.claude/agents/librarian.md +70 -0
  11. package/.claude/agents/metis.md +85 -0
  12. package/.claude/agents/momus.md +97 -0
  13. package/.claude/agents/multimodal-looker.md +39 -0
  14. package/.claude/agents/olympian-high.md +32 -0
  15. package/.claude/agents/olympian-low.md +22 -0
  16. package/.claude/agents/olympian.md +78 -0
  17. package/.claude/agents/oracle-low.md +23 -0
  18. package/.claude/agents/oracle-medium.md +28 -0
  19. package/.claude/agents/oracle.md +77 -0
  20. package/.claude/agents/prometheus.md +125 -0
  21. package/.claude/agents/qa-tester.md +220 -0
  22. package/.claude/commands/analyze/skill.md +14 -0
  23. package/.claude/commands/ascent/skill.md +152 -0
  24. package/.claude/commands/cancel-ascent.md +9 -0
  25. package/.claude/commands/complete-plan.md +101 -0
  26. package/.claude/commands/deepsearch/skill.md +15 -0
  27. package/.claude/commands/olympus/skill.md +82 -0
  28. package/.claude/commands/olympus-default.md +26 -0
  29. package/.claude/commands/plan.md +71 -0
  30. package/.claude/commands/prometheus/skill.md +38 -0
  31. package/.claude/commands/review/skill.md +34 -0
  32. package/.claude/commands/ultrawork/skill.md +90 -0
  33. package/.claude/commands/update.md +38 -0
  34. package/.claude-plugin/plugin.json +1 -1
  35. package/COPYRIGHT +22 -0
  36. package/LICENSE +1 -1
  37. package/NOTICE +24 -0
  38. package/README.md +376 -10
  39. package/dist/__tests__/installer.test.js +1 -1
  40. package/dist/__tests__/learning/cleanup.test.d.ts +2 -0
  41. package/dist/__tests__/learning/cleanup.test.d.ts.map +1 -0
  42. package/dist/__tests__/learning/cleanup.test.js +122 -0
  43. package/dist/__tests__/learning/cleanup.test.js.map +1 -0
  44. package/dist/__tests__/learning/storage.test.d.ts +2 -0
  45. package/dist/__tests__/learning/storage.test.d.ts.map +1 -0
  46. package/dist/__tests__/learning/storage.test.js +75 -0
  47. package/dist/__tests__/learning/storage.test.js.map +1 -0
  48. package/dist/agents/definitions.d.ts.map +1 -1
  49. package/dist/agents/definitions.js +22 -6
  50. package/dist/agents/definitions.js.map +1 -1
  51. package/dist/agents/olympian.d.ts.map +1 -1
  52. package/dist/agents/olympian.js +23 -7
  53. package/dist/agents/olympian.js.map +1 -1
  54. package/dist/agents/orchestrator-olympus.js +1 -1
  55. package/dist/cli/index.js +128 -9
  56. package/dist/cli/index.js.map +1 -1
  57. package/dist/hooks/context-window-limit-recovery/index.d.ts +2 -3
  58. package/dist/hooks/context-window-limit-recovery/index.d.ts.map +1 -1
  59. package/dist/hooks/context-window-limit-recovery/index.js +2 -3
  60. package/dist/hooks/context-window-limit-recovery/index.js.map +1 -1
  61. package/dist/hooks/olympus-orchestrator/constants.d.ts +3 -3
  62. package/dist/hooks/olympus-orchestrator/constants.d.ts.map +1 -1
  63. package/dist/hooks/olympus-orchestrator/constants.js +3 -3
  64. package/dist/hooks/preemptive-compaction/index.d.ts +2 -3
  65. package/dist/hooks/preemptive-compaction/index.d.ts.map +1 -1
  66. package/dist/hooks/preemptive-compaction/index.js +2 -3
  67. package/dist/hooks/preemptive-compaction/index.js.map +1 -1
  68. package/dist/installer/index.d.ts +2 -2
  69. package/dist/installer/index.d.ts.map +1 -1
  70. package/dist/installer/index.js +114 -30
  71. package/dist/installer/index.js.map +1 -1
  72. package/dist/learning/cleanup.d.ts +18 -0
  73. package/dist/learning/cleanup.d.ts.map +1 -0
  74. package/dist/learning/cleanup.js +160 -0
  75. package/dist/learning/cleanup.js.map +1 -0
  76. package/dist/learning/discovery.d.ts.map +1 -1
  77. package/dist/learning/discovery.js +3 -1
  78. package/dist/learning/discovery.js.map +1 -1
  79. package/dist/learning/pattern-extractor.d.ts +1 -1
  80. package/dist/learning/pattern-extractor.d.ts.map +1 -1
  81. package/dist/learning/pattern-extractor.js +4 -2
  82. package/dist/learning/pattern-extractor.js.map +1 -1
  83. package/dist/learning/stats.d.ts +28 -0
  84. package/dist/learning/stats.d.ts.map +1 -0
  85. package/dist/learning/stats.js +112 -0
  86. package/dist/learning/stats.js.map +1 -0
  87. package/dist/learning/storage.d.ts +4 -0
  88. package/dist/learning/storage.d.ts.map +1 -1
  89. package/dist/learning/storage.js +26 -1
  90. package/dist/learning/storage.js.map +1 -1
  91. package/package.json +9 -4
  92. package/{dist → scripts/dist}/hooks/olympus-hooks.cjs +70 -69
  93. package/scripts/esbuild.hooks.mjs +67 -0
  94. package/scripts/generate-logo-hybrid-v2.mjs +213 -0
  95. package/scripts/generate-logo-hybrid.mjs +209 -0
  96. package/scripts/generate-logo-infinity.mjs +239 -0
  97. package/scripts/generate-logo-mythology.mjs +190 -0
  98. package/scripts/generate-logo-orchestration.mjs +228 -0
  99. package/scripts/generate-logo-recraft.mjs +147 -0
  100. package/scripts/generate-logo-simple.mjs +154 -0
  101. package/scripts/generate-logo.mjs +117 -0
  102. package/scripts/install.sh +4 -7
  103. package/scripts/rebrand.mjs +206 -0
  104. package/.claude-plugin/nul +0 -3
package/README.md CHANGED
@@ -4,13 +4,14 @@
4
4
 
5
5
  ### Multi-Agent Orchestration for Claude Code
6
6
 
7
- [![Version](https://img.shields.io/badge/version-2.7.3-gold)](https://github.com/mikev10/olympus/releases)
7
+ [![npm version](https://img.shields.io/npm/v/olympus-ai.svg)](https://www.npmjs.com/package/olympus-ai)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
- [![Agents](https://img.shields.io/badge/Agents-18-blue)](https://github.com/mikev10/olympus)
9
+ [![Agents](https://img.shields.io/badge/Agents-20+-blue)](https://github.com/mikev10/olympus)
10
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/mikev10/olympus/claude.yml)](https://github.com/mikev10/olympus/actions)
10
11
 
11
12
  **Summon the gods of code.**
12
13
 
13
- [Install](#installation) • [Usage](#usage) • [Agents](#available-agents) • [Commands](#slash-commands)
14
+ [Why Olympus?](#why-olympus) • [Quick Start](#quick-start) • [Self-Learning](#self-learning-system) • [Use Cases](#use-cases) • [Agents](#available-agents) • [Docs](#documentation)
14
15
 
15
16
  </div>
16
17
 
@@ -20,11 +21,86 @@
20
21
 
21
22
  Olympus is a multi-agent orchestration system for [Claude Code](https://docs.anthropic.com/claude-code). It provides:
22
23
 
23
- - **18 Specialized Agents** - Oracle, Prometheus, Olympian, and more
24
- - **13 Slash Commands** - `/olympus`, `/ultrawork`, `/plan`, `/ascent`, etc.
25
- - **Intelligent Model Routing** - Routes tasks to Haiku/Sonnet/Opus based on complexity
26
- - **The Ascent** - Persistence loop that ensures tasks complete before stopping
27
- - **Magic Keywords** - Say "ultrawork" to activate maximum performance mode
24
+ - 🧠 **Self-Learning System** - Learns your preferences, patterns, and codebase over time
25
+ - 🤖 **20+ Specialized Agents** - Oracle, Prometheus, Olympian, Librarian, and more
26
+ - **Smart Model Routing** - Auto-selects Haiku/Sonnet/Opus based on task complexity
27
+ - 📋 **Todo Management** - Tracks progress with real-time updates
28
+ - 🔄 **Background Execution** - Long-running tasks run async with notifications
29
+ - 🎯 **Continuation Enforcement** - Never stops until all tasks are complete
30
+ - 💬 **13+ Slash Commands** - `/ultrawork`, `/plan`, `/ascent`, and more
31
+ - 🔮 **Magic Keywords** - Natural language triggers for enhanced modes
32
+
33
+ ---
34
+
35
+ ## Why Olympus?
36
+
37
+ Olympus transforms Claude Code from a single agent into a **pantheon of specialized experts** that work together seamlessly.
38
+
39
+ ### 🧠 Self-Learning System
40
+
41
+ **Olympus learns from your preferences and evolves over time.**
42
+
43
+ - **Active Agent Learning** - Agents proactively record patterns, gotchas, and workarounds they discover during work
44
+ - **Passive Feedback Capture** - Automatically detects corrections, preferences, and patterns from your interactions
45
+ - **Pattern Extraction** - Identifies recurring feedback and adapts behavior accordingly
46
+ - **Preference Learning** - Infers your communication style (concise vs. detailed, autonomous vs. collaborative)
47
+ - **Agent Performance Tracking** - Monitors which agents succeed or fail for specific tasks
48
+ - **Discovery Storage** - Structured JSONL storage with verification tracking and confidence scoring
49
+ - **Context Injection** - Learned preferences and discoveries are automatically applied in new sessions
50
+
51
+ **The more you use Olympus, the better it understands your workflow.**
52
+
53
+ ### ⚡ Intelligent Orchestration
54
+
55
+ - **Smart Delegation** - Routes tasks to specialized agents based on complexity
56
+ - **Model Routing** - Automatically selects Haiku/Sonnet/Opus to optimize cost and performance
57
+ - **Parallel Execution** - Runs independent tasks concurrently for maximum throughput
58
+
59
+ ### 🎯 Continuous Delivery
60
+
61
+ - **Todo Management** - Tracks progress across complex multi-step tasks
62
+ - **Continuation Enforcement** - Never stops until all tasks are verified complete
63
+ - **Background Operations** - Long-running builds, tests, and installs run async with notifications
64
+
65
+ ### 🔧 Developer Experience
66
+
67
+ - **Zero Configuration** - Works out-of-the-box with sensible defaults
68
+ - **Slash Commands** - 13+ productivity commands (`/ultrawork`, `/plan`, `/ascent`)
69
+ - **Magic Keywords** - Natural language triggers for enhanced modes
70
+
71
+ ### 📊 Olympus vs. Manual Claude Usage
72
+
73
+ | Feature | Manual Claude | Olympus |
74
+ |---------|---------------|---------|
75
+ | **Multi-Step Tasks** | Sequential, manual tracking | Automatic todo management |
76
+ | **Parallel Execution** | One task at a time | 3-5x faster with concurrent agents |
77
+ | **Learning** | Repeats mistakes | Learns from corrections automatically |
78
+ | **Model Selection** | Manual switching | Smart routing (cost optimized) |
79
+ | **Task Persistence** | Stops when asked | Continues until verified complete |
80
+ | **Background Tasks** | Blocks waiting | Runs async with notifications |
81
+ | **Agent Specialization** | Generic responses | 20+ experts for specific domains |
82
+
83
+ ---
84
+
85
+ ## Quick Start
86
+
87
+ Get started in under 60 seconds:
88
+
89
+ ```bash
90
+ # Install globally
91
+ npm install -g olympus-ai
92
+
93
+ # Initialize Olympus
94
+ olympus-ai install
95
+
96
+ # Start Claude Code
97
+ claude
98
+
99
+ # Try it out
100
+ /olympus implement a REST API for user management
101
+ ```
102
+
103
+ **That's it.** Olympus is now active and learning from your interactions.
28
104
 
29
105
  ---
30
106
 
@@ -112,6 +188,116 @@ Include these words anywhere in your prompt to activate enhanced modes:
112
188
 
113
189
  ---
114
190
 
191
+ ## Use Cases
192
+
193
+ ### 🏗️ Complex Refactoring
194
+
195
+ ```bash
196
+ /ascent refactor the entire authentication module to use OAuth 2.0
197
+ ```
198
+
199
+ **What happens:**
200
+ - Creates todo list for all subtasks
201
+ - Delegates to specialized agents (Oracle for architecture, Olympian for execution)
202
+ - Runs tests in background
203
+ - Continues until all tasks verified complete
204
+
205
+ ### 📊 Multi-Agent Research
206
+
207
+ ```bash
208
+ /ultrawork research and document all API endpoints in the codebase
209
+ ```
210
+
211
+ **What happens:**
212
+ - Spawns multiple agents in parallel (Explore for search, Librarian for docs)
213
+ - Aggregates findings
214
+ - Generates comprehensive documentation
215
+ - ~3x faster than sequential execution
216
+
217
+ ### 📋 Strategic Planning
218
+
219
+ ```bash
220
+ /plan build a real-time chat application with WebSocket support
221
+ ```
222
+
223
+ **What happens:**
224
+ - Prometheus interviews you about requirements
225
+ - Creates detailed work plan with phases
226
+ - Identifies dependencies and risks
227
+ - Saves plan to `.olympus/plans/` for execution
228
+
229
+ ### 🧠 Learning Your Workflow
230
+
231
+ **Automatic - no command needed**
232
+
233
+ You: "No, use TypeScript interfaces instead of types"
234
+ → Olympus records this preference
235
+
236
+ You: "Use functional components, not class components"
237
+ → Olympus learns your React style
238
+
239
+ **Next session:** Claude automatically applies these preferences without being told.
240
+
241
+ ---
242
+
243
+ ## Architecture
244
+
245
+ Olympus operates as a three-tier orchestration system with a continuous learning loop:
246
+
247
+ ```mermaid
248
+ graph TD
249
+ A[User Request] --> B[Orchestrator]
250
+ B --> C{Task Analysis}
251
+ C -->|Simple| D[Haiku Agent]
252
+ C -->|Standard| E[Sonnet Agent]
253
+ C -->|Complex| F[Opus Agent]
254
+ D --> G[Learning System]
255
+ E --> G
256
+ F --> G
257
+ G --> H[Feedback Storage]
258
+ H -.->|Next Session| B
259
+ B --> I[Todo Manager]
260
+ I --> J[Background Executor]
261
+ J --> K[Result]
262
+ ```
263
+
264
+ ### How It Works
265
+
266
+ **Current Session Flow:**
267
+ 1. **User Request** → Arrives with learned context already injected at SessionStart
268
+ 2. **Orchestrator** → Analyzes task complexity and delegates to appropriate agents
269
+ 3. **Model Router** → Selects Haiku (simple), Sonnet (standard), or Opus (complex)
270
+ 4. **Agents Execute** → Specialized agents complete their tasks
271
+ 5. **Learning System** → Passively captures feedback from corrections, preferences, and patterns
272
+ 6. **Feedback Storage** → Stores learned preferences, agent performance, and discoveries
273
+ 7. **Result** → User sees the completed work
274
+
275
+ **Learning & Context Injection (Between Sessions):**
276
+
277
+ The learning system operates across session boundaries:
278
+
279
+ - **During Session**: Captures feedback from user corrections ("No, use async/await"), preferences ("Always use TypeScript"), and agent discoveries (gotchas, workarounds)
280
+ - **Storage**: Writes to `~/.claude/olympus/learning/` (global) and `.olympus/learning/` (project-specific)
281
+ - **Next Session Start**: SessionStart hook automatically injects learned context into the initial prompt
282
+ - **Context Types Injected**:
283
+ - User preferences (verbosity, autonomy, explicit rules)
284
+ - Recurring corrections (mistakes to avoid)
285
+ - Project conventions (tech stack, patterns)
286
+ - Agent performance notes (weak areas to watch)
287
+ - Recent discoveries (technical insights about your codebase)
288
+
289
+ **Key Insight:** Context injection happens at the **beginning** of each session (via SessionStart hook), not in the result. This means every new conversation starts with Claude already aware of your preferences and past learnings.
290
+
291
+ **Key Components:**
292
+ - **Orchestrator** - Delegates tasks to specialized agents based on complexity
293
+ - **Model Router** - Selects optimal tier (Haiku/Sonnet/Opus) to balance cost and capability
294
+ - **Learning System** - Captures feedback passively and builds preference models
295
+ - **Todo Manager** - Tracks multi-step task progress with real-time status updates
296
+ - **Background Executor** - Runs long-running operations (builds, tests, installs) async with notifications
297
+ - **Feedback Storage** - Persists learned preferences, patterns, and discoveries across sessions
298
+
299
+ ---
300
+
115
301
  ## Available Agents
116
302
 
117
303
  ### Task Execution
@@ -182,16 +368,139 @@ Plans are saved to `.olympus/plans/` in your project directory.
182
368
 
183
369
  ---
184
370
 
371
+ ## Self-Learning System
372
+
373
+ Olympus continuously learns from your interactions to provide increasingly personalized assistance.
374
+
375
+ ### How It Works
376
+
377
+ **Phase 1: Passive Feedback Capture**
378
+ - Detects corrections: "No, that's wrong"
379
+ - Identifies rejections: "Stop", "Cancel"
380
+ - Recognizes clarifications: "I meant X"
381
+ - Captures enhancements: "Also add Y"
382
+ - Records praise: "Perfect", "Thanks"
383
+ - Extracts explicit preferences: "Always use X"
384
+
385
+ **Phase 2: Pattern Extraction**
386
+ - Clusters similar feedback using Jaccard similarity
387
+ - Identifies recurring corrections (minimum 3 occurrences)
388
+ - Categorizes patterns: style, behavior, tooling, communication
389
+
390
+ **Phase 3: Preference Learning**
391
+ - Infers verbosity level (concise vs. detailed)
392
+ - Determines autonomy preference (ask first vs. just do it)
393
+ - Tracks agent-specific performance
394
+ - Implements 30-day decay for outdated patterns
395
+
396
+ **Phase 4: Context Injection**
397
+ - Automatically applies learned preferences at session start
398
+ - Injects relevant discoveries about your codebase
399
+ - Limits injection to ~500 tokens to avoid context bloat
400
+
401
+ **Phase 5: Agent Discovery**
402
+ - Agents record technical insights about your project
403
+ - Discoveries include: gotchas, workarounds, patterns, dependencies
404
+ - Validated and deduplicated before storage
405
+ - Retrieved contextually in future sessions
406
+
407
+ ### Storage Locations
408
+
409
+ **Global Learning:**
410
+ ```
411
+ ~/.claude/olympus/learning/
412
+ ├── feedback-log.jsonl # All feedback entries (auto-rotates at 10k lines)
413
+ ├── user-preferences.json # Learned preferences
414
+ ├── agent-performance.json # Per-agent metrics
415
+ └── discoveries.jsonl # Global discoveries (auto-rotates at 10k lines)
416
+ ```
417
+
418
+ **Project-Specific Learning:**
419
+ ```
420
+ .olympus/learning/
421
+ ├── session-state.json # Current session state
422
+ ├── patterns.json # Project patterns
423
+ └── discoveries.jsonl # Project discoveries (auto-rotates at 10k lines)
424
+ ```
425
+
426
+ **Data Lifecycle:**
427
+ - JSONL files automatically rotate when they exceed 10,000 lines
428
+ - Archived files are saved with timestamps (e.g., `feedback-log.2026-01-28.old.jsonl`)
429
+ - Manual cleanup available via CLI (see Managing Learning Data below)
430
+
431
+ ### Managing Learning Data
432
+
433
+ View learning statistics and manage stored data using the CLI:
434
+
435
+ ```bash
436
+ # View learning statistics
437
+ olympus-ai learn --stats
438
+
439
+ # Preview cleanup (dry run)
440
+ olympus-ai learn --cleanup --dry-run
441
+
442
+ # Clean up entries older than 180 days (default)
443
+ olympus-ai learn --cleanup
444
+
445
+ # Clean up with custom age threshold
446
+ olympus-ai learn --cleanup --age 90
447
+
448
+ # Remove archived files
449
+ olympus-ai learn --cleanup --remove-archived
450
+
451
+ # View current learnings
452
+ olympus-ai learn --show
453
+
454
+ # Analyze feedback and update patterns
455
+ olympus-ai learn --analyze
456
+
457
+ # Forget all learnings
458
+ olympus-ai learn --forget
459
+ ```
460
+
461
+ **Example output:**
462
+ ```
463
+ Learning System Statistics
464
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
465
+
466
+ Feedback Entries: 1247 (1.2 MB)
467
+ Discoveries: 123
468
+ Total Storage: 1.5 MB
469
+
470
+ Top Verified Discoveries:
471
+ 1. Prisma migrations must run before seeding (8×)
472
+ 2. This codebase uses kebab-case for files (6×)
473
+ 3. Environment variable DATABASE_URL required (5×)
474
+ ```
475
+
476
+ ### Example
477
+
478
+ **Session 1:** You tell Claude "No, use async/await instead of .then()"
479
+ → Olympus records this as a correction
480
+
481
+ **Session 2:** Similar situation arises
482
+ → You provide the same feedback
483
+
484
+ **Session 3:** Olympus detects the pattern (3+ occurrences)
485
+ → Learns your preference: "Use async/await over Promise chains"
486
+
487
+ **Session 4+:** This preference is automatically injected
488
+ → Claude proactively uses async/await without being told
489
+
490
+ **The learning happens silently in the background. No configuration required.**
491
+
492
+ ---
493
+
185
494
  ## What Gets Installed
186
495
 
187
496
  ```
188
497
  ~/.claude/
189
- ├── agents/ # 18 agent definitions
498
+ ├── agents/ # 20+ agent definitions
190
499
  │ ├── oracle.md
191
500
  │ ├── prometheus.md
192
501
  │ ├── olympian.md
193
502
  │ └── ...
194
- ├── commands/ # 13 slash commands
503
+ ├── commands/ # 13+ slash commands
195
504
  │ ├── olympus/skill.md
196
505
  │ ├── ultrawork/skill.md
197
506
  │ ├── plan.md
@@ -245,6 +554,62 @@ rm -rf ~/.claude/agents ~/.claude/commands ~/.claude/hooks ~/.claude/CLAUDE.md
245
554
 
246
555
  ---
247
556
 
557
+ ## Contributing
558
+
559
+ We welcome contributions! Here's how to get started:
560
+
561
+ ### Development Setup
562
+
563
+ ```bash
564
+ # Clone the repository
565
+ git clone https://github.com/mikev10/olympus.git
566
+ cd olympus
567
+
568
+ # Install dependencies
569
+ npm install
570
+
571
+ # Build the project
572
+ npm run build
573
+
574
+ # Test locally
575
+ node dist/cli/index.js install --local
576
+ ```
577
+
578
+ ### Running Tests
579
+
580
+ ```bash
581
+ npm test # Run tests in watch mode
582
+ npm run test:run # Run tests once
583
+ npm run test:coverage # Generate coverage report
584
+ ```
585
+
586
+ ### Project Structure
587
+
588
+ ```
589
+ olympus/
590
+ ├── src/
591
+ │ ├── agents/ # Agent definitions
592
+ │ ├── features/ # Core features (routing, learning, etc.)
593
+ │ ├── hooks/ # Event handlers
594
+ │ ├── learning/ # Self-learning system
595
+ │ └── cli/ # CLI commands
596
+ ├── agents/ # Agent markdown files (installed)
597
+ ├── commands/ # Slash command files (installed)
598
+ └── scripts/ # Build and installation scripts
599
+ ```
600
+
601
+ ---
602
+
603
+ ## Documentation
604
+
605
+ - 📖 [Getting Started Guide](docs/Olympus.md)
606
+ - 🤖 [Agent Reference](docs/AGENTS.md)
607
+ - 🏗️ [Architecture Overview](docs/ARCHITECTURE.md)
608
+ - 🗺️ [Roadmap](docs/ROADMAP.md)
609
+ - 📋 [Changelog](CHANGELOG.md)
610
+
611
+ ---
612
+
248
613
  ## License
249
614
 
250
615
  MIT - see [LICENSE](LICENSE)
@@ -260,3 +625,4 @@ MIT - see [LICENSE](LICENSE)
260
625
  **Summon the gods of code.**
261
626
 
262
627
  </div>
628
+
@@ -231,7 +231,7 @@ describe('Installer Constants', () => {
231
231
  });
232
232
  it('should match package.json version', () => {
233
233
  // This is a runtime check - VERSION should match the package.json
234
- expect(VERSION).toBe('2.5.0');
234
+ expect(VERSION).toBe('3.1.0');
235
235
  });
236
236
  });
237
237
  describe('File Paths', () => {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cleanup.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/learning/cleanup.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,122 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { cleanupLearning } from '../../learning/cleanup.js';
5
+ const TEST_DIR = join(process.cwd(), '.test-cleanup');
6
+ describe('Learning Cleanup', () => {
7
+ beforeEach(() => {
8
+ if (existsSync(TEST_DIR)) {
9
+ rmSync(TEST_DIR, { recursive: true });
10
+ }
11
+ mkdirSync(TEST_DIR, { recursive: true });
12
+ process.env.HOME = TEST_DIR;
13
+ });
14
+ afterEach(() => {
15
+ if (existsSync(TEST_DIR)) {
16
+ rmSync(TEST_DIR, { recursive: true });
17
+ }
18
+ delete process.env.HOME;
19
+ });
20
+ it('removes old feedback entries', () => {
21
+ const learningDir = join(TEST_DIR, '.claude', 'olympus', 'learning');
22
+ mkdirSync(learningDir, { recursive: true });
23
+ const logPath = join(learningDir, 'feedback-log.jsonl');
24
+ const oldDate = new Date();
25
+ oldDate.setDate(oldDate.getDate() - 200); // 200 days ago
26
+ const entries = [
27
+ {
28
+ id: 'old-1',
29
+ timestamp: oldDate.toISOString(),
30
+ session_id: 'session-1',
31
+ project_path: '/test',
32
+ event_type: 'revision',
33
+ user_message: 'Old message',
34
+ feedback_category: 'correction',
35
+ confidence: 0.9,
36
+ },
37
+ {
38
+ id: 'new-1',
39
+ timestamp: new Date().toISOString(),
40
+ session_id: 'session-2',
41
+ project_path: '/test',
42
+ event_type: 'revision',
43
+ user_message: 'New message',
44
+ feedback_category: 'correction',
45
+ confidence: 0.9,
46
+ },
47
+ ];
48
+ writeFileSync(logPath, entries.map(e => JSON.stringify(e)).join('\n') + '\n', 'utf-8');
49
+ const result = cleanupLearning('/test', { ageDays: 180, dryRun: false });
50
+ expect(result.feedback_entries_removed).toBe(1);
51
+ expect(result.space_freed_mb).toBeGreaterThan(0);
52
+ });
53
+ it('removes expired discoveries', () => {
54
+ const learningDir = join(TEST_DIR, '.claude', 'olympus', 'learning');
55
+ mkdirSync(learningDir, { recursive: true });
56
+ const discoveryPath = join(learningDir, 'discoveries.jsonl');
57
+ const expiredDate = new Date();
58
+ expiredDate.setDate(expiredDate.getDate() - 10);
59
+ const futureDate = new Date();
60
+ futureDate.setDate(futureDate.getDate() + 10);
61
+ const discoveries = [
62
+ {
63
+ id: 'expired-1',
64
+ timestamp: new Date().toISOString(),
65
+ session_id: 'session-1',
66
+ project_path: '/test',
67
+ category: 'workaround',
68
+ summary: 'Expired discovery',
69
+ details: 'This is expired',
70
+ agent_name: 'oracle',
71
+ confidence: 0.9,
72
+ verified: false,
73
+ verification_count: 0,
74
+ scope: 'global',
75
+ expires_at: expiredDate.toISOString(),
76
+ last_useful: new Date().toISOString(),
77
+ },
78
+ {
79
+ id: 'active-1',
80
+ timestamp: new Date().toISOString(),
81
+ session_id: 'session-1',
82
+ project_path: '/test',
83
+ category: 'pattern',
84
+ summary: 'Active discovery',
85
+ details: 'This is active',
86
+ agent_name: 'oracle',
87
+ confidence: 0.9,
88
+ verified: false,
89
+ verification_count: 0,
90
+ scope: 'global',
91
+ expires_at: futureDate.toISOString(),
92
+ last_useful: new Date().toISOString(),
93
+ },
94
+ ];
95
+ writeFileSync(discoveryPath, discoveries.map(d => JSON.stringify(d)).join('\n') + '\n', 'utf-8');
96
+ const result = cleanupLearning('/test', { compactExpired: true, dryRun: false });
97
+ expect(result.discoveries_removed).toBe(1);
98
+ });
99
+ it('dry run does not modify files', () => {
100
+ const learningDir = join(TEST_DIR, '.claude', 'olympus', 'learning');
101
+ mkdirSync(learningDir, { recursive: true });
102
+ const logPath = join(learningDir, 'feedback-log.jsonl');
103
+ const oldDate = new Date();
104
+ oldDate.setDate(oldDate.getDate() - 200);
105
+ const entry = {
106
+ id: 'old-1',
107
+ timestamp: oldDate.toISOString(),
108
+ session_id: 'session-1',
109
+ project_path: '/test',
110
+ event_type: 'revision',
111
+ user_message: 'Old message',
112
+ feedback_category: 'correction',
113
+ confidence: 0.9,
114
+ };
115
+ writeFileSync(logPath, JSON.stringify(entry) + '\n', 'utf-8');
116
+ const sizeBefore = require('fs').statSync(logPath).size;
117
+ cleanupLearning('/test', { ageDays: 180, dryRun: true });
118
+ const sizeAfter = require('fs').statSync(logPath).size;
119
+ expect(sizeBefore).toBe(sizeAfter);
120
+ });
121
+ });
122
+ //# sourceMappingURL=cleanup.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.test.js","sourceRoot":"","sources":["../../../src/__tests__/learning/cleanup.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/learning/storage.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { appendFeedback, readFeedbackLog } from '../../learning/storage.js';
5
+ const TEST_DIR = join(process.cwd(), '.test-learning');
6
+ describe('Storage with Rotation', () => {
7
+ beforeEach(() => {
8
+ // Override getLearningDir for testing
9
+ process.env.HOME = TEST_DIR;
10
+ if (existsSync(TEST_DIR)) {
11
+ rmSync(TEST_DIR, { recursive: true });
12
+ }
13
+ mkdirSync(TEST_DIR, { recursive: true });
14
+ });
15
+ afterEach(() => {
16
+ if (existsSync(TEST_DIR)) {
17
+ rmSync(TEST_DIR, { recursive: true });
18
+ }
19
+ delete process.env.HOME;
20
+ });
21
+ it('rotates JSONL file when exceeding threshold', () => {
22
+ const testEntry = {
23
+ id: 'test-1',
24
+ timestamp: new Date().toISOString(),
25
+ session_id: 'session-1',
26
+ project_path: '/test',
27
+ event_type: 'revision',
28
+ user_message: 'Test message',
29
+ feedback_category: 'correction',
30
+ confidence: 0.9,
31
+ };
32
+ // Create a file with many lines (simulating large file)
33
+ const learningDir = join(TEST_DIR, '.claude', 'olympus', 'learning');
34
+ mkdirSync(learningDir, { recursive: true });
35
+ const logPath = join(learningDir, 'feedback-log.jsonl');
36
+ // Write 10,001 lines to trigger rotation
37
+ const lines = [];
38
+ for (let i = 0; i < 10001; i++) {
39
+ lines.push(JSON.stringify({ ...testEntry, id: `test-${i}` }));
40
+ }
41
+ writeFileSync(logPath, lines.join('\n') + '\n', 'utf-8');
42
+ // Append new entry (should trigger rotation)
43
+ appendFeedback(testEntry);
44
+ // Check that archive file was created
45
+ const files = require('fs').readdirSync(learningDir);
46
+ const archiveFiles = files.filter((f) => f.includes('.old.jsonl'));
47
+ expect(archiveFiles.length).toBeGreaterThan(0);
48
+ // Check that new file has only 1 entry
49
+ const newLog = readFeedbackLog();
50
+ expect(newLog.length).toBe(1);
51
+ });
52
+ it('does not rotate when below threshold', () => {
53
+ const testEntry = {
54
+ id: 'test-1',
55
+ timestamp: new Date().toISOString(),
56
+ session_id: 'session-1',
57
+ project_path: '/test',
58
+ event_type: 'revision',
59
+ user_message: 'Test message',
60
+ feedback_category: 'correction',
61
+ confidence: 0.9,
62
+ };
63
+ // Add a few entries (below threshold)
64
+ for (let i = 0; i < 5; i++) {
65
+ appendFeedback({ ...testEntry, id: `test-${i}` });
66
+ }
67
+ const learningDir = join(TEST_DIR, '.claude', 'olympus', 'learning');
68
+ const files = require('fs').readdirSync(learningDir);
69
+ const archiveFiles = files.filter((f) => f.includes('.old.jsonl'));
70
+ expect(archiveFiles.length).toBe(0);
71
+ const log = readFeedbackLog();
72
+ expect(log.length).toBe(5);
73
+ });
74
+ });
75
+ //# sourceMappingURL=storage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../../src/__tests__/learning/storage.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAgB,MAAM,IAAI,CAAC;AAChF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,eAAe,EAAkB,MAAM,2BAA2B,CAAC;AAG5F,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAEvD,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,UAAU,CAAC,GAAG,EAAE;QACd,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;QAC5B,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,SAAS,GAAkB;YAC/B,EAAE,EAAE,QAAQ;YACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,UAAU,EAAE,WAAW;YACvB,YAAY,EAAE,OAAO;YACrB,UAAU,EAAE,UAAU;YACtB,YAAY,EAAE,cAAc;YAC5B,iBAAiB,EAAE,YAAY;YAC/B,UAAU,EAAE,GAAG;SAChB,CAAC;QAEF,wDAAwD;QACxD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACrE,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;QAExD,yCAAyC;QACzC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,SAAS,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QAEzD,6CAA6C;QAC7C,cAAc,CAAC,SAAS,CAAC,CAAC;QAE1B,sCAAsC;QACtC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;QAE3E,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAE/C,uCAAuC;QACvC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,SAAS,GAAkB;YAC/B,EAAE,EAAE,QAAQ;YACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,UAAU,EAAE,WAAW;YACvB,YAAY,EAAE,OAAO;YACrB,UAAU,EAAE,UAAU;YACtB,YAAY,EAAE,cAAc;YAC5B,iBAAiB,EAAE,YAAY;YAC/B,UAAU,EAAE,GAAG;SAChB,CAAC;QAEF,sCAAsC;QACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,cAAc,CAAC,EAAE,GAAG,SAAS,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;QAE3E,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpC,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}