
Cm
- 58 installs
- 408 repo stars
- Updated August 4, 2026
- dicklesworthstone/cass_memory_system
Give coding agents persistent cross-agent procedural memory via a three-layer architecture with confidence decay and anti-pattern learning.
About
CM (CASS Memory System) turns scattered sessions into playbook rules shared across Claude Code, Cursor, Codex, and more. Use it before non-trivial tasks to retrieve relevant rules, anti-patterns, and history.
- cm context <task> --json returns scored rules and anti-patterns
- Cross-agent learning: a Cursor pattern helps Claude Code
Cm by the numbers
- 58 all-time installs (skills.sh)
- Ranked #6,589 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dicklesworthstone/cass_memory_system --skill cmAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 58 |
|---|---|
| repo stars | ★ 408 |
| Last updated | August 4, 2026 |
| Repository | dicklesworthstone/cass_memory_system ↗ |
What it does
Give coding agents persistent cross-agent procedural memory via a three-layer architecture with confidence decay and anti-pattern learning.
Files
CM - CASS Memory System
Procedural memory for AI coding agents. Transforms scattered sessions into persistent, cross-agent memory. Uses a three-layer cognitive architecture that mirrors human expertise development.
Why This Exists
AI coding agents accumulate valuable knowledge but it's:
- Trapped in sessions - Context lost when session ends
- Agent-specific - Claude doesn't know what Cursor learned
- Unstructured - Raw logs aren't actionable guidance
- Subject to collapse - Naive summarization loses critical details
You've solved auth bugs three times this month across different agents. Each time you started from scratch.
CM solves this with cross-agent learning: a pattern discovered in Cursor is immediately available to Claude Code.
---
Three-Layer Cognitive Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ EPISODIC MEMORY (cass) │
│ Raw session logs from all agents — the "ground truth" │
│ Claude Code │ Codex │ Cursor │ Aider │ PI │ Gemini │ ChatGPT │ ...│
└───────────────────────────┬─────────────────────────────────────────┘
│ cass search
▼
┌─────────────────────────────────────────────────────────────────────┐
│ WORKING MEMORY (Diary) │
│ Structured session summaries: accomplishments, decisions, etc. │
└───────────────────────────┬─────────────────────────────────────────┘
│ reflect + curate (automated)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ PROCEDURAL MEMORY (Playbook) │
│ Distilled rules with confidence tracking and decay │
└─────────────────────────────────────────────────────────────────────┘Every agent's sessions feed the shared memory. A pattern discovered in Cursor automatically helps Claude Code on the next session.
---
The One Command You Need
cm context "<your task>" --jsonRun this before starting any non-trivial task. Returns:
- relevantBullets - Rules from playbook scored by task relevance
- antiPatterns - Things that have caused problems
- historySnippets - Past sessions (yours and other agents')
- suggestedCassQueries - Deeper investigation searches
Filtering History by Source
historySnippets[].origin.kind is "local" or "remote". Remote hits include origin.host:
{
"historySnippets": [
{
"source_path": "~/.claude/sessions/session-001.jsonl",
"origin": { "kind": "local" }
},
{
"source_path": "/home/user/.codex/sessions/session.jsonl",
"origin": { "kind": "remote", "host": "workstation" }
}
]
}---
Confidence Decay System
Rules aren't immortal. Confidence decays without revalidation:
| Mechanism | Effect |
|---|---|
| 90-day half-life | Confidence halves every 90 days without feedback |
| 4x harmful multiplier | One mistake counts 4× as much as one success |
| Maturity progression | candidate → established → proven |
Score Decay Visualization
Initial score: 10.0 (10 helpful marks today)
After 90 days (half-life): 5.0
After 180 days: 2.5
After 270 days: 1.25
After 365 days: 0.78Effective Score Formula
effectiveScore = decayedHelpful - (4 × decayedHarmful)
// Where decay factor = 0.5 ^ (daysSinceFeedback / 90)Maturity State Machine
┌──────────┐ ┌─────────────┐ ┌────────┐
│ candidate│──────▶│ established │───▶│ proven │
└──────────┘ └─────────────┘ └────────┘
│ │ │
│ │ (harmful >25%) │
│ ▼ │
│ ┌─────────────┐ │
└────────────▶│ deprecated │◀─────────┘
└─────────────┘Transition Rules:
| Transition | Criteria |
|---|---|
candidate → established | 3+ helpful, harmful ratio <25% |
established → proven | 10+ helpful, harmful ratio <10% |
any → deprecated | Harmful ratio >25% OR explicit deprecation |
---
Anti-Pattern Learning
Bad rules don't just get deleted. They become warnings:
"Cache auth tokens for performance"
↓ (3 harmful marks)
"PITFALL: Don't cache auth tokens without expiry validation"When a rule is marked harmful multiple times (>50% harmful ratio with 3+ marks), it's automatically inverted into an anti-pattern.
---
ACE Pipeline (How Rules Are Created)
Generator → Reflector → Validator → Curator| Stage | Role | LLM? |
|---|---|---|
| Generator | Pre-task context hydration (cm context) | No |
| Reflector | Extract patterns from sessions (cm reflect) | Yes |
| Validator | Evidence gate against cass history | Yes |
| Curator | Deterministic delta merge | No |
Critical: Curator has NO LLM to prevent context collapse from iterative drift. LLMs propose patterns; deterministic logic manages them.
Scientific Validation
Before a rule joins your playbook, it's validated against cass history:
Proposed rule: "Always check token expiry before auth debugging"
↓
Evidence gate: Search cass for sessions where this applied
↓
Result: 5 sessions found, 4 successful outcomes → ACCEPTRules without historical evidence are flagged as candidates until proven.
---
Commands Reference
Context Retrieval (Primary Workflow)
# THE MAIN COMMAND - run before non-trivial tasks
cm context "implement user authentication" --json
# Limit results for token budget
cm context "fix bug" --json --limit 5 --no-history
# With workspace filter
cm context "refactor" --json --workspace /path/to/project
# Self-documenting explanation
cm quickstart --json
# System health
cm doctor --json
cm doctor --fix # Auto-fix issues
# Find similar rules
cm similar "error handling best practices"Playbook Management
cm playbook list # All rules
cm playbook get b-8f3a2c # Rule details
cm playbook add "Always run tests first" # Add rule
cm playbook add --file rules.json # Batch add from file
cm playbook add --file rules.json --session /path/session.jsonl # Track source
cm playbook remove b-xyz --reason "Outdated" # Remove
cm playbook export > backup.yaml # Export
cm playbook import shared.yaml # Import
cm playbook bootstrap react # Apply starter to existing
cm top 10 # Top effective rules
cm stale --days 60 # Rules without recent feedback
cm why b-8f3a2c # Rule provenance
cm stats --json # Playbook health metricsLearning & Feedback
# Manual feedback
cm mark b-8f3a2c --helpful
cm mark b-xyz789 --harmful --reason "Caused regression"
cm undo b-xyz789 # Revert feedback
# Session outcomes (positional: status, rules)
cm outcome success b-8f3a2c,b-def456
cm outcome failure b-x7k9p1 --summary "Auth approach failed"
cm outcome-apply # Apply to playbook
# Reflection (usually automated)
cm reflect --days 7 --json
cm reflect --session /path/to/session.jsonl # Single session
cm reflect --workspace /path/to/project # Project-specific
# Validation
cm validate "Always check null before dereferencing"
# Audit sessions against rules
cm audit --days 30
# Deprecate permanently
cm forget b-xyz789 --reason "Superseded by better pattern"Onboarding (Agent-Native)
Zero-cost playbook building using your existing agent:
cm onboard status # Check progress
cm onboard gaps # Category gaps
cm onboard sample --fill-gaps # Prioritized sessions
cm onboard sample --agent claude --days 14 # Filter by agent/time
cm onboard sample --workspace /path/project # Filter by workspace
cm onboard sample --include-processed # Re-analyze sessions
cm onboard read /path/session.jsonl --template # Rich context
cm onboard mark-done /path/session.jsonl # Mark processed
cm onboard reset # Start freshTrauma Guard (Safety System)
cm trauma list # Active patterns
cm trauma add "DROP TABLE" --description "Mass deletion" --severity critical
cm trauma heal t-abc --reason "Intentional migration"
cm trauma remove t-abc
cm trauma scan --days 30 # Scan for traumas
cm trauma import shared-traumas.yaml
cm guard --install # Claude Code hook
cm guard --git # Git pre-commit hook
cm guard --install --git # Both
cm guard --status # Check installationSystem Commands
cm init # Initialize
cm init --starter typescript # With template
cm init --force # Reinitialize (creates backup)
cm starters # List templates
cm serve --port 3001 # MCP server
cm usage # LLM cost stats
cm privacy status # Privacy settings
cm privacy enable # Enable cross-agent enrichment
cm privacy disable # Disable enrichment
cm project --format agents.md # Export for AGENTS.md---
Starter Playbooks
Starting with an empty playbook is daunting. Starters provide curated best practices:
cm starters # List available
cm init --starter typescript # Initialize with starter
cm playbook bootstrap react # Apply to existing playbookBuilt-in Starters
| Starter | Focus | Rules |
|---|---|---|
| general | Universal best practices | 5 |
| typescript | TypeScript/Node.js patterns | 4 |
| react | React/Next.js development | 4 |
| python | Python/FastAPI/Django | 4 |
| node | Node.js/Express services | 4 |
| rust | Rust service patterns | 4 |
Custom Starters
Create YAML files in ~/.cass-memory/starters/:
# ~/.cass-memory/starters/django.yaml
name: django
description: Django web framework best practices
bullets:
- content: "Always use Django's ORM for database operations"
category: database
maturity: established
tags: [django, orm]---
Inline Feedback (During Work)
Leave feedback in code comments. Parsed during reflection:
// [cass: helpful b-8f3a2c] - this rule saved me from a rabbit hole
// [cass: harmful b-x7k9p1] - this advice was wrong for our use case---
Agent Protocol
1. START: cm context "<task>" --json
2. WORK: Reference rule IDs when following them (e.g., "Following b-8f3a2c...")
3. FEEDBACK: Leave inline comments when rules help/hurt
4. END: Just finish. Learning happens automatically.You do NOT need to:
- Run
cm reflect(automation handles this) - Run
cm markmanually (use inline comments) - Manually add rules to the playbook
---
Gap Analysis Categories
| Category | Keywords |
|---|---|
debugging | error, fix, bug, trace, stack |
testing | test, mock, assert, expect, jest |
architecture | design, pattern, module, abstraction |
workflow | task, CI/CD, deployment |
documentation | comment, README, API doc |
integration | API, HTTP, JSON, endpoint |
collaboration | review, PR, team |
git | branch, merge, commit |
security | auth, token, encrypt, permission |
performance | optimize, cache, profile |
Category Status Thresholds:
| Status | Rule Count | Priority |
|---|---|---|
critical | 0 rules | High |
underrepresented | 1-2 rules | Medium |
adequate | 3-10 rules | Low |
well-covered | 11+ rules | None |
---
Trauma Guard: Safety System
The "hot stove" principle—learn from past incidents and prevent recurrence.
How It Works
Session History Trauma Registry Runtime Guard
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ rm -rf /* (oops)│ ──────▶ │ Pattern: rm -rf │ ──────▶ │ BLOCKED: This │
│ "sorry, I made │ scan │ Severity: FATAL │ hook │ command matches │
│ a mistake..." │ │ Session: abc123 │ │ a trauma pattern│
└─────────────────┘ └─────────────────┘ └─────────────────┘Built-in Doom Patterns (20+)
| Category | Examples |
|---|---|
| Filesystem | rm -rf /, rm -rf ~, recursive deletes |
| Database | DROP DATABASE, TRUNCATE, DELETE FROM without WHERE |
| Git | git push --force to main/master, git reset --hard |
| Infrastructure | terraform destroy -auto-approve, kubectl delete namespace |
| Cloud | aws s3 rm --recursive, destructive CloudFormation |
Pattern Storage
| Scope | Location | Purpose |
|---|---|---|
| Global | ~/.cass-memory/traumas.jsonl | Personal patterns |
| Project | .cass/traumas.jsonl | Commit to repo for team |
Pattern Lifecycle
- Active: Blocks matching commands
- Healed: Temporarily bypassed (with reason and timestamp)
- Deleted: Removed (can be re-added)
---
MCP Server
Run as MCP server for agent integration:
# Local-only (recommended)
cm serve --port 3001
# With auth token (for non-loopback)
MCP_HTTP_TOKEN="<random>" cm serve --host 0.0.0.0 --port 3001Tools Exposed
| Tool | Purpose | Parameters |
|---|---|---|
cm_context | Get rules + history | task, limit?, history?, days?, workspace? |
cm_feedback | Record feedback | bulletId, helpful?, harmful?, reason? |
cm_outcome | Record session outcome | sessionId, outcome, rulesUsed? |
memory_search | Search playbook/cass | query, scope?, limit?, days? |
memory_reflect | Trigger reflection | days?, maxSessions?, dryRun? |
Resources Exposed
| URI | Purpose |
|---|---|
cm://playbook | Current playbook state |
cm://diary | Recent diary entries |
cm://outcomes | Session outcomes |
cm://stats | Playbook health metrics |
Client Configuration
Claude Code (~/.config/claude/mcp.json):
{
"mcpServers": {
"cm": {
"command": "cm",
"args": ["serve"]
}
}
}---
Graceful Degradation
| Condition | Behavior |
|---|---|
| No cass | Playbook-only scoring, no history snippets |
| No playbook | Empty playbook, commands still work |
| No LLM | Deterministic reflection, no semantic enhancement |
| Offline | Cached playbook + local diary |
---
Output Format
All commands support --json for machine-readable output.
Design principle: stdout = JSON only; diagnostics go to stderr.
Success Response
{
"success": true,
"task": "fix the auth timeout bug",
"relevantBullets": [
{
"id": "b-8f3a2c",
"content": "Always check token expiry before auth debugging",
"effectiveScore": 8.5,
"maturity": "proven",
"relevanceScore": 0.92,
"reasoning": "Extracted from 5 successful sessions"
}
],
"antiPatterns": [...],
"historySnippets": [...],
"suggestedCassQueries": [...],
"degraded": null
}Error Response
{
"success": false,
"code": "PLAYBOOK_NOT_FOUND",
"error": "Playbook file not found",
"hint": "Run 'cm init' to create a new playbook",
"retryable": false,
"recovery": ["cm init", "cm doctor --fix"],
"docs": "README.md#-troubleshooting"
}Exit Codes
| Code | Meaning |
|---|---|
| 1 | Internal error |
| 2 | User input/usage |
| 3 | Configuration |
| 4 | Filesystem |
| 5 | Network |
| 6 | cass error |
| 7 | LLM/provider error |
---
Token Budget Management
| Flag | Effect |
|---|---|
--limit N | Cap number of rules |
--min-score N | Only rules above threshold |
--no-history | Skip historical snippets (faster) |
--json | Structured output |
---
Configuration
Config lives at ~/.cass-memory/config.json (global) and .cass/config.json (repo).
Precedence: CLI flags > Repo config > Global config > Defaults
Security: Repo config cannot override sensitive paths or user-level consent settings.
Key Options
{
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"budget": {
"dailyLimit": 0.10,
"monthlyLimit": 2.00
},
"scoring": {
"decayHalfLifeDays": 90,
"harmfulMultiplier": 4
},
"maxBulletsInContext": 50,
"maxHistoryInContext": 10,
"sessionLookbackDays": 7,
"crossAgent": {
"enabled": false,
"consentGiven": false,
"auditLog": true
},
"remoteCass": {
"enabled": false,
"hosts": [{"host": "workstation", "label": "work"}]
},
"semanticSearchEnabled": false,
"embeddingModel": "Xenova/all-MiniLM-L6-v2",
"dedupSimilarityThreshold": 0.85
}Environment Variables
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY | API key for Anthropic (Claude) |
OPENAI_API_KEY | API key for OpenAI |
GOOGLE_GENERATIVE_AI_API_KEY | API key for Google Gemini |
CASS_PATH | Path to cass binary |
CASS_MEMORY_LLM | Set to none for LLM-free mode |
MCP_HTTP_TOKEN | Auth token for non-loopback MCP server |
---
Data Locations
~/.cass-memory/ # Global (user-level)
├── config.json # Configuration
├── playbook.yaml # Personal playbook
├── diary/ # Session summaries
├── outcomes/ # Session outcomes
├── traumas.jsonl # Trauma patterns
├── starters/ # Custom starter playbooks
├── onboarding-state.json # Onboarding progress
├── privacy-audit.jsonl # Cross-agent audit trail
├── processed-sessions.jsonl # Reflection progress
└── usage.jsonl # LLM cost tracking
.cass/ # Project-level (in repo)
├── config.json # Project-specific overrides
├── playbook.yaml # Project-specific rules
├── traumas.jsonl # Project-specific patterns
└── blocked.yaml # Anti-patterns to block---
Automating Reflection
Cron Job
# Daily at 2am
0 2 * * * /usr/local/bin/cm reflect --days 7 >> ~/.cass-memory/reflect.log 2>&1Claude Code Hook
.claude/hooks.json:
{
"post-session": ["cm reflect --days 1"]
}---
Privacy & Security
Local-First Design
- All data stays on your machine
- No cloud sync, no telemetry
- Cross-agent enrichment is opt-in with explicit consent
- Audit log for enrichment events
Secret Sanitization
Before processing, content is sanitized:
- OpenAI/Anthropic/AWS/Google API keys
- GitHub tokens
- JWTs
- Passwords and secrets in config patterns
Privacy Controls
cm privacy status # Check settings
cm privacy enable # Enable cross-agent enrichment
cm privacy disable # Disable enrichment---
Performance Characteristics
| Operation | Typical Latency |
|---|---|
cm context (cached) | 50-150ms |
cm context (cold) | 200-500ms |
cm context (no cass) | 30-80ms |
cm reflect (1 session) | 5-15s |
cm reflect (5 sessions) | 20-60s |
cm playbook list | <50ms |
cm similar (keyword) | 20-50ms |
cm similar (semantic) | 100-300ms |
LLM Cost Estimates
| Operation | Typical Cost |
|---|---|
| Reflect (1 session) | $0.01-0.05 |
| Reflect (7 days) | $0.05-0.20 |
| Validate (1 rule) | $0.005-0.01 |
With default budget ($0.10/day, $2.00/month): ~5-10 sessions/day.
---
Batch Rule Addition
After analyzing a session, add multiple rules at once:
# Create JSON file
cat > rules.json << 'EOF'
[
{"content": "Always run tests before committing", "category": "testing"},
{"content": "Check token expiry before auth debugging", "category": "debugging"},
{"content": "AVOID: Mocking entire modules in tests", "category": "testing"}
]
EOF
# Add all rules
cm playbook add --file rules.json
# Track which session they came from
cm playbook add --file rules.json --session /path/to/session.jsonl
# Or pipe from stdin
echo '[{"content": "Rule", "category": "workflow"}]' | cm playbook add --file ----
Template Output for Onboarding
--template provides rich context for rule extraction:
cm onboard read /path/to/session.jsonl --template --jsonReturns:
- metadata: path, workspace, message count, topic hints
- context: related rules, playbook gaps, suggested focus
- extractionFormat: schema, categories, examples
- sessionContent: actual session data
---
Integration with CASS
CASS provides episodic memory (raw sessions). CM extracts procedural memory (rules and playbooks).
# CASS: Search raw sessions
cass search "authentication timeout" --robot
# CM: Get distilled rules for a task
cm context "authentication timeout" --json---
Troubleshooting
| Error | Solution |
|---|---|
cass not found | Install from cass repo |
cass search failed | Run cass index --full |
API key missing | Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY |
Playbook corrupt | Run cm doctor --fix |
Budget exceeded | Check cm usage, adjust limits |
Diagnostic Commands
cm doctor --json # System health
cm doctor --fix # Auto-fix issues
cm usage # LLM budget status
cm stats --json # Playbook health
cm why <bullet-id> # Rule provenanceLLM-Free Mode
CASS_MEMORY_LLM=none cm context "task" --json---
Installation
# One-liner (recommended)
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/cass_memory_system/main/install.sh \
| bash -s -- --easy-mode --verify
# Specific version
install.sh --version v0.2.2 --verify
# System-wide
install.sh --system --verify
# From source
git clone https://github.com/Dicklesworthstone/cass_memory_system.git
cd cass_memory_system
bun install && bun run build
sudo mv ./dist/cass-memory /usr/local/bin/cm---
Integration with Flywheel
| Tool | Integration |
|---|---|
| CASS | CM reads from cass episodic memory, writes procedural memory |
| NTM | Robot mode integrates with cm for context before agent work |
| Agent Mail | Rules can reference mail threads as provenance |
| BV | Task context enriched with relevant playbook rules |
# SQLite databases
*.db
*.db?*
*.db-journal
*.db-wal
*.db-shm
# Daemon runtime files
daemon.lock
daemon.log
daemon.pid
bd.sock
sync-state.json
last-touched
# Local version tracking (prevents upgrade notification spam after git ops)
.local_version
# Legacy database files
db.sqlite
bd.db
# Worktree redirect file (contains relative path to main repo's .beads/)
# Must not be committed as paths would be wrong in other clones
redirect
# Merge artifacts (temporary files from 3-way merge)
beads.base.jsonl
beads.base.meta.json
beads.left.jsonl
beads.left.meta.json
beads.right.jsonl
beads.right.meta.json
# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here.
# They would override fork protection in .git/info/exclude, allowing
# contributors to accidentally commit upstream issue databases.
# The JSONL files (issues.jsonl, interactions.jsonl) and config files
# are tracked by git by default since no pattern above ignores them.
# Local history backups
.br_history/
# bv (beads viewer) lock file
.bv.lock
# Beads Configuration File
# This file configures default behavior for all bd commands in this repository
# All settings can also be set via environment variables (BD_* prefix)
# or overridden with command-line flags
# Issue prefix for this repository (used by bd init)
# If not set, bd init will auto-detect from directory name
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
# issue-prefix: ""
# Use no-db mode: load from JSONL, no SQLite, write back after each command
# When true, bd will use .beads/issues.jsonl as the source of truth
# instead of SQLite database
# no-db: false
# Disable daemon for RPC communication (forces direct database access)
# no-daemon: false
# Disable auto-flush of database to JSONL after mutations
# no-auto-flush: false
# Disable auto-import from JSONL when it's newer than database
# no-auto-import: false
# Enable JSON output by default
# json: false
# Default actor for audit trails (overridden by BD_ACTOR or --actor)
# actor: ""
# Path to database (overridden by BEADS_DB or --db)
# db: ""
# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
# auto-start-daemon: true
# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
# flush-debounce: "5s"
# Git branch for beads commits (bd sync will commit to this branch)
# IMPORTANT: Set this for team projects so all clones use the same sync branch.
# This setting persists across clones (unlike database config which is gitignored).
# Can also use BEADS_SYNC_BRANCH env var for local override.
# If not set, bd sync will require you to run 'bd config set sync.branch <branch>'.
sync-branch: "beads-sync"
# Multi-repo configuration (experimental - bd-307)
# Allows hydrating from multiple repositories and routing writes to the correct JSONL
# repos:
# primary: "." # Primary repo (where this database lives)
# additional: # Additional repos to hydrate from (read-only)
# - ~/beads-planning # Personal planning repo
# - ~/work-planning # Work planning repo
# Integration settings (access with 'bd config get/set')
# These are stored in the database, not in this file:
# - jira.url
# - jira.project
# - linear.url
# - linear.api-key
# - github.org
# - github.repo
{"id":"cass_memory_system-ulot","ts":"2025-12-07T21:50:16.045482Z","by":"jemanuel","reason":"batch delete"}
{"id":"cass_memory_system-8pmn","ts":"2025-12-07T21:50:16.050305Z","by":"jemanuel","reason":"batch delete"}
{"id":"cass_memory_system-gn8h","ts":"2025-12-07T21:50:16.054251Z","by":"jemanuel","reason":"batch delete"}
{"id":"cass_memory_system-bxfx","ts":"2025-12-07T21:50:16.057369Z","by":"jemanuel","reason":"batch delete"}
{"id":"cass_memory_system-js90","ts":"2025-12-07T21:50:16.061448Z","by":"jemanuel","reason":"batch delete"}
{
"database": "beads.db",
"jsonl_export": "issues.jsonl"
}Onboard v2 Enhancement Plan
This file defines all beads for the Enhanced Agent-Native Onboarding v2 initiative
Import with: bd create --file .beads/onboard-v2-plan.md
---
Feature: Onboarding Progress Tracking
type: feature priority: 1 parent: cass_memory_system-hb4y labels: onboard-v2, foundation
Background & Rationale
Currently, there's no memory of which sessions have been analyzed. If an agent's context window fills up mid-onboarding, they must start over or manually remember where they left off. This is a critical gap for the "agent-native" workflow where agents work autonomously.
User Story: As an AI coding agent, I want to resume onboarding from where I left off so that I don't waste time re-analyzing sessions.
Design Decisions
State Location: ~/.cass-memory/onboarding-state.json
- Consistent with existing config location
- Separate from playbook (different concern)
- Survives
cm init --force(intentional)
State Schema v1:
{
"version": 1,
"startedAt": "ISO8601",
"lastUpdatedAt": "ISO8601",
"processedSessions": [
{"path": "/path/session.jsonl", "processedAt": "ISO8601", "rulesExtracted": 3}
],
"stats": {
"totalSessionsProcessed": 5,
"totalRulesExtracted": 15
}
}Tracking by Path: We track sessions by file path (not content hash). This is simpler and good enough for v1. Content hashing adds complexity for minimal benefit (session files rarely move).
Acceptance Criteria
- [ ]
cm onboard --statusshows progress stats - [ ]
cm onboard --sampleexcludes already-processed sessions - [ ]
cm onboard --mark-done <path>marks session without adding rules - [ ]
cm onboard --resetclears all progress - [ ]
cm onboard --sample --include-processedoverrides exclusion - [ ] All operations have JSON output
- [ ] State file created lazily on first use
Files to Modify
src/commands/onboard.ts- Add state management- New:
src/onboard-state.ts- State schema and I/O (or inline in onboard.ts if small)
---
Task: Implement onboarding state persistence
type: task priority: 1 parent: Feature: Onboarding Progress Tracking labels: onboard-v2, implementation estimate: 90
Implementation Details
1. Define TypeScript interfaces for state schema 2. Implement loadOnboardState() - reads file, returns default if missing 3. Implement saveOnboardState() - writes file atomically 4. Implement markSessionProcessed(path, rulesExtracted) - adds to processed list 5. Implement isSessionProcessed(path) - checks if in list 6. Implement resetOnboardState() - deletes state file
Considerations
- Use atomic write (write to temp, rename) to prevent corruption
- Handle missing file gracefully (return empty state)
- Version field allows future schema migrations
- Stats are derived from processedSessions array
Acceptance Criteria
- [ ] State file created on first
markSessionProcessedcall - [ ] State survives process restart
- [ ] Concurrent access is safe (atomic writes)
- [ ] Invalid JSON in state file logs warning and returns empty state
---
Task: Integrate progress into sample and status commands
type: task priority: 1 parent: Feature: Onboarding Progress Tracking deps: Task: Implement onboarding state persistence labels: onboard-v2, implementation estimate: 60
Implementation Details
1. Modify --status to include:
- Sessions processed count
- Rules extracted count
- Time since onboarding started
- Sessions remaining (estimated)
2. Modify --sample to:
- Load state
- Filter out processed sessions
- Show "X of Y sessions remaining" in output
3. Add --include-processed flag to override filtering
JSON Output Changes
{
"status": {
"cassAvailable": true,
"playbookRules": 13,
"progress": {
"sessionsProcessed": 5,
"rulesExtracted": 15,
"startedAt": "2025-01-15T10:00:00Z",
"lastActivity": "2025-01-15T11:30:00Z"
}
}
}---
Task: Add mark-done and reset commands
type: task priority: 2 parent: Feature: Onboarding Progress Tracking deps: Task: Implement onboarding state persistence labels: onboard-v2, implementation estimate: 45
Implementation Details
1. cm onboard --mark-done <path>:
- Validates path exists in cass
- Marks as processed with rulesExtracted=0
- Use case: Agent read session but found nothing useful
2. cm onboard --reset:
- Deletes state file
- Confirms in human mode: "Reset onboarding progress? [y/N]"
- In JSON mode or with --yes: no confirmation
- Use case: Start fresh after playbook changes
Acceptance Criteria
- [ ] --mark-done validates session exists
- [ ] --mark-done is idempotent (marking twice is fine)
- [ ] --reset requires confirmation in interactive mode
- [ ] --reset --yes skips confirmation
---
Feature: Batch Rule Addition
type: feature priority: 1 parent: cass_memory_system-hb4y labels: onboard-v2, friction-reduction
Background & Rationale
After analyzing a session, agents typically extract 3-10 rules. Currently they must run cm playbook add for each one. This is:
- Tedious (N commands instead of 1)
- Error-prone (typos in repeated commands)
- Slow (process startup overhead × N)
User Story: As an AI coding agent, I want to add multiple rules at once so that I can efficiently batch my extractions.
Design Decision: Enhance playbook add vs new command
Option A: Add --file to cm playbook add
- Pro: Minimal API surface increase
- Pro: Consistent with existing command
- Con: Slightly overloaded command
Option B: New cm playbook add-batch command
- Pro: Clear separation
- Con: Another command to remember
Decision: Option A - Add --file to playbook add. The existing command already handles single rules; extending it for multiple rules is natural. Use - for stdin support.
Input Format
[
{"content": "Rule text here", "category": "debugging"},
{"content": "Another rule", "category": "testing"}
]Why JSON array:
- Structured and unambiguous
- Easy for agents to generate
- Supports all fields (content, category)
- Can extend with more fields later (tags, scope)
Acceptance Criteria
- [ ]
cm playbook add --file rules.jsonadds all rules from file - [ ]
echo '[...]' | cm playbook add --file -reads from stdin - [ ] Returns structured results: successes and failures
- [ ] Partial success is allowed (add what we can)
- [ ] Updates onboarding state with rules extracted count
---
Task: Add --file option to playbook add command
type: task priority: 1 parent: Feature: Batch Rule Addition labels: onboard-v2, implementation estimate: 60
Implementation Details
1. Add --file <path> option to playbook add command 2. When --file provided:
- Ignore positional
<content>argument - Read file (or stdin if
-) - Parse as JSON array
- Validate each entry has
contentfield - Add each rule, collecting results
3. Return structured output
JSON Output
{
"success": true,
"added": [
{"id": "b-xxx", "content": "Rule 1", "category": "debugging"},
{"id": "b-yyy", "content": "Rule 2", "category": "testing"}
],
"failed": [
{"content": "Bad rule", "error": "Content too short"}
],
"summary": {
"total": 3,
"succeeded": 2,
"failed": 1
}
}Error Handling
- Invalid JSON: Fail fast, report error
- Missing content field: Skip entry, report in failed
- Duplicate detection: If validation enabled, warn but still add
Files to Modify
src/commands/playbook.ts- Add --file handlingsrc/cm.ts- Add --file option to command definition
---
Task: Integrate batch add with onboarding state
type: task priority: 2 parent: Feature: Batch Rule Addition deps: Task: Add --file option to playbook add command, Task: Implement onboarding state persistence labels: onboard-v2, integration estimate: 30
Implementation Details
When batch add completes successfully: 1. If a session path is provided (new --session option), update onboarding state 2. Mark session as processed with count of rules added
This connects the batch add flow to progress tracking.
Usage
# After reading session, agent generates rules JSON, then:
echo '[...]' | cm playbook add --file - --session /path/to/session.jsonlThe --session option is optional - batch add works without it, but with it, progress is tracked.
---
Feature: Gap-Aware Sampling
type: feature priority: 2 parent: cass_memory_system-hb4y labels: onboard-v2, smart-sampling
Background & Rationale
Current sampling uses hardcoded queries ("fix bug", "implement feature", etc.). This doesn't consider:
- What the playbook already covers well
- What categories are underrepresented
- What would provide the most value
User Story: As an AI coding agent, I want sampling to prioritize sessions that fill gaps in my playbook so that I build a balanced rule set.
Design Decision: Playbook-only gap analysis (v1)
Option A: Analyze playbook categories + estimate cass content categories
- Pro: More accurate gap detection
- Con: Complex, requires cass content analysis
Option B: Analyze playbook categories only
- Pro: Simple, fast, no cass overhead
- Con: Doesn't know what cass actually contains
Decision: Option B for v1. If playbook has 0 testing rules, "testing" is a gap regardless of what cass contains. We can add cass-aware analysis in v2 if needed.
Gap Categorization
- Critical gaps: Categories with 0 rules
- Underrepresented: Categories with < 3 rules
- Adequate: Categories with 3-10 rules
- Well-covered: Categories with > 10 rules
Acceptance Criteria
- [ ]
cm onboard --sample --fill-gapsprioritizes gap-filling sessions - [ ] Gap analysis shown in
--statusoutput - [ ] Sessions tagged with likely categories based on keywords
- [ ] JSON output includes gap analysis
---
Task: Implement playbook gap analysis function
type: task priority: 2 parent: Feature: Gap-Aware Sampling labels: onboard-v2, implementation estimate: 45
Implementation Details
1. Create analyzePlaybookGaps(playbook) function:
- Count rules per category
- Classify as critical/underrepresented/adequate/well-covered
- Return structured analysis
2. Add category keyword detection:
- Map keywords to categories (e.g., "test", "spec", "mock" → testing)
- Use for estimating session categories from snippets
Output Structure
{
"totalRules": 13,
"byCategory": {
"debugging": {"count": 5, "status": "adequate"},
"testing": {"count": 1, "status": "underrepresented"},
"security": {"count": 0, "status": "critical"}
},
"gaps": {
"critical": ["security", "performance"],
"underrepresented": ["testing"],
"suggestions": "Focus on security and performance patterns"
}
}---
Task: Add --fill-gaps flag to sampling
type: task priority: 2 parent: Feature: Gap-Aware Sampling deps: Task: Implement playbook gap analysis function labels: onboard-v2, implementation estimate: 60
Implementation Details
1. Add --fill-gaps flag to cm onboard --sample 2. When enabled:
- Run gap analysis
- Modify search queries to target gap categories
- Score sessions by likely gap-filling potential
- Sort results by gap-filling score
3. Include rationale in output:
{
"sessions": [{
"path": "/path/session.jsonl",
"reason": "Contains testing patterns; playbook has 1 testing rule",
"likelyCategories": ["testing", "debugging"],
"gapScore": 0.85
}]
}Keyword → Category Mapping
const CATEGORY_KEYWORDS = {
testing: ["test", "spec", "mock", "assert", "expect", "jest", "vitest"],
debugging: ["debug", "error", "fix", "bug", "issue", "trace"],
security: ["auth", "security", "token", "password", "encrypt", "permission"],
performance: ["performance", "optimize", "cache", "slow", "memory", "profile"],
// ... etc
};---
Feature: Targeted Sampling Options
type: feature priority: 2 parent: cass_memory_system-hb4y labels: onboard-v2, filtering
Background & Rationale
Agents may want to focus onboarding on specific areas:
- A specific project/workspace they're working on
- A specific agent's sessions (Claude vs Cursor patterns)
- A specific time period (recent sessions more relevant)
- Quick bootstrap vs thorough analysis
User Story: As an AI coding agent, I want to filter sampled sessions by workspace/agent/time/depth so that I can focus on what's most relevant.
New Options
# Scope filters
--workspace <path> # Only sessions from this workspace
--agent <name> # Only sessions from this agent (claude, cursor, etc.)
--category <cat> # Sessions likely about this category
# Depth modes
--quick # 5 sessions for fast bootstrap
--deep # 30 sessions for thorough analysis
# Time filters
--days <n> # Sessions from last N days
--since <date> # Sessions after date (ISO8601)
--before <date> # Sessions before dateAcceptance Criteria
- [ ] All filters work independently
- [ ] Filters can be combined (--workspace X --days 30)
- [ ] --quick and --deep set reasonable defaults
- [ ] Filters passed through to cass search where possible
- [ ] JSON output includes applied filters
---
Task: Add scope filters to sampling
type: task priority: 2 parent: Feature: Targeted Sampling Options labels: onboard-v2, implementation estimate: 45
Implementation Details
1. Add options: --workspace, --agent, --category 2. Pass through to cass search:
--workspace→ cass--workspacefilter--agent→ cass--agentfilter--category→ modify search queries to category keywords
Files to Modify
src/cm.ts- Add options to onboard commandsrc/commands/onboard.ts- Implement filtering logicsrc/cass.ts- Ensure CassSearchOptions supports these filters
---
Task: Add depth modes and time filters
type: task priority: 2 parent: Feature: Targeted Sampling Options labels: onboard-v2, implementation estimate: 30
Implementation Details
1. Depth modes:
--quick: Sets limit=5, uses broader queries--deep: Sets limit=30, uses more diverse queries
2. Time filters:
--days <n>: Passed to cass search--since <date>: Convert to days, pass to cass--before <date>: Filter results post-search (cass may not support)
Default Behavior
Without flags: limit=10 (current default), no time filter
---
Feature: Pre-Add Validation
type: feature priority: 3 parent: cass_memory_system-hb4y labels: onboard-v2, quality
Background & Rationale
Without validation, agents can easily add:
- Near-duplicate rules (wastes context in cm context)
- Low-quality rules (too vague, too specific, missing context)
- Miscategorized rules (reduces retrieval accuracy)
User Story: As an AI coding agent, I want feedback on rule quality before adding so that I maintain a high-quality playbook.
Design Decision: Non-blocking validation
Validation should inform, not block by default. Agents can decide whether to proceed.
Default behavior: Return validation results, add rule anyway Strict mode: --strict flag makes warnings into errors
Validation Checks
1. Similarity check: Compare against existing rules using cm similar
- Warn if >0.8 similarity with existing rule
2. Quality heuristics:
- Too short: < 10 words
- Too long: > 100 words
- Missing context: No "when", "if", "before", "after" words
- Too vague: Only contains generic words
3. Category suggestion: Based on keywords, suggest better category if mismatch
Acceptance Criteria
- [ ]
cm playbook add "..." --checkshows validation results - [ ]
cm playbook add "..." --strictfails on warnings - [ ] Validation works with --file batch add
- [ ] JSON output includes validation details
---
Task: Implement similarity and quality checks
type: task priority: 3 parent: Feature: Pre-Add Validation labels: onboard-v2, implementation estimate: 60
Implementation Details
1. Create validateRule(content, category, playbook) function:
- Run similarity check against playbook
- Run quality heuristics
- Suggest category based on keywords
- Return validation result
2. Quality heuristic functions:
checkLength(content)→ short/ok/longcheckContext(content)→ has context words or notcheckSpecificity(content)→ vague/specific
Validation Result Structure
{
"valid": true,
"warnings": [
{"type": "similar", "message": "85% similar to b-abc123", "severity": "warning"},
{"type": "context", "message": "Consider adding when this applies", "severity": "suggestion"}
],
"suggestions": {
"category": "integration",
"reason": "Contains API-related keywords"
}
}---
Task: Add --check and --strict flags
type: task priority: 3 parent: Feature: Pre-Add Validation deps: Task: Implement similarity and quality checks labels: onboard-v2, implementation estimate: 30
Implementation Details
1. Add --check flag to cm playbook add:
- Runs validation and shows results
- Still adds rule (unless --strict)
2. Add --strict flag:
- Combined with --check
- Fails if any warnings present
- Exit code 1 on validation failure
3. For batch add with --file:
- --check validates each rule
- --strict skips rules with warnings (adds others)
---
Feature: Enhanced Read Output
type: feature priority: 2 parent: cass_memory_system-hb4y labels: onboard-v2, ux
Background & Rationale
cm onboard --read currently dumps raw session content. The agent must:
- Figure out what the session is about
- Remember what rules already exist
- Know what gaps to look for
User Story: As an AI coding agent, I want contextual guidance when reading sessions so that I extract more relevant rules.
Template Output
The --template flag enriches read output with: 1. Session metadata (agent, workspace, message count) 2. Topic hints (detected from content) 3. Related existing rules (so agent knows what's covered) 4. Playbook gaps (so agent knows what to look for) 5. Suggested extraction focus
Acceptance Criteria
- [ ]
cm onboard --read <path> --templatereturns enriched output - [ ] Related rules found via similarity search on session snippets
- [ ] Gaps included from gap analysis
- [ ] JSON output is structured and comprehensive
---
Task: Add --template flag to read command
type: task priority: 2 parent: Feature: Enhanced Read Output deps: Task: Implement playbook gap analysis function labels: onboard-v2, implementation estimate: 75
Implementation Details
1. Add --template flag to cm onboard --read 2. When enabled, output includes:
{
"metadata": {
"path": "/path/session.jsonl",
"agent": "claude",
"workspace": "/Users/x/project",
"messageCount": 45,
"topicHints": ["authentication", "API", "error handling"]
},
"context": {
"relatedRules": [
{"id": "b-abc", "content": "...", "similarity": 0.6}
],
"playbookGaps": {
"critical": ["security"],
"underrepresented": ["testing"]
},
"suggestedFocus": "Look for error handling and API patterns"
},
"extractionFormat": {
"schema": [{"content": "string", "category": "string"}],
"categories": ["debugging", "testing", ...]
},
"sessionContent": "..."
}3. Topic hints via keyword extraction from first N messages 4. Related rules via similarity search on session summary
Performance Consideration
Template generation adds overhead (similarity search, gap analysis). Cache gap analysis for session duration.
---
Dependencies Summary
The dependency graph for implementation order:
Progress Tracking (Foundation)
├── State Persistence [no deps]
├── Integrate into Sample/Status [deps: State]
└── Mark-Done and Reset [deps: State]
Batch Add
├── --file option [no deps]
└── Integrate with State [deps: --file, State]
Gap Analysis
├── Gap Analysis Function [no deps]
└── --fill-gaps flag [deps: Gap Analysis]
Targeted Sampling
├── Scope Filters [no deps]
└── Depth/Time Filters [no deps]
Validation
├── Similarity/Quality Checks [no deps]
└── --check/--strict flags [deps: Checks]
Enhanced Read
└── --template flag [deps: Gap Analysis]Critical path: State → Batch Add + Gap Analysis → Template Output
Parallelizable: Targeted Sampling, Validation (can be done alongside other work)
Beads - AI-Native Issue Tracking
Welcome to Beads! This repository uses Beads for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.
What is Beads?
Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.
Learn more: github.com/steveyegge/beads
Quick Start
Essential Commands
# Create new issues
bd create "Add user authentication"
# View all issues
bd list
# View issue details
bd show <issue-id>
# Update issue status
bd update <issue-id> --status in_progress
bd update <issue-id> --status done
# Sync with git remote
bd syncWorking with Issues
Issues in Beads are:
- Git-native: Stored in
.beads/issues.jsonland synced like code - AI-friendly: CLI-first design works perfectly with AI coding agents
- Branch-aware: Issues can follow your branch workflow
- Always in sync: Auto-syncs with your commits
Why Beads?
✨ AI-Native Design
- Built specifically for AI-assisted development workflows
- CLI-first interface works seamlessly with AI coding agents
- No context switching to web UIs
🚀 Developer Focused
- Issues live in your repo, right next to your code
- Works offline, syncs when you push
- Fast, lightweight, and stays out of your way
🔧 Git Integration
- Automatic sync with git commits
- Branch-aware issue tracking
- Intelligent JSONL merge resolution
Get Started with Beads
Try Beads in your own projects:
# Install Beads
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
# Initialize in your repo
bd init
# Create your first issue
bd create "Try out Beads"Learn More
- Documentation: github.com/steveyegge/beads/docs
- Quick Start Guide: Run
bd quickstart - Examples: github.com/steveyegge/beads/examples
---
Beads: Issue tracking that moves at the speed of thought ⚡
# Project-specific playbook rules
# These are merged with your global ~/.cass-memory/playbook.yaml
# Project rules take precedence over global rules
schema_version: 2
name: repo-playbook
description: Project-specific rules for this repository
metadata:
createdAt: 2025-12-08T02:22:13.680Z
totalReflections: 0
totalSessionsProcessed: 0
deprecatedPatterns: []
bullets: []
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
# Prevent duplicate workflow runs for the same branch/PR
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Type check
run: bun run typecheck
- name: Guardrail (tests must not use bun mocks)
run: |
set -euo pipefail
if command -v rg >/dev/null 2>&1; then
if rg -n "\\bmock\\(" test; then
echo "::error::Forbidden bun:test mock() usage detected in test/**. Use closure-based spies/counters instead (see test/llm-with-retry.test.ts)."
exit 1
fi
if rg -n "mock\\.module\\(" test; then
echo "::error::Forbidden module mocking detected in test/**. Use dependency injection / injected providers instead (see src/llm.ts LLMIO + test/llm.mocked.test.ts)."
exit 1
fi
else
echo "rg not found; falling back to grep"
if grep -R -n -E '(^|[^A-Za-z0-9_])mock\\(' test; then
echo "::error::Forbidden bun:test mock() usage detected in test/**. Use closure-based spies/counters instead."
exit 1
fi
if grep -R -n -E 'mock\\.module\\(' test; then
echo "::error::Forbidden module mocking detected in test/**. Use dependency injection / injected providers instead."
exit 1
fi
fi
- name: Run tests
run: bun run test:ci
coverage:
runs-on: ubuntu-latest
timeout-minutes: 15
env:
# Phase 1 thresholds (raise intentionally via PRs).
COVERAGE_MIN_FUNCS: "70"
COVERAGE_MIN_LINES: "70"
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Run tests with coverage (offline)
run: bash scripts/coverage.sh
env:
LOG_DIR: ${{ runner.temp }}/cm-coverage
- name: Upload coverage artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-artifacts
path: ${{ runner.temp }}/cm-coverage
if-no-files-found: warn
- name: Enforce coverage thresholds
run: |
bun -e '
const fs = require("fs");
const path = require("path");
const logDir = process.env.LOG_DIR;
const summaryPath = path.join(logDir, "summary.json");
const minFuncs = Number(process.env.COVERAGE_MIN_FUNCS || 0);
const minLines = Number(process.env.COVERAGE_MIN_LINES || 0);
const summary = JSON.parse(fs.readFileSync(summaryPath, "utf8"));
const funcs = Number(summary?.totals?.funcs ?? 0);
const lines = Number(summary?.totals?.lines ?? 0);
const failures = [];
if (funcs < minFuncs) failures.push(`Functions: ${funcs.toFixed(2)} < ${minFuncs}`);
if (lines < minLines) failures.push(`Lines: ${lines.toFixed(2)} < ${minLines}`);
if (failures.length) {
console.error("Coverage gate failed:");
for (const f of failures) console.error(`- ${f}`);
process.exit(1);
}
console.log(`Coverage gate passed: funcs=${funcs.toFixed(2)} lines=${lines.toFixed(2)}`);
'
env:
LOG_DIR: ${{ runner.temp }}/cm-coverage
- name: Show coverage summary on failure
if: failure()
run: |
echo "---- summary.json ----"
cat "${LOG_DIR}/summary.json" || true
echo "---- coverage.txt (tail) ----"
tail -n 60 "${LOG_DIR}/artifacts/coverage.txt" || true
env:
LOG_DIR: ${{ runner.temp }}/cm-coverage
e2e-scripts:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Run e2e smoke script (offline)
run: bash scripts/e2e-smoke.sh
env:
LOG_DIR: ${{ runner.temp }}/cm-e2e
- name: Upload e2e artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-smoke-artifacts
path: ${{ runner.temp }}/cm-e2e
if-no-files-found: warn
- name: Show steps.jsonl on failure
if: failure()
run: |
echo "---- steps.jsonl ----"
cat "${LOG_DIR}/steps.jsonl" || true
env:
LOG_DIR: ${{ runner.temp }}/cm-e2e
build:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Build
run: |
mkdir -p dist
bun run build
- name: Verify binary
run: |
chmod +x dist/cass-memory
./dist/cass-memory --version
# installer-notify.yml
# Copy this to .github/workflows/ in your project
# Notifies ACFS when install.sh changes
#
# Setup:
# 1. Create a GitHub PAT with `repo` scope
# 2. Add it as ACFS_DISPATCH_TOKEN secret in your repo
# 3. Copy this file to .github/workflows/
name: Notify ACFS of Installer Change
on:
push:
branches: [main, master]
paths:
- 'install.sh'
- 'scripts/install.sh'
- '**/install.sh'
pull_request:
branches: [main, master]
paths:
- 'install.sh'
- 'scripts/install.sh'
- '**/install.sh'
concurrency:
group: installer-notify-${{ github.ref }}
cancel-in-progress: true
jobs:
notify-acfs:
# Only notify on push to main, not PRs
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Compute installer SHA256
id: checksum
run: |
# Find the installer file
if [ -f install.sh ]; then
INSTALLER_PATH="install.sh"
elif [ -f scripts/install.sh ]; then
INSTALLER_PATH="scripts/install.sh"
else
echo "No installer found"
exit 1
fi
SHA256=$(sha256sum "$INSTALLER_PATH" | cut -d' ' -f1)
echo "sha256=$SHA256" >> $GITHUB_OUTPUT
echo "Computed SHA256: $SHA256"
- name: Notify ACFS
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.ACFS_DISPATCH_TOKEN }}
repository: Dicklesworthstone/agentic_coding_flywheel_setup
event-type: installer-updated
client-payload: |
{
"tool": "${{ github.event.repository.name }}",
"repo": "${{ github.repository }}",
"commit": "${{ github.sha }}",
"new_sha256": "${{ steps.checksum.outputs.sha256 }}",
"ref": "${{ github.ref }}",
"actor": "${{ github.actor }}"
}
- name: Log notification
run: |
echo "::notice::Notified ACFS about installer change"
echo "Repository: ${{ github.repository }}"
echo "Commit: ${{ github.sha }}"
echo "SHA256: ${{ steps.checksum.outputs.sha256 }}"
# Validate installer syntax on PRs
validate-installer:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install shellcheck
run: sudo apt-get update && sudo apt-get install -y shellcheck
- name: Shellcheck installer
run: |
EXIT_CODE=0
for script in install.sh scripts/install.sh; do
if [ -f "$script" ]; then
echo "Checking $script..."
shellcheck "$script" || EXIT_CODE=1
fi
done
exit $EXIT_CODE
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version tag (e.g., v0.1.0)'
required: true
type: string
# Prevent concurrent releases
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write
jobs:
# Linux x64 and Windows x64 cross-compile from ubuntu-latest.
build-linux-windows:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Build Linux x64 and Windows x64
run: |
# Start from a clean dist/ so stale artifacts cannot leak into
# the release (see #45 — shipped binaries can quietly carry pre-fix
# content if dist/ is reused).
rm -rf dist
mkdir -p dist
# Linux x64 — use baseline target (no AVX2) for maximum CPU compatibility
# Without -baseline, the binary uses AVX2 which crashes with "Illegal
# instruction" on older CPUs (see issue #40).
bun build src/cm.ts --compile --target=bun-linux-x64-baseline --outfile dist/cass-memory-linux-x64
# Windows x64 — use baseline target for maximum CPU compatibility
bun build src/cm.ts --compile --target=bun-windows-x64-baseline --outfile dist/cass-memory-windows-x64.exe
ls -la dist/
- name: Verify compiled binaries contain no Rust-style \u{...} escapes (#45)
run: |
# Regression guard for issue #45: Bun's TypeScript loader normalises
# non-ASCII characters inside `String.raw` templates to `\u{…}`
# escape sequences that Python's parser rejects. The unit tests cover
# the TypeScript source, but the failure mode is only visible in the
# final compiled binary.
#
# We scan for the specific failure shape — a `\u{…}` escape adjacent
# to content that's clearly meant to be user-facing text (e.g. the
# "HOT STOVE" banner). This is tight enough to avoid false positives
# from legitimate JavaScript Unicode regex patterns like
# `/[\u{D800}-\u{DFFF}]/u` that survive bundling inside JS source.
#
# Capture matches into a variable instead of using `if pipe | head`
# — `head -5` always exits 0 regardless of grep's match status, so
# the naive `if` form is a constant-true guard.
for bin in dist/cass-memory-linux-x64 dist/cass-memory-windows-x64.exe; do
echo "Scanning $bin for mangled trauma-guard emoji..."
matches="$(strings "$bin" | grep -E '\\u\{[0-9a-fA-F]+\} ?HOT STOVE|HOT STOVE ?\\u\{[0-9a-fA-F]+\}' | head -5 || true)"
if [ -n "$matches" ]; then
echo "$matches"
echo "::error::Binary $bin contains Rust-style \\u{...} escapes in trauma-guard text (regression of #45)."
echo "::error::A String.raw template almost certainly has a literal non-ASCII character."
echo "::error::Route the character through \${VAR} interpolation. See src/trauma_guard_script.ts."
exit 1
fi
done
echo "All Linux/Windows binaries clean."
- name: Upload Linux/Windows artifacts
uses: actions/upload-artifact@v4
with:
name: linux-windows-binaries
path: dist/*
if-no-files-found: error
# macOS binaries must be built natively so codesign is available.
# Apple Silicon (arm64) mandatorily requires at least an ad-hoc signature:
# AMFI terminates unsigned arm64 Mach-Os with SIGKILL at exec.
# See issue #43.
build-macos:
runs-on: macos-15
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Build macOS arm64 and x64
run: |
# Start from a clean dist/ so stale artifacts cannot leak into the
# release (see #45).
rm -rf dist
mkdir -p dist
# macOS ARM64 (Apple Silicon) — native build on macos-15 runner
bun build src/cm.ts --compile --target=bun-darwin-arm64 --outfile dist/cass-memory-macos-arm64
# macOS x64 (Intel) — use baseline target for maximum CPU compatibility
bun build src/cm.ts --compile --target=bun-darwin-x64-baseline --outfile dist/cass-memory-macos-x64
ls -la dist/
- name: Verify compiled binaries contain no Rust-style \u{...} escapes (#45)
run: |
# Regression guard for issue #45 — see the Linux/Windows job for rationale.
for bin in dist/cass-memory-macos-arm64 dist/cass-memory-macos-x64; do
echo "Scanning $bin for mangled trauma-guard emoji..."
matches="$(strings "$bin" | grep -E '\\u\{[0-9a-fA-F]+\} ?HOT STOVE|HOT STOVE ?\\u\{[0-9a-fA-F]+\}' | head -5 || true)"
if [ -n "$matches" ]; then
echo "$matches"
echo "::error::Binary $bin contains Rust-style \\u{...} escapes in trauma-guard text (regression of #45)."
echo "::error::Route the character through \${VAR} interpolation. See src/trauma_guard_script.ts."
exit 1
fi
done
echo "All macOS binaries clean."
- name: Ad-hoc codesign macOS binaries
run: |
# On Apple Silicon, AMFI terminates unsigned arm64 binaries with
# SIGKILL at exec. Installing via curl does not set the
# com.apple.quarantine xattr, so Gatekeeper is not involved — the
# kernel itself refuses to run unsigned arm64 Mach-Os. An ad-hoc
# signature (signer "-") is sufficient to satisfy AMFI.
# See issue #43.
codesign --force --sign - --timestamp=none dist/cass-memory-macos-arm64
codesign --force --sign - --timestamp=none dist/cass-memory-macos-x64
# Verify both signatures exist and are structurally valid.
codesign -dv dist/cass-memory-macos-arm64
codesign -dv dist/cass-memory-macos-x64
codesign --verify --verbose=2 dist/cass-memory-macos-arm64
codesign --verify --verbose=2 dist/cass-memory-macos-x64
# Smoke test: the signed arm64 binary must actually exec on this
# Apple Silicon runner (previously SIGKILL'd here under AMFI).
dist/cass-memory-macos-arm64 --version
- name: Upload macOS artifacts
uses: actions/upload-artifact@v4
with:
name: macos-binaries
path: dist/*
if-no-files-found: error
release:
needs: [build-linux-windows, build-macos]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Download Linux/Windows artifacts
uses: actions/download-artifact@v4
with:
name: linux-windows-binaries
path: release
- name: Download macOS artifacts
uses: actions/download-artifact@v4
with:
name: macos-binaries
path: release
- name: List release assets
run: ls -la release/
- name: Generate checksums
run: |
cd release
sha256sum cass-memory-linux-x64 > cass-memory-linux-x64.sha256
sha256sum cass-memory-macos-arm64 > cass-memory-macos-arm64.sha256
sha256sum cass-memory-macos-x64 > cass-memory-macos-x64.sha256
sha256sum cass-memory-windows-x64.exe > cass-memory-windows-x64.exe.sha256
ls -la
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.version }}
name: cass-memory ${{ steps.version.outputs.version }}
draft: false
prerelease: ${{ contains(steps.version.outputs.version, '-') }}
generate_release_notes: true
files: |
release/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-installer:
needs: release
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Generate installer checksum
run: sha256sum install.sh > install.sh.sha256
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Upload installer checksum to release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.version }}
files: install.sh.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ==========================================================================
# Notify Package Managers to Update
# ==========================================================================
notify-homebrew-tap:
name: Notify Homebrew Tap
runs-on: ubuntu-latest
timeout-minutes: 5
needs: publish-installer
# Skip if the tap dispatch token is not configured.
if: ${{ github.repository_owner == 'Dicklesworthstone' }}
steps:
- name: Check for dispatch token
id: check_token
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
if [ -n "$HOMEBREW_TAP_TOKEN" ]; then
echo "has_token=true" >> "$GITHUB_OUTPUT"
else
echo "has_token=false" >> "$GITHUB_OUTPUT"
echo "HOMEBREW_TAP_TOKEN is not configured — skipping dispatch."
fi
- name: Trigger formula update
if: steps.check_token.outputs.has_token == 'true'
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
repository: Dicklesworthstone/homebrew-tap
event-type: formula-update
client-payload: |
{
"tool": "cm",
"version": "${{ needs.publish-installer.outputs.version }}"
}
- name: Log dispatch
if: steps.check_token.outputs.has_token == 'true'
run: |
echo "Dispatched formula-update event to homebrew-tap"
echo " Tool: cm"
echo " Version: ${{ needs.publish-installer.outputs.version }}"
notify-scoop-bucket:
name: Notify Scoop Bucket
runs-on: ubuntu-latest
timeout-minutes: 5
needs: publish-installer
if: ${{ github.repository_owner == 'Dicklesworthstone' }}
steps:
- name: Check for dispatch token
id: check_token
env:
SCOOP_BUCKET_TOKEN: ${{ secrets.SCOOP_BUCKET_TOKEN }}
run: |
if [ -n "$SCOOP_BUCKET_TOKEN" ]; then
echo "has_token=true" >> "$GITHUB_OUTPUT"
else
echo "has_token=false" >> "$GITHUB_OUTPUT"
echo "SCOOP_BUCKET_TOKEN is not configured — skipping dispatch."
fi
- name: Trigger manifest update
if: steps.check_token.outputs.has_token == 'true'
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.SCOOP_BUCKET_TOKEN }}
repository: Dicklesworthstone/scoop-bucket
event-type: manifest-update
client-payload: |
{
"tool": "cm",
"version": "${{ needs.publish-installer.outputs.version }}"
}
- name: Log dispatch
if: steps.check_token.outputs.has_token == 'true'
run: |
echo "Dispatched manifest-update event to scoop-bucket"
echo " Tool: cm"
echo " Version: ${{ needs.publish-installer.outputs.version }}"
# Dependencies
node_modules/
.pnp.*
.yarn/
# Build output
dist/
dist-dsr/
build/
*.tsbuildinfo
# TypeScript artifacts (compiled JS/d.ts)
*.js.map
*.d.ts
# Environment & secrets
.env
.env.local
.env.*.local
config.json
*.key
*.pem
*.p12
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
pnpm-debug.log*
# Testing
coverage/
.nyc_output/
*.lcov
test/logs/
# IDE & OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
.vscode/
.idea/
*.swp
*.swo
*~
# Bun
bun.lockb
# CASS memory system (local/ephemeral)
.cass/config.yaml
.cass/outcomes.jsonl
diary/*.md
usage.jsonl
# Beads (issue tracking is committed; runtime files are ignored via `.beads/.gitignore`)
.beads/.local_version
# Runtime interactions log — written by the cass_memory_system process
# alongside the canonical issues.jsonl; not part of the tracked corpus.
.beads/interactions.jsonl
# Python / uv
__pycache__/
*.py[cod]
*.pyo
*.pyd
*.so
.venv/
.python-version
# Environment files
.env
.env.*
*.env
# Packaging and build artifacts
build/
dist/
.eggs/
*.egg-info/
# Testing and coverage
.pytest_cache/
.mypy_cache/
.ruff_cache/
.coverage
.coverage.*
htmlcov/
# Tool caches and notebooks
.cache/
.ipynb_checkpoints/
# Editors and IDEs
.vscode/
.idea/
*.swp
*.swo
# Node.js / Bun
node_modules/
tsconfig.tsbuildinfo
# bv (beads viewer) local config and caches
.bv/
# UBS ignore list
# These entries are legitimate and should not be flagged as secrets or bugs.
# Intentional secret-scrubbing regex patterns (false positive for hardcoded secrets)
src/sanitize.ts:51
# Proposal/design docs (not runtime code) with loose parsing examples
competing_proposal_plans/**
AGENTS.md — cass-memory
Guidelines for AI coding agents working in this TypeScript codebase.
---
RULE 0 - THE FUNDAMENTAL OVERRIDE PREROGATIVE
If I tell you to do something, even if it goes against what follows below, YOU MUST LISTEN TO ME. I AM IN CHARGE, NOT YOU.
---
RULE NUMBER 1: NO FILE DELETION
YOU ARE NEVER ALLOWED TO DELETE A FILE WITHOUT EXPRESS PERMISSION. Even a new file that you yourself created, such as a test code file. You have a horrible track record of deleting critically important files or otherwise throwing away tons of expensive work. As a result, you have permanently lost any and all rights to determine that a file or folder should be deleted.
YOU MUST ALWAYS ASK AND RECEIVE CLEAR, WRITTEN PERMISSION BEFORE EVER DELETING A FILE OR FOLDER OF ANY KIND.
---
Irreversible Git & Filesystem Actions — DO NOT EVER BREAK GLASS
1. Absolutely forbidden commands: git reset --hard, git clean -fd, rm -rf, or any command that can delete or overwrite code/data must never be run unless the user explicitly provides the exact command and states, in the same message, that they understand and want the irreversible consequences. 2. No guessing: If there is any uncertainty about what a command might delete or overwrite, stop immediately and ask the user for specific approval. "I think it's safe" is never acceptable. 3. Safer alternatives first: When cleanup or rollbacks are needed, request permission to use non-destructive options (git status, git diff, git stash, copying to backups) before ever considering a destructive command. 4. Mandatory explicit plan: Even after explicit user authorization, restate the command verbatim, list exactly what will be affected, and wait for a confirmation that your understanding is correct. Only then may you execute it—if anything remains ambiguous, refuse and escalate. 5. Document the confirmation: When running any approved destructive command, record (in the session notes / final response) the exact user text that authorized it, the command actually run, and the execution time. If that record is absent, the operation did not happen.
---
Git Branch: ONLY Use main, NEVER master
The default branch is `main`. The `master` branch exists only for legacy URL compatibility.
- All work happens on `main` — commits, PRs, feature branches all merge to
main - Never reference `master` in code or docs — if you see
masteranywhere, it's a bug that needs fixing - The `master` branch must stay synchronized with `main` — after pushing to
main, also push tomaster:
git push origin main:masterIf you see `master` referenced anywhere: 1. Update it to main 2. Ensure master is synchronized: git push origin main:master
---
Toolchain: Bun & TypeScript
We only use Bun in this project, NEVER any other package manager or runtime.
- Runtime: Bun >= 1.0.0 (see
enginesinpackage.json) - Language: TypeScript with strict mode (
"strict": trueintsconfig.json) - Module system: ESNext modules (
"type": "module"inpackage.json) - Lockfile:
bun.lockonly. Never introducepackage-lock.json,yarn.lock, orpnpm-lock.yaml. - Never use
npm,yarn, orpnpm. - Target: Latest Node.js. No need to support old versions.
Key Dependencies
| Package | Purpose |
|---|---|
@ai-sdk/anthropic | Anthropic Claude model provider for AI SDK |
@ai-sdk/google | Google Gemini model provider for AI SDK |
@ai-sdk/openai | OpenAI model provider for AI SDK |
@xenova/transformers | Local embedding models for semantic search |
ai | Vercel AI SDK — unified LLM interface |
chalk | Terminal output coloring |
commander | CLI argument parsing and subcommand routing |
yaml | YAML parsing for playbook files |
zod | Runtime schema validation for all data models |
fast-check | Property-based testing (dev) |
typescript | Type checking (dev) |
---
Code Editing Discipline
No Script-Based Changes
NEVER run a script that processes/changes code files in this repo. Brittle regex-based transformations create far more problems than they solve.
- Always make code changes manually, even when there are many instances
- For many simple changes: use parallel subagents
- For subtle/complex changes: do them methodically yourself
No File Proliferation
If you want to change something or add a feature, revise existing code files in place.
NEVER create variations like:
mainV2.tsmain_improved.tsmain_enhanced.ts
New files are reserved for genuinely new functionality that makes zero sense to include in any existing file. The bar for creating new files is incredibly high.
---
Backwards Compatibility
We do not care about backwards compatibility—we're in early development with no users. We want to do things the RIGHT way with NO TECH DEBT.
- Never create "compatibility shims"
- Never create wrapper functions for deprecated APIs
- Just fix the code directly
---
Compiler Checks (CRITICAL)
After any substantive code changes, you MUST verify no errors were introduced:
# Type-check the entire project
bun run typecheck
# Run the full test suite
bun test
# Run only unit tests (fast)
bun run test:unitIf you see errors, carefully understand and resolve each issue. Read sufficient context to fix them the RIGHT way.
---
Testing
Testing Policy
Tests live in the test/ directory. Tests must cover:
- Happy path
- Edge cases (empty input, max values, boundary conditions)
- Error conditions
Running Tests
# Run all tests
bun test
# Run with output
bun test --verbose
# Run unit tests only (excludes integration and e2e)
bun run test:unit
# Run integration tests
bun run test:integration
# Run e2e tests
bun run test:e2e
# Run property-based tests
bun run test:property
# Run with coverage
bun run test:coverage
# Run in CI mode (60s timeout)
bun run test:ciTest Categories
| Category | Focus Areas |
|---|---|
Unit (*.test.ts) | Scoring, validation, sanitization, path utils, error categorization, inline feedback parsing, truncation |
Integration (*integration*.test.ts) | Config scoring integration, context+outcome pipeline, curator pipeline |
E2E (*e2e*.test.ts) | ACE pipeline, blocked filtering, CLI config cascade, playbook merge, concurrency stress, scoring decay |
Property (*property*.test.ts) | Deduplication invariants via fast-check |
Test Configuration
Tests are configured via bunfig.toml:
- Preload:
./test/setup.ts(global test setup) - Timeout: 30,000ms (30 seconds for E2E tests)
- Smol mode: Enabled for faster execution
---
Logging & Console Output
- Prefer a shared logger over raw
console.log. - No random console logs in UI components; if needed, make them dev-only and clean them up.
- Log structured context: IDs, user, request, model, etc.
- If a logger helper exists, you must use it; do not invent a different pattern.
---
Third-Party Library Usage
If you aren't 100% sure how to use a third-party library, SEARCH ONLINE to find the latest documentation and current best practices.
---
cass-memory — This Project
This is the project you're working on. cass-memory is a procedural memory system for AI coding agents. It transforms scattered agent sessions into persistent, cross-agent memory so every agent learns from every other agent's experience.
What It Does
Implements a three-layer cognitive architecture (ACE framework) that converts raw session logs from multiple AI coding agents (Claude Code, Codex, Cursor, Aider, Gemini, ChatGPT, etc.) into actionable, confidence-tracked rules stored in a shared playbook.
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ EPISODIC MEMORY (cass) │
│ Raw session logs from all agents — the "ground truth" │
│ Claude Code │ Codex │ Cursor │ Aider │ PI │ Gemini │ ChatGPT │ ...│
└───────────────────────────┬─────────────────────────────────────────┘
│ cass search
▼
┌─────────────────────────────────────────────────────────────────────┐
│ WORKING MEMORY (Diary) │
│ Structured session summaries bridging raw logs to rules │
│ accomplishments │ decisions │ challenges │ outcomes │
└───────────────────────────┬─────────────────────────────────────────┘
│ reflect + curate (automated)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ PROCEDURAL MEMORY (Playbook) │
│ Distilled rules with confidence tracking │
│ Rules │ Anti-patterns │ Feedback │ Decay │
└─────────────────────────────────────────────────────────────────────┘Source Structure
cass_memory_system/
├── package.json # Project manifest (bun)
├── tsconfig.json # TypeScript strict config
├── bunfig.toml # Bun test configuration
├── src/
│ ├── cm.ts # CLI entry point (commander)
│ ├── cass.ts # cass search engine integration
│ ├── types.ts # Zod schemas and TypeScript types
│ ├── config.ts # Configuration loading and defaults
│ ├── scoring.ts # Confidence scoring and decay
│ ├── semantic.ts # Semantic search via local embeddings
│ ├── playbook.ts # Playbook CRUD and rule management
│ ├── curate.ts # Automated curation pipeline
│ ├── reflect.ts # Reflection engine (session → rules)
│ ├── diary.ts # Working memory (session summaries)
│ ├── outcome.ts # Outcome tracking and analysis
│ ├── tracking.ts # Usage and feedback tracking
│ ├── trauma.ts # Trauma guard safety system
│ ├── trauma_guard_script.ts # Trauma guard automation
│ ├── validate.ts # Rule validation logic
│ ├── rule-validation.ts # Scientific rule validation
│ ├── sanitize.ts # Input sanitization
│ ├── llm.ts # Multi-provider LLM interface
│ ├── lock.ts # File locking for concurrency
│ ├── audit.ts # Audit trail logging
│ ├── cost.ts # LLM cost estimation
│ ├── info.ts # System info and diagnostics
│ ├── output.ts # Output formatting
│ ├── progress.ts # Progress display
│ ├── starters.ts # Starter playbook templates
│ ├── examples.ts # Usage examples
│ ├── gap-analysis.ts # Playbook coverage gap analysis
│ ├── onboard-state.ts # Onboarding state management
│ ├── orchestrator.ts # Pipeline orchestration
│ ├── utils.ts # Shared utilities
│ └── commands/ # CLI subcommands
│ ├── context.ts # cm context — task-specific memory retrieval
│ ├── playbook.ts # cm playbook — rule management
│ ├── onboard.ts # cm onboard — session analysis workflow
│ ├── doctor.ts # cm doctor — health checks and repairs
│ ├── reflect.ts # cm reflect — session reflection
│ ├── serve.ts # cm serve — MCP server mode
│ ├── diary.ts # cm diary — session summaries
│ ├── outcome.ts # cm outcome — outcome tracking
│ ├── trauma.ts # cm trauma — safety system
│ ├── guard.ts # cm guard — content guardrails
│ ├── init.ts # cm init — project initialization
│ ├── privacy.ts # cm privacy — data management
│ ├── project.ts # cm project — project config
│ ├── similar.ts # cm similar — find similar rules
│ ├── stats.ts # cm stats — playbook statistics
│ ├── stale.ts # cm stale — find stale rules
│ ├── top.ts # cm top — top-performing rules
│ ├── forget.ts # cm forget — selective memory removal
│ ├── undo.ts # cm undo — revert operations
│ ├── audit.ts # cm audit — audit trail
│ ├── mark.ts # cm mark — rule feedback
│ ├── validate.ts # cm validate — rule validation
│ ├── quickstart.ts # cm quickstart — self-documenting intro
│ ├── starters.ts # cm starters — template management
│ ├── usage.ts # cm usage — usage statistics
│ └── why.ts # cm why — explain rule reasoning
├── test/ # Tests (unit, integration, e2e, property)
│ ├── helpers/ # Shared test utilities
│ └── fixtures/ # Test fixture data
└── dist/ # Compiled binaries (bun --compile)Key Modules
| Module | Purpose |
|---|---|
cm.ts | CLI entry point — routes subcommands via commander |
types.ts | Zod schemas for all data models (playbook, diary, bullets, config) |
scoring.ts | Confidence scoring with 90-day half-life decay, 4x harmful multiplier, maturity progression |
playbook.ts | Playbook CRUD — add/remove/merge/dedup rules with file locking |
curate.ts | Automated curation: evidence gating, anti-pattern inversion, deduplication |
semantic.ts | Local embedding-based semantic search via @xenova/transformers |
reflect.ts | Reflection engine: extracts structured rules from raw sessions |
diary.ts | Working memory: accomplishments, decisions, challenges, outcomes |
trauma.ts | Safety system: prevents harmful rule propagation, guards against collapse |
llm.ts | Multi-provider LLM interface via Vercel AI SDK (Anthropic, OpenAI, Google) |
orchestrator.ts | ACE pipeline orchestration (Analyze, Curate, Extract) |
commands/context.ts | The primary agent entry point: cm context "<task>" --json |
Core Concepts
| Concept | Description |
|---|---|
| Episodic Memory | Raw session logs from all agents (ground truth), searched via cass |
| Working Memory | Structured session summaries (diary entries) bridging logs to rules |
| Procedural Memory | Distilled playbook rules with confidence tracking and decay |
| ACE Pipeline | Analyze-Curate-Extract: the automated pipeline from sessions to rules |
| Confidence Decay | 90-day half-life; rules lose confidence without revalidation |
| Harmful Multiplier | One harmful mark counts 4x as much as one helpful mark |
| Maturity Progression | Rules progress: candidate -> established -> proven |
| Anti-Pattern Inversion | Rules marked harmful multiple times become warnings |
| Evidence Gating | New rules validated against cass history before acceptance |
| Trauma Guard | Safety system preventing harmful rule propagation and collapse |
| Graceful Degradation | System works with missing components (no cass, no LLM, offline) |
Key Design Decisions
- Zod for all schemas — runtime validation, not just compile-time types
- File-based storage — playbook YAML + diary JSON; no database dependency
- Multi-provider LLM via Vercel AI SDK — Anthropic, OpenAI, Google interchangeable
- Local embeddings via
@xenova/transformers— semantic search without API calls - Confidence-weighted scoring — rules ranked by relevance, recency, and track record
- Cross-agent learning — sessions from any agent feed the shared playbook
- `--json` for all agent output — stdout is data, stderr is diagnostics, exit 0 is success
- File locking for concurrent access safety
- Bun compile for single-binary distribution (Linux, macOS, Windows)
---
Memory System: cass-memory
The Cass Memory System (cm) is a tool for giving agents an effective memory based on the ability to quickly search across previous coding agent sessions across an array of different coding agent tools (e.g., Claude Code, Codex, Gemini-CLI, Cursor, etc.) and projects (and even across multiple machines, optionally) and then reflect on what they find and learn in new sessions to draw out useful lessons and takeaways; these lessons are then stored and can be queried and retrieved later, much like how human memory works.
The cm onboard command guides you through analyzing historical sessions and extracting valuable rules.
Quick Start
# 1. Check status and see recommendations
cm onboard status
# 2. Get sessions to analyze (filtered by gaps in your playbook)
cm onboard sample --fill-gaps
# 3. Read a session with rich context
cm onboard read /path/to/session.jsonl --template
# 4. Add extracted rules (one at a time or batch)
cm playbook add "Your rule content" --category "debugging"
# Or batch add:
cm playbook add --file rules.json
# 5. Mark session as processed
cm onboard mark-done /path/to/session.jsonlBefore starting complex tasks, retrieve relevant context:
cm context "<task description>" --jsonThis returns:
- relevantBullets: Rules that may help with your task
- antiPatterns: Pitfalls to avoid
- historySnippets: Past sessions that solved similar problems
- suggestedCassQueries: Searches for deeper investigation
Protocol
1. START: Run cm context "<task>" --json before non-trivial work 2. WORK: Reference rule IDs when following them (e.g., "Following b-8f3a2c...") 3. FEEDBACK: Leave inline comments when rules help/hurt:
// [cass: helpful b-xyz] - reason// [cass: harmful b-xyz] - reason
4. END: Just finish your work. Learning happens automatically.
Key Flags
| Flag | Purpose |
|---|---|
--json | Machine-readable JSON output (required!) |
--limit N | Cap number of rules returned |
--no-history | Skip historical snippets for faster response |
stdout = data only, stderr = diagnostics. Exit 0 = success.
---
MCP Agent Mail — Multi-Agent Coordination
A mail-like layer that lets coding agents coordinate asynchronously via MCP tools and resources. Provides identities, inbox/outbox, searchable threads, and advisory file reservations with human-auditable artifacts in Git.
Why It's Useful
- Prevents conflicts: Explicit file reservations (leases) for files/globs
- Token-efficient: Messages stored in per-project archive, not in context
- Quick reads:
resource://inbox/...,resource://thread/...
Same Repository Workflow
1. Register identity:
ensure_project(project_key=<abs-path>)
register_agent(project_key, program, model)2. Reserve files before editing:
file_reservation_paths(project_key, agent_name, ["src/**"], ttl_seconds=3600, exclusive=true)3. Communicate with threads:
send_message(..., thread_id="FEAT-123")
fetch_inbox(project_key, agent_name)
acknowledge_message(project_key, agent_name, message_id)4. Quick reads:
resource://inbox/{Agent}?project=<abs-path>&limit=20
resource://thread/{id}?project=<abs-path>&include_bodies=trueMacros vs Granular Tools
- Prefer macros for speed:
macro_start_session,macro_prepare_thread,macro_file_reservation_cycle,macro_contact_handshake - Use granular tools for control:
register_agent,file_reservation_paths,send_message,fetch_inbox,acknowledge_message
Common Pitfalls
"from_agent not registered": Alwaysregister_agentin the correctproject_keyfirst"FILE_RESERVATION_CONFLICT": Adjust patterns, wait for expiry, or use non-exclusive reservation- Auth errors: If JWT+JWKS enabled, include bearer token with matching
kid
---
Beads (br) — Dependency-Aware Issue Tracking
Beads provides a lightweight, dependency-aware issue database and CLI (br - beads_rust) for selecting "ready work," setting priorities, and tracking status. It complements MCP Agent Mail's messaging and file reservations.
Important: br is non-invasive—it NEVER runs git commands automatically. You must manually commit changes after br sync --flush-only.
Conventions
- Single source of truth: Beads for task status/priority/dependencies; Agent Mail for conversation and audit
- Shared identifiers: Use Beads issue ID (e.g.,
br-123) as Mailthread_idand prefix subjects with[br-123] - Reservations: When starting a task, call
file_reservation_paths()with the issue ID inreason
Typical Agent Flow
1. Pick ready work (Beads):
br ready --json # Choose highest priority, no blockers2. Reserve edit surface (Mail):
file_reservation_paths(project_key, agent_name, ["src/**"], ttl_seconds=3600, exclusive=true, reason="br-123")3. Announce start (Mail):
send_message(..., thread_id="br-123", subject="[br-123] Start: <title>", ack_required=true)4. Work and update: Reply in-thread with progress
5. Complete and release:
br close 123 --reason "Completed"
br sync --flush-only # Export to JSONL (no git operations) release_file_reservations(project_key, agent_name, paths=["src/**"])Final Mail reply: [br-123] Completed with summary
Mapping Cheat Sheet
| Concept | Value |
|---|---|
Mail thread_id | br-### |
| Mail subject | [br-###] ... |
File reservation reason | br-### |
| Commit messages | Include br-### for traceability |
---
bv — Graph-Aware Triage Engine
bv is a graph-aware triage engine for Beads projects (.beads/beads.jsonl). It computes PageRank, betweenness, critical path, cycles, HITS, eigenvector, and k-core metrics deterministically.
Scope boundary: bv handles what to work on (triage, priority, planning). For agent-to-agent coordination (messaging, work claiming, file reservations), use MCP Agent Mail.
*CRITICAL: Use ONLY `--robot- flags. Bare bv` launches an interactive TUI that blocks your session.**
The Workflow: Start With Triage
`bv --robot-triage` is your single entry point. It returns:
quick_ref: at-a-glance counts + top 3 picksrecommendations: ranked actionable items with scores, reasons, unblock infoquick_wins: low-effort high-impact itemsblockers_to_clear: items that unblock the most downstream workproject_health: status/type/priority distributions, graph metricscommands: copy-paste shell commands for next steps
bv --robot-triage # THE MEGA-COMMAND: start here
bv --robot-next # Minimal: just the single top pick + claim commandCommand Reference
Planning:
| Command | Returns |
|---|---|
--robot-plan | Parallel execution tracks with unblocks lists |
--robot-priority | Priority misalignment detection with confidence |
Graph Analysis:
| Command | Returns |
|---|---|
--robot-insights | Full metrics: PageRank, betweenness, HITS, eigenvector, critical path, cycles, k-core, articulation points, slack |
--robot-label-health | Per-label health: health_level, velocity_score, staleness, blocked_count |
--robot-label-flow | Cross-label dependency: flow_matrix, dependencies, bottleneck_labels |
--robot-label-attention [--attention-limit=N] | Attention-ranked labels |
History & Change Tracking:
| Command | Returns |
|---|---|
--robot-history | Bead-to-commit correlations |
--robot-diff --diff-since <ref> | Changes since ref: new/closed/modified issues, cycles |
Other:
| Command | Returns |
|---|---|
--robot-burndown <sprint> | Sprint burndown, scope changes, at-risk items |
| `--robot-forecast <id\ | all>` |
--robot-alerts | Stale issues, blocking cascades, priority mismatches |
--robot-suggest | Hygiene: duplicates, missing deps, label suggestions |
| `--robot-graph [--graph-format=json\ | dot\ |
--export-graph <file.html> | Interactive HTML visualization |
Scoping & Filtering
bv --robot-plan --label backend # Scope to label's subgraph
bv --robot-insights --as-of HEAD~30 # Historical point-in-time
bv --recipe actionable --robot-plan # Pre-filter: ready to work
bv --recipe high-impact --robot-triage # Pre-filter: top PageRank
bv --robot-triage --robot-triage-by-track # Group by parallel work streams
bv --robot-triage --robot-triage-by-label # Group by domainUnderstanding Robot Output
All robot JSON includes:
data_hash— Fingerprint of source beads.jsonlstatus— Per-metric state:computed|approx|timeout|skipped+ elapsed msas_of/as_of_commit— Present when using--as-of
Two-phase analysis:
- Phase 1 (instant): degree, topo sort, density
- Phase 2 (async, 500ms timeout): PageRank, betweenness, HITS, eigenvector, cycles
jq Quick Reference
bv --robot-triage | jq '.quick_ref' # At-a-glance summary
bv --robot-triage | jq '.recommendations[0]' # Top recommendation
bv --robot-plan | jq '.plan.summary.highest_impact' # Best unblock target
bv --robot-insights | jq '.status' # Check metric readiness
bv --robot-insights | jq '.Cycles' # Circular deps (must fix!)---
UBS — Ultimate Bug Scanner
Golden Rule: ubs <changed-files> before every commit. Exit 0 = safe. Exit >0 = fix & re-run.
Commands
ubs file.ts file2.py # Specific files (< 1s) — USE THIS
ubs $(git diff --name-only --cached) # Staged files — before commit
ubs --only=js,python src/ # Language filter (3-5x faster)
ubs --ci --fail-on-warning . # CI mode — before PR
ubs . # Whole project (ignores node_modules automatically)Output Format
Warning Category (N errors)
file.ts:42:5 - Issue description
Suggested fix
Exit code: 1Parse: file:line:col -> location | fix suggestion -> how to fix | Exit 0/1 -> pass/fail
Fix Workflow
1. Read finding -> category + fix suggestion 2. Navigate file:line:col -> view context 3. Verify real issue (not false positive) 4. Fix root cause (not symptom) 5. Re-run ubs <file> -> exit 0 6. Commit
Bug Severity
- Critical (always fix): Null safety, XSS/injection, async/await, memory leaks
- Important (production): Type narrowing, division-by-zero, resource leaks
- Contextual (judgment): TODO/FIXME, console logs
---
RCH — Remote Compilation Helper
RCH offloads cargo build, cargo test, cargo clippy, and other compilation commands to a fleet of 8 remote Contabo VPS workers instead of building locally. This prevents compilation storms from overwhelming csd when many agents run simultaneously.
RCH is installed at `~/.local/bin/rch` and is hooked into Claude Code's PreToolUse automatically. Most of the time you don't need to do anything if you are Claude Code — builds are intercepted and offloaded transparently.
To manually offload a build:
rch exec -- cargo build --release
rch exec -- cargo test
rch exec -- cargo clippyQuick commands:
rch doctor # Health check
rch workers probe --all # Test connectivity to all 8 workers
rch status # Overview of current state
rch queue # See active/waiting buildsIf rch or its workers are unavailable, it fails open — builds run locally as normal.
Note for Codex/GPT-5.2: Codex does not have the automatic PreToolUse hook, but you can (and should) still manually offload compute-intensive compilation commands using rch exec -- <command>. This avoids local resource contention when multiple agents are building simultaneously.
---
ast-grep vs ripgrep
Use `ast-grep` when structure matters. It parses code and matches AST nodes, ignoring comments/strings, and can safely rewrite code.
- Refactors/codemods: rename APIs, change import forms
- Policy checks: enforce patterns across a repo
- Editor/automation: LSP mode,
--jsonoutput
Use `ripgrep` when text is enough. Fastest way to grep literals/regex.
- Recon: find strings, TODOs, log lines, config values
- Pre-filter: narrow candidate files before ast-grep
Rule of Thumb
- Need correctness or applying changes ->
ast-grep - Need raw speed or hunting text ->
rg - Often combine:
rgto shortlist files, thenast-grepto match/modify
TypeScript Examples
# Find structured code (ignores comments)
ast-grep run -l TypeScript -p 'function $NAME($$$ARGS): $RET { $$$BODY }'
# Find all non-null assertions
ast-grep run -l TypeScript -p '$EXPR!'
# Quick textual hunt
rg -n 'console.log' -t ts
# Combine speed + precision
rg -l -t ts 'throw new' | xargs ast-grep run -l TypeScript -p 'throw new $ERR($$$ARGS)' --json---
Morph Warp Grep — AI-Powered Code Search
Use `mcp__morph-mcp__warp_grep` for exploratory "how does X work?" questions. An AI agent expands your query, greps the codebase, reads relevant files, and returns precise line ranges with full context.
Use `ripgrep` for targeted searches. When you know exactly what you're looking for.
Use `ast-grep` for structural patterns. When you need AST precision for matching/rewriting.
When to Use What
| Scenario | Tool | Why |
|---|---|---|
| "How does the ACE pipeline work?" | warp_grep | Exploratory; don't know where to start |
| "Where is confidence decay implemented?" | warp_grep | Need to understand architecture |
"Find all uses of PlaybookBullet" | ripgrep | Targeted literal search |
"Find files with console.log" | ripgrep | Simple pattern |
"Replace all throw new Error with custom errors" | ast-grep | Structural refactor |
warp_grep Usage
mcp__morph-mcp__warp_grep(
repoPath: "/dp/cass_memory_system",
query: "How does the confidence decay scoring system work?"
)Returns structured results with file paths, line ranges, and extracted code snippets.
Anti-Patterns
- Don't use
warp_grepto find a specific function name -> useripgrep - Don't use
ripgrepto understand "how does X work" -> wastes time with manual reads - Don't use
ripgrepfor codemods -> risks collateral edits
---
cass — Cross-Agent Search
cass indexes prior agent conversations (Claude Code, Codex, Cursor, Gemini, ChatGPT, etc.) so we can reuse solved problems.
Rules:
- Never run bare
cass(TUI). Always use--robotor--json.
Examples:
cass health
cass search "authentication error" --robot --limit 5
cass view /path/to/session.jsonl -n 42 --json
cass expand /path/to/session.jsonl -n 42 -C 3 --json
cass capabilities --json
cass robot-docs guideTips:
- Use
--fields minimalfor lean output. - Filter by agent with
--agent. - Use
--days Nto limit to recent history.
stdout is data-only, stderr is diagnostics; exit code 0 means success.
Treat cass as a way to avoid re-solving problems other agents already handled.
---
Contribution Policy
The README must include the "About Contributions" disclaimer at the end explaining that outside contributions are not accepted directly. Do not remove this policy text.
<!-- bv-agent-instructions-v1 -->
---
Beads Workflow Integration
This project uses beads_rust (br) for issue tracking. Issues are stored in .beads/ and tracked in git.
Important: br is non-invasive—it NEVER executes git commands. After br sync --flush-only, you must manually run git add .beads/ && git commit.
Essential Commands
# View issues (launches TUI - avoid in automated sessions)
bv
# CLI commands for agents (use these instead)
br ready # Show issues ready to work (no blockers)
br list --status=open # All open issues
br show <id> # Full issue details with dependencies
br create --title="..." --type=task --priority=2
br update <id> --status=in_progress
br close <id> --reason "Completed"
br close <id1> <id2> # Close multiple issues at once
br sync --flush-only # Export to JSONL (NO git operations)Workflow Pattern
1. Start: Run br ready to find actionable work 2. Claim: Use br update <id> --status=in_progress 3. Work: Implement the task 4. Complete: Use br close <id> 5. Sync: Run br sync --flush-only then manually commit
Key Concepts
- Dependencies: Issues can block other issues.
br readyshows only unblocked work. - Priority: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (use numbers, not words)
- Types: task, bug, feature, epic, question, docs
- Blocking:
br dep add <issue> <depends-on>to add dependencies
Session Protocol
Before ending any session, run this checklist:
git status # Check what changed
git add <files> # Stage code changes
br sync --flush-only # Export beads to JSONL
git add .beads/ # Stage beads changes
git commit -m "..." # Commit everything together
git push # Push to remoteBest Practices
- Check
br readyat session start to find available work - Update status as you work (in_progress -> closed)
- Create new issues with
br createwhen you discover tasks - Use descriptive titles and set appropriate priority/type
- Always
br sync --flush-only && git add .beads/before ending session
<!-- end-bv-agent-instructions -->
Landing the Plane (Session Completion)
When ending a work session, you MUST complete ALL steps below.
MANDATORY WORKFLOW:
1. File issues for remaining work - Create issues for anything that needs follow-up 2. Run quality gates (if code changed) - Tests, linters, builds 3. Update issue status - Close finished work, update in-progress items 4. Sync beads - br sync --flush-only to export to JSONL 5. Hand off - Provide context for next session
---
Note for Codex/GPT-5.2:
You constantly bother me and stop working with concerned questions that look similar to this:
Unexpected changes (need guidance)
- Working tree still shows edits I did not make in Cargo.toml, Cargo.lock, src/main.rs, src/patterns.rs. Please advise whether to keep/commit/revert these before any further work. I did not touch them.
Next steps (pick one)
1. Decide how to handle the unrelated modified files above so we can resume cleanly.NEVER EVER DO THAT AGAIN. The answer is literally ALWAYS the same: those are changes created by the potentially dozen of other agents working on the project at the same time. This is not only a common occurence, it happens multiple times PER MINUTE. The way to deal with it is simple: you NEVER, under ANY CIRCUMSTANCE, stash, revert, overwrite, or otherwise disturb in ANY way the work of other agents. Just treat those changes identically to changes that you yourself made. Just fool yourself into thinking YOU made the changes and simply don't recall it for some reason.
---
Note on Built-in TODO Functionality
Also, if I ask you to explicitly use your built-in TODO functionality, don't complain about this and say you need to use beads. You can use built-in TODOs if I tell you specifically to do so. Always comply with such orders.
# Bun configuration for cass-memory
# See: https://bun.sh/docs/runtime/bunfig
[test]
# Preload global test setup
preload = ["./test/setup.ts"]
# Test timeout in milliseconds (30 seconds for E2E tests)
timeout = 30000
# Root directory for test discovery
root = "."
# Smol mode for faster test execution
smol = true
AGENTS.md - cass-reflect Integration Guide
This file teaches AI coding agents how to use cass-reflect for memory and reflection.Overview
cass-reflect is your memory system. It: 1. Searches your past sessions across ALL agents (Claude, Codex, Cursor, Aider, etc.) 2. Maintains a "playbook" of reusable coding wisdom 3. Tracks which rules help vs. cause problems
Always use `--json` output for parsing.
Quick Reference
# Before starting a task - get relevant context
cass-reflect context "your task description" --json
# After using a playbook bullet successfully
cass-reflect mark <bullet-id> --helpful
# When a playbook bullet caused problems
cass-reflect mark <bullet-id> --harmful
# List available bullets
cass-reflect playbook list --json
# Search past sessions (via cass)
cass search "error pattern" --robot --limit 5Workflow Integration
At Task Start
Before diving into complex tasks, retrieve context:
CONTEXT=$(cass-reflect context "Fix the authentication timeout in login.ts" --json)The response includes:
bullets: Relevant playbook entries with IDshistory: Snippets from past sessions that solved similar problemsprompt: Pre-formatted context to include in your reasoning
During Task Execution
When you apply a playbook bullet:
# If it helped solve the problem
cass-reflect mark b-abc123 --helpful --session "$CURRENT_SESSION"
# If it led you astray or caused issues
cass-reflect mark b-abc123 --harmful --session "$CURRENT_SESSION"After Task Completion
For significant sessions, generate a diary entry:
cass-reflect diary "$SESSION_PATH" --jsonThis captures:
- What was accomplished
- Key decisions made
- Challenges encountered
- User preferences revealed
Playbook Bullet Format
Bullets in the response look like:
{
"id": "b-1a2b3c4d",
"category": "debugging",
"content": "For TypeScript generic errors, check the instantiated type at call site",
"helpful_count": 8,
"harmful_count": 1,
"tags": ["typescript", "debugging"]
}When referencing bullets in your work:
- Cite the ID: "Following [b-1a2b3c4d], I'll check the instantiated type..."
- Mark usage after: helpful if it worked, harmful if it misled
Adding New Learnings
When you discover something reusable:
cass-reflect playbook add \
--category "testing" \
--tags "jest,async" \
"Wrap async act() calls in try/finally to ensure cleanup runs"Guidelines for good bullets:
- Be specific: Not "write tests" but "For React async effects, use waitFor() not act()"
- Include context: When does this apply? What triggers it?
- Cite evidence: What error/situation revealed this?
Error Handling
| Exit Code | Meaning | Action |
|---|---|---|
| 0 | Success | Parse stdout as JSON |
| 1 | General error | Check stderr for message |
| 2 | Config missing | Run cass-reflect init |
Environment Requirements
cassmust be installed and in PATH- One of:
ANTHROPIC_API_KEY,OPENAI_API_KEY,GOOGLE_GENERATIVE_AI_API_KEY
Example Integration
import subprocess
import json
def get_task_context(task: str) -> dict:
"""Get relevant playbook entries and history for a task."""
result = subprocess.run(
["cass-reflect", "context", task, "--json"],
capture_output=True, text=True
)
if result.returncode != 0:
return {"bullets": [], "history": [], "prompt": ""}
return json.loads(result.stdout)
def mark_bullet(bullet_id: str, helpful: bool, session_path: str = None):
"""Track bullet usage."""
cmd = ["cass-reflect", "mark", bullet_id]
cmd.append("--helpful" if helpful else "--harmful")
if session_path:
cmd.extend(["--session", session_path])
subprocess.run(cmd)
def search_history(query: str, limit: int = 5) -> list:
"""Search past sessions via cass."""
result = subprocess.run(
["cass", "search", query, "--robot", "--limit", str(limit)],
capture_output=True, text=True
)
if result.returncode != 0:
return []
return json.loads(result.stdout).get("hits", [])Best Practices
1. Always check context first for non-trivial tasks 2. Mark bullets honestly - harmful marks improve the system 3. Be specific when adding bullets - generic rules don't help 4. Search history when stuck - someone probably solved this before 5. Generate diaries for significant sessions to capture learnings
{
"name": "cass-reflect",
"version": "0.1.0",
"description": "Agent-Agnostic Reflection & Memory System - ACE pattern implementation for coding agents",
"type": "module",
"main": "cass-reflect.ts",
"bin": {
"cass-reflect": "./cass-reflect.ts"
},
"scripts": {
"start": "bun run cass-reflect.ts",
"build": "bun build --compile --minify cass-reflect.ts --outfile dist/cass-reflect",
"build:all": "bun run build:linux && bun run build:macos && bun run build:windows",
"build:linux": "bun build --compile --minify --target=bun-linux-x64 cass-reflect.ts --outfile dist/cass-reflect-linux-x64",
"build:macos": "bun build --compile --minify --target=bun-darwin-arm64 cass-reflect.ts --outfile dist/cass-reflect-darwin-arm64",
"build:windows": "bun build --compile --minify --target=bun-windows-x64 cass-reflect.ts --outfile dist/cass-reflect-windows-x64.exe",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"ai": "^4.0.0",
"@ai-sdk/openai": "^1.0.0",
"@ai-sdk/anthropic": "^1.0.0",
"@ai-sdk/google": "^1.0.0",
"zod": "^3.23.0"
},
"devDependencies": {
"@types/bun": "latest",
"typescript": "^5.0.0"
},
"keywords": [
"ai",
"coding-agent",
"reflection",
"memory",
"ace",
"llm",
"claude",
"cass"
],
"author": "Jeff Emanuel",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/Dicklesworthstone/cass-reflect"
},
"engines": {
"bun": ">=1.0.0"
}
}
Contributing to cass-memory
1) Development setup
- Prerequisites: Bun ≥1.0, Node.js 18+, Git
- Clone:
git clone <repo>thencd cass_memory_system - Install deps:
bun install - Dev entrypoints:
- One-off:
bun run dev -- <command> [args] - Hot reload while editing:
bun run dev:watch -- <command> [args] - Keep type safety running:
bun run typecheck:watch
2) Running tests
- Unit tests:
bun test - Watch mode:
bun run test:watch - Integration tests:
bun test --filter integration(when added) - Coverage:
bun test --coverage - Typecheck:
bun run typecheck
3) Code style
- TypeScript strict mode is enabled; no implicit any.
- Use existing formatting (Prettier-equivalent); keep imports ESM with
.jssuffix for local modules. - Avoid console.log in production code; use shared logger helpers when available.
4) PR process
- Branch from
main; use feature branches. - Add/adjust tests for new behavior.
- Ensure
bun run typecheckandbun testpass. - Update docs (README/AGENTS.md/CONTRIBUTING.md) when behavior or commands change.
- PR description: what changed, why, testing done.
5) Issue templates
- Bug reports: steps to reproduce, expected/actual, logs, versions.
- Feature requests: use-case, proposed shape, acceptance criteria.
- Docs: what’s unclear or missing; suggested wording if possible.
6) Architecture overview (quick)
- Three-layer ACE pipeline: Generator (context) → Reflector (deltas) → Curator (deterministic merge).
- Storage: playbook YAML in
~/.cass-memory/and.cass/(repo-level); diaries in~/.cass-memory/diary. - CLI:
cm(cass-memory) commands undersrc/commands. - Keep schemas single-sourced in
src/types.ts; other modules must import from there to avoid drift.
Agent-Native Onboarding: Populating cass-memory Without API Costs
The Problem
cm reflect uses LLM API calls to extract rules from sessions. This costs real money per token. But if you're using Claude Code via Claude Max ($100/month) or GPT via ChatGPT Pro, you've already paid for unlimited LLM usage.
The insight: Have the coding agent do the reflection work directly, for "free".
The Solution: Agent-Native Reflection
Instead of:
cass sessions → cm reflect → LLM API ($$$) → playbookUse:
cass sessions → agent reads → agent extracts rules → cm playbook add → playbookStep-by-Step Onboarding Process
1. Check Available Sessions
# Get diverse sessions across workspaces and agents
cass search "function" --robot --limit 30 | jq -r '.hits[] | "\(.agent)|\(.workspace)|\(.source_path)"' | sort -u
# Or search by workspace
cass search "*" --workspace /path/to/project --robot --limit 202. Export Sessions for Analysis
# Export a session to readable text
cass export "/path/to/session.jsonl" --format text | head -500
# Or as markdown for better formatting
cass export "/path/to/session.jsonl" --format markdown > session.md3. Agent Analyzes Sessions
As the coding agent, read the exported sessions and identify:
1. Patterns that led to success - What approaches worked? 2. Patterns that caused problems - What should be avoided? 3. Workflow insights - How did the agent coordinate, prioritize, debug? 4. Tool-specific knowledge - CLI quirks, API formats, configuration patterns
4. Add Rules via CLI
# Add a positive rule
cm playbook add "Your rule content here" --category "category"
# Categories: debugging, testing, architecture, workflow, documentation, integration, collaboration
# Add an anti-pattern (AVOID prefix)
cm playbook add "AVOID: Description of what not to do" --category "category"5. Verify and Test
# List all rules
cm playbook list
# Test context retrieval
cm context "your task description" --json | jq '.relevantBullets[] | {content, relevanceScore}'
# Check playbook health
cm stats --jsonExample Rule Extraction
From a session where an agent fixed a JSON parsing bug:
Session excerpt:
"The cass search command returns { count, hits, ... } but the code expected a raw array..."Extracted rule:
cm playbook add "When parsing JSON output from external CLI tools, handle both raw arrays and wrapper objects like { count, hits } - APIs often evolve their response formats" --category "integration"Categories to Use
| Category | Use For |
|---|---|
debugging | Bug investigation patterns |
testing | Test writing and maintenance |
architecture | Code organization patterns |
workflow | Task management and prioritization |
documentation | Doc writing standards |
integration | External tool and API patterns |
collaboration | Multi-agent coordination |
git | Version control patterns |
security | Security best practices |
Batch Onboarding Script
For systematic onboarding, have the agent process sessions in batches:
#!/bin/bash
# Agent-assisted onboarding
# 1. List sessions to process
cass search "*" --robot --limit 50 | jq -r '.hits[].source_path' | sort -u > sessions.txt
# 2. For each session, agent reads and extracts rules
# (Agent does this interactively)
# 3. After extraction, check results
cm playbook list
cm stats --jsonMarking Feedback
When rules prove helpful or harmful during actual work:
# Mark a rule as helpful
cm mark <bullet-id> --helpful
# Mark a rule as harmful with reason
cm mark <bullet-id> --harmful --reason "Caused regression in X"Or use inline comments in code:
// [cass: helpful b-xyz123] - this rule saved debugging time
// [cass: harmful b-abc456] - this advice was wrong for our use caseWhen to Use This vs API-Based Reflection
| Situation | Approach |
|---|---|
| Initial onboarding (many sessions) | Agent-native (free) |
| Ongoing daily reflection | Either (API is fine for small batches) |
| Specific session deep-dive | Agent-native (more thorough) |
| Automated CI/CD integration | API-based (unattended) |
Benefits
1. Zero API cost - Uses your existing Claude Max/GPT Pro subscription 2. More thorough - Agent can read full context, not just summaries 3. Interactive - Agent can ask clarifying questions 4. Immediate - No waiting for API rate limits 5. Better rules - Agent understands nuance better than batch API
Limitations
1. Requires agent time - Not fully automated 2. Manual process - Each session needs explicit review 3. No validation gate - Rules aren't evidence-checked against cass history
Recommended Workflow
1. Initial onboarding: Agent processes 20-50 diverse sessions manually 2. Ongoing maintenance: Mix of agent-native (complex sessions) and API-based (simple sessions) 3. Rule refinement: Agent periodically reviews and consolidates rules
## Memory System: cass-memory
Before starting complex tasks, retrieve relevant context:
```bash
cm context "<task description>" --json
```
This returns:
- **relevantBullets**: Rules that may help with your task
- **antiPatterns**: Pitfalls to avoid
- **historySnippets**: Past sessions that solved similar problems
- **suggestedCassQueries**: Searches for deeper investigation
### Protocol
1. **START**: Run `cm context "<task>" --json` before non-trivial work
2. **WORK**: Reference rule IDs when following them (e.g., "Following b-8f3a2c, checking token expiry first...")
3. **FEEDBACK**: Leave inline comments when rules help/hurt:
- `// [cass: helpful b-xyz] - reason`
- `// [cass: harmful b-xyz] - reason`
4. **END**: Just finish your work. Learning happens automatically.
### What You Don't Need To Do
- Run `cm reflect` (automation handles this)
- Run `cm mark` for feedback (use inline comments instead)
- Manually add rules to the playbook
- Worry about the learning pipeline
### Quick Examples
```bash
# Before implementing auth
cm context "implement JWT authentication" --json
# When stuck on a bug
cm context "fix memory leak in connection pool" --json
# Checking for past solutions
cm context "optimize database queries" --json
```
### Inline Feedback Format
```typescript
// [cass: helpful b-8f3a2c] - token expiry check prevented auth rabbit hole
// [cass: harmful b-x7k9p1] - caching advice was wrong for our stateless arch
```
For more details: `cm quickstart` or see https://github.com/Dicklesworthstone/cass_memory_system