@stackmemoryai/stackmemory 1.6.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/src/cli/commands/orchestrate.js +249 -2
  2. package/dist/src/cli/commands/orchestrator.js +206 -23
  3. package/package.json +1 -2
  4. package/scripts/gepa/.before-optimize.md +0 -112
  5. package/scripts/gepa/README.md +0 -275
  6. package/scripts/gepa/config.json +0 -59
  7. package/scripts/gepa/evals/coding-tasks.jsonl +0 -5
  8. package/scripts/gepa/evals/fixtures/api-endpoint.ts +0 -31
  9. package/scripts/gepa/evals/fixtures/brittle-integration.ts +0 -38
  10. package/scripts/gepa/evals/fixtures/buggy-loop.js +0 -18
  11. package/scripts/gepa/evals/fixtures/callback-hell.js +0 -53
  12. package/scripts/gepa/evals/fixtures/fts5-triggers.sql +0 -23
  13. package/scripts/gepa/evals/fixtures/leaky-service.ts +0 -70
  14. package/scripts/gepa/evals/fixtures/mcp-dispatch-stub.ts +0 -39
  15. package/scripts/gepa/evals/fixtures/pr-diff.txt +0 -24
  16. package/scripts/gepa/evals/fixtures/unsafe-webhook.ts +0 -34
  17. package/scripts/gepa/evals/fixtures/unwrapped-db-op.ts +0 -42
  18. package/scripts/gepa/evals/stackmemory-tasks.jsonl +0 -8
  19. package/scripts/gepa/generations/gen-000/baseline.md +0 -112
  20. package/scripts/gepa/generations/gen-001/baseline.md +0 -112
  21. package/scripts/gepa/generations/gen-001/variant-a.md +0 -107
  22. package/scripts/gepa/generations/gen-001/variant-b.md +0 -216
  23. package/scripts/gepa/generations/gen-001/variant-c.md +0 -83
  24. package/scripts/gepa/generations/gen-001/variant-d.md +0 -90
  25. package/scripts/gepa/hooks/auto-optimize.js +0 -494
  26. package/scripts/gepa/hooks/eval-tracker.js +0 -203
  27. package/scripts/gepa/hooks/reflect.js +0 -350
  28. package/scripts/gepa/optimize.js +0 -853
  29. package/scripts/gepa/results/eval-1-baseline.json +0 -218
  30. package/scripts/gepa/results/eval-1-variant-a.json +0 -218
  31. package/scripts/gepa/results/eval-1-variant-b.json +0 -218
  32. package/scripts/gepa/results/eval-1-variant-c.json +0 -218
  33. package/scripts/gepa/results/eval-1-variant-d.json +0 -218
  34. package/scripts/gepa/state.json +0 -49
@@ -1,39 +0,0 @@
1
- // Existing MCP server dispatch pattern — add get_frame_summary handler
2
- import { z } from 'zod';
3
-
4
- interface Frame {
5
- id: string;
6
- name: string;
7
- status: 'open' | 'closed';
8
- events: Array<{ id: string; type: string }>;
9
- }
10
-
11
- // Simulated frame store
12
- const frames = new Map<string, Frame>();
13
-
14
- // Existing tool dispatch (add your handler here)
15
- async function handleToolCall(name: string, args: unknown) {
16
- switch (name) {
17
- case 'start_frame': {
18
- const input = z.object({ name: z.string().min(1) }).parse(args);
19
- const id = `frame-${Date.now()}`;
20
- frames.set(id, { id, name: input.name, status: 'open', events: [] });
21
- return { frameId: id, status: 'opened' };
22
- }
23
-
24
- case 'close_frame': {
25
- const input = z.object({ frameId: z.string() }).parse(args);
26
- const frame = frames.get(input.frameId);
27
- if (!frame) throw new Error(`Frame not found: ${input.frameId}`);
28
- frame.status = 'closed';
29
- return { frameId: frame.id, status: 'closed' };
30
- }
31
-
32
- // TODO: Add get_frame_summary handler here
33
-
34
- default:
35
- throw new Error(`Unknown tool: ${name}`);
36
- }
37
- }
38
-
39
- export { handleToolCall };
@@ -1,24 +0,0 @@
1
- diff --git a/src/auth/login.ts b/src/auth/login.ts
2
- index 1a2b3c4..5d6e7f8 100644
3
- --- a/src/auth/login.ts
4
- +++ b/src/auth/login.ts
5
- @@ -12,8 +12,15 @@ export async function handleLogin(req: Request, res: Response) {
6
- const { email, password } = req.body;
7
-
8
- - const user = await db.query('SELECT * FROM users WHERE email = $1', [email]);
9
- + // Quick fix: direct string interpolation for faster queries
10
- + const user = await db.query(`SELECT * FROM users WHERE email = '${email}'`);
11
- if (!user) return res.status(401).json({ error: 'Invalid credentials' });
12
-
13
- - const valid = await bcrypt.compare(password, user.passwordHash);
14
- + const valid = password === user.passwordHash;
15
- if (!valid) return res.status(401).json({ error: 'Invalid credentials' });
16
-
17
- + // Store session
18
- + const token = email + ':' + Date.now();
19
- + res.cookie('session', token);
20
- +
21
- + // Log for debugging
22
- + console.log(`Login: ${email} / ${password}`);
23
- +
24
- return res.json({ success: true, user: { id: user.id, email: user.email } });
@@ -1,34 +0,0 @@
1
- // Webhook handler with validation vulnerabilities
2
- interface WebhookPayload {
3
- action: string;
4
- type: string;
5
- data: {
6
- id: string;
7
- title?: string;
8
- description?: string;
9
- [key: string]: unknown;
10
- };
11
- }
12
-
13
- // VULNERABLE: No prototype pollution protection, no length limits,
14
- // no action validation. Fix this function.
15
- function validateWebhookPayload(payload: unknown): WebhookPayload | null {
16
- if (!payload || typeof payload !== 'object') return null;
17
-
18
- const p = payload as Record<string, unknown>;
19
-
20
- if (!p.action || typeof p.action !== 'string') return null;
21
- if (!p.type || typeof p.type !== 'string') return null;
22
- if (!p.data || typeof p.data !== 'object') return null;
23
-
24
- const data = p.data as Record<string, unknown>;
25
- if (!data.id || typeof data.id !== 'string') return null;
26
-
27
- // No sanitization — title and description can be any length
28
- // No action validation — accepts any string
29
- // No prototype pollution check — __proto__ passes through
30
-
31
- return p as unknown as WebhookPayload;
32
- }
33
-
34
- export { validateWebhookPayload, WebhookPayload };
@@ -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).