@stackmemoryai/stackmemory 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli/commands/orchestrate.js +334 -4
- package/dist/src/cli/commands/orchestrator.js +283 -24
- package/package.json +1 -2
- package/scripts/gepa/.before-optimize.md +0 -112
- package/scripts/gepa/README.md +0 -275
- package/scripts/gepa/config.json +0 -59
- package/scripts/gepa/evals/coding-tasks.jsonl +0 -5
- package/scripts/gepa/evals/fixtures/api-endpoint.ts +0 -31
- package/scripts/gepa/evals/fixtures/brittle-integration.ts +0 -38
- package/scripts/gepa/evals/fixtures/buggy-loop.js +0 -18
- package/scripts/gepa/evals/fixtures/callback-hell.js +0 -53
- package/scripts/gepa/evals/fixtures/fts5-triggers.sql +0 -23
- package/scripts/gepa/evals/fixtures/leaky-service.ts +0 -70
- package/scripts/gepa/evals/fixtures/mcp-dispatch-stub.ts +0 -39
- package/scripts/gepa/evals/fixtures/pr-diff.txt +0 -24
- package/scripts/gepa/evals/fixtures/unsafe-webhook.ts +0 -34
- package/scripts/gepa/evals/fixtures/unwrapped-db-op.ts +0 -42
- package/scripts/gepa/evals/stackmemory-tasks.jsonl +0 -8
- package/scripts/gepa/generations/gen-000/baseline.md +0 -112
- package/scripts/gepa/generations/gen-001/baseline.md +0 -112
- package/scripts/gepa/generations/gen-001/variant-a.md +0 -107
- package/scripts/gepa/generations/gen-001/variant-b.md +0 -216
- package/scripts/gepa/generations/gen-001/variant-c.md +0 -83
- package/scripts/gepa/generations/gen-001/variant-d.md +0 -90
- package/scripts/gepa/hooks/auto-optimize.js +0 -494
- package/scripts/gepa/hooks/eval-tracker.js +0 -203
- package/scripts/gepa/hooks/reflect.js +0 -350
- package/scripts/gepa/optimize.js +0 -853
- package/scripts/gepa/results/eval-1-baseline.json +0 -218
- package/scripts/gepa/results/eval-1-variant-a.json +0 -218
- package/scripts/gepa/results/eval-1-variant-b.json +0 -218
- package/scripts/gepa/results/eval-1-variant-c.json +0 -218
- package/scripts/gepa/results/eval-1-variant-d.json +0 -218
- package/scripts/gepa/state.json +0 -49
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
// Database operation with no error handling — needs StackMemory error wrapping
|
|
2
|
-
|
|
3
|
-
interface Frame {
|
|
4
|
-
id: string;
|
|
5
|
-
name: string;
|
|
6
|
-
status: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// Simulated database
|
|
10
|
-
const db = {
|
|
11
|
-
prepare(sql: string) {
|
|
12
|
-
return {
|
|
13
|
-
get(...params: unknown[]): Frame | undefined {
|
|
14
|
-
// May throw: SQLITE_BUSY, SQLITE_CONSTRAINT, SQLITE_CORRUPT
|
|
15
|
-
throw new Error('SQLITE_BUSY: database is locked');
|
|
16
|
-
},
|
|
17
|
-
run(...params: unknown[]) {
|
|
18
|
-
// May throw various SQLite errors
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// This function has NO error handling. Wrap it properly using:
|
|
25
|
-
// - DatabaseError from core/errors
|
|
26
|
-
// - Appropriate ErrorCode (DB_QUERY_FAILED, DB_CONNECTION_FAILED)
|
|
27
|
-
// - Preserve the original error as cause
|
|
28
|
-
// - Set isRetryable = true for connection/busy errors, false for constraint errors
|
|
29
|
-
// - Log with structured context (operation name, frameId)
|
|
30
|
-
async function getFrameById(frameId: string): Promise<Frame | null> {
|
|
31
|
-
const row = db.prepare('SELECT * FROM frames WHERE id = ?').get(frameId);
|
|
32
|
-
return row || null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function updateFrameStatus(
|
|
36
|
-
frameId: string,
|
|
37
|
-
status: string
|
|
38
|
-
): Promise<void> {
|
|
39
|
-
db.prepare('UPDATE frames SET status = ? WHERE id = ?').run(status, frameId);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export { getFrameById, updateFrameStatus };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{"id": "sm-001", "name": "add_mcp_tool_handler", "prompt": "Add a new MCP tool handler called 'get_frame_summary' that takes a frameId (required string) and returns { frameId, name, status, eventCount }. Follow the existing switch/case dispatch pattern in server.ts. Include Zod input validation.", "input_file": "fixtures/mcp-dispatch-stub.ts", "expected": {"has_switch_case": true, "has_zod_schema": true, "validates_input": true, "returns_typed_response": true, "handles_not_found": true}, "weight": 1.5}
|
|
2
|
-
{"id": "sm-002", "name": "fix_fts5_trigger_bug", "prompt": "The FTS5 DELETE trigger is missing — when a frame is deleted from the frames table, the frames_fts index is not updated. Add the missing AFTER DELETE trigger following the pattern of the existing INSERT and UPDATE triggers.", "input_file": "fixtures/fts5-triggers.sql", "expected": {"has_delete_trigger": true, "uses_fts_delete_syntax": true, "references_old_row": true, "matches_column_list": true}, "weight": 1.8}
|
|
3
|
-
{"id": "sm-003", "name": "daemon_service_lifecycle", "prompt": "This daemon service has a timer leak — when updateConfig() restarts the service, the old interval is not cleared before creating a new one if start() is called while already running. Fix the bug and add a getState() method that returns { isRunning, intervalMs, lastRunTime, errorCount }.", "input_file": "fixtures/leaky-service.ts", "expected": {"clears_old_interval": true, "prevents_double_start": true, "has_getstate_method": true, "returns_correct_state_shape": true}, "weight": 1.5}
|
|
4
|
-
{"id": "sm-004", "name": "webhook_payload_validation", "prompt": "This webhook handler is vulnerable to prototype pollution and has no input length limits. Fix the validation to: 1) reject __proto__ and constructor keys, 2) limit title to 500 chars, 3) limit description to 5000 chars, 4) validate that action is one of create/update/remove.", "input_file": "fixtures/unsafe-webhook.ts", "expected": {"blocks_proto_pollution": true, "limits_title_length": true, "limits_description_length": true, "validates_action_enum": true, "returns_null_on_invalid": true}, "weight": 2.0}
|
|
5
|
-
{"id": "sm-005", "name": "error_handling_chain", "prompt": "Wrap this database operation in proper StackMemory error handling: use DatabaseError with appropriate ErrorCode, preserve the cause chain, set isRetryable based on error type (connection errors are retryable, constraint violations are not), and log with structured context.", "input_file": "fixtures/unwrapped-db-op.ts", "expected": {"uses_database_error": true, "preserves_cause": true, "sets_retryable_correctly": true, "has_structured_logging": true, "catches_unknown_type": true}, "weight": 1.3}
|
|
6
|
-
{"id": "sm-006", "name": "integration_graceful_degradation", "prompt": "This integration handler crashes the MCP server when the external API is down. Refactor it to degrade gracefully: catch connection errors, return a user-friendly MCPResponse with metadata.unavailable=true, log at debug level (not error), and don't retry on 4xx errors.", "input_file": "fixtures/brittle-integration.ts", "expected": {"catches_connection_errors": true, "returns_mcp_response": true, "sets_unavailable_metadata": true, "logs_at_debug": true, "no_retry_on_4xx": true}, "weight": 1.5}
|
|
7
|
-
{"id": "sm-007", "name": "sqlite_migration_safety", "prompt": "Write a safe SQLite migration that adds a 'tags' TEXT column to the frames table. The migration must: 1) check if column already exists first (idempotent), 2) wrap in a transaction, 3) update the schema_version table, 4) handle the case where schema_version table doesn't exist yet.", "expected": {"checks_column_exists": true, "uses_transaction": true, "updates_schema_version": true, "is_idempotent": true, "handles_missing_version_table": true}, "weight": 1.5}
|
|
8
|
-
{"id": "sm-008", "name": "review_pr_security", "prompt": "Review this PR diff and identify all security issues, performance problems, and code quality concerns. Provide actionable feedback for each issue found.", "input_file": "fixtures/pr-diff.txt", "expected": {"identifies_sql_injection": true, "identifies_plaintext_password": true, "identifies_credential_logging": true, "identifies_weak_session": true, "provides_fix_suggestions": true}, "weight": 2.0}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
Sol is the monorepo for **Rize**, an automatic time tracking application. The stack consists of:
|
|
8
|
-
- **api/** - Rails 7.1 GraphQL backend (Ruby 3.3.5)
|
|
9
|
-
- **web/** - Next.js 14 React web app (Node 22)
|
|
10
|
-
- **electron/** - Electron desktop app (Node 22)
|
|
11
|
-
- **services/** - Bun-based TypeScript event consumers/workers
|
|
12
|
-
- **vanity/** - Webflow marketing site scripts (deprecated)
|
|
13
|
-
- **voyager/** - Marketing website for home and landing pageas (Next.js)
|
|
14
|
-
- **puppet/** - Puppeteer server for images/PDFs
|
|
15
|
-
- **chrome/** - Chrome browser extension
|
|
16
|
-
- **docs/** - Docusaurus documentation site
|
|
17
|
-
- **zapier/** - Zapier integration
|
|
18
|
-
|
|
19
|
-
## Development Commands
|
|
20
|
-
|
|
21
|
-
### Starting Development Environment
|
|
22
|
-
```bash
|
|
23
|
-
# Start all services (requires iTerm2 on macOS)
|
|
24
|
-
./scripts/run-dev.sh
|
|
25
|
-
|
|
26
|
-
# Or start individually:
|
|
27
|
-
cd api && hivemind Procfile.dev # Rails + AnyCable + Sidekiq + Clockwork
|
|
28
|
-
cd web && npm run dev # Next.js dev server
|
|
29
|
-
cd electron && npm run dev # Electron with hot reload
|
|
30
|
-
cd services && hivemind Procfile.dev # Bun services
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### Docker Dependencies (api/docker-compose.yml)
|
|
34
|
-
```bash
|
|
35
|
-
cd api && docker-compose up -d
|
|
36
|
-
# TimescaleDB: localhost:15432
|
|
37
|
-
# Redis: localhost:16379
|
|
38
|
-
# Kafka: localhost:9092
|
|
39
|
-
# MySQL: localhost:13306
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Testing
|
|
43
|
-
```bash
|
|
44
|
-
# API (RSpec)
|
|
45
|
-
cd api && bundle exec rspec
|
|
46
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb # Single file
|
|
47
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb:42 # Single test at line
|
|
48
|
-
|
|
49
|
-
# Electron (Jest)
|
|
50
|
-
cd electron && npm test
|
|
51
|
-
cd electron && npm run test:watch
|
|
52
|
-
cd electron && npm run test:coverage
|
|
53
|
-
|
|
54
|
-
# Web - no active tests (exits 0)
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Building
|
|
58
|
-
```bash
|
|
59
|
-
cd api && bundle install && rake db:migrate
|
|
60
|
-
cd web && npm run build # Runs gql-gen, tailwind, next build
|
|
61
|
-
cd electron && npm run build # Electron Forge make
|
|
62
|
-
cd services && bun install
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### GraphQL Code Generation
|
|
66
|
-
```bash
|
|
67
|
-
cd web && npm run build # Includes gql codegen
|
|
68
|
-
cd electron && npm run dev # Runs gql codegen as part of dev
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Architecture
|
|
72
|
-
|
|
73
|
-
### GraphQL API Structure
|
|
74
|
-
The API exposes two GraphQL endpoints:
|
|
75
|
-
- **api/v1** - Public API (OAuth consumers, Zapier)
|
|
76
|
-
- **private/v1** - Private API (web, electron apps)
|
|
77
|
-
|
|
78
|
-
Located at `api/app/graphql/{api,private}/v1/`
|
|
79
|
-
|
|
80
|
-
### Real-time Communication
|
|
81
|
-
- **AnyCable** WebSocket server for subscriptions
|
|
82
|
-
- ActionCable channels in `api/app/channels/`
|
|
83
|
-
- WebSocket config: `api/config/cable.yml` and `api/config/anycable.yml`
|
|
84
|
-
|
|
85
|
-
### Background Jobs
|
|
86
|
-
- **Sidekiq** for async job processing (`api/config/sidekiq.yml`)
|
|
87
|
-
- **Clockwork** for scheduled jobs (`api/config/clock.rb`)
|
|
88
|
-
|
|
89
|
-
### Event Streaming
|
|
90
|
-
- **Kafka** for event publishing/consumption
|
|
91
|
-
- Services consume events via `services/consumers/`
|
|
92
|
-
- Kafka config: `api/config/initializers/kafka.rb`
|
|
93
|
-
|
|
94
|
-
### Databases
|
|
95
|
-
- **Primary PostgreSQL** - Main application data
|
|
96
|
-
- **TimescaleDB** - Time-series data (separate connection in `database.yml`)
|
|
97
|
-
- **MySQL** - Legacy/external integrations
|
|
98
|
-
- **Redis** - Caching, ActionCable, Sidekiq
|
|
99
|
-
|
|
100
|
-
## Style Guidelines
|
|
101
|
-
|
|
102
|
-
### JavaScript/TypeScript
|
|
103
|
-
- Use `test()` instead of `it()` in tests
|
|
104
|
-
- Use `toBeCalled()` instead of `toHaveBeenCalledWith()` in jest assertions
|
|
105
|
-
|
|
106
|
-
## Key Configuration Files
|
|
107
|
-
|
|
108
|
-
- `api/config/database.yml` - Database connections (primary + timescale)
|
|
109
|
-
- `api/config/cable.yml` - AnyCable WebSocket config
|
|
110
|
-
- `api/Procfile.dev` - Development processes (rails, anycable, sidekiq, clockwork)
|
|
111
|
-
- `sol.code-workspace` - VS Code multi-folder workspace
|
|
112
|
-
- Each project requires its own `.env` file (not in repo)
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
Sol is the monorepo for **Rize**, an automatic time tracking application. The stack consists of:
|
|
8
|
-
- **api/** - Rails 7.1 GraphQL backend (Ruby 3.3.5)
|
|
9
|
-
- **web/** - Next.js 14 React web app (Node 22)
|
|
10
|
-
- **electron/** - Electron desktop app (Node 22)
|
|
11
|
-
- **services/** - Bun-based TypeScript event consumers/workers
|
|
12
|
-
- **vanity/** - Webflow marketing site scripts (deprecated)
|
|
13
|
-
- **voyager/** - Marketing website for home and landing pageas (Next.js)
|
|
14
|
-
- **puppet/** - Puppeteer server for images/PDFs
|
|
15
|
-
- **chrome/** - Chrome browser extension
|
|
16
|
-
- **docs/** - Docusaurus documentation site
|
|
17
|
-
- **zapier/** - Zapier integration
|
|
18
|
-
|
|
19
|
-
## Development Commands
|
|
20
|
-
|
|
21
|
-
### Starting Development Environment
|
|
22
|
-
```bash
|
|
23
|
-
# Start all services (requires iTerm2 on macOS)
|
|
24
|
-
./scripts/run-dev.sh
|
|
25
|
-
|
|
26
|
-
# Or start individually:
|
|
27
|
-
cd api && hivemind Procfile.dev # Rails + AnyCable + Sidekiq + Clockwork
|
|
28
|
-
cd web && npm run dev # Next.js dev server
|
|
29
|
-
cd electron && npm run dev # Electron with hot reload
|
|
30
|
-
cd services && hivemind Procfile.dev # Bun services
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### Docker Dependencies (api/docker-compose.yml)
|
|
34
|
-
```bash
|
|
35
|
-
cd api && docker-compose up -d
|
|
36
|
-
# TimescaleDB: localhost:15432
|
|
37
|
-
# Redis: localhost:16379
|
|
38
|
-
# Kafka: localhost:9092
|
|
39
|
-
# MySQL: localhost:13306
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Testing
|
|
43
|
-
```bash
|
|
44
|
-
# API (RSpec)
|
|
45
|
-
cd api && bundle exec rspec
|
|
46
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb # Single file
|
|
47
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb:42 # Single test at line
|
|
48
|
-
|
|
49
|
-
# Electron (Jest)
|
|
50
|
-
cd electron && npm test
|
|
51
|
-
cd electron && npm run test:watch
|
|
52
|
-
cd electron && npm run test:coverage
|
|
53
|
-
|
|
54
|
-
# Web - no active tests (exits 0)
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Building
|
|
58
|
-
```bash
|
|
59
|
-
cd api && bundle install && rake db:migrate
|
|
60
|
-
cd web && npm run build # Runs gql-gen, tailwind, next build
|
|
61
|
-
cd electron && npm run build # Electron Forge make
|
|
62
|
-
cd services && bun install
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### GraphQL Code Generation
|
|
66
|
-
```bash
|
|
67
|
-
cd web && npm run build # Includes gql codegen
|
|
68
|
-
cd electron && npm run dev # Runs gql codegen as part of dev
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Architecture
|
|
72
|
-
|
|
73
|
-
### GraphQL API Structure
|
|
74
|
-
The API exposes two GraphQL endpoints:
|
|
75
|
-
- **api/v1** - Public API (OAuth consumers, Zapier)
|
|
76
|
-
- **private/v1** - Private API (web, electron apps)
|
|
77
|
-
|
|
78
|
-
Located at `api/app/graphql/{api,private}/v1/`
|
|
79
|
-
|
|
80
|
-
### Real-time Communication
|
|
81
|
-
- **AnyCable** WebSocket server for subscriptions
|
|
82
|
-
- ActionCable channels in `api/app/channels/`
|
|
83
|
-
- WebSocket config: `api/config/cable.yml` and `api/config/anycable.yml`
|
|
84
|
-
|
|
85
|
-
### Background Jobs
|
|
86
|
-
- **Sidekiq** for async job processing (`api/config/sidekiq.yml`)
|
|
87
|
-
- **Clockwork** for scheduled jobs (`api/config/clock.rb`)
|
|
88
|
-
|
|
89
|
-
### Event Streaming
|
|
90
|
-
- **Kafka** for event publishing/consumption
|
|
91
|
-
- Services consume events via `services/consumers/`
|
|
92
|
-
- Kafka config: `api/config/initializers/kafka.rb`
|
|
93
|
-
|
|
94
|
-
### Databases
|
|
95
|
-
- **Primary PostgreSQL** - Main application data
|
|
96
|
-
- **TimescaleDB** - Time-series data (separate connection in `database.yml`)
|
|
97
|
-
- **MySQL** - Legacy/external integrations
|
|
98
|
-
- **Redis** - Caching, ActionCable, Sidekiq
|
|
99
|
-
|
|
100
|
-
## Style Guidelines
|
|
101
|
-
|
|
102
|
-
### JavaScript/TypeScript
|
|
103
|
-
- Use `test()` instead of `it()` in tests
|
|
104
|
-
- Use `toBeCalled()` instead of `toHaveBeenCalledWith()` in jest assertions
|
|
105
|
-
|
|
106
|
-
## Key Configuration Files
|
|
107
|
-
|
|
108
|
-
- `api/config/database.yml` - Database connections (primary + timescale)
|
|
109
|
-
- `api/config/cable.yml` - AnyCable WebSocket config
|
|
110
|
-
- `api/Procfile.dev` - Development processes (rails, anycable, sidekiq, clockwork)
|
|
111
|
-
- `sol.code-workspace` - VS Code multi-folder workspace
|
|
112
|
-
- Each project requires its own `.env` file (not in repo)
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
Guidance for Claude Code when working in this repository.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
Sol is the **Rize** monorepo (automatic time tracking). Stack:
|
|
8
|
-
- **api/** - Rails 7.1 GraphQL backend (Ruby 3.3.5)
|
|
9
|
-
- **web/** - Next.js 14 React app (Node 22)
|
|
10
|
-
- **electron/** - Electron desktop app (Node 22)
|
|
11
|
-
- **services/** - Bun TypeScript event consumers/workers
|
|
12
|
-
- **vanity/** - Webflow marketing scripts (deprecated)
|
|
13
|
-
- **voyager/** - Marketing website (Next.js)
|
|
14
|
-
- **puppet/** - Puppeteer server for images/PDFs
|
|
15
|
-
- **chrome/** - Chrome extension
|
|
16
|
-
- **docs/** - Docusaurus site
|
|
17
|
-
- **zapier/** - Zapier integration
|
|
18
|
-
|
|
19
|
-
## Development Commands
|
|
20
|
-
|
|
21
|
-
### Start Dev Environment
|
|
22
|
-
```bash
|
|
23
|
-
./scripts/run-dev.sh # All services (requires iTerm2 on macOS)
|
|
24
|
-
|
|
25
|
-
# Individually:
|
|
26
|
-
cd api && hivemind Procfile.dev # Rails + AnyCable + Sidekiq + Clockwork
|
|
27
|
-
cd web && npm run dev # Next.js (port 3001)
|
|
28
|
-
cd electron && npm run dev # Electron with hot reload
|
|
29
|
-
cd services && hivemind Procfile.dev # Bun services
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Docker (required before api/services)
|
|
33
|
-
```bash
|
|
34
|
-
cd api && docker-compose up -d
|
|
35
|
-
# TimescaleDB: localhost:15432 | Redis: localhost:16379
|
|
36
|
-
# Kafka: localhost:9092 | MySQL: localhost:13306
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Testing
|
|
40
|
-
```bash
|
|
41
|
-
# API (RSpec)
|
|
42
|
-
cd api && bundle exec rspec
|
|
43
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb
|
|
44
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb:42
|
|
45
|
-
|
|
46
|
-
# Electron (Jest)
|
|
47
|
-
cd electron && npm test
|
|
48
|
-
cd electron && npm run test:watch
|
|
49
|
-
cd electron && npm run test:coverage
|
|
50
|
-
|
|
51
|
-
# Web: no active tests (exits 0)
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Building
|
|
55
|
-
```bash
|
|
56
|
-
cd api && bundle install && rake db:migrate
|
|
57
|
-
cd web && npm run build # gql-gen + tailwind + next build
|
|
58
|
-
cd electron && npm run build # Electron Forge make
|
|
59
|
-
cd services && bun install
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### GraphQL Code Generation
|
|
63
|
-
- `cd web && npm run build` — includes gql codegen
|
|
64
|
-
- `cd electron && npm run dev` — runs gql codegen automatically
|
|
65
|
-
|
|
66
|
-
## Architecture
|
|
67
|
-
|
|
68
|
-
### GraphQL API
|
|
69
|
-
Two endpoints:
|
|
70
|
-
- **api/v1** — Public API (OAuth, Zapier) → `api/app/graphql/api/v1/`
|
|
71
|
-
- **private/v1** — Internal API (web, electron) → `api/app/graphql/private/v1/`
|
|
72
|
-
|
|
73
|
-
### Real-time
|
|
74
|
-
- AnyCable WebSocket subscriptions
|
|
75
|
-
- ActionCable channels: `api/app/channels/`
|
|
76
|
-
- Config: `api/config/cable.yml`, `api/config/anycable.yml`
|
|
77
|
-
|
|
78
|
-
### Background Jobs
|
|
79
|
-
- Sidekiq (async): `api/config/sidekiq.yml`
|
|
80
|
-
- Clockwork (scheduled): `api/config/clock.rb`
|
|
81
|
-
|
|
82
|
-
### Event Streaming
|
|
83
|
-
- Kafka publish/consume via `services/consumers/`
|
|
84
|
-
- Config: `api/config/initializers/kafka.rb`
|
|
85
|
-
|
|
86
|
-
### Databases
|
|
87
|
-
- **PostgreSQL** — primary app data
|
|
88
|
-
- **TimescaleDB** — time-series (separate connection in `database.yml`)
|
|
89
|
-
- **MySQL** — legacy integrations
|
|
90
|
-
- **Redis** — caching, ActionCable, Sidekiq
|
|
91
|
-
|
|
92
|
-
## Style Guidelines
|
|
93
|
-
|
|
94
|
-
### JavaScript/TypeScript Tests
|
|
95
|
-
- Use `test()` not `it()`
|
|
96
|
-
- Use `toBeCalled()` not `toHaveBeenCalledWith()`
|
|
97
|
-
|
|
98
|
-
## Key Config Files
|
|
99
|
-
|
|
100
|
-
| File | Purpose |
|
|
101
|
-
|------|---------|
|
|
102
|
-
| `api/config/database.yml` | DB connections (primary + timescale) |
|
|
103
|
-
| `api/config/cable.yml` | AnyCable WebSocket config |
|
|
104
|
-
| `api/Procfile.dev` | Dev processes (rails, anycable, sidekiq, clockwork) |
|
|
105
|
-
| `sol.code-workspace` | VS Code multi-folder workspace |
|
|
106
|
-
|
|
107
|
-
Each subproject needs its own `.env` file (not committed).
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
```markdown
|
|
2
|
-
# CLAUDE.md
|
|
3
|
-
|
|
4
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
5
|
-
|
|
6
|
-
## Project Overview
|
|
7
|
-
|
|
8
|
-
Sol is the monorepo for **Rize**, an automatic time tracking application. The stack consists of:
|
|
9
|
-
- **api/** - Rails 7.1 GraphQL backend (Ruby 3.3.5)
|
|
10
|
-
- **web/** - Next.js 14 React web app (Node 22)
|
|
11
|
-
- **electron/** - Electron desktop app (Node 22)
|
|
12
|
-
- **services/** - Bun-based TypeScript event consumers/workers
|
|
13
|
-
- **vanity/** - Webflow marketing site scripts (deprecated)
|
|
14
|
-
- **voyager/** - Marketing website for home and landing pages (Next.js)
|
|
15
|
-
- **puppet/** - Puppeteer server for images/PDFs
|
|
16
|
-
- **chrome/** - Chrome browser extension
|
|
17
|
-
- **docs/** - Docusaurus documentation site
|
|
18
|
-
- **zapier/** - Zapier integration
|
|
19
|
-
|
|
20
|
-
## Development Commands
|
|
21
|
-
|
|
22
|
-
### Starting Development Environment
|
|
23
|
-
```bash
|
|
24
|
-
# Start all services (requires iTerm2 on macOS)
|
|
25
|
-
./scripts/run-dev.sh
|
|
26
|
-
|
|
27
|
-
# Or start individually:
|
|
28
|
-
cd api && hivemind Procfile.dev # Rails + AnyCable + Sidekiq + Clockwork
|
|
29
|
-
cd web && npm run dev # Next.js dev server
|
|
30
|
-
cd electron && npm run dev # Electron with hot reload
|
|
31
|
-
cd services && hivemind Procfile.dev # Bun services
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Docker Dependencies (api/docker-compose.yml)
|
|
35
|
-
```bash
|
|
36
|
-
cd api && docker-compose up -d
|
|
37
|
-
# TimescaleDB: localhost:15432
|
|
38
|
-
# Redis: localhost:16379
|
|
39
|
-
# Kafka: localhost:9092
|
|
40
|
-
# MySQL: localhost:13306
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Testing
|
|
44
|
-
```bash
|
|
45
|
-
# API (RSpec)
|
|
46
|
-
cd api && bundle exec rspec
|
|
47
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb # Single file
|
|
48
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb:42 # Single test at line
|
|
49
|
-
|
|
50
|
-
# Electron (Jest)
|
|
51
|
-
cd electron && npm test
|
|
52
|
-
cd electron && npm run test:watch
|
|
53
|
-
cd electron && npm run test:coverage
|
|
54
|
-
|
|
55
|
-
# Web - no active tests (exits 0)
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Building
|
|
59
|
-
```bash
|
|
60
|
-
cd api && bundle install && rake db:migrate
|
|
61
|
-
cd web && npm run build # Runs gql-gen, tailwind, next build
|
|
62
|
-
cd electron && npm run build # Electron Forge make
|
|
63
|
-
cd services && bun install
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### GraphQL Code Generation
|
|
67
|
-
```bash
|
|
68
|
-
cd web && npm run build # Includes gql codegen
|
|
69
|
-
cd electron && npm run dev # Runs gql codegen as part of dev
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Architecture
|
|
73
|
-
|
|
74
|
-
### GraphQL API Structure
|
|
75
|
-
The API exposes two GraphQL endpoints:
|
|
76
|
-
- **api/v1** - Public API (OAuth consumers, Zapier)
|
|
77
|
-
- **private/v1** - Private API (web, electron apps)
|
|
78
|
-
|
|
79
|
-
Located at `api/app/graphql/{api,private}/v1/`
|
|
80
|
-
|
|
81
|
-
<example>
|
|
82
|
-
# Adding a new mutation to the private API:
|
|
83
|
-
# File: api/app/graphql/private/v1/mutations/update_something.rb
|
|
84
|
-
module Private
|
|
85
|
-
module V1
|
|
86
|
-
module Mutations
|
|
87
|
-
class UpdateSomething < BaseMutation
|
|
88
|
-
argument :id, ID, required: true
|
|
89
|
-
field :something, Types::SomethingType, null: true
|
|
90
|
-
|
|
91
|
-
def resolve(id:)
|
|
92
|
-
something = Something.find(id)
|
|
93
|
-
something.update!(...)
|
|
94
|
-
{ something: something }
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
</example>
|
|
101
|
-
|
|
102
|
-
### Real-time Communication
|
|
103
|
-
- **AnyCable** WebSocket server for subscriptions
|
|
104
|
-
- ActionCable channels in `api/app/channels/`
|
|
105
|
-
- WebSocket config: `api/config/cable.yml` and `api/config/anycable.yml`
|
|
106
|
-
|
|
107
|
-
### Background Jobs
|
|
108
|
-
- **Sidekiq** for async job processing (`api/config/sidekiq.yml`)
|
|
109
|
-
- **Clockwork** for scheduled jobs (`api/config/clock.rb`)
|
|
110
|
-
|
|
111
|
-
<example>
|
|
112
|
-
# Adding a new Sidekiq job:
|
|
113
|
-
class MyWorker
|
|
114
|
-
include Sidekiq::Worker
|
|
115
|
-
sidekiq_options queue: :default
|
|
116
|
-
|
|
117
|
-
def perform(user_id)
|
|
118
|
-
user = User.find(user_id)
|
|
119
|
-
# do work
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# Enqueue it:
|
|
124
|
-
MyWorker.perform_async(user.id)
|
|
125
|
-
</example>
|
|
126
|
-
|
|
127
|
-
### Event Streaming
|
|
128
|
-
- **Kafka** for event publishing/consumption
|
|
129
|
-
- Services consume events via `services/consumers/`
|
|
130
|
-
- Kafka config: `api/config/initializers/kafka.rb`
|
|
131
|
-
|
|
132
|
-
### Databases
|
|
133
|
-
- **Primary PostgreSQL** - Main application data
|
|
134
|
-
- **TimescaleDB** - Time-series data (separate connection in `database.yml`)
|
|
135
|
-
- **MySQL** - Legacy/external integrations
|
|
136
|
-
- **Redis** - Caching, ActionCable, Sidekiq
|
|
137
|
-
|
|
138
|
-
## Style Guidelines
|
|
139
|
-
|
|
140
|
-
### JavaScript/TypeScript
|
|
141
|
-
|
|
142
|
-
Use `test()` instead of `it()` in tests:
|
|
143
|
-
|
|
144
|
-
<example>
|
|
145
|
-
// CORRECT
|
|
146
|
-
test('returns the user name', () => {
|
|
147
|
-
expect(getUser().name).toBe('Alice')
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
// WRONG
|
|
151
|
-
it('returns the user name', () => {
|
|
152
|
-
expect(getUser().name).toBe('Alice')
|
|
153
|
-
})
|
|
154
|
-
</example>
|
|
155
|
-
|
|
156
|
-
Use `toBeCalled()` instead of `toHaveBeenCalledWith()` in jest assertions:
|
|
157
|
-
|
|
158
|
-
<example>
|
|
159
|
-
// CORRECT
|
|
160
|
-
expect(mockFn).toBeCalled()
|
|
161
|
-
|
|
162
|
-
// WRONG
|
|
163
|
-
expect(mockFn).toHaveBeenCalledWith(someArg)
|
|
164
|
-
</example>
|
|
165
|
-
|
|
166
|
-
### Ruby/RSpec
|
|
167
|
-
|
|
168
|
-
Use `be_between` for time assertions (no `freeze_time` or `travel_to` in this repo):
|
|
169
|
-
|
|
170
|
-
<example>
|
|
171
|
-
# CORRECT
|
|
172
|
-
before = Time.current
|
|
173
|
-
subject.call
|
|
174
|
-
after = Time.current
|
|
175
|
-
expect(record.updated_at).to be_between(before, after)
|
|
176
|
-
|
|
177
|
-
# WRONG - freeze_time not available
|
|
178
|
-
freeze_time do
|
|
179
|
-
subject.call
|
|
180
|
-
expect(record.updated_at).to eq(Time.current)
|
|
181
|
-
end
|
|
182
|
-
</example>
|
|
183
|
-
|
|
184
|
-
Use `create(:user_with_default_workspace)` for a user with identity + workspace:
|
|
185
|
-
|
|
186
|
-
<example>
|
|
187
|
-
let(:user) { create(:user_with_default_workspace) }
|
|
188
|
-
let(:identity) { user.identities.first }
|
|
189
|
-
let(:workspace) { identity.workspaces.first }
|
|
190
|
-
</example>
|
|
191
|
-
|
|
192
|
-
Use `private_v1_execute_query` / `private_v1_execute_mutation` in GraphQL specs:
|
|
193
|
-
|
|
194
|
-
<example>
|
|
195
|
-
RSpec.describe 'someQuery', type: :request do
|
|
196
|
-
let(:user) { create(:user_with_default_workspace) }
|
|
197
|
-
|
|
198
|
-
it 'returns expected data' do
|
|
199
|
-
private_v1_execute_query(
|
|
200
|
-
query: SOME_QUERY,
|
|
201
|
-
variables: { id: user.id },
|
|
202
|
-
user: user
|
|
203
|
-
)
|
|
204
|
-
expect(response_data['someQuery']['field']).to eq('value')
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
</example>
|
|
208
|
-
|
|
209
|
-
## Key Configuration Files
|
|
210
|
-
|
|
211
|
-
- `api/config/database.yml` - Database connections (primary + timescale)
|
|
212
|
-
- `api/config/cable.yml` - AnyCable WebSocket config
|
|
213
|
-
- `api/Procfile.dev` - Development processes (rails, anycable, sidekiq, clockwork)
|
|
214
|
-
- `sol.code-workspace` - VS Code multi-folder workspace
|
|
215
|
-
- Each project requires its own `.env` file (not in repo)
|
|
216
|
-
```
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
```markdown
|
|
2
|
-
# CLAUDE.md
|
|
3
|
-
|
|
4
|
-
Sol is the monorepo for **Rize**, an automatic time tracking application.
|
|
5
|
-
|
|
6
|
-
## Stack
|
|
7
|
-
- **api/** - Rails 7.1 GraphQL backend (Ruby 3.3.5)
|
|
8
|
-
- **web/** - Next.js 14 React web app (Node 22)
|
|
9
|
-
- **electron/** - Electron desktop app (Node 22)
|
|
10
|
-
- **services/** - Bun-based TypeScript event consumers/workers
|
|
11
|
-
- **voyager/** - Marketing website (Next.js)
|
|
12
|
-
- **puppet/** - Puppeteer server for images/PDFs
|
|
13
|
-
- **chrome/** - Chrome browser extension
|
|
14
|
-
- **docs/** - Docusaurus documentation site
|
|
15
|
-
- **zapier/** - Zapier integration
|
|
16
|
-
- **vanity/** - Webflow scripts (deprecated)
|
|
17
|
-
|
|
18
|
-
## Development Commands
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# Start all (requires iTerm2)
|
|
22
|
-
./scripts/run-dev.sh
|
|
23
|
-
|
|
24
|
-
# Individual services
|
|
25
|
-
cd api && hivemind Procfile.dev # Rails + AnyCable + Sidekiq + Clockwork
|
|
26
|
-
cd web && npm run dev # Next.js (port 3001)
|
|
27
|
-
cd electron && npm run dev # Electron + gql codegen
|
|
28
|
-
cd services && hivemind Procfile.dev # Bun consumers
|
|
29
|
-
|
|
30
|
-
# Docker deps (TimescaleDB:15432, Redis:16379, Kafka:9092, MySQL:13306)
|
|
31
|
-
cd api && docker-compose up -d
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Testing & Building
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# API (RSpec)
|
|
38
|
-
cd api && bundle exec rspec
|
|
39
|
-
cd api && bundle exec rspec spec/path/to/file_spec.rb:42
|
|
40
|
-
|
|
41
|
-
# Electron (Jest)
|
|
42
|
-
cd electron && npm test
|
|
43
|
-
|
|
44
|
-
# Web - no active tests (exits 0)
|
|
45
|
-
|
|
46
|
-
# Build
|
|
47
|
-
cd api && bundle install && rake db:migrate
|
|
48
|
-
cd web && npm run build # gql-gen + tailwind + next build
|
|
49
|
-
cd electron && npm run build
|
|
50
|
-
cd services && bun install
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Architecture
|
|
54
|
-
|
|
55
|
-
### GraphQL API
|
|
56
|
-
Two endpoints at `api/app/graphql/{api,private}/v1/`:
|
|
57
|
-
- **api/v1** - Public API (OAuth, Zapier)
|
|
58
|
-
- **private/v1** - Private API (web, electron)
|
|
59
|
-
|
|
60
|
-
### Infrastructure
|
|
61
|
-
- **AnyCable** WebSocket subscriptions (`api/config/cable.yml`, `anycable.yml`)
|
|
62
|
-
- **Sidekiq** async jobs (`api/config/sidekiq.yml`)
|
|
63
|
-
- **Clockwork** scheduled jobs (`api/config/clock.rb`)
|
|
64
|
-
- **Kafka** event streaming (`api/config/initializers/kafka.rb`, `services/consumers/`)
|
|
65
|
-
|
|
66
|
-
### Databases
|
|
67
|
-
- **PostgreSQL** - Primary app data
|
|
68
|
-
- **TimescaleDB** - Time-series (separate connection in `database.yml`)
|
|
69
|
-
- **MySQL** - Legacy integrations
|
|
70
|
-
- **Redis** - Caching, ActionCable, Sidekiq
|
|
71
|
-
|
|
72
|
-
## Style Guidelines
|
|
73
|
-
|
|
74
|
-
### JavaScript/TypeScript
|
|
75
|
-
- Use `test()` not `it()` in tests
|
|
76
|
-
- Use `toBeCalled()` not `toHaveBeenCalledWith()` in Jest assertions
|
|
77
|
-
|
|
78
|
-
## Key Config Files
|
|
79
|
-
- `api/config/database.yml` - DB connections
|
|
80
|
-
- `api/Procfile.dev` - Dev processes
|
|
81
|
-
- `sol.code-workspace` - VS Code workspace
|
|
82
|
-
- Each project requires its own `.env` (not in repo)
|
|
83
|
-
```
|