diff --git a/examples/workflows/memory-stack-integration.md b/examples/workflows/memory-stack-integration.md new file mode 100644 index 0000000..0504ae8 --- /dev/null +++ b/examples/workflows/memory-stack-integration.md @@ -0,0 +1,854 @@ +# Memory Stack Integration: Real-World Multi-Day Workflow + +**Scenario**: Refactoring authentication system from session-based to JWT across a 5-day sprint + +**Tools Used**: claude-mem (auto capture) + Serena (manual decisions) + grepai (discovery) + rg (exact search) + +**Project**: E-commerce API (Node.js/TypeScript, 50k lines, 200+ files) + +--- + +## Day 1: Discovery & Planning + +### Morning: Initial Exploration + +**User**: "Let's explore the current authentication system" + +**Claude** (with no claude-mem yet): +```bash +# Manual discovery +rg "authenticate|session" --type ts | head -20 +# 47 matches across 12 files +``` + +**Problem**: Too many files, no context on architecture decisions. + +--- + +### After Installing claude-mem + +```bash +# Install claude-mem +/plugin marketplace add thedotmack/claude-mem +/plugin install claude-mem +# Restart Claude Code +``` + +**User**: "Explore authentication architecture" + +**Claude** (now with auto-capture): +```bash +# 1. SEMANTIC DISCOVERY (grepai) +grepai search "authentication and session management" +# โ†’ Finds: +# - src/auth/auth.service.ts (main service) +# - src/middleware/session.middleware.ts (session handling) +# - src/controllers/user.controller.ts (endpoints) +# - config/session.config.ts (session config) + +# 2. STRUCTURAL OVERVIEW (Serena) +serena get_symbols_overview --file src/auth/auth.service.ts +# โ†’ AuthService class: +# - login(email, password) +# - logout(sessionId) +# - validateSession(sessionId) +# - createSession(userId) + +# 3. CALL GRAPH (grepai) +grepai trace callers "createSession" +# โ†’ Called by: +# - UserController.login() (47 times) +# - AdminController.authenticate() (12 times) +# - OAuthController.callback() (8 times) + +# 4. EXACT SEARCH (rg) +rg "express-session" --type ts +# โ†’ Found in: +# - package.json (dependency) +# - session.middleware.ts (import) +# - app.ts (config) +``` + +**claude-mem** automatically captures: +- 4 files read (auth.service.ts, session.middleware.ts, user.controller.ts, session.config.ts) +- 67 tool calls (reads, searches, traces) +- Key finding: "Current system uses express-session, stored in Redis" + +--- + +### Afternoon: Architectural Decision + +**User**: "Should we use JWT or stick with sessions?" + +**Discussion**: +- JWT: Stateless, scalable, no Redis dependency +- Sessions: Server-side control, easy revocation +- **Decision**: JWT for API, keep sessions for web dashboard + +**Record Decision (Serena)**: +```bash +serena write_memory "auth_architecture" "$(cat <<'EOF' +Decision: Migrate API to JWT, keep sessions for web dashboard. + +Rationale: +- API clients (mobile, SPA) benefit from stateless JWT +- Web dashboard needs session revocation (admin logout) +- Hybrid approach: /api/* uses JWT, /admin/* uses sessions + +Library choice: jose (vs jsonwebtoken) +- Lighter (40% fewer dependencies) +- Better TypeScript support +- Active maintenance (last update: 2 weeks ago) + +Next steps: +1. Install jose +2. Create JwtService +3. Update UserController to use JWT for /api/* routes +4. Keep SessionMiddleware for /admin/* routes +EOF +)" +``` + +**claude-mem** automatically captures: +- Decision discussion (compressed summary) +- Serena write_memory call +- Rationale for JWT + jose library + +--- + +### End of Day 1 + +**Claude** auto-generates session summary: +``` +Session Summary (Day 1): +- Explored authentication system (4 key files identified) +- Current: express-session + Redis +- Decision: Migrate to JWT for API, keep sessions for admin +- Library: jose (lighter, better TS support) +- Next: Install jose, create JwtService +``` + +**claude-mem dashboard** (`http://localhost:37777`): +- Timeline: 67 observations +- Key files: auth.service.ts, session.middleware.ts +- Decision recorded: auth_architecture + +--- + +## Day 2: Implementation Start + +### Morning: Session Resume + +**Claude** (auto-injected context): +``` +๐Ÿ“‹ Previous Session (Day 1): +- Explored auth system (4 files: auth.service.ts, session.middleware.ts, user.controller.ts, session.config.ts) +- Decision: JWT for API, sessions for admin +- Library: jose (40% lighter than jsonwebtoken) +- Next steps: Install jose, create JwtService +``` + +**User**: "Let's implement JWT service" + +**Claude** (already has context, no re-reading): +```bash +# Install jose +npm install jose + +# Create JWT service +``` + +**Implementation**: +```typescript +// src/auth/jwt.service.ts +import * as jose from 'jose'; + +export class JwtService { + private secret: Uint8Array; + + constructor(secretKey: string) { + this.secret = new TextEncoder().encode(secretKey); + } + + async generateToken(userId: string, email: string): Promise { + const jwt = await new jose.SignJWT({ userId, email }) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime('24h') + .sign(this.secret); + + return jwt; + } + + async verifyToken(token: string): Promise<{ userId: string; email: string }> { + const { payload } = await jose.jwtVerify(token, this.secret); + return payload as { userId: string; email: string }; + } +} +``` + +**claude-mem** automatically captures: +- npm install jose +- JwtService implementation +- Method signatures (generateToken, verifyToken) + +--- + +### Afternoon: Decision Checkpoint + +**User**: "Should we add refresh tokens now or later?" + +**Discussion**: +- Refresh tokens = better security (short access tokens) +- BUT: More complexity, need database storage +- **Decision**: Add in Phase 2 (after basic JWT works) + +**Record Decision (Serena)**: +```bash +serena write_memory "jwt_refresh_tokens" "$(cat <<'EOF' +Decision: Defer refresh tokens to Phase 2 + +Rationale: +- Phase 1: Basic JWT (access tokens only, 24h expiry) +- Phase 2: Add refresh tokens (1 week expiry, stored in DB) + +Why defer: +- Validate JWT flow works first +- Avoid premature complexity +- Need to design refresh token storage schema + +Reminder for Phase 2: +- Refresh tokens in separate table (id, userId, token, expiresAt) +- Rotation on refresh (invalidate old, issue new) +- Endpoint: POST /api/auth/refresh +EOF +)" +``` + +**claude-mem** automatically captures: +- Refresh token discussion +- Decision to defer +- Phase 2 reminder + +--- + +### End of Day 2 + +**Claude** auto-generates session summary: +``` +Session Summary (Day 2): +- Installed jose library +- Implemented JwtService (generateToken, verifyToken) +- Decision: Defer refresh tokens to Phase 2 +- Next: Update UserController to use JwtService +``` + +**Memory Stack Status**: + +| Layer | Content | Tool | +|-------|---------|------| +| **Session capture** | Day 1-2 observations (134 total) | claude-mem | +| **Manual decisions** | 2 memories (auth_architecture, jwt_refresh_tokens) | Serena | +| **Code discovery** | 4 files indexed, call graph mapped | grepai | + +--- + +## Day 3: Integration + +### Morning: Session Resume + +**Claude** (auto-injected context): +``` +๐Ÿ“‹ Previous Sessions (Day 1-2): +- Day 1: Explored auth, decided JWT for API +- Day 2: Implemented JwtService, deferred refresh tokens to Phase 2 +- Files modified: jwt.service.ts +- Next: Update UserController to use JwtService +``` + +**User**: "Update login endpoint to return JWT" + +**Claude** (already knows the context): +```bash +# 1. FIND DEPENDENCIES (grepai) +grepai trace callers "login" +# โ†’ UserController.login() called by 47 routes + +# 2. READ CURRENT IMPLEMENTATION (rg + Read) +rg "async login" src/controllers/user.controller.ts -A 10 +``` + +**Current Implementation**: +```typescript +// src/controllers/user.controller.ts (before) +async login(req: Request, res: Response) { + const { email, password } = req.body; + const user = await this.authService.authenticate(email, password); + + if (!user) { + return res.status(401).json({ error: 'Invalid credentials' }); + } + + // OLD: Create session + const sessionId = await this.authService.createSession(user.id); + req.session.userId = user.id; + + return res.json({ success: true, sessionId }); +} +``` + +**Update to JWT**: +```typescript +// src/controllers/user.controller.ts (after) +import { JwtService } from '../auth/jwt.service'; + +async login(req: Request, res: Response) { + const { email, password } = req.body; + const user = await this.authService.authenticate(email, password); + + if (!user) { + return res.status(401).json({ error: 'Invalid credentials' }); + } + + // NEW: Generate JWT + const token = await this.jwtService.generateToken(user.id, user.email); + + return res.json({ success: true, token }); +} +``` + +**claude-mem** automatically captures: +- UserController modification +- Removed: createSession call, session storage +- Added: JWT generation + +--- + +### Afternoon: Middleware Update + +**User**: "Create JWT authentication middleware" + +**Implementation**: +```typescript +// src/middleware/jwt.middleware.ts +import { Request, Response, NextFunction } from 'express'; +import { JwtService } from '../auth/jwt.service'; + +export function jwtAuthMiddleware(jwtService: JwtService) { + return async (req: Request, res: Response, next: NextFunction) => { + const authHeader = req.headers.authorization; + + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return res.status(401).json({ error: 'Missing or invalid token' }); + } + + const token = authHeader.slice(7); // Remove "Bearer " + + try { + const payload = await jwtService.verifyToken(token); + req.user = payload; // Attach user to request + next(); + } catch (error) { + return res.status(401).json({ error: 'Invalid or expired token' }); + } + }; +} +``` + +**Apply to API routes**: +```typescript +// src/app.ts +import { jwtAuthMiddleware } from './middleware/jwt.middleware'; + +// Apply JWT middleware to /api/* routes +app.use('/api/*', jwtAuthMiddleware(jwtService)); + +// Keep session middleware for /admin/* routes +app.use('/admin/*', sessionMiddleware); +``` + +**claude-mem** automatically captures: +- New middleware: jwt.middleware.ts +- Route split: /api/* (JWT) vs /admin/* (sessions) +- Backward compatibility maintained + +--- + +### End of Day 3 + +**User**: "Record the migration status" + +**Serena Memory Update**: +```bash +serena write_memory "jwt_migration_status" "$(cat <<'EOF' +JWT Migration Status (Day 3): + +โœ… Completed: +- JwtService implemented (jose library) +- UserController.login() updated to return JWT +- jwtAuthMiddleware created and applied to /api/* routes +- Admin routes still use sessions (/admin/*) + +๐Ÿ“ Files Modified: +- src/auth/jwt.service.ts (new) +- src/middleware/jwt.middleware.ts (new) +- src/controllers/user.controller.ts (updated) +- src/app.ts (route split) + +๐Ÿงช Next Steps (Day 4): +1. Write tests for JwtService +2. Test login flow end-to-end +3. Update API clients to use JWT (frontend, mobile) +4. Monitor logs for any session-related errors + +โš ๏ธ Rollback Plan: +- Keep session code intact (not deleted) +- Can revert by changing app.ts route config +- Database unchanged (no schema migration needed) +EOF +)" +``` + +**claude-mem dashboard** shows: +- 3 days of history +- 217 observations total +- 3 Serena memories (arch, refresh_tokens, migration_status) +- 8 files modified + +--- + +## Day 4: Testing & Validation + +### Morning: Session Resume + +**Claude** (auto-injected context): +``` +๐Ÿ“‹ Previous Sessions (Day 1-3): +- Day 1: Explored auth, decided JWT +- Day 2: Implemented JwtService +- Day 3: Updated login endpoint, created JWT middleware +- Status: /api/* uses JWT, /admin/* uses sessions +- Next: Write tests, validate end-to-end +``` + +**User**: "Write tests for JwtService" + +**Claude** (knows implementation from Day 2): +```typescript +// src/auth/__tests__/jwt.service.test.ts +import { JwtService } from '../jwt.service'; + +describe('JwtService', () => { + let jwtService: JwtService; + + beforeEach(() => { + jwtService = new JwtService('test-secret-key-32-chars-long!!'); + }); + + describe('generateToken', () => { + it('should generate valid JWT token', async () => { + const token = await jwtService.generateToken('user-123', 'test@example.com'); + + expect(token).toBeDefined(); + expect(typeof token).toBe('string'); + expect(token.split('.')).toHaveLength(3); // JWT format: header.payload.signature + }); + + it('should include userId and email in payload', async () => { + const token = await jwtService.generateToken('user-456', 'user@example.com'); + const payload = await jwtService.verifyToken(token); + + expect(payload.userId).toBe('user-456'); + expect(payload.email).toBe('user@example.com'); + }); + + it('should set 24h expiration', async () => { + const token = await jwtService.generateToken('user-789', 'exp@example.com'); + const payload = await jwtService.verifyToken(token); + + // JWT exp is in seconds, not milliseconds + const now = Math.floor(Date.now() / 1000); + const expectedExp = now + (24 * 60 * 60); // 24 hours + + expect(payload.exp).toBeGreaterThan(now); + expect(payload.exp).toBeLessThanOrEqual(expectedExp + 10); // 10s tolerance + }); + }); + + describe('verifyToken', () => { + it('should verify valid token', async () => { + const token = await jwtService.generateToken('user-abc', 'valid@example.com'); + const payload = await jwtService.verifyToken(token); + + expect(payload).toEqual({ + userId: 'user-abc', + email: 'valid@example.com', + iat: expect.any(Number), + exp: expect.any(Number) + }); + }); + + it('should throw on invalid token', async () => { + await expect(jwtService.verifyToken('invalid.token.here')) + .rejects.toThrow(); + }); + + it('should throw on expired token', async () => { + // Create token with -1h expiration (already expired) + const jwtService2 = new JwtService('test-secret'); + const expiredToken = await jwtService2.generateToken('user-old', 'old@example.com'); + + // Wait 2 seconds (simulate expiration) + await new Promise(resolve => setTimeout(resolve, 2000)); + + await expect(jwtService2.verifyToken(expiredToken)) + .rejects.toThrow('expired'); + }); + + it('should throw on token with wrong secret', async () => { + const token = await jwtService.generateToken('user-123', 'test@example.com'); + + // Try to verify with different secret + const jwtService2 = new JwtService('different-secret-key-here!!!!'); + await expect(jwtService2.verifyToken(token)) + .rejects.toThrow(); + }); + }); +}); +``` + +**Run Tests**: +```bash +npm test jwt.service.test.ts + +# Output: +# JwtService +# generateToken +# โœ“ should generate valid JWT token (45ms) +# โœ“ should include userId and email in payload (32ms) +# โœ“ should set 24h expiration (28ms) +# verifyToken +# โœ“ should verify valid token (21ms) +# โœ“ should throw on invalid token (15ms) +# โœ“ should throw on expired token (2018ms) +# โœ“ should throw on token with wrong secret (19ms) +# +# Tests: 7 passed, 7 total +``` + +**claude-mem** automatically captures: +- Test file created (jwt.service.test.ts) +- 7 test cases (all passing) +- Edge cases tested (invalid, expired, wrong secret) + +--- + +### Afternoon: End-to-End Test + +**User**: "Test the full login flow" + +**Manual E2E Test**: +```bash +# 1. Login (get JWT) +curl -X POST http://localhost:3000/api/auth/login \ + -H "Content-Type: application/json" \ + -d '{"email":"test@example.com","password":"password123"}' + +# Response: +# { +# "success": true, +# "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c2VyLTEyMyIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImlhdCI6MTcwNzU4MjAwMCwiZXhwIjoxNzA3NjY4NDAwfQ.xYz..." +# } + +# 2. Access protected API endpoint +curl -X GET http://localhost:3000/api/profile \ + -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + +# Response: +# { +# "userId": "user-123", +# "email": "test@example.com", +# "profile": { ... } +# } + +# 3. Test without token (should fail) +curl -X GET http://localhost:3000/api/profile + +# Response: +# { "error": "Missing or invalid token" } + +# 4. Test admin route (should still use sessions) +curl -X GET http://localhost:3000/admin/dashboard \ + -H "Cookie: connect.sid=s%3A..." + +# Response: +# { "dashboard": "admin data" } +``` + +**โœ… All tests pass!** + +**Record Validation (Serena)**: +```bash +serena write_memory "jwt_validation_results" "$(cat <<'EOF' +JWT Validation Results (Day 4): + +โœ… Unit Tests: 7/7 passed +- Token generation works +- Token verification works +- Expiration handling correct +- Error cases handled (invalid, expired, wrong secret) + +โœ… E2E Tests: 4/4 passed +- Login returns JWT +- Protected routes accept JWT +- Unauthorized requests rejected +- Admin routes still use sessions (backward compatibility) + +๐Ÿ“Š Performance: +- Token generation: ~30ms +- Token verification: ~20ms +- No Redis dependency (stateless) + +โš ๏ธ Observations: +- Frontend needs update to store JWT (localStorage) +- Mobile app needs update to send Authorization header +- Consider token refresh after 24h (Phase 2) + +โœ… Ready for deployment +EOF +)" +``` + +--- + +### End of Day 4 + +**Memory Search Demo**: + +```bash +# User searches session history +"Search my memory for JWT decisions" +``` + +**claude-mem returns**: +``` +๐Ÿ” Found 3 relevant sessions: + +Session 1 (Day 1): +- Decision: JWT for API, sessions for admin +- Library: jose (40% lighter) + +Session 2 (Day 2): +- Implemented JwtService +- Deferred refresh tokens to Phase 2 + +Session 4 (Day 4): +- All tests passing (7/7 unit, 4/4 E2E) +- Ready for deployment +``` + +**Memory Stack Final Status**: + +| Layer | Content | Tool | +|-------|---------|------| +| **Session capture** | 4 days, 312 observations | claude-mem | +| **Manual decisions** | 4 memories (arch, refresh, migration, validation) | Serena | +| **Code discovery** | 8 files modified, call graph updated | grepai | + +--- + +## Day 5: Deployment + +### Morning: Pre-Deployment Check + +**User**: "What did we accomplish this week?" + +**Claude** (query claude-mem): +``` +"Show summary of JWT migration project" +``` + +**claude-mem comprehensive summary**: +``` +๐Ÿ“‹ JWT Migration Project Summary (5 days): + +Day 1: Discovery & Planning +- Explored auth system (4 key files) +- Decision: JWT for API, sessions for admin +- Library: jose (40% lighter, better TS) + +Day 2: Implementation +- Installed jose +- Created JwtService (generateToken, verifyToken) +- Deferred refresh tokens to Phase 2 + +Day 3: Integration +- Updated UserController.login() +- Created jwtAuthMiddleware +- Applied to /api/*, kept sessions for /admin/* + +Day 4: Testing +- Unit tests: 7/7 passed +- E2E tests: 4/4 passed +- Validation complete + +๐Ÿ“Š Impact: +- Files modified: 8 +- Tool calls: 312 +- Dependencies removed: express-session, connect-redis +- Dependencies added: jose +- Performance: Stateless (no Redis lookups) + +โœ… Ready for deployment +``` + +**Serena Memories Available**: +```bash +serena list_memories + +# Output: +# 1. auth_architecture (Day 1) +# 2. jwt_refresh_tokens (Day 2) +# 3. jwt_migration_status (Day 3) +# 4. jwt_validation_results (Day 4) +``` + +--- + +### Afternoon: Deployment & Handoff + +**User**: "Deploy to staging" + +```bash +# Deploy to staging +git checkout -b feature/jwt-migration +git add . +git commit -m "feat: migrate API authentication to JWT + +- Replace express-session with JWT (jose library) +- Apply JWT to /api/* routes +- Keep sessions for /admin/* routes +- Add comprehensive tests (7 unit, 4 E2E) +- All tests passing + +Breaking changes: None (backward compatible) +Migration: None required (no DB changes) +Rollback: Change app.ts route config" + +git push origin feature/jwt-migration + +# Create PR +gh pr create --title "Migrate API to JWT authentication" \ + --body "$(serena read_memory jwt_migration_status)" +``` + +**Handoff Document** (auto-generated from memories): +```bash +# Generate handoff doc from Serena memories +serena read_memory auth_architecture > docs/jwt-migration.md +serena read_memory jwt_migration_status >> docs/jwt-migration.md +serena read_memory jwt_validation_results >> docs/jwt-migration.md +``` + +**Result**: Complete documentation of architectural decisions, implementation details, and validation results. + +--- + +## ๐ŸŽฏ Key Takeaways + +### Memory Stack in Action + +**Without Memory Stack**: +- Re-read files every day (~200 files ร— 5 days = 1000 reads) +- Lose context between sessions +- Forget architectural decisions +- Manual documentation of decisions + +**With Memory Stack (claude-mem + Serena + grepai)**: +- Auto-injected context every morning (0 re-reads) +- Preserved architectural decisions (4 Serena memories) +- Call graph maintained (grepai traces) +- Comprehensive session history (312 observations) +- **Result**: 5-day project completed with full context retention + +--- + +### Token Efficiency + +| Metric | Without | With Memory Stack | Savings | +|--------|---------|-------------------|---------| +| **File reads** | 1000 | 150 (85% reduction) | 850 reads | +| **Input tokens** | ~500k | ~75k (85% reduction) | 425k tokens | +| **Context loss** | Every session | Never | 100% retention | +| **Decision recall** | Manual notes | 4 Serena memories | Instant | + +**Progressive Disclosure Impact**: +- Day 5 summary query: 3 layers (search โ†’ timeline โ†’ details) +- Without: Load all 312 observations (~50k tokens) +- With: Load summary โ†’ 5 sessions โ†’ 1 detail (~5k tokens) +- **Savings**: 90% tokens + +--- + +### Practical Insights + +**When to Use Each Tool**: + +1. **claude-mem** (automatic): + - Session start/end (auto) + - "What did we do yesterday?" + - "Show me the full project history" + +2. **Serena** (manual, high-value): + - Architectural decisions + - Library choices + - Migration status + - Rollback plans + +3. **grepai** (semantic discovery): + - "Find authentication code" + - "Who calls this function?" + - "Show dependency graph" + +4. **rg** (exact search): + - "Find import statements" + - "Show all TODOs" + - "Grep for specific pattern" + +--- + +### Cost Analysis + +**5-Day Project**: + +| Tool | Cost | Notes | +|------|------|-------| +| **claude-mem** | $4.68 | 312 observations ร— $0.15/100 | +| **Serena** | Free | Local storage | +| **grepai** | Free | Local Ollama | +| **Total** | **$4.68** | For 5 days of perfect memory | + +**ROI**: 850 fewer file reads ร— ~500 tokens/read = 425k tokens saved = $4.25 (at $0.01/1k tokens) + +**Net cost**: $0.43 for complete memory across 5 days + +--- + +## ๐Ÿ”— Resources + +**Memory Stack Tools**: +- [claude-mem GitHub](https://github.com/thedotmack/claude-mem) +- [Serena GitHub](https://github.com/oraios/serena) +- [grepai GitHub](https://github.com/yoanbernabeu/grepai) + +**Guide Sections**: +- Section 8.2.3: Serena (Symbol Memory) +- Section 8.2.4: grepai (Semantic Search) +- Section 8.2.5: claude-mem (Automatic Session Memory) +- Memory Tools Decision Matrix: guide/ultimate-guide.md:8630 + +--- + +**Workflow Created**: 2026-02-10 +**Guide Version**: 3.24.0 +**Author**: Florian BRUNIAUX + Claude (Anthropic)