diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..21256661 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/README.md b/README.md index 3a38b350..d1986cc7 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ PROMETHEUS_PORT=3200 GEMINI_API.KEY=key SEARXNG_URL=http://searxng:8888 FORGEVM_URL=http://forgevm:7423 +FORGEVM_API_TOKEN=key SANDBOX_IMAGE=sandbox-python:latest SANDBOX_MEMORY=512 SANDBOX_CPU=1 diff --git a/TODO.md b/TODO.md index b9332933..c9b9c724 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,3 @@ -- [ ] OpenUI and shadcn/ui - - [ ] Github OAuth - [ ] Implement an user management system so the user can customize its name, change password, profile picture and settings - [ ] Make an Password Recovery system and 2FA using the Email Protocol @@ -12,6 +10,8 @@ - [ ] drop {service_name}_PORT and {serivce_name}_HOST and replace it with nginx managed services - [ ] p99 latency and context switches monitor at /status - [ ] feather cache for synced cache and with redis for a flock replacement +- [ ] prevent scraping by using a cookie token linked session, if theres more than one tab active with a cookie token, one page will be blocked, forcing hte user to use a single tab, similar to how whatsapp web works +- [ ] api routing via random uuids for page requests that might use the stocks api data, making the requests not reproducable and making hte work of scraping way harder # diff --git a/config.py b/config.py index b2a40db2..dcc87304 100644 --- a/config.py +++ b/config.py @@ -65,6 +65,7 @@ class PrometheusSettings(BaseSettings): GEMINI_API_KEY: str = Field(default="", validation_alias=AliasChoices("GEMINI_API.KEY")) SEARXNG_URL: str = Field(default="http://searxng:8888", validation_alias=AliasChoices("SEARXNG_URL")) FORGEVM_URL: str = Field(default="http://forgevm:7423", validation_alias=AliasChoices("FORGEVM_URL")) + FORGEVM_API_TOKEN: str = Field(default="", validation_alias=AliasChoices("FORGEVM_API_TOKEN")) SANDBOX_IMAGE: str = Field(default="sandbox-python:latest", validation_alias=AliasChoices("SANDBOX_IMAGE")) SANDBOX_MEMORY: int = Field(default=512, validation_alias=AliasChoices("SANDBOX_MEMORY")) SANDBOX_CPU: int = Field(default=1, validation_alias=AliasChoices("SANDBOX_CPU")) @@ -124,6 +125,7 @@ class Config: ) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) +StocksSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=stocksEngine) def getSession(): @@ -132,3 +134,11 @@ def getSession(): yield db finally: db.close() + + +def getStocksSession(): + db = StocksSessionLocal() + try: + yield db + finally: + db.close() diff --git a/docker-compose.yml b/docker-compose.yml index ed4ddcc6..f4203e12 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,6 +36,7 @@ services: environment: - FORGEVM_DATABASE_PATH=/data/forgevm.db - FORGEVM_LOGGING_LEVEL=info + - FORGEVM_API_TOKEN=${FORGEVM_API_TOKEN:-} api: build: @@ -52,6 +53,7 @@ services: environment: - DEBUG_MODE=TRUE - TZ=America/Sao_Paulo + - FORGEVM_API_TOKEN=${FORGEVM_API_TOKEN:-} volumes: - .:/app diff --git a/forgevm.yaml b/forgevm.yaml index 00598780..a8b23d71 100644 --- a/forgevm.yaml +++ b/forgevm.yaml @@ -17,7 +17,8 @@ defaults: vcpus: 1 auth: - enabled: false + enabled: true + token: "${FORGEVM_API_TOKEN}" logging: level: "info" diff --git a/graphify-out/.graphify_labels.json b/graphify-out/.graphify_labels.json index f2f53dd5..5078b198 100644 --- a/graphify-out/.graphify_labels.json +++ b/graphify-out/.graphify_labels.json @@ -207,9 +207,14 @@ "205": "Community 205", "206": "Community 206", "207": "Community 207", + "208": "Community 208", "209": "Community 209", "210": "Community 210", "211": "Community 211", + "212": "Community 212", + "213": "Community 213", + "214": "Community 214", + "215": "Community 215", "216": "Community 216", "217": "Community 217", "218": "Community 218", @@ -257,6 +262,7 @@ "260": "Community 260", "261": "Community 261", "262": "Community 262", + "263": "Community 263", "264": "Community 264", "265": "Community 265", "266": "Community 266", @@ -467,6 +473,7 @@ "471": "Community 471", "472": "Community 472", "473": "Community 473", + "474": "Community 474", "475": "Community 475", "476": "Community 476", "477": "Community 477", @@ -478,18 +485,20 @@ "483": "Community 483", "484": "Community 484", "485": "Community 485", + "486": "Community 486", "487": "Community 487", "488": "Community 488", "489": "Community 489", "490": "Community 490", + "491": "Community 491", "492": "Community 492", "493": "Community 493", "494": "Community 494", + "495": "Community 495", "496": "Community 496", "497": "Community 497", "498": "Community 498", "499": "Community 499", - "500": "Community 500", "501": "Community 501", "502": "Community 502", "503": "Community 503", @@ -497,15 +506,55 @@ "505": "Community 505", "506": "Community 506", "507": "Community 507", + "508": "Community 508", "509": "Community 509", "510": "Community 510", "511": "Community 511", + "512": "Community 512", "513": "Community 513", "514": "Community 514", "515": "Community 515", "516": "Community 516", + "517": "Community 517", "518": "Community 518", + "519": "Community 519", "520": "Community 520", + "521": "Community 521", "522": "Community 522", - "527": "Community 527" + "523": "Community 523", + "524": "Community 524", + "525": "Community 525", + "526": "Community 526", + "527": "Community 527", + "528": "Community 528", + "531": "Community 531", + "532": "Community 532", + "533": "Community 533", + "534": "Community 534", + "536": "Community 536", + "537": "Community 537", + "538": "Community 538", + "540": "Community 540", + "542": "Community 542", + "545": "Community 545", + "546": "Community 546", + "547": "Community 547", + "548": "Community 548", + "549": "Community 549", + "550": "Community 550", + "551": "Community 551", + "552": "Community 552", + "553": "Community 553", + "554": "Community 554", + "555": "Community 555", + "556": "Community 556", + "557": "Community 557", + "558": "Community 558", + "559": "Community 559", + "561": "Community 561", + "562": "Community 562", + "563": "Community 563", + "566": "Community 566", + "567": "Community 567", + "568": "Community 568" } diff --git a/graphify-out/GRAPH_REPORT.md b/graphify-out/GRAPH_REPORT.md index dd75a551..fab88c8b 100644 --- a/graphify-out/GRAPH_REPORT.md +++ b/graphify-out/GRAPH_REPORT.md @@ -1,16 +1,16 @@ -# Graph Report - server (2026-08-16) +# Graph Report - server (2026-09-12) ## Corpus Check -- 102 files · ~46,927 words +- 121 files · ~71,539 words - Verdict: corpus is large enough that graph structure adds value. ## Summary -- 5461 nodes · 7350 edges · 509 communities (284 shown, 225 thin omitted) -- Extraction: 83% EXTRACTED · 17% INFERRED · 0% AMBIGUOUS · INFERRED: 1221 edges (avg confidence: 0.69) +- 5953 nodes · 7953 edges · 558 communities (330 shown, 228 thin omitted) +- Extraction: 84% EXTRACTED · 16% INFERRED · 0% AMBIGUOUS · INFERRED: 1251 edges (avg confidence: 0.69) - Token cost: 0 input · 0 output ## Graph Freshness -- Built from commit: `5f72f66a` +- Built from commit: `0f03079f` - Run `git rev-parse HEAD` and compare to check if the graph is stale. - Run `graphify update .` after code changes (no API cost). @@ -223,9 +223,14 @@ - [[_COMMUNITY_Community 205|Community 205]] - [[_COMMUNITY_Community 206|Community 206]] - [[_COMMUNITY_Community 207|Community 207]] +- [[_COMMUNITY_Community 208|Community 208]] - [[_COMMUNITY_Community 209|Community 209]] - [[_COMMUNITY_Community 210|Community 210]] - [[_COMMUNITY_Community 211|Community 211]] +- [[_COMMUNITY_Community 212|Community 212]] +- [[_COMMUNITY_Community 213|Community 213]] +- [[_COMMUNITY_Community 214|Community 214]] +- [[_COMMUNITY_Community 215|Community 215]] - [[_COMMUNITY_Community 216|Community 216]] - [[_COMMUNITY_Community 217|Community 217]] - [[_COMMUNITY_Community 218|Community 218]] @@ -273,6 +278,7 @@ - [[_COMMUNITY_Community 260|Community 260]] - [[_COMMUNITY_Community 261|Community 261]] - [[_COMMUNITY_Community 262|Community 262]] +- [[_COMMUNITY_Community 263|Community 263]] - [[_COMMUNITY_Community 264|Community 264]] - [[_COMMUNITY_Community 265|Community 265]] - [[_COMMUNITY_Community 266|Community 266]] @@ -474,6 +480,7 @@ - [[_COMMUNITY_Community 471|Community 471]] - [[_COMMUNITY_Community 472|Community 472]] - [[_COMMUNITY_Community 473|Community 473]] +- [[_COMMUNITY_Community 474|Community 474]] - [[_COMMUNITY_Community 475|Community 475]] - [[_COMMUNITY_Community 476|Community 476]] - [[_COMMUNITY_Community 477|Community 477]] @@ -485,17 +492,19 @@ - [[_COMMUNITY_Community 483|Community 483]] - [[_COMMUNITY_Community 484|Community 484]] - [[_COMMUNITY_Community 485|Community 485]] +- [[_COMMUNITY_Community 486|Community 486]] - [[_COMMUNITY_Community 487|Community 487]] - [[_COMMUNITY_Community 488|Community 488]] - [[_COMMUNITY_Community 489|Community 489]] - [[_COMMUNITY_Community 490|Community 490]] +- [[_COMMUNITY_Community 491|Community 491]] - [[_COMMUNITY_Community 492|Community 492]] - [[_COMMUNITY_Community 493|Community 493]] - [[_COMMUNITY_Community 494|Community 494]] +- [[_COMMUNITY_Community 495|Community 495]] - [[_COMMUNITY_Community 497|Community 497]] - [[_COMMUNITY_Community 498|Community 498]] - [[_COMMUNITY_Community 499|Community 499]] -- [[_COMMUNITY_Community 500|Community 500]] - [[_COMMUNITY_Community 501|Community 501]] - [[_COMMUNITY_Community 502|Community 502]] - [[_COMMUNITY_Community 503|Community 503]] @@ -503,36 +512,76 @@ - [[_COMMUNITY_Community 505|Community 505]] - [[_COMMUNITY_Community 506|Community 506]] - [[_COMMUNITY_Community 507|Community 507]] +- [[_COMMUNITY_Community 508|Community 508]] - [[_COMMUNITY_Community 509|Community 509]] - [[_COMMUNITY_Community 510|Community 510]] +- [[_COMMUNITY_Community 512|Community 512]] +- [[_COMMUNITY_Community 517|Community 517]] - [[_COMMUNITY_Community 518|Community 518]] +- [[_COMMUNITY_Community 519|Community 519]] - [[_COMMUNITY_Community 520|Community 520]] +- [[_COMMUNITY_Community 521|Community 521]] - [[_COMMUNITY_Community 522|Community 522]] +- [[_COMMUNITY_Community 523|Community 523]] +- [[_COMMUNITY_Community 524|Community 524]] +- [[_COMMUNITY_Community 525|Community 525]] +- [[_COMMUNITY_Community 526|Community 526]] - [[_COMMUNITY_Community 527|Community 527]] +- [[_COMMUNITY_Community 528|Community 528]] +- [[_COMMUNITY_Community 531|Community 531]] +- [[_COMMUNITY_Community 532|Community 532]] +- [[_COMMUNITY_Community 533|Community 533]] +- [[_COMMUNITY_Community 534|Community 534]] +- [[_COMMUNITY_Community 536|Community 536]] +- [[_COMMUNITY_Community 537|Community 537]] +- [[_COMMUNITY_Community 538|Community 538]] +- [[_COMMUNITY_Community 540|Community 540]] +- [[_COMMUNITY_Community 542|Community 542]] +- [[_COMMUNITY_Community 545|Community 545]] +- [[_COMMUNITY_Community 546|Community 546]] +- [[_COMMUNITY_Community 547|Community 547]] +- [[_COMMUNITY_Community 548|Community 548]] +- [[_COMMUNITY_Community 549|Community 549]] +- [[_COMMUNITY_Community 550|Community 550]] +- [[_COMMUNITY_Community 551|Community 551]] +- [[_COMMUNITY_Community 552|Community 552]] +- [[_COMMUNITY_Community 553|Community 553]] +- [[_COMMUNITY_Community 554|Community 554]] +- [[_COMMUNITY_Community 555|Community 555]] +- [[_COMMUNITY_Community 556|Community 556]] +- [[_COMMUNITY_Community 557|Community 557]] +- [[_COMMUNITY_Community 558|Community 558]] +- [[_COMMUNITY_Community 559|Community 559]] +- [[_COMMUNITY_Community 561|Community 561]] +- [[_COMMUNITY_Community 562|Community 562]] +- [[_COMMUNITY_Community 563|Community 563]] +- [[_COMMUNITY_Community 566|Community 566]] +- [[_COMMUNITY_Community 567|Community 567]] +- [[_COMMUNITY_Community 568|Community 568]] ## God Nodes (most connected - your core abstractions) 1. `vocab` - 456 edges 2. `StocksCacheManager` - 79 edges 3. `HarnessState` - 68 edges -4. `UserManager` - 55 edges +4. `UserManager` - 56 edges 5. `Permission` - 50 edges 6. `Pytest Testing` - 50 edges 7. `StocksQueryManager` - 48 edges 8. `Roles` - 45 edges -9. `Prometheus` - 41 edges -10. `TestQueryFundamental` - 38 edges +9. `cn()` - 43 edges +10. `Prometheus` - 41 edges ## Surprising Connections (you probably didn't know these) +- `lifespan()` --calls--> `runAll()` [INFERRED] + run.py → main/utils/service_manager.py - `StocksCacheManager` --calls--> `test_cache_scheduler_starts_apscheduler()` [INFERRED] main/app/stocks_api/cache.py → tests/test_stocks_api_coverage.py - `StocksCacheManager` --calls--> `test_cache_scheduler_starts_daemon_thread()` [INFERRED] main/app/stocks_api/cache.py → tests/test_stocks_api_coverage.py -- `HarnessState` --uses--> `TestCheckCache` [INFERRED] - main/app/prometheus/state.py → tests/test_sandbox_tools.py -- `HarnessState` --uses--> `TestDispatchToolCallSandbox` [INFERRED] - main/app/prometheus/state.py → tests/test_sandbox_tools.py -- `get_state()` --calls--> `test_get_state_no_state_returns_error()` [INFERRED] - main/app/prometheus/tools.py → tests/test_prometheus_tools.py +- `HarnessState` --uses--> `TestGetState` [INFERRED] + main/app/prometheus/state.py → tests/test_state_tools.py +- `HarnessState` --uses--> `TestSetState` [INFERRED] + main/app/prometheus/state.py → tests/test_state_tools.py ## Hyperedges (group relationships) - **Authentication Module** — AuthenticationManager, SessionManager, auth_util, auth_constants, getGoogleSSO [INFERRED] @@ -542,7 +591,7 @@ - **Configuration & Database Infrastructure** — config_Config, config_engine, config_stocksEngine [INFERRED] - **User Authentication & Authorization** — user_service, authentication, user_roles, permission_system [INFERRED] -## Communities (509 total, 225 thin omitted) +## Communities (558 total, 228 thin omitted) ### Community 0 - "Stocks API Endpoints" Cohesion: 0.0 @@ -558,15 +607,15 @@ Nodes (21): Thin async wrapper around the CubeSandbox/E2B HTTP API. All met ### Community 3 - "Prometheus Agent" Cohesion: 0.06 -Nodes (28): Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., Tests covering cache.py lines 28-76., Non-JSON-dict/list string is left as-is., Tests covering cache.py lines 28-76. (+20 more) +Nodes (28): Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., Tests covering query.py lines 22-48., replaceNan handles direct float NaN values (line 34)., Tests covering cache.py lines 28-76., Tests covering cache.py lines 28-76. (+20 more) ### Community 4 - "Data Models & Types" Cohesion: 0.11 Nodes (24): PrometheusSandbox, cleanup_expired_sandboxes(), Remove DB mappings for sandboxes that no longer exist in ForgeVM., _mock_forgevm(), Wire up mock forgevm AsyncClient that returns sandbox with all methods., Enforce one active sandbox per user via application logic., Enforce one active sandbox per user via application logic., Enforce one active sandbox per user via application logic. (+16 more) ### Community 5 - "Prometheus Services" -Cohesion: 0.22 -Nodes (13): AuthForm(), apiFetch(), authHeaders(), createSession(), deleteSession(), deleteWorkspaceFile(), googleAuthUrl(), listWorkspaceFiles() (+5 more) +Cohesion: 0.12 +Nodes (21): AuthForm(), apiFetch(), authHeaders(), createHolding(), createLot(), createSession(), deleteSession(), deleteWorkspaceFile() (+13 more) ### Community 6 - "Database Schema" Cohesion: 0.04 @@ -578,7 +627,7 @@ Nodes (29): Algorithmic Compression (`compact.py`) Implementation Plan, code:pyt ### Community 8 - "Device Detection" Cohesion: 0.06 -Nodes (27): HarnessState, Retrieve a value from state. Returns default if key not found., Return a copy of the current state., Format state as a string for injection into the LLM context., Check if state changed since last reset., Reset the changed flag. Returns the previous state., Clear all state data., In-memory state dict that persists across loop iterations within a single reques (+19 more) +Nodes (15): HarnessState, Retrieve a value from state. Returns default if key not found., Return a copy of the current state., Format state as a string for injection into the LLM context., Check if state changed since last reset., Reset the changed flag. Returns the previous state., Clear all state data., In-memory state dict that persists across loop iterations within a single reques (+7 more) ### Community 9 - "Server Configuration" Cohesion: 0.11 @@ -597,8 +646,8 @@ Cohesion: 0.08 Nodes (13): LoopEvent, LoopEvent model for observable agent loops., LoopLogger, LoopLogger — batched event logging for observable agent loops., Queue events during a loop, flush to DB at end., Log a generic event with optional metadata., Log a tool invocation., Log end of a turn with timing. (+5 more) ### Community 13 - "Prometheus Tools" -Cohesion: 0.22 -Nodes (10): batchCosineSimilarity(), decodeEmbeddings(), Empty matrix → empty array., Single row matches cosine_similarity., Multiple rows ranked correctly., Zero query → all zeros., TestBatchCosineSimilarity, batch_cosine_similarity() (+2 more) +Cohesion: 0.15 +Nodes (13): benchOnce(), main(), batchCosineSimilarity(), decodeEmbeddings(), normalizeRows(), Empty matrix → empty array., Single row matches cosine_similarity., Multiple rows ranked correctly. (+5 more) ### Community 14 - "User Roles & Permissions" Cohesion: 0.05 @@ -609,12 +658,12 @@ Cohesion: 0.05 Nodes (38): code:block1 (User 123: "Analyze PETR4 vs VALE3 correlation"), code:python (from main.app.prometheus.sandbox import SandboxManager), code:python (TOOL_REGISTRY: dict[str, Any] = {), code:bash (git add main/app/prometheus/tools.py tests/test_sandbox_tool), code:python (import pytest), code:python (from main.app.prometheus.sandbox import SandboxManager), code:python (async def streamMessage(self, query=None, sessionId=None, db), code:python (## Code Sandbox (On-Demand)) (+30 more) ### Community 16 - "Community 16" -Cohesion: 0.04 -Nodes (42): _make_prometheus_client(), Covers lines 95-98: session deleted., Covers lines 96-97: session not found., Covers lines 96-97: session not found., Covers lines 96-97: session not found., Covers lines 95-98: DELETE /prometheus/sessions/{sessionId}., Covers lines 95-98: session deleted., Covers lines 96-97: session not found. (+34 more) +Cohesion: 0.05 +Nodes (34): _make_prometheus_client(), Generic Exception in chat propagates to FastAPI's default 500 handler., Generic Exception in chat propagates to FastAPI's default 500 handler., Generic Exception in chat propagates to FastAPI's default 500 handler., Generic Exception in chat propagates via SSE error event., Covers line 125, 126-128: generic Exception in chat., Return (client, app) with prometheus router and mocked deps., Covers lines 33-36: GET /prometheus/sessions. (+26 more) ### Community 17 - "Community 17" -Cohesion: 0.07 -Nodes (26): Two dates in the range, both valid., Two dates in the range, both valid., Two dates in the range, both valid., Two dates in the range, both valid., Search with no index match falls back to string startswith., Search with no index match falls back to string startswith., search.strip() == '' should still dedup (line 181)., Search with no index match falls back to string startswith. (+18 more) +Cohesion: 0.08 +Nodes (23): search.strip() == '' should still dedup (line 181)., search.strip() == '' should still dedup (line 181)., search.strip() == '' should still dedup (line 181)., DataFrame without TIME column., DataFrame without TIME column., DataFrame without TIME column., search.strip() == '' should still dedup (line 181)., Multiple search terms with tickerIndex. (+15 more) ### Community 18 - "Community 18" Cohesion: 0.07 @@ -629,12 +678,12 @@ Cohesion: 0.06 Nodes (35): 1. Memory System (B+), 2. Summarizer/Episodes (B), 3. Loop Events (A-), 4. Core Architecture (B+), 5. Security (B+), 6. Performance (B), 7. Code Quality (B), After (B+) (+27 more) ### Community 21 - "Community 21" -Cohesion: 0.05 -Nodes (39): AuthenticationManager, IntFlag, Covers line 18: GET /stocks/health., Covers line 18: GET /stocks/health., Covers line 18: GET /stocks/health., Covers line 18: GET /stocks/health., Covers line 18: GET /stocks/health., Covers line 28: GET /auth/health. (+31 more) +Cohesion: 0.06 +Nodes (24): Store a value in state. Marks state as changed for context injection., _make_stocks_df(), Return a small DataFrame with the columns the query module expects., Return a small DataFrame with the columns the query module expects., Tests covering query.py lines 77-132., Tests covering query.py lines 77-132., Tests covering query.py lines 77-132., Tests covering query.py lines 77-132. (+16 more) ### Community 22 - "Community 22" -Cohesion: 0.07 -Nodes (19): filterCotationColumn(), Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., GET /stocks/realtime-cotation without search returns 422., GET /cotations without search returns 422. (+11 more) +Cohesion: 0.14 +Nodes (7): filterCotationColumn(), Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., Tests for queryLiveCotation and /stocks/cotations/live., TestQueryLiveCotation ### Community 23 - "Community 23" Cohesion: 0.06 @@ -649,20 +698,20 @@ Cohesion: 0.06 Nodes (13): Tests for input validation via HTTP endpoints. Validation is now inline via Bod, PUT /prometheus/sessions/{sessionId} — validates title via Body(...), POST /prometheus/chat/stream — validates query via Body(...), POST /auth/register — validates username, email, password via Body(...), Test that endpoints reject requests with missing required fields., POST /auth/login — validates username, password via Body(...), POST /prometheus/sessions — validates title via Body(...), TestChatValidation (+5 more) ### Community 26 - "Community 26" -Cohesion: 0.1 -Nodes (23): generateKey(), createKey(), _hash_key(), hashKey(), Return SHA-256 hex digest of the given key., Test that concurrent requests are properly serialized at DB level. Th, Test edge case: request exactly at quota limit., Test edge case: request exactly at quota limit. (+15 more) +Cohesion: 0.13 +Nodes (16): generateKey(), createKey(), _hash_key(), hashKey(), Return SHA-256 hex digest of the given key., Test edge case: request exactly at quota limit., Test edge case: request exactly at quota limit., Test that increment works from zero usage. (+8 more) ### Community 27 - "Community 27" -Cohesion: 0.16 -Nodes (14): getRelevanceScore(), _FakeMemory, A memory with no lastAccessedAt should use baseScore as-is., Scores are deterministic — no cron mutation needed., Same memory at different points in time yields different scores., A memory accessed 10x (baseScore 1.0) should still outrank a memory acce, A rarely-used old memory should lose to a popular fresh one., With same access time, higher baseScore always wins. (+6 more) +Cohesion: 0.15 +Nodes (15): getUserMemories(), getRelevanceScore(), _FakeMemory, A memory with no lastAccessedAt should use baseScore as-is., Scores are deterministic — no cron mutation needed., Same memory at different points in time yields different scores., A memory accessed 10x (baseScore 1.0) should still outrank a memory acce, A rarely-used old memory should lose to a popular fresh one. (+7 more) ### Community 28 - "Community 28" Cohesion: 0.07 -Nodes (26): Pass field name WITHOUT year (how categorizeColumns returns them)., Pass field name WITHOUT year (how categorizeColumns returns them)., No historical data columns -> inner 400 caught by outer except -> 500., Pass field name WITHOUT year (how categorizeColumns returns them)., Pass field name WITHOUT year (how categorizeColumns returns them)., No historical data columns -> inner 400 caught by outer except -> 500., If an unexpected exception occurs in queryHistorical., No historical data columns -> inner 400 caught by outer except -> 500. (+18 more) +Nodes (27): Pass field name WITHOUT year (how categorizeColumns returns them)., Pass field name WITHOUT year (how categorizeColumns returns them)., Pass field name WITHOUT year (how categorizeColumns returns them)., Pass field name WITHOUT year (how categorizeColumns returns them)., If an unexpected exception occurs in queryHistorical., Pass field name WITHOUT year (how categorizeColumns returns them)., Pass field name WITHOUT year (how categorizeColumns returns them)., Pass field name WITHOUT year (how categorizeColumns returns them). (+19 more) ### Community 29 - "Community 29" -Cohesion: 0.09 -Nodes (15): PrometheusGenerator, _make_generator(), Tests to increase coverage for: - main/app/prometheus/generation.py - main/a, test_execute_workflow_basic_no_history(), test_execute_workflow_global_request_api_error(), test_execute_workflow_global_request_status_not_200(), test_execute_workflow_global_request_with_api_key(), test_execute_workflow_session_db_exception() (+7 more) +Cohesion: 0.08 +Nodes (17): PrometheusGenerator, Thread-safe proxy that delegates to per-thread sessions., SessionProxy, _make_generator(), Tests to increase coverage for: - main/app/prometheus/generation.py - main/a, test_execute_workflow_basic_no_history(), test_execute_workflow_global_request_api_error(), test_execute_workflow_global_request_status_not_200() (+9 more) ### Community 30 - "Community 30" Cohesion: 0.07 @@ -677,8 +726,8 @@ Cohesion: 0.11 Nodes (12): ToolContext — bundles all dependencies for tool execution. Replace passing user, Single dependency bundle for tool execution. Created once per request in ag, Extract userId from user dict if not explicitly set., ToolContext, Unit tests for ToolContext dataclass., Dataclass equality works out of the box., Explicit userId takes precedence over user dict., Two contexts share no mutable defaults. (+4 more) ### Community 33 - "Community 33" -Cohesion: 0.06 -Nodes (23): BaseHTTPMiddleware, BaseModel, Tests for standardized error responses (errors.py)., SampleBody, TestErrorResponseModel, TestGenericExceptionHandler, TestHTTPExceptionHandler, TestRequestContextFilter (+15 more) +Cohesion: 0.09 +Nodes (23): BaseHTTPMiddleware, BaseModel, app(), Tests for standardized error responses (errors.py)., SampleBody, TestErrorResponseModel, TestGenericExceptionHandler, TestHTTPExceptionHandler (+15 more) ### Community 34 - "Community 34" Cohesion: 0.11 @@ -701,8 +750,8 @@ Cohesion: 0.07 Nodes (27): code:json ([), code:javascript (const loadHistory = async (sid) => {), code:jsx (export default function MessageList({ messages, toolEvents, ), code:javascript (const loadHistory = async (sid) => {), code:jsx (export default function AgentLoop({ toolEvents, turnMetrics ), code:bash (git add frontend/src/App.jsx frontend/src/components/Message), code:bash (docker-compose up -d --build), code:sql (SELECT COUNT(*) FROM prometheus WHERE JSON_CONTAINS_PATH(his) (+19 more) ### Community 39 - "Community 39" -Cohesion: 0.06 -Nodes (31): Invalid date -> inner 400 passes through (not wrapped as 500)., Invalid date -> inner 400 caught by outer except -> 500., Invalid date -> inner 400 caught by outer except -> 500., Invalid date -> inner 400 caught by outer except -> 500., search.strip() == '' should still dedup (line 181)., search.strip() == '' should still dedup (line 181)., Invalid date -> inner 400 caught by outer except -> 500., Invalid date -> inner 400 caught by outer except -> 500. (+23 more) +Cohesion: 0.07 +Nodes (25): Two dates in the range, both valid., Two dates in the range, both valid., Two dates in the range, both valid., Two dates in the range, both valid., Search with no index match falls back to string startswith., Search with no index match falls back to string startswith., search.strip() == '' should still dedup (line 181)., Search with no index match falls back to string startswith. (+17 more) ### Community 40 - "Community 40" Cohesion: 0.12 @@ -737,12 +786,12 @@ Cohesion: 0.1 Nodes (17): _make_user_client(), Return (client, app) with user router and mocked deps., Covers line 24: GET /user/me returns currentUser., Covers line 24: GET /user/me returns currentUser., Covers line 24: GET /user/me returns currentUser., Covers lines 31-32, 36, 43-44, 48: upgrade developer starter/enterprise., Covers lines 31-32, 36, 43-44, 48: upgrade developer starter/enterprise., Covers lines 31-32, 36, 43-44, 48: upgrade developer starter/enterprise. (+9 more) ### Community 48 - "Community 48" -Cohesion: 0.19 -Nodes (7): Tests for thread safety utilities (Issues 5 & 6). Issue 5: DiscordHandler use, Verify getSession returns thread-local sessions under concurrency., getSession() must give each thread its own Session., connectivity.checkServiceConnection must call getSession(), not use a global Ses, connectivity.checkServiceConnection must call getSession(), not use a global Ses, TestConcurrentGetSession, TestConcurrentHttpProxy +Cohesion: 0.06 +Nodes (34): Backend (COMMIT), code:bash (cd frontend && pnpm add @openuidev/react-lang), code:bash (rm frontend/src/components/MdocMessage.jsx), code:python ("""OpenUI Lang system prompt section for Prometheus agent.), code:block12, code:block13, code:block14, code:block15 (+26 more) ### Community 49 - "Community 49" -Cohesion: 0.06 -Nodes (32): dispatchToolCall(), TDD tests: verify memory tools are wired into the Prometheus agent. RED: Thes, dispatchToolCall must route memory tool names via TOOL_REGISTRY., makeChat must include MEMORY_TOOLS alongside MCP sessions., makeChat must include MEMORY_TOOLS alongside MCP sessions., makeChat must include MEMORY_TOOLS alongside MCP sessions., makeChat must include MEMORY_TOOLS alongside MCP sessions., TOOL_REGISTRY pattern must work correctly. (+24 more) +Cohesion: 0.1 +Nodes (20): dispatchToolCall(), TDD tests: verify memory tools are wired into the Prometheus agent. RED: Thes, TOOL_REGISTRY pattern must work correctly., test_memory_tool_skipped_without_user(), test_non_memory_tool_not_routed_to_executeMemoryTool(), test_non_registry_tool_not_routed(), test_save_memory_routed_to_executeMemoryTool(), test_save_memory_routed_via_registry() (+12 more) ### Community 50 - "Community 50" Cohesion: 0.07 @@ -758,19 +807,19 @@ Nodes (7): Cover all methods in chat.py (lines 11-120)., Cover all methods in ch ### Community 53 - "Community 53" Cohesion: 0.12 -Nodes (19): archiveDead(), count_memories(), countMemories(), decayScores(), deleteMemory(), extract(), findSimilarKey(), _fulltext_search() (+11 more) +Nodes (23): archiveDead(), count_memories(), countMemories(), decayScores(), deleteMemory(), extract(), findSimilarKey(), _fulltext_search() (+15 more) ### Community 54 - "Community 54" Cohesion: 0.06 -Nodes (29): memoryMaintenance(), create_memories(), Zero access but score still above threshold → not archived., Even with low score, if accessed → not archived., Even with low score, if accessed → not archived., Already archived memories are skipped., Already archived memories are skipped., Decay happens first, then archive check with new scores. (+21 more) +Nodes (30): memoryMaintenance(), create_memories(), Zero access but score still above threshold → not archived., Even with low score, if accessed → not archived., Even with low score, if accessed → not archived., Already archived memories are skipped., Already archived memories are skipped., Decay happens first, then archive check with new scores. (+22 more) ### Community 55 - "Community 55" Cohesion: 0.11 Nodes (17): Backend Contract (source of truth for api.js), code:js (describe('workspace API', () => {), code:bash (git add frontend/src/components/InputBar.jsx frontend/tests/), code:js (export async function listWorkspaceFiles(path = '/workspace'), code:bash (git add frontend/src/api.js frontend/tests/api.test.js front), code:jsx (import { describe, it, expect, vi, beforeEach } from 'vitest), code:jsx (// SettingsDialog.jsx — workspace files grid), code:jsx (