PR-013 Endpoint: GET /v1/leaderboard (vibe-kanban)
## Dependencies
- Depends on: PR-012 (Endpoint: /v1/pnl)
## Scope
### Deterministic user universe:
- LEADERBOARD\_USERS (comma-separated) or LEADERBOARD\_USERS\_FILE
### For each user, compute metric over window:
- **volume**: sum(px \* sz) from effects
- **pnl**: realizedPnl
- **returnPct**
### Ranking:
- Rank with stable tie-breakers
- builderOnly excludes tainted lifecycles
---
## API Contract (from Section 5.4)
### Query Parameters:
| Parameter | Required | Description |
| --- | --- | --- |
| --- | --- | --- |
| ----------- | ---------- | ------------- |
| `coin` | optional | Filter by coin |
| `fromMs` | optional | Start of time window |
| `toMs` | optional | End of time window |
| `metric` | required | One of: `volume`, `pnl`, `returnPct` |
| `builderOnly` | optional | Filter to builder-attributed trades only |
| `maxStartCapital` | optional | Cap for effective capital calculation |
### Response (array):
- `rank` - Position in leaderboard
- `user` - User address
- `metricValue` - The computed metric value
- `tradeCount` - Number of trades
- `tainted` - (only when builderOnly=true) Indicates if exclusions occurred
### User Universe:
- Must be deterministic
- Provided via `LEADERBOARD_USERS` env var or `LEADERBOARD_USERS_FILE`
### Tie-breakers (in order):
1. metricValue desc
2. tradeCount desc
3. user asc
---
## Tests (RED first)
1. **Ranking test with tie-breakers** - Verify correct ordering when metrics are equal
2. **Metric correctness tests on synthetic data** - Verify volume, pnl, returnPct calculations
3. **builderOnly exclusion test** - Verify tainted lifecycles are excluded and tainted flag is set
---
## Definition of Done
- [ ] All tests pass
- [ ] 100% code coverage
- [ ] cargo fmt --check passes
- [ ] cargo clippy --all-targets --all-features -- -D warnings passes
- [ ] Endpoint returns deterministic JSON output
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Introduced `/v1/leaderboard` API endpoint for user rankings with configurable metrics (volume, PnL, return percentage)
* Supports coin filtering, custom time windows, builder-only filtering, and trade count tie-breakers
* Includes risk-adjusted return calculations with maximum starting capital options
* **Tests**
* Added comprehensive integration tests validating metrics, rankings, and filtering logic
<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
make the hook thing work for this (vibe-kanban)
i have had tried the proxy and file fetching for context but it doesnt work with tht. this is idea behind it "Universal Memory for AI CLI Tools
## One-liner
A local-first “universal context layer” that gives persistent, shareable memory across AI coding CLI tools (OpenCode, Claude Code, Codex, etc.) via a standard store + adapters.
## Problem
AI coding CLIs are powerful, but each one lives in its own memory silo:
- You repeat preferences (stack, style, conventions) in every tool.
- Project context (architecture, commands, env quirks, domain rules) gets lost between sessions.
- Switching tools means re-onboarding the AI every time.
- Teams can’t easily share “working context” in a controlled way.
## Core idea
Create a **Universal Memory Daemon** + **Memory Store** that any CLI tool can read/write using a small standard API.
Each tool gets an adapter that:
- Pulls the right memory for the current repo/session/task
- Injects it into prompts/context
- Writes back useful updates after tasks finish (with safety controls)
Think of it like “git config + notes + brain” for AI CLIs.
## Goals
- **Universal**: Works with multiple AI CLIs through adapters.
- **Local-first**: Runs on developer machine by default, works offline.
- **Scoped**: Memory is not one blob—it's separated by repo, org, and user.
- **Controllable**: Users can view/edit/approve what gets stored.
- **Composable**: Support rules, summaries, facts, snippets, workflows.
- **Portable**: Sync across devices optionally (end-to-end encrypted).
## Non-goals (initial)
- Replacing the tool’s internal memory system entirely
- Building a full “agent framework”
- Cloud-only product (cloud sync can be optional later)
## Memory types (what we store)
1. **User profile**
- Tone preferences, coding style, formatting, “don’t do” rules
- Preferred stack, editors, commit style, testing habits
2. **Project memory (repo-scoped)**
- Architecture summary, key modules, naming conventions
- Setup commands, scripts, env vars, common fixes
- Domain rules (business logic constraints)
- “Traps” (things that often break)
3. **Session memory (short-lived)**
- Current task goal, constraints, intermediate decisions
- Auto-expire or roll up into project memory as summary
4. **Snippets and artifacts**
- Known-good commands, curl examples, SQL snippets
- Reusable prompt macros (e.g., “review PR checklist”)
5. **Embeddings / semantic memory (optional)**
- Vector index for retrieval over notes, docs summaries, decisions
- Not for storing proprietary code by default—store references
## Scoping model
Memory should be retrievable by context keys:
- `user:*`
- `repo:<git_remote or repo_hash>`
- `repo:<...>:branch:<name>` (optional)
- `org:<company>` (optional)
- `tool:<claude_code|codex|opencode>`
- `task:<ticket_id>` (optional)
Retrieval should support “merge” behavior:
- User profile + repo memory + session memory + tool overrides
## Architecture (MVP)
## Components
- **memd** (daemon)
- Local HTTP server on `localhost`
- Offers CRUD + retrieval endpoints
- Handles encryption, permissions, TTL, and indexing
- **memctl** (CLI)
- `memctl get`, `memctl set`, `memctl search`, `memctl doctor`
- `memctl approve` queue for pending writes
- `memctl export/import` for portability
- **Adapters**
- `memwrap` command that wraps any CLI tool:
- `memwrap codex ...`
- `memwrap claude-code ...`
- Tool-specific plugins later (nicer integration)
## Storage
Start simple:
- SQLite for structured memory + metadata
- Optional local vector store (SQLite + sqlite-vss, LanceDB, or FAISS)
Encryption:
- At-rest encryption using OS keychain or a user-supplied passphrase
- Separate keys per scope (user vs repo) if possible
## API sketch (local)
- `GET /v1/context?repo=...&tool=...&task=...`
- returns: ordered blocks to inject (system-ish, user prefs, project notes)
- `POST /v1/memory`
- body: `{scope, type, content, tags, ttl, confidence, source}`
- `POST /v1/memory/suggest`
- tool submits candidate memory updates (goes to approval queue)
- `GET /v1/memory/search?q=...&scope=...`
- `POST /v1/events`
- log tool runs, outcomes (for later auto-summarization)
## Prompt injection format (tool-agnostic)
Return memory as structured blocks:
- “User preferences”
- “Project conventions”
- “Known pitfalls”
- “Common commands”
- “Current task summary”
Adapters decide how to inject based on tool:
- Some support system prompts, some only user messages
- Some have config files; adapter can write temp config
## Write-back policy (important)
Most problems come from bad memory. So:
- Default to **suggest-only** writes
- User approves, or enable auto-approve for specific types/tags
- Attach provenance:
- which tool wrote it
- timestamp
- related command/task
- Support “confidence” and “expires\_at”
- Keep memory diffable and revertible
## UX flows
## First run (per repo)
- Detect git repo + remote
- Ask:
- “Do you want a repo memory file/store?”
- “Should this repo allow write-back suggestions?”
- Auto-generate starter memory:
- read README + package files + lockfiles
- summarize structure (optional, user-approved)
## During usage
- Tool starts → adapter calls `GET /context` → injects memory
- Tool finishes → adapter extracts:
- key decisions
- new commands discovered
- pitfalls encountered
- Sends as suggestion → user approves → stored
## Manual control
- `memctl edit repo` opens interactive editor (like `git config --edit`)
- `memctl ls` shows memory entries with tags + last used
- `memctl prune` cleans old session memory
## Safety + privacy
- Local by default, no silent cloud sync
- Repo-level allowlist/denylist for:
- file patterns never to store (`.env`, `secrets`, keys)
- scopes that can be written
- Redaction hooks:
- detect tokens, emails, private keys
- Support “private repo mode” where semantic indexing is disabled
## Integration ideas (adapters)
1. **Wrapper mode (fastest MVP)**
- `memwrap <tool> <args>`
- Injects context through env vars, temp files, or CLI flags where available
2. **Config patching mode**
- Some tools read config files—generate ephemeral config with memory blocks
3. **MCP mode (future)**
- Expose memory as an MCP server so tools that support MCP can query it directly
## MVP milestones
1. `memd` daemon + SQLite store + `memctl`
2. Repo/user scoping + retrieval ordering
3. `memwrap` adapter for 1 tool (pick the easiest)
4. Suggest-only writeback + approval queue
5. Basic search + tagging
6. Optional: vector retrieval for long notes
## Tech choices (suggested)
- Language: Go or Rust (single binary, easy daemon) or Node.js (fast iteration)
- Store: SQLite
- Vectors: sqlite-vss or LanceDB
- Auth: localhost token + file permissions
- Packaging: Homebrew + npm + curl install script
"
implement the hooks and test it out too
PR-013 Endpoint: GET /v1/leaderboard (vibe-kanban)
## Dependencies
- Depends on: PR-012 (Endpoint: /v1/pnl)
## Scope
### Deterministic user universe:
- LEADERBOARD\_USERS (comma-separated) or LEADERBOARD\_USERS\_FILE
### For each user, compute metric over window:
- **volume**: sum(px \* sz) from effects
- **pnl**: realizedPnl
- **returnPct**
### Ranking:
- Rank with stable tie-breakers
- builderOnly excludes tainted lifecycles
---
## API Contract (from Section 5.4)
### Query Parameters:
| Parameter | Required | Description |
| --- | --- | --- |
| --- | --- | --- |
| ----------- | ---------- | ------------- |
| `coin` | optional | Filter by coin |
| `fromMs` | optional | Start of time window |
| `toMs` | optional | End of time window |
| `metric` | required | One of: `volume`, `pnl`, `returnPct` |
| `builderOnly` | optional | Filter to builder-attributed trades only |
| `maxStartCapital` | optional | Cap for effective capital calculation |
### Response (array):
- `rank` - Position in leaderboard
- `user` - User address
- `metricValue` - The computed metric value
- `tradeCount` - Number of trades
- `tainted` - (only when builderOnly=true) Indicates if exclusions occurred
### User Universe:
- Must be deterministic
- Provided via `LEADERBOARD_USERS` env var or `LEADERBOARD_USERS_FILE`
### Tie-breakers (in order):
1. metricValue desc
2. tradeCount desc
3. user asc
---
## Tests (RED first)
1. **Ranking test with tie-breakers** - Verify correct ordering when metrics are equal
2. **Metric correctness tests on synthetic data** - Verify volume, pnl, returnPct calculations
3. **builderOnly exclusion test** - Verify tainted lifecycles are excluded and tainted flag is set
---
## Definition of Done
- [ ] All tests pass
- [ ] 100% code coverage
- [ ] cargo fmt --check passes
- [ ] cargo clippy --all-targets --all-features -- -D warnings passes
- [ ] Endpoint returns deterministic JSON output
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Introduced `/v1/leaderboard` API endpoint for user rankings with configurable metrics (volume, PnL, return percentage)
* Supports coin filtering, custom time windows, builder-only filtering, and trade count tie-breakers
* Includes risk-adjusted return calculations with maximum starting capital options
* **Tests**
* Added comprehensive integration tests validating metrics, rankings, and filtering logic
<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
make the hook thing work for this (vibe-kanban)
i have had tried the proxy and file fetching for context but it doesnt work with tht. this is idea behind it "Universal Memory for AI CLI Tools
## One-liner
A local-first “universal context layer” that gives persistent, shareable memory across AI coding CLI tools (OpenCode, Claude Code, Codex, etc.) via a standard store + adapters.
## Problem
AI coding CLIs are powerful, but each one lives in its own memory silo:
- You repeat preferences (stack, style, conventions) in every tool.
- Project context (architecture, commands, env quirks, domain rules) gets lost between sessions.
- Switching tools means re-onboarding the AI every time.
- Teams can’t easily share “working context” in a controlled way.
## Core idea
Create a **Universal Memory Daemon** + **Memory Store** that any CLI tool can read/write using a small standard API.
Each tool gets an adapter that:
- Pulls the right memory for the current repo/session/task
- Injects it into prompts/context
- Writes back useful updates after tasks finish (with safety controls)
Think of it like “git config + notes + brain” for AI CLIs.
## Goals
- **Universal**: Works with multiple AI CLIs through adapters.
- **Local-first**: Runs on developer machine by default, works offline.
- **Scoped**: Memory is not one blob—it's separated by repo, org, and user.
- **Controllable**: Users can view/edit/approve what gets stored.
- **Composable**: Support rules, summaries, facts, snippets, workflows.
- **Portable**: Sync across devices optionally (end-to-end encrypted).
## Non-goals (initial)
- Replacing the tool’s internal memory system entirely
- Building a full “agent framework”
- Cloud-only product (cloud sync can be optional later)
## Memory types (what we store)
1. **User profile**
- Tone preferences, coding style, formatting, “don’t do” rules
- Preferred stack, editors, commit style, testing habits
2. **Project memory (repo-scoped)**
- Architecture summary, key modules, naming conventions
- Setup commands, scripts, env vars, common fixes
- Domain rules (business logic constraints)
- “Traps” (things that often break)
3. **Session memory (short-lived)**
- Current task goal, constraints, intermediate decisions
- Auto-expire or roll up into project memory as summary
4. **Snippets and artifacts**
- Known-good commands, curl examples, SQL snippets
- Reusable prompt macros (e.g., “review PR checklist”)
5. **Embeddings / semantic memory (optional)**
- Vector index for retrieval over notes, docs summaries, decisions
- Not for storing proprietary code by default—store references
## Scoping model
Memory should be retrievable by context keys:
- `user:*`
- `repo:<git_remote or repo_hash>`
- `repo:<...>:branch:<name>` (optional)
- `org:<company>` (optional)
- `tool:<claude_code|codex|opencode>`
- `task:<ticket_id>` (optional)
Retrieval should support “merge” behavior:
- User profile + repo memory + session memory + tool overrides
## Architecture (MVP)
## Components
- **memd** (daemon)
- Local HTTP server on `localhost`
- Offers CRUD + retrieval endpoints
- Handles encryption, permissions, TTL, and indexing
- **memctl** (CLI)
- `memctl get`, `memctl set`, `memctl search`, `memctl doctor`
- `memctl approve` queue for pending writes
- `memctl export/import` for portability
- **Adapters**
- `memwrap` command that wraps any CLI tool:
- `memwrap codex ...`
- `memwrap claude-code ...`
- Tool-specific plugins later (nicer integration)
## Storage
Start simple:
- SQLite for structured memory + metadata
- Optional local vector store (SQLite + sqlite-vss, LanceDB, or FAISS)
Encryption:
- At-rest encryption using OS keychain or a user-supplied passphrase
- Separate keys per scope (user vs repo) if possible
## API sketch (local)
- `GET /v1/context?repo=...&tool=...&task=...`
- returns: ordered blocks to inject (system-ish, user prefs, project notes)
- `POST /v1/memory`
- body: `{scope, type, content, tags, ttl, confidence, source}`
- `POST /v1/memory/suggest`
- tool submits candidate memory updates (goes to approval queue)
- `GET /v1/memory/search?q=...&scope=...`
- `POST /v1/events`
- log tool runs, outcomes (for later auto-summarization)
## Prompt injection format (tool-agnostic)
Return memory as structured blocks:
- “User preferences”
- “Project conventions”
- “Known pitfalls”
- “Common commands”
- “Current task summary”
Adapters decide how to inject based on tool:
- Some support system prompts, some only user messages
- Some have config files; adapter can write temp config
## Write-back policy (important)
Most problems come from bad memory. So:
- Default to **suggest-only** writes
- User approves, or enable auto-approve for specific types/tags
- Attach provenance:
- which tool wrote it
- timestamp
- related command/task
- Support “confidence” and “expires\_at”
- Keep memory diffable and revertible
## UX flows
## First run (per repo)
- Detect git repo + remote
- Ask:
- “Do you want a repo memory file/store?”
- “Should this repo allow write-back suggestions?”
- Auto-generate starter memory:
- read README + package files + lockfiles
- summarize structure (optional, user-approved)
## During usage
- Tool starts → adapter calls `GET /context` → injects memory
- Tool finishes → adapter extracts:
- key decisions
- new commands discovered
- pitfalls encountered
- Sends as suggestion → user approves → stored
## Manual control
- `memctl edit repo` opens interactive editor (like `git config --edit`)
- `memctl ls` shows memory entries with tags + last used
- `memctl prune` cleans old session memory
## Safety + privacy
- Local by default, no silent cloud sync
- Repo-level allowlist/denylist for:
- file patterns never to store (`.env`, `secrets`, keys)
- scopes that can be written
- Redaction hooks:
- detect tokens, emails, private keys
- Support “private repo mode” where semantic indexing is disabled
## Integration ideas (adapters)
1. **Wrapper mode (fastest MVP)**
- `memwrap <tool> <args>`
- Injects context through env vars, temp files, or CLI flags where available
2. **Config patching mode**
- Some tools read config files—generate ephemeral config with memory blocks
3. **MCP mode (future)**
- Expose memory as an MCP server so tools that support MCP can query it directly
## MVP milestones
1. `memd` daemon + SQLite store + `memctl`
2. Repo/user scoping + retrieval ordering
3. `memwrap` adapter for 1 tool (pick the easiest)
4. Suggest-only writeback + approval queue
5. Basic search + tagging
6. Optional: vector retrieval for long notes
## Tech choices (suggested)
- Language: Go or Rust (single binary, easy daemon) or Node.js (fast iteration)
- Store: SQLite
- Vectors: sqlite-vss or LanceDB
- Auth: localhost token + file permissions
- Packaging: Homebrew + npm + curl install script
"
implement the hooks and test it out too